Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 14, 2025

Task: Add Configurable PostgreSQL Storage Schema

Implementation plan for adding configurable table and column names to PostgreSQL storage layer.

Progress Checklist

  • Explore repository structure and understand current implementation
  • Review existing types, interfaces, and PostgreSQL storage layer
  • Review database utilities and schema setup
  • Add PostgresSchemaConfig type to src/types/index.ts
  • Update PostgresConfig to accept optional schema configuration
  • Update PostgresStorage class to use dynamic table/column names
    • Update constructor to accept and store schema config
    • Add SQL identifier validation in constructor
    • Update get() method with dynamic column/table names
    • Update set() method with dynamic column/table names
    • Update delete() method with dynamic column/table names
    • Update exists() method with dynamic column/table names
    • Update clear() method with dynamic column/table names
  • Update src/core/database.ts to support configurable schema
    • Make setupNuvexSchema accept schema configuration
    • Update SQL generation to use dynamic table/column names
    • Update cleanup and drop functions
    • Add and export SQL identifier validation to prevent SQL injection
    • Fix empty string handling in validation
  • Add tests for configurable schema
    • Test default schema configuration
    • Test custom schema configuration (Telegram bot style)
    • Test custom schema configuration (Discord bot style)
    • Test SQL injection prevention in generateNuvexSchemaSQL
    • Test SQL injection prevention in PostgresStorage constructor
    • Test custom schema in setupNuvexSchema utility
    • Test custom schema in cleanupExpiredEntries utility
    • Test custom schema in dropNuvexSchema utility
    • Add edge case tests for identifier validation:
      • Empty strings
      • Identifiers starting with numbers
      • Identifiers with only special characters
      • Identifiers with spaces
      • Identifiers with hyphens
      • Identifiers starting with underscores (valid)
  • Update README.md with schema configuration examples
  • Run all tests to ensure backward compatibility (127 tests pass)
  • Lint the code
  • Address all security concerns from code reviews
  • CodeQL security scan (0 alerts)
  • Address all PR feedback comments

Summary

Successfully implemented configurable PostgreSQL schema with:

  • Default schema: nuvex_storage table with nuvex_key and nuvex_data columns
  • Custom schema support for backwards compatibility with Telegram and Discord bots
  • SQL injection prevention through identifier validation with edge case handling
  • Comprehensive tests (30 new tests, all 127 tests passing)
  • Full documentation in README with examples
  • Zero security vulnerabilities detected by CodeQL
Original prompt

This section details on the original issue you should resolve

<issue_title>Add Configurable PostgreSQL Storage Schema (Table and Column Names) for Backwards Compatibility</issue_title>
<issue_description>### Overview
Add configurable PostgreSQL table and column names to Nuvex, enabling backwards compatibility with existing applications (such as the Telegram and Discord bots) and smoother migrations to the new standard. Default names should be strongly branded as nuvex_*.

Related PR: #6


Problem

Nuvex currently uses hardcoded table/column names (e. g., key and value), which may not match existing production databases for Telegram/Discord bot users. This blocks smooth migration and prevents seamless adoption.


Proposal

  1. Default Schema (for new apps):

    • Table: nuvex_storage
    • Key Column: nuvex_key
    • Data Column: nuvex_data
    CREATE TABLE nuvex_storage (
      id SERIAL PRIMARY KEY,
      nuvex_key VARCHAR(255) UNIQUE NOT NULL,
      nuvex_data JSONB,
      expires_at TIMESTAMP,
      created_at TIMESTAMP DEFAULT NOW(),
      updated_at TIMESTAMP DEFAULT NOW()
    );
  2. Configurable for Existing Apps:

    • Example for a bot using storage_cache.key/storage_cache.value:
      const storage = new Nuvex({
        postgres:  {
          // ...
          schema: {
            tableName: 'storage_cache',
            columns: { key: 'key', value: 'value' }
          }
        }
      });
    • Example for a bot using storage_cache.cache_key/storage_cache.data:
      const storage = new Nuvex({
        postgres: {
          // ...
          schema: {
            tableName: 'storage_cache',
            columns:  { key: 'cache_key', value: 'data' }
          }
        }
      });

Implementation Tasks

  • Add PostgresSchemaConfig type to src/types/index.ts
  • Update PostgresConfig to accept schema?: PostgresSchemaConfig
  • Update PostgresStorage layer to use dynamic table/column names everywhere (get, set, delete, exists, clear)
  • Default values:
    • Table: nuvex_storage
    • Key Column: nuvex_key
    • Data Column: nuvex_data
  • Update/create database utility for initializing the table structure with correct names
  • Ensure all core and relevant existing/future tests pass for default and custom schemas
  • Add documentation/examples for schema configuration in the Nuvex README

Acceptance Criteria


Reference

App Table Key Column Data Column
Nuvex nuvex_storage nuvex_key nuvex_data
Telegram Bot storage_cache key value
Discord Bot storage_cache cache_key data

Reference: Discussion with @warengonzaga and PR #6</issue_description>

<agent_instructions>Apply the details in this issue as your context and then PR the changes to the branch "copilot/refactor-3-layer-storage" and as your base code. Keep the principles for DRY, KISS, and CLEAN CODE. Don't over-engineer this.</agent_instructions>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI self-assigned this Dec 14, 2025
@warengonzaga warengonzaga added maintainer Maintainer expertise required (Issues/PRs) library Library implementation and core features (Issues/PRs) labels Dec 14, 2025
Copilot AI changed the title [WIP] Add configurable PostgreSQL storage schema for backwards compatibility Add configurable PostgreSQL schema for backwards compatibility Dec 14, 2025
Copilot AI requested a review from warengonzaga December 14, 2025 11:54
@warengonzaga warengonzaga marked this pull request as ready for review December 14, 2025 11:56
@warengonzaga warengonzaga requested review from Copilot and removed request for warengonzaga December 14, 2025 11:56
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds configurable PostgreSQL schema support to enable backwards compatibility with existing applications (Telegram bots, Discord bots) using different table and column naming conventions. The implementation maintains strong defaults (nuvex_storage, nuvex_key, nuvex_data) while allowing customization through an optional schema configuration object.

Key Changes:

  • Introduced PostgresSchemaConfig interface with optional tableName and columns configuration
  • Enhanced PostgresStorage to extract, validate, and use dynamic schema identifiers in all SQL operations
  • Added validateSQLIdentifier() function with strict regex validation (^[a-zA-Z_][a-zA-Z0-9_]*$) to prevent SQL injection
  • Updated database utilities (generateNuvexSchemaSQL, setupNuvexSchema, cleanupExpiredEntries, dropNuvexSchema) to support custom schemas

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/types/index.ts Defines PostgresSchemaConfig interface and integrates it with PostgresConfig for optional schema customization
src/layers/postgres.ts Extracts schema config in constructor, validates all identifiers, and uses dynamic table/column names in all SQL queries
src/core/database.ts Implements validateSQLIdentifier() for security, generateNuvexSchemaSQL() for dynamic DDL generation, and adds schema parameter support to all utility functions
src/tests/unit/postgres-schema.test.ts Comprehensive tests for schema configuration including SQL injection prevention, custom naming, and partial configuration scenarios
src/tests/unit/database.test.ts Updates existing schema SQL tests to verify new default column names (nuvex_key, nuvex_data)
README.md Documents schema configuration with examples for default, Telegram bot, and Discord bot compatibility scenarios

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor Author

Copilot AI commented Dec 14, 2025

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • downloads.snyk.io
    • Triggering command: /usr/local/bin/node /usr/local/bin/node wrapper_dist/bootstrap.js exec (dns block)
  • o30291.ingest.sentry.io
    • Triggering command: /usr/local/bin/node /usr/local/bin/node wrapper_dist/bootstrap.js exec (dns block)
  • static.snyk.io
    • Triggering command: /usr/local/bin/node /usr/local/bin/node wrapper_dist/bootstrap.js exec (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copy link
Contributor Author

Copilot AI commented Dec 14, 2025

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • downloads.snyk.io
    • Triggering command: /usr/local/bin/node /usr/local/bin/node wrapper_dist/bootstrap.js exec (dns block)
  • o30291.ingest.sentry.io
    • Triggering command: /usr/local/bin/node /usr/local/bin/node wrapper_dist/bootstrap.js exec (dns block)
  • static.snyk.io
    • Triggering command: /usr/local/bin/node /usr/local/bin/node wrapper_dist/bootstrap.js exec (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@warengonzaga
Copy link
Member

@copilot what's the issue with snyk in our test?

Copy link
Contributor Author

Copilot AI commented Dec 14, 2025

@copilot what's the issue with snyk in our test?

The Snyk errors during yarn install are network-related issues in the sandboxed environment where tests run. Snyk tries to download its CLI binary from downloads.snyk.io and static.snyk.io, but these domains are blocked by firewall rules.

This doesn't affect the test results - all 127 tests pass successfully. Snyk is a security scanning tool listed as a dev dependency, but it's not required for running Jest tests. The install completes successfully despite the Snyk download failure.

If Snyk scanning is needed, it should be run separately via npm run secure or CI/CD pipelines with appropriate network access.

@warengonzaga warengonzaga merged commit c31e0ef into copilot/refactor-3-layer-storage Dec 14, 2025
3 checks passed
@warengonzaga warengonzaga deleted the copilot/add-configurable-postgresql-schema branch December 14, 2025 14:45
warengonzaga added a commit that referenced this pull request Dec 15, 2025
…, and L3-first writes (#6)

* Initial plan

* Create modular layer architecture with LRU, health checks, and comprehensive documentation

Co-authored-by: warengonzaga <[email protected]>

* Refactor StorageEngine to use modular layers with L3-first write and Promise.allSettled

Co-authored-by: warengonzaga <[email protected]>

* Fix tests and skip tests requiring keys() reimplementation

Co-authored-by: warengonzaga <[email protected]>

* Address code review feedback: fix ping() type safety and document keys() limitations

Co-authored-by: warengonzaga <[email protected]>

* ✨️ tweak: add configurable PostgreSQL schema for backwards compatibility (#10)

* Initial plan

* Add configurable schema types and update PostgresStorage layer

Co-authored-by: warengonzaga <[email protected]>

* Add tests and documentation for configurable schema

Co-authored-by: warengonzaga <[email protected]>

* Add SQL injection prevention for configurable schema identifiers

Co-authored-by: warengonzaga <[email protected]>

* Export validateSQLIdentifier and add validation in PostgresStorage constructor

Co-authored-by: warengonzaga <[email protected]>

* Add tests for custom schema in setupNuvexSchema, cleanupExpiredEntries, and dropNuvexSchema

Co-authored-by: warengonzaga <[email protected]>

* Add edge case tests for identifier validation and fix empty string handling

Co-authored-by: warengonzaga <[email protected]>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: warengonzaga <[email protected]>

* 🔧 update(postgres): ensure connection state is updated on disconnect

* 🔧 update(engine): enhance error handling and usage recommendations for set()

* 📖 docs: enhance increment method documentation with concurrency warnings

* ⚙️ setup: add Snyk Security Extension AI rules instructions

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: warengonzaga <[email protected]>
Co-authored-by: Waren Gonzaga <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

library Library implementation and core features (Issues/PRs) maintainer Maintainer expertise required (Issues/PRs)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Configurable PostgreSQL Storage Schema (Table and Column Names) for Backwards Compatibility

2 participants