pg-migration-engine 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/LICENSE +35 -0
  2. package/README.md +304 -0
  3. package/package.json +52 -0
  4. package/src/behavioral/behavioral-applier.js +374 -0
  5. package/src/behavioral/behavioral-extractor.js +266 -0
  6. package/src/behavioral/behavioral-puller.js +35 -0
  7. package/src/behavioral/index.js +4 -0
  8. package/src/behavioral/phase-sorter.js +24 -0
  9. package/src/constants.js +97 -0
  10. package/src/ddl-generator/alter-generator.js +1512 -0
  11. package/src/ddl-generator/comment-generator.js +95 -0
  12. package/src/ddl-generator/create-generator.js +1426 -0
  13. package/src/ddl-generator/drop-generator.js +194 -0
  14. package/src/ddl-generator/generator.js +78 -0
  15. package/src/ddl-generator/grant-generator.js +31 -0
  16. package/src/ddl-generator/index.js +3 -0
  17. package/src/ddl-generator/pg-version.js +15 -0
  18. package/src/ddl-generator/rename-generator.js +88 -0
  19. package/src/ddl-generator/safe-patterns.js +241 -0
  20. package/src/differ/change-classifier.js +192 -0
  21. package/src/differ/dependency-resolver.js +523 -0
  22. package/src/differ/index.js +12 -0
  23. package/src/differ/object-matcher.js +510 -0
  24. package/src/differ/property-differ.js +1134 -0
  25. package/src/differ/risk-tagger.js +561 -0
  26. package/src/differ/schema-differ.js +309 -0
  27. package/src/differ/utils/levenshtein.js +210 -0
  28. package/src/differ/utils/path-builder.js +198 -0
  29. package/src/differ/utils/type-compatibility.js +472 -0
  30. package/src/errors.js +147 -0
  31. package/src/executor/drift-detector.js +221 -0
  32. package/src/executor/index.js +7 -0
  33. package/src/executor/lock-manager.js +308 -0
  34. package/src/executor/migration-executor.js +1249 -0
  35. package/src/executor/progress-tracker.js +81 -0
  36. package/src/executor/recovery-manager.js +47 -0
  37. package/src/executor/snapshot-manager.js +22 -0
  38. package/src/executor/sql-splitter.js +120 -0
  39. package/src/executor/transaction-manager.js +288 -0
  40. package/src/index.js +483 -0
  41. package/src/introspection/index.js +4 -0
  42. package/src/introspection/introspector.js +250 -0
  43. package/src/introspection/queries/access-methods.js +29 -0
  44. package/src/introspection/queries/casts.js +38 -0
  45. package/src/introspection/queries/collations.js +51 -0
  46. package/src/introspection/queries/comments.js +66 -0
  47. package/src/introspection/queries/constraints.js +65 -0
  48. package/src/introspection/queries/conversions.js +39 -0
  49. package/src/introspection/queries/databases.js +43 -0
  50. package/src/introspection/queries/default-privileges.js +37 -0
  51. package/src/introspection/queries/event-triggers.js +43 -0
  52. package/src/introspection/queries/extensions.js +21 -0
  53. package/src/introspection/queries/foreign-data.js +136 -0
  54. package/src/introspection/queries/functions.js +75 -0
  55. package/src/introspection/queries/grants.js +38 -0
  56. package/src/introspection/queries/index.js +33 -0
  57. package/src/introspection/queries/indexes.js +99 -0
  58. package/src/introspection/queries/inheritance.js +24 -0
  59. package/src/introspection/queries/multiranges.js +37 -0
  60. package/src/introspection/queries/operators.js +180 -0
  61. package/src/introspection/queries/partitions.js +42 -0
  62. package/src/introspection/queries/pg18-19.js +43 -0
  63. package/src/introspection/queries/policies.js +35 -0
  64. package/src/introspection/queries/procedural-languages.js +36 -0
  65. package/src/introspection/queries/publications.js +114 -0
  66. package/src/introspection/queries/roles.js +66 -0
  67. package/src/introspection/queries/rules.js +49 -0
  68. package/src/introspection/queries/sequences.js +37 -0
  69. package/src/introspection/queries/statistics.js +74 -0
  70. package/src/introspection/queries/subscriptions.js +99 -0
  71. package/src/introspection/queries/tables.js +151 -0
  72. package/src/introspection/queries/tablespaces.js +36 -0
  73. package/src/introspection/queries/text-search.js +146 -0
  74. package/src/introspection/queries/triggers.js +61 -0
  75. package/src/introspection/queries/types.js +106 -0
  76. package/src/introspection/queries/views.js +146 -0
  77. package/src/introspection/translator.js +1283 -0
  78. package/src/introspection/version-detector.js +25 -0
  79. package/src/planner/backfill-planner.js +36 -0
  80. package/src/planner/dry-run.js +21 -0
  81. package/src/planner/index.js +6 -0
  82. package/src/planner/migration-planner.js +356 -0
  83. package/src/planner/smart-migrator.js +82 -0
  84. package/src/planner/step-sequencer.js +61 -0
  85. package/src/planner/type-registry.js +47 -0
  86. package/src/risk/compatibility-checker.js +29 -0
  87. package/src/risk/data-loss-checker.js +32 -0
  88. package/src/risk/destructive-checker.js +38 -0
  89. package/src/risk/index.js +6 -0
  90. package/src/risk/lock-analyzer.js +39 -0
  91. package/src/risk/recommendations.js +44 -0
  92. package/src/risk/risk-engine.js +25 -0
  93. package/src/storage/index.js +5 -0
  94. package/src/storage/memory-storage.js +87 -0
  95. package/src/storage/migration-table.js +423 -0
  96. package/src/storage/rollback-generator.js +344 -0
  97. package/src/types/changes.js +136 -0
  98. package/src/types/connection.js +17 -0
  99. package/src/types/execution.js +107 -0
  100. package/src/types/index.js +1 -0
  101. package/src/types/migration.js +67 -0
  102. package/src/types/risk.js +32 -0
  103. package/src/types/schema.d.ts +1004 -0
  104. package/src/types/schema.js +561 -0
@@ -0,0 +1,344 @@
1
+ /**
2
+ * Rollback Generator - Generate rollback SQL for migrations
3
+ */
4
+
5
+ export class RollbackGenerator {
6
+ /**
7
+ * Generate rollback SQL from a completed migration's history
8
+ * @param {Object} migration - Migration history record
9
+ * @returns {Array} Rollback SQL statements in reverse order
10
+ */
11
+ generateRollback(migration) {
12
+ const diff = migration.schema_diff || migration.diff;
13
+ const rollbackSteps = [];
14
+
15
+ if (!diff?.changes) {
16
+ return rollbackSteps;
17
+ }
18
+
19
+ const changes = [...diff.changes].reverse();
20
+
21
+ for (const change of changes) {
22
+ const undoSQL = this.generateUndoForChange(change);
23
+ if (undoSQL) {
24
+ rollbackSteps.push({
25
+ sql: undoSQL,
26
+ originalChangeId: change.id,
27
+ changeType: change.changeType,
28
+ objectKey: change.objectKey || change.path,
29
+ isTransactional: change.isTransactional !== false,
30
+ });
31
+ }
32
+ }
33
+
34
+ return rollbackSteps;
35
+ }
36
+
37
+ /**
38
+ * Generate undo SQL for a single change
39
+ * @param {Object} change
40
+ * @returns {string|null}
41
+ */
42
+ generateUndoForChange(change) {
43
+ const changeType = change.changeType;
44
+ const objectType = change.objectType;
45
+ const path = change.objectKey || change.path;
46
+ const schema = change.schema;
47
+ const name = change.name;
48
+
49
+ switch (changeType) {
50
+ case 'CREATE':
51
+ case 'ADD':
52
+ return this.generateUndoForCreate(change, objectType, path);
53
+
54
+ case 'DROP':
55
+ case 'REMOVE':
56
+ return this.generateUndoForDrop(change, objectType, path);
57
+
58
+ case 'ALTER':
59
+ return this.generateUndoForAlter(change, objectType, path);
60
+
61
+ case 'RENAME':
62
+ return this.generateUndoForRename(change, path);
63
+
64
+ case 'RECREATE':
65
+ case 'REPLACE':
66
+ return this.generateUndoForReplace(change, objectType, path);
67
+
68
+ default:
69
+ if (changeType?.startsWith('CREATE')) {
70
+ return this.generateUndoForCreate(change, objectType, path);
71
+ }
72
+ if (changeType?.startsWith('DROP')) {
73
+ return this.generateUndoForDrop(change, objectType, path);
74
+ }
75
+ return `-- CANNOT AUTO-ROLLBACK: Unknown change type "${changeType}" for ${path}`;
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Generate undo for CREATE operations
81
+ */
82
+ generateUndoForCreate(change, objectType, path) {
83
+ switch (objectType) {
84
+ case 'table':
85
+ return `DROP TABLE IF EXISTS ${path} CASCADE;`;
86
+
87
+ case 'index':
88
+ if (change.isConcurrent) {
89
+ return `DROP INDEX CONCURRENTLY IF EXISTS ${path};`;
90
+ }
91
+ return `DROP INDEX IF EXISTS ${path};`;
92
+
93
+ case 'constraint':
94
+ const conTable = change.after?.tableKey || change.schema;
95
+ const conName = change.after?.name || change.name;
96
+ return `ALTER TABLE ${conTable} DROP CONSTRAINT IF EXISTS ${conName};`;
97
+
98
+ case 'view':
99
+ return `DROP VIEW IF EXISTS ${path} CASCADE;`;
100
+
101
+ case 'materializedView':
102
+ return `DROP MATERIALIZED VIEW IF EXISTS ${path} CASCADE;`;
103
+
104
+ case 'function':
105
+ case 'procedure':
106
+ const fnArgs = change.after?.argumentTypes
107
+ ? `(${change.after.argumentTypes.join(', ')})`
108
+ : '';
109
+ return `DROP ${objectType === 'procedure' ? 'PROCEDURE' : 'FUNCTION'} IF EXISTS ${path}${fnArgs} CASCADE;`;
110
+
111
+ case 'trigger':
112
+ const trigTable = change.after?.tableName || change.after?.table;
113
+ const trigName = change.after?.name || change.name;
114
+ return `DROP TRIGGER IF EXISTS ${trigName} ON ${trigTable};`;
115
+
116
+ case 'policy':
117
+ const polTable = change.after?.table;
118
+ const polName = change.after?.name || change.name;
119
+ return `DROP POLICY IF EXISTS ${polName} ON ${polTable};`;
120
+
121
+ case 'type':
122
+ return `DROP TYPE IF EXISTS ${path} CASCADE;`;
123
+
124
+ case 'sequence':
125
+ return `DROP SEQUENCE IF EXISTS ${path} CASCADE;`;
126
+
127
+ case 'schema':
128
+ return `DROP SCHEMA IF EXISTS ${change.after?.name || change.name} CASCADE;`;
129
+
130
+ case 'extension':
131
+ return `DROP EXTENSION IF EXISTS ${change.after?.name || change.name} CASCADE;`;
132
+
133
+ case 'rule':
134
+ const ruleTable = change.after?.tableName || change.after?.table;
135
+ const ruleName = change.after?.name || change.name;
136
+ return `DROP RULE IF EXISTS ${ruleName} ON ${ruleTable};`;
137
+
138
+ default:
139
+ return `-- CANNOT AUTO-ROLLBACK: CREATE for object type "${objectType}" on ${path}`;
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Generate undo for DROP operations
145
+ */
146
+ generateUndoForDrop(change, objectType, path) {
147
+ switch (objectType) {
148
+ case 'table':
149
+ return `-- CANNOT ROLLBACK: Table ${path} was dropped. Data cannot be recovered.`;
150
+
151
+ case 'column':
152
+ return `-- CANNOT FULLY ROLLBACK: Column ${path} was dropped. Data cannot be recovered.`;
153
+
154
+ case 'constraint':
155
+ return `-- CANNOT ROLLBACK: Constraint ${path} was dropped. Recreate manually with original definition.`;
156
+
157
+ case 'index':
158
+ return `-- CANNOT ROLLBACK: Index ${path} was dropped. Recreate manually with original definition.`;
159
+
160
+ case 'view':
161
+ case 'materializedView':
162
+ return `-- CANNOT ROLLBACK: ${objectType} ${path} was dropped. Recreate manually.`;
163
+
164
+ case 'function':
165
+ case 'procedure':
166
+ return `-- CANNOT ROLLBACK: ${objectType} ${path} was dropped. Recreate manually.`;
167
+
168
+ case 'trigger':
169
+ case 'policy':
170
+ case 'rule':
171
+ return `-- CANNOT ROLLBACK: ${objectType} ${path} was dropped. Recreate manually.`;
172
+
173
+ default:
174
+ return `-- CANNOT AUTO-ROLLBACK: DROP for object type "${objectType}" on ${path}`;
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Generate undo for ALTER operations
180
+ */
181
+ generateUndoForAlter(change, objectType, path) {
182
+ const property = change.property;
183
+ const currentValue = change.currentValue;
184
+ const desiredValue = change.desiredValue;
185
+ const parts = path.split('.');
186
+ const col = parts.pop();
187
+ const table = parts.join('.');
188
+
189
+ switch (property) {
190
+ case 'dataType':
191
+ case 'type':
192
+ return `ALTER TABLE ${table} ALTER COLUMN "${col}" TYPE ${currentValue};`;
193
+
194
+ case 'isNullable':
195
+ case 'notNull':
196
+ if (desiredValue === true || desiredValue === false && currentValue === true) {
197
+ return `ALTER TABLE ${table} ALTER COLUMN "${col}" DROP NOT NULL;`;
198
+ }
199
+ return `ALTER TABLE ${table} ALTER COLUMN "${col}" SET NOT NULL;`;
200
+
201
+ case 'defaultValue':
202
+ case 'default':
203
+ if (desiredValue === null) {
204
+ return `ALTER TABLE ${table} ALTER COLUMN "${col}" SET DEFAULT ${currentValue};`;
205
+ }
206
+ if (currentValue === null) {
207
+ return `ALTER TABLE ${table} ALTER COLUMN "${col}" DROP DEFAULT;`;
208
+ }
209
+ return `ALTER TABLE ${table} ALTER COLUMN "${col}" SET DEFAULT ${currentValue};`;
210
+
211
+ case 'comment':
212
+ if (currentValue) {
213
+ return `COMMENT ON COLUMN ${path} IS '${currentValue.replace(/'/g, "''")}';`;
214
+ }
215
+ return `COMMENT ON COLUMN ${path} IS NULL;`;
216
+
217
+ default:
218
+ return `-- CANNOT AUTO-ROLLBACK: Property "${property}" change on ${path}`;
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Generate undo for RENAME operations
224
+ */
225
+ generateUndoForRename(change, path) {
226
+ const oldName = change.oldName || change.before?.name;
227
+ const newName = change.newName || change.after?.name;
228
+ const objectType = change.objectType;
229
+ const schema = change.schema;
230
+
231
+ switch (objectType) {
232
+ case 'table':
233
+ return `ALTER TABLE ${schema}.${newName} RENAME TO ${oldName};`;
234
+
235
+ case 'column':
236
+ const tableName = change.tableName || change.after?.tableName;
237
+ return `ALTER TABLE ${schema}.${tableName} RENAME COLUMN ${newName} TO ${oldName};`;
238
+
239
+ case 'index':
240
+ return `ALTER INDEX ${schema}.${newName} RENAME TO ${oldName};`;
241
+
242
+ case 'constraint':
243
+ const conTable = change.tableName || change.after?.tableName;
244
+ return `ALTER TABLE ${schema}.${conTable} RENAME CONSTRAINT ${newName} TO ${oldName};`;
245
+
246
+ default:
247
+ return `-- CANNOT AUTO-ROLLBACK: RENAME for object type "${objectType}" on ${path}`;
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Generate undo for REPLACE/RECREATE operations
253
+ */
254
+ generateUndoForReplace(change, objectType, path) {
255
+ const currentValue = change.currentValue || change.before;
256
+ const before = change.before;
257
+
258
+ switch (objectType) {
259
+ case 'view':
260
+ if (currentValue?.definition || before?.definition) {
261
+ return `CREATE OR REPLACE VIEW ${path} AS ${currentValue?.definition || before.definition};`;
262
+ }
263
+ return `-- CANNOT ROLLBACK: View ${path} was replaced. Original definition not available.`;
264
+
265
+ case 'materializedView':
266
+ return `-- CANNOT FULLY ROLLBACK: Materialized view ${path} was recreated. Data would need to be refreshed.`;
267
+
268
+ case 'function':
269
+ case 'procedure':
270
+ if (currentValue?.source || before?.source) {
271
+ return `CREATE OR REPLACE ${objectType === 'procedure' ? 'PROCEDURE' : 'FUNCTION'} ${path} AS $$${currentValue?.source || before.source}$$;`;
272
+ }
273
+ return `-- CANNOT ROLLBACK: ${objectType} ${path} was replaced. Original source not available.`;
274
+
275
+ case 'trigger':
276
+ const trigTable = change.tableName || before?.tableName;
277
+ const trigName = change.name || before?.name;
278
+ return `DROP TRIGGER IF EXISTS ${trigName} ON ${trigTable};`;
279
+
280
+ case 'policy':
281
+ return `-- CANNOT FULLY ROLLBACK: Policy ${path} was recreated. May need manual restoration.`;
282
+
283
+ default:
284
+ return `-- CANNOT AUTO-ROLLBACK: REPLACE for object type "${objectType}" on ${path}`;
285
+ }
286
+ }
287
+
288
+ /**
289
+ * Check if rollback is possible for a change
290
+ * @param {Object} change
291
+ * @returns {{possible: boolean, reason: string}}
292
+ */
293
+ canRollback(change) {
294
+ const changeType = change.changeType;
295
+ const objectType = change.objectType;
296
+
297
+ if (changeType?.startsWith('DROP')) {
298
+ if (objectType === 'table' || objectType === 'column') {
299
+ return { possible: false, reason: 'Data loss - cannot recover dropped data' };
300
+ }
301
+ return { possible: false, reason: 'Definition lost - need original DDL to recreate' };
302
+ }
303
+
304
+ if (changeType === 'ADD_ENUM_VALUES') {
305
+ return { possible: false, reason: 'PostgreSQL cannot remove enum values without recreating type' };
306
+ }
307
+
308
+ return { possible: true, reason: 'Rollback available' };
309
+ }
310
+
311
+ /**
312
+ * Generate full rollback script with comments
313
+ * @param {Object} migration
314
+ * @returns {string}
315
+ */
316
+ generateRollbackScript(migration) {
317
+ const steps = this.generateRollback(migration);
318
+ const lines = [];
319
+
320
+ lines.push(`-- Rollback script for migration: ${migration.migration_id || migration.id}`);
321
+ lines.push(`-- Generated at: ${new Date().toISOString()}`);
322
+ lines.push(`-- WARNING: This is a best-effort rollback. Some changes cannot be reversed.`);
323
+ lines.push('');
324
+ lines.push('BEGIN;');
325
+ lines.push('');
326
+
327
+ for (const step of steps) {
328
+ if (step.sql.startsWith('--')) {
329
+ lines.push(`-- Step ${step.originalChangeId}: (cannot rollback)`);
330
+ lines.push(`-- ${step.sql.replace(/^-- /, '')}`);
331
+ } else {
332
+ lines.push(`-- Rollback step ${step.originalChangeId}: ${step.changeType} ${step.objectKey}`);
333
+ lines.push(step.sql);
334
+ }
335
+ lines.push('');
336
+ }
337
+
338
+ lines.push('COMMIT;');
339
+ lines.push('');
340
+ lines.push('-- End of rollback script');
341
+
342
+ return lines.join('\n');
343
+ }
344
+ }
@@ -0,0 +1,136 @@
1
+ /**
2
+ * @typedef {'CREATE'|'DROP'|'ALTER'|'RENAME'|'COMMENT'|'ADD_COLUMN'|'DROP_COLUMN'|'ALTER_COLUMN'|'ADD_CONSTRAINT'|'DROP_CONSTRAINT'|'ALTER_CONSTRAINT'|'ADD_INDEX'|'DROP_INDEX'|'ADD_TRIGGER'|'DROP_TRIGGER'|'ADD_POLICY'|'DROP_POLICY'|'ADD_EXTENSION'|'DROP_EXTENSION'|'ADD_FUNCTION'|'DROP_FUNCTION'|'ALTER_FUNCTION'|'ADD_VIEW'|'DROP_VIEW'|'ALTER_VIEW'|'ADD_TYPE'|'DROP_TYPE'|'ALTER_TYPE'|'ADD_SEQUENCE'|'DROP_SEQUENCE'|'ALTER_SEQUENCE'|'ADD_SCHEMA'|'DROP_SCHEMA'|'GRANT'|'REVOKE'|'IMPOSSIBLE_CAST'|'UNSAFE_CAST'|'NARROWING_CAST'|'SAFE_CAST'|'RECREATE_MATERIALIZED_VIEW'|'ADD_ENUM_VALUES'|'REMOVE_ENUM_VALUES'} ChangeType
3
+ */
4
+
5
+ /**
6
+ * @typedef {'none'|'low'|'medium'|'high'|'critical'} RiskLevel
7
+ */
8
+
9
+ /**
10
+ * @typedef {Object} RiskInfo
11
+ * @property {RiskLevel} level
12
+ * @property {string[]} categories - e.g., ['data_loss', 'lock_hazard']
13
+ * @property {string[]} warnings
14
+ * @property {boolean} safePatternAvailable
15
+ * @property {boolean} requiresDowntime
16
+ * @property {string|null} estimatedDuration
17
+ */
18
+
19
+ /**
20
+ * @typedef {Object} ChangeWarning
21
+ * @property {string} code
22
+ * @property {string} message
23
+ * @property {string} [changeKey]
24
+ * @property {'info'|'warning'|'high'|'critical'} severity
25
+ * @property {string} [reason]
26
+ * @property {string[]} [suggestions]
27
+ */
28
+
29
+ /**
30
+ * @typedef {Object} SchemaChange
31
+ * @property {string} id - Unique change ID
32
+ * @property {ChangeType} changeType - Type of change
33
+ * @property {string} objectType - Object type (table, column, index, etc.)
34
+ * @property {string} objectKey - Fully qualified key (e.g., "public.users.email")
35
+ * @property {string} [schema] - Schema name
36
+ * @property {string} [name] - Object name
37
+ * @property {string} [property] - Property being changed (for ALTERs)
38
+ * @property {*} [before] - Current value
39
+ * @property {*} [after] - Desired value
40
+ * @property {*} [currentValue] - Current property value (property-level diff)
41
+ * @property {*} [desiredValue] - Desired property value (property-level diff)
42
+ * @property {number} track - 1 = structural, 2 = behavioral
43
+ * @property {number} phase - Execution phase (1-25)
44
+ * @property {string} ddlStrategy - How to generate DDL (CREATE, ALTER, DROP, etc.)
45
+ * @property {string[]} dependencies - ObjectKeys this change depends on
46
+ * @property {string[]} dependents - ObjectKeys that depend on this change
47
+ * @property {RiskInfo} risk - Risk assessment
48
+ * @property {boolean} [isNonTransactional] - Cannot run in transaction
49
+ * @property {boolean} [requiresRecreation] - Object must be dropped and recreated
50
+ * @property {boolean} [safePatternAvailable] - Has a non-blocking alternative
51
+ * @property {number|null} [pgVersionMinimum] - Minimum PG version (e.g., 14 means PG 14+)
52
+ * @property {boolean} [dataLossRisk] - This change may lose data
53
+ * @property {string[]} [collateralDamage] - Other objects affected
54
+ * @property {boolean} [isRename] - Is a rename change
55
+ * @property {string} [renameFrom] - Original name if rename
56
+ * @property {string} [renameTo] - New name if rename
57
+ * @property {number} [confidence] - Rename detection confidence (0-1)
58
+ * @property {boolean} [confirmed] - Rename confirmed by user
59
+ * @property {string} [sql] - Generated SQL (filled by DDL generator)
60
+ * @property {Record<string,*>} [metadata] - Additional metadata
61
+ */
62
+
63
+ /**
64
+ * @typedef {Object} ObjectMatch
65
+ * @property {string} objectType
66
+ * @property {string} key
67
+ * @property {*} [object] - The object definition
68
+ * @property {*} [desired] - Desired snapshot object
69
+ * @property {*} [current] - Current snapshot object
70
+ * @property {number} [similarity] - Match similarity score
71
+ */
72
+
73
+ /**
74
+ * @typedef {Object} RenameMatch
75
+ * @property {string} objectType
76
+ * @property {string} key
77
+ * @property {string} oldName
78
+ * @property {string} newName
79
+ * @property {number} confidence - 0-1
80
+ * @property {boolean} confirmed - Was rename confirmed by user?
81
+ * @property {*} [object]
82
+ */
83
+
84
+ /**
85
+ * @typedef {Object} MatchedObjects
86
+ * @property {ObjectMatch[]} creates - Objects only in desired
87
+ * @property {ObjectMatch[]} drops - Objects only in current
88
+ * @property {ObjectMatch[]} matches - Objects in both (property diff needed)
89
+ * @property {RenameMatch[]} renames - Detected renames (unconfirmed)
90
+ */
91
+
92
+ /**
93
+ * @typedef {Object} DependencyNode
94
+ * @property {string} key
95
+ * @property {string} objectType
96
+ * @property {string[]} dependencies
97
+ * @property {string[]} dependents
98
+ */
99
+
100
+ /**
101
+ * @typedef {Object} DependencyGraph
102
+ * @property {Map<string, DependencyNode>} nodes
103
+ * @property {string[][]} cycles - Detected cycles
104
+ */
105
+
106
+ /**
107
+ * @typedef {Object} ChangeSummary
108
+ * @property {number} totalChanges
109
+ * @property {number} creates
110
+ * @property {number} drops
111
+ * @property {number} alters
112
+ * @property {number} renames
113
+ * @property {number} recreates
114
+ * @property {number} replaces
115
+ * @property {Object} byTrack
116
+ * @property {Object} byPhase
117
+ * @property {Object} byObjectType
118
+ * @property {Object} riskSummary
119
+ * @property {boolean} requiresDowntime
120
+ * @property {string} estimatedDuration
121
+ */
122
+
123
+ /**
124
+ * @typedef {Object} SchemaDiff
125
+ * @property {ChangeSummary} summary
126
+ * @property {SchemaChange[]} changes
127
+ * @property {ChangeWarning[]} warnings
128
+ * @property {DependencyGraph} dependencyGraph
129
+ * @property {Object} metadata
130
+ * @property {number} metadata.diffDuration
131
+ * @property {number} metadata.pgVersion
132
+ * @property {string} [metadata.desiredChecksum]
133
+ * @property {string} [metadata.currentChecksum]
134
+ */
135
+
136
+ export {};
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @typedef {Object} ConnectionConfig
3
+ * @property {string} host
4
+ * @property {number} port
5
+ * @property {string} database
6
+ * @property {string} user
7
+ * @property {string} password
8
+ * @property {boolean|{ca:string,cert:string,key:string}} [ssl]
9
+ * @property {string[]} [schema]
10
+ * @property {Record<string,string>} [options]
11
+ */
12
+
13
+ /**
14
+ * @typedef {ConnectionConfig & {maxConnections?:number,idleTimeoutMs?:number,connectionTimeoutMs?:number}} PoolConfig
15
+ */
16
+
17
+ export {};
@@ -0,0 +1,107 @@
1
+ /**
2
+ * @typedef {Object} ExecutionOptions
3
+ * @property {boolean} [dryRun]
4
+ * @property {boolean} [force]
5
+ * @property {number} [statementTimeoutMs]
6
+ * @property {number} [batchSize]
7
+ * @property {number} [sleepMs]
8
+ * @property {function(string, string):void} [onProgress]
9
+ * @property {string} [resumeFrom]
10
+ */
11
+
12
+ /**
13
+ * @typedef {Object} PlanOptions
14
+ * @property {string} [name]
15
+ * @property {string} [description]
16
+ * @property {string} sourceChecksum
17
+ * @property {string} targetChecksum
18
+ * @property {boolean} [safeMode]
19
+ * @property {number} [batchSize]
20
+ * @property {number} [sleepMs]
21
+ */
22
+
23
+ /**
24
+ * @typedef {Object} MigrationOptions
25
+ * @property {string} [name]
26
+ * @property {boolean} [dryRun]
27
+ * @property {boolean} [force]
28
+ * @property {boolean} [safeMode]
29
+ * @property {number} [statementTimeoutMs]
30
+ * @property {number} [batchSize]
31
+ * @property {number} [sleepMs]
32
+ * @property {function(string, string):void} [onProgress]
33
+ */
34
+
35
+ /**
36
+ * @typedef {Object} DdlOptions
37
+ * @property {number} [pgVersion]
38
+ * @property {boolean} [safeMode]
39
+ * @property {boolean} [includeComments]
40
+ * @property {boolean} [includeGrants]
41
+ */
42
+
43
+ /**
44
+ * @typedef {Object} DriftResult
45
+ * @property {boolean} hasDrift
46
+ * @property {import('./changes.js').SchemaChange[]} changes
47
+ * @property {string} [resolution]
48
+ */
49
+
50
+ /**
51
+ * @typedef {Object} RecoveryResult
52
+ * @property {string} action
53
+ * @property {string} message
54
+ */
55
+
56
+ /**
57
+ * @typedef {Object} MigrationRecord
58
+ * @property {string} id
59
+ * @property {string} name
60
+ * @property {string} checksum
61
+ * @property {'PENDING'|'RUNNING'|'COMPLETED'|'FAILED'|'STALE'} status
62
+ * @property {MigrationPlan} plan
63
+ * @property {MigrationResult} [result]
64
+ * @property {string} [snapshotBefore]
65
+ * @property {string} [snapshotAfter]
66
+ * @property {string} [appliedAt]
67
+ * @property {string} [appliedBy]
68
+ * @property {number} [durationMs]
69
+ * @property {string} createdAt
70
+ */
71
+
72
+ /**
73
+ * @typedef {Object} EngineConfig
74
+ * @property {import('./connection.js').PoolConfig} connection
75
+ * @property {StorageProvider} [storage]
76
+ * @property {boolean} [safeMode]
77
+ * @property {number} [defaultBatchSize]
78
+ * @property {number} [defaultSleepMs]
79
+ * @property {number} [statementTimeoutMs]
80
+ */
81
+
82
+ /**
83
+ * @typedef {Object} BackfillOptions
84
+ * @property {string} table
85
+ * @property {string} fromColumn
86
+ * @property {string} toColumn
87
+ * @property {string} transform
88
+ * @property {number} batchSize
89
+ * @property {number} rateLimitMs
90
+ * @property {string} pkColumn
91
+ */
92
+
93
+ /**
94
+ * @typedef {Object} StorageProvider
95
+ * @property {function(string, import('./schema.js').SchemaModel):Promise<void>} saveSnapshot
96
+ * @property {function(string):Promise<import('./schema.js').SchemaModel>} loadSnapshot
97
+ * @property {function():Promise<Array<{checksum:string,timestamp:string}>>} listSnapshots
98
+ * @property {function(MigrationRecord):Promise<void>} saveMigration
99
+ * @property {function(string):Promise<MigrationRecord|null>} getMigration
100
+ * @property {function():Promise<MigrationRecord|null>} getLatestMigration
101
+ * @property {function():Promise<MigrationRecord[]>} getMigrationHistory
102
+ * @property {function(string,string):Promise<void>} saveMigrationFile
103
+ * @property {function(string):Promise<string>} loadMigrationFile
104
+ * @property {function():Promise<string[]>} listMigrationFiles
105
+ */
106
+
107
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @typedef {Object} MigrationPlan
3
+ * @property {string} id
4
+ * @property {string} name
5
+ * @property {string} [description]
6
+ * @property {string} createdAt
7
+ * @property {string} sourceChecksum
8
+ * @property {string} targetChecksum
9
+ * @property {import('./changes.js').SchemaChange[]} changes
10
+ * @property {MigrationStep[]} steps
11
+ * @property {import('./risk.js').RiskAssessment} riskAssessment
12
+ * @property {number} [estimatedDurationMs]
13
+ * @property {boolean} isReversible
14
+ * @property {MigrationPlan} [reversePlan]
15
+ */
16
+
17
+ /**
18
+ * @typedef {'pre_check'|'advisory_lock'|'pre_structural'|'structural'|'index'|'data_migration'|'constraint'|'post_structural'|'policy'|'grant'|'cleanup'|'snapshot'|'verify'} StepType
19
+ */
20
+
21
+ /**
22
+ * @typedef {Object} MigrationStep
23
+ * @property {string} id
24
+ * @property {StepType} type
25
+ * @property {number} phase
26
+ * @property {string} description
27
+ * @property {string} sql
28
+ * @property {boolean} isTransactional
29
+ * @property {number} [timeoutMs]
30
+ * @property {number} [retryCount]
31
+ * @property {import('./risk.js').RiskLevel} riskLevel
32
+ * @property {string[]} dependencies
33
+ * @property {number} [estimatedRows]
34
+ */
35
+
36
+ /**
37
+ * @typedef {Object} MigrationResult
38
+ * @property {boolean} success
39
+ * @property {string} migrationId
40
+ * @property {number} stepsCompleted
41
+ * @property {number} stepsTotal
42
+ * @property {number} durationMs
43
+ * @property {number} changesApplied
44
+ * @property {MigrationWarning[]} warnings
45
+ * @property {MigrationError[]} errors
46
+ * @property {string} [snapshotBefore]
47
+ * @property {string} [snapshotAfter]
48
+ */
49
+
50
+ /**
51
+ * @typedef {Object} MigrationWarning
52
+ * @property {string} step
53
+ * @property {string} message
54
+ * @property {import('./risk.js').RiskLevel} severity
55
+ */
56
+
57
+ /**
58
+ * @typedef {Object} MigrationError
59
+ * @property {string} step
60
+ * @property {string} message
61
+ * @property {string} sql
62
+ * @property {string} [code]
63
+ * @property {boolean} isRecoverable
64
+ * @property {string} [recoveryHint]
65
+ */
66
+
67
+ export {};