@noego/proper 0.2.0 → 0.2.1
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.
- package/bin/cli.js +7 -3
- package/bin/cli.js.map +1 -1
- package/bin/cli.mjs +8 -3
- package/bin/cli.mjs.map +1 -1
- package/bin/index.js +7 -3
- package/bin/index.js.map +1 -1
- package/bin/index.mjs +7 -3
- package/bin/index.mjs.map +1 -1
- package/package.json +1 -1
- package/readme.md +5 -0
package/bin/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../framework/MigrationRunner.ts","../framework/MigrationDirectoryReader.ts","../framework/errors.ts","../framework/MigrationNode.ts","../framework/SqlMigrationBuilder.ts","../framework/MigrationManifest.ts","../framework/MigrationSetup.ts","../framework/PatchTypes.ts","../framework/MigrationFilter.ts","../framework/MigrationDialectParser.ts","../framework/PatchDirectoryReader.ts","../framework/PatchValidator.ts","../framework/PatchRunner.ts","../framework/PatchCreator.ts","../framework/SQLRunner.ts","../framework/SeedRunner.ts"],"sourcesContent":["// Node built-in modules\nimport fs from 'fs';\n\n// Database driver types (value imports are lazy – see createConnection())\nimport type mysql from 'mysql2/promise';\n\n// Helper function to convert any error to Error object\nfunction toError(error: unknown): Error {\n if (error instanceof Error) return error;\n return new Error(String(error));\n}\n\n// Migration framework\nimport { MigrationConfig } from \"./MigrationConfig\";\nimport { MigrationDirectoryReader } from './MigrationDirectoryReader';\nimport { MigrationNode } from './MigrationNode';\nimport { MigrationSetup } from './MigrationSetup';\nimport { migration_filter } from './MigrationFilter';\nimport * as dialect from \"./MigrationDialectParser\";\nimport { PatchRunner } from './PatchRunner';\nimport { PatchCreator } from './PatchCreator';\nimport { PatchApplyResult, resolvePatchFolder } from './PatchTypes';\n\n\nimport { ISQLRunner,SQLRunner,SQLiteRunner,PgRunner } from './SQLRunner';\n\ntype Dialect = 'sql' | 'sqlite' | 'pg';\n\nfunction makeRunner(database: string, conn: any): ISQLRunner {\n switch(database as Dialect){\n case \"sql\":\n return new SQLRunner(conn);\n case \"sqlite\":\n return new SQLiteRunner(conn);\n case \"pg\":\n return new PgRunner(conn);\n default:\n throw ConfigurationError.unknownDatabaseType(database);\n }\n}\nimport { ErrorMessage } from './ErrorMessage';\nimport { \n ConfigurationError, \n DatabaseConnectionError, \n MigrationExecutionError,\n CLIError \n} from './errors';\n\n\nexport function loadMigrationConfig(configFile: string): MigrationConfig {\n const reader = new FileMigrationConfigReader(configFile);\n return reader.loadFile();\n}\n\nexport class MigrationRunnerFactory {\n\n private static isSQLRunner(conn: any): conn is ISQLRunner {\n return !!conn\n && typeof conn.query === \"function\"\n && typeof conn.execute === \"function\"\n && typeof conn.end === \"function\";\n }\n\n static async create(configFile:string,conn?:any){\n const configReader = new FileMigrationConfigReader(configFile);\n const config = configReader.loadFile();\n\n let factoryOwnsConnection = false;\n if(!conn){\n conn = await this.createConnection(config)\n factoryOwnsConnection = true;\n }\n return new MigrationRunnerFactory().create(config,conn,factoryOwnsConnection)\n }\n\n static async createConnection(config:MigrationConfig){\n let conn = null as any\n switch(config.database){\n case \"sql\":\n if (!config.sql){\n throw ConfigurationError.missingDatabaseConfiguration(\"sql\");\n }\n const settings = Object.assign({\n password:process.env.SQL_PASSWORD\n },config.sql);\n try {\n const mysql = await import('mysql2/promise');\n conn = await (mysql.default?.createConnection ?? mysql.createConnection)(settings);\n return conn;\n } catch (error) {\n throw DatabaseConnectionError.connectionFailed(\"sql\", toError(error).message);\n }\n case \"sqlite\":\n if (!config.sqlite){\n throw ConfigurationError.missingDatabaseConfiguration(\"sqlite\");\n }\n try {\n const sqlite = await import('sqlite');\n const sqlite3 = await import('sqlite3');\n conn = await (sqlite.default?.open ?? sqlite.open)({\n filename:config.sqlite.database,\n driver:sqlite3.default?.Database ?? sqlite3.Database\n });\n return conn;\n } catch (error) {\n throw DatabaseConnectionError.connectionFailed(\"sqlite\", toError(error).message);\n }\n case \"pg\":\n if (!config.pg && !process.env.DATABASE_URL){\n throw ConfigurationError.missingDatabaseConfiguration(\"pg\");\n }\n try {\n const pgcfg = config.pg ?? {};\n const connectionString = pgcfg.connectionString ?? process.env.DATABASE_URL;\n const settings: Record<string, unknown> = connectionString\n ? { connectionString, ssl: pgcfg.ssl }\n : { ...pgcfg, password: pgcfg.password ?? process.env.PG_PASSWORD };\n const pg = await import('pg');\n const Client = (pg as any).default?.Client ?? (pg as any).Client;\n conn = new Client(settings);\n await conn.connect();\n return conn;\n } catch (error) {\n throw DatabaseConnectionError.connectionFailed(\"pg\", toError(error).message);\n }\n default:\n throw ConfigurationError.unknownDatabaseType(config.database);\n }\n \n }\n\n static async createEmpty(configFile:string){\n const configReader = new FileMigrationConfigReader(configFile);\n const config = configReader.loadFile();\n return new MigrationRunnerFactory().createEmpty(config)\n }\n\n\n async create(config:MigrationConfig,conn:any,factoryOwnsConnection:boolean=false):Promise<MySQLMigrationRunner>{\n let sqlrunner:ISQLRunner;\n let driverConnection = conn;\n\n if (MigrationRunnerFactory.isSQLRunner(conn)) {\n sqlrunner = conn;\n driverConnection = null;\n } else {\n sqlrunner = makeRunner(config.database, conn);\n }\n const setup = new MigrationSetup(sqlrunner,config);\n const read_strategy = this.getReadStategy(config)\n\n const migration_files = new MigrationDirectoryReader(config.migration_folder,read_strategy,sqlrunner,config.database as Dialect)\n\n const runner = new MySQLMigrationRunner(config,migration_files,setup,sqlrunner,driverConnection);\n\n // Single preflight authority: create the migrations infrastructure\n // AND apply pending ledger patches before the runner is handed back.\n // Callers (embedded consumers included) therefore never observe\n // migration completion state that patches would have repaired.\n try {\n await runner.setup();\n } catch (error) {\n // Close only a connection the factory itself created; a\n // caller-injected connection stays open for the caller to manage.\n if (factoryOwnsConnection) {\n try { await sqlrunner.end(); } catch { /* best-effort cleanup */ }\n }\n throw error;\n }\n\n return runner;\n }\n\n\n async createEmpty(config:MigrationConfig):Promise<MySQLMigrationRunner>{\n const conn = null as any\n const sqlrunner = makeRunner(config.database, conn);\n const setup = new MigrationSetup(sqlrunner,config);\n const read_strategy = this.getReadStategy(config)\n\n const migration_files = new MigrationDirectoryReader(config.migration_folder,read_strategy,sqlrunner,config.database as Dialect)\n // createEmpty never performs setup or patch application.\n return new MySQLMigrationRunner(config,migration_files,setup,sqlrunner,conn,false);\n }\n\n private getReadStategy(config:MigrationConfig){\n switch(config.database){\n case \"sql\":\n return dialect.MySqlDialectParser\n case \"sqlite\":\n return dialect.SqliteDialectParser\n case \"pg\":\n return dialect.PgDialectParser\n default:\n throw ConfigurationError.unknownDatabaseType(config.database);\n }\n }\n}\n\n\nexport interface MigrationHistory{\n name:string\n up:string\n down:string\n}\n\nexport interface IMigrationRunner {\n setup(): Promise<void>;\n applyPendingPatches(): Promise<PatchApplyResult[]>;\n createPatch(name: string): string;\n terminate(): Promise<void>;\n getMigrationsHistory(): Promise<MigrationHistory[]>;\n getMigrations(): Promise<MigrationNode[]>;\n getPendingMigrations(): Promise<MigrationNode[]>;\n getCompletedMigrations(): Promise<MigrationNode[]>;\n migrate(migrationNodes: MigrationNode[], forward: boolean): Promise<void>;\n reset(): Promise<void>;\n createMigration(name: string): void;\n close(): Promise<void>;\n init(config_file: string): Promise<void>;\n query(sql: string, params?: any[]): Promise<any>;\n}\n\nexport class MySQLMigrationRunner implements IMigrationRunner {\n\n /**\n * Memoized in-flight preflight promise. Simultaneous or repeated calls\n * to setup() on one runner execute the preflight (migration table setup\n * + patch application) exactly once. Cleared after rejection so a caller\n * may retry after fixing the cause.\n */\n private preflightPromise: Promise<void> | null = null;\n private lastPatchResults: PatchApplyResult[] = [];\n\n constructor(\n private config:MigrationConfig,\n private directory:MigrationDirectoryReader,\n private setupRunner:MigrationSetup,\n private sqlrunner:ISQLRunner,\n private connection:mysql.Connection,\n private preflightEnabled:boolean = true\n){\n\n }\n\n async setup(){\n if (!this.preflightEnabled) {\n // Runners built by createEmpty() never perform setup or patch\n // application; calling setup() on them remains harmless.\n return;\n }\n if (!this.preflightPromise) {\n this.preflightPromise = this.runPreflight();\n this.preflightPromise.catch(() => {\n // Clear the memoized promise after rejection so a caller may\n // retry after fixing the cause.\n this.preflightPromise = null;\n });\n }\n return this.preflightPromise;\n }\n\n private async runPreflight(): Promise<void> {\n try {\n await this.setupRunner.setup();\n } catch (error) {\n throw new MigrationExecutionError('Failed to set up migration database', undefined, undefined, toError(error));\n }\n // Patch internals use ISQLRunner directly and never call the public\n // runner methods, avoiding setup recursion. Patch errors are already\n // typed (PatchError subclasses) and propagate as-is.\n const patchRunner = new PatchRunner(this.sqlrunner, this.config);\n this.lastPatchResults = await patchRunner.applyPending();\n }\n\n /**\n * Delegates to the same idempotent preflight; returns the results of the\n * patch pass that ran (or is running) for this runner.\n */\n async applyPendingPatches(): Promise<PatchApplyResult[]> {\n await this.setup();\n return this.lastPatchResults;\n }\n\n /**\n * Scaffolds a new ledger patch file and returns the created path.\n * Never connects to a database.\n */\n createPatch(name: string): string {\n const creator = new PatchCreator(resolvePatchFolder(this.config));\n return creator.create(name);\n }\n\n async terminate(){\n try {\n await this.setupRunner.teardown();\n } catch (error) {\n throw new MigrationExecutionError('Failed to tear down migration database', undefined, undefined, toError(error));\n }\n }\n\n async getMigrationsHistory():Promise<MigrationHistory[]>{\n await this.setup();\n try {\n const results = await this.sqlrunner.query(`\n select * \n from ${this.config.migration_table}\n `);\n return results[0] as any;\n } catch (error) {\n throw new MigrationExecutionError('Failed to get migration history', undefined, undefined, toError(error));\n }\n }\n\n\n async getMigrations(){\n await this.setup();\n try {\n return this.directory.loadMigrations(this.config.migration_table,this.connection);\n } catch (error) {\n throw new MigrationExecutionError('Failed to load migrations', undefined, undefined, toError(error));\n }\n }\n\n async getPendingMigrations(){\n try {\n const migrations = await this.getMigrations();\n return migration_filter(migrations,false);\n } catch (error) {\n if (error instanceof MigrationExecutionError) {\n throw error;\n }\n throw new MigrationExecutionError('Failed to get pending migrations', undefined, undefined, toError(error));\n }\n }\n\n async getCompletedMigrations(){\n try {\n const migrations = await this.getMigrations();\n return migration_filter(migrations,true);\n } catch (error) {\n if (error instanceof MigrationExecutionError) {\n throw error;\n }\n throw new MigrationExecutionError('Failed to get completed migrations', undefined, undefined, toError(error));\n }\n }\n\n async migrate(migrationNodes:MigrationNode[],forward:boolean):Promise<void>{\n await this.setup();\n for(let node of migrationNodes){\n try {\n if(forward){\n await node.up();\n }else{\n await node.down();\n }\n } catch (error) {\n throw new MigrationExecutionError(\n `Failed to ${forward ? 'apply' : 'rollback'} migration`,\n node.name || String(node),\n forward ? node.up_sql() : node.down_sql(),\n toError(error)\n );\n }\n }\n }\n\n\n async reset(){\n await this.setup();\n try {\n let migrations = await this.getMigrations();\n const rollback = await migration_filter(migrations,true);\n await this.migrate(rollback.reverse(),false);\n migrations = await this.getMigrations();\n const rollforward = await migration_filter(migrations,false);\n await this.migrate(rollforward,true);\n } catch (error) {\n if (error instanceof MigrationExecutionError) {\n throw error;\n }\n throw new MigrationExecutionError('Failed to reset migrations', undefined, undefined, toError(error));\n }\n }\n\n\n createMigration(name:string){\n try {\n const creator = new MigrationCreator(this.config);\n creator.create(name);\n } catch (error) {\n throw new MigrationExecutionError(`Failed to create migration: ${name}`, undefined, undefined, toError(error));\n }\n }\n\n\n async close(){\n if (this.sqlrunner) {\n try {\n await this.sqlrunner.end();\n } catch (error) {\n throw new DatabaseConnectionError(`Failed to close database connection: ${toError(error).message}`);\n }\n }\n }\n\n async query(sql: string, params?: any[]): Promise<any> {\n return await this.sqlrunner.query(sql, params);\n }\n\n async init(config_file:string){\n try {\n console.log(`Checking for ${config_file}`);\n const config_exist = fs.existsSync(config_file);\n\n if(!config_exist){\n console.log(`Creating ${config_file}`);\n const default_config = {\n \"migration_folder\":\"migrations\",\n \"migration_table\":\"proper_migrations\",\n \"database\": \"sql\",\n \"sql\":{\n \"host\":\"localhost\",\n \"user\":\"root\",\n \"database\":\"proper\",\n \"password\":\"\"\n }\n };\n fs.writeFileSync(config_file,JSON.stringify(default_config,null,2)); \n console.log(`Created ${config_file}`);\n }\n } catch (error) {\n throw new ConfigurationError(`Failed to initialize config file: ${toError(error).message}`);\n }\n }\n}\n\n\nexport class FileMigrationConfigReader{\n\n constructor(private configFile:string){\n\n }\n\n loadFile(){\n try {\n const fileContent = fs.readFileSync(this.configFile);\n const config:MigrationConfig = JSON.parse(fileContent.toString());\n \n // Validate required fields\n if (!config.migration_folder) {\n throw ConfigurationError.missingRequiredProperty('migration_folder');\n }\n \n if (!config.migration_table) {\n throw ConfigurationError.missingRequiredProperty('migration_table');\n }\n \n // For backward compatibility: if database type is omitted we derive\n // it from the presence of the dialect specific configuration\n // blocks. This keeps older `proper.json` files – that only defined\n // an \"sql\" or \"sqlite\" section – working without modification.\n if (!config.database) {\n if (config.sql) {\n config.database = 'sql';\n } else if (config.sqlite) {\n config.database = 'sqlite';\n } else if (config.pg) {\n config.database = 'pg';\n } else {\n throw ConfigurationError.missingRequiredProperty('database');\n }\n }\n \n return config;\n } catch (error) {\n if (error instanceof ConfigurationError) {\n throw error;\n }\n const err = toError(error);\n if (err.message.includes('ENOENT')) {\n throw new ConfigurationError(`Config file not found: ${this.configFile}`);\n }\n throw new ConfigurationError(`Failed to load config file: ${err.message}`);\n }\n }\n}\n\n\nexport class MigrationCreator{\n constructor(private config:MigrationConfig){\n \n }\n\n\n create(name:string){\n if (!name) {\n throw new CLIError('Migration name is required');\n }\n\n try {\n // Ensure the migration folder exists\n if (!fs.existsSync(this.config.migration_folder)) {\n fs.mkdirSync(this.config.migration_folder, { recursive: true });\n }\n\n const now_timestamp = Date.now();\n\n const filename_up = `${now_timestamp}_${name}.up.sql`;\n const filename_down = `${now_timestamp}_${name}.down.sql`;\n\n fs.writeFileSync(`${this.config.migration_folder}/${filename_up}`,`\n-- Write your up migration here\n `.trim());\n\n fs.writeFileSync(`${this.config.migration_folder}/${filename_down}`,`\n-- Write your down migration here\n `.trim());\n \n console.log(`Created migration files:`);\n console.log(` ${filename_up}`);\n console.log(` ${filename_down}`);\n } catch (error) {\n if (error instanceof CLIError) {\n throw error;\n }\n throw new MigrationExecutionError(`Failed to create migration files: ${toError(error).message}`);\n }\n }\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport { MigrationNode } from './MigrationNode';\nimport { SqlMigrationBuilder } from './SqlMigrationBuilder';\nimport type mysql from \"mysql2/promise\";\nimport { ISQLRunner } from \"./SQLRunner\";\nimport { canonicalMigrationKey, resolveMigrationFile, Dialect } from \"./MigrationManifest\";\n\n\nexport interface MigrationOptions{\n conn:mysql.Connection\n}\n\nexport class MigrationDirectoryReader {\n\n constructor(\n private directory: string,\n private read_strategy: any,\n private sqlrunner: ISQLRunner,\n private dialect: 'sql' | 'sqlite' | 'pg' = 'sql'\n ) {\n\n }\n\n /**\n * Resolves the appropriate file for a migration based on dialect.\n * Priority: dialect-specific file > generic file\n * File extensions: `.mysql.up.sql`, `.sqlite.up.sql`, `.pg.up.sql`.\n */\n private resolveFile(baseName: string, direction: 'up' | 'down'): string | null {\n return resolveMigrationFile(this.directory, baseName, direction, this.dialect as Dialect);\n }\n\n /**\n * Checks if a file path is dialect-specific (contains .mysql. or .sqlite. in the name)\n */\n private isDialectSpecific(filePath: string): boolean {\n return /\\.(mysql|sqlite|pg)\\.(up|down)\\.sql$/i.test(filePath);\n }\n\n loadMigrations(table:string,connection:any):MigrationNode[] {\n\n fs.existsSync(this.directory) || fs.mkdirSync(this.directory);\n const dir_content = fs.readdirSync(this.directory,{withFileTypes:true}).filter(file=>file.isFile()).map(file=>file.name);\n\n // Extract unique migration keys (stripping dialect extensions)\n const uniqueKeys = new Set<string>();\n dir_content.forEach(file => {\n // Strip dialect extension (.mysql or .sqlite) and direction (.up or .down) to get base key\n const key = canonicalMigrationKey(file);\n uniqueKeys.add(key);\n });\n\n const migration_sorter: any = {};\n\n // For each unique key, resolve the correct files based on dialect\n uniqueKeys.forEach((migration_key) => {\n const builder = new SqlMigrationBuilder(migration_key);\n\n const upFile = this.resolveFile(migration_key, 'up');\n const downFile = this.resolveFile(migration_key, 'down');\n\n if (upFile) {\n this.loadMigration(builder, upFile);\n }\n if (downFile) {\n this.loadMigration(builder, downFile);\n }\n\n migration_sorter[migration_key] = builder;\n });\n\n const keys = Object.keys(migration_sorter)\n\n keys.sort()\n\n const built = keys.map(key=>{\n return migration_sorter[key].build(table,this.sqlrunner)\n })\n return built\n\n }\n\n\n loadMigration(builder: SqlMigrationBuilder, file: string) {\n const is_sql = /sql$/i.test(file);\n const is_js = /js$/i.test(file);\n const is_up = /up\\.(js|sql)/i.test(file);\n const is_down = /down\\.(js|sql)/i.test(file);\n if (is_sql && is_up) {\n const content = this.sql_up(file);\n builder.set_up(file,content);\n } else if (is_sql && is_down) {\n const content = this.sql_down(file);\n builder.set_down(file,content);\n } else {\n throw new Error(`Invalid migration file: ${file}`);\n }\n return builder;\n }\n\n\n sql_up(file: string) {\n let content = fs.readFileSync(file).toString();\n // Dialect-specific files bypass read_strategy (no inline marker parsing needed)\n if (!this.isDialectSpecific(file)) {\n content = this.read_strategy(content);\n }\n return content.trim();\n }\n\n sql_down(file: string) {\n let content = fs.readFileSync(file).toString();\n // Dialect-specific files bypass read_strategy (no inline marker parsing needed)\n if (!this.isDialectSpecific(file)) {\n content = this.read_strategy(content);\n }\n return content.trim();\n }\n\n}\n","/**\n * Base class for all migration-related errors\n */\nexport class MigrationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'MigrationError';\n // This is needed to make instanceof work correctly in ES5\n Object.setPrototypeOf(this, MigrationError.prototype);\n }\n}\n\n/**\n * Error thrown when there is an issue with the configuration\n */\nexport class ConfigurationError extends MigrationError {\n constructor(message: string) {\n super(`Configuration Error: ${message}`);\n this.name = 'ConfigurationError';\n Object.setPrototypeOf(this, ConfigurationError.prototype);\n }\n\n /**\n * Helper method for missing database configuration\n * @param dbType The database type (e.g., 'sql', 'sqlite')\n * @returns A ConfigurationError with appropriate message\n */\n static missingDatabaseConfiguration(dbType: string): ConfigurationError {\n return new ConfigurationError(`Missing ${dbType} configuration`);\n }\n\n /**\n * Helper method for unknown database type\n * @param dbType The unknown database type\n * @returns A ConfigurationError with appropriate message\n */\n static unknownDatabaseType(dbType: string): ConfigurationError {\n return new ConfigurationError(`Unknown database type: ${dbType}`);\n }\n\n /**\n * Helper method for missing required configuration properties\n * @param property The name of the missing property\n * @returns A ConfigurationError with appropriate message\n */\n static missingRequiredProperty(property: string): ConfigurationError {\n return new ConfigurationError(`Missing required property: ${property}`);\n }\n}\n\n/**\n * Error thrown when there is an issue with the database connection\n */\nexport class DatabaseConnectionError extends MigrationError {\n constructor(message: string) {\n super(`Database Connection Error: ${message}`);\n this.name = 'DatabaseConnectionError';\n Object.setPrototypeOf(this, DatabaseConnectionError.prototype);\n }\n\n /**\n * Helper method for connection errors\n * @param dbType The database type (e.g., 'sql', 'sqlite')\n * @param details Additional error details\n * @returns A DatabaseConnectionError with appropriate message\n */\n static connectionFailed(dbType: string, details?: string): DatabaseConnectionError {\n const message = details \n ? `Failed to connect to ${dbType} database: ${details}`\n : `Failed to connect to ${dbType} database`;\n return new DatabaseConnectionError(message);\n }\n\n /**\n * Helper method for authentication errors\n * @param dbType The database type (e.g., 'sql', 'sqlite')\n * @returns A DatabaseConnectionError with appropriate message\n */\n static authenticationFailed(dbType: string): DatabaseConnectionError {\n return new DatabaseConnectionError(`Authentication failed for ${dbType} database`);\n }\n}\n\n/**\n * Error thrown when there is an issue with executing a migration\n */\nexport class MigrationExecutionError extends MigrationError {\n constructor(\n message: string,\n public readonly migrationName?: string,\n public readonly sql?: string,\n public readonly originalError?: Error\n ) {\n /*\n * The public `message` that gets surfaced to callers **must not** include the\n * raw SQL text. The SQL string is already exposed through the dedicated\n * `sql` property and adding it to the message makes it unnecessarily noisy\n * and difficult to assert against in unit-tests. Therefore we only embed\n * the essential information (error type, optional migration name and the\n * short error message) in the main message string while keeping the full\n * SQL available separately.\n */\n let fullMessage = `Migration Execution Error${migrationName ? ` in '${migrationName}'` : ''}: ${message}`;\n\n if(originalError){\n fullMessage += `\\nOriginal Error:\\n${originalError.message}`;\n }\n\n super(fullMessage);\n this.name = 'MigrationExecutionError';\n Object.setPrototypeOf(this, MigrationExecutionError.prototype);\n }\n\n /**\n * Helper method for SQL execution errors\n * @param migrationName The name of the migration\n * @param sql The SQL that caused the error\n * @param originalError The original error thrown by the database driver\n * @returns A MigrationExecutionError with appropriate message\n */\n static sqlExecutionFailed(migrationName: string, sql: string, originalError: Error): MigrationExecutionError {\n return new MigrationExecutionError(\n originalError.message,\n migrationName,\n sql,\n originalError\n );\n }\n\n /**\n * Helper method for missing migration file errors\n * @param filename The missing file\n * @returns A MigrationExecutionError with appropriate message\n */\n static missingMigrationFile(filename: string): MigrationExecutionError {\n return new MigrationExecutionError(`Migration file not found: ${filename}`);\n }\n\n /**\n * Helper method for invalid migration file format errors\n * @param filename The invalid file\n * @param details Additional error details\n * @returns A MigrationExecutionError with appropriate message\n */\n static invalidMigrationFile(filename: string, details?: string): MigrationExecutionError {\n const message = details\n ? `Invalid migration file format in ${filename}: ${details}`\n : `Invalid migration file format in ${filename}`;\n return new MigrationExecutionError(message);\n }\n}\n\n/**\n * Base class for all patch-related errors.\n */\nexport class PatchError extends MigrationError {\n constructor(\n message: string,\n public readonly patchFile?: string,\n public readonly patchKey?: string\n ) {\n super(`Patch Error: ${message}`);\n this.name = 'PatchError';\n Object.setPrototypeOf(this, PatchError.prototype);\n }\n}\n\n/**\n * A patch file failed YAML parsing or schema/plan validation.\n */\nexport class PatchValidationError extends PatchError {\n constructor(message: string, patchFile?: string, patchKey?: string) {\n super(message, patchFile, patchKey);\n this.name = 'PatchValidationError';\n Object.setPrototypeOf(this, PatchValidationError.prototype);\n }\n}\n\n/**\n * An applied patch's file is missing or its content no longer matches the\n * checksum recorded at application time.\n */\nexport class PatchIntegrityError extends PatchError {\n constructor(\n message: string,\n patchFile?: string,\n patchKey?: string,\n public readonly expectedChecksum?: string,\n public readonly actualChecksum?: string\n ) {\n super(message, patchFile, patchKey);\n this.name = 'PatchIntegrityError';\n Object.setPrototypeOf(this, PatchIntegrityError.prototype);\n }\n}\n\n/**\n * An operation precondition failed: ledger conflict or corruption\n * (unexpected row counts) at the operation's turn.\n */\nexport class PatchConflictError extends PatchError {\n constructor(\n message: string,\n patchFile?: string,\n patchKey?: string,\n public readonly operationIndex?: number,\n public readonly operationVerb?: string,\n public readonly migrationKeys?: string[],\n public readonly observedRowCounts?: Record<string, number>\n ) {\n super(message, patchFile, patchKey);\n this.name = 'PatchConflictError';\n Object.setPrototypeOf(this, PatchConflictError.prototype);\n }\n}\n\n/**\n * A database/transaction failure while applying a patch.\n */\nexport class PatchExecutionError extends PatchError {\n constructor(\n message: string,\n patchFile?: string,\n patchKey?: string,\n public readonly operationIndex?: number,\n public readonly operationVerb?: string,\n public readonly originalError?: Error\n ) {\n super(originalError ? `${message}\\nOriginal Error:\\n${originalError.message}` : message, patchFile, patchKey);\n this.name = 'PatchExecutionError';\n Object.setPrototypeOf(this, PatchExecutionError.prototype);\n }\n}\n\n/**\n * Error thrown when there is an issue with the migration CLI\n */\nexport class CLIError extends MigrationError {\n constructor(message: string) {\n super(`CLI Error: ${message}`);\n this.name = 'CLIError';\n Object.setPrototypeOf(this, CLIError.prototype);\n }\n\n /**\n * Helper method for missing command errors\n * @returns A CLIError with appropriate message\n */\n static missingCommand(): CLIError {\n return new CLIError('No command specified. Run with --help for usage information.');\n }\n\n /**\n * Helper method for unknown command errors\n * @param command The unknown command\n * @returns A CLIError with appropriate message\n */\n static unknownCommand(command: string): CLIError {\n return new CLIError(`Unknown command: ${command}. Run with --help for usage information.`);\n }\n\n /**\n * Helper method for missing required argument errors\n * @param argument The missing argument\n * @returns A CLIError with appropriate message\n */\n static missingRequiredArgument(argument: string): CLIError {\n return new CLIError(`Missing required argument: ${argument}`);\n }\n}\n","import type { Connection } from 'mysql2/promise';\nimport { MigrationStatus } from './MigrationStatus';\nimport { ISQLRunner } from './SQLRunner';\nimport { MigrationExecutionError } from './errors';\n\nexport abstract class MigrationNode {\n name: string;\n\n constructor(name?: string) {\n this.name = name || '';\n }\n\n abstract get_key():string;\n abstract status(): Promise<MigrationStatus>;\n abstract up(): Promise<void>;\n abstract down(): Promise<void>;\n abstract up_sql(): string;\n abstract down_sql(): string;\n}\n\n\nexport class SqlMigrationNode extends MigrationNode {\n up_sql(): string {\n return this.sql_up;\n }\n down_sql(): string {\n return this.sql_down;\n }\n get_key(): string {\n return this.key;\n }\n\n constructor(private conn:ISQLRunner,\n private table:string, \n private key:string,\n private up_file:string,\n private sql_up:string,\n private down_file:string,\n private sql_down:string) {\n super(key);\n }\n\n async status(): Promise<MigrationStatus> {\n try {\n const result = await this.conn.query(`\n select * \n from ${this.table}\n where migration_key = ?;\n `, [this.key]);\n\n if(result.length > 0 && result[0].length > 0){\n return {\n completed: true\n };\n } else {\n return {\n completed: false\n };\n }\n } catch (error) {\n throw new MigrationExecutionError(\n `Error checking status for migration`,\n this.key,\n undefined,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n async up(): Promise<void> {\n try {\n await this.conn.execute(this.sql_up);\n } catch (error) {\n throw new MigrationExecutionError(\n `Error executing UP migration`,\n this.key,\n this.sql_up,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n \n try {\n await this.conn.execute(`\n insert into ${this.table} (migration_key,up,down)\n values (?,?,?)\n `, [this.key, this.up_file, this.down_file]);\n } catch (error) {\n throw new MigrationExecutionError(\n `Error recording migration completion`,\n this.key,\n undefined,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n async down(): Promise<void> {\n try {\n await this.conn.execute(this.sql_down);\n } catch (error) {\n throw new MigrationExecutionError(\n `Error executing DOWN migration`,\n this.key,\n this.sql_down,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n \n try {\n await this.conn.execute(`\n delete from ${this.table}\n where migration_key = ?\n `, [this.key]);\n } catch (error) {\n throw new MigrationExecutionError(\n `Error removing migration record`,\n this.key,\n undefined,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n}\n\n\nexport class SqliteMigrationNode extends MigrationNode {\n up_sql(): string {\n return this.sql_up;\n }\n down_sql(): string {\n return this.sql_down;\n }\n constructor(\n private conn: ISQLRunner, // your SQLite runner\n private table: string,\n private key: string,\n private up_file: string,\n private sql_up: string,\n private down_file: string,\n private sql_down: string\n ) {\n super(key);\n }\n\n /**\n * Returns the unique key for this migration (e.g. timestamp + name).\n */\n get_key(): string {\n return this.key;\n }\n\n /**\n * Check if this migration is already completed by looking in the migration table.\n */\n async status(): Promise<MigrationStatus> {\n try {\n // Usually `this.conn.query(...)` returns an array of rows.\n // The first element might be the row set, depending on your runner.\n const cursor = await this.conn.query(\n `SELECT * FROM ${this.table} WHERE migration_key = ?;`,\n [this.key]\n );\n\n // Usually, `cursor[0]` is the row array in many MySQL runners;\n // In a SQLite scenario, it may be just `cursor`\n // So adjust depending on your actual runner's return shape.\n const rows = cursor[0] as any[];\n\n if (rows && rows.length > 0) {\n return { completed: true };\n } else {\n return { completed: false };\n }\n } catch (error) {\n throw new MigrationExecutionError(\n `Error checking status for migration`,\n this.key,\n undefined,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n /**\n * Run the 'up' SQL, then record this migration in the table.\n */\n async up(): Promise<void> {\n try {\n // Execute the 'up' script\n await this.conn.execute(this.sql_up);\n } catch (error) {\n throw new MigrationExecutionError(\n `Error executing UP migration`,\n this.key,\n this.sql_up,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n\n // Insert a record of this migration having completed\n try {\n await this.conn.execute(\n `\n INSERT INTO ${this.table} (migration_key, up, down)\n VALUES (?, ?, ?)\n `,\n [this.key, this.up_file, this.down_file]\n );\n } catch (error) {\n throw new MigrationExecutionError(\n `Error recording migration completion`,\n this.key,\n undefined,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n /**\n * Run the 'down' SQL, then remove this migration record from the table.\n */\n async down(): Promise<void> {\n try {\n // Execute the 'down' script\n await this.conn.execute(this.sql_down);\n } catch (error) {\n throw new MigrationExecutionError(\n `Error executing DOWN migration`,\n this.key,\n this.sql_down,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n\n // Remove the migration from the table\n try {\n await this.conn.execute(\n `\n DELETE FROM ${this.table}\n WHERE migration_key = ?\n `,\n [this.key]\n );\n } catch (error) {\n throw new MigrationExecutionError(\n `Error removing migration record`,\n this.key,\n undefined,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n}","import type { Connection } from 'mysql2/promise';\nimport { SqlMigrationNode } from './MigrationNode';\nimport { ISQLRunner } from './SQLRunner';\n\n\n\nexport class SqlMigrationBuilder {\n\n private up: string = '';\n private up_file: string = '';\n private down: string = '';\n private down_file: string = '';\n\n constructor(private key: string) {\n }\n\n set_up(file:string,up: string) {\n this.up_file = file;\n this.up = up;\n }\n\n set_down(file:string,down: string) {\n this.down_file = file;\n this.down = down;\n }\n\n build(table:string,conn: ISQLRunner) {\n return new SqlMigrationNode(conn, table,this.key, this.up_file, this.up, this.down_file,this.down);\n }\n}\n","import fs from \"fs\";\nimport path from \"path\";\n\nexport type Dialect = 'sql' | 'sqlite' | 'pg';\n\n/**\n * Canonicalizes a migration key the same way MigrationDirectoryReader derives\n * keys from filenames: strip any dialect/direction extension and lowercase.\n * Accepts either a bare key or a migration filename.\n */\nexport function canonicalMigrationKey(value: string): string {\n return value\n .replace(/(?:\\.(mysql|sqlite|pg))?\\.(up|down)\\.(sql|js)$/i, \"\")\n .toLowerCase();\n}\n\n/**\n * Resolves the up/down file for a migration base name honoring dialect\n * priority: dialect-specific file > generic file. Mirrors\n * MigrationDirectoryReader.resolveFile.\n */\nexport function resolveMigrationFile(\n directory: string,\n baseName: string,\n direction: 'up' | 'down',\n dialect: Dialect\n): string | null {\n const dialectExt = dialect === 'sql' ? 'mysql' : dialect;\n\n const dialectFile = path.join(directory, `${baseName}.${dialectExt}.${direction}.sql`);\n if (fs.existsSync(dialectFile)) return dialectFile;\n\n const genericFile = path.join(directory, `${baseName}.${direction}.sql`);\n if (fs.existsSync(genericFile)) return genericFile;\n\n return null;\n}\n\nexport interface MigrationManifestEntry {\n key: string;\n upFile: string | null;\n downFile: string | null;\n}\n\n/**\n * Loads the migration manifest: canonical keys plus resolved file paths.\n * Does not read migration status and does not execute any SQL.\n * A missing migration folder yields an empty manifest.\n */\nexport function loadMigrationManifest(directory: string, dialect: Dialect): Map<string, MigrationManifestEntry> {\n const manifest = new Map<string, MigrationManifestEntry>();\n if (!fs.existsSync(directory)) return manifest;\n\n const files = fs.readdirSync(directory, { withFileTypes: true })\n .filter(f => f.isFile())\n .map(f => f.name);\n\n const uniqueKeys = new Set<string>();\n files.forEach(file => uniqueKeys.add(canonicalMigrationKey(file)));\n\n uniqueKeys.forEach(key => {\n manifest.set(key, {\n key,\n upFile: resolveMigrationFile(directory, key, 'up', dialect),\n downFile: resolveMigrationFile(directory, key, 'down', dialect),\n });\n });\n\n return manifest;\n}\n","import { MigrationConfig } from \"./MigrationConfig\";\nimport fs from \"fs\";\nimport { ISQLRunner } from './SQLRunner';\nimport { resolvePatchTable } from './PatchTypes';\n\nexport class MigrationSetup {\n constructor(private sqlrunner: ISQLRunner, private config: MigrationConfig) {}\n\n\n async setup() {\n\n fs.existsSync(this.config.migration_folder) || fs.mkdirSync(this.config.migration_folder);\n\n const tableName = this.config.migration_table;\n\n // Use dialect-specific DDL so that the migrations table can be created\n // both in MySQL/MariaDB and in SQLite. The two dialects differ mainly\n // in the auto-increment syntax and the column types.\n const createTableSql = this.config.database === 'sqlite'\n ? `CREATE TABLE IF NOT EXISTS ${tableName} (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n migration_key TEXT,\n up TEXT,\n down TEXT,\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n )`\n : this.config.database === 'pg'\n ? `CREATE TABLE IF NOT EXISTS ${tableName} (\n id SERIAL PRIMARY KEY,\n migration_key TEXT,\n up TEXT,\n down TEXT,\n created_at TIMESTAMPTZ DEFAULT now()\n )`\n : `CREATE TABLE IF NOT EXISTS ${tableName} (\n id INT AUTO_INCREMENT PRIMARY KEY,\n migration_key VARCHAR(255),\n up VARCHAR(255),\n down VARCHAR(255),\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n )`;\n\n await this.sqlrunner.query(createTableSql);\n\n // Patch table: records applied ledger patches. The composite primary\n // key (migration_table, patch_key) scopes a patch to the configured\n // migration ledger and makes patch claiming concurrency-safe even\n // when one database hosts multiple Proper ledgers.\n const patchTable = resolvePatchTable(this.config);\n const createPatchTableSql = this.config.database === 'sqlite'\n ? `CREATE TABLE IF NOT EXISTS ${patchTable} (\n migration_table TEXT NOT NULL,\n patch_key TEXT NOT NULL,\n checksum TEXT NOT NULL,\n format_version INTEGER NOT NULL,\n description TEXT NOT NULL,\n applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (migration_table, patch_key)\n )`\n : this.config.database === 'pg'\n ? `CREATE TABLE IF NOT EXISTS ${patchTable} (\n migration_table TEXT NOT NULL,\n patch_key TEXT NOT NULL,\n checksum TEXT NOT NULL,\n format_version INTEGER NOT NULL,\n description TEXT NOT NULL,\n applied_at TIMESTAMPTZ NOT NULL DEFAULT now(),\n PRIMARY KEY (migration_table, patch_key)\n )`\n : `CREATE TABLE IF NOT EXISTS ${patchTable} (\n migration_table VARCHAR(255) NOT NULL,\n patch_key VARCHAR(255) NOT NULL,\n checksum CHAR(64) NOT NULL,\n format_version INT NOT NULL,\n description TEXT NOT NULL,\n applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (migration_table, patch_key)\n )`;\n\n await this.sqlrunner.query(createPatchTableSql);\n }\n\n async teardown() {\n await this.sqlrunner.execute(`DROP TABLE ${this.config.migration_table}`);\n await this.sqlrunner.execute(`DROP TABLE IF EXISTS ${resolvePatchTable(this.config)}`);\n }\n}\n\n\n\n\n","import path from \"path\";\nimport { MigrationConfig } from \"./MigrationConfig\";\n\nexport const PATCH_FORMAT_VERSION = 1;\nexport const DEFAULT_PATCH_TABLE = \"proper_patches\";\n\n/** Filename contract: 13-digit stamp, underscore, normalized name, .yaml */\nexport const PATCH_FILENAME_REGEX = /^(?<stamp>[0-9]{13})_(?<name>[a-z0-9][a-z0-9_-]{0,119})\\.yaml$/;\n\nexport type PatchOperation =\n | { verb: 'rename_migration'; from: string; to: string }\n | { verb: 'mark_applied'; key: string }\n | { verb: 'unmark_applied'; key: string };\n\n/** A parsed and schema-validated patch file. */\nexport interface PatchDocument {\n /** Filename without `.yaml`. */\n patchKey: string;\n /** Basename including `.yaml`. */\n fileName: string;\n /** Absolute or config-relative resolved path. */\n filePath: string;\n /** SHA-256 hex over the exact UTF-8 file bytes. */\n checksum: string;\n version: number;\n description: string;\n operations: PatchOperation[];\n}\n\nexport interface PatchOperationResult {\n verb: PatchOperation['verb'];\n /** True when the operation mutated the ledger; false for a conditional no-op. */\n changed: boolean;\n}\n\nexport interface PatchApplyResult {\n patchKey: string;\n fileName: string;\n /**\n * applied - this process committed the patch\n * already_applied - a matching patch-history row already existed\n */\n status: 'applied' | 'already_applied';\n operations: PatchOperationResult[];\n}\n\n/** Resolved patch settings with defaults applied. */\nexport function resolvePatchFolder(config: MigrationConfig): string {\n if (config.patch_folder) return config.patch_folder;\n const dir = path.dirname(config.migration_folder);\n return dir === '.' && !config.migration_folder.includes(path.sep) && !config.migration_folder.includes('/')\n ? 'patches'\n : path.join(dir, 'patches');\n}\n\nexport function resolvePatchTable(config: MigrationConfig): string {\n return config.patch_table || DEFAULT_PATCH_TABLE;\n}\n","import { MigrationNode } from \"./MigrationNode\";\n\n\n\n\nexport async function migration_filter(migrations:MigrationNode[],completed:boolean=true,keep:MigrationNode[]=[]){\n if(migrations.length === 0){\n return keep\n }\n\n const [first,...rest] = migrations\n\n const status = await first.status()\n\n if(status.completed == completed){\n keep.push(first)\n }\n\n return migration_filter(rest,completed,keep)\n}","export function MySqlDialectParser(sql: string): string {\n const lines = sql.split('\\n');\n let result = '';\n \n // We start \"in MySQL\" so that lines before [sql] are kept.\n let isInMySQLBlock = true;\n \n // e.g. `-- [sql]`, `-- [ sql ]`, `-- [mysql]`, ignoring case/spaces\n const startSQLRegex = /^\\s*--\\s*\\[\\s*(sql|mysql)\\s*\\]\\s*$/i;\n // e.g. `-- [sqlite]`, `-- [ pg ]`, `-- [mydialect]` (any bracket means \"turn off MySQL\")\n const anyDialectRegex = /^\\s*--\\s*\\[\\s*\\w+\\s*\\]\\s*$/i;\n \n for (const line of lines) {\n const trimmed = line.trim();\n \n // If line is \" -- [sql] \" or \" -- [mysql] \", we *turn on* MySQL capturing:\n if (startSQLRegex.test(trimmed)) {\n isInMySQLBlock = true;\n // We also include this line in output\n result += line + '\\n';\n continue;\n }\n \n // If line is *some other* bracket, e.g. \" -- [sqlite] \"\n // then switch MySQL off, and do NOT keep that line\n if (anyDialectRegex.test(trimmed) && !startSQLRegex.test(trimmed)) {\n isInMySQLBlock = false;\n // Skip to next line\n continue;\n }\n \n // If we get here and see a line without a [dialect] marker,\n // and we were previously turned off because of non-mysql dialect,\n // then check if it's common SQL (like CREATE INDEX).\n // Turn MySQL back on for this line\n if (!isInMySQLBlock && line.toLowerCase().includes('create index')) {\n isInMySQLBlock = true;\n }\n \n // If we're in MySQL mode, keep the line\n if (isInMySQLBlock) {\n result += line + '\\n';\n }\n }\n \n return result;\n}\n\n/**\n * Generic inline-marker parser. Lines before any `-- [dialect]` marker are\n * kept; a marker matching one of `names` turns capturing on (and the marker\n * line is kept), any other `-- [x]` marker turns it off (marker dropped).\n * `CREATE INDEX` lines are treated as common SQL and re-enable capturing.\n */\nfunction markerDialectParser(names: string[]): (sql: string) => string {\n const startRegex = new RegExp(`^\\\\s*--\\\\s*\\\\[\\\\s*(${names.join('|')})\\\\s*\\\\]\\\\s*$`, 'i');\n const anyDialectRegex = /^\\s*--\\s*\\[\\s*\\w+\\s*\\]\\s*$/i;\n\n return function (sql: string): string {\n const lines = sql.split('\\n');\n let result = '';\n let capturing = true;\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n if (startRegex.test(trimmed)) {\n capturing = true;\n result += line + '\\n';\n continue;\n } else if (anyDialectRegex.test(trimmed)) {\n capturing = false;\n continue;\n }\n\n if (!capturing && line.toLowerCase().includes('create index')) {\n capturing = true;\n }\n\n if (capturing) {\n result += line + '\\n';\n }\n }\n\n return result;\n };\n}\n\n/** `-- [sqlite]` blocks. */\nexport const SqliteDialectParser = markerDialectParser(['sqlite']);\n\n/** `-- [pg]` / `-- [postgres]` / `-- [postgresql]` blocks. */\nexport const PgDialectParser = markerDialectParser(['pg', 'postgres', 'postgresql']);","import crypto from \"crypto\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { PatchValidationError } from \"./errors\";\nimport { parsePatchContent } from \"./PatchValidator\";\nimport { PatchDocument, PATCH_FILENAME_REGEX } from \"./PatchTypes\";\n\n/**\n * Discovers, checksums, parses, and validates every patch file in the patch\n * folder. Discovery rules:\n * - only top-level regular files ending in `.yaml` are patch files;\n * - `.yml`, nested files, and symlinks are not loaded;\n * - non-`.yaml` files are ignored;\n * - a `.yaml` file with an invalid filename or invalid contents is a hard error;\n * - a missing folder is empty discovery (never created here).\n *\n * All files are parsed and validated before any patch is applied, so a\n * malformed later file cannot be discovered only after earlier patches\n * mutate the ledger.\n */\nexport class PatchDirectoryReader {\n constructor(private directory: string) {}\n\n loadPatches(): PatchDocument[] {\n if (!fs.existsSync(this.directory)) return [];\n\n const entries = fs.readdirSync(this.directory, { withFileTypes: true });\n const patchFiles: string[] = [];\n\n for (const entry of entries) {\n if (!entry.name.endsWith('.yaml')) continue;\n // Regular files only: symlinks and directories are not loaded.\n if (!entry.isFile() || entry.isSymbolicLink()) {\n if (entry.isSymbolicLink()) {\n throw new PatchValidationError(`patch file must be a regular file, not a symlink`, entry.name);\n }\n continue;\n }\n patchFiles.push(entry.name);\n }\n\n // Ascending numeric stamp, then full basename as the tie-breaker.\n patchFiles.sort((a, b) => {\n const stampA = parseInt(a.slice(0, 13), 10);\n const stampB = parseInt(b.slice(0, 13), 10);\n if (!Number.isNaN(stampA) && !Number.isNaN(stampB) && stampA !== stampB) {\n return stampA - stampB;\n }\n return a < b ? -1 : a > b ? 1 : 0;\n });\n\n return patchFiles.map(fileName => {\n const match = PATCH_FILENAME_REGEX.exec(fileName);\n if (!match) {\n throw new PatchValidationError(\n `invalid patch filename (expected <13-digit-stamp>_<name>.yaml with name matching [a-z0-9][a-z0-9_-]{0,119})`,\n fileName\n );\n }\n const patchKey = fileName.slice(0, -'.yaml'.length);\n const filePath = path.join(this.directory, fileName);\n const bytes = fs.readFileSync(filePath);\n const checksum = crypto.createHash('sha256').update(bytes).digest('hex');\n const content = bytes.toString('utf8');\n const { version, description, operations } = parsePatchContent(content, fileName, patchKey);\n\n return { patchKey, fileName, filePath, checksum, version, description, operations };\n });\n }\n}\n","import Ajv from \"ajv\";\nimport { Document, parseDocument } from \"yaml\";\nimport { PatchValidationError } from \"./errors\";\nimport { canonicalMigrationKey, MigrationManifestEntry } from \"./MigrationManifest\";\nimport { PatchDocument, PatchOperation, PATCH_FORMAT_VERSION } from \"./PatchTypes\";\n\nconst MAX_DESCRIPTION_LENGTH = 500;\nconst MAX_MIGRATION_KEY_LENGTH = 255;\n\nconst migrationKeySchema = {\n type: \"string\",\n minLength: 1,\n maxLength: MAX_MIGRATION_KEY_LENGTH,\n};\n\nconst patchSchema = {\n type: \"object\",\n additionalProperties: false,\n required: [\"version\", \"description\", \"operations\"],\n properties: {\n version: { type: \"integer\" },\n description: { type: \"string\" },\n operations: {\n type: \"array\",\n minItems: 1,\n items: {\n type: \"object\",\n additionalProperties: false,\n minProperties: 1,\n maxProperties: 1,\n properties: {\n rename_migration: {\n type: \"object\",\n additionalProperties: false,\n required: [\"from\", \"to\"],\n properties: { from: migrationKeySchema, to: migrationKeySchema },\n },\n mark_applied: {\n type: \"object\",\n additionalProperties: false,\n required: [\"key\"],\n properties: { key: migrationKeySchema },\n },\n unmark_applied: {\n type: \"object\",\n additionalProperties: false,\n required: [\"key\"],\n properties: { key: migrationKeySchema },\n },\n },\n },\n },\n },\n};\n\nconst ajv = new Ajv({ allErrors: true, strict: true });\nconst validateSchema = ajv.compile(patchSchema);\n\nfunction fail(message: string, file: string, patchKey?: string): never {\n throw new PatchValidationError(message, file, patchKey);\n}\n\n/** Rejects keys with path separators, NUL/control chars, or surrounding whitespace. */\nfunction checkMigrationKey(value: string, context: string, file: string, patchKey: string): string {\n if (value !== value.trim()) fail(`${context}: migration key has leading/trailing whitespace`, file, patchKey);\n if (/[/\\\\]/.test(value)) fail(`${context}: migration key contains a path separator`, file, patchKey);\n // eslint-disable-next-line no-control-regex\n if (/[\\x00-\\x1f\\x7f]/.test(value)) fail(`${context}: migration key contains control characters`, file, patchKey);\n if (value.length === 0 || value.length > MAX_MIGRATION_KEY_LENGTH) {\n fail(`${context}: migration key length out of bounds`, file, patchKey);\n }\n return canonicalMigrationKey(value);\n}\n\n/**\n * Walks the parsed YAML CST and rejects aliases, anchors, merge keys,\n * custom tags, and non-core scalar types.\n */\nfunction assertStrictYaml(doc: Document.Parsed, file: string, patchKey: string) {\n if (doc.errors.length > 0) {\n fail(`YAML parse error: ${doc.errors[0].message}`, file, patchKey);\n }\n if (doc.warnings.length > 0) {\n fail(`YAML warning treated as error: ${doc.warnings[0].message}`, file, patchKey);\n }\n\n const visit = (node: any): void => {\n if (node == null || typeof node !== 'object') return;\n // Alias nodes\n if ('source' in node && node.constructor?.name === 'Alias') {\n fail('YAML aliases are not permitted in patch files', file, patchKey);\n }\n if (node.anchor) {\n fail('YAML anchors are not permitted in patch files', file, patchKey);\n }\n if (node.tag && !['tag:yaml.org,2002:str', 'tag:yaml.org,2002:int', 'tag:yaml.org,2002:bool',\n 'tag:yaml.org,2002:null', 'tag:yaml.org,2002:map', 'tag:yaml.org,2002:seq'].includes(node.tag)) {\n fail(`YAML tag '${node.tag}' is not permitted in patch files`, file, patchKey);\n }\n if (Array.isArray(node.items)) {\n for (const item of node.items) {\n if (item && typeof item === 'object' && 'key' in item) {\n // Pair: reject merge keys\n const keyValue = item.key?.value;\n if (keyValue === '<<') fail('YAML merge keys are not permitted in patch files', file, patchKey);\n visit(item.key);\n visit(item.value);\n } else {\n visit(item);\n }\n }\n }\n };\n visit(doc.contents);\n}\n\n/**\n * Strictly parses and validates one patch file's content. Duplicate mapping\n * keys, aliases/anchors, merge keys, custom tags, unknown fields, and unknown\n * verbs are all rejected. Returns validated operations plus metadata.\n */\nexport function parsePatchContent(\n content: string,\n fileName: string,\n patchKey: string\n): { version: number; description: string; operations: PatchOperation[] } {\n const doc = parseDocument(content, {\n uniqueKeys: true, // duplicate mapping keys become errors\n merge: false,\n schema: 'core',\n version: '1.2',\n });\n assertStrictYaml(doc, fileName, patchKey);\n\n const raw = doc.toJS({ mapAsMap: false });\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n fail('Patch document must be a YAML mapping', fileName, patchKey);\n }\n\n if (!validateSchema(raw)) {\n const detail = (validateSchema.errors ?? [])\n .map(e => `${e.instancePath || '/'} ${e.message}`)\n .join('; ');\n // Distinguish unknown version specifically for a clearer diagnostic\n const anyRaw = raw as any;\n if (typeof anyRaw.version === 'number' && anyRaw.version !== PATCH_FORMAT_VERSION) {\n fail(`Unknown patch format version: ${anyRaw.version} (supported: ${PATCH_FORMAT_VERSION})`, fileName, patchKey);\n }\n fail(`Schema validation failed: ${detail}`, fileName, patchKey);\n }\n\n const parsed = raw as { version: number; description: string; operations: Record<string, any>[] };\n\n if (parsed.version !== PATCH_FORMAT_VERSION) {\n fail(`Unknown patch format version: ${parsed.version} (supported: ${PATCH_FORMAT_VERSION})`, fileName, patchKey);\n }\n\n const description = parsed.description.trim();\n if (description.length === 0) fail('description must be non-empty', fileName, patchKey);\n if (description.length > MAX_DESCRIPTION_LENGTH) {\n fail(`description exceeds ${MAX_DESCRIPTION_LENGTH} characters`, fileName, patchKey);\n }\n\n const operations: PatchOperation[] = parsed.operations.map((op, index) => {\n const verbs = Object.keys(op);\n const verb = verbs[0];\n const context = `operation ${index} (${verb})`;\n switch (verb) {\n case 'rename_migration': {\n const from = checkMigrationKey(op.rename_migration.from, context, fileName, patchKey);\n const to = checkMigrationKey(op.rename_migration.to, context, fileName, patchKey);\n if (from === to) {\n fail(`${context}: 'from' and 'to' are identical after canonicalization ('${from}')`, fileName, patchKey);\n }\n return { verb: 'rename_migration', from, to };\n }\n case 'mark_applied':\n return { verb: 'mark_applied', key: checkMigrationKey(op.mark_applied.key, context, fileName, patchKey) };\n case 'unmark_applied':\n return { verb: 'unmark_applied', key: checkMigrationKey(op.unmark_applied.key, context, fileName, patchKey) };\n default:\n fail(`operation ${index}: unknown verb '${verb}'`, fileName, patchKey);\n }\n });\n\n return { version: parsed.version, description, operations };\n}\n\n/**\n * Validates the ordered rename plan of ALL patches (file order, then\n * operation order) against the current migration manifest.\n *\n * - Every historical key absent from the manifest must finish at a key\n * present in the manifest.\n * - Every key present in the manifest must finish at itself.\n * - Convergence and corrective chains (A->B->C, A->B->A) are allowed.\n *\n * mark_applied keys must exist in the manifest; unmark_applied keys may be\n * absent historical keys.\n */\nexport function validatePatchPlan(\n patches: PatchDocument[],\n manifest: Map<string, MigrationManifestEntry>\n): void {\n const renames: { from: string; to: string; file: string }[] = [];\n for (const patch of patches) {\n patch.operations.forEach((op, index) => {\n if (op.verb === 'rename_migration') {\n renames.push({ from: op.from, to: op.to, file: patch.fileName });\n } else if (op.verb === 'mark_applied') {\n if (!manifest.has(op.key)) {\n throw new PatchValidationError(\n `operation ${index} (mark_applied): key '${op.key}' is not present in the current migration manifest`,\n patch.fileName,\n patch.patchKey\n );\n }\n }\n });\n }\n\n if (renames.length === 0) return;\n\n // All keys mentioned by any rename\n const mentioned = new Set<string>();\n renames.forEach(r => { mentioned.add(r.from); mentioned.add(r.to); });\n\n const finalKey = (start: string): string => {\n let current = start;\n for (const r of renames) {\n if (current === r.from) current = r.to;\n }\n return current;\n };\n\n for (const key of mentioned) {\n const finish = finalKey(key);\n if (manifest.has(key)) {\n if (finish !== key) {\n throw new PatchValidationError(\n `rename plan moves current migration '${key}' to '${finish}', which would make its file incorrectly pending`\n );\n }\n } else {\n if (!manifest.has(finish)) {\n throw new PatchValidationError(\n `rename plan leaves historical key '${key}' at '${finish}', which is not present in the current migration manifest`\n );\n }\n }\n }\n}\n","import { MigrationConfig } from \"./MigrationConfig\";\nimport { ISQLRunner } from \"./SQLRunner\";\nimport { PatchDirectoryReader } from \"./PatchDirectoryReader\";\nimport { validatePatchPlan } from \"./PatchValidator\";\nimport { Dialect, loadMigrationManifest, MigrationManifestEntry } from \"./MigrationManifest\";\nimport {\n PatchApplyResult,\n PatchDocument,\n PatchOperation,\n PatchOperationResult,\n resolvePatchFolder,\n resolvePatchTable,\n} from \"./PatchTypes\";\nimport {\n PatchConflictError,\n PatchExecutionError,\n PatchIntegrityError,\n} from \"./errors\";\n\nfunction toError(error: unknown): Error {\n if (error instanceof Error) return error;\n return new Error(String(error));\n}\n\ninterface PatchHistoryRow {\n patch_key: string;\n checksum: string;\n}\n\n/**\n * Extracts the rows array from an ISQLRunner.query() result.\n *\n * BaseSQLRunner normally returns `[rows, extra]`, but a raw rows array of\n * exactly two elements escapes unwrapped (tuple ambiguity in\n * BaseSQLRunner.query). This helper handles both shapes.\n */\nfunction extractRows(result: any): any[] {\n if (!Array.isArray(result)) return [];\n if (Array.isArray(result[0])) return result[0]; // [rows, extra]\n if (result.length === 2\n && result[0] && typeof result[0] === 'object'\n && result[1] && typeof result[1] === 'object'\n && !('rows' in result[1])) {\n return result; // unwrapped 2-row array\n }\n if (result[0] == null) return [];\n return [result[0]];\n}\n\n/**\n * Applies pending ledger patches. Uses ISQLRunner directly (never the public\n * runner methods) so it can run inside the runner's preflight without\n * recursion.\n *\n * Precondition: the provided connection must not already be inside an\n * application-managed transaction when preflight begins; Proper will issue\n * its own BEGIN/COMMIT/ROLLBACK per patch and must not commit or roll back a\n * caller's outer transaction.\n */\nexport class PatchRunner {\n private patchTable: string;\n private migrationTable: string;\n private dialect: Dialect;\n\n constructor(private sqlrunner: ISQLRunner, private config: MigrationConfig) {\n this.patchTable = resolvePatchTable(config);\n this.migrationTable = config.migration_table;\n this.dialect = config.database as Dialect;\n }\n\n /**\n * Discovers, validates, and applies every unapplied patch in order.\n * Each unapplied patch is its own transaction; earlier committed patches\n * remain committed if a later patch fails.\n */\n async applyPending(): Promise<PatchApplyResult[]> {\n const reader = new PatchDirectoryReader(resolvePatchFolder(this.config));\n // Parse and validate ALL files before touching the database.\n const patches = reader.loadPatches();\n\n const history = await this.loadHistory();\n\n if (patches.length === 0 && history.length === 0) {\n return [];\n }\n\n // Applied rows must have a matching, unmodified file.\n const byKey = new Map(patches.map(p => [p.patchKey, p]));\n for (const row of history) {\n const file = byKey.get(row.patch_key);\n if (!file) {\n throw new PatchIntegrityError(\n `applied patch '${row.patch_key}' has no corresponding file in the patch folder; patch files are permanent and must never be renamed or deleted`,\n undefined,\n row.patch_key\n );\n }\n if (file.checksum !== row.checksum) {\n throw new PatchIntegrityError(\n `applied patch '${row.patch_key}' content changed after application; patch files are immutable once recorded`,\n file.fileName,\n row.patch_key,\n row.checksum,\n file.checksum\n );\n }\n }\n\n // Validate rename convergence against the current migration manifest.\n const manifest = loadMigrationManifest(this.config.migration_folder, this.dialect);\n validatePatchPlan(patches, manifest);\n\n const appliedKeys = new Set(history.map(r => r.patch_key));\n const results: PatchApplyResult[] = [];\n\n for (const patch of patches) {\n if (appliedKeys.has(patch.patchKey)) {\n results.push({\n patchKey: patch.patchKey,\n fileName: patch.fileName,\n status: 'already_applied',\n operations: [],\n });\n continue;\n }\n results.push(await this.applyOne(patch, manifest));\n }\n\n return results;\n }\n\n private async loadHistory(): Promise<PatchHistoryRow[]> {\n try {\n const result = await this.sqlrunner.query(\n `SELECT patch_key, checksum FROM ${this.patchTable} WHERE migration_table = ?`,\n [this.migrationTable]\n );\n return extractRows(result) as PatchHistoryRow[];\n } catch (error) {\n throw new PatchExecutionError(\n `failed to read patch history from '${this.patchTable}'`,\n undefined, undefined, undefined, undefined,\n toError(error)\n );\n }\n }\n\n private beginSql(): string {\n switch (this.dialect) {\n case 'sqlite': return 'BEGIN IMMEDIATE';\n case 'pg': return 'BEGIN';\n default: return 'START TRANSACTION';\n }\n }\n\n private async begin(patch: PatchDocument): Promise<void> {\n // SQLite BEGIN IMMEDIATE can fail with SQLITE_BUSY while a sibling\n // holds the write lock; retry briefly so a concurrent patch race\n // resolves instead of erroring instantly.\n const deadline = Date.now() + 10_000;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n try {\n await this.sqlrunner.execute(this.beginSql());\n return;\n } catch (error) {\n const message = toError(error).message;\n if (/SQLITE_BUSY|database is locked/i.test(message) && Date.now() < deadline) {\n await new Promise(resolve => setTimeout(resolve, 50));\n continue;\n }\n throw new PatchExecutionError(\n 'failed to start patch transaction',\n patch.fileName, patch.patchKey, undefined, undefined,\n toError(error)\n );\n }\n }\n }\n\n private async rollbackQuietly(): Promise<void> {\n try {\n await this.sqlrunner.execute('ROLLBACK');\n } catch {\n // The transaction may already be gone; nothing more to do.\n }\n }\n\n private async applyOne(\n patch: PatchDocument,\n manifest: Map<string, MigrationManifestEntry>\n ): Promise<PatchApplyResult> {\n await this.begin(patch);\n\n // Atomically claim (migration_table, patch_key) under the composite\n // primary key. If a sibling already committed the same key, the\n // insert fails and we resolve the race below.\n try {\n await this.sqlrunner.execute(\n `INSERT INTO ${this.patchTable} (migration_table, patch_key, checksum, format_version, description)\n VALUES (?, ?, ?, ?, ?)`,\n [this.migrationTable, patch.patchKey, patch.checksum, patch.version, patch.description]\n );\n } catch (claimError) {\n await this.rollbackQuietly();\n const committed = await this.findCommittedRow(patch.patchKey);\n if (committed) {\n if (committed.checksum === patch.checksum) {\n return {\n patchKey: patch.patchKey,\n fileName: patch.fileName,\n status: 'already_applied',\n operations: [],\n };\n }\n throw new PatchIntegrityError(\n `patch '${patch.patchKey}' was applied elsewhere with a different checksum`,\n patch.fileName, patch.patchKey,\n committed.checksum, patch.checksum\n );\n }\n throw new PatchExecutionError(\n 'failed to claim patch-history row',\n patch.fileName, patch.patchKey, undefined, undefined,\n toError(claimError)\n );\n }\n\n const operationResults: PatchOperationResult[] = [];\n try {\n for (let index = 0; index < patch.operations.length; index++) {\n operationResults.push(\n await this.applyOperation(patch, patch.operations[index], index, manifest)\n );\n }\n await this.sqlrunner.execute('COMMIT');\n } catch (error) {\n await this.rollbackQuietly();\n if (error instanceof PatchConflictError || error instanceof PatchExecutionError || error instanceof PatchIntegrityError) {\n throw error;\n }\n throw new PatchExecutionError(\n 'patch application failed',\n patch.fileName, patch.patchKey, undefined, undefined,\n toError(error)\n );\n }\n\n return {\n patchKey: patch.patchKey,\n fileName: patch.fileName,\n status: 'applied',\n operations: operationResults,\n };\n }\n\n private async findCommittedRow(patchKey: string): Promise<PatchHistoryRow | null> {\n const result = await this.sqlrunner.query(\n `SELECT patch_key, checksum FROM ${this.patchTable} WHERE migration_table = ? AND patch_key = ?`,\n [this.migrationTable, patchKey]\n );\n const list = extractRows(result) as PatchHistoryRow[];\n return list.length > 0 ? list[0] : null;\n }\n\n private async countRows(key: string): Promise<number> {\n // COUNT(*) always yields exactly one row, which sidesteps the\n // BaseSQLRunner tuple ambiguity for multi-row results.\n const result = await this.sqlrunner.query(\n `SELECT COUNT(*) AS row_count FROM ${this.migrationTable} WHERE migration_key = ?`,\n [key]\n );\n const rows = extractRows(result);\n const value = rows[0]?.row_count ?? Object.values(rows[0] ?? {})[0];\n return Number(value ?? 0);\n }\n\n private conflict(\n patch: PatchDocument,\n index: number,\n verb: string,\n message: string,\n keys: string[],\n counts: Record<string, number>\n ): never {\n throw new PatchConflictError(\n `operation ${index} (${verb}): ${message}`,\n patch.fileName, patch.patchKey, index, verb, keys, counts\n );\n }\n\n private async applyOperation(\n patch: PatchDocument,\n op: PatchOperation,\n index: number,\n manifest: Map<string, MigrationManifestEntry>\n ): Promise<PatchOperationResult> {\n try {\n switch (op.verb) {\n case 'rename_migration': {\n const fromCount = await this.countRows(op.from);\n const toCount = await this.countRows(op.to);\n const counts = { [op.from]: fromCount, [op.to]: toCount };\n\n if (fromCount > 1 || toCount > 1) {\n this.conflict(patch, index, op.verb,\n `ledger corruption: duplicate rows for a migration key`,\n [op.from, op.to], counts);\n }\n if (fromCount === 1 && toCount === 1) {\n this.conflict(patch, index, op.verb,\n `both '${op.from}' and '${op.to}' exist in the ledger`,\n [op.from, op.to], counts);\n }\n if (fromCount === 0) {\n // 0/0 no-op, or 0/1 already converged.\n return { verb: op.verb, changed: false };\n }\n // 1/0: update the row, preserving created_at and other\n // metadata. When `to` exists in the manifest, update the\n // up/down paths to what a fresh application would record.\n const target = manifest.get(op.to);\n if (target) {\n await this.sqlrunner.execute(\n `UPDATE ${this.migrationTable} SET migration_key = ?, up = ?, down = ? WHERE migration_key = ?`,\n [op.to, target.upFile ?? '', target.downFile ?? '', op.from]\n );\n } else {\n await this.sqlrunner.execute(\n `UPDATE ${this.migrationTable} SET migration_key = ? WHERE migration_key = ?`,\n [op.to, op.from]\n );\n }\n return { verb: op.verb, changed: true };\n }\n\n case 'mark_applied': {\n const count = await this.countRows(op.key);\n if (count > 1) {\n this.conflict(patch, index, op.verb,\n `ledger corruption: duplicate rows for '${op.key}'`,\n [op.key], { [op.key]: count });\n }\n if (count === 1) {\n return { verb: op.verb, changed: false };\n }\n const entry = manifest.get(op.key);\n await this.sqlrunner.execute(\n `INSERT INTO ${this.migrationTable} (migration_key, up, down) VALUES (?, ?, ?)`,\n [op.key, entry?.upFile ?? '', entry?.downFile ?? '']\n );\n return { verb: op.verb, changed: true };\n }\n\n case 'unmark_applied': {\n const count = await this.countRows(op.key);\n if (count > 1) {\n this.conflict(patch, index, op.verb,\n `ledger corruption: duplicate rows for '${op.key}'`,\n [op.key], { [op.key]: count });\n }\n if (count === 0) {\n return { verb: op.verb, changed: false };\n }\n await this.sqlrunner.execute(\n `DELETE FROM ${this.migrationTable} WHERE migration_key = ?`,\n [op.key]\n );\n return { verb: op.verb, changed: true };\n }\n }\n } catch (error) {\n if (error instanceof PatchConflictError) throw error;\n throw new PatchExecutionError(\n `operation failed`,\n patch.fileName, patch.patchKey, index, op.verb,\n toError(error)\n );\n }\n }\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport { CLIError } from \"./errors\";\n\nconst MAX_NAME_LENGTH = 120;\n\nconst SCAFFOLD = `version: 1\ndescription: TODO\noperations: []\n`;\n\n/**\n * Scaffolds a new patch file. Never connects to a database.\n */\nexport class PatchCreator {\n constructor(private patchFolder: string) {}\n\n /**\n * Normalizes a patch name: trim, whitespace runs -> `_`, lowercase.\n * Rejects empty results, path separators, `..`, control characters,\n * characters outside [a-z0-9_-], and names longer than 120 characters.\n */\n static normalizeName(name: string): string {\n const normalized = (name ?? '')\n .trim()\n .replace(/\\s+/g, '_')\n .toLowerCase();\n\n if (normalized.length === 0) {\n throw new CLIError('Patch name is required');\n }\n if (normalized.includes('/') || normalized.includes('\\\\')) {\n throw new CLIError('Patch name must not contain path separators');\n }\n if (normalized.includes('..')) {\n throw new CLIError(\"Patch name must not contain '..'\");\n }\n // eslint-disable-next-line no-control-regex\n if (/[\\x00-\\x1f\\x7f]/.test(normalized)) {\n throw new CLIError('Patch name must not contain control characters');\n }\n if (!/^[a-z0-9_-]+$/.test(normalized)) {\n throw new CLIError('Patch name may only contain characters [a-z0-9_-]');\n }\n if (normalized.length > MAX_NAME_LENGTH) {\n throw new CLIError(`Patch name exceeds ${MAX_NAME_LENGTH} characters after normalization`);\n }\n return normalized;\n }\n\n /**\n * Creates `<patch_folder>/<stamp>_<normalized_name>.yaml` with exclusive\n * file creation. On a millisecond-stamp collision, mints a later stamp\n * and retries. Returns the created path.\n */\n create(name: string): string {\n const normalized = PatchCreator.normalizeName(name);\n\n if (!fs.existsSync(this.patchFolder)) {\n fs.mkdirSync(this.patchFolder, { recursive: true });\n }\n\n let stamp = Date.now();\n // Bounded retry: collisions can only occur per-millisecond.\n for (let attempt = 0; attempt < 1000; attempt++) {\n const filePath = path.join(this.patchFolder, `${stamp}_${normalized}.yaml`);\n try {\n // 'wx': exclusive creation; never overwrites an existing file.\n fs.writeFileSync(filePath, SCAFFOLD, { flag: 'wx' });\n return filePath;\n } catch (error: any) {\n if (error && error.code === 'EEXIST') {\n stamp += 1; // mint a later stamp and retry\n continue;\n }\n throw error;\n }\n }\n throw new CLIError('Unable to create patch file: too many filename collisions');\n }\n}\n","\nimport type * as sqlite from 'sqlite';\nimport type { Statement } from 'sqlite3';\nimport type mysql from 'mysql2/promise';\n\n\n\ntype QueryResult = {\n stmt: Statement;\n lastID: number;\n changes: number;\n}\n\nexport interface ISQLRunner {\n query(sql: string, params?: any[]): Promise<any>;\n execute(sql: string, params?: any[]): Promise<any>;\n end(): Promise<void>;\n}\n\n/**\n * Base class that implements the common contract and helper utilities that are\n * shared between the different dialect runners. The concrete subclasses only\n * need to implement the three primitive methods `_query`, `_execute` and\n * `_end` that perform the actual driver-specific interaction. Everything else\n * – such as ensuring a uniform return shape – is handled here once.\n */\nexport abstract class BaseSQLRunner implements ISQLRunner {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n abstract _query(sql: string, params?: any[]): Promise<any>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n abstract _execute(sql: string, params?: any[]): Promise<any>;\n abstract _end(): Promise<void>;\n\n /**\n * Ensures that both MySQL and SQLite return the same tuple shape that callers\n * expect: `[rowsOrResult, extra]`. For SQLite there is no `extra` metadata\n * comparable to MySQL's `FieldPacket[]`, so we just use `undefined`.\n */\n async query(sql: string, params: any[] = []): Promise<any> {\n const result = await this._query(sql, params);\n\n // MySQL already returns the desired tuple. For SQLite we need to wrap.\n return Array.isArray(result) && result.length === 2 ? result : [result, undefined];\n }\n\n async execute(sql: string, params: any[] = []): Promise<any> {\n const result = await this._execute(sql, params);\n return Array.isArray(result) && result.length === 2 ? result : [result, undefined];\n }\n\n async end(): Promise<void> {\n await this._end();\n }\n}\n\nfunction isPromiseLike<T>(value: unknown): value is Promise<T> {\n return !!value && typeof (value as Promise<T>).then === \"function\";\n}\n\nexport class SQLRunner extends BaseSQLRunner {\n constructor(private connection: mysql.Connection) {\n super();\n }\n\n // The MySQL driver already returns the correct tuple shapes.\n async _query(sql: string, params: any[] = []) {\n return await this.connection.query(sql, params);\n }\n\n async _execute(sql: string, params: any[] = []) {\n return await this.connection.execute(sql, params);\n }\n\n async _end() {\n if (this.connection) {\n await this.connection.end();\n }\n }\n}\n\nexport class SQLiteRunner extends BaseSQLRunner {\n constructor(private connection: sqlite.Database | any) {\n super();\n }\n\n private async prepareStatement(sql: string) {\n if (typeof this.connection.prepare !== \"function\") {\n throw new Error(\"SQLite connection does not support prepare()\");\n }\n const stmt = this.connection.prepare(sql);\n return isPromiseLike(stmt) ? await stmt : stmt;\n }\n\n private async finalizeStatement(stmt: any) {\n if (!stmt || typeof stmt.finalize !== \"function\") return;\n const result = stmt.finalize();\n if (isPromiseLike(result)) {\n await result;\n }\n }\n\n private async statementAll(stmt: any, params: any[]) {\n if (typeof stmt.all !== \"function\") {\n throw new Error(\"SQLite statement does not support all()\");\n }\n // sqlite3 callback-style API\n if (stmt.all.length >= 2) {\n return await new Promise((resolve, reject) => {\n const callback = (err: Error | null, rows: any[]) => {\n if (err) return reject(err);\n resolve(rows || []);\n };\n try {\n if (params.length > 0) {\n stmt.all(params, callback);\n } else {\n stmt.all(callback);\n }\n } catch (error) {\n reject(error);\n }\n });\n }\n const result = stmt.all(...params);\n return isPromiseLike(result) ? await result : result;\n }\n\n private async statementRun(stmt: any, params: any[]) {\n if (typeof stmt.run !== \"function\") {\n throw new Error(\"SQLite statement does not support run()\");\n }\n if (stmt.run.length >= 2) {\n return await new Promise((resolve, reject) => {\n const callback = function (this: any, err: Error | null) {\n if (err) return reject(err);\n resolve({ changes: this?.changes ?? 0, lastID: this?.lastID });\n };\n try {\n if (params.length > 0) {\n stmt.run(params, callback);\n } else {\n stmt.run(callback);\n }\n } catch (error) {\n reject(error);\n }\n });\n }\n const result = stmt.run(...params);\n return isPromiseLike(result) ? await result : result;\n }\n\n async _query(sql: string, params: any[] = []) {\n const stmt = await this.prepareStatement(sql);\n try {\n const rows = await this.statementAll(stmt, params);\n return rows;\n } finally {\n await this.finalizeStatement(stmt);\n }\n }\n\n async _execute(sql: string, params: any[] = []) {\n // Handle empty or comment-only SQL gracefully\n if (this.isEmptySQL(sql)) {\n return { changes: 0, lastID: 0 }; // No-op result\n }\n\n if (this.isMultiStatement(sql)) {\n return await this.executeMultiStatement(sql, params)\n .catch((err) => {\n console.error((\n \"Error executing multi-statement SQL:\\n\"+\n `${sql}\\n`\n ), err);\n throw err;\n });\n }\n\n const stmt = await this.prepareStatement(sql);\n try {\n const info = await this.statementRun(stmt, params);\n return info;\n } finally {\n await this.finalizeStatement(stmt);\n }\n }\n\n /**\n * Checks if SQL is empty or contains only comments/whitespace.\n * Returns true if there is no actual SQL to execute.\n */\n private isEmptySQL(sql: string): boolean {\n // Remove all comments and whitespace\n const withoutComments = sql\n .replace(/--.*$/gm, '') // Remove single-line comments\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '') // Remove multi-line comments\n .trim();\n return withoutComments.length === 0;\n }\n\n private isMultiStatement(sql: string): boolean {\n // SQLite does not support multiple statements in a single query.\n return sql.split(';').length > 1;\n }\n\n private async executeMultiStatement(sql: string, params: any[] = []) {\n const statements = sql.split(';')\n .map((s) => s.split('\\n')\n .map(\n s=>this.removeComments(s))\n .filter(s=>s.trim()!='')\n .join('\\n')\n )\n .filter((s) => s.trim() !== '');\n \n const infos = await statements.reduce(async (prev,statement) => {\n const infos = await prev;\n const stmt = await this.prepareStatement(`${statement};`);\n try {\n const info = await this.statementRun(stmt, params);\n infos.push(info);\n return infos;\n } finally {\n await this.finalizeStatement(stmt);\n }\n },Promise.resolve([null] as any[]))\n .then((infos:QueryResult[]) => {\n return infos.filter((info) => info !== null);\n })\n return infos.reduce((acc,latest)=>{\n if(latest){\n acc.stmt = latest.stmt;\n acc.lastID = latest.lastID;\n acc.changes += latest.changes;\n }\n return acc\n })\n }\n\n private removeComments(sql: string): string {\n // Remove single-line comments\n sql = sql.replace(/--.*$/gm, '');\n return sql;\n }\n\n\n async _end() {\n if (this.connection) {\n await this.connection.close();\n }\n }\n}\n\n/**\n * Minimal structural type for a `pg` Client or Pool (or anything shaped like\n * one, e.g. a Hyperdrive/Neon client). We only rely on `query()` and `end()`.\n */\nexport interface PgQueryable {\n query(text: string, values?: any[]): Promise<{ rows: any[]; rowCount: number | null }>;\n end?(): Promise<void>;\n}\n\n/**\n * PostgreSQL runner.\n *\n * Proper's internal bookkeeping statements use MySQL-style `?` placeholders;\n * Postgres wants `$1..$n`, so parameterised statements are rewritten here.\n * Migration files themselves are executed verbatim with no parameters — a\n * parameter-less `query()` goes through the simple protocol, which allows\n * multiple `;`-separated statements in one call, so no client-side splitting\n * (as SQLite needs) is required.\n */\nexport class PgRunner extends BaseSQLRunner {\n constructor(private connection: PgQueryable) {\n super();\n }\n\n /** `?` -> `$1`, `$2`, ... outside of string literals / comments. */\n static toPositional(sql: string): string {\n let out = '';\n let n = 0;\n let inSingle = false;\n let inDouble = false;\n let inLineComment = false;\n let inBlockComment = false;\n for (let i = 0; i < sql.length; i++) {\n const ch = sql[i];\n const next = sql[i + 1];\n if (inLineComment) {\n out += ch;\n if (ch === '\\n') inLineComment = false;\n continue;\n }\n if (inBlockComment) {\n out += ch;\n if (ch === '*' && next === '/') { out += next; i++; inBlockComment = false; }\n continue;\n }\n if (inSingle) {\n out += ch;\n if (ch === \"'\") inSingle = false;\n continue;\n }\n if (inDouble) {\n out += ch;\n if (ch === '\"') inDouble = false;\n continue;\n }\n if (ch === '-' && next === '-') { out += ch; inLineComment = true; continue; }\n if (ch === '/' && next === '*') { out += ch + next; i++; inBlockComment = true; continue; }\n if (ch === \"'\") { out += ch; inSingle = true; continue; }\n if (ch === '\"') { out += ch; inDouble = true; continue; }\n if (ch === '?') { out += `$${++n}`; continue; }\n out += ch;\n }\n return out;\n }\n\n private async run(sql: string, params: any[]) {\n if (params.length > 0) {\n return await this.connection.query(PgRunner.toPositional(sql), params);\n }\n return await this.connection.query(sql);\n }\n\n async _query(sql: string, params: any[] = []) {\n const result = await this.run(sql, params);\n return [result.rows, result];\n }\n\n async _execute(sql: string, params: any[] = []) {\n const result = await this.run(sql, params);\n return [{ changes: result.rowCount ?? 0, lastID: undefined }, result];\n }\n\n async _end() {\n if (this.connection && typeof this.connection.end === 'function') {\n await this.connection.end();\n }\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { pathToFileURL } from 'url';\nimport Ajv from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { tsImport } from 'tsx/esm/api';\n\nimport type { IMigrationRunner, MigrationHistory } from './MigrationRunner';\nimport { MigrationRunnerFactory, FileMigrationConfigReader, loadMigrationConfig } from './MigrationRunner';\nimport type { MigrationConfig } from './MigrationConfig';\n\nexport type SeedTransactionalMode = 'runner' | 'seed' | 'none';\n\nexport type SeedOptions = {\n migrationsDir?: string;\n dataDir?: string;\n validate?: boolean;\n transactional?: SeedTransactionalMode;\n aliasMap?: Record<string, string>;\n preloadedData?: Record<string, unknown>;\n log?: (msg: string) => void;\n names?: string[];\n};\n\nexport type ResolvedSeed = {\n kind: 'sql' | 'ts' | 'js';\n name: string;\n alias: string;\n upPath: string;\n downPath?: string;\n dataPath: string | null;\n schemaPath: string | null;\n};\n\nfunction resolveAlias(name: string, aliasMap?: Record<string, string>): string {\n if (!aliasMap) return name;\n return aliasMap[name] ?? name;\n}\n\nfunction walkForFile(rootDir: string, fileName: string): string | null {\n if (!fs.existsSync(rootDir)) return null;\n const entries = fs.readdirSync(rootDir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(rootDir, entry.name);\n if (entry.isDirectory()) {\n const found = walkForFile(full, fileName);\n if (found) return found;\n } else if (entry.isFile() && entry.name === fileName) {\n return full;\n }\n }\n return null;\n}\n\nfunction resolveMigrationsDir(migrationConfig: MigrationConfig, options: SeedOptions): string {\n const fromOptions = options.migrationsDir;\n const fromConfig = migrationConfig.seeds?.migrationsDir;\n\n const dir = fromOptions ?? fromConfig;\n if (!dir) {\n throw new Error('Seed migrationsDir not configured. Set seeds.migrationsDir in proper.json or pass it explicitly.');\n }\n return dir;\n}\n\nfunction mergeSeedConfig(\n migrationConfig: MigrationConfig,\n options: SeedOptions,\n): { names: string[]; finalOptions: SeedOptions & { migrationsDir: string; validate: boolean; transactional: SeedTransactionalMode } } {\n const names = options.names && options.names.length\n ? options.names\n : migrationConfig.seeds?.list && migrationConfig.seeds.list.length\n ? migrationConfig.seeds.list\n : [];\n\n if (!names.length) {\n throw new Error('No seed names provided and no seeds.list defined in proper config');\n }\n\n const migrationsDir = resolveMigrationsDir(migrationConfig, options);\n const dataDir = options.dataDir ?? migrationConfig.seeds?.dataDir;\n const validate = options.validate !== undefined ? options.validate : true;\n const transactional = options.transactional ?? 'none';\n\n const finalOptions: SeedOptions & { migrationsDir: string; validate: boolean; transactional: SeedTransactionalMode } = {\n ...options,\n migrationsDir,\n dataDir,\n validate,\n transactional,\n };\n\n return { names, finalOptions };\n}\n\n// export function loadMigrationConfig(configFile: string): MigrationConfig {\n// const reader = new FileMigrationConfigReader(configFile);\n// return reader.loadFile();\n// }\n\nfunction resolveSqlPair(name: string, migrationsDir: string): { upPath: string; downPath: string } | null {\n const up = walkForFile(migrationsDir, `${name}.up.sql`);\n const down = walkForFile(migrationsDir, `${name}.down.sql`);\n if (up && down) {\n return { upPath: up, downPath: down };\n }\n return null;\n}\n\nfunction resolveModule(name: string, migrationsDir: string): { kind: 'ts' | 'js'; modulePath: string } | null {\n const ts = walkForFile(migrationsDir, `${name}.ts`);\n if (ts) return { kind: 'ts', modulePath: ts };\n const js = walkForFile(migrationsDir, `${name}.js`);\n if (js) return { kind: 'js', modulePath: js };\n return null;\n}\n\nexport async function resolveSeed(\n name: string,\n migrationConfig: MigrationConfig,\n options: SeedOptions,\n): Promise<ResolvedSeed> {\n const migrationsDir = resolveMigrationsDir(migrationConfig, options);\n const alias = resolveAlias(name, options.aliasMap);\n\n const sqlPair = resolveSqlPair(name, migrationsDir);\n if (sqlPair) {\n return {\n kind: 'sql',\n name,\n alias,\n upPath: sqlPair.upPath,\n downPath: sqlPair.downPath,\n dataPath: null,\n schemaPath: null,\n };\n }\n\n const module = resolveModule(name, migrationsDir);\n if (!module) {\n throw new Error(`Seed implementation not found for \"${name}\" under ${migrationsDir}`);\n }\n\n const dataDir = options.dataDir ?? migrationConfig.seeds?.dataDir;\n let dataPath: string | null = null;\n let schemaPath: string | null = null;\n\n if (dataDir) {\n dataPath = walkForFile(dataDir, `${alias}.json`);\n schemaPath = walkForFile(dataDir, `${alias}.schema.json`);\n }\n\n return {\n kind: module.kind,\n name,\n alias,\n upPath: module.modulePath,\n downPath: module.modulePath,\n dataPath,\n schemaPath,\n };\n}\n\nasync function loadJson(filePath: string): Promise<unknown> {\n const content = await fs.promises.readFile(filePath, 'utf8');\n return JSON.parse(content);\n}\n\nfunction createValidator() {\n const ajv = new Ajv({ allErrors: true, strict: false });\n addFormats(ajv);\n return ajv;\n}\n\nasync function validateData(schemaPath: string | null, data: unknown, validate: boolean, log?: (msg: string) => void) {\n if (!validate || !schemaPath) return;\n const content = await fs.promises.readFile(schemaPath, 'utf8');\n const schema = JSON.parse(content);\n const ajv = createValidator();\n const validateFn = ajv.compile(schema);\n const ok = validateFn(data);\n if (!ok) {\n log?.(`Validation failed for seed data (${schemaPath})`);\n throw new Error(`Seed data validation failed: ${ajv.errorsText(validateFn.errors || [])}`);\n }\n}\n\nasync function runSqlSeed(\n runner: IMigrationRunner,\n resolved: ResolvedSeed,\n direction: 'up' | 'down',\n): Promise<void> {\n const sqlPath = direction === 'up' ? resolved.upPath : resolved.downPath!;\n const sql = await fs.promises.readFile(sqlPath, 'utf8');\n await runner.query(sql);\n}\n\nexport type SeedContext = {\n data: unknown;\n log?: (msg: string) => void;\n dialect: string;\n};\n\nasync function loadSeedModule(modulePath: string): Promise<any> {\n const resolved = path.resolve(modulePath);\n\n // For .ts files, use tsx's tsImport which handles TypeScript in both ESM and CJS contexts\n if (resolved.endsWith('.ts')) {\n const fileUrl = pathToFileURL(resolved).href;\n return tsImport(fileUrl, fileUrl);\n }\n\n // For .js files, use standard dynamic import\n return import(resolved);\n}\n\nasync function runModuleSeed(\n runner: IMigrationRunner,\n resolved: ResolvedSeed,\n migrationConfig: MigrationConfig,\n options: SeedOptions & { validate: boolean },\n direction: 'up' | 'down',\n): Promise<void> {\n const { log } = options;\n const module = await loadSeedModule(resolved.upPath);\n const handler = module[direction];\n if (typeof handler !== 'function') {\n throw new Error(`Seed module \"${resolved.name}\" does not export ${direction}()`);\n }\n\n let data: unknown = null;\n if (options.preloadedData && Object.prototype.hasOwnProperty.call(options.preloadedData, resolved.name)) {\n data = options.preloadedData[resolved.name];\n } else if (resolved.dataPath) {\n data = await loadJson(resolved.dataPath);\n }\n\n await validateData(resolved.schemaPath, data, options.validate, log);\n\n const ctx: SeedContext = {\n data,\n log,\n dialect: migrationConfig.database || 'sql',\n };\n\n await handler(runner, ctx);\n}\n\nasync function runSingleSeed(\n runner: IMigrationRunner,\n migrationConfig: MigrationConfig,\n name: string,\n options: SeedOptions & { validate: boolean; transactional: SeedTransactionalMode },\n direction: 'up' | 'down',\n): Promise<void> {\n const resolved = await resolveSeed(name, migrationConfig, options);\n\n if (resolved.kind === 'sql') {\n await runSqlSeed(runner, resolved, direction);\n } else {\n await runModuleSeed(runner, resolved, migrationConfig, options, direction);\n }\n}\n\nasync function withTransactionalMode(\n runner: IMigrationRunner,\n migrationConfig: MigrationConfig,\n names: string[],\n options: SeedOptions & { validate: boolean; transactional: SeedTransactionalMode },\n direction: 'up' | 'down',\n): Promise<void> {\n const mode = options.transactional;\n\n if (mode === 'runner') {\n await runner.query('BEGIN');\n try {\n for (const name of names) {\n await runSingleSeed(runner, migrationConfig, name, options, direction);\n }\n await runner.query('COMMIT');\n } catch (err) {\n try {\n await runner.query('ROLLBACK');\n } catch {\n }\n throw err;\n }\n return;\n }\n\n if (mode === 'seed') {\n for (const name of names) {\n await runner.query('BEGIN');\n try {\n await runSingleSeed(runner, migrationConfig, name, options, direction);\n await runner.query('COMMIT');\n } catch (err) {\n try {\n await runner.query('ROLLBACK');\n } catch {\n }\n throw err;\n }\n }\n return;\n }\n\n for (const name of names) {\n await runSingleSeed(runner, migrationConfig, name, options, direction);\n }\n}\n\nexport async function runSeedsWithRunner(\n runner: IMigrationRunner,\n migrationConfig: MigrationConfig,\n direction: 'up' | 'down',\n options: SeedOptions,\n): Promise<void> {\n const { names, finalOptions } = mergeSeedConfig(migrationConfig, options);\n await withTransactionalMode(runner, migrationConfig, names, finalOptions, direction);\n}\n\nexport type SeedFactoryOptions = SeedOptions & {\n configFile?: string;\n};\n\nexport type SeedFactory = {\n up(names?: string[]): Promise<void>;\n down(names?: string[]): Promise<void>;\n};\n\nexport function createSeedFactory(options: SeedFactoryOptions): SeedFactory {\n const configFile = options.configFile ?? 'proper.json';\n\n return {\n async up(names?: string[]) {\n const runner = await MigrationRunnerFactory.create(configFile);\n const migrationConfig = loadMigrationConfig(configFile);\n try {\n await runSeedsWithRunner(runner, migrationConfig, 'up', {\n ...options,\n names: names && names.length ? names : options.names,\n });\n } finally {\n await runner.close();\n }\n },\n\n async down(names?: string[]) {\n const runner = await MigrationRunnerFactory.create(configFile);\n const migrationConfig = loadMigrationConfig(configFile);\n try {\n await runSeedsWithRunner(runner, migrationConfig, 'down', {\n ...options,\n names: names && names.length ? names : options.names,\n });\n } finally {\n await runner.close();\n }\n },\n };\n}\n"],"mappings":"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","names":["fs","fs","fs","fs","path","fs","fs","path","fs","path","fs","path","fs","path","s","infos","toError","settings","fs","fs","path","Ajv","fs","path","ajv","Ajv"]}
|
|
1
|
+
{"version":3,"sources":["../framework/MigrationRunner.ts","../framework/MigrationDirectoryReader.ts","../framework/errors.ts","../framework/MigrationNode.ts","../framework/SqlMigrationBuilder.ts","../framework/MigrationManifest.ts","../framework/MigrationSetup.ts","../framework/PatchTypes.ts","../framework/MigrationFilter.ts","../framework/MigrationDialectParser.ts","../framework/PatchDirectoryReader.ts","../framework/PatchValidator.ts","../framework/PatchRunner.ts","../framework/PatchCreator.ts","../framework/SQLRunner.ts","../framework/SeedRunner.ts"],"sourcesContent":["// Node built-in modules\nimport fs from 'fs';\n\n// Database driver types (value imports are lazy – see createConnection())\nimport type mysql from 'mysql2/promise';\n\n// Helper function to convert any error to Error object\nfunction toError(error: unknown): Error {\n if (error instanceof Error) return error;\n return new Error(String(error));\n}\n\n// Migration framework\nimport { MigrationConfig } from \"./MigrationConfig\";\nimport { MigrationDirectoryReader } from './MigrationDirectoryReader';\nimport { MigrationNode } from './MigrationNode';\nimport { MigrationSetup } from './MigrationSetup';\nimport { migration_filter } from './MigrationFilter';\nimport * as dialect from \"./MigrationDialectParser\";\nimport { PatchRunner } from './PatchRunner';\nimport { PatchCreator } from './PatchCreator';\nimport { PatchApplyResult, resolvePatchFolder } from './PatchTypes';\n\n\nimport { ISQLRunner,SQLRunner,SQLiteRunner,PgRunner } from './SQLRunner';\n\ntype Dialect = 'sql' | 'sqlite' | 'pg';\n\nfunction makeRunner(database: string, conn: any): ISQLRunner {\n switch(database as Dialect){\n case \"sql\":\n return new SQLRunner(conn);\n case \"sqlite\":\n return new SQLiteRunner(conn);\n case \"pg\":\n return new PgRunner(conn);\n default:\n throw ConfigurationError.unknownDatabaseType(database);\n }\n}\nimport { ErrorMessage } from './ErrorMessage';\nimport { \n ConfigurationError, \n DatabaseConnectionError, \n MigrationExecutionError,\n CLIError \n} from './errors';\n\n\nexport function loadMigrationConfig(configFile: string): MigrationConfig {\n const reader = new FileMigrationConfigReader(configFile);\n return reader.loadFile();\n}\n\nexport class MigrationRunnerFactory {\n\n private static isSQLRunner(conn: any): conn is ISQLRunner {\n return !!conn\n && typeof conn.query === \"function\"\n && typeof conn.execute === \"function\"\n && typeof conn.end === \"function\";\n }\n\n static async create(configFile:string,conn?:any){\n const configReader = new FileMigrationConfigReader(configFile);\n const config = configReader.loadFile();\n\n let factoryOwnsConnection = false;\n if(!conn){\n conn = await this.createConnection(config)\n factoryOwnsConnection = true;\n }\n return new MigrationRunnerFactory().create(config,conn,factoryOwnsConnection)\n }\n\n static async createConnection(config:MigrationConfig){\n let conn = null as any\n switch(config.database){\n case \"sql\":\n if (!config.sql){\n throw ConfigurationError.missingDatabaseConfiguration(\"sql\");\n }\n const settings = Object.assign({\n password:process.env.SQL_PASSWORD\n },config.sql);\n try {\n const mysql = await import('mysql2/promise');\n conn = await (mysql.default?.createConnection ?? mysql.createConnection)(settings);\n return conn;\n } catch (error) {\n throw DatabaseConnectionError.connectionFailed(\"sql\", toError(error).message);\n }\n case \"sqlite\":\n if (!config.sqlite){\n throw ConfigurationError.missingDatabaseConfiguration(\"sqlite\");\n }\n try {\n const sqlite = await import('sqlite');\n const sqlite3 = await import('sqlite3');\n conn = await (sqlite.default?.open ?? sqlite.open)({\n filename:config.sqlite.database,\n driver:sqlite3.default?.Database ?? sqlite3.Database\n });\n return conn;\n } catch (error) {\n throw DatabaseConnectionError.connectionFailed(\"sqlite\", toError(error).message);\n }\n case \"pg\":\n if (!config.pg && !process.env.DATABASE_URL){\n throw ConfigurationError.missingDatabaseConfiguration(\"pg\");\n }\n try {\n const pgcfg = config.pg ?? {};\n const connectionString = pgcfg.connectionString ?? process.env.DATABASE_URL;\n const settings: Record<string, unknown> = connectionString\n ? { connectionString, ssl: pgcfg.ssl }\n : { ...pgcfg, password: pgcfg.password ?? process.env.PG_PASSWORD };\n const pg = await import('pg');\n const Client = (pg as any).default?.Client ?? (pg as any).Client;\n conn = new Client(settings);\n await conn.connect();\n return conn;\n } catch (error) {\n throw DatabaseConnectionError.connectionFailed(\"pg\", toError(error).message);\n }\n default:\n throw ConfigurationError.unknownDatabaseType(config.database);\n }\n \n }\n\n static async createEmpty(configFile:string){\n const configReader = new FileMigrationConfigReader(configFile);\n const config = configReader.loadFile();\n return new MigrationRunnerFactory().createEmpty(config)\n }\n\n\n async create(config:MigrationConfig,conn:any,factoryOwnsConnection:boolean=false):Promise<MySQLMigrationRunner>{\n let sqlrunner:ISQLRunner;\n let driverConnection = conn;\n\n if (MigrationRunnerFactory.isSQLRunner(conn)) {\n sqlrunner = conn;\n driverConnection = null;\n } else {\n sqlrunner = makeRunner(config.database, conn);\n }\n const setup = new MigrationSetup(sqlrunner,config);\n const read_strategy = this.getReadStategy(config)\n\n const migration_files = new MigrationDirectoryReader(config.migration_folder,read_strategy,sqlrunner,config.database as Dialect)\n\n const runner = new MySQLMigrationRunner(config,migration_files,setup,sqlrunner,driverConnection);\n\n // Single preflight authority: create the migrations infrastructure\n // AND apply pending ledger patches before the runner is handed back.\n // Callers (embedded consumers included) therefore never observe\n // migration completion state that patches would have repaired.\n try {\n await runner.setup();\n } catch (error) {\n // Close only a connection the factory itself created; a\n // caller-injected connection stays open for the caller to manage.\n if (factoryOwnsConnection) {\n try { await sqlrunner.end(); } catch { /* best-effort cleanup */ }\n }\n throw error;\n }\n\n return runner;\n }\n\n\n async createEmpty(config:MigrationConfig):Promise<MySQLMigrationRunner>{\n const conn = null as any\n const sqlrunner = makeRunner(config.database, conn);\n const setup = new MigrationSetup(sqlrunner,config);\n const read_strategy = this.getReadStategy(config)\n\n const migration_files = new MigrationDirectoryReader(config.migration_folder,read_strategy,sqlrunner,config.database as Dialect)\n // createEmpty never performs setup or patch application.\n return new MySQLMigrationRunner(config,migration_files,setup,sqlrunner,conn,false);\n }\n\n private getReadStategy(config:MigrationConfig){\n switch(config.database){\n case \"sql\":\n return dialect.MySqlDialectParser\n case \"sqlite\":\n return dialect.SqliteDialectParser\n case \"pg\":\n return dialect.PgDialectParser\n default:\n throw ConfigurationError.unknownDatabaseType(config.database);\n }\n }\n}\n\n\nexport interface MigrationHistory{\n name:string\n up:string\n down:string\n}\n\nexport interface IMigrationRunner {\n setup(): Promise<void>;\n applyPendingPatches(): Promise<PatchApplyResult[]>;\n createPatch(name: string): string;\n terminate(): Promise<void>;\n getMigrationsHistory(): Promise<MigrationHistory[]>;\n getMigrations(): Promise<MigrationNode[]>;\n getPendingMigrations(): Promise<MigrationNode[]>;\n getCompletedMigrations(): Promise<MigrationNode[]>;\n migrate(migrationNodes: MigrationNode[], forward: boolean): Promise<void>;\n reset(): Promise<void>;\n createMigration(name: string): void;\n close(): Promise<void>;\n init(config_file: string): Promise<void>;\n query(sql: string, params?: any[]): Promise<any>;\n}\n\nexport class MySQLMigrationRunner implements IMigrationRunner {\n\n /**\n * Memoized in-flight preflight promise. Simultaneous or repeated calls\n * to setup() on one runner execute the preflight (migration table setup\n * + patch application) exactly once. Cleared after rejection so a caller\n * may retry after fixing the cause.\n */\n private preflightPromise: Promise<void> | null = null;\n private lastPatchResults: PatchApplyResult[] = [];\n\n constructor(\n private config:MigrationConfig,\n private directory:MigrationDirectoryReader,\n private setupRunner:MigrationSetup,\n private sqlrunner:ISQLRunner,\n private connection:mysql.Connection,\n private preflightEnabled:boolean = true\n){\n\n }\n\n async setup(){\n if (!this.preflightEnabled) {\n // Runners built by createEmpty() never perform setup or patch\n // application; calling setup() on them remains harmless.\n return;\n }\n if (!this.preflightPromise) {\n this.preflightPromise = this.runPreflight();\n this.preflightPromise.catch(() => {\n // Clear the memoized promise after rejection so a caller may\n // retry after fixing the cause.\n this.preflightPromise = null;\n });\n }\n return this.preflightPromise;\n }\n\n private async runPreflight(): Promise<void> {\n try {\n await this.setupRunner.setup();\n } catch (error) {\n throw new MigrationExecutionError('Failed to set up migration database', undefined, undefined, toError(error));\n }\n // Patch internals use ISQLRunner directly and never call the public\n // runner methods, avoiding setup recursion. Patch errors are already\n // typed (PatchError subclasses) and propagate as-is.\n const patchRunner = new PatchRunner(this.sqlrunner, this.config);\n this.lastPatchResults = await patchRunner.applyPending();\n }\n\n /**\n * Delegates to the same idempotent preflight; returns the results of the\n * patch pass that ran (or is running) for this runner.\n */\n async applyPendingPatches(): Promise<PatchApplyResult[]> {\n await this.setup();\n return this.lastPatchResults;\n }\n\n /**\n * Scaffolds a new ledger patch file and returns the created path.\n * Never connects to a database.\n */\n createPatch(name: string): string {\n const creator = new PatchCreator(resolvePatchFolder(this.config));\n return creator.create(name);\n }\n\n async terminate(){\n try {\n await this.setupRunner.teardown();\n } catch (error) {\n throw new MigrationExecutionError('Failed to tear down migration database', undefined, undefined, toError(error));\n }\n }\n\n async getMigrationsHistory():Promise<MigrationHistory[]>{\n await this.setup();\n try {\n const results = await this.sqlrunner.query(`\n select * \n from ${this.config.migration_table}\n `);\n return results[0] as any;\n } catch (error) {\n throw new MigrationExecutionError('Failed to get migration history', undefined, undefined, toError(error));\n }\n }\n\n\n async getMigrations(){\n await this.setup();\n try {\n return this.directory.loadMigrations(this.config.migration_table,this.connection);\n } catch (error) {\n throw new MigrationExecutionError('Failed to load migrations', undefined, undefined, toError(error));\n }\n }\n\n async getPendingMigrations(){\n try {\n const migrations = await this.getMigrations();\n return migration_filter(migrations,false);\n } catch (error) {\n if (error instanceof MigrationExecutionError) {\n throw error;\n }\n throw new MigrationExecutionError('Failed to get pending migrations', undefined, undefined, toError(error));\n }\n }\n\n async getCompletedMigrations(){\n try {\n const migrations = await this.getMigrations();\n return migration_filter(migrations,true);\n } catch (error) {\n if (error instanceof MigrationExecutionError) {\n throw error;\n }\n throw new MigrationExecutionError('Failed to get completed migrations', undefined, undefined, toError(error));\n }\n }\n\n async migrate(migrationNodes:MigrationNode[],forward:boolean):Promise<void>{\n await this.setup();\n for(let node of migrationNodes){\n try {\n if(forward){\n await node.up();\n }else{\n await node.down();\n }\n } catch (error) {\n throw new MigrationExecutionError(\n `Failed to ${forward ? 'apply' : 'rollback'} migration`,\n node.name || String(node),\n forward ? node.up_sql() : node.down_sql(),\n toError(error)\n );\n }\n }\n }\n\n\n async reset(){\n await this.setup();\n try {\n let migrations = await this.getMigrations();\n const rollback = await migration_filter(migrations,true);\n await this.migrate(rollback.reverse(),false);\n migrations = await this.getMigrations();\n const rollforward = await migration_filter(migrations,false);\n await this.migrate(rollforward,true);\n } catch (error) {\n if (error instanceof MigrationExecutionError) {\n throw error;\n }\n throw new MigrationExecutionError('Failed to reset migrations', undefined, undefined, toError(error));\n }\n }\n\n\n createMigration(name:string){\n try {\n const creator = new MigrationCreator(this.config);\n creator.create(name);\n } catch (error) {\n throw new MigrationExecutionError(`Failed to create migration: ${name}`, undefined, undefined, toError(error));\n }\n }\n\n\n async close(){\n if (this.sqlrunner) {\n try {\n await this.sqlrunner.end();\n } catch (error) {\n throw new DatabaseConnectionError(`Failed to close database connection: ${toError(error).message}`);\n }\n }\n }\n\n async query(sql: string, params?: any[]): Promise<any> {\n return await this.sqlrunner.query(sql, params);\n }\n\n async init(config_file:string){\n try {\n console.log(`Checking for ${config_file}`);\n const config_exist = fs.existsSync(config_file);\n\n if(!config_exist){\n console.log(`Creating ${config_file}`);\n const default_config = {\n \"migration_folder\":\"migrations\",\n \"migration_table\":\"proper_migrations\",\n \"database\": \"sql\",\n \"sql\":{\n \"host\":\"localhost\",\n \"user\":\"root\",\n \"database\":\"proper\",\n \"password\":\"\"\n }\n };\n fs.writeFileSync(config_file,JSON.stringify(default_config,null,2)); \n console.log(`Created ${config_file}`);\n }\n } catch (error) {\n throw new ConfigurationError(`Failed to initialize config file: ${toError(error).message}`);\n }\n }\n}\n\n\nexport class FileMigrationConfigReader{\n\n constructor(private configFile:string){\n\n }\n\n loadFile(){\n try {\n const fileContent = fs.readFileSync(this.configFile);\n const config:MigrationConfig = JSON.parse(fileContent.toString());\n \n // Validate required fields\n if (!config.migration_folder) {\n throw ConfigurationError.missingRequiredProperty('migration_folder');\n }\n \n if (!config.migration_table) {\n throw ConfigurationError.missingRequiredProperty('migration_table');\n }\n \n // For backward compatibility: if database type is omitted we derive\n // it from the presence of the dialect specific configuration\n // blocks. This keeps older `proper.json` files – that only defined\n // an \"sql\" or \"sqlite\" section – working without modification.\n if (!config.database) {\n if (config.sql) {\n config.database = 'sql';\n } else if (config.sqlite) {\n config.database = 'sqlite';\n } else if (config.pg) {\n config.database = 'pg';\n } else {\n throw ConfigurationError.missingRequiredProperty('database');\n }\n }\n \n return config;\n } catch (error) {\n if (error instanceof ConfigurationError) {\n throw error;\n }\n const err = toError(error);\n if (err.message.includes('ENOENT')) {\n throw new ConfigurationError(`Config file not found: ${this.configFile}`);\n }\n throw new ConfigurationError(`Failed to load config file: ${err.message}`);\n }\n }\n}\n\n\nexport class MigrationCreator{\n constructor(private config:MigrationConfig){\n \n }\n\n\n create(name:string){\n if (!name) {\n throw new CLIError('Migration name is required');\n }\n\n try {\n // Ensure the migration folder exists\n if (!fs.existsSync(this.config.migration_folder)) {\n fs.mkdirSync(this.config.migration_folder, { recursive: true });\n }\n\n const now_timestamp = Date.now();\n\n const filename_up = `${now_timestamp}_${name}.up.sql`;\n const filename_down = `${now_timestamp}_${name}.down.sql`;\n\n fs.writeFileSync(`${this.config.migration_folder}/${filename_up}`,`\n-- Write your up migration here\n `.trim());\n\n fs.writeFileSync(`${this.config.migration_folder}/${filename_down}`,`\n-- Write your down migration here\n `.trim());\n \n console.log(`Created migration files:`);\n console.log(` ${filename_up}`);\n console.log(` ${filename_down}`);\n } catch (error) {\n if (error instanceof CLIError) {\n throw error;\n }\n throw new MigrationExecutionError(`Failed to create migration files: ${toError(error).message}`);\n }\n }\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport { MigrationNode } from './MigrationNode';\nimport { SqlMigrationBuilder } from './SqlMigrationBuilder';\nimport type mysql from \"mysql2/promise\";\nimport { ISQLRunner } from \"./SQLRunner\";\nimport { canonicalMigrationKey, isMigrationFile, resolveMigrationFile, Dialect } from \"./MigrationManifest\";\n\n\nexport interface MigrationOptions{\n conn:mysql.Connection\n}\n\nexport class MigrationDirectoryReader {\n\n constructor(\n private directory: string,\n private read_strategy: any,\n private sqlrunner: ISQLRunner,\n private dialect: 'sql' | 'sqlite' | 'pg' = 'sql'\n ) {\n\n }\n\n /**\n * Resolves the appropriate file for a migration based on dialect.\n * Priority: dialect-specific file > generic file\n * File extensions: `.mysql.up.sql`, `.sqlite.up.sql`, `.pg.up.sql`.\n */\n private resolveFile(baseName: string, direction: 'up' | 'down'): string | null {\n return resolveMigrationFile(this.directory, baseName, direction, this.dialect as Dialect);\n }\n\n /**\n * Checks if a file path is dialect-specific (contains .mysql. or .sqlite. in the name)\n */\n private isDialectSpecific(filePath: string): boolean {\n return /\\.(mysql|sqlite|pg)\\.(up|down)\\.sql$/i.test(filePath);\n }\n\n loadMigrations(table:string,connection:any):MigrationNode[] {\n\n fs.existsSync(this.directory) || fs.mkdirSync(this.directory);\n // Only `<key>[.dialect].up|down.sql|js` files are migrations; anything\n // else sharing the folder (patch YAML files, docs, ...) is ignored so\n // it can never become a phantom migration key.\n const dir_content = fs.readdirSync(this.directory,{withFileTypes:true})\n .filter(file=>file.isFile())\n .map(file=>file.name)\n .filter(isMigrationFile);\n\n // Extract unique migration keys (stripping dialect extensions)\n const uniqueKeys = new Set<string>();\n dir_content.forEach(file => {\n // Strip dialect extension (.mysql or .sqlite) and direction (.up or .down) to get base key\n const key = canonicalMigrationKey(file);\n uniqueKeys.add(key);\n });\n\n const migration_sorter: any = {};\n\n // For each unique key, resolve the correct files based on dialect\n uniqueKeys.forEach((migration_key) => {\n const builder = new SqlMigrationBuilder(migration_key);\n\n const upFile = this.resolveFile(migration_key, 'up');\n const downFile = this.resolveFile(migration_key, 'down');\n\n if (upFile) {\n this.loadMigration(builder, upFile);\n }\n if (downFile) {\n this.loadMigration(builder, downFile);\n }\n\n migration_sorter[migration_key] = builder;\n });\n\n const keys = Object.keys(migration_sorter)\n\n keys.sort()\n\n const built = keys.map(key=>{\n return migration_sorter[key].build(table,this.sqlrunner)\n })\n return built\n\n }\n\n\n loadMigration(builder: SqlMigrationBuilder, file: string) {\n const is_sql = /sql$/i.test(file);\n const is_js = /js$/i.test(file);\n const is_up = /up\\.(js|sql)/i.test(file);\n const is_down = /down\\.(js|sql)/i.test(file);\n if (is_sql && is_up) {\n const content = this.sql_up(file);\n builder.set_up(file,content);\n } else if (is_sql && is_down) {\n const content = this.sql_down(file);\n builder.set_down(file,content);\n } else {\n throw new Error(`Invalid migration file: ${file}`);\n }\n return builder;\n }\n\n\n sql_up(file: string) {\n let content = fs.readFileSync(file).toString();\n // Dialect-specific files bypass read_strategy (no inline marker parsing needed)\n if (!this.isDialectSpecific(file)) {\n content = this.read_strategy(content);\n }\n return content.trim();\n }\n\n sql_down(file: string) {\n let content = fs.readFileSync(file).toString();\n // Dialect-specific files bypass read_strategy (no inline marker parsing needed)\n if (!this.isDialectSpecific(file)) {\n content = this.read_strategy(content);\n }\n return content.trim();\n }\n\n}\n","/**\n * Base class for all migration-related errors\n */\nexport class MigrationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'MigrationError';\n // This is needed to make instanceof work correctly in ES5\n Object.setPrototypeOf(this, MigrationError.prototype);\n }\n}\n\n/**\n * Error thrown when there is an issue with the configuration\n */\nexport class ConfigurationError extends MigrationError {\n constructor(message: string) {\n super(`Configuration Error: ${message}`);\n this.name = 'ConfigurationError';\n Object.setPrototypeOf(this, ConfigurationError.prototype);\n }\n\n /**\n * Helper method for missing database configuration\n * @param dbType The database type (e.g., 'sql', 'sqlite')\n * @returns A ConfigurationError with appropriate message\n */\n static missingDatabaseConfiguration(dbType: string): ConfigurationError {\n return new ConfigurationError(`Missing ${dbType} configuration`);\n }\n\n /**\n * Helper method for unknown database type\n * @param dbType The unknown database type\n * @returns A ConfigurationError with appropriate message\n */\n static unknownDatabaseType(dbType: string): ConfigurationError {\n return new ConfigurationError(`Unknown database type: ${dbType}`);\n }\n\n /**\n * Helper method for missing required configuration properties\n * @param property The name of the missing property\n * @returns A ConfigurationError with appropriate message\n */\n static missingRequiredProperty(property: string): ConfigurationError {\n return new ConfigurationError(`Missing required property: ${property}`);\n }\n}\n\n/**\n * Error thrown when there is an issue with the database connection\n */\nexport class DatabaseConnectionError extends MigrationError {\n constructor(message: string) {\n super(`Database Connection Error: ${message}`);\n this.name = 'DatabaseConnectionError';\n Object.setPrototypeOf(this, DatabaseConnectionError.prototype);\n }\n\n /**\n * Helper method for connection errors\n * @param dbType The database type (e.g., 'sql', 'sqlite')\n * @param details Additional error details\n * @returns A DatabaseConnectionError with appropriate message\n */\n static connectionFailed(dbType: string, details?: string): DatabaseConnectionError {\n const message = details \n ? `Failed to connect to ${dbType} database: ${details}`\n : `Failed to connect to ${dbType} database`;\n return new DatabaseConnectionError(message);\n }\n\n /**\n * Helper method for authentication errors\n * @param dbType The database type (e.g., 'sql', 'sqlite')\n * @returns A DatabaseConnectionError with appropriate message\n */\n static authenticationFailed(dbType: string): DatabaseConnectionError {\n return new DatabaseConnectionError(`Authentication failed for ${dbType} database`);\n }\n}\n\n/**\n * Error thrown when there is an issue with executing a migration\n */\nexport class MigrationExecutionError extends MigrationError {\n constructor(\n message: string,\n public readonly migrationName?: string,\n public readonly sql?: string,\n public readonly originalError?: Error\n ) {\n /*\n * The public `message` that gets surfaced to callers **must not** include the\n * raw SQL text. The SQL string is already exposed through the dedicated\n * `sql` property and adding it to the message makes it unnecessarily noisy\n * and difficult to assert against in unit-tests. Therefore we only embed\n * the essential information (error type, optional migration name and the\n * short error message) in the main message string while keeping the full\n * SQL available separately.\n */\n let fullMessage = `Migration Execution Error${migrationName ? ` in '${migrationName}'` : ''}: ${message}`;\n\n if(originalError){\n fullMessage += `\\nOriginal Error:\\n${originalError.message}`;\n }\n\n super(fullMessage);\n this.name = 'MigrationExecutionError';\n Object.setPrototypeOf(this, MigrationExecutionError.prototype);\n }\n\n /**\n * Helper method for SQL execution errors\n * @param migrationName The name of the migration\n * @param sql The SQL that caused the error\n * @param originalError The original error thrown by the database driver\n * @returns A MigrationExecutionError with appropriate message\n */\n static sqlExecutionFailed(migrationName: string, sql: string, originalError: Error): MigrationExecutionError {\n return new MigrationExecutionError(\n originalError.message,\n migrationName,\n sql,\n originalError\n );\n }\n\n /**\n * Helper method for missing migration file errors\n * @param filename The missing file\n * @returns A MigrationExecutionError with appropriate message\n */\n static missingMigrationFile(filename: string): MigrationExecutionError {\n return new MigrationExecutionError(`Migration file not found: ${filename}`);\n }\n\n /**\n * Helper method for invalid migration file format errors\n * @param filename The invalid file\n * @param details Additional error details\n * @returns A MigrationExecutionError with appropriate message\n */\n static invalidMigrationFile(filename: string, details?: string): MigrationExecutionError {\n const message = details\n ? `Invalid migration file format in ${filename}: ${details}`\n : `Invalid migration file format in ${filename}`;\n return new MigrationExecutionError(message);\n }\n}\n\n/**\n * Base class for all patch-related errors.\n */\nexport class PatchError extends MigrationError {\n constructor(\n message: string,\n public readonly patchFile?: string,\n public readonly patchKey?: string\n ) {\n super(`Patch Error: ${message}`);\n this.name = 'PatchError';\n Object.setPrototypeOf(this, PatchError.prototype);\n }\n}\n\n/**\n * A patch file failed YAML parsing or schema/plan validation.\n */\nexport class PatchValidationError extends PatchError {\n constructor(message: string, patchFile?: string, patchKey?: string) {\n super(message, patchFile, patchKey);\n this.name = 'PatchValidationError';\n Object.setPrototypeOf(this, PatchValidationError.prototype);\n }\n}\n\n/**\n * An applied patch's file is missing or its content no longer matches the\n * checksum recorded at application time.\n */\nexport class PatchIntegrityError extends PatchError {\n constructor(\n message: string,\n patchFile?: string,\n patchKey?: string,\n public readonly expectedChecksum?: string,\n public readonly actualChecksum?: string\n ) {\n super(message, patchFile, patchKey);\n this.name = 'PatchIntegrityError';\n Object.setPrototypeOf(this, PatchIntegrityError.prototype);\n }\n}\n\n/**\n * An operation precondition failed: ledger conflict or corruption\n * (unexpected row counts) at the operation's turn.\n */\nexport class PatchConflictError extends PatchError {\n constructor(\n message: string,\n patchFile?: string,\n patchKey?: string,\n public readonly operationIndex?: number,\n public readonly operationVerb?: string,\n public readonly migrationKeys?: string[],\n public readonly observedRowCounts?: Record<string, number>\n ) {\n super(message, patchFile, patchKey);\n this.name = 'PatchConflictError';\n Object.setPrototypeOf(this, PatchConflictError.prototype);\n }\n}\n\n/**\n * A database/transaction failure while applying a patch.\n */\nexport class PatchExecutionError extends PatchError {\n constructor(\n message: string,\n patchFile?: string,\n patchKey?: string,\n public readonly operationIndex?: number,\n public readonly operationVerb?: string,\n public readonly originalError?: Error\n ) {\n super(originalError ? `${message}\\nOriginal Error:\\n${originalError.message}` : message, patchFile, patchKey);\n this.name = 'PatchExecutionError';\n Object.setPrototypeOf(this, PatchExecutionError.prototype);\n }\n}\n\n/**\n * Error thrown when there is an issue with the migration CLI\n */\nexport class CLIError extends MigrationError {\n constructor(message: string) {\n super(`CLI Error: ${message}`);\n this.name = 'CLIError';\n Object.setPrototypeOf(this, CLIError.prototype);\n }\n\n /**\n * Helper method for missing command errors\n * @returns A CLIError with appropriate message\n */\n static missingCommand(): CLIError {\n return new CLIError('No command specified. Run with --help for usage information.');\n }\n\n /**\n * Helper method for unknown command errors\n * @param command The unknown command\n * @returns A CLIError with appropriate message\n */\n static unknownCommand(command: string): CLIError {\n return new CLIError(`Unknown command: ${command}. Run with --help for usage information.`);\n }\n\n /**\n * Helper method for missing required argument errors\n * @param argument The missing argument\n * @returns A CLIError with appropriate message\n */\n static missingRequiredArgument(argument: string): CLIError {\n return new CLIError(`Missing required argument: ${argument}`);\n }\n}\n","import type { Connection } from 'mysql2/promise';\nimport { MigrationStatus } from './MigrationStatus';\nimport { ISQLRunner } from './SQLRunner';\nimport { MigrationExecutionError } from './errors';\n\nexport abstract class MigrationNode {\n name: string;\n\n constructor(name?: string) {\n this.name = name || '';\n }\n\n abstract get_key():string;\n abstract status(): Promise<MigrationStatus>;\n abstract up(): Promise<void>;\n abstract down(): Promise<void>;\n abstract up_sql(): string;\n abstract down_sql(): string;\n}\n\n\nexport class SqlMigrationNode extends MigrationNode {\n up_sql(): string {\n return this.sql_up;\n }\n down_sql(): string {\n return this.sql_down;\n }\n get_key(): string {\n return this.key;\n }\n\n constructor(private conn:ISQLRunner,\n private table:string, \n private key:string,\n private up_file:string,\n private sql_up:string,\n private down_file:string,\n private sql_down:string) {\n super(key);\n }\n\n async status(): Promise<MigrationStatus> {\n try {\n const result = await this.conn.query(`\n select * \n from ${this.table}\n where migration_key = ?;\n `, [this.key]);\n\n if(result.length > 0 && result[0].length > 0){\n return {\n completed: true\n };\n } else {\n return {\n completed: false\n };\n }\n } catch (error) {\n throw new MigrationExecutionError(\n `Error checking status for migration`,\n this.key,\n undefined,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n async up(): Promise<void> {\n try {\n await this.conn.execute(this.sql_up);\n } catch (error) {\n throw new MigrationExecutionError(\n `Error executing UP migration`,\n this.key,\n this.sql_up,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n \n try {\n await this.conn.execute(`\n insert into ${this.table} (migration_key,up,down)\n values (?,?,?)\n `, [this.key, this.up_file, this.down_file]);\n } catch (error) {\n throw new MigrationExecutionError(\n `Error recording migration completion`,\n this.key,\n undefined,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n async down(): Promise<void> {\n try {\n await this.conn.execute(this.sql_down);\n } catch (error) {\n throw new MigrationExecutionError(\n `Error executing DOWN migration`,\n this.key,\n this.sql_down,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n \n try {\n await this.conn.execute(`\n delete from ${this.table}\n where migration_key = ?\n `, [this.key]);\n } catch (error) {\n throw new MigrationExecutionError(\n `Error removing migration record`,\n this.key,\n undefined,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n}\n\n\nexport class SqliteMigrationNode extends MigrationNode {\n up_sql(): string {\n return this.sql_up;\n }\n down_sql(): string {\n return this.sql_down;\n }\n constructor(\n private conn: ISQLRunner, // your SQLite runner\n private table: string,\n private key: string,\n private up_file: string,\n private sql_up: string,\n private down_file: string,\n private sql_down: string\n ) {\n super(key);\n }\n\n /**\n * Returns the unique key for this migration (e.g. timestamp + name).\n */\n get_key(): string {\n return this.key;\n }\n\n /**\n * Check if this migration is already completed by looking in the migration table.\n */\n async status(): Promise<MigrationStatus> {\n try {\n // Usually `this.conn.query(...)` returns an array of rows.\n // The first element might be the row set, depending on your runner.\n const cursor = await this.conn.query(\n `SELECT * FROM ${this.table} WHERE migration_key = ?;`,\n [this.key]\n );\n\n // Usually, `cursor[0]` is the row array in many MySQL runners;\n // In a SQLite scenario, it may be just `cursor`\n // So adjust depending on your actual runner's return shape.\n const rows = cursor[0] as any[];\n\n if (rows && rows.length > 0) {\n return { completed: true };\n } else {\n return { completed: false };\n }\n } catch (error) {\n throw new MigrationExecutionError(\n `Error checking status for migration`,\n this.key,\n undefined,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n /**\n * Run the 'up' SQL, then record this migration in the table.\n */\n async up(): Promise<void> {\n try {\n // Execute the 'up' script\n await this.conn.execute(this.sql_up);\n } catch (error) {\n throw new MigrationExecutionError(\n `Error executing UP migration`,\n this.key,\n this.sql_up,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n\n // Insert a record of this migration having completed\n try {\n await this.conn.execute(\n `\n INSERT INTO ${this.table} (migration_key, up, down)\n VALUES (?, ?, ?)\n `,\n [this.key, this.up_file, this.down_file]\n );\n } catch (error) {\n throw new MigrationExecutionError(\n `Error recording migration completion`,\n this.key,\n undefined,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n /**\n * Run the 'down' SQL, then remove this migration record from the table.\n */\n async down(): Promise<void> {\n try {\n // Execute the 'down' script\n await this.conn.execute(this.sql_down);\n } catch (error) {\n throw new MigrationExecutionError(\n `Error executing DOWN migration`,\n this.key,\n this.sql_down,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n\n // Remove the migration from the table\n try {\n await this.conn.execute(\n `\n DELETE FROM ${this.table}\n WHERE migration_key = ?\n `,\n [this.key]\n );\n } catch (error) {\n throw new MigrationExecutionError(\n `Error removing migration record`,\n this.key,\n undefined,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n}","import type { Connection } from 'mysql2/promise';\nimport { SqlMigrationNode } from './MigrationNode';\nimport { ISQLRunner } from './SQLRunner';\n\n\n\nexport class SqlMigrationBuilder {\n\n private up: string = '';\n private up_file: string = '';\n private down: string = '';\n private down_file: string = '';\n\n constructor(private key: string) {\n }\n\n set_up(file:string,up: string) {\n this.up_file = file;\n this.up = up;\n }\n\n set_down(file:string,down: string) {\n this.down_file = file;\n this.down = down;\n }\n\n build(table:string,conn: ISQLRunner) {\n return new SqlMigrationNode(conn, table,this.key, this.up_file, this.up, this.down_file,this.down);\n }\n}\n","import fs from \"fs\";\nimport path from \"path\";\n\nexport type Dialect = 'sql' | 'sqlite' | 'pg';\n\n/**\n * Matches valid migration filenames: `<key>[.dialect].up|down.sql|js`.\n * Anything else in the migration folder (patch YAML files, READMEs, editor\n * droppings, ...) is not a migration file and must never become a\n * migration key.\n */\nconst MIGRATION_FILE_REGEX = /(?:\\.(mysql|sqlite|pg))?\\.(up|down)\\.(sql|js)$/i;\n\nexport function isMigrationFile(fileName: string): boolean {\n return MIGRATION_FILE_REGEX.test(fileName);\n}\n\n/**\n * Canonicalizes a migration key the same way MigrationDirectoryReader derives\n * keys from filenames: strip any dialect/direction extension and lowercase.\n * Accepts either a bare key or a migration filename.\n */\nexport function canonicalMigrationKey(value: string): string {\n return value\n .replace(MIGRATION_FILE_REGEX, \"\")\n .toLowerCase();\n}\n\n/**\n * Resolves the up/down file for a migration base name honoring dialect\n * priority: dialect-specific file > generic file. Mirrors\n * MigrationDirectoryReader.resolveFile.\n */\nexport function resolveMigrationFile(\n directory: string,\n baseName: string,\n direction: 'up' | 'down',\n dialect: Dialect\n): string | null {\n const dialectExt = dialect === 'sql' ? 'mysql' : dialect;\n\n const dialectFile = path.join(directory, `${baseName}.${dialectExt}.${direction}.sql`);\n if (fs.existsSync(dialectFile)) return dialectFile;\n\n const genericFile = path.join(directory, `${baseName}.${direction}.sql`);\n if (fs.existsSync(genericFile)) return genericFile;\n\n return null;\n}\n\nexport interface MigrationManifestEntry {\n key: string;\n upFile: string | null;\n downFile: string | null;\n}\n\n/**\n * Loads the migration manifest: canonical keys plus resolved file paths.\n * Does not read migration status and does not execute any SQL.\n * A missing migration folder yields an empty manifest.\n */\nexport function loadMigrationManifest(directory: string, dialect: Dialect): Map<string, MigrationManifestEntry> {\n const manifest = new Map<string, MigrationManifestEntry>();\n if (!fs.existsSync(directory)) return manifest;\n\n const files = fs.readdirSync(directory, { withFileTypes: true })\n .filter(f => f.isFile())\n .map(f => f.name)\n .filter(isMigrationFile);\n\n const uniqueKeys = new Set<string>();\n files.forEach(file => uniqueKeys.add(canonicalMigrationKey(file)));\n\n uniqueKeys.forEach(key => {\n manifest.set(key, {\n key,\n upFile: resolveMigrationFile(directory, key, 'up', dialect),\n downFile: resolveMigrationFile(directory, key, 'down', dialect),\n });\n });\n\n return manifest;\n}\n","import { MigrationConfig } from \"./MigrationConfig\";\nimport fs from \"fs\";\nimport { ISQLRunner } from './SQLRunner';\nimport { resolvePatchTable } from './PatchTypes';\n\nexport class MigrationSetup {\n constructor(private sqlrunner: ISQLRunner, private config: MigrationConfig) {}\n\n\n async setup() {\n\n fs.existsSync(this.config.migration_folder) || fs.mkdirSync(this.config.migration_folder);\n\n const tableName = this.config.migration_table;\n\n // Use dialect-specific DDL so that the migrations table can be created\n // both in MySQL/MariaDB and in SQLite. The two dialects differ mainly\n // in the auto-increment syntax and the column types.\n const createTableSql = this.config.database === 'sqlite'\n ? `CREATE TABLE IF NOT EXISTS ${tableName} (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n migration_key TEXT,\n up TEXT,\n down TEXT,\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n )`\n : this.config.database === 'pg'\n ? `CREATE TABLE IF NOT EXISTS ${tableName} (\n id SERIAL PRIMARY KEY,\n migration_key TEXT,\n up TEXT,\n down TEXT,\n created_at TIMESTAMPTZ DEFAULT now()\n )`\n : `CREATE TABLE IF NOT EXISTS ${tableName} (\n id INT AUTO_INCREMENT PRIMARY KEY,\n migration_key VARCHAR(255),\n up VARCHAR(255),\n down VARCHAR(255),\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n )`;\n\n await this.sqlrunner.query(createTableSql);\n\n // Patch table: records applied ledger patches. The composite primary\n // key (migration_table, patch_key) scopes a patch to the configured\n // migration ledger and makes patch claiming concurrency-safe even\n // when one database hosts multiple Proper ledgers.\n const patchTable = resolvePatchTable(this.config);\n const createPatchTableSql = this.config.database === 'sqlite'\n ? `CREATE TABLE IF NOT EXISTS ${patchTable} (\n migration_table TEXT NOT NULL,\n patch_key TEXT NOT NULL,\n checksum TEXT NOT NULL,\n format_version INTEGER NOT NULL,\n description TEXT NOT NULL,\n applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (migration_table, patch_key)\n )`\n : this.config.database === 'pg'\n ? `CREATE TABLE IF NOT EXISTS ${patchTable} (\n migration_table TEXT NOT NULL,\n patch_key TEXT NOT NULL,\n checksum TEXT NOT NULL,\n format_version INTEGER NOT NULL,\n description TEXT NOT NULL,\n applied_at TIMESTAMPTZ NOT NULL DEFAULT now(),\n PRIMARY KEY (migration_table, patch_key)\n )`\n : `CREATE TABLE IF NOT EXISTS ${patchTable} (\n migration_table VARCHAR(255) NOT NULL,\n patch_key VARCHAR(255) NOT NULL,\n checksum CHAR(64) NOT NULL,\n format_version INT NOT NULL,\n description TEXT NOT NULL,\n applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (migration_table, patch_key)\n )`;\n\n await this.sqlrunner.query(createPatchTableSql);\n }\n\n async teardown() {\n await this.sqlrunner.execute(`DROP TABLE ${this.config.migration_table}`);\n await this.sqlrunner.execute(`DROP TABLE IF EXISTS ${resolvePatchTable(this.config)}`);\n }\n}\n\n\n\n\n","import path from \"path\";\nimport { MigrationConfig } from \"./MigrationConfig\";\n\nexport const PATCH_FORMAT_VERSION = 1;\nexport const DEFAULT_PATCH_TABLE = \"proper_patches\";\n\n/** Filename contract: 13-digit stamp, underscore, normalized name, .yaml */\nexport const PATCH_FILENAME_REGEX = /^(?<stamp>[0-9]{13})_(?<name>[a-z0-9][a-z0-9_-]{0,119})\\.yaml$/;\n\nexport type PatchOperation =\n | { verb: 'rename_migration'; from: string; to: string }\n | { verb: 'mark_applied'; key: string }\n | { verb: 'unmark_applied'; key: string };\n\n/** A parsed and schema-validated patch file. */\nexport interface PatchDocument {\n /** Filename without `.yaml`. */\n patchKey: string;\n /** Basename including `.yaml`. */\n fileName: string;\n /** Absolute or config-relative resolved path. */\n filePath: string;\n /** SHA-256 hex over the exact UTF-8 file bytes. */\n checksum: string;\n version: number;\n description: string;\n operations: PatchOperation[];\n}\n\nexport interface PatchOperationResult {\n verb: PatchOperation['verb'];\n /** True when the operation mutated the ledger; false for a conditional no-op. */\n changed: boolean;\n}\n\nexport interface PatchApplyResult {\n patchKey: string;\n fileName: string;\n /**\n * applied - this process committed the patch\n * already_applied - a matching patch-history row already existed\n */\n status: 'applied' | 'already_applied';\n operations: PatchOperationResult[];\n}\n\n/** Resolved patch settings with defaults applied. */\nexport function resolvePatchFolder(config: MigrationConfig): string {\n if (config.patch_folder) return config.patch_folder;\n const dir = path.dirname(config.migration_folder);\n return dir === '.' && !config.migration_folder.includes(path.sep) && !config.migration_folder.includes('/')\n ? 'patches'\n : path.join(dir, 'patches');\n}\n\nexport function resolvePatchTable(config: MigrationConfig): string {\n return config.patch_table || DEFAULT_PATCH_TABLE;\n}\n","import { MigrationNode } from \"./MigrationNode\";\n\n\n\n\nexport async function migration_filter(migrations:MigrationNode[],completed:boolean=true,keep:MigrationNode[]=[]){\n if(migrations.length === 0){\n return keep\n }\n\n const [first,...rest] = migrations\n\n const status = await first.status()\n\n if(status.completed == completed){\n keep.push(first)\n }\n\n return migration_filter(rest,completed,keep)\n}","export function MySqlDialectParser(sql: string): string {\n const lines = sql.split('\\n');\n let result = '';\n \n // We start \"in MySQL\" so that lines before [sql] are kept.\n let isInMySQLBlock = true;\n \n // e.g. `-- [sql]`, `-- [ sql ]`, `-- [mysql]`, ignoring case/spaces\n const startSQLRegex = /^\\s*--\\s*\\[\\s*(sql|mysql)\\s*\\]\\s*$/i;\n // e.g. `-- [sqlite]`, `-- [ pg ]`, `-- [mydialect]` (any bracket means \"turn off MySQL\")\n const anyDialectRegex = /^\\s*--\\s*\\[\\s*\\w+\\s*\\]\\s*$/i;\n \n for (const line of lines) {\n const trimmed = line.trim();\n \n // If line is \" -- [sql] \" or \" -- [mysql] \", we *turn on* MySQL capturing:\n if (startSQLRegex.test(trimmed)) {\n isInMySQLBlock = true;\n // We also include this line in output\n result += line + '\\n';\n continue;\n }\n \n // If line is *some other* bracket, e.g. \" -- [sqlite] \"\n // then switch MySQL off, and do NOT keep that line\n if (anyDialectRegex.test(trimmed) && !startSQLRegex.test(trimmed)) {\n isInMySQLBlock = false;\n // Skip to next line\n continue;\n }\n \n // If we get here and see a line without a [dialect] marker,\n // and we were previously turned off because of non-mysql dialect,\n // then check if it's common SQL (like CREATE INDEX).\n // Turn MySQL back on for this line\n if (!isInMySQLBlock && line.toLowerCase().includes('create index')) {\n isInMySQLBlock = true;\n }\n \n // If we're in MySQL mode, keep the line\n if (isInMySQLBlock) {\n result += line + '\\n';\n }\n }\n \n return result;\n}\n\n/**\n * Generic inline-marker parser. Lines before any `-- [dialect]` marker are\n * kept; a marker matching one of `names` turns capturing on (and the marker\n * line is kept), any other `-- [x]` marker turns it off (marker dropped).\n * `CREATE INDEX` lines are treated as common SQL and re-enable capturing.\n */\nfunction markerDialectParser(names: string[]): (sql: string) => string {\n const startRegex = new RegExp(`^\\\\s*--\\\\s*\\\\[\\\\s*(${names.join('|')})\\\\s*\\\\]\\\\s*$`, 'i');\n const anyDialectRegex = /^\\s*--\\s*\\[\\s*\\w+\\s*\\]\\s*$/i;\n\n return function (sql: string): string {\n const lines = sql.split('\\n');\n let result = '';\n let capturing = true;\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n if (startRegex.test(trimmed)) {\n capturing = true;\n result += line + '\\n';\n continue;\n } else if (anyDialectRegex.test(trimmed)) {\n capturing = false;\n continue;\n }\n\n if (!capturing && line.toLowerCase().includes('create index')) {\n capturing = true;\n }\n\n if (capturing) {\n result += line + '\\n';\n }\n }\n\n return result;\n };\n}\n\n/** `-- [sqlite]` blocks. */\nexport const SqliteDialectParser = markerDialectParser(['sqlite']);\n\n/** `-- [pg]` / `-- [postgres]` / `-- [postgresql]` blocks. */\nexport const PgDialectParser = markerDialectParser(['pg', 'postgres', 'postgresql']);","import crypto from \"crypto\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { PatchValidationError } from \"./errors\";\nimport { parsePatchContent } from \"./PatchValidator\";\nimport { PatchDocument, PATCH_FILENAME_REGEX } from \"./PatchTypes\";\n\n/**\n * Discovers, checksums, parses, and validates every patch file in the patch\n * folder. Discovery rules:\n * - only top-level regular files ending in `.yaml` are patch files;\n * - `.yml`, nested files, and symlinks are not loaded;\n * - non-`.yaml` files are ignored;\n * - a `.yaml` file with an invalid filename or invalid contents is a hard error;\n * - a missing folder is empty discovery (never created here).\n *\n * All files are parsed and validated before any patch is applied, so a\n * malformed later file cannot be discovered only after earlier patches\n * mutate the ledger.\n */\nexport class PatchDirectoryReader {\n constructor(private directory: string) {}\n\n loadPatches(): PatchDocument[] {\n if (!fs.existsSync(this.directory)) return [];\n\n const entries = fs.readdirSync(this.directory, { withFileTypes: true });\n const patchFiles: string[] = [];\n\n for (const entry of entries) {\n if (!entry.name.endsWith('.yaml')) continue;\n // Regular files only: symlinks and directories are not loaded.\n if (!entry.isFile() || entry.isSymbolicLink()) {\n if (entry.isSymbolicLink()) {\n throw new PatchValidationError(`patch file must be a regular file, not a symlink`, entry.name);\n }\n continue;\n }\n patchFiles.push(entry.name);\n }\n\n // Ascending numeric stamp, then full basename as the tie-breaker.\n patchFiles.sort((a, b) => {\n const stampA = parseInt(a.slice(0, 13), 10);\n const stampB = parseInt(b.slice(0, 13), 10);\n if (!Number.isNaN(stampA) && !Number.isNaN(stampB) && stampA !== stampB) {\n return stampA - stampB;\n }\n return a < b ? -1 : a > b ? 1 : 0;\n });\n\n return patchFiles.map(fileName => {\n const match = PATCH_FILENAME_REGEX.exec(fileName);\n if (!match) {\n throw new PatchValidationError(\n `invalid patch filename (expected <13-digit-stamp>_<name>.yaml with name matching [a-z0-9][a-z0-9_-]{0,119})`,\n fileName\n );\n }\n const patchKey = fileName.slice(0, -'.yaml'.length);\n const filePath = path.join(this.directory, fileName);\n const bytes = fs.readFileSync(filePath);\n const checksum = crypto.createHash('sha256').update(bytes).digest('hex');\n const content = bytes.toString('utf8');\n const { version, description, operations } = parsePatchContent(content, fileName, patchKey);\n\n return { patchKey, fileName, filePath, checksum, version, description, operations };\n });\n }\n}\n","import Ajv from \"ajv\";\nimport { Document, parseDocument } from \"yaml\";\nimport { PatchValidationError } from \"./errors\";\nimport { canonicalMigrationKey, MigrationManifestEntry } from \"./MigrationManifest\";\nimport { PatchDocument, PatchOperation, PATCH_FORMAT_VERSION } from \"./PatchTypes\";\n\nconst MAX_DESCRIPTION_LENGTH = 500;\nconst MAX_MIGRATION_KEY_LENGTH = 255;\n\nconst migrationKeySchema = {\n type: \"string\",\n minLength: 1,\n maxLength: MAX_MIGRATION_KEY_LENGTH,\n};\n\nconst patchSchema = {\n type: \"object\",\n additionalProperties: false,\n required: [\"version\", \"description\", \"operations\"],\n properties: {\n version: { type: \"integer\" },\n description: { type: \"string\" },\n operations: {\n type: \"array\",\n minItems: 1,\n items: {\n type: \"object\",\n additionalProperties: false,\n minProperties: 1,\n maxProperties: 1,\n properties: {\n rename_migration: {\n type: \"object\",\n additionalProperties: false,\n required: [\"from\", \"to\"],\n properties: { from: migrationKeySchema, to: migrationKeySchema },\n },\n mark_applied: {\n type: \"object\",\n additionalProperties: false,\n required: [\"key\"],\n properties: { key: migrationKeySchema },\n },\n unmark_applied: {\n type: \"object\",\n additionalProperties: false,\n required: [\"key\"],\n properties: { key: migrationKeySchema },\n },\n },\n },\n },\n },\n};\n\nconst ajv = new Ajv({ allErrors: true, strict: true });\nconst validateSchema = ajv.compile(patchSchema);\n\nfunction fail(message: string, file: string, patchKey?: string): never {\n throw new PatchValidationError(message, file, patchKey);\n}\n\n/** Rejects keys with path separators, NUL/control chars, or surrounding whitespace. */\nfunction checkMigrationKey(value: string, context: string, file: string, patchKey: string): string {\n if (value !== value.trim()) fail(`${context}: migration key has leading/trailing whitespace`, file, patchKey);\n if (/[/\\\\]/.test(value)) fail(`${context}: migration key contains a path separator`, file, patchKey);\n // eslint-disable-next-line no-control-regex\n if (/[\\x00-\\x1f\\x7f]/.test(value)) fail(`${context}: migration key contains control characters`, file, patchKey);\n if (value.length === 0 || value.length > MAX_MIGRATION_KEY_LENGTH) {\n fail(`${context}: migration key length out of bounds`, file, patchKey);\n }\n return canonicalMigrationKey(value);\n}\n\n/**\n * Walks the parsed YAML CST and rejects aliases, anchors, merge keys,\n * custom tags, and non-core scalar types.\n */\nfunction assertStrictYaml(doc: Document.Parsed, file: string, patchKey: string) {\n if (doc.errors.length > 0) {\n fail(`YAML parse error: ${doc.errors[0].message}`, file, patchKey);\n }\n if (doc.warnings.length > 0) {\n fail(`YAML warning treated as error: ${doc.warnings[0].message}`, file, patchKey);\n }\n\n const visit = (node: any): void => {\n if (node == null || typeof node !== 'object') return;\n // Alias nodes\n if ('source' in node && node.constructor?.name === 'Alias') {\n fail('YAML aliases are not permitted in patch files', file, patchKey);\n }\n if (node.anchor) {\n fail('YAML anchors are not permitted in patch files', file, patchKey);\n }\n if (node.tag && !['tag:yaml.org,2002:str', 'tag:yaml.org,2002:int', 'tag:yaml.org,2002:bool',\n 'tag:yaml.org,2002:null', 'tag:yaml.org,2002:map', 'tag:yaml.org,2002:seq'].includes(node.tag)) {\n fail(`YAML tag '${node.tag}' is not permitted in patch files`, file, patchKey);\n }\n if (Array.isArray(node.items)) {\n for (const item of node.items) {\n if (item && typeof item === 'object' && 'key' in item) {\n // Pair: reject merge keys\n const keyValue = item.key?.value;\n if (keyValue === '<<') fail('YAML merge keys are not permitted in patch files', file, patchKey);\n visit(item.key);\n visit(item.value);\n } else {\n visit(item);\n }\n }\n }\n };\n visit(doc.contents);\n}\n\n/**\n * Strictly parses and validates one patch file's content. Duplicate mapping\n * keys, aliases/anchors, merge keys, custom tags, unknown fields, and unknown\n * verbs are all rejected. Returns validated operations plus metadata.\n */\nexport function parsePatchContent(\n content: string,\n fileName: string,\n patchKey: string\n): { version: number; description: string; operations: PatchOperation[] } {\n const doc = parseDocument(content, {\n uniqueKeys: true, // duplicate mapping keys become errors\n merge: false,\n schema: 'core',\n version: '1.2',\n });\n assertStrictYaml(doc, fileName, patchKey);\n\n const raw = doc.toJS({ mapAsMap: false });\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n fail('Patch document must be a YAML mapping', fileName, patchKey);\n }\n\n if (!validateSchema(raw)) {\n const detail = (validateSchema.errors ?? [])\n .map(e => `${e.instancePath || '/'} ${e.message}`)\n .join('; ');\n // Distinguish unknown version specifically for a clearer diagnostic\n const anyRaw = raw as any;\n if (typeof anyRaw.version === 'number' && anyRaw.version !== PATCH_FORMAT_VERSION) {\n fail(`Unknown patch format version: ${anyRaw.version} (supported: ${PATCH_FORMAT_VERSION})`, fileName, patchKey);\n }\n fail(`Schema validation failed: ${detail}`, fileName, patchKey);\n }\n\n const parsed = raw as { version: number; description: string; operations: Record<string, any>[] };\n\n if (parsed.version !== PATCH_FORMAT_VERSION) {\n fail(`Unknown patch format version: ${parsed.version} (supported: ${PATCH_FORMAT_VERSION})`, fileName, patchKey);\n }\n\n const description = parsed.description.trim();\n if (description.length === 0) fail('description must be non-empty', fileName, patchKey);\n if (description.length > MAX_DESCRIPTION_LENGTH) {\n fail(`description exceeds ${MAX_DESCRIPTION_LENGTH} characters`, fileName, patchKey);\n }\n\n const operations: PatchOperation[] = parsed.operations.map((op, index) => {\n const verbs = Object.keys(op);\n const verb = verbs[0];\n const context = `operation ${index} (${verb})`;\n switch (verb) {\n case 'rename_migration': {\n const from = checkMigrationKey(op.rename_migration.from, context, fileName, patchKey);\n const to = checkMigrationKey(op.rename_migration.to, context, fileName, patchKey);\n if (from === to) {\n fail(`${context}: 'from' and 'to' are identical after canonicalization ('${from}')`, fileName, patchKey);\n }\n return { verb: 'rename_migration', from, to };\n }\n case 'mark_applied':\n return { verb: 'mark_applied', key: checkMigrationKey(op.mark_applied.key, context, fileName, patchKey) };\n case 'unmark_applied':\n return { verb: 'unmark_applied', key: checkMigrationKey(op.unmark_applied.key, context, fileName, patchKey) };\n default:\n fail(`operation ${index}: unknown verb '${verb}'`, fileName, patchKey);\n }\n });\n\n return { version: parsed.version, description, operations };\n}\n\n/**\n * Validates the ordered rename plan of ALL patches (file order, then\n * operation order) against the current migration manifest.\n *\n * - Every historical key absent from the manifest must finish at a key\n * present in the manifest.\n * - Every key present in the manifest must finish at itself.\n * - Convergence and corrective chains (A->B->C, A->B->A) are allowed.\n *\n * mark_applied keys must exist in the manifest; unmark_applied keys may be\n * absent historical keys.\n */\nexport function validatePatchPlan(\n patches: PatchDocument[],\n manifest: Map<string, MigrationManifestEntry>\n): void {\n const renames: { from: string; to: string; file: string }[] = [];\n for (const patch of patches) {\n patch.operations.forEach((op, index) => {\n if (op.verb === 'rename_migration') {\n renames.push({ from: op.from, to: op.to, file: patch.fileName });\n } else if (op.verb === 'mark_applied') {\n if (!manifest.has(op.key)) {\n throw new PatchValidationError(\n `operation ${index} (mark_applied): key '${op.key}' is not present in the current migration manifest`,\n patch.fileName,\n patch.patchKey\n );\n }\n }\n });\n }\n\n if (renames.length === 0) return;\n\n // All keys mentioned by any rename\n const mentioned = new Set<string>();\n renames.forEach(r => { mentioned.add(r.from); mentioned.add(r.to); });\n\n const finalKey = (start: string): string => {\n let current = start;\n for (const r of renames) {\n if (current === r.from) current = r.to;\n }\n return current;\n };\n\n for (const key of mentioned) {\n const finish = finalKey(key);\n if (manifest.has(key)) {\n if (finish !== key) {\n throw new PatchValidationError(\n `rename plan moves current migration '${key}' to '${finish}', which would make its file incorrectly pending`\n );\n }\n } else {\n if (!manifest.has(finish)) {\n throw new PatchValidationError(\n `rename plan leaves historical key '${key}' at '${finish}', which is not present in the current migration manifest`\n );\n }\n }\n }\n}\n","import { MigrationConfig } from \"./MigrationConfig\";\nimport { ISQLRunner } from \"./SQLRunner\";\nimport { PatchDirectoryReader } from \"./PatchDirectoryReader\";\nimport { validatePatchPlan } from \"./PatchValidator\";\nimport { Dialect, loadMigrationManifest, MigrationManifestEntry } from \"./MigrationManifest\";\nimport {\n PatchApplyResult,\n PatchDocument,\n PatchOperation,\n PatchOperationResult,\n resolvePatchFolder,\n resolvePatchTable,\n} from \"./PatchTypes\";\nimport {\n PatchConflictError,\n PatchExecutionError,\n PatchIntegrityError,\n} from \"./errors\";\n\nfunction toError(error: unknown): Error {\n if (error instanceof Error) return error;\n return new Error(String(error));\n}\n\ninterface PatchHistoryRow {\n patch_key: string;\n checksum: string;\n}\n\n/**\n * Extracts the rows array from an ISQLRunner.query() result.\n *\n * BaseSQLRunner normally returns `[rows, extra]`, but a raw rows array of\n * exactly two elements escapes unwrapped (tuple ambiguity in\n * BaseSQLRunner.query). This helper handles both shapes.\n */\nfunction extractRows(result: any): any[] {\n if (!Array.isArray(result)) return [];\n if (Array.isArray(result[0])) return result[0]; // [rows, extra]\n if (result.length === 2\n && result[0] && typeof result[0] === 'object'\n && result[1] && typeof result[1] === 'object'\n && !('rows' in result[1])) {\n return result; // unwrapped 2-row array\n }\n if (result[0] == null) return [];\n return [result[0]];\n}\n\n/**\n * Applies pending ledger patches. Uses ISQLRunner directly (never the public\n * runner methods) so it can run inside the runner's preflight without\n * recursion.\n *\n * Precondition: the provided connection must not already be inside an\n * application-managed transaction when preflight begins; Proper will issue\n * its own BEGIN/COMMIT/ROLLBACK per patch and must not commit or roll back a\n * caller's outer transaction.\n */\nexport class PatchRunner {\n private patchTable: string;\n private migrationTable: string;\n private dialect: Dialect;\n\n constructor(private sqlrunner: ISQLRunner, private config: MigrationConfig) {\n this.patchTable = resolvePatchTable(config);\n this.migrationTable = config.migration_table;\n this.dialect = config.database as Dialect;\n }\n\n /**\n * Discovers, validates, and applies every unapplied patch in order.\n * Each unapplied patch is its own transaction; earlier committed patches\n * remain committed if a later patch fails.\n */\n async applyPending(): Promise<PatchApplyResult[]> {\n const reader = new PatchDirectoryReader(resolvePatchFolder(this.config));\n // Parse and validate ALL files before touching the database.\n const patches = reader.loadPatches();\n\n const history = await this.loadHistory();\n\n if (patches.length === 0 && history.length === 0) {\n return [];\n }\n\n // Applied rows must have a matching, unmodified file.\n const byKey = new Map(patches.map(p => [p.patchKey, p]));\n for (const row of history) {\n const file = byKey.get(row.patch_key);\n if (!file) {\n throw new PatchIntegrityError(\n `applied patch '${row.patch_key}' has no corresponding file in the patch folder; patch files are permanent and must never be renamed or deleted`,\n undefined,\n row.patch_key\n );\n }\n if (file.checksum !== row.checksum) {\n throw new PatchIntegrityError(\n `applied patch '${row.patch_key}' content changed after application; patch files are immutable once recorded`,\n file.fileName,\n row.patch_key,\n row.checksum,\n file.checksum\n );\n }\n }\n\n // Validate rename convergence against the current migration manifest.\n const manifest = loadMigrationManifest(this.config.migration_folder, this.dialect);\n validatePatchPlan(patches, manifest);\n\n const appliedKeys = new Set(history.map(r => r.patch_key));\n const results: PatchApplyResult[] = [];\n\n for (const patch of patches) {\n if (appliedKeys.has(patch.patchKey)) {\n results.push({\n patchKey: patch.patchKey,\n fileName: patch.fileName,\n status: 'already_applied',\n operations: [],\n });\n continue;\n }\n results.push(await this.applyOne(patch, manifest));\n }\n\n return results;\n }\n\n private async loadHistory(): Promise<PatchHistoryRow[]> {\n try {\n const result = await this.sqlrunner.query(\n `SELECT patch_key, checksum FROM ${this.patchTable} WHERE migration_table = ?`,\n [this.migrationTable]\n );\n return extractRows(result) as PatchHistoryRow[];\n } catch (error) {\n throw new PatchExecutionError(\n `failed to read patch history from '${this.patchTable}'`,\n undefined, undefined, undefined, undefined,\n toError(error)\n );\n }\n }\n\n private beginSql(): string {\n switch (this.dialect) {\n case 'sqlite': return 'BEGIN IMMEDIATE';\n case 'pg': return 'BEGIN';\n default: return 'START TRANSACTION';\n }\n }\n\n private async begin(patch: PatchDocument): Promise<void> {\n // SQLite BEGIN IMMEDIATE can fail with SQLITE_BUSY while a sibling\n // holds the write lock; retry briefly so a concurrent patch race\n // resolves instead of erroring instantly.\n const deadline = Date.now() + 10_000;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n try {\n await this.sqlrunner.execute(this.beginSql());\n return;\n } catch (error) {\n const message = toError(error).message;\n if (/SQLITE_BUSY|database is locked/i.test(message) && Date.now() < deadline) {\n await new Promise(resolve => setTimeout(resolve, 50));\n continue;\n }\n throw new PatchExecutionError(\n 'failed to start patch transaction',\n patch.fileName, patch.patchKey, undefined, undefined,\n toError(error)\n );\n }\n }\n }\n\n private async rollbackQuietly(): Promise<void> {\n try {\n await this.sqlrunner.execute('ROLLBACK');\n } catch {\n // The transaction may already be gone; nothing more to do.\n }\n }\n\n private async applyOne(\n patch: PatchDocument,\n manifest: Map<string, MigrationManifestEntry>\n ): Promise<PatchApplyResult> {\n await this.begin(patch);\n\n // Atomically claim (migration_table, patch_key) under the composite\n // primary key. If a sibling already committed the same key, the\n // insert fails and we resolve the race below.\n try {\n await this.sqlrunner.execute(\n `INSERT INTO ${this.patchTable} (migration_table, patch_key, checksum, format_version, description)\n VALUES (?, ?, ?, ?, ?)`,\n [this.migrationTable, patch.patchKey, patch.checksum, patch.version, patch.description]\n );\n } catch (claimError) {\n await this.rollbackQuietly();\n const committed = await this.findCommittedRow(patch.patchKey);\n if (committed) {\n if (committed.checksum === patch.checksum) {\n return {\n patchKey: patch.patchKey,\n fileName: patch.fileName,\n status: 'already_applied',\n operations: [],\n };\n }\n throw new PatchIntegrityError(\n `patch '${patch.patchKey}' was applied elsewhere with a different checksum`,\n patch.fileName, patch.patchKey,\n committed.checksum, patch.checksum\n );\n }\n throw new PatchExecutionError(\n 'failed to claim patch-history row',\n patch.fileName, patch.patchKey, undefined, undefined,\n toError(claimError)\n );\n }\n\n const operationResults: PatchOperationResult[] = [];\n try {\n for (let index = 0; index < patch.operations.length; index++) {\n operationResults.push(\n await this.applyOperation(patch, patch.operations[index], index, manifest)\n );\n }\n await this.sqlrunner.execute('COMMIT');\n } catch (error) {\n await this.rollbackQuietly();\n if (error instanceof PatchConflictError || error instanceof PatchExecutionError || error instanceof PatchIntegrityError) {\n throw error;\n }\n throw new PatchExecutionError(\n 'patch application failed',\n patch.fileName, patch.patchKey, undefined, undefined,\n toError(error)\n );\n }\n\n return {\n patchKey: patch.patchKey,\n fileName: patch.fileName,\n status: 'applied',\n operations: operationResults,\n };\n }\n\n private async findCommittedRow(patchKey: string): Promise<PatchHistoryRow | null> {\n const result = await this.sqlrunner.query(\n `SELECT patch_key, checksum FROM ${this.patchTable} WHERE migration_table = ? AND patch_key = ?`,\n [this.migrationTable, patchKey]\n );\n const list = extractRows(result) as PatchHistoryRow[];\n return list.length > 0 ? list[0] : null;\n }\n\n private async countRows(key: string): Promise<number> {\n // COUNT(*) always yields exactly one row, which sidesteps the\n // BaseSQLRunner tuple ambiguity for multi-row results.\n const result = await this.sqlrunner.query(\n `SELECT COUNT(*) AS row_count FROM ${this.migrationTable} WHERE migration_key = ?`,\n [key]\n );\n const rows = extractRows(result);\n const value = rows[0]?.row_count ?? Object.values(rows[0] ?? {})[0];\n return Number(value ?? 0);\n }\n\n private conflict(\n patch: PatchDocument,\n index: number,\n verb: string,\n message: string,\n keys: string[],\n counts: Record<string, number>\n ): never {\n throw new PatchConflictError(\n `operation ${index} (${verb}): ${message}`,\n patch.fileName, patch.patchKey, index, verb, keys, counts\n );\n }\n\n private async applyOperation(\n patch: PatchDocument,\n op: PatchOperation,\n index: number,\n manifest: Map<string, MigrationManifestEntry>\n ): Promise<PatchOperationResult> {\n try {\n switch (op.verb) {\n case 'rename_migration': {\n const fromCount = await this.countRows(op.from);\n const toCount = await this.countRows(op.to);\n const counts = { [op.from]: fromCount, [op.to]: toCount };\n\n if (fromCount > 1 || toCount > 1) {\n this.conflict(patch, index, op.verb,\n `ledger corruption: duplicate rows for a migration key`,\n [op.from, op.to], counts);\n }\n if (fromCount === 1 && toCount === 1) {\n this.conflict(patch, index, op.verb,\n `both '${op.from}' and '${op.to}' exist in the ledger`,\n [op.from, op.to], counts);\n }\n if (fromCount === 0) {\n // 0/0 no-op, or 0/1 already converged.\n return { verb: op.verb, changed: false };\n }\n // 1/0: update the row, preserving created_at and other\n // metadata. When `to` exists in the manifest, update the\n // up/down paths to what a fresh application would record.\n const target = manifest.get(op.to);\n if (target) {\n await this.sqlrunner.execute(\n `UPDATE ${this.migrationTable} SET migration_key = ?, up = ?, down = ? WHERE migration_key = ?`,\n [op.to, target.upFile ?? '', target.downFile ?? '', op.from]\n );\n } else {\n await this.sqlrunner.execute(\n `UPDATE ${this.migrationTable} SET migration_key = ? WHERE migration_key = ?`,\n [op.to, op.from]\n );\n }\n return { verb: op.verb, changed: true };\n }\n\n case 'mark_applied': {\n const count = await this.countRows(op.key);\n if (count > 1) {\n this.conflict(patch, index, op.verb,\n `ledger corruption: duplicate rows for '${op.key}'`,\n [op.key], { [op.key]: count });\n }\n if (count === 1) {\n return { verb: op.verb, changed: false };\n }\n const entry = manifest.get(op.key);\n await this.sqlrunner.execute(\n `INSERT INTO ${this.migrationTable} (migration_key, up, down) VALUES (?, ?, ?)`,\n [op.key, entry?.upFile ?? '', entry?.downFile ?? '']\n );\n return { verb: op.verb, changed: true };\n }\n\n case 'unmark_applied': {\n const count = await this.countRows(op.key);\n if (count > 1) {\n this.conflict(patch, index, op.verb,\n `ledger corruption: duplicate rows for '${op.key}'`,\n [op.key], { [op.key]: count });\n }\n if (count === 0) {\n return { verb: op.verb, changed: false };\n }\n await this.sqlrunner.execute(\n `DELETE FROM ${this.migrationTable} WHERE migration_key = ?`,\n [op.key]\n );\n return { verb: op.verb, changed: true };\n }\n }\n } catch (error) {\n if (error instanceof PatchConflictError) throw error;\n throw new PatchExecutionError(\n `operation failed`,\n patch.fileName, patch.patchKey, index, op.verb,\n toError(error)\n );\n }\n }\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport { CLIError } from \"./errors\";\n\nconst MAX_NAME_LENGTH = 120;\n\nconst SCAFFOLD = `version: 1\ndescription: TODO\noperations: []\n`;\n\n/**\n * Scaffolds a new patch file. Never connects to a database.\n */\nexport class PatchCreator {\n constructor(private patchFolder: string) {}\n\n /**\n * Normalizes a patch name: trim, whitespace runs -> `_`, lowercase.\n * Rejects empty results, path separators, `..`, control characters,\n * characters outside [a-z0-9_-], and names longer than 120 characters.\n */\n static normalizeName(name: string): string {\n const normalized = (name ?? '')\n .trim()\n .replace(/\\s+/g, '_')\n .toLowerCase();\n\n if (normalized.length === 0) {\n throw new CLIError('Patch name is required');\n }\n if (normalized.includes('/') || normalized.includes('\\\\')) {\n throw new CLIError('Patch name must not contain path separators');\n }\n if (normalized.includes('..')) {\n throw new CLIError(\"Patch name must not contain '..'\");\n }\n // eslint-disable-next-line no-control-regex\n if (/[\\x00-\\x1f\\x7f]/.test(normalized)) {\n throw new CLIError('Patch name must not contain control characters');\n }\n if (!/^[a-z0-9_-]+$/.test(normalized)) {\n throw new CLIError('Patch name may only contain characters [a-z0-9_-]');\n }\n if (normalized.length > MAX_NAME_LENGTH) {\n throw new CLIError(`Patch name exceeds ${MAX_NAME_LENGTH} characters after normalization`);\n }\n return normalized;\n }\n\n /**\n * Creates `<patch_folder>/<stamp>_<normalized_name>.yaml` with exclusive\n * file creation. On a millisecond-stamp collision, mints a later stamp\n * and retries. Returns the created path.\n */\n create(name: string): string {\n const normalized = PatchCreator.normalizeName(name);\n\n if (!fs.existsSync(this.patchFolder)) {\n fs.mkdirSync(this.patchFolder, { recursive: true });\n }\n\n let stamp = Date.now();\n // Bounded retry: collisions can only occur per-millisecond.\n for (let attempt = 0; attempt < 1000; attempt++) {\n const filePath = path.join(this.patchFolder, `${stamp}_${normalized}.yaml`);\n try {\n // 'wx': exclusive creation; never overwrites an existing file.\n fs.writeFileSync(filePath, SCAFFOLD, { flag: 'wx' });\n return filePath;\n } catch (error: any) {\n if (error && error.code === 'EEXIST') {\n stamp += 1; // mint a later stamp and retry\n continue;\n }\n throw error;\n }\n }\n throw new CLIError('Unable to create patch file: too many filename collisions');\n }\n}\n","\nimport type * as sqlite from 'sqlite';\nimport type { Statement } from 'sqlite3';\nimport type mysql from 'mysql2/promise';\n\n\n\ntype QueryResult = {\n stmt: Statement;\n lastID: number;\n changes: number;\n}\n\nexport interface ISQLRunner {\n query(sql: string, params?: any[]): Promise<any>;\n execute(sql: string, params?: any[]): Promise<any>;\n end(): Promise<void>;\n}\n\n/**\n * Base class that implements the common contract and helper utilities that are\n * shared between the different dialect runners. The concrete subclasses only\n * need to implement the three primitive methods `_query`, `_execute` and\n * `_end` that perform the actual driver-specific interaction. Everything else\n * – such as ensuring a uniform return shape – is handled here once.\n */\nexport abstract class BaseSQLRunner implements ISQLRunner {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n abstract _query(sql: string, params?: any[]): Promise<any>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n abstract _execute(sql: string, params?: any[]): Promise<any>;\n abstract _end(): Promise<void>;\n\n /**\n * Ensures that both MySQL and SQLite return the same tuple shape that callers\n * expect: `[rowsOrResult, extra]`. For SQLite there is no `extra` metadata\n * comparable to MySQL's `FieldPacket[]`, so we just use `undefined`.\n */\n async query(sql: string, params: any[] = []): Promise<any> {\n const result = await this._query(sql, params);\n\n // MySQL already returns the desired tuple. For SQLite we need to wrap.\n return Array.isArray(result) && result.length === 2 ? result : [result, undefined];\n }\n\n async execute(sql: string, params: any[] = []): Promise<any> {\n const result = await this._execute(sql, params);\n return Array.isArray(result) && result.length === 2 ? result : [result, undefined];\n }\n\n async end(): Promise<void> {\n await this._end();\n }\n}\n\nfunction isPromiseLike<T>(value: unknown): value is Promise<T> {\n return !!value && typeof (value as Promise<T>).then === \"function\";\n}\n\nexport class SQLRunner extends BaseSQLRunner {\n constructor(private connection: mysql.Connection) {\n super();\n }\n\n // The MySQL driver already returns the correct tuple shapes.\n async _query(sql: string, params: any[] = []) {\n return await this.connection.query(sql, params);\n }\n\n async _execute(sql: string, params: any[] = []) {\n return await this.connection.execute(sql, params);\n }\n\n async _end() {\n if (this.connection) {\n await this.connection.end();\n }\n }\n}\n\nexport class SQLiteRunner extends BaseSQLRunner {\n constructor(private connection: sqlite.Database | any) {\n super();\n }\n\n private async prepareStatement(sql: string) {\n if (typeof this.connection.prepare !== \"function\") {\n throw new Error(\"SQLite connection does not support prepare()\");\n }\n const stmt = this.connection.prepare(sql);\n return isPromiseLike(stmt) ? await stmt : stmt;\n }\n\n private async finalizeStatement(stmt: any) {\n if (!stmt || typeof stmt.finalize !== \"function\") return;\n const result = stmt.finalize();\n if (isPromiseLike(result)) {\n await result;\n }\n }\n\n private async statementAll(stmt: any, params: any[]) {\n if (typeof stmt.all !== \"function\") {\n throw new Error(\"SQLite statement does not support all()\");\n }\n // sqlite3 callback-style API\n if (stmt.all.length >= 2) {\n return await new Promise((resolve, reject) => {\n const callback = (err: Error | null, rows: any[]) => {\n if (err) return reject(err);\n resolve(rows || []);\n };\n try {\n if (params.length > 0) {\n stmt.all(params, callback);\n } else {\n stmt.all(callback);\n }\n } catch (error) {\n reject(error);\n }\n });\n }\n const result = stmt.all(...params);\n return isPromiseLike(result) ? await result : result;\n }\n\n private async statementRun(stmt: any, params: any[]) {\n if (typeof stmt.run !== \"function\") {\n throw new Error(\"SQLite statement does not support run()\");\n }\n if (stmt.run.length >= 2) {\n return await new Promise((resolve, reject) => {\n const callback = function (this: any, err: Error | null) {\n if (err) return reject(err);\n resolve({ changes: this?.changes ?? 0, lastID: this?.lastID });\n };\n try {\n if (params.length > 0) {\n stmt.run(params, callback);\n } else {\n stmt.run(callback);\n }\n } catch (error) {\n reject(error);\n }\n });\n }\n const result = stmt.run(...params);\n return isPromiseLike(result) ? await result : result;\n }\n\n async _query(sql: string, params: any[] = []) {\n const stmt = await this.prepareStatement(sql);\n try {\n const rows = await this.statementAll(stmt, params);\n return rows;\n } finally {\n await this.finalizeStatement(stmt);\n }\n }\n\n async _execute(sql: string, params: any[] = []) {\n // Handle empty or comment-only SQL gracefully\n if (this.isEmptySQL(sql)) {\n return { changes: 0, lastID: 0 }; // No-op result\n }\n\n if (this.isMultiStatement(sql)) {\n return await this.executeMultiStatement(sql, params)\n .catch((err) => {\n console.error((\n \"Error executing multi-statement SQL:\\n\"+\n `${sql}\\n`\n ), err);\n throw err;\n });\n }\n\n const stmt = await this.prepareStatement(sql);\n try {\n const info = await this.statementRun(stmt, params);\n return info;\n } finally {\n await this.finalizeStatement(stmt);\n }\n }\n\n /**\n * Checks if SQL is empty or contains only comments/whitespace.\n * Returns true if there is no actual SQL to execute.\n */\n private isEmptySQL(sql: string): boolean {\n // Remove all comments and whitespace\n const withoutComments = sql\n .replace(/--.*$/gm, '') // Remove single-line comments\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '') // Remove multi-line comments\n .trim();\n return withoutComments.length === 0;\n }\n\n private isMultiStatement(sql: string): boolean {\n // SQLite does not support multiple statements in a single query.\n return sql.split(';').length > 1;\n }\n\n private async executeMultiStatement(sql: string, params: any[] = []) {\n const statements = sql.split(';')\n .map((s) => s.split('\\n')\n .map(\n s=>this.removeComments(s))\n .filter(s=>s.trim()!='')\n .join('\\n')\n )\n .filter((s) => s.trim() !== '');\n \n const infos = await statements.reduce(async (prev,statement) => {\n const infos = await prev;\n const stmt = await this.prepareStatement(`${statement};`);\n try {\n const info = await this.statementRun(stmt, params);\n infos.push(info);\n return infos;\n } finally {\n await this.finalizeStatement(stmt);\n }\n },Promise.resolve([null] as any[]))\n .then((infos:QueryResult[]) => {\n return infos.filter((info) => info !== null);\n })\n return infos.reduce((acc,latest)=>{\n if(latest){\n acc.stmt = latest.stmt;\n acc.lastID = latest.lastID;\n acc.changes += latest.changes;\n }\n return acc\n })\n }\n\n private removeComments(sql: string): string {\n // Remove single-line comments\n sql = sql.replace(/--.*$/gm, '');\n return sql;\n }\n\n\n async _end() {\n if (this.connection) {\n await this.connection.close();\n }\n }\n}\n\n/**\n * Minimal structural type for a `pg` Client or Pool (or anything shaped like\n * one, e.g. a Hyperdrive/Neon client). We only rely on `query()` and `end()`.\n */\nexport interface PgQueryable {\n query(text: string, values?: any[]): Promise<{ rows: any[]; rowCount: number | null }>;\n end?(): Promise<void>;\n}\n\n/**\n * PostgreSQL runner.\n *\n * Proper's internal bookkeeping statements use MySQL-style `?` placeholders;\n * Postgres wants `$1..$n`, so parameterised statements are rewritten here.\n * Migration files themselves are executed verbatim with no parameters — a\n * parameter-less `query()` goes through the simple protocol, which allows\n * multiple `;`-separated statements in one call, so no client-side splitting\n * (as SQLite needs) is required.\n */\nexport class PgRunner extends BaseSQLRunner {\n constructor(private connection: PgQueryable) {\n super();\n }\n\n /** `?` -> `$1`, `$2`, ... outside of string literals / comments. */\n static toPositional(sql: string): string {\n let out = '';\n let n = 0;\n let inSingle = false;\n let inDouble = false;\n let inLineComment = false;\n let inBlockComment = false;\n for (let i = 0; i < sql.length; i++) {\n const ch = sql[i];\n const next = sql[i + 1];\n if (inLineComment) {\n out += ch;\n if (ch === '\\n') inLineComment = false;\n continue;\n }\n if (inBlockComment) {\n out += ch;\n if (ch === '*' && next === '/') { out += next; i++; inBlockComment = false; }\n continue;\n }\n if (inSingle) {\n out += ch;\n if (ch === \"'\") inSingle = false;\n continue;\n }\n if (inDouble) {\n out += ch;\n if (ch === '\"') inDouble = false;\n continue;\n }\n if (ch === '-' && next === '-') { out += ch; inLineComment = true; continue; }\n if (ch === '/' && next === '*') { out += ch + next; i++; inBlockComment = true; continue; }\n if (ch === \"'\") { out += ch; inSingle = true; continue; }\n if (ch === '\"') { out += ch; inDouble = true; continue; }\n if (ch === '?') { out += `$${++n}`; continue; }\n out += ch;\n }\n return out;\n }\n\n private async run(sql: string, params: any[]) {\n if (params.length > 0) {\n return await this.connection.query(PgRunner.toPositional(sql), params);\n }\n return await this.connection.query(sql);\n }\n\n async _query(sql: string, params: any[] = []) {\n const result = await this.run(sql, params);\n return [result.rows, result];\n }\n\n async _execute(sql: string, params: any[] = []) {\n const result = await this.run(sql, params);\n return [{ changes: result.rowCount ?? 0, lastID: undefined }, result];\n }\n\n async _end() {\n if (this.connection && typeof this.connection.end === 'function') {\n await this.connection.end();\n }\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { pathToFileURL } from 'url';\nimport Ajv from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { tsImport } from 'tsx/esm/api';\n\nimport type { IMigrationRunner, MigrationHistory } from './MigrationRunner';\nimport { MigrationRunnerFactory, FileMigrationConfigReader, loadMigrationConfig } from './MigrationRunner';\nimport type { MigrationConfig } from './MigrationConfig';\n\nexport type SeedTransactionalMode = 'runner' | 'seed' | 'none';\n\nexport type SeedOptions = {\n migrationsDir?: string;\n dataDir?: string;\n validate?: boolean;\n transactional?: SeedTransactionalMode;\n aliasMap?: Record<string, string>;\n preloadedData?: Record<string, unknown>;\n log?: (msg: string) => void;\n names?: string[];\n};\n\nexport type ResolvedSeed = {\n kind: 'sql' | 'ts' | 'js';\n name: string;\n alias: string;\n upPath: string;\n downPath?: string;\n dataPath: string | null;\n schemaPath: string | null;\n};\n\nfunction resolveAlias(name: string, aliasMap?: Record<string, string>): string {\n if (!aliasMap) return name;\n return aliasMap[name] ?? name;\n}\n\nfunction walkForFile(rootDir: string, fileName: string): string | null {\n if (!fs.existsSync(rootDir)) return null;\n const entries = fs.readdirSync(rootDir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(rootDir, entry.name);\n if (entry.isDirectory()) {\n const found = walkForFile(full, fileName);\n if (found) return found;\n } else if (entry.isFile() && entry.name === fileName) {\n return full;\n }\n }\n return null;\n}\n\nfunction resolveMigrationsDir(migrationConfig: MigrationConfig, options: SeedOptions): string {\n const fromOptions = options.migrationsDir;\n const fromConfig = migrationConfig.seeds?.migrationsDir;\n\n const dir = fromOptions ?? fromConfig;\n if (!dir) {\n throw new Error('Seed migrationsDir not configured. Set seeds.migrationsDir in proper.json or pass it explicitly.');\n }\n return dir;\n}\n\nfunction mergeSeedConfig(\n migrationConfig: MigrationConfig,\n options: SeedOptions,\n): { names: string[]; finalOptions: SeedOptions & { migrationsDir: string; validate: boolean; transactional: SeedTransactionalMode } } {\n const names = options.names && options.names.length\n ? options.names\n : migrationConfig.seeds?.list && migrationConfig.seeds.list.length\n ? migrationConfig.seeds.list\n : [];\n\n if (!names.length) {\n throw new Error('No seed names provided and no seeds.list defined in proper config');\n }\n\n const migrationsDir = resolveMigrationsDir(migrationConfig, options);\n const dataDir = options.dataDir ?? migrationConfig.seeds?.dataDir;\n const validate = options.validate !== undefined ? options.validate : true;\n const transactional = options.transactional ?? 'none';\n\n const finalOptions: SeedOptions & { migrationsDir: string; validate: boolean; transactional: SeedTransactionalMode } = {\n ...options,\n migrationsDir,\n dataDir,\n validate,\n transactional,\n };\n\n return { names, finalOptions };\n}\n\n// export function loadMigrationConfig(configFile: string): MigrationConfig {\n// const reader = new FileMigrationConfigReader(configFile);\n// return reader.loadFile();\n// }\n\nfunction resolveSqlPair(name: string, migrationsDir: string): { upPath: string; downPath: string } | null {\n const up = walkForFile(migrationsDir, `${name}.up.sql`);\n const down = walkForFile(migrationsDir, `${name}.down.sql`);\n if (up && down) {\n return { upPath: up, downPath: down };\n }\n return null;\n}\n\nfunction resolveModule(name: string, migrationsDir: string): { kind: 'ts' | 'js'; modulePath: string } | null {\n const ts = walkForFile(migrationsDir, `${name}.ts`);\n if (ts) return { kind: 'ts', modulePath: ts };\n const js = walkForFile(migrationsDir, `${name}.js`);\n if (js) return { kind: 'js', modulePath: js };\n return null;\n}\n\nexport async function resolveSeed(\n name: string,\n migrationConfig: MigrationConfig,\n options: SeedOptions,\n): Promise<ResolvedSeed> {\n const migrationsDir = resolveMigrationsDir(migrationConfig, options);\n const alias = resolveAlias(name, options.aliasMap);\n\n const sqlPair = resolveSqlPair(name, migrationsDir);\n if (sqlPair) {\n return {\n kind: 'sql',\n name,\n alias,\n upPath: sqlPair.upPath,\n downPath: sqlPair.downPath,\n dataPath: null,\n schemaPath: null,\n };\n }\n\n const module = resolveModule(name, migrationsDir);\n if (!module) {\n throw new Error(`Seed implementation not found for \"${name}\" under ${migrationsDir}`);\n }\n\n const dataDir = options.dataDir ?? migrationConfig.seeds?.dataDir;\n let dataPath: string | null = null;\n let schemaPath: string | null = null;\n\n if (dataDir) {\n dataPath = walkForFile(dataDir, `${alias}.json`);\n schemaPath = walkForFile(dataDir, `${alias}.schema.json`);\n }\n\n return {\n kind: module.kind,\n name,\n alias,\n upPath: module.modulePath,\n downPath: module.modulePath,\n dataPath,\n schemaPath,\n };\n}\n\nasync function loadJson(filePath: string): Promise<unknown> {\n const content = await fs.promises.readFile(filePath, 'utf8');\n return JSON.parse(content);\n}\n\nfunction createValidator() {\n const ajv = new Ajv({ allErrors: true, strict: false });\n addFormats(ajv);\n return ajv;\n}\n\nasync function validateData(schemaPath: string | null, data: unknown, validate: boolean, log?: (msg: string) => void) {\n if (!validate || !schemaPath) return;\n const content = await fs.promises.readFile(schemaPath, 'utf8');\n const schema = JSON.parse(content);\n const ajv = createValidator();\n const validateFn = ajv.compile(schema);\n const ok = validateFn(data);\n if (!ok) {\n log?.(`Validation failed for seed data (${schemaPath})`);\n throw new Error(`Seed data validation failed: ${ajv.errorsText(validateFn.errors || [])}`);\n }\n}\n\nasync function runSqlSeed(\n runner: IMigrationRunner,\n resolved: ResolvedSeed,\n direction: 'up' | 'down',\n): Promise<void> {\n const sqlPath = direction === 'up' ? resolved.upPath : resolved.downPath!;\n const sql = await fs.promises.readFile(sqlPath, 'utf8');\n await runner.query(sql);\n}\n\nexport type SeedContext = {\n data: unknown;\n log?: (msg: string) => void;\n dialect: string;\n};\n\nasync function loadSeedModule(modulePath: string): Promise<any> {\n const resolved = path.resolve(modulePath);\n\n // For .ts files, use tsx's tsImport which handles TypeScript in both ESM and CJS contexts\n if (resolved.endsWith('.ts')) {\n const fileUrl = pathToFileURL(resolved).href;\n return tsImport(fileUrl, fileUrl);\n }\n\n // For .js files, use standard dynamic import\n return import(resolved);\n}\n\nasync function runModuleSeed(\n runner: IMigrationRunner,\n resolved: ResolvedSeed,\n migrationConfig: MigrationConfig,\n options: SeedOptions & { validate: boolean },\n direction: 'up' | 'down',\n): Promise<void> {\n const { log } = options;\n const module = await loadSeedModule(resolved.upPath);\n const handler = module[direction];\n if (typeof handler !== 'function') {\n throw new Error(`Seed module \"${resolved.name}\" does not export ${direction}()`);\n }\n\n let data: unknown = null;\n if (options.preloadedData && Object.prototype.hasOwnProperty.call(options.preloadedData, resolved.name)) {\n data = options.preloadedData[resolved.name];\n } else if (resolved.dataPath) {\n data = await loadJson(resolved.dataPath);\n }\n\n await validateData(resolved.schemaPath, data, options.validate, log);\n\n const ctx: SeedContext = {\n data,\n log,\n dialect: migrationConfig.database || 'sql',\n };\n\n await handler(runner, ctx);\n}\n\nasync function runSingleSeed(\n runner: IMigrationRunner,\n migrationConfig: MigrationConfig,\n name: string,\n options: SeedOptions & { validate: boolean; transactional: SeedTransactionalMode },\n direction: 'up' | 'down',\n): Promise<void> {\n const resolved = await resolveSeed(name, migrationConfig, options);\n\n if (resolved.kind === 'sql') {\n await runSqlSeed(runner, resolved, direction);\n } else {\n await runModuleSeed(runner, resolved, migrationConfig, options, direction);\n }\n}\n\nasync function withTransactionalMode(\n runner: IMigrationRunner,\n migrationConfig: MigrationConfig,\n names: string[],\n options: SeedOptions & { validate: boolean; transactional: SeedTransactionalMode },\n direction: 'up' | 'down',\n): Promise<void> {\n const mode = options.transactional;\n\n if (mode === 'runner') {\n await runner.query('BEGIN');\n try {\n for (const name of names) {\n await runSingleSeed(runner, migrationConfig, name, options, direction);\n }\n await runner.query('COMMIT');\n } catch (err) {\n try {\n await runner.query('ROLLBACK');\n } catch {\n }\n throw err;\n }\n return;\n }\n\n if (mode === 'seed') {\n for (const name of names) {\n await runner.query('BEGIN');\n try {\n await runSingleSeed(runner, migrationConfig, name, options, direction);\n await runner.query('COMMIT');\n } catch (err) {\n try {\n await runner.query('ROLLBACK');\n } catch {\n }\n throw err;\n }\n }\n return;\n }\n\n for (const name of names) {\n await runSingleSeed(runner, migrationConfig, name, options, direction);\n }\n}\n\nexport async function runSeedsWithRunner(\n runner: IMigrationRunner,\n migrationConfig: MigrationConfig,\n direction: 'up' | 'down',\n options: SeedOptions,\n): Promise<void> {\n const { names, finalOptions } = mergeSeedConfig(migrationConfig, options);\n await withTransactionalMode(runner, migrationConfig, names, finalOptions, direction);\n}\n\nexport type SeedFactoryOptions = SeedOptions & {\n configFile?: string;\n};\n\nexport type SeedFactory = {\n up(names?: string[]): Promise<void>;\n down(names?: string[]): Promise<void>;\n};\n\nexport function createSeedFactory(options: SeedFactoryOptions): SeedFactory {\n const configFile = options.configFile ?? 'proper.json';\n\n return {\n async up(names?: string[]) {\n const runner = await MigrationRunnerFactory.create(configFile);\n const migrationConfig = loadMigrationConfig(configFile);\n try {\n await runSeedsWithRunner(runner, migrationConfig, 'up', {\n ...options,\n names: names && names.length ? names : options.names,\n });\n } finally {\n await runner.close();\n }\n },\n\n async down(names?: string[]) {\n const runner = await MigrationRunnerFactory.create(configFile);\n const migrationConfig = loadMigrationConfig(configFile);\n try {\n await runSeedsWithRunner(runner, migrationConfig, 'down', {\n ...options,\n names: names && names.length ? names : options.names,\n });\n } finally {\n await runner.close();\n }\n },\n };\n}\n"],"mappings":"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","names":["fs","fs","fs","fs","path","fs","fs","path","fs","path","fs","path","fs","path","s","infos","toError","settings","fs","fs","path","Ajv","fs","path","ajv","Ajv"]}
|