nexusql 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/database.ts","../src/lib/db-url.ts","../src/lib/migrations.ts","../src/lib/reverse.ts","../src/lib/runner.ts","../src/lib/dbml.ts","../src/lib/migra.ts","../src/lib/config.ts","../src/commands/gen.ts","../src/commands/migrate.ts","../src/utils/prompts.ts","../src/commands/mark-applied.ts","../src/commands/init.ts"],"sourcesContent":["import pg from \"pg\";\nimport { parseAndEncodeDbUrl, buildDbUrl, type DbUrlParts } from \"./db-url.js\";\n\nconst { Client } = pg;\n\nexport interface QueryResult {\n rows: Record<string, unknown>[];\n rowCount: number;\n}\n\nexport class Database {\n private connectionString: string;\n private dbParts: DbUrlParts;\n\n constructor(connectionString: string) {\n this.dbParts = parseAndEncodeDbUrl(connectionString);\n this.connectionString = this.dbParts.url;\n }\n\n /**\n * Execute a query and return results.\n */\n async query(sql: string): Promise<QueryResult> {\n const client = new Client({ connectionString: this.connectionString });\n try {\n await client.connect();\n const result = await client.query(sql);\n return {\n rows: result.rows,\n rowCount: result.rowCount ?? 0,\n };\n } finally {\n await client.end();\n }\n }\n\n /**\n * Execute a parameterized query and return results.\n */\n async queryParams(sql: string, params: unknown[]): Promise<QueryResult> {\n const client = new Client({ connectionString: this.connectionString });\n try {\n await client.connect();\n const result = await client.query(sql, params);\n return {\n rows: result.rows,\n rowCount: result.rowCount ?? 0,\n };\n } finally {\n await client.end();\n }\n }\n\n /**\n * Execute a parameterized query without returning results.\n */\n async execParams(sql: string, params: unknown[]): Promise<void> {\n const client = new Client({ connectionString: this.connectionString });\n try {\n await client.connect();\n await client.query(sql, params);\n } finally {\n await client.end();\n }\n }\n\n /**\n * Execute a query without returning results (for DDL/DML).\n */\n async exec(sql: string): Promise<void> {\n const client = new Client({ connectionString: this.connectionString });\n try {\n await client.connect();\n await client.query(sql);\n } finally {\n await client.end();\n }\n }\n\n /**\n * Execute operations within a transaction.\n * Automatically commits on success, rolls back on error.\n */\n async withTransaction<T>(fn: (client: pg.Client) => Promise<T>): Promise<T> {\n const client = new Client({ connectionString: this.connectionString });\n try {\n await client.connect();\n await client.query(\"BEGIN\");\n const result = await fn(client);\n await client.query(\"COMMIT\");\n return result;\n } catch (error) {\n await client.query(\"ROLLBACK\");\n throw error;\n } finally {\n await client.end();\n }\n }\n\n /**\n * Create a new database.\n */\n async createDatabase(name: string): Promise<void> {\n await this.exec(`CREATE DATABASE \"${name}\";`);\n }\n\n /**\n * Drop a database if it exists.\n */\n async dropDatabase(name: string): Promise<void> {\n await this.exec(`DROP DATABASE IF EXISTS \"${name}\";`);\n }\n\n /**\n * Create a Database instance connected to a different database.\n */\n withDatabase(name: string): Database {\n const newUrl = buildDbUrl(this.dbParts, name);\n return new Database(newUrl);\n }\n\n /**\n * Get connection URL for external tools (like migra).\n */\n getConnectionUrl(): string {\n return this.connectionString;\n }\n\n /**\n * Get parsed database URL parts.\n */\n getParts(): DbUrlParts {\n return this.dbParts;\n }\n\n /**\n * Install PostgreSQL extensions.\n */\n async installExtensions(extensions: string[]): Promise<void> {\n for (const ext of extensions) {\n try {\n await this.exec(`CREATE EXTENSION IF NOT EXISTS \"${ext}\";`);\n } catch {\n // Ignore extension errors - some might not be available\n }\n }\n }\n\n /**\n * Get column information for a table.\n */\n async getTableColumns(\n tableName: string\n ): Promise<{ column_name: string; ordinal_position: number }[]> {\n const result = await this.query(`\n SELECT column_name, ordinal_position\n FROM information_schema.columns\n WHERE table_name = '${tableName}'\n ORDER BY ordinal_position;\n `);\n return result.rows as { column_name: string; ordinal_position: number }[];\n }\n\n /**\n * List all tables in the public schema.\n */\n async listTables(): Promise<string[]> {\n const result = await this.query(`\n SELECT tablename FROM pg_tables WHERE schemaname = 'public';\n `);\n return result.rows.map((row) => row.tablename as string);\n }\n}\n","export interface DbUrlParts {\n url: string;\n protocol: string;\n user: string;\n password: string;\n host: string;\n port: string;\n database: string;\n params: string;\n}\n\n/**\n * Parse a PostgreSQL connection URL and encode special characters in password.\n * Handles URLs like: postgres://user:password@host:port/database?params\n */\nexport function parseAndEncodeDbUrl(rawUrl: string): DbUrlParts {\n const match = rawUrl.match(\n /^(postgres(?:ql)?):\\/\\/([^:]+):(.+)@([^:]+):(\\d+)\\/([^?]+)(\\?.*)?$/\n );\n\n if (!match) {\n throw new Error(\n 'Invalid DATABASE_URL format. Expected: postgres://user:password@host:port/database'\n );\n }\n\n const [, protocol, user, password, host, port, database, params = ''] = match;\n const encodedPassword = encodeURIComponent(password);\n\n return {\n url: `${protocol}://${user}:${encodedPassword}@${host}:${port}/${database}${params}`,\n protocol,\n user,\n password: encodedPassword,\n host,\n port,\n database,\n params,\n };\n}\n\n/**\n * Build a connection URL with a different database name.\n */\nexport function buildDbUrl(parts: DbUrlParts, database: string): string {\n return `${parts.protocol}://${parts.user}:${parts.password}@${parts.host}:${parts.port}/${database}${parts.params}`;\n}\n","import { readdirSync, statSync, readFileSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { generateReverseSql } from \"./reverse.js\";\n\nexport interface MigrationFile {\n name: string;\n path: string;\n version: string;\n mtime: number;\n}\n\n/**\n * List all migration files in a directory.\n */\nexport function listMigrations(migrationsDir: string): MigrationFile[] {\n try {\n const files = readdirSync(migrationsDir);\n return files\n .filter((f) => f.endsWith(\".sql\"))\n .map((f) => {\n const path = join(migrationsDir, f);\n const match = f.match(/^(\\d+)/);\n return {\n name: f,\n path,\n version: match ? match[1] : f,\n mtime: statSync(path).mtime.getTime(),\n };\n })\n .sort((a, b) => a.version.localeCompare(b.version));\n } catch {\n return [];\n }\n}\n\n/**\n * Get the most recently created migration file.\n */\nexport function getMostRecentMigration(\n migrationsDir: string\n): MigrationFile | null {\n const migrations = listMigrations(migrationsDir);\n if (migrations.length === 0) return null;\n\n return migrations.reduce((most, current) =>\n current.mtime > most.mtime ? current : most\n );\n}\n\n/**\n * Generate a new migration filename with timestamp.\n */\nexport function generateMigrationFilename(name: string): string {\n const timestamp = new Date().toISOString().replace(/[-:T]/g, \"\").slice(0, 14);\n const sanitized = name.replace(/\\s+/g, \"_\").toLowerCase();\n return `${timestamp}_${sanitized}.sql`;\n}\n\n/**\n * Create a new migration file with dbmate format.\n */\nexport function createMigrationFile(\n migrationsDir: string,\n name: string,\n upSql: string = \"\",\n downSql: string = \"\"\n): string {\n const filename = generateMigrationFilename(name);\n const filepath = join(migrationsDir, filename);\n\n // Auto-generate down SQL if not provided and up SQL exists\n if (!downSql && upSql) {\n downSql = generateReverseSql(upSql);\n }\n\n const content = `-- migrate:up\n${upSql}\n\n-- migrate:down\n${downSql}\n`;\n\n writeFileSync(filepath, content, \"utf-8\");\n return filepath;\n}\n\n/**\n * Update an existing migration file with SQL.\n */\nexport function updateMigrationFile(filepath: string, upSql: string): void {\n const content = readFileSync(filepath, \"utf-8\");\n const updated = content.replace(\n /-- migrate:up\\n/,\n `-- migrate:up\\n${upSql}\\n\\n`\n );\n writeFileSync(filepath, updated, \"utf-8\");\n}\n\n/**\n * Parse a migration file into up and down sections.\n */\nexport function parseMigrationFile(filepath: string): {\n up: string;\n down: string;\n} {\n const content = readFileSync(filepath, \"utf-8\");\n const upMatch = content.match(\n /-- migrate:up\\n([\\s\\S]*?)(?=-- migrate:down|$)/\n );\n const downMatch = content.match(/-- migrate:down\\n([\\s\\S]*?)$/);\n\n return {\n up: upMatch ? upMatch[1].trim() : \"\",\n down: downMatch ? downMatch[1].trim() : \"\",\n };\n}\n","/**\n * Generate reverse SQL for simple DDL statements.\n * LIMITATION: Only supports basic CREATE/DROP TABLE/INDEX and ADD/DROP COLUMN.\n * Complex changes (ALTER COLUMN type, constraints) need manual intervention.\n */\nexport function generateReverseSql(upSql: string): string {\n if (!upSql) return \"\";\n\n const downStatements: string[] = [];\n const lines = upSql\n .split(\";\")\n .map((l) => l.trim())\n .filter((l) => l);\n\n for (const line of lines) {\n // CREATE TABLE x -> DROP TABLE x\n const createTableMatch = line.match(\n /CREATE\\s+TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?([^\\s(]+)/i\n );\n if (createTableMatch) {\n const tableName = createTableMatch[1];\n downStatements.push(`DROP TABLE ${tableName};`);\n continue;\n }\n\n // DROP TABLE x -> Manual\n const dropTableMatch = line.match(\n /DROP\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?([^\\s;]+)/i\n );\n if (dropTableMatch) {\n const tableName = dropTableMatch[1];\n downStatements.push(`-- Manual: Recreate table ${tableName}`);\n continue;\n }\n\n // ALTER TABLE x ADD COLUMN y -> ALTER TABLE x DROP COLUMN y\n const addColumnMatch = line.match(\n /ALTER\\s+TABLE\\s+([^\\s]+)\\s+ADD\\s+(?:COLUMN\\s+)?([^\\s;]+)/i\n );\n if (addColumnMatch) {\n const [, tableName, colName] = addColumnMatch;\n downStatements.push(`ALTER TABLE ${tableName} DROP COLUMN ${colName};`);\n continue;\n }\n\n // ALTER TABLE x DROP COLUMN y -> Manual\n const dropColumnMatch = line.match(\n /ALTER\\s+TABLE\\s+([^\\s]+)\\s+DROP\\s+(?:COLUMN\\s+)?([^\\s;]+)/i\n );\n if (dropColumnMatch) {\n const [, tableName, colName] = dropColumnMatch;\n downStatements.push(\n `-- Manual: Add column ${colName} back to table ${tableName}`\n );\n continue;\n }\n\n // CREATE INDEX x -> DROP INDEX x\n const createIndexMatch = line.match(\n /CREATE\\s+(?:UNIQUE\\s+)?INDEX\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?([^\\s]+)\\s+ON/i\n );\n if (createIndexMatch) {\n const indexName = createIndexMatch[1];\n downStatements.push(`DROP INDEX ${indexName};`);\n continue;\n }\n\n // DROP INDEX x -> Manual\n const dropIndexMatch = line.match(\n /DROP\\s+INDEX\\s+(?:IF\\s+EXISTS\\s+)?([^\\s;]+)/i\n );\n if (dropIndexMatch) {\n const indexName = dropIndexMatch[1];\n downStatements.push(`-- Manual: Recreate index ${indexName}`);\n continue;\n }\n\n // Fallback\n downStatements.push(`-- Manual: Revert ${line.substring(0, 50)}...`);\n }\n\n // Reverse the order of down statements\n return downStatements.reverse().join(\"\\n\");\n}\n","import { Database } from \"./database.js\";\nimport {\n listMigrations,\n parseMigrationFile,\n type MigrationFile,\n} from \"./migrations.js\";\n\nconst SCHEMA_MIGRATIONS_TABLE = \"schema_migrations\";\n\n/**\n * Migration runner - replaces dbmate functionality.\n */\nexport class MigrationRunner {\n private db: Database;\n private migrationsDir: string;\n\n constructor(db: Database, migrationsDir: string) {\n this.db = db;\n this.migrationsDir = migrationsDir;\n }\n\n /**\n * Ensure schema_migrations table exists.\n */\n async ensureTable(): Promise<void> {\n await this.db.exec(`\n CREATE TABLE IF NOT EXISTS ${SCHEMA_MIGRATIONS_TABLE} (\n version VARCHAR(255) PRIMARY KEY\n );\n `);\n }\n\n /**\n * Get list of applied migration versions.\n */\n async getAppliedVersions(): Promise<Set<string>> {\n await this.ensureTable();\n const result = await this.db.query(\n `SELECT version FROM ${SCHEMA_MIGRATIONS_TABLE};`\n );\n return new Set(result.rows.map((row) => row.version as string));\n }\n\n /**\n * Mark a migration as applied.\n */\n async markApplied(version: string, client?: any): Promise<void> {\n await this.ensureTable();\n const sql = `\n INSERT INTO ${SCHEMA_MIGRATIONS_TABLE} (version)\n VALUES ($1)\n ON CONFLICT DO NOTHING;\n `;\n\n if (client) {\n await client.query(sql, [version]);\n } else {\n await this.db.execParams(sql, [version]);\n }\n }\n\n /**\n * Mark a migration as not applied (for rollback).\n */\n async markUnapplied(version: string, client?: any): Promise<void> {\n const sql = `\n DELETE FROM ${SCHEMA_MIGRATIONS_TABLE}\n WHERE version = $1;\n `;\n\n if (client) {\n await client.query(sql, [version]);\n } else {\n await this.db.execParams(sql, [version]);\n }\n }\n\n /**\n * Get pending migrations (not yet applied).\n */\n async getPendingMigrations(): Promise<MigrationFile[]> {\n const all = listMigrations(this.migrationsDir);\n const applied = await this.getAppliedVersions();\n return all.filter((m) => !applied.has(m.version));\n }\n\n /**\n * Apply a single migration.\n */\n async applyMigration(migration: MigrationFile): Promise<void> {\n const { up } = parseMigrationFile(migration.path);\n\n await this.db.withTransaction(async (client) => {\n if (up) {\n await client.query(up);\n }\n await this.markApplied(migration.version, client);\n });\n }\n\n /**\n * Roll back a single migration.\n */\n async rollbackMigration(migration: MigrationFile): Promise<void> {\n const { down } = parseMigrationFile(migration.path);\n\n await this.db.withTransaction(async (client) => {\n if (down) {\n await client.query(down);\n }\n await this.markUnapplied(migration.version, client);\n });\n }\n\n /**\n * Apply all pending migrations.\n */\n async migrateUp(): Promise<MigrationFile[]> {\n const pending = await this.getPendingMigrations();\n for (const migration of pending) {\n await this.applyMigration(migration);\n }\n return pending;\n }\n\n /**\n * Get migration status.\n */\n async status(): Promise<{\n applied: MigrationFile[];\n pending: MigrationFile[];\n }> {\n const all = listMigrations(this.migrationsDir);\n const appliedVersions = await this.getAppliedVersions();\n\n return {\n applied: all.filter((m) => appliedVersions.has(m.version)),\n pending: all.filter((m) => !appliedVersions.has(m.version)),\n };\n }\n}\n","import { Parser, ModelExporter } from '@dbml/core';\n\nexport interface DbmlResult {\n sql: string;\n}\n\n/**\n * Convert DBML schema to PostgreSQL SQL.\n */\nexport function dbmlToSql(dbmlContent: string): DbmlResult {\n const database = new Parser().parse(dbmlContent, 'dbml');\n const sql = ModelExporter.export(database, 'postgres');\n return { sql };\n}\n","import { execFileSync } from 'child_process';\n\nexport interface MigraResult {\n sql: string;\n hasChanges: boolean;\n}\n\n/**\n * Run migra to generate schema diff between two databases.\n *\n * Exit codes:\n * - 0: No differences\n * - 2: Differences found (SQL output on stdout)\n * - 1: Error\n */\nexport function runMigra(\n fromUrl: string,\n toUrl: string,\n options: { unsafe?: boolean } = {}\n): MigraResult {\n const args = [fromUrl, toUrl];\n if (options.unsafe) {\n args.push('--unsafe');\n }\n\n try {\n const output = execFileSync('migra', args, {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n // Exit code 0 = no changes\n return { sql: output || '', hasChanges: false };\n } catch (error) {\n const err = error as { status?: number; stdout?: string; stderr?: string };\n\n if (err.status === 2 && err.stdout) {\n // Exit code 2 = changes found\n return { sql: err.stdout, hasChanges: true };\n }\n\n if (err.status === 1) {\n throw new Error(`migra error: ${err.stderr || 'Unknown error'}`);\n }\n\n // Other exit codes - might still have output\n return { sql: err.stdout || '', hasChanges: Boolean(err.stdout) };\n }\n}\n\n/**\n * Filter out schema_migrations table from migration SQL.\n */\nexport function filterSchemaMigrations(sql: string): string {\n return sql\n .split('\\n')\n .filter((line) => !line.includes('schema_migrations'))\n .join('\\n')\n .trim();\n}\n","import { existsSync } from 'fs';\nimport { join } from 'path';\nimport { pathToFileURL } from 'url';\nimport { config as loadDotenv } from 'dotenv';\n\nexport interface NexusqlConfig {\n schema: string;\n migrations: string;\n extensions: string[];\n databaseUrl?: string;\n}\n\nconst DEFAULT_CONFIG: NexusqlConfig = {\n schema: './schema.dbml',\n migrations: './db/migrations',\n extensions: ['uuid-ossp'],\n};\n\n/**\n * Load configuration from nexusql.config.js or defaults.\n */\nexport async function loadConfig(cwd: string = process.cwd()): Promise<NexusqlConfig> {\n // Load .env file\n loadDotenv();\n\n const configPath = join(cwd, 'nexusql.config.js');\n let userConfig: Partial<NexusqlConfig> = {};\n\n if (existsSync(configPath)) {\n try {\n const configUrl = pathToFileURL(configPath).href;\n const module = await import(configUrl);\n userConfig = module.default || module;\n } catch {\n // Ignore config load errors, use defaults\n }\n }\n\n return {\n ...DEFAULT_CONFIG,\n ...userConfig,\n databaseUrl: process.env.DATABASE_URL || userConfig.databaseUrl,\n };\n}\n\n/**\n * Get database URL from config or environment.\n */\nexport function getDatabaseUrl(config: NexusqlConfig): string {\n const url = config.databaseUrl || process.env.DATABASE_URL;\n if (!url) {\n throw new Error('DATABASE_URL not set. Set it in .env or nexusql.config.js');\n }\n return url;\n}\n\n/**\n * Generate default config file content.\n */\nexport function generateConfigTemplate(): string {\n return `/** @type {import('nexusql').NexusqlConfig} */\nexport default {\n // Path to your DBML schema file\n schema: './schema.dbml',\n\n // Directory for migration files\n migrations: './db/migrations',\n\n // PostgreSQL extensions to install in temp database\n extensions: ['uuid-ossp'],\n};\n`;\n}\n","import { readFileSync, writeFileSync } from 'fs';\nimport { resolve } from 'path';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport { Database } from '../lib/database.js';\nimport { dbmlToSql } from '../lib/dbml.js';\nimport { runMigra, filterSchemaMigrations } from '../lib/migra.js';\nimport { loadConfig, getDatabaseUrl } from '../lib/config.js';\n\nexport interface GenOptions {\n output?: string;\n verbose?: boolean;\n}\n\n/**\n * Generate migration SQL by diffing current DB against DBML schema.\n */\nexport async function gen(options: GenOptions = {}): Promise<string> {\n const config = await loadConfig();\n const databaseUrl = getDatabaseUrl(config);\n const db = new Database(databaseUrl);\n\n const spinner = ora();\n\n // Read DBML schema\n spinner.start('Reading DBML schema...');\n const schemaPath = resolve(config.schema);\n let dbmlContent: string;\n try {\n dbmlContent = readFileSync(schemaPath, 'utf-8');\n spinner.succeed('Read DBML schema');\n } catch {\n spinner.fail(`Failed to read schema: ${schemaPath}`);\n throw new Error(`Schema file not found: ${schemaPath}`);\n }\n\n // Convert DBML to SQL\n spinner.start('Converting DBML to SQL...');\n const { sql: targetSql } = dbmlToSql(dbmlContent);\n spinner.succeed('Converted DBML to SQL');\n\n // Create temp database\n const tempDbName = `nexusql_temp_${Date.now()}`;\n spinner.start(`Creating temp database: ${tempDbName}`);\n try {\n await db.createDatabase(tempDbName);\n spinner.succeed(`Created temp database: ${tempDbName}`);\n } catch (error) {\n spinner.fail('Failed to create temp database');\n throw error;\n }\n\n const tempDb = db.withDatabase(tempDbName);\n let migrationSql = '';\n\n try {\n // Install extensions\n spinner.start('Installing extensions...');\n await tempDb.installExtensions(config.extensions);\n spinner.succeed('Installed extensions');\n\n // Load schema into temp database\n spinner.start('Loading schema into temp database...');\n await tempDb.exec(targetSql);\n spinner.succeed('Loaded schema into temp database');\n\n // Debug: List tables\n if (options.verbose) {\n const tables = await tempDb.listTables();\n console.log(chalk.dim(`\\nTables in temp database: ${tables.join(', ')}`));\n }\n\n // Run migra to generate diff\n spinner.start('Generating migration diff...');\n const migraResult = runMigra(\n db.getConnectionUrl(),\n tempDb.getConnectionUrl(),\n { unsafe: true }\n );\n\n migrationSql = filterSchemaMigrations(migraResult.sql);\n\n if (migraResult.hasChanges) {\n spinner.succeed('Generated migration diff');\n } else {\n spinner.info('No schema changes detected');\n }\n\n // Get comment changes\n spinner.start('Checking comment changes...');\n const commentSql = await getCommentChanges(db, tempDb);\n if (commentSql) {\n migrationSql = migrationSql\n ? `${migrationSql}\\n\\n-- Comment changes\\n${commentSql}`\n : `-- Comment changes\\n${commentSql}`;\n }\n spinner.succeed('Checked comment changes');\n } finally {\n // Cleanup temp database\n spinner.start('Cleaning up temp database...');\n try {\n await db.dropDatabase(tempDbName);\n spinner.succeed('Cleaned up temp database');\n } catch {\n spinner.warn('Failed to cleanup temp database');\n }\n }\n\n // Output result\n const finalSql = migrationSql || '-- No changes detected';\n\n if (options.output) {\n writeFileSync(options.output, finalSql, 'utf-8');\n console.log(chalk.green(`\\nMigration SQL written to: ${options.output}`));\n } else {\n console.log(chalk.cyan('\\n=== Migration SQL ===\\n'));\n console.log(finalSql);\n }\n\n return finalSql;\n}\n\n/**\n * Get comment changes between two databases.\n * migra doesn't support COMMENT ON statements.\n */\nasync function getCommentChanges(\n currentDb: Database,\n targetDb: Database\n): Promise<string> {\n const commentQuery = `\n SELECT\n format('COMMENT ON COLUMN %I.%I IS %L;',\n c.table_name,\n c.column_name,\n pgd.description\n ) as comment_sql,\n c.table_name,\n c.column_name,\n pgd.description\n FROM information_schema.columns c\n JOIN pg_catalog.pg_class pc ON pc.relname = c.table_name\n JOIN pg_catalog.pg_namespace pn ON pn.oid = pc.relnamespace AND pn.nspname = c.table_schema\n LEFT JOIN pg_catalog.pg_description pgd ON pgd.objoid = pc.oid AND pgd.objsubid = c.ordinal_position\n WHERE c.table_schema = 'public'\n AND c.table_name != 'schema_migrations'\n ORDER BY c.table_name, c.ordinal_position;\n `;\n\n const [currentComments, targetComments] = await Promise.all([\n currentDb.query(commentQuery),\n targetDb.query(commentQuery),\n ]);\n\n const currentMap = new Map<string, string | null>();\n const targetMap = new Map<string, { sql: string; description: string | null }>();\n\n for (const row of currentComments.rows) {\n const key = `${row.table_name}.${row.column_name}`;\n currentMap.set(key, row.description as string | null);\n }\n\n for (const row of targetComments.rows) {\n const key = `${row.table_name}.${row.column_name}`;\n targetMap.set(key, {\n sql: row.comment_sql as string,\n description: row.description as string | null,\n });\n }\n\n const commentDiffs: string[] = [];\n\n for (const [key, target] of targetMap) {\n const current = currentMap.get(key);\n if (current !== target.description && target.sql) {\n commentDiffs.push(target.sql);\n }\n }\n\n return commentDiffs.join('\\n');\n}\n","import { mkdirSync, existsSync } from \"fs\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { gen } from \"./gen.js\";\nimport { Database } from \"../lib/database.js\";\nimport { MigrationRunner } from \"../lib/runner.js\";\nimport { createMigrationFile } from \"../lib/migrations.js\";\nimport { loadConfig, getDatabaseUrl } from \"../lib/config.js\";\nimport { question, confirm, closePrompts } from \"../utils/prompts.js\";\n\nexport interface MigrateOptions {\n name?: string;\n apply?: boolean;\n yes?: boolean;\n}\n\n/**\n * Interactive migration workflow.\n */\nexport async function migrate(options: MigrateOptions = {}): Promise<void> {\n const config = await loadConfig();\n const databaseUrl = getDatabaseUrl(config);\n const db = new Database(databaseUrl);\n const runner = new MigrationRunner(db, config.migrations);\n\n console.log(chalk.bold(\"\\nInteractive Database Migration\\n\"));\n console.log(\"This will:\");\n console.log(\" 1. Generate migration diff from DBML\");\n console.log(\" 2. Create a new migration file\");\n console.log(\" 3. Optionally apply the migration\\n\");\n\n try {\n // Step 1: Generate diff\n console.log(chalk.cyan(\"Step 1: Generating migration diff...\\n\"));\n const migrationSql = await gen({ verbose: false });\n\n const noChanges =\n !migrationSql || migrationSql === \"-- No changes detected\";\n\n if (noChanges) {\n console.log(chalk.yellow(\"\\nNo schema changes detected.\\n\"));\n\n if (!options.yes) {\n const proceed = await confirm(\n \"Do you still want to create an empty migration?\"\n );\n if (!proceed) {\n console.log(chalk.red(\"\\nMigration cancelled.\"));\n return;\n }\n }\n }\n\n // Step 2: Get migration name\n console.log(chalk.cyan(\"\\n--- Step 2: Create Migration File ---\\n\"));\n\n let migrationName = options.name;\n if (!migrationName) {\n migrationName = await question(\n 'Enter migration name (e.g., \"add_users_table\"): '\n );\n }\n\n if (!migrationName || migrationName.trim() === \"\") {\n console.log(chalk.red(\"\\nMigration name cannot be empty. Exiting...\"));\n return;\n }\n\n const sanitizedName = migrationName.trim().replace(/\\s+/g, \"_\");\n console.log(chalk.green(`\\nUsing migration name: ${sanitizedName}`));\n\n // Confirm before creating\n if (!options.yes) {\n const proceed = await confirm(\"\\nCreate this migration?\");\n if (!proceed) {\n console.log(chalk.red(\"\\nMigration cancelled.\"));\n return;\n }\n }\n\n // Create migrations directory if needed\n if (!existsSync(config.migrations)) {\n mkdirSync(config.migrations, { recursive: true });\n }\n\n // Create migration file\n const spinner = ora(\"Creating migration file...\").start();\n const filepath = createMigrationFile(\n config.migrations,\n sanitizedName,\n noChanges ? \"\" : migrationSql\n );\n spinner.succeed(`Created migration file: ${filepath}`);\n\n // Step 3: Apply migration\n console.log(chalk.cyan(\"\\n--- Step 3: Apply Migration ---\\n\"));\n\n let shouldApply = options.apply;\n if (shouldApply === undefined && !options.yes) {\n shouldApply = await confirm(\"Apply this migration now?\");\n }\n\n if (shouldApply) {\n const applySpinner = ora(\"Applying migration...\").start();\n try {\n const applied = await runner.migrateUp();\n if (applied.length > 0) {\n applySpinner.succeed(\n `Applied ${applied.length} migration(s) successfully`\n );\n } else {\n applySpinner.info(\"No pending migrations to apply\");\n }\n } catch (error) {\n applySpinner.fail(\"Failed to apply migration\");\n throw error;\n }\n } else {\n console.log(chalk.dim(\"\\nMigration created but not applied.\"));\n console.log(chalk.dim(`Run \"nexusql up\" to apply pending migrations.`));\n }\n\n console.log(chalk.green(`\\nMigration file: ${filepath}\\n`));\n } finally {\n closePrompts();\n }\n}\n\n/**\n * Apply all pending migrations.\n */\nexport async function up(options: { dryRun?: boolean } = {}): Promise<void> {\n const config = await loadConfig();\n const databaseUrl = getDatabaseUrl(config);\n const db = new Database(databaseUrl);\n const runner = new MigrationRunner(db, config.migrations);\n\n const spinner = ora(\"Checking migrations...\").start();\n\n try {\n const pending = await runner.getPendingMigrations();\n\n if (pending.length === 0) {\n spinner.info(\"No pending migrations\");\n return;\n }\n\n if (options.dryRun) {\n spinner.info(`found ${pending.length} pending migration(s):`);\n for (const m of pending) {\n console.log(chalk.cyan(` ○ ${m.name}`));\n }\n return;\n }\n\n spinner.text = \"Applying migrations...\";\n for (const migration of pending) {\n await runner.applyMigration(migration);\n console.log(chalk.green(` ✓ ${migration.name}`));\n }\n spinner.succeed(`Applied ${pending.length} migration(s)`);\n } catch (error) {\n spinner.fail(\"Migration failed\");\n throw error;\n }\n}\n\n/**\n * Rollback applied migrations.\n */\nexport async function down(\n options: { steps?: number; to?: string; dryRun?: boolean } = {}\n): Promise<void> {\n const config = await loadConfig();\n const databaseUrl = getDatabaseUrl(config);\n const db = new Database(databaseUrl);\n const runner = new MigrationRunner(db, config.migrations);\n\n const spinner = ora(\"Checking migrations...\").start();\n\n try {\n // Optimization: status() reads all files. A more efficient way to get ordered applied migrations is needed if history is huge.\n // For now, sorting 'applied' from status() works.\n const { applied } = await runner.status();\n const sortedApplied = applied.sort((a, b) =>\n b.version.localeCompare(a.version)\n ); // Newest first\n\n if (sortedApplied.length === 0) {\n spinner.info(\"No applied migrations to rollback\");\n return;\n }\n\n let toRollback: typeof applied = [];\n\n if (options.to) {\n const targetIndex = sortedApplied.findIndex(\n (m) => m.version === options.to\n );\n if (targetIndex === -1) {\n // If options.to is \"rollback to version X\", we want to rollback everything > X.\n // Let's assume options.to is the target version we want to KEEP.\n // So we rollback everything where version > options.to\n toRollback = sortedApplied.filter((m) => m.version > options.to!);\n if (toRollback.length === 0) {\n spinner.info(\n `Version ${options.to} is already the latest applied or doesn't exist in future history.`\n );\n return;\n }\n } else {\n // Rollback migrations newer than X.\n toRollback = sortedApplied.filter((m) => m.version > options.to!);\n }\n } else {\n const steps = options.steps ?? 1;\n toRollback = sortedApplied.slice(0, steps);\n }\n\n if (toRollback.length === 0) {\n spinner.info(\"No migrations to rollback\");\n return;\n }\n\n if (options.dryRun) {\n spinner.info(`Would rollback ${toRollback.length} migration(s):`);\n for (const m of toRollback) {\n console.log(chalk.yellow(` ○ ${m.name}`));\n }\n return;\n }\n\n spinner.text = \"Rolling back migrations...\";\n for (const migration of toRollback) {\n await runner.rollbackMigration(migration);\n console.log(chalk.yellow(` reverted ${migration.name}`));\n }\n spinner.succeed(`Rolled back ${toRollback.length} migration(s)`);\n } catch (error) {\n spinner.fail(\"Rollback failed\");\n throw error;\n }\n}\n\n/**\n * Show migration status.\n */\nexport async function status(): Promise<void> {\n const config = await loadConfig();\n const databaseUrl = getDatabaseUrl(config);\n const db = new Database(databaseUrl);\n const runner = new MigrationRunner(db, config.migrations);\n\n const spinner = ora(\"Checking migration status...\").start();\n const { applied, pending } = await runner.status();\n spinner.stop();\n\n console.log(chalk.bold(\"\\nMigration Status\\n\"));\n\n if (applied.length > 0) {\n console.log(chalk.green(\"Applied:\"));\n for (const m of applied) {\n console.log(chalk.green(` ✓ ${m.name}`));\n }\n }\n\n if (pending.length > 0) {\n console.log(chalk.yellow(\"\\nPending:\"));\n for (const m of pending) {\n console.log(chalk.yellow(` ○ ${m.name}`));\n }\n }\n\n if (applied.length === 0 && pending.length === 0) {\n console.log(chalk.dim(\"No migrations found.\"));\n }\n\n console.log();\n}\n","import * as readline from 'readline';\n\nlet rl: readline.Interface | null = null;\n\n/**\n * Get or create readline interface.\n */\nfunction getReadline(): readline.Interface {\n if (!rl) {\n rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n }\n return rl;\n}\n\n/**\n * Close readline interface.\n */\nexport function closePrompts(): void {\n if (rl) {\n rl.close();\n rl = null;\n }\n}\n\n/**\n * Ask user a question and return their answer.\n */\nexport function question(query: string): Promise<string> {\n return new Promise((resolve) => {\n getReadline().question(query, (answer) => {\n resolve(answer);\n });\n });\n}\n\n/**\n * Ask a yes/no question.\n */\nexport async function confirm(query: string): Promise<boolean> {\n const answer = await question(`${query} (yes/no): `);\n return answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y';\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { Database } from '../lib/database.js';\nimport { MigrationRunner } from '../lib/runner.js';\nimport { loadConfig, getDatabaseUrl } from '../lib/config.js';\n\n/**\n * Mark a migration as applied without running it.\n */\nexport async function markApplied(version: string): Promise<void> {\n if (!version) {\n console.error(chalk.red('Error: Migration version is required'));\n console.log(chalk.dim('\\nUsage: nexusql mark-applied <version>'));\n console.log(chalk.dim('Example: nexusql mark-applied 20251209153535'));\n process.exit(1);\n }\n\n const config = await loadConfig();\n const databaseUrl = getDatabaseUrl(config);\n const db = new Database(databaseUrl);\n const runner = new MigrationRunner(db, config.migrations);\n\n const spinner = ora(`Marking migration ${version} as applied...`).start();\n\n try {\n await runner.markApplied(version);\n spinner.succeed(`Migration ${version} marked as applied`);\n } catch (error) {\n spinner.fail('Failed to mark migration as applied');\n throw error;\n }\n}\n","import { writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport chalk from 'chalk';\nimport { generateConfigTemplate } from '../lib/config.js';\n\nexport interface InitOptions {\n force?: boolean;\n}\n\n/**\n * Initialize nexusql configuration.\n */\nexport async function init(options: InitOptions = {}): Promise<void> {\n const cwd = process.cwd();\n\n // Create config file\n const configPath = join(cwd, 'nexusql.config.js');\n\n if (existsSync(configPath) && !options.force) {\n console.log(chalk.yellow('nexusql.config.js already exists.'));\n console.log(chalk.dim('Use --force to overwrite.'));\n return;\n }\n\n writeFileSync(configPath, generateConfigTemplate(), 'utf-8');\n console.log(chalk.green('Created nexusql.config.js'));\n\n // Create migrations directory\n const migrationsDir = join(cwd, 'db', 'migrations');\n if (!existsSync(migrationsDir)) {\n mkdirSync(migrationsDir, { recursive: true });\n console.log(chalk.green('Created db/migrations/'));\n }\n\n // Create .env.example if it doesn't exist\n const envExamplePath = join(cwd, '.env.example');\n if (!existsSync(envExamplePath)) {\n writeFileSync(\n envExamplePath,\n 'DATABASE_URL=postgres://user:password@localhost:5432/database\\n',\n 'utf-8'\n );\n console.log(chalk.green('Created .env.example'));\n }\n\n console.log(chalk.bold('\\nNext steps:'));\n console.log(' 1. Copy .env.example to .env and set your DATABASE_URL');\n console.log(' 2. Create your schema.dbml file');\n console.log(' 3. Run \"nexusql gen\" to generate migration SQL');\n console.log(' 4. Run \"nexusql migrate\" to create and apply migrations\\n');\n}\n"],"mappings":"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","names":["up","join","readFileSync","writeFileSync","readFileSync","writeFileSync","existsSync","chalk","ora","resolve","chalk","existsSync","ora","ora","chalk","chalk","ora","chalk","ora","writeFileSync","existsSync","mkdirSync","join","chalk","join","existsSync","chalk","writeFileSync","mkdirSync"]}
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "nexusql",
3
+ "version": "0.1.0",
4
+ "description": "Database migration toolkit for PostgreSQL with DBML schema support",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "nexusql": "./bin/nexusql.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.js",
14
+ "types": "./dist/index.d.ts"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "bin"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsup",
23
+ "dev": "tsup --watch",
24
+ "prepublishOnly": "pnpm run build",
25
+ "typecheck": "tsc --noEmit",
26
+ "test": "vitest"
27
+ },
28
+ "keywords": [
29
+ "postgresql",
30
+ "postgres",
31
+ "database",
32
+ "migration",
33
+ "schema",
34
+ "dbml",
35
+ "sql",
36
+ "cli"
37
+ ],
38
+ "author": "Fibonacci Forge",
39
+ "license": "MIT",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/Fibonacci-Forge/nexusql.git"
43
+ },
44
+ "bugs": {
45
+ "url": "https://github.com/Fibonacci-Forge/nexusql/issues"
46
+ },
47
+ "homepage": "https://github.com/Fibonacci-Forge/nexusql#readme",
48
+ "engines": {
49
+ "node": ">=18"
50
+ },
51
+ "dependencies": {
52
+ "@dbml/core": "^3.8.1",
53
+ "chalk": "^5.3.0",
54
+ "commander": "^12.1.0",
55
+ "dotenv": "^16.4.7",
56
+ "ora": "^8.1.1",
57
+ "pg": "^8.13.1"
58
+ },
59
+ "devDependencies": {
60
+ "@types/node": "^22.10.2",
61
+ "@types/pg": "^8.11.10",
62
+ "tsup": "^8.3.5",
63
+ "typescript": "^5.7.2",
64
+ "vitest": "^1.0.0"
65
+ }
66
+ }