@lyku/lockstep-pg 0.1.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/LLMs.md +86 -0
- package/README.md +93 -0
- package/package.json +32 -0
- package/src/buildTableIndexCommand.d.ts +3 -0
- package/src/buildTableIndexCommand.d.ts.map +1 -0
- package/src/buildTableIndexCommand.js +46 -0
- package/src/buildTableIndexCommand.js.map +1 -0
- package/src/buildTableTriggerCommands.d.ts +3 -0
- package/src/buildTableTriggerCommands.d.ts.map +1 -0
- package/src/buildTableTriggerCommands.js +23 -0
- package/src/buildTableTriggerCommands.js.map +1 -0
- package/src/createTable.d.ts +3 -0
- package/src/createTable.d.ts.map +1 -0
- package/src/createTable.js +46 -0
- package/src/createTable.js.map +1 -0
- package/src/dateToPostgresString.d.ts +2 -0
- package/src/dateToPostgresString.d.ts.map +1 -0
- package/src/dateToPostgresString.js +7 -0
- package/src/dateToPostgresString.js.map +1 -0
- package/src/diff.d.ts +82 -0
- package/src/diff.d.ts.map +1 -0
- package/src/diff.js +218 -0
- package/src/diff.js.map +1 -0
- package/src/drift.d.ts +16 -0
- package/src/drift.d.ts.map +1 -0
- package/src/drift.js +299 -0
- package/src/drift.js.map +1 -0
- package/src/form.d.ts +3 -0
- package/src/form.d.ts.map +1 -0
- package/src/form.js +9 -0
- package/src/form.js.map +1 -0
- package/src/generateSql.d.ts +16 -0
- package/src/generateSql.d.ts.map +1 -0
- package/src/generateSql.js +306 -0
- package/src/generateSql.js.map +1 -0
- package/src/index.d.ts +16 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +21 -0
- package/src/index.js.map +1 -0
- package/src/introspect.d.ts +56 -0
- package/src/introspect.d.ts.map +1 -0
- package/src/introspect.js +435 -0
- package/src/introspect.js.map +1 -0
- package/src/mapArrayType.d.ts +3 -0
- package/src/mapArrayType.d.ts.map +1 -0
- package/src/mapArrayType.js +41 -0
- package/src/mapArrayType.js.map +1 -0
- package/src/mapBigintType.d.ts +3 -0
- package/src/mapBigintType.d.ts.map +1 -0
- package/src/mapBigintType.js +17 -0
- package/src/mapBigintType.js.map +1 -0
- package/src/mapBigserialType.d.ts +3 -0
- package/src/mapBigserialType.d.ts.map +1 -0
- package/src/mapBigserialType.js +12 -0
- package/src/mapBigserialType.js.map +1 -0
- package/src/mapCharType.d.ts +3 -0
- package/src/mapCharType.d.ts.map +1 -0
- package/src/mapCharType.js +22 -0
- package/src/mapCharType.js.map +1 -0
- package/src/mapColumnType.d.ts +3 -0
- package/src/mapColumnType.d.ts.map +1 -0
- package/src/mapColumnType.js +63 -0
- package/src/mapColumnType.js.map +1 -0
- package/src/mapIntegerType.d.ts +3 -0
- package/src/mapIntegerType.d.ts.map +1 -0
- package/src/mapIntegerType.js +12 -0
- package/src/mapIntegerType.js.map +1 -0
- package/src/mapSerialType.d.ts +3 -0
- package/src/mapSerialType.d.ts.map +1 -0
- package/src/mapSerialType.js +12 -0
- package/src/mapSerialType.js.map +1 -0
- package/src/mapTextType.d.ts +3 -0
- package/src/mapTextType.d.ts.map +1 -0
- package/src/mapTextType.js +44 -0
- package/src/mapTextType.js.map +1 -0
- package/src/mapTimestamptzType.d.ts +3 -0
- package/src/mapTimestamptzType.d.ts.map +1 -0
- package/src/mapTimestamptzType.js +13 -0
- package/src/mapTimestamptzType.js.map +1 -0
- package/src/mapVarcharType.d.ts +3 -0
- package/src/mapVarcharType.d.ts.map +1 -0
- package/src/mapVarcharType.js +44 -0
- package/src/mapVarcharType.js.map +1 -0
- package/src/migrate.d.ts +13 -0
- package/src/migrate.d.ts.map +1 -0
- package/src/migrate.js +350 -0
- package/src/migrate.js.map +1 -0
- package/src/numberChecks.d.ts +11 -0
- package/src/numberChecks.d.ts.map +1 -0
- package/src/numberChecks.js +22 -0
- package/src/numberChecks.js.map +1 -0
- package/src/seed.d.ts +3 -0
- package/src/seed.d.ts.map +1 -0
- package/src/seed.js +56 -0
- package/src/seed.js.map +1 -0
- package/src/setupTable.d.ts +3 -0
- package/src/setupTable.d.ts.map +1 -0
- package/src/setupTable.js +41 -0
- package/src/setupTable.js.map +1 -0
- package/src/timestampChecks.d.ts +11 -0
- package/src/timestampChecks.d.ts.map +1 -0
- package/src/timestampChecks.js +22 -0
- package/src/timestampChecks.js.map +1 -0
package/src/diff.js
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diff two table models and generate migration operations
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Check if two sets of columns match (order-independent)
|
|
6
|
+
*/
|
|
7
|
+
function columnsMatch(a, b) {
|
|
8
|
+
if (a.length !== b.length)
|
|
9
|
+
return false;
|
|
10
|
+
const sortedA = [...a].sort();
|
|
11
|
+
const sortedB = [...b].sort();
|
|
12
|
+
// eslint-disable-next-line security/detect-object-injection -- i is a controlled array index
|
|
13
|
+
return sortedA.every((col, i) => col === sortedB[i]);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Check if two enum value arrays are equivalent
|
|
17
|
+
*/
|
|
18
|
+
function enumValuesMatch(a, b) {
|
|
19
|
+
if (a === null && b === null)
|
|
20
|
+
return true;
|
|
21
|
+
if (a === null || b === null)
|
|
22
|
+
return false;
|
|
23
|
+
if (a.length !== b.length)
|
|
24
|
+
return false;
|
|
25
|
+
const sortedA = [...a].sort();
|
|
26
|
+
const sortedB = [...b].sort();
|
|
27
|
+
// eslint-disable-next-line security/detect-object-injection -- i is a controlled array index
|
|
28
|
+
return sortedA.every((v, i) => v === sortedB[i]);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Diff a single column
|
|
32
|
+
*/
|
|
33
|
+
function diffColumn(tableName, dbCol, codeCol) {
|
|
34
|
+
const ops = [];
|
|
35
|
+
// Column doesn't exist in DB but exists in code -> add
|
|
36
|
+
if (!dbCol && codeCol) {
|
|
37
|
+
ops.push({ type: 'add_column', tableName, column: codeCol });
|
|
38
|
+
return ops;
|
|
39
|
+
}
|
|
40
|
+
// Column exists in DB but not in code -> drop
|
|
41
|
+
if (dbCol && !codeCol) {
|
|
42
|
+
ops.push({ type: 'drop_column', tableName, columnName: dbCol.name });
|
|
43
|
+
return ops;
|
|
44
|
+
}
|
|
45
|
+
// Both exist -> compare properties
|
|
46
|
+
if (dbCol && codeCol) {
|
|
47
|
+
// Type mismatch
|
|
48
|
+
if (dbCol.type !== codeCol.type) {
|
|
49
|
+
ops.push({
|
|
50
|
+
type: 'alter_column_type',
|
|
51
|
+
tableName,
|
|
52
|
+
columnName: dbCol.name,
|
|
53
|
+
fromType: dbCol.type,
|
|
54
|
+
toType: codeCol.type,
|
|
55
|
+
toArrayItemType: codeCol.arrayItemType,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
// Nullable mismatch
|
|
59
|
+
if (dbCol.nullable !== codeCol.nullable) {
|
|
60
|
+
ops.push({
|
|
61
|
+
type: 'alter_column_nullable',
|
|
62
|
+
tableName,
|
|
63
|
+
columnName: dbCol.name,
|
|
64
|
+
nullable: codeCol.nullable,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
// Enum values mismatch (CHECK constraint)
|
|
68
|
+
if (!enumValuesMatch(dbCol.enumValues, codeCol.enumValues)) {
|
|
69
|
+
ops.push({
|
|
70
|
+
type: 'update_check_constraint',
|
|
71
|
+
tableName,
|
|
72
|
+
columnName: dbCol.name,
|
|
73
|
+
oldValues: dbCol.enumValues ?? [],
|
|
74
|
+
newValues: codeCol.enumValues ?? [],
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return ops;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Diff indexes between DB and code
|
|
82
|
+
*/
|
|
83
|
+
function diffIndexes(tableName, dbIndexes, codeIndexes) {
|
|
84
|
+
const ops = [];
|
|
85
|
+
// Skip primary key indexes (named like tableName_pkey)
|
|
86
|
+
const dbNonPk = dbIndexes.filter((i) => !i.name.endsWith('_pkey') && !i.name.includes('_pkey'));
|
|
87
|
+
// Find indexes in code that don't exist in DB
|
|
88
|
+
for (const codeIdx of codeIndexes) {
|
|
89
|
+
const found = dbNonPk.some((dbIdx) => columnsMatch(dbIdx.columns, codeIdx.columns));
|
|
90
|
+
if (!found) {
|
|
91
|
+
ops.push({ type: 'add_index', tableName, index: codeIdx });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Note: We don't drop extra indexes by default as they may be intentional
|
|
95
|
+
// performance optimizations added manually
|
|
96
|
+
return ops;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Diff unique constraints
|
|
100
|
+
*/
|
|
101
|
+
function diffUniqueConstraints(tableName, dbUnique, codeUnique) {
|
|
102
|
+
const ops = [];
|
|
103
|
+
// Find constraints in code that don't exist in DB
|
|
104
|
+
for (const codeCols of codeUnique) {
|
|
105
|
+
const found = dbUnique.some((dbCols) => columnsMatch(dbCols, codeCols));
|
|
106
|
+
if (!found) {
|
|
107
|
+
ops.push({ type: 'add_unique_constraint', tableName, columns: codeCols });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return ops;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Diff two tables and generate operations needed to migrate DB to match code
|
|
114
|
+
*/
|
|
115
|
+
export function diffTable(dbTable, codeTable) {
|
|
116
|
+
const ops = [];
|
|
117
|
+
// Table doesn't exist in DB but exists in code -> create
|
|
118
|
+
if (!dbTable && codeTable) {
|
|
119
|
+
ops.push({ type: 'create_table', table: codeTable });
|
|
120
|
+
return ops;
|
|
121
|
+
}
|
|
122
|
+
// Table exists in DB but not in code -> drop (dangerous!)
|
|
123
|
+
if (dbTable && !codeTable) {
|
|
124
|
+
ops.push({ type: 'drop_table', tableName: dbTable.name });
|
|
125
|
+
return ops;
|
|
126
|
+
}
|
|
127
|
+
// Both exist -> diff columns, indexes, constraints
|
|
128
|
+
if (dbTable && codeTable) {
|
|
129
|
+
const tableName = dbTable.name;
|
|
130
|
+
// Get all column names from both
|
|
131
|
+
const allColumns = new Set([
|
|
132
|
+
...dbTable.columns.keys(),
|
|
133
|
+
...codeTable.columns.keys(),
|
|
134
|
+
]);
|
|
135
|
+
for (const colName of allColumns) {
|
|
136
|
+
const dbCol = dbTable.columns.get(colName);
|
|
137
|
+
const codeCol = codeTable.columns.get(colName);
|
|
138
|
+
ops.push(...diffColumn(tableName, dbCol, codeCol));
|
|
139
|
+
}
|
|
140
|
+
// Diff indexes
|
|
141
|
+
ops.push(...diffIndexes(tableName, dbTable.indexes, codeTable.indexes));
|
|
142
|
+
// Diff unique constraints
|
|
143
|
+
ops.push(...diffUniqueConstraints(tableName, dbTable.uniqueConstraints, codeTable.uniqueConstraints));
|
|
144
|
+
// Diff foreign keys
|
|
145
|
+
const dbFks = dbTable.foreignKeys ?? [];
|
|
146
|
+
const codeFks = codeTable.foreignKeys ?? [];
|
|
147
|
+
// Find FKs to add (in code but not in DB)
|
|
148
|
+
for (const codeFk of codeFks) {
|
|
149
|
+
const existing = dbFks.find((dbFk) => dbFk.column === codeFk.column &&
|
|
150
|
+
dbFk.referencedTable === codeFk.referencedTable &&
|
|
151
|
+
dbFk.referencedColumn === codeFk.referencedColumn);
|
|
152
|
+
if (!existing) {
|
|
153
|
+
ops.push({ type: 'add_foreign_key', tableName, fk: codeFk });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Find FKs to drop (in DB but not in code)
|
|
157
|
+
for (const dbFk of dbFks) {
|
|
158
|
+
const existing = codeFks.find((codeFk) => codeFk.column === dbFk.column &&
|
|
159
|
+
codeFk.referencedTable === dbFk.referencedTable &&
|
|
160
|
+
codeFk.referencedColumn === dbFk.referencedColumn);
|
|
161
|
+
if (!existing) {
|
|
162
|
+
ops.push({
|
|
163
|
+
type: 'drop_foreign_key',
|
|
164
|
+
tableName,
|
|
165
|
+
constraintName: dbFk.constraintName,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return ops;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Diff entire database against code models
|
|
174
|
+
*/
|
|
175
|
+
export function diffDatabase(dbTables, codeTables) {
|
|
176
|
+
const ops = [];
|
|
177
|
+
// Get all table names from both
|
|
178
|
+
const allTables = new Set([...dbTables.keys(), ...codeTables.keys()]);
|
|
179
|
+
for (const tableName of allTables) {
|
|
180
|
+
const dbTable = dbTables.get(tableName);
|
|
181
|
+
const codeTable = codeTables.get(tableName);
|
|
182
|
+
ops.push(...diffTable(dbTable, codeTable));
|
|
183
|
+
}
|
|
184
|
+
return ops;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Categorize operations into safe and destructive
|
|
188
|
+
*/
|
|
189
|
+
export function categorizeOperations(ops) {
|
|
190
|
+
const safe = [];
|
|
191
|
+
const destructive = [];
|
|
192
|
+
for (const op of ops) {
|
|
193
|
+
switch (op.type) {
|
|
194
|
+
case 'create_table':
|
|
195
|
+
case 'add_column':
|
|
196
|
+
case 'add_index':
|
|
197
|
+
case 'add_unique_constraint':
|
|
198
|
+
case 'update_check_constraint':
|
|
199
|
+
safe.push(op);
|
|
200
|
+
break;
|
|
201
|
+
case 'drop_table':
|
|
202
|
+
case 'drop_column':
|
|
203
|
+
case 'drop_index':
|
|
204
|
+
case 'drop_unique_constraint':
|
|
205
|
+
destructive.push(op);
|
|
206
|
+
break;
|
|
207
|
+
case 'alter_column_type':
|
|
208
|
+
case 'alter_column_nullable':
|
|
209
|
+
case 'alter_column_default':
|
|
210
|
+
// These can be safe or destructive depending on the change
|
|
211
|
+
// For now, treat as safe but with warning
|
|
212
|
+
safe.push(op);
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return { safe, destructive };
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=diff.js.map
|
package/src/diff.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../../../libs/lockstep-pg/src/diff.ts"],"names":[],"mappings":"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"}
|
package/src/drift.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PostgresRecordModel, PostgresTableModel } from '@lyku/lockstep-core';
|
|
2
|
+
export interface Drift {
|
|
3
|
+
type: 'missing_table' | 'extra_table' | 'missing_column' | 'extra_column' | 'column_type_mismatch' | 'nullable_mismatch' | 'missing_index' | 'extra_index' | 'missing_constraint' | 'extra_constraint' | 'check_constraint_mismatch' | 'missing_stock_doc';
|
|
4
|
+
table: string;
|
|
5
|
+
details: string;
|
|
6
|
+
column?: string;
|
|
7
|
+
expected?: string;
|
|
8
|
+
actual?: string;
|
|
9
|
+
constraintName?: string;
|
|
10
|
+
docId?: string | number;
|
|
11
|
+
}
|
|
12
|
+
export interface DataformConfig {
|
|
13
|
+
tables: Record<string, PostgresTableModel<PostgresRecordModel>>;
|
|
14
|
+
}
|
|
15
|
+
export declare function detectDrift(connectionString: string, config: DataformConfig): Promise<Drift[]>;
|
|
16
|
+
//# sourceMappingURL=drift.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drift.d.ts","sourceRoot":"","sources":["../../../../libs/lockstep-pg/src/drift.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEX,mBAAmB,EACnB,kBAAkB,EAClB,MAAM,qBAAqB,CAAC;AAqB7B,MAAM,WAAW,KAAK;IACrB,IAAI,EACD,eAAe,GACf,aAAa,GACb,gBAAgB,GAChB,cAAc,GACd,sBAAsB,GACtB,mBAAmB,GACnB,eAAe,GACf,aAAa,GACb,oBAAoB,GACpB,kBAAkB,GAClB,2BAA2B,GAC3B,mBAAmB,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AA4CD,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,mBAAmB,CAAC,CAAC,CAAC;CAChE;AAED,wBAAsB,WAAW,CAChC,gBAAgB,EAAE,MAAM,EACxB,MAAM,EAAE,cAAc,GACpB,OAAO,CAAC,KAAK,EAAE,CAAC,CA2SlB"}
|
package/src/drift.js
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { Client } from 'pg';
|
|
2
|
+
// Normalize postgres type names for comparison
|
|
3
|
+
function normalizeType(pgType) {
|
|
4
|
+
const lower = pgType.toLowerCase();
|
|
5
|
+
if (lower === 'bigint' || lower === 'int8')
|
|
6
|
+
return 'bigint';
|
|
7
|
+
if (lower === 'integer' || lower === 'int' || lower === 'int4')
|
|
8
|
+
return 'integer';
|
|
9
|
+
if (lower === 'smallint' || lower === 'int2')
|
|
10
|
+
return 'smallint';
|
|
11
|
+
if (lower === 'boolean' || lower === 'bool')
|
|
12
|
+
return 'boolean';
|
|
13
|
+
if (lower.startsWith('character varying') || lower === 'varchar')
|
|
14
|
+
return 'text';
|
|
15
|
+
if (lower.startsWith('character(') ||
|
|
16
|
+
lower.startsWith('character') ||
|
|
17
|
+
lower === 'bpchar' ||
|
|
18
|
+
lower === 'char')
|
|
19
|
+
return 'text';
|
|
20
|
+
if (lower === 'text')
|
|
21
|
+
return 'text';
|
|
22
|
+
if (lower === 'double precision' || lower === 'float8')
|
|
23
|
+
return 'double precision';
|
|
24
|
+
if (lower === 'timestamp with time zone' || lower === 'timestamptz')
|
|
25
|
+
return 'timestamptz';
|
|
26
|
+
if (lower === 'timestamp without time zone' || lower === 'timestamp')
|
|
27
|
+
return 'timestamp';
|
|
28
|
+
if (lower === 'jsonb')
|
|
29
|
+
return 'jsonb';
|
|
30
|
+
if (lower === 'numeric' || lower === 'decimal')
|
|
31
|
+
return 'numeric';
|
|
32
|
+
if (lower === 'array' || lower.endsWith('[]'))
|
|
33
|
+
return 'array';
|
|
34
|
+
// user-defined types in Postgres (custom enums) are stored as text with CHECK
|
|
35
|
+
if (lower === 'user-defined')
|
|
36
|
+
return 'text';
|
|
37
|
+
return lower;
|
|
38
|
+
}
|
|
39
|
+
// Get expected type from schema
|
|
40
|
+
function getExpectedType(columnSchema) {
|
|
41
|
+
const t = columnSchema.type;
|
|
42
|
+
if (t === 'bigserial')
|
|
43
|
+
return 'bigint'; // bigserial is stored as bigint
|
|
44
|
+
if (t === 'serial')
|
|
45
|
+
return 'integer'; // serial is stored as integer
|
|
46
|
+
if (t === 'enum')
|
|
47
|
+
return 'text'; // enums are stored as TEXT with CHECK constraint
|
|
48
|
+
if (t === 'char' || t === 'varchar')
|
|
49
|
+
return 'text'; // char/varchar normalize to text
|
|
50
|
+
return normalizeType(t);
|
|
51
|
+
}
|
|
52
|
+
export async function detectDrift(connectionString, config) {
|
|
53
|
+
const client = new Client({
|
|
54
|
+
connectionString,
|
|
55
|
+
ssl: true,
|
|
56
|
+
connectionTimeoutMillis: 30000,
|
|
57
|
+
});
|
|
58
|
+
const drifts = [];
|
|
59
|
+
try {
|
|
60
|
+
await client.connect();
|
|
61
|
+
// Get all tables from database
|
|
62
|
+
const tablesResult = await client.query(`
|
|
63
|
+
SELECT table_name
|
|
64
|
+
FROM information_schema.tables
|
|
65
|
+
WHERE table_schema = 'public'
|
|
66
|
+
AND table_type = 'BASE TABLE'
|
|
67
|
+
`);
|
|
68
|
+
const actualTables = new Set(tablesResult.rows.map((r) => r.table_name));
|
|
69
|
+
const expectedTables = Object.keys(config.tables);
|
|
70
|
+
// Check for missing tables
|
|
71
|
+
for (const tableName of expectedTables) {
|
|
72
|
+
if (!actualTables.has(tableName)) {
|
|
73
|
+
drifts.push({
|
|
74
|
+
type: 'missing_table',
|
|
75
|
+
table: tableName,
|
|
76
|
+
details: `Table "${tableName}" exists in schema but not in database`,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Check for extra tables (not in schema)
|
|
81
|
+
for (const tableName of actualTables) {
|
|
82
|
+
if (!expectedTables.includes(tableName)) {
|
|
83
|
+
drifts.push({
|
|
84
|
+
type: 'extra_table',
|
|
85
|
+
table: tableName,
|
|
86
|
+
details: `Table "${tableName}" exists in database but not in schema`,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// For each expected table that exists, check columns
|
|
91
|
+
for (const [tableName, tableModel] of Object.entries(config.tables)) {
|
|
92
|
+
if (!actualTables.has(tableName))
|
|
93
|
+
continue;
|
|
94
|
+
const schema = tableModel.schema;
|
|
95
|
+
if (!('properties' in schema))
|
|
96
|
+
continue;
|
|
97
|
+
// Get actual columns
|
|
98
|
+
const columnsResult = await client.query(`
|
|
99
|
+
SELECT column_name, data_type, is_nullable, column_default, character_maximum_length
|
|
100
|
+
FROM information_schema.columns
|
|
101
|
+
WHERE table_schema = 'public' AND table_name = $1
|
|
102
|
+
`, [tableName]);
|
|
103
|
+
const actualColumns = new Map(columnsResult.rows.map((r) => [r.column_name, r]));
|
|
104
|
+
const expectedColumns = Object.entries(schema.properties);
|
|
105
|
+
const required = 'required' in schema ? schema.required : [];
|
|
106
|
+
// Check for missing columns
|
|
107
|
+
for (const [columnName, columnSchema] of expectedColumns) {
|
|
108
|
+
const actualCol = actualColumns.get(columnName);
|
|
109
|
+
if (!actualCol) {
|
|
110
|
+
drifts.push({
|
|
111
|
+
type: 'missing_column',
|
|
112
|
+
table: tableName,
|
|
113
|
+
column: columnName,
|
|
114
|
+
details: `Column "${columnName}" missing from table`,
|
|
115
|
+
});
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
// Check type
|
|
119
|
+
const expectedType = getExpectedType(columnSchema);
|
|
120
|
+
const actualType = normalizeType(actualCol.data_type);
|
|
121
|
+
if (expectedType !== actualType) {
|
|
122
|
+
drifts.push({
|
|
123
|
+
type: 'column_type_mismatch',
|
|
124
|
+
table: tableName,
|
|
125
|
+
column: columnName,
|
|
126
|
+
details: `Column "${columnName}" type mismatch`,
|
|
127
|
+
expected: expectedType,
|
|
128
|
+
actual: actualType,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
// Check nullable
|
|
132
|
+
const expectedNullable = !required.includes(columnName);
|
|
133
|
+
const actualNullable = actualCol.is_nullable === 'YES';
|
|
134
|
+
if (expectedNullable !== actualNullable) {
|
|
135
|
+
drifts.push({
|
|
136
|
+
type: 'nullable_mismatch',
|
|
137
|
+
table: tableName,
|
|
138
|
+
column: columnName,
|
|
139
|
+
details: `Column "${columnName}" nullable mismatch`,
|
|
140
|
+
expected: expectedNullable ? 'nullable' : 'not null',
|
|
141
|
+
actual: actualNullable ? 'nullable' : 'not null',
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
actualColumns.delete(columnName);
|
|
145
|
+
}
|
|
146
|
+
// Extra columns (in DB but not schema)
|
|
147
|
+
for (const [columnName] of actualColumns) {
|
|
148
|
+
drifts.push({
|
|
149
|
+
type: 'extra_column',
|
|
150
|
+
table: tableName,
|
|
151
|
+
column: columnName,
|
|
152
|
+
details: `Column "${columnName}" exists in database but not in schema`,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// Check CHECK constraints for enum columns
|
|
156
|
+
const checkConstraintsResult = await client.query(`
|
|
157
|
+
SELECT
|
|
158
|
+
con.conname AS constraint_name,
|
|
159
|
+
att.attname AS column_name,
|
|
160
|
+
pg_get_constraintdef(con.oid) AS check_clause
|
|
161
|
+
FROM pg_constraint con
|
|
162
|
+
JOIN pg_attribute att ON att.attnum = ANY(con.conkey) AND att.attrelid = con.conrelid
|
|
163
|
+
WHERE con.conrelid = $1::regclass
|
|
164
|
+
AND con.contype = 'c'
|
|
165
|
+
`, [`"${tableName}"`]);
|
|
166
|
+
const actualCheckConstraints = new Map();
|
|
167
|
+
for (const row of checkConstraintsResult.rows) {
|
|
168
|
+
if (row.check_clause.includes(' IN (') ||
|
|
169
|
+
row.check_clause.includes('ANY (ARRAY[') ||
|
|
170
|
+
row.check_clause.includes('ANY(ARRAY[')) {
|
|
171
|
+
actualCheckConstraints.set(row.column_name, row);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Compare enum columns with their CHECK constraints
|
|
175
|
+
for (const [columnName, columnSchema] of expectedColumns) {
|
|
176
|
+
const colSchema = columnSchema;
|
|
177
|
+
if (colSchema.type !== 'enum' || !colSchema.enum)
|
|
178
|
+
continue;
|
|
179
|
+
const actualConstraint = actualCheckConstraints.get(columnName);
|
|
180
|
+
if (!actualConstraint) {
|
|
181
|
+
drifts.push({
|
|
182
|
+
type: 'missing_constraint',
|
|
183
|
+
table: tableName,
|
|
184
|
+
column: columnName,
|
|
185
|
+
details: `Missing CHECK constraint for enum column "${columnName}"`,
|
|
186
|
+
expected: colSchema.enum.join(', '),
|
|
187
|
+
});
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
const checkClause = actualConstraint.check_clause;
|
|
191
|
+
const actualValues = [];
|
|
192
|
+
const valueMatches = checkClause.matchAll(/'([^']+)'/g);
|
|
193
|
+
for (const match of valueMatches) {
|
|
194
|
+
if (!match[1].includes('::')) {
|
|
195
|
+
actualValues.push(match[1]);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const expectedSet = new Set(colSchema.enum);
|
|
199
|
+
const actualSet = new Set(actualValues);
|
|
200
|
+
const missing = colSchema.enum.filter((v) => !actualSet.has(v));
|
|
201
|
+
const extra = actualValues.filter((v) => !expectedSet.has(v));
|
|
202
|
+
if (missing.length > 0 || extra.length > 0) {
|
|
203
|
+
drifts.push({
|
|
204
|
+
type: 'check_constraint_mismatch',
|
|
205
|
+
table: tableName,
|
|
206
|
+
column: columnName,
|
|
207
|
+
constraintName: actualConstraint.constraint_name,
|
|
208
|
+
details: `CHECK constraint values mismatch for "${columnName}"`,
|
|
209
|
+
expected: colSchema.enum.join(', '),
|
|
210
|
+
actual: actualValues.join(', '),
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// Check for missing stock documents
|
|
215
|
+
const docs = tableModel.docs;
|
|
216
|
+
if (docs && Array.isArray(docs) && docs.length > 0) {
|
|
217
|
+
const primaryKey = tableModel.primaryKey || 'id';
|
|
218
|
+
for (const doc of docs) {
|
|
219
|
+
if (doc &&
|
|
220
|
+
typeof doc === 'object' &&
|
|
221
|
+
!Array.isArray(doc) &&
|
|
222
|
+
'id' in doc) {
|
|
223
|
+
const docRecord = doc;
|
|
224
|
+
const docId = docRecord['id'];
|
|
225
|
+
const checkResult = await client.query(`SELECT 1 FROM "${tableName}" WHERE "${String(primaryKey)}" = $1 LIMIT 1`, [docId]);
|
|
226
|
+
if (checkResult.rows.length === 0) {
|
|
227
|
+
const docTitle = 'title' in doc
|
|
228
|
+
? docRecord['title']
|
|
229
|
+
: 'name' in doc
|
|
230
|
+
? docRecord['name']
|
|
231
|
+
: 'slug' in doc
|
|
232
|
+
? docRecord['slug']
|
|
233
|
+
: undefined;
|
|
234
|
+
drifts.push({
|
|
235
|
+
type: 'missing_stock_doc',
|
|
236
|
+
table: tableName,
|
|
237
|
+
docId: typeof docId === 'bigint'
|
|
238
|
+
? docId.toString()
|
|
239
|
+
: docId,
|
|
240
|
+
details: `Stock document ${String(primaryKey)}=${docId}${docTitle ? ` (${docTitle})` : ''} missing from table`,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// Check indexes
|
|
247
|
+
const indexesResult = await client.query(`
|
|
248
|
+
SELECT indexname, indexdef
|
|
249
|
+
FROM pg_indexes
|
|
250
|
+
WHERE schemaname = 'public' AND tablename = $1
|
|
251
|
+
`, [tableName]);
|
|
252
|
+
const actualIndexes = new Map(indexesResult.rows.map((r) => [r.indexname, r.indexdef]));
|
|
253
|
+
// Expected indexes from model
|
|
254
|
+
const expectedIndexColumns = tableModel.indexes || [];
|
|
255
|
+
for (const indexCol of expectedIndexColumns) {
|
|
256
|
+
let cols;
|
|
257
|
+
if (typeof indexCol === 'string') {
|
|
258
|
+
cols = [indexCol];
|
|
259
|
+
}
|
|
260
|
+
else if (Array.isArray(indexCol)) {
|
|
261
|
+
cols = indexCol;
|
|
262
|
+
}
|
|
263
|
+
else if (typeof indexCol === 'object' && indexCol !== null) {
|
|
264
|
+
const objIndex = indexCol;
|
|
265
|
+
cols = Array.isArray(objIndex.columns)
|
|
266
|
+
? objIndex.columns
|
|
267
|
+
: [objIndex.columns];
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
let found = false;
|
|
273
|
+
for (const [, indexDef] of actualIndexes) {
|
|
274
|
+
const defLower = indexDef.toLowerCase();
|
|
275
|
+
if (cols.every((c) => {
|
|
276
|
+
const colLower = c.toLowerCase().split(' ')[0];
|
|
277
|
+
return (defLower.includes(`"${colLower}"`) ||
|
|
278
|
+
defLower.includes(colLower));
|
|
279
|
+
})) {
|
|
280
|
+
found = true;
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
if (!found) {
|
|
285
|
+
drifts.push({
|
|
286
|
+
type: 'missing_index',
|
|
287
|
+
table: tableName,
|
|
288
|
+
details: `Missing index on column(s): ${cols.join(', ')}`,
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return drifts;
|
|
294
|
+
}
|
|
295
|
+
finally {
|
|
296
|
+
await client.end();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=drift.js.map
|
package/src/drift.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drift.js","sourceRoot":"","sources":["../../../../libs/lockstep-pg/src/drift.ts"],"names":[],"mappings":"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"}
|
package/src/form.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../../../libs/lockstep-pg/src/form.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAQtE"}
|
package/src/form.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { setupTable } from './setupTable';
|
|
2
|
+
export function generateCreateTablesSql(config) {
|
|
3
|
+
const outputs = [];
|
|
4
|
+
for (const [tableName, table] of Object.entries(config.tables)) {
|
|
5
|
+
outputs.push(setupTable(tableName, table));
|
|
6
|
+
}
|
|
7
|
+
return outputs.join('\n\n');
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=form.js.map
|
package/src/form.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form.js","sourceRoot":"","sources":["../../../../libs/lockstep-pg/src/form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,MAAM,UAAU,uBAAuB,CAAC,MAAsB;IAC7D,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate SQL from diff operations
|
|
3
|
+
*/
|
|
4
|
+
import type { DiffOperation } from './diff';
|
|
5
|
+
/**
|
|
6
|
+
* Convert a single diff operation to SQL
|
|
7
|
+
*/
|
|
8
|
+
export declare function operationToSql(op: DiffOperation): string[];
|
|
9
|
+
/**
|
|
10
|
+
* Generate full migration SQL from operations
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateMigrationSql(ops: DiffOperation[], _includeDestructive?: boolean): {
|
|
13
|
+
safe: string;
|
|
14
|
+
destructive: string;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=generateSql.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateSql.d.ts","sourceRoot":"","sources":["../../../../libs/lockstep-pg/src/generateSql.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AA4K5C;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,aAAa,GAAG,MAAM,EAAE,CAkI1D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CACnC,GAAG,EAAE,aAAa,EAAE,EACpB,mBAAmB,UAAQ,GACzB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAoDvC"}
|