@happyvertical/smrt-core 0.40.5 → 0.40.7
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/dist/manifest/static-manifest.js +2 -2
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest/test-manifest-stub.js +2 -2
- package/dist/manifest/test-manifest-stub.js.map +1 -1
- package/dist/manifest.json +2 -2
- package/dist/migrations/tracker.d.ts.map +1 -1
- package/dist/migrations/tracker.js +9 -7
- package/dist/migrations/tracker.js.map +1 -1
- package/dist/migrations/types.d.ts +6 -0
- package/dist/migrations/types.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +4 -4
- package/package.json +10 -10
package/dist/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "1.0.0",
|
|
3
|
-
"timestamp":
|
|
3
|
+
"timestamp": 1784269655431,
|
|
4
4
|
"packageName": "@happyvertical/smrt-core",
|
|
5
|
-
"packageVersion": "0.40.
|
|
5
|
+
"packageVersion": "0.40.7",
|
|
6
6
|
"objects": {
|
|
7
7
|
"@happyvertical/smrt-core:SmrtClass": {
|
|
8
8
|
"name": "smrtclass",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/migrations/tracker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EACV,sBAAsB,EAEtB,uBAAuB,EACvB,eAAe,EAChB,MAAM,YAAY,CAAC;AAkEpB;;;;;;;;;GASG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,OAAO,CAA+D;IAC9E,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAiB;IACjC;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB,CAA8B;IACvD,OAAO,CAAC,YAAY,CAAuB;gBAE/B,OAAO,EAAE,uBAAuB;IAa5C;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAQtB;;OAEG;IACH,SAAS,IAAI,cAAc;IAI3B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAUnB,gBAAgB;IAW9B;;OAEG;IACG,oBAAoB,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAe9D;;OAEG;IACG,oBAAoB,CACxB,WAAW,EAAE,mBAAmB,EAAE,GACjC,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAMjC;;OAEG;IACG,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWtD;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAmBvE;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAWrC;;OAEG;IACG,WAAW,CACf,WAAW,EAAE,mBAAmB,EAAE,GACjC,OAAO,CAAC,WAAW,EAAE,CAAC;IAkDzB;;OAEG;IACG,KAAK,CACT,UAAU,EAAE,mBAAmB,EAC/B,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/migrations/tracker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EACV,sBAAsB,EAEtB,uBAAuB,EACvB,eAAe,EAChB,MAAM,YAAY,CAAC;AAkEpB;;;;;;;;;GASG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,OAAO,CAA+D;IAC9E,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAiB;IACjC;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB,CAA8B;IACvD,OAAO,CAAC,YAAY,CAAuB;gBAE/B,OAAO,EAAE,uBAAuB;IAa5C;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAQtB;;OAEG;IACH,SAAS,IAAI,cAAc;IAI3B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAUnB,gBAAgB;IAW9B;;OAEG;IACG,oBAAoB,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAe9D;;OAEG;IACG,oBAAoB,CACxB,WAAW,EAAE,mBAAmB,EAAE,GACjC,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAMjC;;OAEG;IACG,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWtD;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAmBvE;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAWrC;;OAEG;IACG,WAAW,CACf,WAAW,EAAE,mBAAmB,EAAE,GACjC,OAAO,CAAC,WAAW,EAAE,CAAC;IAkDzB;;OAEG;IACG,KAAK,CACT,UAAU,EAAE,mBAAmB,EAC/B,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,eAAe,CAAC;IA6L3B;;OAEG;IACG,QAAQ,CACZ,WAAW,EAAE,mBAAmB,EAAE,EAClC,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,eAAe,EAAE,CAAC;IAsF7B;;OAEG;IACG,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,mBAAmB,EAC/B,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,eAAe,CAAC;IAiF3B;;OAEG;IACG,UAAU,CACd,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,eAAe,CAAA;KAAO,GACvE,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAiCnC;;OAEG;YACW,iBAAiB;IAW/B;;OAEG;YACW,sBAAsB;IAepC;;;;;;;;;;;OAWG;YACW,yBAAyB;CAqCxC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAAE,EACpB,oBAAoB,EAAE,OAAO,GAC5B;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAgC7C"}
|
|
@@ -197,19 +197,21 @@ var MigrationTracker = class MigrationTracker {
|
|
|
197
197
|
await this.initialize();
|
|
198
198
|
const startTime = Date.now();
|
|
199
199
|
const checksum = computeChecksum(definition.up);
|
|
200
|
+
const force = Boolean(options.force || options.forceMigrations?.includes(definition.id));
|
|
201
|
+
const hasScopedForce = Boolean(options.forceMigrations?.length);
|
|
200
202
|
const existing = await this.getMigration(definition.id);
|
|
201
203
|
if (existing) switch (existing.status) {
|
|
202
204
|
case "completed":
|
|
203
|
-
if (!
|
|
205
|
+
if (!force && existing.checksum !== checksum) return {
|
|
204
206
|
success: false,
|
|
205
207
|
applied: false,
|
|
206
208
|
skipped: false,
|
|
207
209
|
name: definition.id,
|
|
208
210
|
checksum,
|
|
209
211
|
execution_time_ms: 0,
|
|
210
|
-
error: `Migration ${definition.id} checksum mismatch. Was already applied with different checksum. Use --force to override.`
|
|
212
|
+
error: `Migration ${definition.id} checksum mismatch. Was already applied with different checksum. Use --force-migration ${definition.id} to override only this migration, or --force to override the whole batch.`
|
|
211
213
|
};
|
|
212
|
-
if (!
|
|
214
|
+
if (!force && !options.reconcile) return {
|
|
213
215
|
success: true,
|
|
214
216
|
applied: false,
|
|
215
217
|
skipped: true,
|
|
@@ -219,25 +221,25 @@ var MigrationTracker = class MigrationTracker {
|
|
|
219
221
|
};
|
|
220
222
|
break;
|
|
221
223
|
case "failed":
|
|
222
|
-
if (!
|
|
224
|
+
if (!force && (!options.reconcile || hasScopedForce)) return {
|
|
223
225
|
success: false,
|
|
224
226
|
applied: false,
|
|
225
227
|
skipped: false,
|
|
226
228
|
name: definition.id,
|
|
227
229
|
checksum,
|
|
228
230
|
execution_time_ms: 0,
|
|
229
|
-
error: `Migration ${definition.id} previously failed: ${existing.error_message || "Unknown error"}. Use --force to retry.`
|
|
231
|
+
error: `Migration ${definition.id} previously failed: ${existing.error_message || "Unknown error"}. Use --force-migration ${definition.id} to retry only this migration, or --force to retry the whole batch.`
|
|
230
232
|
};
|
|
231
233
|
break;
|
|
232
234
|
case "running":
|
|
233
|
-
if (!
|
|
235
|
+
if (!force) return {
|
|
234
236
|
success: false,
|
|
235
237
|
applied: false,
|
|
236
238
|
skipped: false,
|
|
237
239
|
name: definition.id,
|
|
238
240
|
checksum,
|
|
239
241
|
execution_time_ms: 0,
|
|
240
|
-
error: `Migration ${definition.id} is currently running or was interrupted.
|
|
242
|
+
error: `Migration ${definition.id} is currently running or was interrupted. If the previous run crashed, use --force-migration ${definition.id} to retry only this migration, or --force to retry the whole batch.`
|
|
241
243
|
};
|
|
242
244
|
break;
|
|
243
245
|
case "rolled_back": break;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracker.js","names":[],"sources":["../../src/migrations/tracker.ts"],"sourcesContent":["/**\n * Migration Tracker\n *\n * Manages migration state, tracking which migrations have been applied,\n * and providing idempotent migration application.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { hostname } from 'node:os';\nimport { createLogger } from '@happyvertical/logger';\nimport { detectEngine } from '../schema/ddl/index.js';\n// DatabaseEngine comes from the DDL layer (the json-inclusive type that\n// `detectEngine` actually returns), matching `SchemaComparer` in differ.ts.\n// The migration stack supports the JSON adapter post-R11, so the tracker's\n// engine type must include 'json' too — the narrower `migrations/types`\n// alias would reject it.\nimport type { DatabaseEngine } from '../schema/ddl/types.js';\nimport type {\n DriftReport,\n MigrationDefinition,\n MigrationResult,\n MigrationStatus,\n SchemaMigrationRecord,\n} from '../schema/types.js';\nimport { CREATE_SMRT_SCHEMA_MIGRATIONS_TABLE } from '../system/schema.js';\nimport { computeChecksum, verifyChecksum } from './checksum.js';\nimport type {\n ApplyMigrationsOptions,\n DatabaseInterface,\n MigrationTrackerOptions,\n RollbackOptions,\n} from './types.js';\n\nconst logger = createLogger({ level: 'info' });\n\n/**\n * Row type for _smrt_schema_migrations table\n */\ninterface MigrationRow {\n id: string;\n name: string;\n version: string;\n checksum: string;\n applied_checksum?: string | null;\n applied_at: string;\n execution_time_ms?: number | null;\n package_name?: string | null;\n source_file?: string | null;\n status: string;\n error_message?: string | null;\n attempts: number;\n is_reversible: number | boolean;\n rolled_back_at?: string | null;\n applied_by?: string | null;\n batch: number;\n}\n\n/**\n * Default options for MigrationTracker\n */\nconst DEFAULT_OPTIONS = {\n lockTimeout: 30000,\n statementTimeout: 60000,\n useConcurrentIndexes: true,\n};\n\nclass AtomicMigrationRollback extends Error {\n constructor(\n public readonly results: MigrationResult[],\n public readonly failed: MigrationResult,\n ) {\n super(`Atomic migration batch failed at ${failed.name}`);\n }\n}\n\nconst CONCURRENT_INDEX_STATEMENT_RE =\n /(?:(?:CREATE\\s+(?:UNIQUE\\s+)?INDEX|DROP\\s+INDEX)\\s+CONCURRENTLY|REINDEX(?:\\s*\\([^)]*\\))?\\s+(?:INDEX|TABLE|SCHEMA|DATABASE|SYSTEM)\\s+CONCURRENTLY)/i;\n\nfunction findConcurrentIndexStatement(\n definitions: MigrationDefinition[],\n): { migrationName: string; statement: string } | null {\n for (const definition of definitions) {\n const statement = definition.up.find((sql) =>\n CONCURRENT_INDEX_STATEMENT_RE.test(sql),\n );\n\n if (statement) {\n return {\n migrationName: definition.id,\n statement,\n };\n }\n }\n\n return null;\n}\n\n/**\n * MigrationTracker class\n *\n * Provides migration tracking and state management:\n * - Initializes the _smrt_schema_migrations tracking table\n * - Tracks applied migrations with checksums\n * - Provides idempotent migration application\n * - Supports rollback via DOWN scripts\n * - Handles PostgreSQL-specific concerns (CONCURRENTLY, lock timeout)\n */\nexport class MigrationTracker {\n private db: DatabaseInterface;\n private options: Required<Omit<MigrationTrackerOptions, 'db' | 'engineHint'>>;\n private engineHint?: string;\n private dbEngine: DatabaseEngine;\n /**\n * Memoized initialization promise. Storing the in-flight promise (rather\n * than a `boolean` flag set after the DDL completes) makes `initialize()`\n * safe under concurrency: multiple parallel callers all `await` the same\n * promise instead of independently re-running the DDL. On error the slot\n * is cleared so the next caller retries — a transient failure doesn't\n * permanently poison the instance.\n */\n private initializePromise: Promise<void> | null = null;\n private currentBatch: number | null = null;\n\n constructor(options: MigrationTrackerOptions) {\n this.db = options.db;\n this.options = {\n lockTimeout: options.lockTimeout ?? DEFAULT_OPTIONS.lockTimeout,\n statementTimeout:\n options.statementTimeout ?? DEFAULT_OPTIONS.statementTimeout,\n useConcurrentIndexes:\n options.useConcurrentIndexes ?? DEFAULT_OPTIONS.useConcurrentIndexes,\n };\n this.engineHint = options.engineHint;\n this.dbEngine = this.detectDbEngine();\n }\n\n /**\n * Detect the database engine. Honors an explicit `engineHint` (passed via\n * `MigrationTrackerOptions`) before falling back to URL parsing — this is\n * the same `detectEngine` contract used by `SchemaComparer` and the rest\n * of the migration stack, so the tracker stays consistent with the DDL\n * the orchestrator generated.\n */\n private detectDbEngine(): DatabaseEngine {\n const dbWithConfig = this.db as DatabaseInterface & {\n config?: { url?: string };\n };\n const url = this.db.url || dbWithConfig.config?.url || '';\n return detectEngine(url, this.engineHint);\n }\n\n /**\n * Get the current database engine\n */\n getEngine(): DatabaseEngine {\n return this.dbEngine;\n }\n\n /**\n * Initialize the migrations tracking table\n */\n async initialize(): Promise<void> {\n if (!this.initializePromise) {\n this.initializePromise = this.runInitializeDdl().catch((error) => {\n this.initializePromise = null;\n throw error;\n });\n }\n return this.initializePromise;\n }\n\n private async runInitializeDdl(): Promise<void> {\n // Parse and execute each statement in the DDL\n const statements = CREATE_SMRT_SCHEMA_MIGRATIONS_TABLE.split(';')\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n\n for (const statement of statements) {\n await this.db.query(statement);\n }\n }\n\n /**\n * Get all applied migrations ordered by applied_at\n */\n async getAppliedMigrations(): Promise<SchemaMigrationRecord[]> {\n await this.initialize();\n\n const result = await this.db.query(\n `SELECT * FROM _smrt_schema_migrations WHERE status = 'completed' ORDER BY applied_at ASC`,\n );\n\n return (result.rows as MigrationRow[]).map((row) => ({\n ...row,\n applied_at: new Date(row.applied_at),\n rolled_back_at: row.rolled_back_at ? new Date(row.rolled_back_at) : null,\n is_reversible: Boolean(row.is_reversible),\n })) as SchemaMigrationRecord[];\n }\n\n /**\n * Get pending migrations (defined but not applied)\n */\n async getPendingMigrations(\n definitions: MigrationDefinition[],\n ): Promise<MigrationDefinition[]> {\n const applied = await this.getAppliedMigrations();\n const appliedNames = new Set(applied.map((m) => m.name));\n return definitions.filter((d) => !appliedNames.has(d.id));\n }\n\n /**\n * Check if a migration has been applied\n */\n async isApplied(migrationId: string): Promise<boolean> {\n await this.initialize();\n\n const result = await this.db.query(\n `SELECT 1 FROM _smrt_schema_migrations WHERE name = ? AND status = 'completed' LIMIT 1`,\n migrationId,\n );\n\n return result.rows.length > 0;\n }\n\n /**\n * Get a single migration record by name\n */\n async getMigration(name: string): Promise<SchemaMigrationRecord | null> {\n await this.initialize();\n\n const result = await this.db.query(\n `SELECT * FROM _smrt_schema_migrations WHERE name = ? LIMIT 1`,\n name,\n );\n\n if (result.rows.length === 0) return null;\n\n const row = result.rows[0] as MigrationRow;\n return {\n ...row,\n applied_at: new Date(row.applied_at),\n rolled_back_at: row.rolled_back_at ? new Date(row.rolled_back_at) : null,\n is_reversible: Boolean(row.is_reversible),\n } as SchemaMigrationRecord;\n }\n\n /**\n * Get the next batch number\n */\n async getNextBatch(): Promise<number> {\n await this.initialize();\n\n const result = await this.db.query(\n `SELECT MAX(batch) as max_batch FROM _smrt_schema_migrations`,\n );\n\n const row = result.rows[0] as { max_batch: number | null } | undefined;\n return (row?.max_batch ?? 0) + 1;\n }\n\n /**\n * Detect drift between migration definitions and applied migrations\n */\n async detectDrift(\n definitions: MigrationDefinition[],\n ): Promise<DriftReport[]> {\n const applied = await this.getAppliedMigrations();\n const reports: DriftReport[] = [];\n\n const appliedMap = new Map(applied.map((m) => [m.name, m]));\n const definitionMap = new Map(definitions.map((d) => [d.id, d]));\n\n // Check each applied migration against definitions\n for (const record of applied) {\n const definition = definitionMap.get(record.name);\n\n if (!definition) {\n // Migration applied but definition is missing\n reports.push({\n migration_name: record.name,\n expected_checksum: 'N/A',\n actual_checksum: record.checksum,\n drift_type: 'unknown_in_db',\n recommendation:\n 'Migration exists in database but definition is missing. Manual cleanup may be required.',\n });\n continue;\n }\n\n // Check checksum\n const currentChecksum = computeChecksum(definition.up);\n const verification = verifyChecksum(\n currentChecksum,\n record.checksum,\n record.applied_checksum,\n );\n\n if (!verification.valid) {\n const driftType = verification.drift ?? 'db_modified';\n reports.push({\n migration_name: record.name,\n expected_checksum: record.checksum,\n actual_checksum: currentChecksum,\n drift_type: driftType,\n recommendation:\n driftType === 'file_modified'\n ? 'Migration file was modified after application. Create a new migration instead.'\n : 'Database schema was modified outside of migrations. Review and reconcile manually.',\n });\n }\n }\n\n return reports;\n }\n\n /**\n * Apply a single migration\n */\n async apply(\n definition: MigrationDefinition,\n options: ApplyMigrationsOptions = {},\n ): Promise<MigrationResult> {\n await this.initialize();\n const startTime = Date.now();\n const checksum = computeChecksum(definition.up);\n\n // Check if migration record already exists\n const existing = await this.getMigration(definition.id);\n\n if (existing) {\n // Handle based on existing status\n switch (existing.status) {\n case 'completed':\n if (!options.force && existing.checksum !== checksum) {\n return {\n success: false,\n applied: false,\n skipped: false,\n name: definition.id,\n checksum,\n execution_time_ms: 0,\n error: `Migration ${definition.id} checksum mismatch. Was already applied with different checksum. Use --force to override.`,\n };\n }\n\n if (!options.force && !options.reconcile) {\n // Already applied, skip\n return {\n success: true,\n applied: false,\n skipped: true,\n name: definition.id,\n checksum,\n execution_time_ms: 0,\n };\n }\n break;\n\n case 'failed':\n if (!options.force && !options.reconcile) {\n return {\n success: false,\n applied: false,\n skipped: false,\n name: definition.id,\n checksum,\n execution_time_ms: 0,\n error: `Migration ${definition.id} previously failed: ${existing.error_message || 'Unknown error'}. Use --force to retry.`,\n };\n }\n // Will retry below\n break;\n\n case 'running':\n if (!options.force) {\n return {\n success: false,\n applied: false,\n skipped: false,\n name: definition.id,\n checksum,\n execution_time_ms: 0,\n error: `Migration ${definition.id} is currently running or was interrupted. Use --force to retry if the previous run crashed.`,\n };\n }\n // Will retry below\n break;\n\n case 'rolled_back':\n // Rolled back migrations can be re-applied without --force\n break;\n }\n }\n\n if (options.dryRun) {\n return {\n success: true,\n applied: false,\n skipped: false,\n name: definition.id,\n checksum,\n execution_time_ms: Date.now() - startTime,\n };\n }\n\n // Get batch number\n if (this.currentBatch === null) {\n this.currentBatch = await this.getNextBatch();\n }\n\n // Determine if we're updating an existing record or inserting new\n const id = existing?.id || randomUUID();\n const attempts = (existing?.attempts || 0) + 1;\n\n if (existing) {\n // Update existing record to 'running'\n await this.db.query(\n `UPDATE _smrt_schema_migrations\n SET status = 'running', checksum = ?, attempts = ?, error_message = NULL, batch = ?, applied_by = ?, applied_at = CURRENT_TIMESTAMP\n WHERE id = ?`,\n checksum,\n attempts,\n this.currentBatch,\n hostname(),\n id,\n );\n } else {\n // Insert new record\n await this.db.query(\n `INSERT INTO _smrt_schema_migrations\n (id, name, version, checksum, status, attempts, is_reversible, package_name, source_file, applied_by, batch)\n VALUES (?, ?, ?, ?, 'running', 1, ?, ?, ?, ?, ?)`,\n id,\n definition.id,\n definition.version,\n checksum,\n (definition.is_reversible ?? definition.down.length > 0) ? 1 : 0,\n definition.package_name ?? null,\n definition.source_file ?? null,\n hostname(),\n this.currentBatch,\n );\n }\n\n try {\n // Execute the migration\n await this.executeStatements(definition.up, options);\n\n // Mark as completed\n const executionTime = Date.now() - startTime;\n await this.db.query(\n `UPDATE _smrt_schema_migrations\n SET status = 'completed', execution_time_ms = ?, applied_checksum = ?, applied_at = CURRENT_TIMESTAMP\n WHERE id = ?`,\n executionTime,\n checksum,\n id,\n );\n\n return {\n success: true,\n applied: true,\n skipped: false,\n name: definition.id,\n checksum,\n execution_time_ms: executionTime,\n };\n } catch (error) {\n const migrationError =\n error instanceof Error ? error : new Error(String(error));\n\n // Mark as failed. In an outer atomic Postgres transaction, a DDL error\n // aborts the transaction and this status write must be skipped so the\n // caller can roll back the whole batch while preserving the root error.\n try {\n await this.db.query(\n `UPDATE _smrt_schema_migrations\n SET status = 'failed', error_message = ?\n WHERE id = ?`,\n migrationError.message,\n id,\n );\n } catch (persistError) {\n // Preserve the migration failure; status persistence is secondary and\n // may be impossible until the surrounding transaction rolls back.\n const persistMessage =\n persistError instanceof Error\n ? persistError.message\n : String(persistError);\n logger.error(\n `Failed to persist failed status for migration ${definition.id}: ${persistMessage}`,\n );\n }\n\n return {\n success: false,\n applied: false,\n skipped: false,\n name: definition.id,\n checksum,\n execution_time_ms: Date.now() - startTime,\n error: migrationError,\n };\n }\n }\n\n /**\n * Apply multiple migrations in order\n */\n async applyAll(\n definitions: MigrationDefinition[],\n options: ApplyMigrationsOptions = {},\n ): Promise<MigrationResult[]> {\n if (options.atomic && !options.dryRun) {\n if (!this.db.transaction) {\n throw new Error(\n 'Atomic migration batches require a database adapter with transaction support.',\n );\n }\n\n if (this.dbEngine === 'postgres') {\n const concurrentStatement = findConcurrentIndexStatement(definitions);\n if (concurrentStatement) {\n throw new Error(\n `Atomic migration batch cannot include CONCURRENTLY index DDL in ${concurrentStatement.migrationName}; PostgreSQL forbids CONCURRENTLY inside a transaction.`,\n );\n }\n }\n\n try {\n return await this.db.transaction(async (tx) => {\n const txDb = {\n ...tx,\n transaction: async <T>(\n callback: (transactionDb: DatabaseInterface) => Promise<T>,\n ) => callback(tx as DatabaseInterface),\n } as DatabaseInterface;\n const txTracker = new MigrationTracker({\n db: txDb,\n lockTimeout: this.options.lockTimeout,\n statementTimeout: this.options.statementTimeout,\n useConcurrentIndexes: false,\n });\n const results = await txTracker.applyAll(definitions, {\n ...options,\n atomic: false,\n continueOnError: false,\n postgresSafe: false,\n });\n const failed = results.find((result) => !result.success);\n\n if (failed) {\n throw new AtomicMigrationRollback(results, failed);\n }\n\n return results;\n });\n } catch (error) {\n if (error instanceof AtomicMigrationRollback) {\n return error.results.map((result) => {\n if (!result.success || !result.applied) {\n return result;\n }\n\n return {\n ...result,\n success: false,\n applied: false,\n skipped: false,\n rolled_back: true,\n error: new Error(\n `Rolled back because migration ${error.failed.name} failed`,\n ),\n };\n });\n }\n\n throw error;\n }\n }\n\n const results: MigrationResult[] = [];\n this.currentBatch = await this.getNextBatch();\n\n for (const definition of definitions) {\n const result = await this.apply(definition, options);\n results.push(result);\n options.onProgress?.(result);\n\n if (!result.success && !options.continueOnError) {\n break;\n }\n }\n\n this.currentBatch = null;\n return results;\n }\n\n /**\n * Rollback a migration\n */\n async rollback(\n name: string,\n definition: MigrationDefinition,\n options: RollbackOptions = {},\n ): Promise<MigrationResult> {\n await this.initialize();\n const startTime = Date.now();\n const checksum = computeChecksum(definition.down);\n\n const record = await this.getMigration(name);\n if (!record) {\n return {\n success: false,\n name,\n checksum,\n execution_time_ms: 0,\n error: new Error(`Migration ${name} not found in database`),\n };\n }\n\n if (record.status !== 'completed') {\n return {\n success: false,\n name,\n checksum,\n execution_time_ms: 0,\n error: new Error(\n `Migration ${name} is not in completed state (current: ${record.status})`,\n ),\n };\n }\n\n if (!definition.down.length) {\n return {\n success: false,\n name,\n checksum,\n execution_time_ms: 0,\n error: new Error(\n `Migration ${name} is not reversible (no down statements)`,\n ),\n };\n }\n\n if (options.dryRun) {\n return {\n success: true,\n name,\n checksum,\n execution_time_ms: Date.now() - startTime,\n rolled_back: true,\n };\n }\n\n try {\n // Execute DOWN statements\n await this.executeStatements(definition.down, {});\n\n // Mark as rolled back\n await this.db.query(\n `UPDATE _smrt_schema_migrations\n SET status = 'rolled_back', rolled_back_at = CURRENT_TIMESTAMP\n WHERE name = ?`,\n name,\n );\n\n return {\n success: true,\n name,\n checksum,\n execution_time_ms: Date.now() - startTime,\n rolled_back: true,\n };\n } catch (error) {\n return {\n success: false,\n name,\n checksum,\n execution_time_ms: Date.now() - startTime,\n error: error instanceof Error ? error : new Error(String(error)),\n rolled_back: false,\n };\n }\n }\n\n /**\n * Get migration history with optional filtering\n */\n async getHistory(\n options: { limit?: number; since?: Date; status?: MigrationStatus } = {},\n ): Promise<SchemaMigrationRecord[]> {\n await this.initialize();\n\n let sql = `SELECT * FROM _smrt_schema_migrations WHERE 1=1`;\n const params: unknown[] = [];\n\n if (options.status) {\n sql += ` AND status = ?`;\n params.push(options.status);\n }\n\n if (options.since) {\n sql += ` AND applied_at >= ?`;\n params.push(options.since.toISOString());\n }\n\n sql += ` ORDER BY applied_at DESC`;\n\n if (options.limit) {\n sql += ` LIMIT ?`;\n params.push(options.limit);\n }\n\n const result = await this.db.query(sql, ...params);\n\n return (result.rows as MigrationRow[]).map((row) => ({\n ...row,\n applied_at: new Date(row.applied_at),\n rolled_back_at: row.rolled_back_at ? new Date(row.rolled_back_at) : null,\n is_reversible: Boolean(row.is_reversible),\n })) as SchemaMigrationRecord[];\n }\n\n /**\n * Execute SQL statements with appropriate transaction handling\n */\n private async executeStatements(\n statements: string[],\n options: ApplyMigrationsOptions,\n ): Promise<void> {\n if (this.dbEngine === 'postgres' && options.postgresSafe) {\n await this.executePostgresStatements(statements);\n } else {\n await this.executeWithTransaction(statements);\n }\n }\n\n /**\n * Execute statements within a transaction (SQLite/DuckDB)\n */\n private async executeWithTransaction(statements: string[]): Promise<void> {\n if (this.db.transaction) {\n await this.db.transaction(async (tx) => {\n for (const sql of statements) {\n await tx.query(sql);\n }\n });\n } else {\n // Fallback to sequential execution\n for (const sql of statements) {\n await this.db.query(sql);\n }\n }\n }\n\n /**\n * Execute statements with PostgreSQL-specific handling\n *\n * - CONCURRENTLY statements run outside transaction\n * - Regular statements run in transaction with lock_timeout\n *\n * Both CREATE and DROP variants of CONCURRENTLY must be detected — Postgres\n * forbids `DROP INDEX CONCURRENTLY` inside a transaction block, just like\n * the create variant. Issue #1165: the migration generator emits\n * `DROP INDEX CONCURRENTLY` for shape-drift recreates and orphan-index\n * cleanups, so the regex needs to cover both keywords.\n */\n private async executePostgresStatements(statements: string[]): Promise<void> {\n const { concurrent: finalConcurrent, regular: finalRegular } =\n planPostgresStatements(statements, !!this.options.useConcurrentIndexes);\n\n // CONCURRENTLY statements come from `planPostgresStatements`, which\n // also pushes any post-transform CREATE/DROP CONCURRENTLY into the\n // outside-transaction set. The original `concurrentStatements` list\n // is folded in there too so callers below see one merged stream.\n\n // Execute regular statements in transaction with timeouts\n if (finalRegular.length > 0 && this.db.transaction) {\n await this.db.transaction(async (tx) => {\n // Set session-level timeouts\n await tx.query(\n `SET LOCAL lock_timeout = '${this.options.lockTimeout}ms'`,\n );\n await tx.query(\n `SET LOCAL statement_timeout = '${this.options.statementTimeout}ms'`,\n );\n\n for (const sql of finalRegular) {\n await tx.query(sql);\n }\n });\n } else if (finalRegular.length > 0) {\n for (const sql of finalRegular) {\n await this.db.query(sql);\n }\n }\n\n // Execute CONCURRENTLY statements outside transaction\n for (const sql of finalConcurrent) {\n // Set lock timeout for the session\n await this.db.query(`SET lock_timeout = '${this.options.lockTimeout}ms'`);\n await this.db.query(sql);\n }\n }\n}\n\n/**\n * Split a batch of SQL statements into a transaction-safe set and a\n * concurrent set, applying `--postgres-safe` rewriting if requested.\n *\n * Exported for unit testing and to give external callers a way to\n * reason about what the tracker would execute in PostgreSQL safe mode.\n *\n * Rules:\n * - Statements already containing `CONCURRENTLY` for CREATE/DROP INDEX or\n * REINDEX operations always go to the concurrent set — Postgres rejects\n * them inside transactions.\n * - When `useConcurrentIndexes` is true, plain `CREATE INDEX` and plain\n * `DROP INDEX` are rewritten to use `CONCURRENTLY`, then routed to\n * the concurrent set. This is what the CLI `--postgres-safe` flag and\n * the auto-migrate path rely on for issue #1165's shape-drift drops.\n * - All other statements stay in the regular (transaction) set.\n */\nexport function planPostgresStatements(\n statements: string[],\n useConcurrentIndexes: boolean,\n): { concurrent: string[]; regular: string[] } {\n const concurrentRegex = CONCURRENT_INDEX_STATEMENT_RE;\n\n const concurrent: string[] = [];\n const regular: string[] = [];\n\n for (const sql of statements) {\n if (concurrentRegex.test(sql)) {\n concurrent.push(sql);\n continue;\n }\n if (useConcurrentIndexes) {\n if (/CREATE\\s+(UNIQUE\\s+)?INDEX\\s+(?!CONCURRENTLY)/i.test(sql)) {\n concurrent.push(\n sql.replace(\n /CREATE\\s+(UNIQUE\\s+)?INDEX\\s+/i,\n 'CREATE $1INDEX CONCURRENTLY ',\n ),\n );\n continue;\n }\n if (/DROP\\s+INDEX\\s+(?!CONCURRENTLY)/i.test(sql)) {\n concurrent.push(\n sql.replace(/DROP\\s+INDEX\\s+/i, 'DROP INDEX CONCURRENTLY '),\n );\n continue;\n }\n }\n regular.push(sql);\n }\n\n return { concurrent, regular };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tracker.js","names":[],"sources":["../../src/migrations/tracker.ts"],"sourcesContent":["/**\n * Migration Tracker\n *\n * Manages migration state, tracking which migrations have been applied,\n * and providing idempotent migration application.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { hostname } from 'node:os';\nimport { createLogger } from '@happyvertical/logger';\nimport { detectEngine } from '../schema/ddl/index.js';\n// DatabaseEngine comes from the DDL layer (the json-inclusive type that\n// `detectEngine` actually returns), matching `SchemaComparer` in differ.ts.\n// The migration stack supports the JSON adapter post-R11, so the tracker's\n// engine type must include 'json' too — the narrower `migrations/types`\n// alias would reject it.\nimport type { DatabaseEngine } from '../schema/ddl/types.js';\nimport type {\n DriftReport,\n MigrationDefinition,\n MigrationResult,\n MigrationStatus,\n SchemaMigrationRecord,\n} from '../schema/types.js';\nimport { CREATE_SMRT_SCHEMA_MIGRATIONS_TABLE } from '../system/schema.js';\nimport { computeChecksum, verifyChecksum } from './checksum.js';\nimport type {\n ApplyMigrationsOptions,\n DatabaseInterface,\n MigrationTrackerOptions,\n RollbackOptions,\n} from './types.js';\n\nconst logger = createLogger({ level: 'info' });\n\n/**\n * Row type for _smrt_schema_migrations table\n */\ninterface MigrationRow {\n id: string;\n name: string;\n version: string;\n checksum: string;\n applied_checksum?: string | null;\n applied_at: string;\n execution_time_ms?: number | null;\n package_name?: string | null;\n source_file?: string | null;\n status: string;\n error_message?: string | null;\n attempts: number;\n is_reversible: number | boolean;\n rolled_back_at?: string | null;\n applied_by?: string | null;\n batch: number;\n}\n\n/**\n * Default options for MigrationTracker\n */\nconst DEFAULT_OPTIONS = {\n lockTimeout: 30000,\n statementTimeout: 60000,\n useConcurrentIndexes: true,\n};\n\nclass AtomicMigrationRollback extends Error {\n constructor(\n public readonly results: MigrationResult[],\n public readonly failed: MigrationResult,\n ) {\n super(`Atomic migration batch failed at ${failed.name}`);\n }\n}\n\nconst CONCURRENT_INDEX_STATEMENT_RE =\n /(?:(?:CREATE\\s+(?:UNIQUE\\s+)?INDEX|DROP\\s+INDEX)\\s+CONCURRENTLY|REINDEX(?:\\s*\\([^)]*\\))?\\s+(?:INDEX|TABLE|SCHEMA|DATABASE|SYSTEM)\\s+CONCURRENTLY)/i;\n\nfunction findConcurrentIndexStatement(\n definitions: MigrationDefinition[],\n): { migrationName: string; statement: string } | null {\n for (const definition of definitions) {\n const statement = definition.up.find((sql) =>\n CONCURRENT_INDEX_STATEMENT_RE.test(sql),\n );\n\n if (statement) {\n return {\n migrationName: definition.id,\n statement,\n };\n }\n }\n\n return null;\n}\n\n/**\n * MigrationTracker class\n *\n * Provides migration tracking and state management:\n * - Initializes the _smrt_schema_migrations tracking table\n * - Tracks applied migrations with checksums\n * - Provides idempotent migration application\n * - Supports rollback via DOWN scripts\n * - Handles PostgreSQL-specific concerns (CONCURRENTLY, lock timeout)\n */\nexport class MigrationTracker {\n private db: DatabaseInterface;\n private options: Required<Omit<MigrationTrackerOptions, 'db' | 'engineHint'>>;\n private engineHint?: string;\n private dbEngine: DatabaseEngine;\n /**\n * Memoized initialization promise. Storing the in-flight promise (rather\n * than a `boolean` flag set after the DDL completes) makes `initialize()`\n * safe under concurrency: multiple parallel callers all `await` the same\n * promise instead of independently re-running the DDL. On error the slot\n * is cleared so the next caller retries — a transient failure doesn't\n * permanently poison the instance.\n */\n private initializePromise: Promise<void> | null = null;\n private currentBatch: number | null = null;\n\n constructor(options: MigrationTrackerOptions) {\n this.db = options.db;\n this.options = {\n lockTimeout: options.lockTimeout ?? DEFAULT_OPTIONS.lockTimeout,\n statementTimeout:\n options.statementTimeout ?? DEFAULT_OPTIONS.statementTimeout,\n useConcurrentIndexes:\n options.useConcurrentIndexes ?? DEFAULT_OPTIONS.useConcurrentIndexes,\n };\n this.engineHint = options.engineHint;\n this.dbEngine = this.detectDbEngine();\n }\n\n /**\n * Detect the database engine. Honors an explicit `engineHint` (passed via\n * `MigrationTrackerOptions`) before falling back to URL parsing — this is\n * the same `detectEngine` contract used by `SchemaComparer` and the rest\n * of the migration stack, so the tracker stays consistent with the DDL\n * the orchestrator generated.\n */\n private detectDbEngine(): DatabaseEngine {\n const dbWithConfig = this.db as DatabaseInterface & {\n config?: { url?: string };\n };\n const url = this.db.url || dbWithConfig.config?.url || '';\n return detectEngine(url, this.engineHint);\n }\n\n /**\n * Get the current database engine\n */\n getEngine(): DatabaseEngine {\n return this.dbEngine;\n }\n\n /**\n * Initialize the migrations tracking table\n */\n async initialize(): Promise<void> {\n if (!this.initializePromise) {\n this.initializePromise = this.runInitializeDdl().catch((error) => {\n this.initializePromise = null;\n throw error;\n });\n }\n return this.initializePromise;\n }\n\n private async runInitializeDdl(): Promise<void> {\n // Parse and execute each statement in the DDL\n const statements = CREATE_SMRT_SCHEMA_MIGRATIONS_TABLE.split(';')\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n\n for (const statement of statements) {\n await this.db.query(statement);\n }\n }\n\n /**\n * Get all applied migrations ordered by applied_at\n */\n async getAppliedMigrations(): Promise<SchemaMigrationRecord[]> {\n await this.initialize();\n\n const result = await this.db.query(\n `SELECT * FROM _smrt_schema_migrations WHERE status = 'completed' ORDER BY applied_at ASC`,\n );\n\n return (result.rows as MigrationRow[]).map((row) => ({\n ...row,\n applied_at: new Date(row.applied_at),\n rolled_back_at: row.rolled_back_at ? new Date(row.rolled_back_at) : null,\n is_reversible: Boolean(row.is_reversible),\n })) as SchemaMigrationRecord[];\n }\n\n /**\n * Get pending migrations (defined but not applied)\n */\n async getPendingMigrations(\n definitions: MigrationDefinition[],\n ): Promise<MigrationDefinition[]> {\n const applied = await this.getAppliedMigrations();\n const appliedNames = new Set(applied.map((m) => m.name));\n return definitions.filter((d) => !appliedNames.has(d.id));\n }\n\n /**\n * Check if a migration has been applied\n */\n async isApplied(migrationId: string): Promise<boolean> {\n await this.initialize();\n\n const result = await this.db.query(\n `SELECT 1 FROM _smrt_schema_migrations WHERE name = ? AND status = 'completed' LIMIT 1`,\n migrationId,\n );\n\n return result.rows.length > 0;\n }\n\n /**\n * Get a single migration record by name\n */\n async getMigration(name: string): Promise<SchemaMigrationRecord | null> {\n await this.initialize();\n\n const result = await this.db.query(\n `SELECT * FROM _smrt_schema_migrations WHERE name = ? LIMIT 1`,\n name,\n );\n\n if (result.rows.length === 0) return null;\n\n const row = result.rows[0] as MigrationRow;\n return {\n ...row,\n applied_at: new Date(row.applied_at),\n rolled_back_at: row.rolled_back_at ? new Date(row.rolled_back_at) : null,\n is_reversible: Boolean(row.is_reversible),\n } as SchemaMigrationRecord;\n }\n\n /**\n * Get the next batch number\n */\n async getNextBatch(): Promise<number> {\n await this.initialize();\n\n const result = await this.db.query(\n `SELECT MAX(batch) as max_batch FROM _smrt_schema_migrations`,\n );\n\n const row = result.rows[0] as { max_batch: number | null } | undefined;\n return (row?.max_batch ?? 0) + 1;\n }\n\n /**\n * Detect drift between migration definitions and applied migrations\n */\n async detectDrift(\n definitions: MigrationDefinition[],\n ): Promise<DriftReport[]> {\n const applied = await this.getAppliedMigrations();\n const reports: DriftReport[] = [];\n\n const appliedMap = new Map(applied.map((m) => [m.name, m]));\n const definitionMap = new Map(definitions.map((d) => [d.id, d]));\n\n // Check each applied migration against definitions\n for (const record of applied) {\n const definition = definitionMap.get(record.name);\n\n if (!definition) {\n // Migration applied but definition is missing\n reports.push({\n migration_name: record.name,\n expected_checksum: 'N/A',\n actual_checksum: record.checksum,\n drift_type: 'unknown_in_db',\n recommendation:\n 'Migration exists in database but definition is missing. Manual cleanup may be required.',\n });\n continue;\n }\n\n // Check checksum\n const currentChecksum = computeChecksum(definition.up);\n const verification = verifyChecksum(\n currentChecksum,\n record.checksum,\n record.applied_checksum,\n );\n\n if (!verification.valid) {\n const driftType = verification.drift ?? 'db_modified';\n reports.push({\n migration_name: record.name,\n expected_checksum: record.checksum,\n actual_checksum: currentChecksum,\n drift_type: driftType,\n recommendation:\n driftType === 'file_modified'\n ? 'Migration file was modified after application. Create a new migration instead.'\n : 'Database schema was modified outside of migrations. Review and reconcile manually.',\n });\n }\n }\n\n return reports;\n }\n\n /**\n * Apply a single migration\n */\n async apply(\n definition: MigrationDefinition,\n options: ApplyMigrationsOptions = {},\n ): Promise<MigrationResult> {\n await this.initialize();\n const startTime = Date.now();\n const checksum = computeChecksum(definition.up);\n const force = Boolean(\n options.force || options.forceMigrations?.includes(definition.id),\n );\n const hasScopedForce = Boolean(options.forceMigrations?.length);\n\n // Check if migration record already exists\n const existing = await this.getMigration(definition.id);\n\n if (existing) {\n // Handle based on existing status\n switch (existing.status) {\n case 'completed':\n if (!force && existing.checksum !== checksum) {\n return {\n success: false,\n applied: false,\n skipped: false,\n name: definition.id,\n checksum,\n execution_time_ms: 0,\n error: `Migration ${definition.id} checksum mismatch. Was already applied with different checksum. Use --force-migration ${definition.id} to override only this migration, or --force to override the whole batch.`,\n };\n }\n\n if (!force && !options.reconcile) {\n // Already applied, skip\n return {\n success: true,\n applied: false,\n skipped: true,\n name: definition.id,\n checksum,\n execution_time_ms: 0,\n };\n }\n break;\n\n case 'failed':\n if (!force && (!options.reconcile || hasScopedForce)) {\n return {\n success: false,\n applied: false,\n skipped: false,\n name: definition.id,\n checksum,\n execution_time_ms: 0,\n error: `Migration ${definition.id} previously failed: ${existing.error_message || 'Unknown error'}. Use --force-migration ${definition.id} to retry only this migration, or --force to retry the whole batch.`,\n };\n }\n // Will retry below\n break;\n\n case 'running':\n if (!force) {\n return {\n success: false,\n applied: false,\n skipped: false,\n name: definition.id,\n checksum,\n execution_time_ms: 0,\n error: `Migration ${definition.id} is currently running or was interrupted. If the previous run crashed, use --force-migration ${definition.id} to retry only this migration, or --force to retry the whole batch.`,\n };\n }\n // Will retry below\n break;\n\n case 'rolled_back':\n // Rolled back migrations can be re-applied without --force\n break;\n }\n }\n\n if (options.dryRun) {\n return {\n success: true,\n applied: false,\n skipped: false,\n name: definition.id,\n checksum,\n execution_time_ms: Date.now() - startTime,\n };\n }\n\n // Get batch number\n if (this.currentBatch === null) {\n this.currentBatch = await this.getNextBatch();\n }\n\n // Determine if we're updating an existing record or inserting new\n const id = existing?.id || randomUUID();\n const attempts = (existing?.attempts || 0) + 1;\n\n if (existing) {\n // Update existing record to 'running'\n await this.db.query(\n `UPDATE _smrt_schema_migrations\n SET status = 'running', checksum = ?, attempts = ?, error_message = NULL, batch = ?, applied_by = ?, applied_at = CURRENT_TIMESTAMP\n WHERE id = ?`,\n checksum,\n attempts,\n this.currentBatch,\n hostname(),\n id,\n );\n } else {\n // Insert new record\n await this.db.query(\n `INSERT INTO _smrt_schema_migrations\n (id, name, version, checksum, status, attempts, is_reversible, package_name, source_file, applied_by, batch)\n VALUES (?, ?, ?, ?, 'running', 1, ?, ?, ?, ?, ?)`,\n id,\n definition.id,\n definition.version,\n checksum,\n (definition.is_reversible ?? definition.down.length > 0) ? 1 : 0,\n definition.package_name ?? null,\n definition.source_file ?? null,\n hostname(),\n this.currentBatch,\n );\n }\n\n try {\n // Execute the migration\n await this.executeStatements(definition.up, options);\n\n // Mark as completed\n const executionTime = Date.now() - startTime;\n await this.db.query(\n `UPDATE _smrt_schema_migrations\n SET status = 'completed', execution_time_ms = ?, applied_checksum = ?, applied_at = CURRENT_TIMESTAMP\n WHERE id = ?`,\n executionTime,\n checksum,\n id,\n );\n\n return {\n success: true,\n applied: true,\n skipped: false,\n name: definition.id,\n checksum,\n execution_time_ms: executionTime,\n };\n } catch (error) {\n const migrationError =\n error instanceof Error ? error : new Error(String(error));\n\n // Mark as failed. In an outer atomic Postgres transaction, a DDL error\n // aborts the transaction and this status write must be skipped so the\n // caller can roll back the whole batch while preserving the root error.\n try {\n await this.db.query(\n `UPDATE _smrt_schema_migrations\n SET status = 'failed', error_message = ?\n WHERE id = ?`,\n migrationError.message,\n id,\n );\n } catch (persistError) {\n // Preserve the migration failure; status persistence is secondary and\n // may be impossible until the surrounding transaction rolls back.\n const persistMessage =\n persistError instanceof Error\n ? persistError.message\n : String(persistError);\n logger.error(\n `Failed to persist failed status for migration ${definition.id}: ${persistMessage}`,\n );\n }\n\n return {\n success: false,\n applied: false,\n skipped: false,\n name: definition.id,\n checksum,\n execution_time_ms: Date.now() - startTime,\n error: migrationError,\n };\n }\n }\n\n /**\n * Apply multiple migrations in order\n */\n async applyAll(\n definitions: MigrationDefinition[],\n options: ApplyMigrationsOptions = {},\n ): Promise<MigrationResult[]> {\n if (options.atomic && !options.dryRun) {\n if (!this.db.transaction) {\n throw new Error(\n 'Atomic migration batches require a database adapter with transaction support.',\n );\n }\n\n if (this.dbEngine === 'postgres') {\n const concurrentStatement = findConcurrentIndexStatement(definitions);\n if (concurrentStatement) {\n throw new Error(\n `Atomic migration batch cannot include CONCURRENTLY index DDL in ${concurrentStatement.migrationName}; PostgreSQL forbids CONCURRENTLY inside a transaction.`,\n );\n }\n }\n\n try {\n return await this.db.transaction(async (tx) => {\n const txDb = {\n ...tx,\n transaction: async <T>(\n callback: (transactionDb: DatabaseInterface) => Promise<T>,\n ) => callback(tx as DatabaseInterface),\n } as DatabaseInterface;\n const txTracker = new MigrationTracker({\n db: txDb,\n lockTimeout: this.options.lockTimeout,\n statementTimeout: this.options.statementTimeout,\n useConcurrentIndexes: false,\n });\n const results = await txTracker.applyAll(definitions, {\n ...options,\n atomic: false,\n continueOnError: false,\n postgresSafe: false,\n });\n const failed = results.find((result) => !result.success);\n\n if (failed) {\n throw new AtomicMigrationRollback(results, failed);\n }\n\n return results;\n });\n } catch (error) {\n if (error instanceof AtomicMigrationRollback) {\n return error.results.map((result) => {\n if (!result.success || !result.applied) {\n return result;\n }\n\n return {\n ...result,\n success: false,\n applied: false,\n skipped: false,\n rolled_back: true,\n error: new Error(\n `Rolled back because migration ${error.failed.name} failed`,\n ),\n };\n });\n }\n\n throw error;\n }\n }\n\n const results: MigrationResult[] = [];\n this.currentBatch = await this.getNextBatch();\n\n for (const definition of definitions) {\n const result = await this.apply(definition, options);\n results.push(result);\n options.onProgress?.(result);\n\n if (!result.success && !options.continueOnError) {\n break;\n }\n }\n\n this.currentBatch = null;\n return results;\n }\n\n /**\n * Rollback a migration\n */\n async rollback(\n name: string,\n definition: MigrationDefinition,\n options: RollbackOptions = {},\n ): Promise<MigrationResult> {\n await this.initialize();\n const startTime = Date.now();\n const checksum = computeChecksum(definition.down);\n\n const record = await this.getMigration(name);\n if (!record) {\n return {\n success: false,\n name,\n checksum,\n execution_time_ms: 0,\n error: new Error(`Migration ${name} not found in database`),\n };\n }\n\n if (record.status !== 'completed') {\n return {\n success: false,\n name,\n checksum,\n execution_time_ms: 0,\n error: new Error(\n `Migration ${name} is not in completed state (current: ${record.status})`,\n ),\n };\n }\n\n if (!definition.down.length) {\n return {\n success: false,\n name,\n checksum,\n execution_time_ms: 0,\n error: new Error(\n `Migration ${name} is not reversible (no down statements)`,\n ),\n };\n }\n\n if (options.dryRun) {\n return {\n success: true,\n name,\n checksum,\n execution_time_ms: Date.now() - startTime,\n rolled_back: true,\n };\n }\n\n try {\n // Execute DOWN statements\n await this.executeStatements(definition.down, {});\n\n // Mark as rolled back\n await this.db.query(\n `UPDATE _smrt_schema_migrations\n SET status = 'rolled_back', rolled_back_at = CURRENT_TIMESTAMP\n WHERE name = ?`,\n name,\n );\n\n return {\n success: true,\n name,\n checksum,\n execution_time_ms: Date.now() - startTime,\n rolled_back: true,\n };\n } catch (error) {\n return {\n success: false,\n name,\n checksum,\n execution_time_ms: Date.now() - startTime,\n error: error instanceof Error ? error : new Error(String(error)),\n rolled_back: false,\n };\n }\n }\n\n /**\n * Get migration history with optional filtering\n */\n async getHistory(\n options: { limit?: number; since?: Date; status?: MigrationStatus } = {},\n ): Promise<SchemaMigrationRecord[]> {\n await this.initialize();\n\n let sql = `SELECT * FROM _smrt_schema_migrations WHERE 1=1`;\n const params: unknown[] = [];\n\n if (options.status) {\n sql += ` AND status = ?`;\n params.push(options.status);\n }\n\n if (options.since) {\n sql += ` AND applied_at >= ?`;\n params.push(options.since.toISOString());\n }\n\n sql += ` ORDER BY applied_at DESC`;\n\n if (options.limit) {\n sql += ` LIMIT ?`;\n params.push(options.limit);\n }\n\n const result = await this.db.query(sql, ...params);\n\n return (result.rows as MigrationRow[]).map((row) => ({\n ...row,\n applied_at: new Date(row.applied_at),\n rolled_back_at: row.rolled_back_at ? new Date(row.rolled_back_at) : null,\n is_reversible: Boolean(row.is_reversible),\n })) as SchemaMigrationRecord[];\n }\n\n /**\n * Execute SQL statements with appropriate transaction handling\n */\n private async executeStatements(\n statements: string[],\n options: ApplyMigrationsOptions,\n ): Promise<void> {\n if (this.dbEngine === 'postgres' && options.postgresSafe) {\n await this.executePostgresStatements(statements);\n } else {\n await this.executeWithTransaction(statements);\n }\n }\n\n /**\n * Execute statements within a transaction (SQLite/DuckDB)\n */\n private async executeWithTransaction(statements: string[]): Promise<void> {\n if (this.db.transaction) {\n await this.db.transaction(async (tx) => {\n for (const sql of statements) {\n await tx.query(sql);\n }\n });\n } else {\n // Fallback to sequential execution\n for (const sql of statements) {\n await this.db.query(sql);\n }\n }\n }\n\n /**\n * Execute statements with PostgreSQL-specific handling\n *\n * - CONCURRENTLY statements run outside transaction\n * - Regular statements run in transaction with lock_timeout\n *\n * Both CREATE and DROP variants of CONCURRENTLY must be detected — Postgres\n * forbids `DROP INDEX CONCURRENTLY` inside a transaction block, just like\n * the create variant. Issue #1165: the migration generator emits\n * `DROP INDEX CONCURRENTLY` for shape-drift recreates and orphan-index\n * cleanups, so the regex needs to cover both keywords.\n */\n private async executePostgresStatements(statements: string[]): Promise<void> {\n const { concurrent: finalConcurrent, regular: finalRegular } =\n planPostgresStatements(statements, !!this.options.useConcurrentIndexes);\n\n // CONCURRENTLY statements come from `planPostgresStatements`, which\n // also pushes any post-transform CREATE/DROP CONCURRENTLY into the\n // outside-transaction set. The original `concurrentStatements` list\n // is folded in there too so callers below see one merged stream.\n\n // Execute regular statements in transaction with timeouts\n if (finalRegular.length > 0 && this.db.transaction) {\n await this.db.transaction(async (tx) => {\n // Set session-level timeouts\n await tx.query(\n `SET LOCAL lock_timeout = '${this.options.lockTimeout}ms'`,\n );\n await tx.query(\n `SET LOCAL statement_timeout = '${this.options.statementTimeout}ms'`,\n );\n\n for (const sql of finalRegular) {\n await tx.query(sql);\n }\n });\n } else if (finalRegular.length > 0) {\n for (const sql of finalRegular) {\n await this.db.query(sql);\n }\n }\n\n // Execute CONCURRENTLY statements outside transaction\n for (const sql of finalConcurrent) {\n // Set lock timeout for the session\n await this.db.query(`SET lock_timeout = '${this.options.lockTimeout}ms'`);\n await this.db.query(sql);\n }\n }\n}\n\n/**\n * Split a batch of SQL statements into a transaction-safe set and a\n * concurrent set, applying `--postgres-safe` rewriting if requested.\n *\n * Exported for unit testing and to give external callers a way to\n * reason about what the tracker would execute in PostgreSQL safe mode.\n *\n * Rules:\n * - Statements already containing `CONCURRENTLY` for CREATE/DROP INDEX or\n * REINDEX operations always go to the concurrent set — Postgres rejects\n * them inside transactions.\n * - When `useConcurrentIndexes` is true, plain `CREATE INDEX` and plain\n * `DROP INDEX` are rewritten to use `CONCURRENTLY`, then routed to\n * the concurrent set. This is what the CLI `--postgres-safe` flag and\n * the auto-migrate path rely on for issue #1165's shape-drift drops.\n * - All other statements stay in the regular (transaction) set.\n */\nexport function planPostgresStatements(\n statements: string[],\n useConcurrentIndexes: boolean,\n): { concurrent: string[]; regular: string[] } {\n const concurrentRegex = CONCURRENT_INDEX_STATEMENT_RE;\n\n const concurrent: string[] = [];\n const regular: string[] = [];\n\n for (const sql of statements) {\n if (concurrentRegex.test(sql)) {\n concurrent.push(sql);\n continue;\n }\n if (useConcurrentIndexes) {\n if (/CREATE\\s+(UNIQUE\\s+)?INDEX\\s+(?!CONCURRENTLY)/i.test(sql)) {\n concurrent.push(\n sql.replace(\n /CREATE\\s+(UNIQUE\\s+)?INDEX\\s+/i,\n 'CREATE $1INDEX CONCURRENTLY ',\n ),\n );\n continue;\n }\n if (/DROP\\s+INDEX\\s+(?!CONCURRENTLY)/i.test(sql)) {\n concurrent.push(\n sql.replace(/DROP\\s+INDEX\\s+/i, 'DROP INDEX CONCURRENTLY '),\n );\n continue;\n }\n }\n regular.push(sql);\n }\n\n return { concurrent, regular };\n}\n"],"mappings":"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"}
|
|
@@ -96,6 +96,12 @@ export interface ApplyMigrationsOptions {
|
|
|
96
96
|
dryRun?: boolean;
|
|
97
97
|
/** Force application even if checksums don't match */
|
|
98
98
|
force?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Force only the migration definitions whose exact IDs appear in this list.
|
|
101
|
+
* Other definitions retain the checksum, failed, and running guards even
|
|
102
|
+
* when the batch also enables reconciliation.
|
|
103
|
+
*/
|
|
104
|
+
forceMigrations?: readonly string[];
|
|
99
105
|
/**
|
|
100
106
|
* Reconcile migration history with live schema drift.
|
|
101
107
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/migrations/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/migrations/types.ts"],"names":[],"mappings":"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"}
|
package/dist/smrt-knowledge.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-07-
|
|
3
|
+
"generatedAt": "2026-07-17T06:27:33.673Z",
|
|
4
4
|
"packageName": "@happyvertical/smrt-core",
|
|
5
|
-
"packageVersion": "0.40.
|
|
5
|
+
"packageVersion": "0.40.7",
|
|
6
6
|
"sourceManifestPath": "dist/manifest.json",
|
|
7
7
|
"agentDocPath": "AGENTS.md",
|
|
8
8
|
"sourceHashes": {
|
|
9
|
-
"manifest": "
|
|
10
|
-
"packageJson": "
|
|
9
|
+
"manifest": "e60fa006e4c905f87353017a3d75e71d0ee6394d4e2ead1826e3c79735827a6d",
|
|
10
|
+
"packageJson": "1890459487e9c7449cee7ca40a11dd662c6f0482beb47c25c1d2a4f746fd1511",
|
|
11
11
|
"agents": "30fbe76583d2c259f28b816269653a700244ff9e68118c51f61cdbac0ba58153"
|
|
12
12
|
},
|
|
13
13
|
"exports": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-core",
|
|
3
|
-
"version": "0.40.
|
|
3
|
+
"version": "0.40.7",
|
|
4
4
|
"description": "Core AI agent framework with standardized collections, object-relational mapping, and code generators",
|
|
5
5
|
"author": "HappyVertical",
|
|
6
6
|
"type": "module",
|
|
@@ -144,12 +144,12 @@
|
|
|
144
144
|
}
|
|
145
145
|
},
|
|
146
146
|
"dependencies": {
|
|
147
|
-
"@happyvertical/ai": "^0.80.
|
|
148
|
-
"@happyvertical/files": "^0.80.
|
|
149
|
-
"@happyvertical/json": "^0.80.
|
|
150
|
-
"@happyvertical/logger": "^0.80.
|
|
151
|
-
"@happyvertical/sql": "^0.80.
|
|
152
|
-
"@happyvertical/utils": "^0.80.
|
|
147
|
+
"@happyvertical/ai": "^0.80.2",
|
|
148
|
+
"@happyvertical/files": "^0.80.2",
|
|
149
|
+
"@happyvertical/json": "^0.80.2",
|
|
150
|
+
"@happyvertical/logger": "^0.80.2",
|
|
151
|
+
"@happyvertical/sql": "^0.80.2",
|
|
152
|
+
"@happyvertical/utils": "^0.80.2",
|
|
153
153
|
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
154
154
|
"@oxc-project/runtime": "^0.138.0",
|
|
155
155
|
"cheerio": "^1.2.0",
|
|
@@ -159,9 +159,9 @@
|
|
|
159
159
|
"tsx": "^4.23.0",
|
|
160
160
|
"typescript": "5.9.3",
|
|
161
161
|
"yaml": "^2.9.0",
|
|
162
|
-
"@happyvertical/smrt-
|
|
163
|
-
"@happyvertical/smrt-
|
|
164
|
-
"@happyvertical/smrt-types": "0.40.
|
|
162
|
+
"@happyvertical/smrt-config": "0.40.7",
|
|
163
|
+
"@happyvertical/smrt-scanner": "0.40.7",
|
|
164
|
+
"@happyvertical/smrt-types": "0.40.7"
|
|
165
165
|
},
|
|
166
166
|
"peerDependencies": {
|
|
167
167
|
"@huggingface/transformers": ">=3.0.0 <4.0.0",
|