orchid-orm 1.24.7 → 1.25.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/dist/index.d.ts +5 -7
- package/dist/index.js +15 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14 -12
- package/dist/index.mjs.map +1 -1
- package/dist/migrations.d.ts +16 -0
- package/dist/migrations.js +2847 -0
- package/dist/migrations.js.map +1 -0
- package/dist/migrations.mjs +2839 -0
- package/dist/migrations.mjs.map +1 -0
- package/package.json +11 -6
- package/codegen/index.d.ts +0 -41
- package/codegen/index.js +0 -1460
- package/codegen/index.js.map +0 -1
- package/codegen/index.mjs +0 -1439
- package/codegen/index.mjs.map +0 -1
|
@@ -0,0 +1,2847 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var rakeDb = require('rake-db');
|
|
4
|
+
var pqb = require('pqb');
|
|
5
|
+
var orchidCore = require('orchid-core');
|
|
6
|
+
var fs = require('fs/promises');
|
|
7
|
+
var path = require('node:path');
|
|
8
|
+
var typescript = require('typescript');
|
|
9
|
+
|
|
10
|
+
const compareSqlExpressions = async (tableExpressions, adapter) => {
|
|
11
|
+
if (tableExpressions.length) {
|
|
12
|
+
let id = 1;
|
|
13
|
+
await Promise.all(
|
|
14
|
+
tableExpressions.map(async ({ source, compare, handle }) => {
|
|
15
|
+
const viewName = `orchidTmpView${id++}`;
|
|
16
|
+
const values = [];
|
|
17
|
+
try {
|
|
18
|
+
const sql = `CREATE TEMPORARY VIEW ${viewName} AS (SELECT ${compare.map(
|
|
19
|
+
({ inDb: inDb2, inCode }, i) => `${inDb2} AS "*inDb-${i}*", ${inCode.map(
|
|
20
|
+
(s, j) => `(${typeof s === "string" ? s : s.toSQL({ values })}) "*inCode-${i}-${j}*"`
|
|
21
|
+
).join(", ")}`
|
|
22
|
+
).join(", ")} FROM ${source})`;
|
|
23
|
+
await adapter.query({ text: sql, values });
|
|
24
|
+
} catch (err) {
|
|
25
|
+
handle();
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const {
|
|
29
|
+
rows: [{ v }]
|
|
30
|
+
} = await adapter.query(
|
|
31
|
+
`SELECT pg_get_viewdef('${viewName}') v`
|
|
32
|
+
);
|
|
33
|
+
await adapter.query(`DROP VIEW ${viewName}`);
|
|
34
|
+
let pos = 7;
|
|
35
|
+
const rgx = /\s+AS\s+"\*(inDb-\d+|inCode-\d+-\d+)\*",?/g;
|
|
36
|
+
let match;
|
|
37
|
+
let inDb = "";
|
|
38
|
+
let codeI = 0;
|
|
39
|
+
const matches = compare[0].inCode.map(() => true);
|
|
40
|
+
while (match = rgx.exec(v)) {
|
|
41
|
+
const sql = v.slice(pos, rgx.lastIndex - match[0].length).trim();
|
|
42
|
+
const arr = match[1].split("-");
|
|
43
|
+
if (arr.length === 2) {
|
|
44
|
+
inDb = sql;
|
|
45
|
+
codeI = 0;
|
|
46
|
+
} else {
|
|
47
|
+
if (inDb !== sql) {
|
|
48
|
+
matches[codeI] = false;
|
|
49
|
+
}
|
|
50
|
+
codeI++;
|
|
51
|
+
}
|
|
52
|
+
pos = rgx.lastIndex;
|
|
53
|
+
}
|
|
54
|
+
const firstMatching = matches.indexOf(true);
|
|
55
|
+
handle(firstMatching === -1 ? void 0 : firstMatching);
|
|
56
|
+
})
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const promptCreateOrRename = (kind, name, drop, verifying) => {
|
|
61
|
+
if (verifying)
|
|
62
|
+
throw new AbortSignal();
|
|
63
|
+
let hintPos = name.length + 4;
|
|
64
|
+
for (const from of drop) {
|
|
65
|
+
const value = from.length + 8 + name.length;
|
|
66
|
+
if (value > hintPos)
|
|
67
|
+
hintPos = value;
|
|
68
|
+
}
|
|
69
|
+
let max = 0;
|
|
70
|
+
const add = name.length + 3;
|
|
71
|
+
for (const name2 of drop) {
|
|
72
|
+
if (name2.length + add > max) {
|
|
73
|
+
max = name2.length + add;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const renameMessage = `rename ${kind}`;
|
|
77
|
+
return rakeDb.promptSelect({
|
|
78
|
+
message: `Create or rename ${rakeDb.colors.blueBold(
|
|
79
|
+
name
|
|
80
|
+
)} ${kind} from another ${kind}?`,
|
|
81
|
+
options: [
|
|
82
|
+
`${rakeDb.colors.greenBold("+")} ${name} ${rakeDb.colors.pale(
|
|
83
|
+
`create ${kind}`.padStart(
|
|
84
|
+
hintPos + renameMessage.length - name.length - 4,
|
|
85
|
+
" "
|
|
86
|
+
)
|
|
87
|
+
)}`,
|
|
88
|
+
...drop.map(
|
|
89
|
+
(d) => `${rakeDb.colors.yellowBold("~")} ${d} ${rakeDb.colors.yellowBold(
|
|
90
|
+
"=>"
|
|
91
|
+
)} ${name} ${rakeDb.colors.pale(
|
|
92
|
+
renameMessage.padStart(
|
|
93
|
+
hintPos + renameMessage.length - d.length - name.length - 8,
|
|
94
|
+
" "
|
|
95
|
+
)
|
|
96
|
+
)}`
|
|
97
|
+
)
|
|
98
|
+
]
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
const checkForColumnChange = (shape, key) => {
|
|
102
|
+
const item = shape[key];
|
|
103
|
+
return item && (Array.isArray(item) || item.type !== "rename");
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const processSchemas = async (ast, schemas, dbStructure, verifying) => {
|
|
107
|
+
const createSchemas = [];
|
|
108
|
+
const dropSchemas = [];
|
|
109
|
+
for (const schema of schemas) {
|
|
110
|
+
if (!dbStructure.schemas.includes(schema)) {
|
|
111
|
+
createSchemas.push(schema);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
for (const schema of dbStructure.schemas) {
|
|
115
|
+
if (!schemas.has(schema) && schema !== "public") {
|
|
116
|
+
dropSchemas.push(schema);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
for (const schema of createSchemas) {
|
|
120
|
+
if (dropSchemas.length) {
|
|
121
|
+
const index = await promptCreateOrRename(
|
|
122
|
+
"schema",
|
|
123
|
+
schema,
|
|
124
|
+
dropSchemas,
|
|
125
|
+
verifying
|
|
126
|
+
);
|
|
127
|
+
if (index) {
|
|
128
|
+
const from = dropSchemas[index - 1];
|
|
129
|
+
dropSchemas.splice(index - 1, 1);
|
|
130
|
+
renameSchemaInStructures(dbStructure.tables, from, schema);
|
|
131
|
+
renameSchemaInStructures(dbStructure.views, from, schema);
|
|
132
|
+
renameSchemaInStructures(dbStructure.indexes, from, schema);
|
|
133
|
+
renameSchemaInStructures(dbStructure.constraints, from, schema);
|
|
134
|
+
renameSchemaInStructures(dbStructure.triggers, from, schema);
|
|
135
|
+
renameSchemaInStructures(dbStructure.enums, from, schema);
|
|
136
|
+
renameSchemaInStructures(dbStructure.domains, from, schema);
|
|
137
|
+
renameSchemaInStructures(dbStructure.collations, from, schema);
|
|
138
|
+
for (const table of dbStructure.tables) {
|
|
139
|
+
for (const column of table.columns) {
|
|
140
|
+
if (column.typeSchema === from) {
|
|
141
|
+
column.typeSchema = schema;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
ast.push({
|
|
146
|
+
type: "renameSchema",
|
|
147
|
+
from,
|
|
148
|
+
to: schema
|
|
149
|
+
});
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
ast.push({
|
|
154
|
+
type: "schema",
|
|
155
|
+
action: "create",
|
|
156
|
+
name: schema
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
for (const schema of dropSchemas) {
|
|
160
|
+
ast.push({
|
|
161
|
+
type: "schema",
|
|
162
|
+
action: "drop",
|
|
163
|
+
name: schema
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
const renameSchemaInStructures = (items, from, to) => {
|
|
168
|
+
for (const item of items) {
|
|
169
|
+
if (item.schemaName === from) {
|
|
170
|
+
item.schemaName = to;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
var __defProp$6 = Object.defineProperty;
|
|
176
|
+
var __getOwnPropSymbols$6 = Object.getOwnPropertySymbols;
|
|
177
|
+
var __hasOwnProp$6 = Object.prototype.hasOwnProperty;
|
|
178
|
+
var __propIsEnum$6 = Object.prototype.propertyIsEnumerable;
|
|
179
|
+
var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
180
|
+
var __spreadValues$6 = (a, b) => {
|
|
181
|
+
for (var prop in b || (b = {}))
|
|
182
|
+
if (__hasOwnProp$6.call(b, prop))
|
|
183
|
+
__defNormalProp$6(a, prop, b[prop]);
|
|
184
|
+
if (__getOwnPropSymbols$6)
|
|
185
|
+
for (var prop of __getOwnPropSymbols$6(b)) {
|
|
186
|
+
if (__propIsEnum$6.call(b, prop))
|
|
187
|
+
__defNormalProp$6(a, prop, b[prop]);
|
|
188
|
+
}
|
|
189
|
+
return a;
|
|
190
|
+
};
|
|
191
|
+
const processExtensions = (ast, dbStructure, currentSchema, extensions) => {
|
|
192
|
+
var _a;
|
|
193
|
+
const codeExtensions = extensions == null ? void 0 : extensions.map((ext) => {
|
|
194
|
+
const [schema, name] = rakeDb.getSchemaAndTableFromName(ext.name);
|
|
195
|
+
return { schema, name, version: ext.version };
|
|
196
|
+
});
|
|
197
|
+
for (const dbExt of dbStructure.extensions) {
|
|
198
|
+
if (codeExtensions) {
|
|
199
|
+
let found = false;
|
|
200
|
+
for (let i = 0; i < codeExtensions.length; i++) {
|
|
201
|
+
const codeExt = codeExtensions[i];
|
|
202
|
+
if (dbExt.name === codeExt.name && dbExt.schemaName === ((_a = codeExt.schema) != null ? _a : currentSchema) && (!codeExt.version || codeExt.version === dbExt.version)) {
|
|
203
|
+
found = true;
|
|
204
|
+
codeExtensions.splice(i, 1);
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (found)
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
ast.push({
|
|
212
|
+
type: "extension",
|
|
213
|
+
action: "drop",
|
|
214
|
+
schema: dbExt.schemaName === currentSchema ? void 0 : dbExt.schemaName,
|
|
215
|
+
name: dbExt.name,
|
|
216
|
+
version: dbExt.version
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
if (codeExtensions == null ? void 0 : codeExtensions.length) {
|
|
220
|
+
ast.push(
|
|
221
|
+
...codeExtensions.map((ext) => __spreadValues$6({
|
|
222
|
+
type: "extension",
|
|
223
|
+
action: "create"
|
|
224
|
+
}, ext))
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
var __defProp$5 = Object.defineProperty;
|
|
230
|
+
var __getOwnPropSymbols$5 = Object.getOwnPropertySymbols;
|
|
231
|
+
var __hasOwnProp$5 = Object.prototype.hasOwnProperty;
|
|
232
|
+
var __propIsEnum$5 = Object.prototype.propertyIsEnumerable;
|
|
233
|
+
var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
234
|
+
var __spreadValues$5 = (a, b) => {
|
|
235
|
+
for (var prop in b || (b = {}))
|
|
236
|
+
if (__hasOwnProp$5.call(b, prop))
|
|
237
|
+
__defNormalProp$5(a, prop, b[prop]);
|
|
238
|
+
if (__getOwnPropSymbols$5)
|
|
239
|
+
for (var prop of __getOwnPropSymbols$5(b)) {
|
|
240
|
+
if (__propIsEnum$5.call(b, prop))
|
|
241
|
+
__defNormalProp$5(a, prop, b[prop]);
|
|
242
|
+
}
|
|
243
|
+
return a;
|
|
244
|
+
};
|
|
245
|
+
const processColumns = async (adapter, structureToAstCtx, dbStructure, domainsMap, changeTableData, ast, currentSchema, compareSql, typeCastsCache, verifying) => {
|
|
246
|
+
const { dbTable } = changeTableData;
|
|
247
|
+
const dbColumns = Object.fromEntries(
|
|
248
|
+
dbTable.columns.map((column) => [column.name, column])
|
|
249
|
+
);
|
|
250
|
+
const { columnsToAdd, columnsToDrop, columnsToChange } = groupColumns(
|
|
251
|
+
structureToAstCtx,
|
|
252
|
+
dbStructure,
|
|
253
|
+
domainsMap,
|
|
254
|
+
dbColumns,
|
|
255
|
+
changeTableData
|
|
256
|
+
);
|
|
257
|
+
await addOrRenameColumns(
|
|
258
|
+
dbStructure,
|
|
259
|
+
changeTableData,
|
|
260
|
+
columnsToAdd,
|
|
261
|
+
columnsToDrop,
|
|
262
|
+
columnsToChange,
|
|
263
|
+
verifying
|
|
264
|
+
);
|
|
265
|
+
await changeColumns(
|
|
266
|
+
adapter,
|
|
267
|
+
structureToAstCtx,
|
|
268
|
+
dbStructure,
|
|
269
|
+
domainsMap,
|
|
270
|
+
ast,
|
|
271
|
+
currentSchema,
|
|
272
|
+
dbColumns,
|
|
273
|
+
columnsToChange,
|
|
274
|
+
compareSql,
|
|
275
|
+
changeTableData,
|
|
276
|
+
typeCastsCache,
|
|
277
|
+
verifying
|
|
278
|
+
);
|
|
279
|
+
dropColumns(changeTableData, columnsToDrop);
|
|
280
|
+
};
|
|
281
|
+
const groupColumns = (structureToAstCtx, dbStructure, domainsMap, dbColumns, changeTableData) => {
|
|
282
|
+
var _a;
|
|
283
|
+
const columnsToAdd = [];
|
|
284
|
+
const columnsToDrop = [];
|
|
285
|
+
const columnsToChange = /* @__PURE__ */ new Map();
|
|
286
|
+
const { codeTable, dbTable, dbTableData } = changeTableData;
|
|
287
|
+
const checks = rakeDb.getDbTableColumnsChecks(changeTableData.dbTableData);
|
|
288
|
+
for (const key in codeTable.shape) {
|
|
289
|
+
const column = codeTable.shape[key];
|
|
290
|
+
if (!column.dataType)
|
|
291
|
+
continue;
|
|
292
|
+
const name = (_a = column.data.name) != null ? _a : key;
|
|
293
|
+
if (dbColumns[name]) {
|
|
294
|
+
columnsToChange.set(name, column);
|
|
295
|
+
} else {
|
|
296
|
+
columnsToAdd.push({ key: name, column });
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
for (const name in dbColumns) {
|
|
300
|
+
if (columnsToChange.has(name))
|
|
301
|
+
continue;
|
|
302
|
+
const [key, column] = rakeDb.dbColumnToAst(
|
|
303
|
+
structureToAstCtx,
|
|
304
|
+
dbStructure,
|
|
305
|
+
domainsMap,
|
|
306
|
+
dbTable.name,
|
|
307
|
+
dbColumns[name],
|
|
308
|
+
dbTable,
|
|
309
|
+
dbTableData,
|
|
310
|
+
checks
|
|
311
|
+
);
|
|
312
|
+
columnsToDrop.push({ key, column });
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
columnsToAdd,
|
|
316
|
+
columnsToDrop,
|
|
317
|
+
columnsToChange
|
|
318
|
+
};
|
|
319
|
+
};
|
|
320
|
+
const addOrRenameColumns = async (dbStructure, {
|
|
321
|
+
dbTableData,
|
|
322
|
+
schema,
|
|
323
|
+
changeTableAst: { name: tableName, shape }
|
|
324
|
+
}, columnsToAdd, columnsToDrop, columnsToChange, verifying) => {
|
|
325
|
+
var _a, _b;
|
|
326
|
+
for (const { key, column } of columnsToAdd) {
|
|
327
|
+
if (columnsToDrop.length) {
|
|
328
|
+
const index = await promptCreateOrRename(
|
|
329
|
+
"column",
|
|
330
|
+
(_a = column.data.name) != null ? _a : key,
|
|
331
|
+
columnsToDrop.map((x) => x.key),
|
|
332
|
+
verifying
|
|
333
|
+
);
|
|
334
|
+
if (index) {
|
|
335
|
+
const drop = columnsToDrop[index - 1];
|
|
336
|
+
columnsToDrop.splice(index - 1, 1);
|
|
337
|
+
const from = drop.key;
|
|
338
|
+
columnsToChange.set(from, column.name(key));
|
|
339
|
+
if (dbTableData.primaryKey) {
|
|
340
|
+
renameColumn(dbTableData.primaryKey.columns, from, key);
|
|
341
|
+
}
|
|
342
|
+
for (const index2 of dbTableData.indexes) {
|
|
343
|
+
for (const column2 of index2.columns) {
|
|
344
|
+
if ("column" in column2 && column2.column === from) {
|
|
345
|
+
column2.column = key;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
for (const c of dbTableData.constraints) {
|
|
350
|
+
if ((_b = c.check) == null ? void 0 : _b.columns) {
|
|
351
|
+
renameColumn(c.check.columns, from, key);
|
|
352
|
+
}
|
|
353
|
+
if (c.references) {
|
|
354
|
+
renameColumn(c.references.columns, from, key);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
for (const c of dbStructure.constraints) {
|
|
358
|
+
if (c.references && c.references.foreignSchema === schema && c.references.foreignTable === tableName) {
|
|
359
|
+
renameColumn(c.references.foreignColumns, from, key);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
shape[key] = {
|
|
366
|
+
type: "add",
|
|
367
|
+
item: column
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
const dropColumns = ({ changeTableAst: { shape } }, columnsToDrop) => {
|
|
372
|
+
for (const { key, column } of columnsToDrop) {
|
|
373
|
+
shape[key] = {
|
|
374
|
+
type: "drop",
|
|
375
|
+
item: column
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
const changeColumns = async (adapter, structureToAstCtx, dbStructure, domainsMap, ast, currentSchema, dbColumns, columnsToChange, compareSql, changeTableData, typeCastsCache, verifying) => {
|
|
380
|
+
var _a, _b, _c, _d, _e, _f;
|
|
381
|
+
const { shape } = changeTableData.changeTableAst;
|
|
382
|
+
for (const [name, codeColumn] of columnsToChange) {
|
|
383
|
+
const dbColumnStructure = dbColumns[name];
|
|
384
|
+
let changed = false;
|
|
385
|
+
const dbColumn = rakeDb.instantiateDbColumn(
|
|
386
|
+
structureToAstCtx,
|
|
387
|
+
dbStructure,
|
|
388
|
+
domainsMap,
|
|
389
|
+
dbColumnStructure
|
|
390
|
+
);
|
|
391
|
+
const dbType = getColumnDbType(dbColumn, currentSchema);
|
|
392
|
+
const codeType = getColumnDbType(codeColumn, currentSchema);
|
|
393
|
+
if (dbType !== codeType) {
|
|
394
|
+
let typeCasts = typeCastsCache.value;
|
|
395
|
+
if (!typeCasts) {
|
|
396
|
+
const { rows } = await adapter.arrays(`SELECT s.typname, t.typname
|
|
397
|
+
FROM pg_cast
|
|
398
|
+
JOIN pg_type AS s ON s.oid = castsource
|
|
399
|
+
JOIN pg_type AS t ON t.oid = casttarget`);
|
|
400
|
+
const directTypeCasts = /* @__PURE__ */ new Map();
|
|
401
|
+
for (const [source, target] of rows) {
|
|
402
|
+
const set = directTypeCasts.get(source);
|
|
403
|
+
if (set) {
|
|
404
|
+
set.add(target);
|
|
405
|
+
} else {
|
|
406
|
+
directTypeCasts.set(source, /* @__PURE__ */ new Set([target]));
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
typeCasts = /* @__PURE__ */ new Map();
|
|
410
|
+
for (const [type, directSet] of directTypeCasts.entries()) {
|
|
411
|
+
const set = new Set(directSet);
|
|
412
|
+
typeCasts.set(type, set);
|
|
413
|
+
for (const subtype of directSet) {
|
|
414
|
+
const subset = directTypeCasts.get(subtype);
|
|
415
|
+
if (subset) {
|
|
416
|
+
for (const type2 of subset) {
|
|
417
|
+
set.add(type2);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
typeCastsCache.value = typeCasts;
|
|
423
|
+
}
|
|
424
|
+
const dbBaseType = dbColumn instanceof pqb.DomainColumn ? (_a = domainsMap[dbColumn.dataType]) == null ? void 0 : _a.dataType : dbType;
|
|
425
|
+
const codeBaseType = codeColumn instanceof pqb.DomainColumn ? (_b = domainsMap[codeColumn.dataType]) == null ? void 0 : _b.dataType : codeType;
|
|
426
|
+
if (!((_c = typeCasts.get(dbBaseType)) == null ? void 0 : _c.has(codeBaseType))) {
|
|
427
|
+
if (!(dbColumn instanceof pqb.EnumColumn) || !(codeColumn instanceof pqb.EnumColumn) || !orchidCore.deepCompare(dbColumn.options, codeColumn.options)) {
|
|
428
|
+
if (verifying)
|
|
429
|
+
throw new AbortSignal();
|
|
430
|
+
const tableName = rakeDb.concatSchemaAndName(changeTableData.changeTableAst);
|
|
431
|
+
const abort = await rakeDb.promptSelect({
|
|
432
|
+
message: `Cannot cast type of ${tableName}'s column ${name} from ${dbType} to ${codeType}`,
|
|
433
|
+
options: [
|
|
434
|
+
`${rakeDb.colors.yellowBold(
|
|
435
|
+
`-/+`
|
|
436
|
+
)} recreate the column, existing data will be ${rakeDb.colors.red(
|
|
437
|
+
"lost"
|
|
438
|
+
)}`,
|
|
439
|
+
`write migration manually`
|
|
440
|
+
]
|
|
441
|
+
});
|
|
442
|
+
if (abort) {
|
|
443
|
+
throw new AbortSignal();
|
|
444
|
+
}
|
|
445
|
+
shape[name] = [
|
|
446
|
+
{
|
|
447
|
+
type: "drop",
|
|
448
|
+
item: dbColumn
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
type: "add",
|
|
452
|
+
item: codeColumn
|
|
453
|
+
}
|
|
454
|
+
];
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
changed = true;
|
|
459
|
+
}
|
|
460
|
+
const dbData = dbColumn.data;
|
|
461
|
+
const codeData = codeColumn.data;
|
|
462
|
+
if (!changed) {
|
|
463
|
+
if (!dbData.isNullable)
|
|
464
|
+
dbData.isNullable = void 0;
|
|
465
|
+
for (const key of ["isNullable", "comment"]) {
|
|
466
|
+
if (dbData[key] !== codeData[key]) {
|
|
467
|
+
changed = true;
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
if (!changed) {
|
|
473
|
+
for (const key of [
|
|
474
|
+
"maxChars",
|
|
475
|
+
"collation",
|
|
476
|
+
"compression",
|
|
477
|
+
"numericPrecision",
|
|
478
|
+
"numericScale",
|
|
479
|
+
"dateTimePrecision"
|
|
480
|
+
]) {
|
|
481
|
+
if (key in codeData && dbData[key] !== codeData[key]) {
|
|
482
|
+
changed = true;
|
|
483
|
+
break;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
if (!changed && !orchidCore.deepCompare(
|
|
488
|
+
dbData.identity,
|
|
489
|
+
codeData.identity ? __spreadValues$5({
|
|
490
|
+
always: false,
|
|
491
|
+
start: 1,
|
|
492
|
+
increment: 1,
|
|
493
|
+
cache: 1,
|
|
494
|
+
cycle: false
|
|
495
|
+
}, (_d = codeData.identity) != null ? _d : {}) : void 0
|
|
496
|
+
)) {
|
|
497
|
+
changed = true;
|
|
498
|
+
}
|
|
499
|
+
if (!changed && dbData.default !== void 0 && dbData.default !== null && codeData.default !== void 0 && codeData.default !== null) {
|
|
500
|
+
const valuesBeforeLen = compareSql.values.length;
|
|
501
|
+
const dbDefault = rakeDb.encodeColumnDefault(
|
|
502
|
+
dbData.default,
|
|
503
|
+
compareSql.values,
|
|
504
|
+
dbColumn
|
|
505
|
+
);
|
|
506
|
+
const dbValues = compareSql.values.slice(valuesBeforeLen);
|
|
507
|
+
const codeDefault = rakeDb.encodeColumnDefault(
|
|
508
|
+
codeData.default,
|
|
509
|
+
compareSql.values,
|
|
510
|
+
codeColumn
|
|
511
|
+
);
|
|
512
|
+
const codeValues = compareSql.values.slice(valuesBeforeLen);
|
|
513
|
+
if (dbValues.length !== codeValues.length || dbValues.length && JSON.stringify(dbValues) !== JSON.stringify(codeValues)) {
|
|
514
|
+
changed = true;
|
|
515
|
+
compareSql.values.length = valuesBeforeLen;
|
|
516
|
+
} else if (dbDefault !== codeDefault && dbDefault !== `(${codeDefault})`) {
|
|
517
|
+
compareSql.expressions.push({
|
|
518
|
+
inDb: dbDefault,
|
|
519
|
+
inCode: codeDefault,
|
|
520
|
+
change: () => {
|
|
521
|
+
changeColumn(shape, name, dbColumn, codeColumn);
|
|
522
|
+
if (!changeTableData.pushedAst) {
|
|
523
|
+
changeTableData.pushedAst = true;
|
|
524
|
+
ast.push(changeTableData.changeTableAst);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
if (changed) {
|
|
531
|
+
changeColumn(shape, name, dbColumn, codeColumn);
|
|
532
|
+
} else {
|
|
533
|
+
const from = (_e = dbColumn.data.name) != null ? _e : name;
|
|
534
|
+
const to = (_f = codeColumn.data.name) != null ? _f : name;
|
|
535
|
+
if (from !== to) {
|
|
536
|
+
shape[from] = {
|
|
537
|
+
type: "rename",
|
|
538
|
+
name: to
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
const changeColumn = (shape, name, dbColumn, codeColumn) => {
|
|
545
|
+
dbColumn.data.as = codeColumn.data.as = void 0;
|
|
546
|
+
shape[name] = {
|
|
547
|
+
type: "change",
|
|
548
|
+
from: { column: dbColumn },
|
|
549
|
+
to: { column: codeColumn }
|
|
550
|
+
};
|
|
551
|
+
};
|
|
552
|
+
const getColumnDbType = (column, currentSchema) => {
|
|
553
|
+
if (column instanceof pqb.EnumColumn) {
|
|
554
|
+
const [schema = currentSchema, name] = rakeDb.getSchemaAndTableFromName(
|
|
555
|
+
column.enumName
|
|
556
|
+
);
|
|
557
|
+
return column.enumName = `${schema}.${name}`;
|
|
558
|
+
} else {
|
|
559
|
+
return column.dataType;
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
const renameColumn = (columns, from, to) => {
|
|
563
|
+
for (let i = 0; i < columns.length; i++) {
|
|
564
|
+
if (columns[i] === from) {
|
|
565
|
+
columns[i] = to;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
|
|
570
|
+
const processDomains = async (ast, adapter, structureToAstCtx, domainsMap, dbStructure, currentSchema, domains) => {
|
|
571
|
+
const codeDomains = [];
|
|
572
|
+
if (domains) {
|
|
573
|
+
for (const { schemaName, name, column } of domains) {
|
|
574
|
+
codeDomains.push(
|
|
575
|
+
makeComparableDomain(currentSchema, schemaName, name, column)
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
const tableExpressions = [];
|
|
580
|
+
const holdCodeDomains = /* @__PURE__ */ new Set();
|
|
581
|
+
for (const domain of dbStructure.domains) {
|
|
582
|
+
const dbColumn = rakeDb.instantiateDbColumn(
|
|
583
|
+
structureToAstCtx,
|
|
584
|
+
dbStructure,
|
|
585
|
+
domainsMap,
|
|
586
|
+
{
|
|
587
|
+
schemaName: domain.typeSchema,
|
|
588
|
+
tableName: "N/A",
|
|
589
|
+
name: domain.name,
|
|
590
|
+
typeSchema: domain.typeSchema,
|
|
591
|
+
type: domain.type,
|
|
592
|
+
isArray: domain.isArray,
|
|
593
|
+
default: domain.default,
|
|
594
|
+
isNullable: domain.isNullable,
|
|
595
|
+
collate: domain.collate
|
|
596
|
+
}
|
|
597
|
+
);
|
|
598
|
+
if (domain.check) {
|
|
599
|
+
dbColumn.data.check = {
|
|
600
|
+
sql: new pqb.RawSQL([[domain.check]])
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
const dbDomain = makeComparableDomain(
|
|
604
|
+
currentSchema,
|
|
605
|
+
domain.schemaName,
|
|
606
|
+
domain.name,
|
|
607
|
+
dbColumn
|
|
608
|
+
);
|
|
609
|
+
const found = codeDomains.filter(
|
|
610
|
+
(codeDomain) => orchidCore.deepCompare(dbDomain.compare, codeDomain.compare)
|
|
611
|
+
);
|
|
612
|
+
if ((domain.default || domain.check) && found.length) {
|
|
613
|
+
for (const codeDomain of found) {
|
|
614
|
+
holdCodeDomains.add(codeDomain);
|
|
615
|
+
}
|
|
616
|
+
const compare = [];
|
|
617
|
+
pushCompare(compare, domain, found, "default");
|
|
618
|
+
pushCompare(compare, domain, found, "check");
|
|
619
|
+
const source = `(VALUES (NULL::${getColumnDbType(
|
|
620
|
+
dbColumn,
|
|
621
|
+
currentSchema
|
|
622
|
+
)})) t(value)`;
|
|
623
|
+
tableExpressions.push({
|
|
624
|
+
compare,
|
|
625
|
+
source,
|
|
626
|
+
handle(index) {
|
|
627
|
+
const codeDomain = index === void 0 ? void 0 : found[index];
|
|
628
|
+
if (!codeDomain) {
|
|
629
|
+
ast.push(dropAst(dbDomain));
|
|
630
|
+
} else {
|
|
631
|
+
holdCodeDomains.delete(codeDomain);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
});
|
|
635
|
+
} else if (found.length) {
|
|
636
|
+
let i = codeDomains.findIndex(
|
|
637
|
+
(codeDomain) => codeDomain.name === dbDomain.name && codeDomain.schemaName === dbDomain.schemaName
|
|
638
|
+
);
|
|
639
|
+
if (i === -1) {
|
|
640
|
+
i = 0;
|
|
641
|
+
const first = found[0];
|
|
642
|
+
ast.push({
|
|
643
|
+
type: "renameType",
|
|
644
|
+
kind: "DOMAIN",
|
|
645
|
+
fromSchema: dbDomain.schemaName,
|
|
646
|
+
from: dbDomain.name,
|
|
647
|
+
toSchema: first.schemaName,
|
|
648
|
+
to: first.name
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
codeDomains.splice(i, 1);
|
|
652
|
+
} else {
|
|
653
|
+
ast.push(dropAst(dbDomain));
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
for (const codeDomain of codeDomains) {
|
|
657
|
+
if (!holdCodeDomains.has(codeDomain)) {
|
|
658
|
+
ast.push(createAst(codeDomain));
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
if (tableExpressions.length) {
|
|
662
|
+
await compareSqlExpressions(tableExpressions, adapter);
|
|
663
|
+
if (holdCodeDomains.size) {
|
|
664
|
+
for (const codeDomain of holdCodeDomains.keys()) {
|
|
665
|
+
ast.push(createAst(codeDomain));
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
const makeComparableDomain = (currentSchema, schemaName, name, column) => {
|
|
671
|
+
var _a;
|
|
672
|
+
let isArray = false;
|
|
673
|
+
const isNullable = (_a = column.data.isNullable) != null ? _a : false;
|
|
674
|
+
let inner = column;
|
|
675
|
+
if (column instanceof pqb.ArrayColumn) {
|
|
676
|
+
inner = column.data.item;
|
|
677
|
+
isArray = true;
|
|
678
|
+
}
|
|
679
|
+
const fullType = getColumnDbType(inner, currentSchema);
|
|
680
|
+
const [typeSchema = "pg_catalog", type] = rakeDb.getSchemaAndTableFromName(fullType);
|
|
681
|
+
return {
|
|
682
|
+
schemaName,
|
|
683
|
+
name,
|
|
684
|
+
column,
|
|
685
|
+
compare: {
|
|
686
|
+
type,
|
|
687
|
+
typeSchema,
|
|
688
|
+
isArray,
|
|
689
|
+
isNullable,
|
|
690
|
+
maxChars: inner.data.maxChars,
|
|
691
|
+
numericPrecision: inner.data.numericPrecision,
|
|
692
|
+
numericScale: inner.data.numericScale,
|
|
693
|
+
dateTimePrecision: inner.data.dateTimePrecision,
|
|
694
|
+
collate: column.data.collate,
|
|
695
|
+
hasDefault: column.data.default !== void 0,
|
|
696
|
+
hasCheck: column.data.check !== void 0
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
};
|
|
700
|
+
const pushCompare = (compare, domain, found, key) => {
|
|
701
|
+
const inDb = domain[key];
|
|
702
|
+
if (inDb) {
|
|
703
|
+
compare.push({
|
|
704
|
+
inDb,
|
|
705
|
+
inCode: found.map((codeDomain) => {
|
|
706
|
+
const value = codeDomain.column.data[key];
|
|
707
|
+
if ("sql" in value) {
|
|
708
|
+
return value.sql;
|
|
709
|
+
}
|
|
710
|
+
return value;
|
|
711
|
+
})
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
};
|
|
715
|
+
const dropAst = (dbDomain) => ({
|
|
716
|
+
type: "domain",
|
|
717
|
+
action: "drop",
|
|
718
|
+
schema: dbDomain.schemaName,
|
|
719
|
+
name: dbDomain.name,
|
|
720
|
+
baseType: dbDomain.column
|
|
721
|
+
});
|
|
722
|
+
const createAst = (codeDomain) => ({
|
|
723
|
+
type: "domain",
|
|
724
|
+
action: "create",
|
|
725
|
+
schema: codeDomain.schemaName,
|
|
726
|
+
name: codeDomain.name,
|
|
727
|
+
baseType: codeDomain.column
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
var __defProp$4 = Object.defineProperty;
|
|
731
|
+
var __getOwnPropSymbols$4 = Object.getOwnPropertySymbols;
|
|
732
|
+
var __hasOwnProp$4 = Object.prototype.hasOwnProperty;
|
|
733
|
+
var __propIsEnum$4 = Object.prototype.propertyIsEnumerable;
|
|
734
|
+
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
735
|
+
var __spreadValues$4 = (a, b) => {
|
|
736
|
+
for (var prop in b || (b = {}))
|
|
737
|
+
if (__hasOwnProp$4.call(b, prop))
|
|
738
|
+
__defNormalProp$4(a, prop, b[prop]);
|
|
739
|
+
if (__getOwnPropSymbols$4)
|
|
740
|
+
for (var prop of __getOwnPropSymbols$4(b)) {
|
|
741
|
+
if (__propIsEnum$4.call(b, prop))
|
|
742
|
+
__defNormalProp$4(a, prop, b[prop]);
|
|
743
|
+
}
|
|
744
|
+
return a;
|
|
745
|
+
};
|
|
746
|
+
const processEnums = async (ast, enums, dbStructure, currentSchema, verifying) => {
|
|
747
|
+
var _a, _b;
|
|
748
|
+
const createEnums = [];
|
|
749
|
+
const dropEnums = [];
|
|
750
|
+
for (const [, codeEnum] of enums) {
|
|
751
|
+
const { schema = currentSchema, name } = codeEnum;
|
|
752
|
+
const dbEnum = dbStructure.enums.find(
|
|
753
|
+
(x) => x.schemaName === schema && x.name === name
|
|
754
|
+
);
|
|
755
|
+
if (!dbEnum) {
|
|
756
|
+
createEnums.push(codeEnum);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
for (const dbEnum of dbStructure.enums) {
|
|
760
|
+
const codeEnum = enums.get(`${dbEnum.schemaName}.${dbEnum.name}`);
|
|
761
|
+
if (codeEnum) {
|
|
762
|
+
changeEnum(ast, dbEnum, codeEnum);
|
|
763
|
+
continue;
|
|
764
|
+
}
|
|
765
|
+
const i = createEnums.findIndex((x) => x.name === dbEnum.name);
|
|
766
|
+
if (i !== -1) {
|
|
767
|
+
const codeEnum2 = createEnums[i];
|
|
768
|
+
createEnums.splice(i, 1);
|
|
769
|
+
const fromSchema = dbEnum.schemaName;
|
|
770
|
+
const toSchema = (_a = codeEnum2.schema) != null ? _a : currentSchema;
|
|
771
|
+
renameColumnsTypeSchema(dbStructure, fromSchema, toSchema);
|
|
772
|
+
ast.push({
|
|
773
|
+
type: "renameType",
|
|
774
|
+
kind: "TYPE",
|
|
775
|
+
fromSchema,
|
|
776
|
+
from: dbEnum.name,
|
|
777
|
+
toSchema,
|
|
778
|
+
to: dbEnum.name
|
|
779
|
+
});
|
|
780
|
+
changeEnum(ast, dbEnum, codeEnum2);
|
|
781
|
+
continue;
|
|
782
|
+
}
|
|
783
|
+
dropEnums.push(dbEnum);
|
|
784
|
+
}
|
|
785
|
+
for (const codeEnum of createEnums) {
|
|
786
|
+
if (dropEnums.length) {
|
|
787
|
+
const index = await promptCreateOrRename(
|
|
788
|
+
"enum",
|
|
789
|
+
codeEnum.name,
|
|
790
|
+
dropEnums.map((x) => x.name),
|
|
791
|
+
verifying
|
|
792
|
+
);
|
|
793
|
+
if (index) {
|
|
794
|
+
const dbEnum = dropEnums[index - 1];
|
|
795
|
+
dropEnums.splice(index - 1, 1);
|
|
796
|
+
const fromSchema = dbEnum.schemaName;
|
|
797
|
+
const from = dbEnum.name;
|
|
798
|
+
const toSchema = (_b = codeEnum.schema) != null ? _b : currentSchema;
|
|
799
|
+
const to = codeEnum.name;
|
|
800
|
+
if (fromSchema !== toSchema) {
|
|
801
|
+
renameColumnsTypeSchema(dbStructure, fromSchema, toSchema);
|
|
802
|
+
}
|
|
803
|
+
for (const table of dbStructure.tables) {
|
|
804
|
+
for (const column of table.columns) {
|
|
805
|
+
if (column.type === from) {
|
|
806
|
+
column.type = to;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
ast.push({
|
|
811
|
+
type: "renameType",
|
|
812
|
+
kind: "TYPE",
|
|
813
|
+
fromSchema,
|
|
814
|
+
from,
|
|
815
|
+
toSchema,
|
|
816
|
+
to
|
|
817
|
+
});
|
|
818
|
+
changeEnum(ast, dbEnum, codeEnum);
|
|
819
|
+
continue;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
ast.push(__spreadValues$4({
|
|
823
|
+
type: "enum",
|
|
824
|
+
action: "create"
|
|
825
|
+
}, codeEnum));
|
|
826
|
+
}
|
|
827
|
+
for (const dbEnum of dropEnums) {
|
|
828
|
+
ast.push({
|
|
829
|
+
type: "enum",
|
|
830
|
+
action: "drop",
|
|
831
|
+
schema: dbEnum.schemaName,
|
|
832
|
+
name: dbEnum.name,
|
|
833
|
+
values: dbEnum.values
|
|
834
|
+
});
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
const changeEnum = (ast, dbEnum, codeEnum) => {
|
|
838
|
+
const { values: dbValues } = dbEnum;
|
|
839
|
+
const { values: codeValues, schema, name } = codeEnum;
|
|
840
|
+
if (dbValues.length < codeValues.length) {
|
|
841
|
+
if (!dbValues.some((value, i) => value !== codeValues[i])) {
|
|
842
|
+
ast.push({
|
|
843
|
+
type: "enumValues",
|
|
844
|
+
action: "add",
|
|
845
|
+
schema,
|
|
846
|
+
name,
|
|
847
|
+
values: codeValues.slice(-(codeValues.length - dbValues.length))
|
|
848
|
+
});
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
} else if (dbValues.length > codeValues.length) {
|
|
852
|
+
if (!codeValues.some((value, i) => value !== dbValues[i])) {
|
|
853
|
+
ast.push({
|
|
854
|
+
type: "enumValues",
|
|
855
|
+
action: "drop",
|
|
856
|
+
schema,
|
|
857
|
+
name,
|
|
858
|
+
values: dbValues.slice(-(dbValues.length - codeValues.length))
|
|
859
|
+
});
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
} else if (!dbValues.some((value, i) => value !== codeValues[i])) {
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
865
|
+
ast.push({
|
|
866
|
+
type: "changeEnumValues",
|
|
867
|
+
schema,
|
|
868
|
+
name,
|
|
869
|
+
fromValues: dbValues,
|
|
870
|
+
toValues: codeValues
|
|
871
|
+
});
|
|
872
|
+
};
|
|
873
|
+
const renameColumnsTypeSchema = (dbStructure, from, to) => {
|
|
874
|
+
for (const table of dbStructure.tables) {
|
|
875
|
+
for (const column of table.columns) {
|
|
876
|
+
if (column.typeSchema === from) {
|
|
877
|
+
column.typeSchema = to;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
};
|
|
882
|
+
|
|
883
|
+
const processPrimaryKey = (ast, changeTableData) => {
|
|
884
|
+
var _a;
|
|
885
|
+
const { codeTable } = changeTableData;
|
|
886
|
+
const columnsPrimaryKey = [];
|
|
887
|
+
for (const key in codeTable.shape) {
|
|
888
|
+
const column = codeTable.shape[key];
|
|
889
|
+
if (column.data.primaryKey) {
|
|
890
|
+
columnsPrimaryKey.push((_a = column.data.name) != null ? _a : key);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
changePrimaryKey(columnsPrimaryKey, changeTableData);
|
|
894
|
+
renamePrimaryKey(ast, changeTableData);
|
|
895
|
+
};
|
|
896
|
+
const changePrimaryKey = (columnsPrimaryKey, {
|
|
897
|
+
codeTable,
|
|
898
|
+
dbTableData: { primaryKey: dbPrimaryKey },
|
|
899
|
+
changeTableAst: { shape, add, drop }
|
|
900
|
+
}) => {
|
|
901
|
+
var _a;
|
|
902
|
+
const tablePrimaryKey = codeTable.internal.primaryKey;
|
|
903
|
+
const primaryKey = [
|
|
904
|
+
.../* @__PURE__ */ new Set([...columnsPrimaryKey, ...(_a = tablePrimaryKey == null ? void 0 : tablePrimaryKey.columns) != null ? _a : []])
|
|
905
|
+
];
|
|
906
|
+
if (!dbPrimaryKey || primaryKey.length !== dbPrimaryKey.columns.length || primaryKey.some((a) => !dbPrimaryKey.columns.some((b) => a === b))) {
|
|
907
|
+
const toDrop = dbPrimaryKey == null ? void 0 : dbPrimaryKey.columns.filter(
|
|
908
|
+
(key) => !checkForColumnChange(shape, key)
|
|
909
|
+
);
|
|
910
|
+
if (toDrop == null ? void 0 : toDrop.length) {
|
|
911
|
+
drop.primaryKey = { columns: toDrop, options: dbPrimaryKey == null ? void 0 : dbPrimaryKey.options };
|
|
912
|
+
}
|
|
913
|
+
const toAdd = primaryKey.filter((key) => !checkForColumnChange(shape, key));
|
|
914
|
+
if (toAdd.length) {
|
|
915
|
+
add.primaryKey = {
|
|
916
|
+
columns: toAdd,
|
|
917
|
+
options: tablePrimaryKey == null ? void 0 : tablePrimaryKey.options
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
};
|
|
922
|
+
const renamePrimaryKey = (ast, {
|
|
923
|
+
codeTable,
|
|
924
|
+
dbTableData: { primaryKey: dbPrimaryKey },
|
|
925
|
+
schema
|
|
926
|
+
}) => {
|
|
927
|
+
var _a, _b, _c, _d, _e, _f;
|
|
928
|
+
const tablePrimaryKey = codeTable.internal.primaryKey;
|
|
929
|
+
if (dbPrimaryKey && tablePrimaryKey && ((_a = dbPrimaryKey == null ? void 0 : dbPrimaryKey.options) == null ? void 0 : _a.name) !== ((_b = tablePrimaryKey == null ? void 0 : tablePrimaryKey.options) == null ? void 0 : _b.name)) {
|
|
930
|
+
ast.push({
|
|
931
|
+
type: "renameTableItem",
|
|
932
|
+
kind: "CONSTRAINT",
|
|
933
|
+
tableSchema: schema,
|
|
934
|
+
tableName: codeTable.table,
|
|
935
|
+
from: (_d = (_c = dbPrimaryKey.options) == null ? void 0 : _c.name) != null ? _d : `${codeTable.table}_pkey`,
|
|
936
|
+
to: (_f = (_e = tablePrimaryKey.options) == null ? void 0 : _e.name) != null ? _f : `${codeTable}_pkey`
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
|
|
941
|
+
var __defProp$3 = Object.defineProperty;
|
|
942
|
+
var __defProps$3 = Object.defineProperties;
|
|
943
|
+
var __getOwnPropDescs$3 = Object.getOwnPropertyDescriptors;
|
|
944
|
+
var __getOwnPropSymbols$3 = Object.getOwnPropertySymbols;
|
|
945
|
+
var __hasOwnProp$3 = Object.prototype.hasOwnProperty;
|
|
946
|
+
var __propIsEnum$3 = Object.prototype.propertyIsEnumerable;
|
|
947
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
948
|
+
var __spreadValues$3 = (a, b) => {
|
|
949
|
+
for (var prop in b || (b = {}))
|
|
950
|
+
if (__hasOwnProp$3.call(b, prop))
|
|
951
|
+
__defNormalProp$3(a, prop, b[prop]);
|
|
952
|
+
if (__getOwnPropSymbols$3)
|
|
953
|
+
for (var prop of __getOwnPropSymbols$3(b)) {
|
|
954
|
+
if (__propIsEnum$3.call(b, prop))
|
|
955
|
+
__defNormalProp$3(a, prop, b[prop]);
|
|
956
|
+
}
|
|
957
|
+
return a;
|
|
958
|
+
};
|
|
959
|
+
var __spreadProps$3 = (a, b) => __defProps$3(a, __getOwnPropDescs$3(b));
|
|
960
|
+
var __objRest = (source, exclude) => {
|
|
961
|
+
var target = {};
|
|
962
|
+
for (var prop in source)
|
|
963
|
+
if (__hasOwnProp$3.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
964
|
+
target[prop] = source[prop];
|
|
965
|
+
if (source != null && __getOwnPropSymbols$3)
|
|
966
|
+
for (var prop of __getOwnPropSymbols$3(source)) {
|
|
967
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum$3.call(source, prop))
|
|
968
|
+
target[prop] = source[prop];
|
|
969
|
+
}
|
|
970
|
+
return target;
|
|
971
|
+
};
|
|
972
|
+
const processIndexes = (config, changeTableData, delayedAst, ast, compareExpressions) => {
|
|
973
|
+
const codeIndexes = collectCodeIndexes(changeTableData);
|
|
974
|
+
const codeComparableIndexes = collectCodeComparableIndexes(codeIndexes);
|
|
975
|
+
const skipCodeIndexes = /* @__PURE__ */ new Map();
|
|
976
|
+
const holdCodeIndexes = /* @__PURE__ */ new Map();
|
|
977
|
+
let wait = 0;
|
|
978
|
+
const {
|
|
979
|
+
changeTableAst: { shape }
|
|
980
|
+
} = changeTableData;
|
|
981
|
+
for (const dbIndex of changeTableData.dbTableData.indexes) {
|
|
982
|
+
const hasChangedColumn = dbIndex.columns.some(
|
|
983
|
+
(column) => "column" in column && checkForColumnChange(shape, column.column)
|
|
984
|
+
);
|
|
985
|
+
if (hasChangedColumn)
|
|
986
|
+
continue;
|
|
987
|
+
normalizeIndex(dbIndex);
|
|
988
|
+
const dbComparableIndex = indexToComparable(dbIndex);
|
|
989
|
+
const { columns: dbColumns } = dbIndex;
|
|
990
|
+
const { found, rename } = findMatchingIndexWithoutSql(
|
|
991
|
+
dbComparableIndex,
|
|
992
|
+
codeComparableIndexes,
|
|
993
|
+
codeIndexes,
|
|
994
|
+
skipCodeIndexes,
|
|
995
|
+
changeTableData.codeTable.table,
|
|
996
|
+
config
|
|
997
|
+
);
|
|
998
|
+
if (found.length && checkIfIndexHasSql(dbComparableIndex)) {
|
|
999
|
+
for (const codeIndex of found) {
|
|
1000
|
+
holdCodeIndexes.set(codeIndex, true);
|
|
1001
|
+
}
|
|
1002
|
+
const compare = [];
|
|
1003
|
+
for (let i = 0; i < dbIndex.columns.length; i++) {
|
|
1004
|
+
const column = dbIndex.columns[i];
|
|
1005
|
+
if (!("expression" in column))
|
|
1006
|
+
continue;
|
|
1007
|
+
compare.push({
|
|
1008
|
+
inDb: column.expression,
|
|
1009
|
+
inCode: found.map(
|
|
1010
|
+
(index) => index.columns[i].expression
|
|
1011
|
+
)
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
if (dbIndex.with) {
|
|
1015
|
+
compare.push({
|
|
1016
|
+
inDb: dbIndex.with,
|
|
1017
|
+
inCode: found.map((index) => index.options.with)
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
if (dbIndex.where) {
|
|
1021
|
+
compare.push({
|
|
1022
|
+
inDb: dbIndex.where,
|
|
1023
|
+
inCode: found.map((index) => index.options.where)
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
1026
|
+
wait++;
|
|
1027
|
+
compareExpressions.push({
|
|
1028
|
+
compare,
|
|
1029
|
+
handle(index) {
|
|
1030
|
+
var _a, _b;
|
|
1031
|
+
const codeIndex = index === void 0 ? void 0 : found[index];
|
|
1032
|
+
handleIndexChange(
|
|
1033
|
+
ast,
|
|
1034
|
+
changeTableData,
|
|
1035
|
+
dbIndex,
|
|
1036
|
+
dbColumns,
|
|
1037
|
+
codeIndex,
|
|
1038
|
+
index === void 0 ? void 0 : rename[index]
|
|
1039
|
+
);
|
|
1040
|
+
if (codeIndex) {
|
|
1041
|
+
holdCodeIndexes.delete(codeIndex);
|
|
1042
|
+
}
|
|
1043
|
+
if (!--wait && holdCodeIndexes.size) {
|
|
1044
|
+
((_b = (_a = changeTableData.changeTableAst.add).indexes) != null ? _b : _a.indexes = []).push(
|
|
1045
|
+
...holdCodeIndexes.keys()
|
|
1046
|
+
);
|
|
1047
|
+
if (!changeTableData.pushedAst) {
|
|
1048
|
+
changeTableData.pushedAst = true;
|
|
1049
|
+
ast.push(changeTableData.changeTableAst);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
});
|
|
1054
|
+
} else {
|
|
1055
|
+
handleIndexChange(
|
|
1056
|
+
delayedAst,
|
|
1057
|
+
changeTableData,
|
|
1058
|
+
dbIndex,
|
|
1059
|
+
dbColumns,
|
|
1060
|
+
found[0],
|
|
1061
|
+
rename[0]
|
|
1062
|
+
);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
const addIndexes = codeIndexes.filter(
|
|
1066
|
+
(index, i) => !skipCodeIndexes.has(i) && !holdCodeIndexes.has(index)
|
|
1067
|
+
);
|
|
1068
|
+
if (addIndexes.length) {
|
|
1069
|
+
changeTableData.changeTableAst.add.indexes = addIndexes;
|
|
1070
|
+
}
|
|
1071
|
+
};
|
|
1072
|
+
const collectCodeIndexes = ({
|
|
1073
|
+
codeTable,
|
|
1074
|
+
changeTableAst: { shape }
|
|
1075
|
+
}) => {
|
|
1076
|
+
var _a;
|
|
1077
|
+
const codeIndexes = [];
|
|
1078
|
+
for (const key in codeTable.shape) {
|
|
1079
|
+
const column = codeTable.shape[key];
|
|
1080
|
+
if (!column.data.indexes)
|
|
1081
|
+
continue;
|
|
1082
|
+
const name = (_a = column.data.name) != null ? _a : key;
|
|
1083
|
+
if (checkForColumnChange(shape, name))
|
|
1084
|
+
continue;
|
|
1085
|
+
codeIndexes.push(
|
|
1086
|
+
...column.data.indexes.map(
|
|
1087
|
+
(_b) => {
|
|
1088
|
+
var _c = _b, { collate, opclass, order, weight } = _c, options = __objRest(_c, ["collate", "opclass", "order", "weight"]);
|
|
1089
|
+
return {
|
|
1090
|
+
columns: [{ collate, opclass, order, weight, column: name }],
|
|
1091
|
+
options
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
)
|
|
1095
|
+
);
|
|
1096
|
+
}
|
|
1097
|
+
if (codeTable.internal.indexes) {
|
|
1098
|
+
codeIndexes.push(...codeTable.internal.indexes);
|
|
1099
|
+
}
|
|
1100
|
+
return codeIndexes;
|
|
1101
|
+
};
|
|
1102
|
+
const collectCodeComparableIndexes = (codeIndexes) => {
|
|
1103
|
+
return codeIndexes.map((codeIndex) => {
|
|
1104
|
+
normalizeIndex(codeIndex.options);
|
|
1105
|
+
return indexToComparable(__spreadProps$3(__spreadValues$3({}, codeIndex.options), {
|
|
1106
|
+
include: codeIndex.options.include === void 0 ? void 0 : orchidCore.toArray(codeIndex.options.include),
|
|
1107
|
+
columns: codeIndex.columns
|
|
1108
|
+
}));
|
|
1109
|
+
});
|
|
1110
|
+
};
|
|
1111
|
+
const normalizeIndex = (index) => {
|
|
1112
|
+
if (index.using === "btree")
|
|
1113
|
+
index.using = void 0;
|
|
1114
|
+
if (index.unique === false)
|
|
1115
|
+
index.unique = void 0;
|
|
1116
|
+
if (index.nullsNotDistinct === false)
|
|
1117
|
+
index.nullsNotDistinct = void 0;
|
|
1118
|
+
};
|
|
1119
|
+
const indexToComparable = (index) => {
|
|
1120
|
+
let hasExpression = false;
|
|
1121
|
+
const columns = index.columns.map((column) => {
|
|
1122
|
+
const result = __spreadProps$3(__spreadValues$3({}, column), {
|
|
1123
|
+
expression: void 0,
|
|
1124
|
+
hasExpression: "expression" in column
|
|
1125
|
+
});
|
|
1126
|
+
if (result.hasExpression)
|
|
1127
|
+
hasExpression = true;
|
|
1128
|
+
return result;
|
|
1129
|
+
});
|
|
1130
|
+
return __spreadProps$3(__spreadValues$3({}, index), {
|
|
1131
|
+
schemaName: void 0,
|
|
1132
|
+
tableName: void 0,
|
|
1133
|
+
with: void 0,
|
|
1134
|
+
hasWith: !!index.with,
|
|
1135
|
+
where: void 0,
|
|
1136
|
+
hasWhere: !!index.where,
|
|
1137
|
+
columns,
|
|
1138
|
+
hasExpression
|
|
1139
|
+
});
|
|
1140
|
+
};
|
|
1141
|
+
const findMatchingIndexWithoutSql = (dbIndex, codeComparableIndexes, codeIndexes, skipCodeIndexes, tableName, config) => {
|
|
1142
|
+
var _c, _d;
|
|
1143
|
+
const found = [];
|
|
1144
|
+
const rename = [];
|
|
1145
|
+
const _a = dbIndex, { columns: dbColumns } = _a, dbIndexWithoutColumns = __objRest(_a, ["columns"]);
|
|
1146
|
+
for (let i = 0; i < codeComparableIndexes.length; i++) {
|
|
1147
|
+
if (skipCodeIndexes.has(i))
|
|
1148
|
+
continue;
|
|
1149
|
+
const _b = codeComparableIndexes[i], { columns: codeColumns } = _b, codeIndex = __objRest(_b, ["columns"]);
|
|
1150
|
+
if (dbColumns.length === codeColumns.length && !dbColumns.some((dbColumn, i2) => !orchidCore.deepCompare(dbColumn, codeColumns[i2]))) {
|
|
1151
|
+
let a = dbIndexWithoutColumns;
|
|
1152
|
+
let b = codeIndex;
|
|
1153
|
+
const codeName = (_c = b.name) != null ? _c : rakeDb.getIndexName(tableName, dbColumns);
|
|
1154
|
+
if (a.name !== b.name) {
|
|
1155
|
+
a = __spreadProps$3(__spreadValues$3({}, a), { name: void 0 });
|
|
1156
|
+
b = __spreadProps$3(__spreadValues$3({}, b), { name: void 0 });
|
|
1157
|
+
if (a.language && !b.language) {
|
|
1158
|
+
b.language = (_d = config.language) != null ? _d : "english";
|
|
1159
|
+
}
|
|
1160
|
+
if (orchidCore.deepCompare(a, b)) {
|
|
1161
|
+
found.push(codeIndexes[i]);
|
|
1162
|
+
rename.push(
|
|
1163
|
+
dbIndexWithoutColumns.name !== codeName ? codeName : void 0
|
|
1164
|
+
);
|
|
1165
|
+
}
|
|
1166
|
+
} else if (orchidCore.deepCompare(dbIndexWithoutColumns, codeIndex)) {
|
|
1167
|
+
found.push(codeIndexes[i]);
|
|
1168
|
+
rename.push(void 0);
|
|
1169
|
+
}
|
|
1170
|
+
if (found.length && !checkIfIndexHasSql(codeIndex)) {
|
|
1171
|
+
skipCodeIndexes.set(i, true);
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
return { found, rename };
|
|
1176
|
+
};
|
|
1177
|
+
const checkIfIndexHasSql = (index) => index.hasWith || index.hasWhere || index.hasExpression;
|
|
1178
|
+
const handleIndexChange = (ast, { changeTableAst, schema, codeTable }, dbIndex, dbColumns, found, rename) => {
|
|
1179
|
+
var _a, _b;
|
|
1180
|
+
if (!found) {
|
|
1181
|
+
((_b = (_a = changeTableAst.drop).indexes) != null ? _b : _a.indexes = []).push({
|
|
1182
|
+
columns: dbColumns,
|
|
1183
|
+
options: dbIndex
|
|
1184
|
+
});
|
|
1185
|
+
} else if (rename) {
|
|
1186
|
+
ast.push({
|
|
1187
|
+
type: "renameTableItem",
|
|
1188
|
+
kind: "INDEX",
|
|
1189
|
+
tableSchema: schema,
|
|
1190
|
+
tableName: codeTable.table,
|
|
1191
|
+
from: dbIndex.name,
|
|
1192
|
+
to: rename
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1195
|
+
};
|
|
1196
|
+
|
|
1197
|
+
const mapMatchToDb = {
|
|
1198
|
+
FULL: "f",
|
|
1199
|
+
PARTIAL: "p",
|
|
1200
|
+
SIMPLE: "s"
|
|
1201
|
+
};
|
|
1202
|
+
const mapMatchToCode = {};
|
|
1203
|
+
for (const key in mapMatchToDb) {
|
|
1204
|
+
mapMatchToCode[mapMatchToDb[key]] = key;
|
|
1205
|
+
}
|
|
1206
|
+
const mapActionToDb = {
|
|
1207
|
+
"NO ACTION": "a",
|
|
1208
|
+
RESTRICT: "r",
|
|
1209
|
+
CASCADE: "c",
|
|
1210
|
+
"SET NULL": "n",
|
|
1211
|
+
"SET DEFAULT": "d"
|
|
1212
|
+
};
|
|
1213
|
+
const mapActionToCode = {};
|
|
1214
|
+
for (const key in mapActionToDb) {
|
|
1215
|
+
mapActionToCode[mapActionToDb[key]] = key;
|
|
1216
|
+
}
|
|
1217
|
+
const processForeignKeys = (ast, changeTables, currentSchema, tableShapes) => {
|
|
1218
|
+
var _a, _b, _c;
|
|
1219
|
+
for (const changeTableData of changeTables) {
|
|
1220
|
+
const codeForeignKeys = collectCodeFkeys(changeTableData, currentSchema);
|
|
1221
|
+
const { codeTable, dbTableData, changeTableAst, schema } = changeTableData;
|
|
1222
|
+
const { shape, add, drop } = changeTableAst;
|
|
1223
|
+
let changed = false;
|
|
1224
|
+
for (const dbConstraint of dbTableData.constraints) {
|
|
1225
|
+
const { references: dbReferences } = dbConstraint;
|
|
1226
|
+
if (!dbReferences)
|
|
1227
|
+
continue;
|
|
1228
|
+
const hasChangedColumn = dbReferences.columns.some(
|
|
1229
|
+
(column) => checkForColumnChange(shape, column)
|
|
1230
|
+
);
|
|
1231
|
+
if (hasChangedColumn)
|
|
1232
|
+
continue;
|
|
1233
|
+
const foreignShape = tableShapes[`${dbReferences.foreignSchema}.${dbReferences.foreignTable}`];
|
|
1234
|
+
const hasForeignChangedColumn = foreignShape && dbReferences.foreignColumns.some(
|
|
1235
|
+
(column) => checkForColumnChange(foreignShape, column)
|
|
1236
|
+
);
|
|
1237
|
+
if (hasForeignChangedColumn)
|
|
1238
|
+
continue;
|
|
1239
|
+
let found = false;
|
|
1240
|
+
let rename;
|
|
1241
|
+
for (let i = 0; i < codeForeignKeys.length; i++) {
|
|
1242
|
+
const codeForeignKey = codeForeignKeys[i];
|
|
1243
|
+
const codeReferences = codeForeignKey.references;
|
|
1244
|
+
if (orchidCore.deepCompare(dbReferences, codeReferences)) {
|
|
1245
|
+
found = true;
|
|
1246
|
+
codeForeignKeys.splice(i, 1);
|
|
1247
|
+
const codeName = (_a = codeForeignKey.codeConstraint.name) != null ? _a : rakeDb.getConstraintName(codeTable.table, codeForeignKey);
|
|
1248
|
+
if (codeName !== dbConstraint.name) {
|
|
1249
|
+
rename = codeName;
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
if (!found) {
|
|
1254
|
+
((_b = drop.constraints) != null ? _b : drop.constraints = []).push(
|
|
1255
|
+
dbForeignKeyToCodeForeignKey(dbConstraint, dbReferences)
|
|
1256
|
+
);
|
|
1257
|
+
changed = true;
|
|
1258
|
+
} else if (rename) {
|
|
1259
|
+
ast.push({
|
|
1260
|
+
type: "renameTableItem",
|
|
1261
|
+
kind: "CONSTRAINT",
|
|
1262
|
+
tableSchema: schema,
|
|
1263
|
+
tableName: codeTable.table,
|
|
1264
|
+
from: dbConstraint.name,
|
|
1265
|
+
to: rename
|
|
1266
|
+
});
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
if (codeForeignKeys.length) {
|
|
1270
|
+
((_c = add.constraints) != null ? _c : add.constraints = []).push(
|
|
1271
|
+
...codeForeignKeys.map((x) => x.codeConstraint)
|
|
1272
|
+
);
|
|
1273
|
+
changed = true;
|
|
1274
|
+
}
|
|
1275
|
+
if (changed && !changeTableData.pushedAst) {
|
|
1276
|
+
changeTableData.pushedAst = true;
|
|
1277
|
+
ast.push(changeTableData.changeTableAst);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
};
|
|
1281
|
+
const collectCodeFkeys = ({ codeTable, changeTableAst: { shape } }, currentSchema) => {
|
|
1282
|
+
var _a;
|
|
1283
|
+
const codeForeignKeys = [];
|
|
1284
|
+
for (const key in codeTable.shape) {
|
|
1285
|
+
const column = codeTable.shape[key];
|
|
1286
|
+
if (!column.data.foreignKeys)
|
|
1287
|
+
continue;
|
|
1288
|
+
const name = (_a = column.data.name) != null ? _a : key;
|
|
1289
|
+
if (checkForColumnChange(shape, name))
|
|
1290
|
+
continue;
|
|
1291
|
+
codeForeignKeys.push(
|
|
1292
|
+
...column.data.foreignKeys.map((x) => {
|
|
1293
|
+
const columns = [name];
|
|
1294
|
+
const references = {
|
|
1295
|
+
columns,
|
|
1296
|
+
fnOrTable: fnOrTableToString("fn" in x ? x.fn : x.table),
|
|
1297
|
+
foreignColumns: x.columns,
|
|
1298
|
+
options: {
|
|
1299
|
+
name: x.name,
|
|
1300
|
+
match: x.match,
|
|
1301
|
+
onUpdate: x.onUpdate,
|
|
1302
|
+
onDelete: x.onDelete
|
|
1303
|
+
}
|
|
1304
|
+
};
|
|
1305
|
+
return parseForeignKey(
|
|
1306
|
+
{
|
|
1307
|
+
name: x.name,
|
|
1308
|
+
references
|
|
1309
|
+
},
|
|
1310
|
+
references,
|
|
1311
|
+
currentSchema
|
|
1312
|
+
);
|
|
1313
|
+
})
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
if (codeTable.internal.constraints) {
|
|
1317
|
+
for (const constraint of codeTable.internal.constraints) {
|
|
1318
|
+
const { references } = constraint;
|
|
1319
|
+
if (!references)
|
|
1320
|
+
continue;
|
|
1321
|
+
references.fnOrTable = fnOrTableToString(references.fnOrTable);
|
|
1322
|
+
codeForeignKeys.push(
|
|
1323
|
+
parseForeignKey(
|
|
1324
|
+
constraint,
|
|
1325
|
+
references,
|
|
1326
|
+
currentSchema
|
|
1327
|
+
)
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
return codeForeignKeys;
|
|
1332
|
+
};
|
|
1333
|
+
const fnOrTableToString = (fnOrTable) => {
|
|
1334
|
+
if (typeof fnOrTable !== "string") {
|
|
1335
|
+
const { schema, table } = new (fnOrTable())();
|
|
1336
|
+
fnOrTable = rakeDb.concatSchemaAndName({ schema, name: table });
|
|
1337
|
+
}
|
|
1338
|
+
return fnOrTable;
|
|
1339
|
+
};
|
|
1340
|
+
const parseForeignKey = (codeConstraint, references, currentSchema) => {
|
|
1341
|
+
const { fnOrTable, columns, foreignColumns, options } = references;
|
|
1342
|
+
const [schema, table] = rakeDb.getSchemaAndTableFromName(fnOrTable);
|
|
1343
|
+
return {
|
|
1344
|
+
references: {
|
|
1345
|
+
foreignSchema: schema != null ? schema : currentSchema,
|
|
1346
|
+
foreignTable: table,
|
|
1347
|
+
columns,
|
|
1348
|
+
foreignColumns,
|
|
1349
|
+
match: mapMatchToDb[(options == null ? void 0 : options.match) || "SIMPLE"],
|
|
1350
|
+
onUpdate: mapActionToDb[(options == null ? void 0 : options.onUpdate) || "NO ACTION"],
|
|
1351
|
+
onDelete: mapActionToDb[(options == null ? void 0 : options.onDelete) || "NO ACTION"]
|
|
1352
|
+
},
|
|
1353
|
+
codeConstraint
|
|
1354
|
+
};
|
|
1355
|
+
};
|
|
1356
|
+
const dbForeignKeyToCodeForeignKey = (dbConstraint, dbReferences) => ({
|
|
1357
|
+
name: dbConstraint.name === rakeDb.getConstraintName(dbConstraint.tableName, { references: dbReferences }) ? void 0 : dbConstraint.name,
|
|
1358
|
+
references: {
|
|
1359
|
+
columns: dbReferences.columns,
|
|
1360
|
+
fnOrTable: `${dbReferences.foreignSchema}.${dbReferences.foreignTable}`,
|
|
1361
|
+
foreignColumns: dbReferences.foreignColumns,
|
|
1362
|
+
options: {
|
|
1363
|
+
match: dbReferences.match === "s" ? void 0 : mapMatchToCode[dbReferences.match],
|
|
1364
|
+
onUpdate: dbReferences.onUpdate === "a" ? void 0 : mapActionToCode[dbReferences.onUpdate],
|
|
1365
|
+
onDelete: dbReferences.onDelete === "a" ? void 0 : mapActionToCode[dbReferences.onDelete]
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
});
|
|
1369
|
+
|
|
1370
|
+
const processChecks = (ast, changeTableData, compareExpressions) => {
|
|
1371
|
+
var _a, _b;
|
|
1372
|
+
const codeChecks = collectCodeChecks(changeTableData);
|
|
1373
|
+
const {
|
|
1374
|
+
dbTableData,
|
|
1375
|
+
changeTableAst: { add, drop, shape }
|
|
1376
|
+
} = changeTableData;
|
|
1377
|
+
const hasDbChecks = dbTableData.constraints.some((c) => c.check);
|
|
1378
|
+
if (!hasDbChecks) {
|
|
1379
|
+
if (codeChecks.length) {
|
|
1380
|
+
((_a = add.constraints) != null ? _a : add.constraints = []).push(
|
|
1381
|
+
...codeChecks.map((check) => {
|
|
1382
|
+
var _a2;
|
|
1383
|
+
return {
|
|
1384
|
+
name: (_a2 = check.options) == null ? void 0 : _a2.name,
|
|
1385
|
+
check: check.sql
|
|
1386
|
+
};
|
|
1387
|
+
})
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
let wait = 0;
|
|
1393
|
+
const foundCodeChecks = /* @__PURE__ */ new Set();
|
|
1394
|
+
for (const dbConstraint of dbTableData.constraints) {
|
|
1395
|
+
const { check: dbCheck, name } = dbConstraint;
|
|
1396
|
+
if (!dbCheck)
|
|
1397
|
+
continue;
|
|
1398
|
+
const hasChangedColumn = (_b = dbCheck.columns) == null ? void 0 : _b.some(
|
|
1399
|
+
(column) => checkForColumnChange(shape, column)
|
|
1400
|
+
);
|
|
1401
|
+
if (hasChangedColumn)
|
|
1402
|
+
continue;
|
|
1403
|
+
if (codeChecks.length) {
|
|
1404
|
+
wait++;
|
|
1405
|
+
compareExpressions.push({
|
|
1406
|
+
compare: [
|
|
1407
|
+
{
|
|
1408
|
+
inDb: dbCheck.expression,
|
|
1409
|
+
inCode: codeChecks.map((check) => check.sql)
|
|
1410
|
+
}
|
|
1411
|
+
],
|
|
1412
|
+
handle(index) {
|
|
1413
|
+
var _a2;
|
|
1414
|
+
if (index !== void 0)
|
|
1415
|
+
return;
|
|
1416
|
+
dropCheck(drop, dbCheck, name);
|
|
1417
|
+
if (--wait === 0 && !changeTableData.pushedAst) {
|
|
1418
|
+
changeTableData.pushedAst = true;
|
|
1419
|
+
((_a2 = add.constraints) != null ? _a2 : add.constraints = []).push(
|
|
1420
|
+
...codeChecks.filter((_, i) => !foundCodeChecks.has(i)).map((check) => {
|
|
1421
|
+
var _a3;
|
|
1422
|
+
return {
|
|
1423
|
+
name: (_a3 = check.options) == null ? void 0 : _a3.name,
|
|
1424
|
+
check: check.sql
|
|
1425
|
+
};
|
|
1426
|
+
})
|
|
1427
|
+
);
|
|
1428
|
+
ast.push(changeTableData.changeTableAst);
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
});
|
|
1432
|
+
} else {
|
|
1433
|
+
dropCheck(drop, dbCheck, name);
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
};
|
|
1437
|
+
const collectCodeChecks = ({
|
|
1438
|
+
codeTable,
|
|
1439
|
+
changeTableAst: { shape }
|
|
1440
|
+
}) => {
|
|
1441
|
+
var _a;
|
|
1442
|
+
const codeChecks = [];
|
|
1443
|
+
for (const key in codeTable.shape) {
|
|
1444
|
+
const column = codeTable.shape[key];
|
|
1445
|
+
if (!column.data.check)
|
|
1446
|
+
continue;
|
|
1447
|
+
const name = (_a = column.data.name) != null ? _a : key;
|
|
1448
|
+
if (checkForColumnChange(shape, name))
|
|
1449
|
+
continue;
|
|
1450
|
+
codeChecks.push(column.data.check);
|
|
1451
|
+
}
|
|
1452
|
+
if (codeTable.internal.constraints) {
|
|
1453
|
+
for (const constraint of codeTable.internal.constraints) {
|
|
1454
|
+
const { check } = constraint;
|
|
1455
|
+
if (check) {
|
|
1456
|
+
codeChecks.push({ sql: check, options: { name: constraint.name } });
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
return codeChecks;
|
|
1461
|
+
};
|
|
1462
|
+
const dropCheck = (drop, dbCheck, name) => {
|
|
1463
|
+
var _a;
|
|
1464
|
+
((_a = drop.constraints) != null ? _a : drop.constraints = []).push({
|
|
1465
|
+
name,
|
|
1466
|
+
check: new pqb.RawSQL([[dbCheck.expression]])
|
|
1467
|
+
});
|
|
1468
|
+
};
|
|
1469
|
+
|
|
1470
|
+
var __defProp$2 = Object.defineProperty;
|
|
1471
|
+
var __defProps$2 = Object.defineProperties;
|
|
1472
|
+
var __getOwnPropDescs$2 = Object.getOwnPropertyDescriptors;
|
|
1473
|
+
var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols;
|
|
1474
|
+
var __hasOwnProp$2 = Object.prototype.hasOwnProperty;
|
|
1475
|
+
var __propIsEnum$2 = Object.prototype.propertyIsEnumerable;
|
|
1476
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1477
|
+
var __spreadValues$2 = (a, b) => {
|
|
1478
|
+
for (var prop in b || (b = {}))
|
|
1479
|
+
if (__hasOwnProp$2.call(b, prop))
|
|
1480
|
+
__defNormalProp$2(a, prop, b[prop]);
|
|
1481
|
+
if (__getOwnPropSymbols$2)
|
|
1482
|
+
for (var prop of __getOwnPropSymbols$2(b)) {
|
|
1483
|
+
if (__propIsEnum$2.call(b, prop))
|
|
1484
|
+
__defNormalProp$2(a, prop, b[prop]);
|
|
1485
|
+
}
|
|
1486
|
+
return a;
|
|
1487
|
+
};
|
|
1488
|
+
var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b));
|
|
1489
|
+
const processTables = async (ast, structureToAstCtx, domainsMap, adapter, tables, dbStructure, currentSchema, config, verifying) => {
|
|
1490
|
+
const createTables = collectCreateTables(
|
|
1491
|
+
tables,
|
|
1492
|
+
dbStructure,
|
|
1493
|
+
currentSchema
|
|
1494
|
+
);
|
|
1495
|
+
const compareSql = { values: [], expressions: [] };
|
|
1496
|
+
const tableExpressions = [];
|
|
1497
|
+
const { changeTables, changeTableSchemas, dropTables, tableShapes } = collectChangeAndDropTables(
|
|
1498
|
+
tables,
|
|
1499
|
+
dbStructure,
|
|
1500
|
+
currentSchema,
|
|
1501
|
+
createTables
|
|
1502
|
+
);
|
|
1503
|
+
applyChangeTableSchemas(changeTableSchemas, currentSchema, ast);
|
|
1504
|
+
await applyCreateOrRenameTables(
|
|
1505
|
+
dbStructure,
|
|
1506
|
+
createTables,
|
|
1507
|
+
dropTables,
|
|
1508
|
+
changeTables,
|
|
1509
|
+
tableShapes,
|
|
1510
|
+
currentSchema,
|
|
1511
|
+
ast,
|
|
1512
|
+
verifying
|
|
1513
|
+
);
|
|
1514
|
+
await applyChangeTables(
|
|
1515
|
+
adapter,
|
|
1516
|
+
changeTables,
|
|
1517
|
+
structureToAstCtx,
|
|
1518
|
+
dbStructure,
|
|
1519
|
+
domainsMap,
|
|
1520
|
+
ast,
|
|
1521
|
+
currentSchema,
|
|
1522
|
+
config,
|
|
1523
|
+
compareSql,
|
|
1524
|
+
tableExpressions,
|
|
1525
|
+
verifying
|
|
1526
|
+
);
|
|
1527
|
+
processForeignKeys(ast, changeTables, currentSchema, tableShapes);
|
|
1528
|
+
await Promise.all([
|
|
1529
|
+
applyCompareSql(compareSql, adapter),
|
|
1530
|
+
compareSqlExpressions(tableExpressions, adapter)
|
|
1531
|
+
]);
|
|
1532
|
+
for (const dbTable of dropTables) {
|
|
1533
|
+
ast.push(
|
|
1534
|
+
rakeDb.tableToAst(structureToAstCtx, dbStructure, dbTable, "drop", domainsMap)
|
|
1535
|
+
);
|
|
1536
|
+
}
|
|
1537
|
+
};
|
|
1538
|
+
const collectCreateTables = (tables, dbStructure, currentSchema) => {
|
|
1539
|
+
return tables.reduce((acc, codeTable) => {
|
|
1540
|
+
var _a;
|
|
1541
|
+
const tableSchema = (_a = codeTable.q.schema) != null ? _a : currentSchema;
|
|
1542
|
+
const hasDbTable = dbStructure.tables.some(
|
|
1543
|
+
(t) => t.name === codeTable.table && t.schemaName === tableSchema
|
|
1544
|
+
);
|
|
1545
|
+
if (!hasDbTable) {
|
|
1546
|
+
acc.push(codeTable);
|
|
1547
|
+
}
|
|
1548
|
+
return acc;
|
|
1549
|
+
}, []);
|
|
1550
|
+
};
|
|
1551
|
+
const collectChangeAndDropTables = (tables, dbStructure, currentSchema, createTables) => {
|
|
1552
|
+
const changeTables = [];
|
|
1553
|
+
const changeTableSchemas = [];
|
|
1554
|
+
const dropTables = [];
|
|
1555
|
+
const tableShapes = {};
|
|
1556
|
+
for (const dbTable of dbStructure.tables) {
|
|
1557
|
+
if (dbTable.name === "schemaMigrations")
|
|
1558
|
+
continue;
|
|
1559
|
+
const codeTable = tables.find(
|
|
1560
|
+
(t) => {
|
|
1561
|
+
var _a;
|
|
1562
|
+
return t.table === dbTable.name && ((_a = t.q.schema) != null ? _a : currentSchema) === dbTable.schemaName;
|
|
1563
|
+
}
|
|
1564
|
+
);
|
|
1565
|
+
if (codeTable) {
|
|
1566
|
+
addChangeTable(
|
|
1567
|
+
dbStructure,
|
|
1568
|
+
changeTables,
|
|
1569
|
+
tableShapes,
|
|
1570
|
+
currentSchema,
|
|
1571
|
+
dbTable,
|
|
1572
|
+
codeTable
|
|
1573
|
+
);
|
|
1574
|
+
continue;
|
|
1575
|
+
}
|
|
1576
|
+
const i = createTables.findIndex((t) => t.table === dbTable.name);
|
|
1577
|
+
if (i !== -1) {
|
|
1578
|
+
const codeTable2 = createTables[i];
|
|
1579
|
+
createTables.splice(i, 1);
|
|
1580
|
+
changeTableSchemas.push({ codeTable: codeTable2, dbTable });
|
|
1581
|
+
continue;
|
|
1582
|
+
}
|
|
1583
|
+
dropTables.push(dbTable);
|
|
1584
|
+
}
|
|
1585
|
+
return { changeTables, changeTableSchemas, dropTables, tableShapes };
|
|
1586
|
+
};
|
|
1587
|
+
const applyChangeTableSchemas = (changeTableSchemas, currentSchema, ast) => {
|
|
1588
|
+
var _a;
|
|
1589
|
+
for (const { codeTable, dbTable } of changeTableSchemas) {
|
|
1590
|
+
const fromSchema = dbTable.schemaName;
|
|
1591
|
+
const toSchema = (_a = codeTable.q.schema) != null ? _a : currentSchema;
|
|
1592
|
+
ast.push({
|
|
1593
|
+
type: "renameType",
|
|
1594
|
+
kind: "TABLE",
|
|
1595
|
+
fromSchema,
|
|
1596
|
+
from: dbTable.name,
|
|
1597
|
+
toSchema,
|
|
1598
|
+
to: dbTable.name
|
|
1599
|
+
});
|
|
1600
|
+
}
|
|
1601
|
+
};
|
|
1602
|
+
const applyChangeTables = async (adapter, changeTables, structureToAstCtx, dbStructure, domainsMap, ast, currentSchema, config, compareSql, tableExpressions, verifying) => {
|
|
1603
|
+
var _a;
|
|
1604
|
+
const compareExpressions = [];
|
|
1605
|
+
const typeCastsCache = {};
|
|
1606
|
+
for (const changeTableData of changeTables) {
|
|
1607
|
+
compareExpressions.length = 0;
|
|
1608
|
+
await processTableChange(
|
|
1609
|
+
adapter,
|
|
1610
|
+
structureToAstCtx,
|
|
1611
|
+
dbStructure,
|
|
1612
|
+
domainsMap,
|
|
1613
|
+
ast,
|
|
1614
|
+
currentSchema,
|
|
1615
|
+
config,
|
|
1616
|
+
changeTableData,
|
|
1617
|
+
compareSql,
|
|
1618
|
+
compareExpressions,
|
|
1619
|
+
typeCastsCache,
|
|
1620
|
+
verifying
|
|
1621
|
+
);
|
|
1622
|
+
if (compareExpressions.length) {
|
|
1623
|
+
const { codeTable } = changeTableData;
|
|
1624
|
+
const names = [];
|
|
1625
|
+
const types = [];
|
|
1626
|
+
for (const key in codeTable.shape) {
|
|
1627
|
+
const column = codeTable.shape[key];
|
|
1628
|
+
if (!column.dataType)
|
|
1629
|
+
continue;
|
|
1630
|
+
const name = (_a = column.data.name) != null ? _a : key;
|
|
1631
|
+
names.push(name);
|
|
1632
|
+
types.push(getColumnDbType(column, currentSchema));
|
|
1633
|
+
}
|
|
1634
|
+
const tableName = codeTable.table;
|
|
1635
|
+
const source = `(VALUES (${types.map((x) => `NULL::${x}`).join(", ")})) "${tableName}"(${names.map((x) => `"${x}"`).join(", ")})`;
|
|
1636
|
+
tableExpressions.push(
|
|
1637
|
+
...compareExpressions.map((x) => __spreadProps$2(__spreadValues$2({}, x), { source }))
|
|
1638
|
+
);
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
};
|
|
1642
|
+
const applyCompareSql = async (compareSql, adapter) => {
|
|
1643
|
+
if (compareSql.expressions.length) {
|
|
1644
|
+
const {
|
|
1645
|
+
rows: [results]
|
|
1646
|
+
} = await adapter.arrays({
|
|
1647
|
+
text: "SELECT " + compareSql.expressions.map((x) => `${x.inDb} = (${x.inCode})`).join(", "),
|
|
1648
|
+
values: compareSql.values
|
|
1649
|
+
});
|
|
1650
|
+
for (let i = 0; i < results.length; i++) {
|
|
1651
|
+
if (!results[i]) {
|
|
1652
|
+
compareSql.expressions[i].change();
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
};
|
|
1657
|
+
const applyCreateOrRenameTables = async (dbStructure, createTables, dropTables, changeTables, tableShapes, currentSchema, ast, verifying) => {
|
|
1658
|
+
var _a;
|
|
1659
|
+
for (const codeTable of createTables) {
|
|
1660
|
+
if (dropTables.length) {
|
|
1661
|
+
const index = await promptCreateOrRename(
|
|
1662
|
+
"table",
|
|
1663
|
+
codeTable.table,
|
|
1664
|
+
dropTables.map((x) => x.name),
|
|
1665
|
+
verifying
|
|
1666
|
+
);
|
|
1667
|
+
if (index) {
|
|
1668
|
+
const dbTable = dropTables[index - 1];
|
|
1669
|
+
dropTables.splice(index - 1, 1);
|
|
1670
|
+
ast.push({
|
|
1671
|
+
type: "renameType",
|
|
1672
|
+
kind: "TABLE",
|
|
1673
|
+
fromSchema: dbTable.schemaName,
|
|
1674
|
+
from: dbTable.name,
|
|
1675
|
+
toSchema: (_a = codeTable.q.schema) != null ? _a : currentSchema,
|
|
1676
|
+
to: codeTable.table
|
|
1677
|
+
});
|
|
1678
|
+
addChangeTable(
|
|
1679
|
+
dbStructure,
|
|
1680
|
+
changeTables,
|
|
1681
|
+
tableShapes,
|
|
1682
|
+
currentSchema,
|
|
1683
|
+
dbTable,
|
|
1684
|
+
codeTable
|
|
1685
|
+
);
|
|
1686
|
+
continue;
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
ast.push(createTableAst(currentSchema, codeTable));
|
|
1690
|
+
}
|
|
1691
|
+
};
|
|
1692
|
+
const addChangeTable = (dbStructure, changeTables, tableShapes, currentSchema, dbTable, codeTable) => {
|
|
1693
|
+
var _a;
|
|
1694
|
+
const shape = {};
|
|
1695
|
+
const schema = (_a = codeTable.q.schema) != null ? _a : currentSchema;
|
|
1696
|
+
changeTables.push({
|
|
1697
|
+
codeTable,
|
|
1698
|
+
dbTable,
|
|
1699
|
+
dbTableData: rakeDb.getDbStructureTableData(dbStructure, dbTable),
|
|
1700
|
+
schema,
|
|
1701
|
+
changeTableAst: {
|
|
1702
|
+
type: "changeTable",
|
|
1703
|
+
schema,
|
|
1704
|
+
name: codeTable.table,
|
|
1705
|
+
shape,
|
|
1706
|
+
add: {},
|
|
1707
|
+
drop: {}
|
|
1708
|
+
},
|
|
1709
|
+
pushedAst: false
|
|
1710
|
+
});
|
|
1711
|
+
tableShapes[`${schema}.${codeTable.table}`] = shape;
|
|
1712
|
+
};
|
|
1713
|
+
const createTableAst = (currentSchema, table) => {
|
|
1714
|
+
return __spreadProps$2(__spreadValues$2({
|
|
1715
|
+
type: "table",
|
|
1716
|
+
action: "create",
|
|
1717
|
+
schema: table.q.schema === currentSchema ? void 0 : table.q.schema,
|
|
1718
|
+
comment: table.internal.comment,
|
|
1719
|
+
name: table.table,
|
|
1720
|
+
shape: makeTableShape(table)
|
|
1721
|
+
}, table.internal), {
|
|
1722
|
+
noPrimaryKey: table.internal.noPrimaryKey ? "ignore" : "error"
|
|
1723
|
+
});
|
|
1724
|
+
};
|
|
1725
|
+
const makeTableShape = (table) => {
|
|
1726
|
+
const shape = {};
|
|
1727
|
+
for (const key in table.shape) {
|
|
1728
|
+
const column = table.shape[key];
|
|
1729
|
+
if (!(column instanceof pqb.VirtualColumn)) {
|
|
1730
|
+
shape[key] = column;
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
return shape;
|
|
1734
|
+
};
|
|
1735
|
+
const processTableChange = async (adapter, structureToAstCtx, dbStructure, domainsMap, ast, currentSchema, config, changeTableData, compareSql, compareExpressions, typeCastsCache, verifying) => {
|
|
1736
|
+
await processColumns(
|
|
1737
|
+
adapter,
|
|
1738
|
+
structureToAstCtx,
|
|
1739
|
+
dbStructure,
|
|
1740
|
+
domainsMap,
|
|
1741
|
+
changeTableData,
|
|
1742
|
+
ast,
|
|
1743
|
+
currentSchema,
|
|
1744
|
+
compareSql,
|
|
1745
|
+
typeCastsCache,
|
|
1746
|
+
verifying
|
|
1747
|
+
);
|
|
1748
|
+
const delayedAst = [];
|
|
1749
|
+
processPrimaryKey(delayedAst, changeTableData);
|
|
1750
|
+
processIndexes(config, changeTableData, delayedAst, ast, compareExpressions);
|
|
1751
|
+
processChecks(ast, changeTableData, compareExpressions);
|
|
1752
|
+
const { changeTableAst } = changeTableData;
|
|
1753
|
+
if (Object.keys(changeTableAst.shape).length || Object.keys(changeTableAst.add).length || Object.keys(changeTableAst.drop).length) {
|
|
1754
|
+
changeTableData.pushedAst = true;
|
|
1755
|
+
ast.push(changeTableAst);
|
|
1756
|
+
}
|
|
1757
|
+
if (delayedAst.length)
|
|
1758
|
+
ast.push(...delayedAst);
|
|
1759
|
+
};
|
|
1760
|
+
|
|
1761
|
+
const composeMigration = async (adapter, config, ast, dbStructure, {
|
|
1762
|
+
structureToAstCtx,
|
|
1763
|
+
codeItems: { schemas, enums, tables, domains },
|
|
1764
|
+
currentSchema,
|
|
1765
|
+
internal,
|
|
1766
|
+
verifying
|
|
1767
|
+
}) => {
|
|
1768
|
+
const domainsMap = rakeDb.makeDomainsMap(structureToAstCtx, dbStructure);
|
|
1769
|
+
await processSchemas(ast, schemas, dbStructure, verifying);
|
|
1770
|
+
processExtensions(ast, dbStructure, currentSchema, internal.extensions);
|
|
1771
|
+
await processDomains(
|
|
1772
|
+
ast,
|
|
1773
|
+
adapter,
|
|
1774
|
+
structureToAstCtx,
|
|
1775
|
+
domainsMap,
|
|
1776
|
+
dbStructure,
|
|
1777
|
+
currentSchema,
|
|
1778
|
+
domains
|
|
1779
|
+
);
|
|
1780
|
+
await processEnums(ast, enums, dbStructure, currentSchema, verifying);
|
|
1781
|
+
await processTables(
|
|
1782
|
+
ast,
|
|
1783
|
+
structureToAstCtx,
|
|
1784
|
+
domainsMap,
|
|
1785
|
+
adapter,
|
|
1786
|
+
tables,
|
|
1787
|
+
dbStructure,
|
|
1788
|
+
currentSchema,
|
|
1789
|
+
config,
|
|
1790
|
+
verifying
|
|
1791
|
+
);
|
|
1792
|
+
return rakeDb.astToMigration(currentSchema, config, ast);
|
|
1793
|
+
};
|
|
1794
|
+
|
|
1795
|
+
const verifyMigration = async (adapter, config, migrationCode, generateMigrationParams) => {
|
|
1796
|
+
const migrationFn = new Function("change", migrationCode);
|
|
1797
|
+
return adapter.transaction(
|
|
1798
|
+
{ text: "BEGIN" },
|
|
1799
|
+
async (trx) => {
|
|
1800
|
+
const changeFns = [];
|
|
1801
|
+
migrationFn((changeCb) => {
|
|
1802
|
+
changeFns.push(changeCb);
|
|
1803
|
+
});
|
|
1804
|
+
const { log } = config;
|
|
1805
|
+
config.log = false;
|
|
1806
|
+
const db = rakeDb.createMigrationInterface(trx, true, config);
|
|
1807
|
+
config.log = log;
|
|
1808
|
+
for (const changeFn of changeFns) {
|
|
1809
|
+
await changeFn(db, true);
|
|
1810
|
+
}
|
|
1811
|
+
const dbStructure = await rakeDb.introspectDbSchema(trx);
|
|
1812
|
+
generateMigrationParams.verifying = true;
|
|
1813
|
+
let code;
|
|
1814
|
+
try {
|
|
1815
|
+
code = await composeMigration(
|
|
1816
|
+
adapter,
|
|
1817
|
+
config,
|
|
1818
|
+
[],
|
|
1819
|
+
dbStructure,
|
|
1820
|
+
generateMigrationParams
|
|
1821
|
+
);
|
|
1822
|
+
} catch (err) {
|
|
1823
|
+
if (err instanceof AbortSignal) {
|
|
1824
|
+
return false;
|
|
1825
|
+
}
|
|
1826
|
+
throw err;
|
|
1827
|
+
}
|
|
1828
|
+
return code;
|
|
1829
|
+
},
|
|
1830
|
+
{ text: "ROLLBACK" }
|
|
1831
|
+
);
|
|
1832
|
+
};
|
|
1833
|
+
|
|
1834
|
+
const report = (ast, config, currentSchema) => {
|
|
1835
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1836
|
+
if (!config.logger)
|
|
1837
|
+
return;
|
|
1838
|
+
const code = [];
|
|
1839
|
+
let green, red, yellow, pale;
|
|
1840
|
+
if (typeof config.log === "object" && config.log.colors === false) {
|
|
1841
|
+
green = red = yellow = pale = (s) => s;
|
|
1842
|
+
} else {
|
|
1843
|
+
({ green, red, yellow, pale } = rakeDb.colors);
|
|
1844
|
+
}
|
|
1845
|
+
for (const a of ast) {
|
|
1846
|
+
switch (a.type) {
|
|
1847
|
+
case "table": {
|
|
1848
|
+
let hasPrimaryKey = !!a.primaryKey;
|
|
1849
|
+
const counters = {
|
|
1850
|
+
column: 0,
|
|
1851
|
+
index: (_b = (_a = a.indexes) == null ? void 0 : _a.length) != null ? _b : 0,
|
|
1852
|
+
"foreign key": (_d = (_c = a.constraints) == null ? void 0 : _c.reduce(
|
|
1853
|
+
(sum, c) => c.references ? sum + 1 : sum,
|
|
1854
|
+
0
|
|
1855
|
+
)) != null ? _d : 0,
|
|
1856
|
+
check: (_f = (_e = a.constraints) == null ? void 0 : _e.reduce(
|
|
1857
|
+
(sum, c) => c.check ? sum + 1 : sum,
|
|
1858
|
+
0
|
|
1859
|
+
)) != null ? _f : 0
|
|
1860
|
+
};
|
|
1861
|
+
for (const key in a.shape) {
|
|
1862
|
+
counters.column++;
|
|
1863
|
+
const column = a.shape[key];
|
|
1864
|
+
if (column.data.primaryKey) {
|
|
1865
|
+
hasPrimaryKey = true;
|
|
1866
|
+
}
|
|
1867
|
+
if (column.data.indexes) {
|
|
1868
|
+
counters.index += column.data.indexes.length;
|
|
1869
|
+
}
|
|
1870
|
+
if (column.data.foreignKeys) {
|
|
1871
|
+
counters["foreign key"] += column.data.foreignKeys.length;
|
|
1872
|
+
}
|
|
1873
|
+
if (column.data.check) {
|
|
1874
|
+
counters.check++;
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
const summary = [];
|
|
1878
|
+
for (const key in counters) {
|
|
1879
|
+
const value = counters[key];
|
|
1880
|
+
if (value || key === "column") {
|
|
1881
|
+
summary.push(
|
|
1882
|
+
`${value} ${rakeDb.pluralize(key, value, key === "index" ? "es" : "s")}`
|
|
1883
|
+
);
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
if (!hasPrimaryKey) {
|
|
1887
|
+
summary.push("no primary key");
|
|
1888
|
+
}
|
|
1889
|
+
code.push(
|
|
1890
|
+
`${a.action === "create" ? green("+ create table") : red("- drop table")} ${dbItemName(a, currentSchema)} (${summary.join(", ")})`
|
|
1891
|
+
);
|
|
1892
|
+
break;
|
|
1893
|
+
}
|
|
1894
|
+
case "changeTable": {
|
|
1895
|
+
const inner = [];
|
|
1896
|
+
for (const key in a.shape) {
|
|
1897
|
+
const changes = orchidCore.toArray(a.shape[key]);
|
|
1898
|
+
for (const change of changes) {
|
|
1899
|
+
if (change.type === "add" || change.type === "drop") {
|
|
1900
|
+
const column = change.item;
|
|
1901
|
+
const name = (_g = column.data.name) != null ? _g : key;
|
|
1902
|
+
const { primaryKey, indexes, foreignKeys, check } = column.data;
|
|
1903
|
+
inner.push(
|
|
1904
|
+
`${change.type === "add" ? green("+ add column") : red("- drop column")} ${name} ${(_h = column.data.alias) != null ? _h : getColumnDbType(column, currentSchema)}${column.data.isNullable ? " nullable" : ""}${primaryKey ? " primary key" : ""}${foreignKeys ? ` references ${foreignKeys.map((fk) => {
|
|
1905
|
+
return `${fnOrTableToString(
|
|
1906
|
+
"fn" in fk ? fk.fn : fk.table
|
|
1907
|
+
)}(${fk.columns.join(", ")})`;
|
|
1908
|
+
}).join(", ")}` : ""}${(indexes == null ? void 0 : indexes.length) ? indexes.length === 1 ? ", has index" : `, has ${indexes.length} indexes` : ""}${check ? `, checks ${check.sql.toSQL({ values: [] })}` : ""}`
|
|
1909
|
+
);
|
|
1910
|
+
} else if (change.type === "change") {
|
|
1911
|
+
const name = (_j = (_i = change.from.column) == null ? void 0 : _i.data.name) != null ? _j : key;
|
|
1912
|
+
const changes2 = [];
|
|
1913
|
+
inner.push(`${yellow("~ change column")} ${name}:`, changes2);
|
|
1914
|
+
changes2.push(`${yellow("from")}: `);
|
|
1915
|
+
for (const code2 of change.from.column.toCode("t", true)) {
|
|
1916
|
+
orchidCore.addCode(changes2, code2);
|
|
1917
|
+
}
|
|
1918
|
+
changes2.push(` ${yellow("to")}: `);
|
|
1919
|
+
for (const code2 of change.to.column.toCode("t", true)) {
|
|
1920
|
+
orchidCore.addCode(changes2, code2);
|
|
1921
|
+
}
|
|
1922
|
+
} else if (change.type === "rename") {
|
|
1923
|
+
inner.push(
|
|
1924
|
+
`${yellow("~ rename column")} ${key} ${yellow("=>")} ${change.name}`
|
|
1925
|
+
);
|
|
1926
|
+
} else {
|
|
1927
|
+
rakeDb.exhaustive(change.type);
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
if (a.drop.primaryKey) {
|
|
1932
|
+
inner.push(
|
|
1933
|
+
`${red(`- drop primary key`)} on (${a.drop.primaryKey.columns.join(
|
|
1934
|
+
", "
|
|
1935
|
+
)})`
|
|
1936
|
+
);
|
|
1937
|
+
}
|
|
1938
|
+
if (a.drop.indexes) {
|
|
1939
|
+
for (const index of a.drop.indexes) {
|
|
1940
|
+
inner.push(
|
|
1941
|
+
`${red(
|
|
1942
|
+
`- drop${index.options.unique ? " unique" : ""} index`
|
|
1943
|
+
)} on (${index.columns.map((c) => "column" in c ? c.column : c.expression).join(", ")})`
|
|
1944
|
+
);
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
if (a.drop.constraints) {
|
|
1948
|
+
for (const { references } of a.drop.constraints) {
|
|
1949
|
+
if (!references)
|
|
1950
|
+
continue;
|
|
1951
|
+
const [schema, name] = rakeDb.getSchemaAndTableFromName(
|
|
1952
|
+
references.fnOrTable
|
|
1953
|
+
);
|
|
1954
|
+
inner.push(
|
|
1955
|
+
`${red(`- drop foreign key`)} on (${references.columns.join(
|
|
1956
|
+
", "
|
|
1957
|
+
)}) to ${dbItemName(
|
|
1958
|
+
{
|
|
1959
|
+
schema,
|
|
1960
|
+
name
|
|
1961
|
+
},
|
|
1962
|
+
currentSchema
|
|
1963
|
+
)}(${references.foreignColumns.join(", ")})`
|
|
1964
|
+
);
|
|
1965
|
+
}
|
|
1966
|
+
for (const { check } of a.drop.constraints) {
|
|
1967
|
+
if (!check)
|
|
1968
|
+
continue;
|
|
1969
|
+
inner.push(`${red(`- drop check`)} ${check.toSQL({ values: [] })}`);
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
if (a.add.primaryKey) {
|
|
1973
|
+
inner.push(
|
|
1974
|
+
`${green(`+ add primary key`)} on (${a.add.primaryKey.columns.join(
|
|
1975
|
+
", "
|
|
1976
|
+
)})`
|
|
1977
|
+
);
|
|
1978
|
+
}
|
|
1979
|
+
if (a.add.indexes) {
|
|
1980
|
+
for (const index of a.add.indexes) {
|
|
1981
|
+
inner.push(
|
|
1982
|
+
`${green(
|
|
1983
|
+
`+ add${index.options.unique ? " unique" : ""} index`
|
|
1984
|
+
)} on (${index.columns.map((c) => "column" in c ? c.column : c.expression).join(", ")})`
|
|
1985
|
+
);
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
if (a.add.constraints) {
|
|
1989
|
+
for (const { references } of a.add.constraints) {
|
|
1990
|
+
if (!references)
|
|
1991
|
+
continue;
|
|
1992
|
+
inner.push(
|
|
1993
|
+
`${green(`+ add foreign key`)} on (${references.columns.join(
|
|
1994
|
+
", "
|
|
1995
|
+
)}) to ${references.fnOrTable}(${references.foreignColumns.join(", ")})`
|
|
1996
|
+
);
|
|
1997
|
+
}
|
|
1998
|
+
for (const { check } of a.add.constraints) {
|
|
1999
|
+
if (!check)
|
|
2000
|
+
continue;
|
|
2001
|
+
inner.push(
|
|
2002
|
+
`${green(`+ add check`)} ${check.toSQL({ values: [] })}`
|
|
2003
|
+
);
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
code.push(
|
|
2007
|
+
`${yellow("~ change table")} ${dbItemName(a, currentSchema)}${inner.length ? ":" : ""}`
|
|
2008
|
+
);
|
|
2009
|
+
if (inner.length) {
|
|
2010
|
+
code.push(inner);
|
|
2011
|
+
}
|
|
2012
|
+
break;
|
|
2013
|
+
}
|
|
2014
|
+
case "schema": {
|
|
2015
|
+
code.push(
|
|
2016
|
+
`${a.action === "create" ? green("+ create schema") : red("- drop schema")} ${a.name}`
|
|
2017
|
+
);
|
|
2018
|
+
break;
|
|
2019
|
+
}
|
|
2020
|
+
case "renameSchema": {
|
|
2021
|
+
code.push(
|
|
2022
|
+
`${yellow("~ rename schema")} ${a.from} ${yellow("=>")} ${a.to}`
|
|
2023
|
+
);
|
|
2024
|
+
break;
|
|
2025
|
+
}
|
|
2026
|
+
case "renameType": {
|
|
2027
|
+
code.push(
|
|
2028
|
+
`${yellow(
|
|
2029
|
+
`~ ${a.fromSchema !== a.toSchema ? a.from !== a.to ? "change schema and rename" : "change schema of" : "rename"} ${a.kind.toLowerCase()}`
|
|
2030
|
+
)} ${dbItemName(
|
|
2031
|
+
{
|
|
2032
|
+
schema: a.fromSchema,
|
|
2033
|
+
name: a.from
|
|
2034
|
+
},
|
|
2035
|
+
currentSchema
|
|
2036
|
+
)} ${yellow("=>")} ${dbItemName(
|
|
2037
|
+
{
|
|
2038
|
+
schema: a.toSchema,
|
|
2039
|
+
name: a.to
|
|
2040
|
+
},
|
|
2041
|
+
currentSchema
|
|
2042
|
+
)}`
|
|
2043
|
+
);
|
|
2044
|
+
break;
|
|
2045
|
+
}
|
|
2046
|
+
case "extension": {
|
|
2047
|
+
code.push(
|
|
2048
|
+
`${a.action === "create" ? green("+ create extension") : red("- drop extension")} ${dbItemName(a, currentSchema)}${a.version ? ` ${pale(a.version)}` : ""}`
|
|
2049
|
+
);
|
|
2050
|
+
break;
|
|
2051
|
+
}
|
|
2052
|
+
case "enum": {
|
|
2053
|
+
code.push(
|
|
2054
|
+
`${a.action === "create" ? green("+ create enum") : red("- drop enum")} ${dbItemName(a, currentSchema)}: (${a.values.join(", ")})`
|
|
2055
|
+
);
|
|
2056
|
+
break;
|
|
2057
|
+
}
|
|
2058
|
+
case "enumValues": {
|
|
2059
|
+
code.push(
|
|
2060
|
+
`${a.action === "add" ? green("+ add values to enum") : red("- remove values from enum")} ${dbItemName(a, currentSchema)}: ${a.values.join(", ")}`
|
|
2061
|
+
);
|
|
2062
|
+
break;
|
|
2063
|
+
}
|
|
2064
|
+
case "changeEnumValues": {
|
|
2065
|
+
if (a.fromValues) {
|
|
2066
|
+
code.push(
|
|
2067
|
+
`${red("- remove values from enum")} ${dbItemName(
|
|
2068
|
+
a,
|
|
2069
|
+
currentSchema
|
|
2070
|
+
)}: ${a.fromValues.join(", ")}`
|
|
2071
|
+
);
|
|
2072
|
+
}
|
|
2073
|
+
if (a.toValues) {
|
|
2074
|
+
code.push(
|
|
2075
|
+
`${green("+ add values to enum")} ${dbItemName(
|
|
2076
|
+
a,
|
|
2077
|
+
currentSchema
|
|
2078
|
+
)}: ${a.toValues.join(", ")}`
|
|
2079
|
+
);
|
|
2080
|
+
}
|
|
2081
|
+
break;
|
|
2082
|
+
}
|
|
2083
|
+
case "domain": {
|
|
2084
|
+
code.push(
|
|
2085
|
+
`${a.action === "create" ? green("+ create domain") : red("- drop domain")} ${dbItemName(a, currentSchema)}`
|
|
2086
|
+
);
|
|
2087
|
+
break;
|
|
2088
|
+
}
|
|
2089
|
+
case "view":
|
|
2090
|
+
case "collation":
|
|
2091
|
+
case "renameEnumValues":
|
|
2092
|
+
case "constraint":
|
|
2093
|
+
break;
|
|
2094
|
+
case "renameTableItem": {
|
|
2095
|
+
code.push(
|
|
2096
|
+
`${yellow(`~ rename ${a.kind.toLowerCase()}`)} on table ${dbItemName(
|
|
2097
|
+
{ schema: a.tableSchema, name: a.tableName },
|
|
2098
|
+
currentSchema
|
|
2099
|
+
)}: ${a.from} ${yellow("=>")} ${a.to}`
|
|
2100
|
+
);
|
|
2101
|
+
break;
|
|
2102
|
+
}
|
|
2103
|
+
default:
|
|
2104
|
+
rakeDb.exhaustive(a);
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
const result = orchidCore.codeToString(code, "", " ");
|
|
2108
|
+
config.logger.log(result);
|
|
2109
|
+
};
|
|
2110
|
+
const dbItemName = ({ schema, name }, currentSchema) => {
|
|
2111
|
+
return schema && schema !== currentSchema ? `${schema}.${name}` : name;
|
|
2112
|
+
};
|
|
2113
|
+
|
|
2114
|
+
var __defProp$1 = Object.defineProperty;
|
|
2115
|
+
var __defProps$1 = Object.defineProperties;
|
|
2116
|
+
var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors;
|
|
2117
|
+
var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
|
|
2118
|
+
var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
|
|
2119
|
+
var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
|
|
2120
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2121
|
+
var __spreadValues$1 = (a, b) => {
|
|
2122
|
+
for (var prop in b || (b = {}))
|
|
2123
|
+
if (__hasOwnProp$1.call(b, prop))
|
|
2124
|
+
__defNormalProp$1(a, prop, b[prop]);
|
|
2125
|
+
if (__getOwnPropSymbols$1)
|
|
2126
|
+
for (var prop of __getOwnPropSymbols$1(b)) {
|
|
2127
|
+
if (__propIsEnum$1.call(b, prop))
|
|
2128
|
+
__defNormalProp$1(a, prop, b[prop]);
|
|
2129
|
+
}
|
|
2130
|
+
return a;
|
|
2131
|
+
};
|
|
2132
|
+
var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
|
|
2133
|
+
class AbortSignal extends Error {
|
|
2134
|
+
}
|
|
2135
|
+
const generate = async (options, config, args, afterPull) => {
|
|
2136
|
+
var _a, _b, _c;
|
|
2137
|
+
let { dbPath } = config;
|
|
2138
|
+
if (!dbPath || !config.baseTable)
|
|
2139
|
+
throw invalidConfig(config);
|
|
2140
|
+
if (!options.length)
|
|
2141
|
+
throw new Error(`Database options must not be empty`);
|
|
2142
|
+
if (!dbPath.endsWith(".ts"))
|
|
2143
|
+
dbPath += ".ts";
|
|
2144
|
+
let migrationName = (_a = args[0]) != null ? _a : "generated";
|
|
2145
|
+
let up;
|
|
2146
|
+
if (migrationName === "up") {
|
|
2147
|
+
up = true;
|
|
2148
|
+
migrationName = "generated";
|
|
2149
|
+
} else {
|
|
2150
|
+
up = args[1] === "up";
|
|
2151
|
+
}
|
|
2152
|
+
const { dbStructure, adapters } = await migrateAndPullStructures(
|
|
2153
|
+
options,
|
|
2154
|
+
config,
|
|
2155
|
+
afterPull
|
|
2156
|
+
);
|
|
2157
|
+
const [adapter] = adapters;
|
|
2158
|
+
const currentSchema = (_b = adapter.schema) != null ? _b : "public";
|
|
2159
|
+
const db = await getDbFromConfig(config, dbPath);
|
|
2160
|
+
const { columnTypes, internal } = db.$queryBuilder;
|
|
2161
|
+
const codeItems = await getActualItems(
|
|
2162
|
+
db,
|
|
2163
|
+
currentSchema,
|
|
2164
|
+
internal,
|
|
2165
|
+
columnTypes
|
|
2166
|
+
);
|
|
2167
|
+
const structureToAstCtx = rakeDb.makeStructureToAstCtx(config, currentSchema);
|
|
2168
|
+
const generateMigrationParams = {
|
|
2169
|
+
structureToAstCtx,
|
|
2170
|
+
codeItems,
|
|
2171
|
+
currentSchema,
|
|
2172
|
+
internal
|
|
2173
|
+
};
|
|
2174
|
+
const ast = [];
|
|
2175
|
+
let migrationCode;
|
|
2176
|
+
try {
|
|
2177
|
+
migrationCode = await composeMigration(
|
|
2178
|
+
adapter,
|
|
2179
|
+
config,
|
|
2180
|
+
ast,
|
|
2181
|
+
dbStructure,
|
|
2182
|
+
generateMigrationParams
|
|
2183
|
+
);
|
|
2184
|
+
} catch (err) {
|
|
2185
|
+
if (err instanceof AbortSignal) {
|
|
2186
|
+
await closeAdapters(adapters);
|
|
2187
|
+
return;
|
|
2188
|
+
}
|
|
2189
|
+
throw err;
|
|
2190
|
+
}
|
|
2191
|
+
if (migrationCode && !afterPull) {
|
|
2192
|
+
const result = await verifyMigration(
|
|
2193
|
+
adapter,
|
|
2194
|
+
config,
|
|
2195
|
+
migrationCode,
|
|
2196
|
+
generateMigrationParams
|
|
2197
|
+
);
|
|
2198
|
+
if (result !== void 0) {
|
|
2199
|
+
throw new Error(
|
|
2200
|
+
`Failed to verify generated migration: some of database changes were not applied properly. This is a bug, please open an issue, attach the following migration code:
|
|
2201
|
+
${migrationCode}${result === false ? "" : `
|
|
2202
|
+
After applying:
|
|
2203
|
+
${result}`}`
|
|
2204
|
+
);
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
const { logger } = config;
|
|
2208
|
+
if ((!up || !migrationCode) && !afterPull)
|
|
2209
|
+
await closeAdapters(adapters);
|
|
2210
|
+
if (!migrationCode) {
|
|
2211
|
+
logger == null ? void 0 : logger.log("No changes were detected");
|
|
2212
|
+
return;
|
|
2213
|
+
}
|
|
2214
|
+
const version = (_c = afterPull == null ? void 0 : afterPull.version) != null ? _c : await rakeDb.makeFileVersion({}, config);
|
|
2215
|
+
const delayLog = [];
|
|
2216
|
+
await rakeDb.writeMigrationFile(
|
|
2217
|
+
__spreadProps$1(__spreadValues$1({}, config), {
|
|
2218
|
+
logger: logger ? __spreadProps$1(__spreadValues$1({}, logger), { log: (msg) => delayLog.push(msg) }) : logger
|
|
2219
|
+
}),
|
|
2220
|
+
version,
|
|
2221
|
+
migrationName,
|
|
2222
|
+
migrationCode
|
|
2223
|
+
);
|
|
2224
|
+
report(ast, config, currentSchema);
|
|
2225
|
+
if (logger) {
|
|
2226
|
+
for (const msg of delayLog) {
|
|
2227
|
+
logger.log(`
|
|
2228
|
+
${msg}`);
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
if (up) {
|
|
2232
|
+
await rakeDb.migrate({}, options, config, void 0, adapters);
|
|
2233
|
+
} else if (!afterPull) {
|
|
2234
|
+
await closeAdapters(adapters);
|
|
2235
|
+
}
|
|
2236
|
+
};
|
|
2237
|
+
const invalidConfig = (config) => new Error(
|
|
2238
|
+
`\`${config.dbPath ? "baseTable" : "dbPath"}\` setting must be set in the migrations config for the generator to work`
|
|
2239
|
+
);
|
|
2240
|
+
const getDbFromConfig = async (config, dbPath) => {
|
|
2241
|
+
var _a, _b;
|
|
2242
|
+
const module = await config.import(dbPath);
|
|
2243
|
+
const db = module[(_a = config.dbExportedAs) != null ? _a : "db"];
|
|
2244
|
+
if (!(db == null ? void 0 : db.$queryBuilder)) {
|
|
2245
|
+
throw new Error(
|
|
2246
|
+
`Unable to import OrchidORM instance as ${(_b = config.dbExportedAs) != null ? _b : "db"} from ${config.dbPath}`
|
|
2247
|
+
);
|
|
2248
|
+
}
|
|
2249
|
+
return db;
|
|
2250
|
+
};
|
|
2251
|
+
const migrateAndPullStructures = async (options, config, afterPull) => {
|
|
2252
|
+
if (afterPull) {
|
|
2253
|
+
return {
|
|
2254
|
+
dbStructure: {
|
|
2255
|
+
schemas: [],
|
|
2256
|
+
tables: [],
|
|
2257
|
+
views: [],
|
|
2258
|
+
indexes: [],
|
|
2259
|
+
constraints: [],
|
|
2260
|
+
triggers: [],
|
|
2261
|
+
extensions: [],
|
|
2262
|
+
enums: [],
|
|
2263
|
+
domains: [],
|
|
2264
|
+
collations: []
|
|
2265
|
+
},
|
|
2266
|
+
adapters: [afterPull.adapter]
|
|
2267
|
+
};
|
|
2268
|
+
}
|
|
2269
|
+
const adapters = await rakeDb.migrate(
|
|
2270
|
+
{},
|
|
2271
|
+
options,
|
|
2272
|
+
config,
|
|
2273
|
+
void 0,
|
|
2274
|
+
void 0,
|
|
2275
|
+
true
|
|
2276
|
+
);
|
|
2277
|
+
const dbStructures = await Promise.all(
|
|
2278
|
+
adapters.map((adapter) => rakeDb.introspectDbSchema(adapter))
|
|
2279
|
+
);
|
|
2280
|
+
const dbStructure = dbStructures[0];
|
|
2281
|
+
for (let i = 1; i < dbStructures.length; i++) {
|
|
2282
|
+
compareDbStructures(dbStructure, dbStructures[i], i);
|
|
2283
|
+
}
|
|
2284
|
+
return { dbStructure, adapters };
|
|
2285
|
+
};
|
|
2286
|
+
const compareDbStructures = (a, b, i, path) => {
|
|
2287
|
+
let err;
|
|
2288
|
+
if (typeof a !== typeof b) {
|
|
2289
|
+
err = true;
|
|
2290
|
+
}
|
|
2291
|
+
if (!a || typeof a !== "object") {
|
|
2292
|
+
if (a !== b) {
|
|
2293
|
+
err = true;
|
|
2294
|
+
}
|
|
2295
|
+
} else {
|
|
2296
|
+
if (Array.isArray(a)) {
|
|
2297
|
+
for (let n = 0, len = a.length; n < len; n++) {
|
|
2298
|
+
compareDbStructures(
|
|
2299
|
+
a[n],
|
|
2300
|
+
b[n],
|
|
2301
|
+
i,
|
|
2302
|
+
path ? `${path}[${n}]` : String(n)
|
|
2303
|
+
);
|
|
2304
|
+
}
|
|
2305
|
+
} else {
|
|
2306
|
+
for (const key in a) {
|
|
2307
|
+
compareDbStructures(
|
|
2308
|
+
a[key],
|
|
2309
|
+
b[key],
|
|
2310
|
+
i,
|
|
2311
|
+
path ? `${path}.${key}` : key
|
|
2312
|
+
);
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
if (err) {
|
|
2317
|
+
throw new Error(`${path} in the db 0 does not match db ${i}`);
|
|
2318
|
+
}
|
|
2319
|
+
};
|
|
2320
|
+
const getActualItems = async (db, currentSchema, internal, columnTypes) => {
|
|
2321
|
+
var _a;
|
|
2322
|
+
const tableNames = /* @__PURE__ */ new Set();
|
|
2323
|
+
const habtmTables = /* @__PURE__ */ new Map();
|
|
2324
|
+
const codeItems = {
|
|
2325
|
+
schemas: /* @__PURE__ */ new Set(void 0),
|
|
2326
|
+
enums: /* @__PURE__ */ new Map(),
|
|
2327
|
+
tables: [],
|
|
2328
|
+
domains: []
|
|
2329
|
+
};
|
|
2330
|
+
const domains = /* @__PURE__ */ new Map();
|
|
2331
|
+
for (const key in db) {
|
|
2332
|
+
if (key[0] === "$")
|
|
2333
|
+
continue;
|
|
2334
|
+
const table = db[key];
|
|
2335
|
+
if (!table.table) {
|
|
2336
|
+
throw new Error(`Table ${key} is missing table property`);
|
|
2337
|
+
}
|
|
2338
|
+
const { schema } = table.q;
|
|
2339
|
+
const name = rakeDb.concatSchemaAndName({ schema, name: table.table });
|
|
2340
|
+
if (tableNames.has(name)) {
|
|
2341
|
+
throw new Error(`Table ${name} is defined more than once`);
|
|
2342
|
+
}
|
|
2343
|
+
tableNames.add(name);
|
|
2344
|
+
if (schema)
|
|
2345
|
+
codeItems.schemas.add(schema);
|
|
2346
|
+
codeItems.tables.push(table);
|
|
2347
|
+
for (const key2 in table.relations) {
|
|
2348
|
+
const column = table.shape[key2];
|
|
2349
|
+
if (column && "joinTable" in column) {
|
|
2350
|
+
processHasAndBelongsToManyColumn(column, habtmTables, codeItems);
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
for (const key2 in table.shape) {
|
|
2354
|
+
const column = table.shape[key2];
|
|
2355
|
+
if (column instanceof pqb.DomainColumn) {
|
|
2356
|
+
const [schemaName = currentSchema, name2] = rakeDb.getSchemaAndTableFromName(
|
|
2357
|
+
column.dataType
|
|
2358
|
+
);
|
|
2359
|
+
domains.set(column.dataType, {
|
|
2360
|
+
schemaName,
|
|
2361
|
+
name: name2,
|
|
2362
|
+
column: (_a = column.data.as) != null ? _a : new pqb.UnknownColumn(pqb.defaultSchemaConfig)
|
|
2363
|
+
});
|
|
2364
|
+
} else if (column.dataType === "enum") {
|
|
2365
|
+
processEnumColumn(column, currentSchema, codeItems);
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
if (internal.extensions) {
|
|
2370
|
+
for (const extension of internal.extensions) {
|
|
2371
|
+
const [schema] = rakeDb.getSchemaAndTableFromName(extension.name);
|
|
2372
|
+
if (schema)
|
|
2373
|
+
codeItems.schemas.add(schema);
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
if (internal.domains) {
|
|
2377
|
+
for (const key in internal.domains) {
|
|
2378
|
+
const [schemaName = currentSchema, name] = rakeDb.getSchemaAndTableFromName(key);
|
|
2379
|
+
const column = internal.domains[key](columnTypes);
|
|
2380
|
+
domains.set(key, {
|
|
2381
|
+
schemaName,
|
|
2382
|
+
name,
|
|
2383
|
+
column
|
|
2384
|
+
});
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
for (const domain of domains.values()) {
|
|
2388
|
+
codeItems.schemas.add(domain.schemaName);
|
|
2389
|
+
codeItems.domains.push(domain);
|
|
2390
|
+
}
|
|
2391
|
+
return codeItems;
|
|
2392
|
+
};
|
|
2393
|
+
const processEnumColumn = (column, currentSchema, codeItems) => {
|
|
2394
|
+
const { enumName, options } = column;
|
|
2395
|
+
const [schema, name] = rakeDb.getSchemaAndTableFromName(enumName);
|
|
2396
|
+
const enumSchema = schema != null ? schema : currentSchema;
|
|
2397
|
+
codeItems.enums.set(`${enumSchema}.${name}`, {
|
|
2398
|
+
schema: enumSchema,
|
|
2399
|
+
name,
|
|
2400
|
+
values: options
|
|
2401
|
+
});
|
|
2402
|
+
if (schema)
|
|
2403
|
+
codeItems.schemas.add(schema);
|
|
2404
|
+
};
|
|
2405
|
+
const processHasAndBelongsToManyColumn = (column, habtmTables, codeItems) => {
|
|
2406
|
+
const q = column.joinTable;
|
|
2407
|
+
const prev = habtmTables.get(q.table);
|
|
2408
|
+
if (prev) {
|
|
2409
|
+
for (const key in q.shape) {
|
|
2410
|
+
if (q.shape[key] !== prev.shape[key]) {
|
|
2411
|
+
throw new Error(
|
|
2412
|
+
`Column ${key} in ${q.table} in hasAndBelongsToMany relation does not match with the relation on the other side`
|
|
2413
|
+
);
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
return;
|
|
2417
|
+
}
|
|
2418
|
+
habtmTables.set(q.table, q);
|
|
2419
|
+
const joinTable = Object.create(q);
|
|
2420
|
+
const shape = {};
|
|
2421
|
+
for (const key in joinTable.shape) {
|
|
2422
|
+
const column2 = Object.create(joinTable.shape[key]);
|
|
2423
|
+
column2.data = __spreadProps$1(__spreadValues$1({}, column2.data), {
|
|
2424
|
+
identity: void 0,
|
|
2425
|
+
isPrimaryKey: void 0,
|
|
2426
|
+
default: void 0
|
|
2427
|
+
});
|
|
2428
|
+
shape[key] = column2;
|
|
2429
|
+
}
|
|
2430
|
+
joinTable.shape = shape;
|
|
2431
|
+
joinTable.internal.primaryKey = {
|
|
2432
|
+
columns: Object.keys(shape)
|
|
2433
|
+
};
|
|
2434
|
+
joinTable.internal.noPrimaryKey = false;
|
|
2435
|
+
codeItems.tables.push(joinTable);
|
|
2436
|
+
return;
|
|
2437
|
+
};
|
|
2438
|
+
const closeAdapters = (adapters) => {
|
|
2439
|
+
return Promise.all(adapters.map((x) => x.close()));
|
|
2440
|
+
};
|
|
2441
|
+
|
|
2442
|
+
var __defProp = Object.defineProperty;
|
|
2443
|
+
var __defProps = Object.defineProperties;
|
|
2444
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
2445
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
2446
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
2447
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
2448
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2449
|
+
var __spreadValues = (a, b) => {
|
|
2450
|
+
for (var prop in b || (b = {}))
|
|
2451
|
+
if (__hasOwnProp.call(b, prop))
|
|
2452
|
+
__defNormalProp(a, prop, b[prop]);
|
|
2453
|
+
if (__getOwnPropSymbols)
|
|
2454
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
2455
|
+
if (__propIsEnum.call(b, prop))
|
|
2456
|
+
__defNormalProp(a, prop, b[prop]);
|
|
2457
|
+
}
|
|
2458
|
+
return a;
|
|
2459
|
+
};
|
|
2460
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
2461
|
+
const getTableInfosAndFKeys = (asts, config) => {
|
|
2462
|
+
var _a, _b, _c;
|
|
2463
|
+
const generateTableTo = (_a = config.generateTableTo) != null ? _a : (name) => `./tables/${name}.table.ts`;
|
|
2464
|
+
const tableInfos = {};
|
|
2465
|
+
const fkeys = {};
|
|
2466
|
+
for (const ast of asts) {
|
|
2467
|
+
if (ast.type === "table") {
|
|
2468
|
+
const tableKey = orchidCore.toCamelCase(ast.name);
|
|
2469
|
+
const dbTableName = ast.schema ? `${ast.schema}.${ast.name}` : ast.name;
|
|
2470
|
+
let tablePath = path.resolve(config.basePath, generateTableTo(tableKey));
|
|
2471
|
+
if (!tablePath.endsWith(".ts"))
|
|
2472
|
+
tablePath += ".ts";
|
|
2473
|
+
const name = orchidCore.toPascalCase(ast.name);
|
|
2474
|
+
const info = {
|
|
2475
|
+
dbTableName,
|
|
2476
|
+
key: tableKey,
|
|
2477
|
+
path: tablePath,
|
|
2478
|
+
name,
|
|
2479
|
+
className: `${name}Table`
|
|
2480
|
+
};
|
|
2481
|
+
tableInfos[dbTableName] = info;
|
|
2482
|
+
if (ast.constraints) {
|
|
2483
|
+
for (const { references } of ast.constraints) {
|
|
2484
|
+
if (!references)
|
|
2485
|
+
continue;
|
|
2486
|
+
((_c = fkeys[_b = references.fnOrTable]) != null ? _c : fkeys[_b] = []).push({
|
|
2487
|
+
table: info,
|
|
2488
|
+
references
|
|
2489
|
+
});
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
return { tableInfos, fkeys };
|
|
2495
|
+
};
|
|
2496
|
+
const appCodeGenTable = (tableInfos, fkeys, ast, baseTablePath, baseTableExportedAs) => {
|
|
2497
|
+
const tableInfo = tableInfos[ast.schema ? `${ast.schema}.${ast.name}` : ast.name];
|
|
2498
|
+
const imports = {
|
|
2499
|
+
"orchid-orm": "Selectable, Insertable, Updatable",
|
|
2500
|
+
[orchidCore.getImportPath(tableInfo.path, baseTablePath)]: baseTableExportedAs
|
|
2501
|
+
};
|
|
2502
|
+
const props = [];
|
|
2503
|
+
if (ast.schema) {
|
|
2504
|
+
props.push(`schema = ${orchidCore.singleQuote(ast.schema)};`);
|
|
2505
|
+
}
|
|
2506
|
+
props.push(`readonly table = ${orchidCore.singleQuote(ast.name)};`);
|
|
2507
|
+
if (ast.comment) {
|
|
2508
|
+
props.push(`comment = ${orchidCore.singleQuote(ast.comment)};`);
|
|
2509
|
+
}
|
|
2510
|
+
if (ast.noPrimaryKey === "ignore") {
|
|
2511
|
+
props.push("noPrimaryKey = true;");
|
|
2512
|
+
}
|
|
2513
|
+
props.push(
|
|
2514
|
+
"columns = this.setColumns((t) => ({",
|
|
2515
|
+
pqb.columnsShapeToCode(ast.shape, ast, "t"),
|
|
2516
|
+
"}));"
|
|
2517
|
+
);
|
|
2518
|
+
const relations = [];
|
|
2519
|
+
const fullTableName = ast.schema ? `${ast.schema}.${ast.name}` : ast.name;
|
|
2520
|
+
const belongsTo = fkeys[fullTableName];
|
|
2521
|
+
if (belongsTo) {
|
|
2522
|
+
for (const { table, references } of belongsTo) {
|
|
2523
|
+
imports[orchidCore.getImportPath(tableInfo.path, table.path)] = table.className;
|
|
2524
|
+
relations.push(
|
|
2525
|
+
`${table.key}: this.belongsTo(() => ${table.className}, {`,
|
|
2526
|
+
[
|
|
2527
|
+
`columns: [${references.foreignColumns.map(orchidCore.singleQuote).join(", ")}],`,
|
|
2528
|
+
`references: [${references.columns.map(orchidCore.singleQuote).join(", ")}],`
|
|
2529
|
+
],
|
|
2530
|
+
"}),"
|
|
2531
|
+
);
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
if (ast.constraints) {
|
|
2535
|
+
for (const { references } of ast.constraints) {
|
|
2536
|
+
if (!references)
|
|
2537
|
+
continue;
|
|
2538
|
+
const table = tableInfos[references.fnOrTable];
|
|
2539
|
+
imports[orchidCore.getImportPath(tableInfo.path, table.path)] = table.className;
|
|
2540
|
+
relations.push(
|
|
2541
|
+
`${table.key}: this.hasMany(() => ${table.className}, {`,
|
|
2542
|
+
[
|
|
2543
|
+
`columns: [${references.columns.map(orchidCore.singleQuote).join(", ")}],`,
|
|
2544
|
+
`references: [${references.foreignColumns.map(orchidCore.singleQuote).join(", ")}],`
|
|
2545
|
+
],
|
|
2546
|
+
"}),"
|
|
2547
|
+
);
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
if (relations.length) {
|
|
2551
|
+
props.push("", "relations = {", relations, "};");
|
|
2552
|
+
}
|
|
2553
|
+
const importsCode = importsToCode(imports);
|
|
2554
|
+
const { name, className } = tableInfo;
|
|
2555
|
+
const code = [
|
|
2556
|
+
`export type ${name} = Selectable<${className}>;
|
|
2557
|
+
export type ${name}New = Insertable<${className}>;
|
|
2558
|
+
export type ${name}Update = Updatable<${className}>;
|
|
2559
|
+
|
|
2560
|
+
export class ${className} extends ${baseTableExportedAs} {`,
|
|
2561
|
+
props,
|
|
2562
|
+
"}\n"
|
|
2563
|
+
];
|
|
2564
|
+
return __spreadProps(__spreadValues({}, tableInfo), {
|
|
2565
|
+
content: importsCode + "\n\n" + orchidCore.codeToString(code, "", " ")
|
|
2566
|
+
});
|
|
2567
|
+
};
|
|
2568
|
+
function importsToCode(imports) {
|
|
2569
|
+
return Object.entries(imports).map(([from, name]) => `import { ${name} } from '${from}';`).join("\n");
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2572
|
+
const { createSourceFile, ScriptTarget, SyntaxKind } = typescript;
|
|
2573
|
+
const appCodeGenUpdateDbFile = async (dbPath, tables, extensions, domains) => {
|
|
2574
|
+
const content = await fs.readFile(dbPath, "utf-8");
|
|
2575
|
+
const statements = getTsStatements(content);
|
|
2576
|
+
const importName = getOrchidOrmImportName(statements);
|
|
2577
|
+
if (!importName) {
|
|
2578
|
+
throw new Error(`Main file does not contain import of orchid-orm`);
|
|
2579
|
+
}
|
|
2580
|
+
const { config, tablesList } = getOrchidOrmArgs(importName, statements);
|
|
2581
|
+
const changes = [];
|
|
2582
|
+
let replacedConfig;
|
|
2583
|
+
if (extensions.length || domains.length) {
|
|
2584
|
+
let code = content.slice(config.pos, config.end).trim();
|
|
2585
|
+
if (code[0] !== "{")
|
|
2586
|
+
code = `{...${code}}`;
|
|
2587
|
+
code = "{\n " + code.slice(1, -1).trim();
|
|
2588
|
+
if (!code.endsWith(","))
|
|
2589
|
+
code += ",";
|
|
2590
|
+
if (extensions.length) {
|
|
2591
|
+
code += `
|
|
2592
|
+
extensions: [${extensions.map(
|
|
2593
|
+
(ext) => ext.version ? `{ ${ext.name}: '${ext.version}' }` : `'${ext.name}'`
|
|
2594
|
+
).join(", ")}],`;
|
|
2595
|
+
}
|
|
2596
|
+
if (domains.length) {
|
|
2597
|
+
code += `
|
|
2598
|
+
domains: {
|
|
2599
|
+
${domains.sort((a, b) => a.name > b.name ? 1 : -1).map(
|
|
2600
|
+
(ast) => `${orchidCore.quoteObjectKey(
|
|
2601
|
+
ast.schema ? `${ast.schema}.${ast.name}` : ast.name
|
|
2602
|
+
)}: (t) => ${ast.baseType.toCode("t")},`
|
|
2603
|
+
).join("\n ")}
|
|
2604
|
+
},`;
|
|
2605
|
+
}
|
|
2606
|
+
replacedConfig = code + "\n}";
|
|
2607
|
+
}
|
|
2608
|
+
const tablesChanges = makeTablesListChanges(
|
|
2609
|
+
content,
|
|
2610
|
+
statements,
|
|
2611
|
+
tablesList,
|
|
2612
|
+
tables,
|
|
2613
|
+
dbPath
|
|
2614
|
+
);
|
|
2615
|
+
if (tablesChanges) {
|
|
2616
|
+
addChange(
|
|
2617
|
+
content,
|
|
2618
|
+
changes,
|
|
2619
|
+
tablesChanges.imports.pos,
|
|
2620
|
+
tablesChanges.imports.text
|
|
2621
|
+
);
|
|
2622
|
+
}
|
|
2623
|
+
if (replacedConfig) {
|
|
2624
|
+
replaceContent(content, changes, config.pos, config.end, replacedConfig);
|
|
2625
|
+
}
|
|
2626
|
+
if (tablesChanges) {
|
|
2627
|
+
addChange(
|
|
2628
|
+
content,
|
|
2629
|
+
changes,
|
|
2630
|
+
tablesChanges.tablesList.pos,
|
|
2631
|
+
tablesChanges.tablesList.text
|
|
2632
|
+
);
|
|
2633
|
+
}
|
|
2634
|
+
return applyChanges(content, changes);
|
|
2635
|
+
};
|
|
2636
|
+
const getTsStatements = (content) => {
|
|
2637
|
+
return createSourceFile("file.ts", content, ScriptTarget.Latest, true).statements;
|
|
2638
|
+
};
|
|
2639
|
+
const getOrchidOrmImportName = (statements) => {
|
|
2640
|
+
var _a, _b;
|
|
2641
|
+
for (const node of statements) {
|
|
2642
|
+
if (node.kind !== SyntaxKind.ImportDeclaration)
|
|
2643
|
+
continue;
|
|
2644
|
+
const imp = node;
|
|
2645
|
+
const source = imp.moduleSpecifier.getText().slice(1, -1);
|
|
2646
|
+
if (source !== "orchid-orm")
|
|
2647
|
+
continue;
|
|
2648
|
+
if (!imp.importClause)
|
|
2649
|
+
continue;
|
|
2650
|
+
const elements = (_a = imp.importClause.namedBindings) == null ? void 0 : _a.elements;
|
|
2651
|
+
for (const element of elements) {
|
|
2652
|
+
if (((_b = element.propertyName) == null ? void 0 : _b.escapedText) === "orchidORM" || element.name.escapedText === "orchidORM") {
|
|
2653
|
+
return element.name.escapedText.toString();
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
return;
|
|
2658
|
+
};
|
|
2659
|
+
const makeTablesListChanges = (content, statements, object, tables, dbPath) => {
|
|
2660
|
+
const spaces = getTablesListSpaces(content, object);
|
|
2661
|
+
let imports = "";
|
|
2662
|
+
let tablesList = "";
|
|
2663
|
+
const prependComma = object.properties.length && !object.properties.hasTrailingComma;
|
|
2664
|
+
const tablesListNewLine = content.slice(object.properties.end, object.end).includes("\n");
|
|
2665
|
+
const tablesArr = Object.values(tables);
|
|
2666
|
+
for (let i = 0; i < tablesArr.length; i++) {
|
|
2667
|
+
const { path, className, key } = tablesArr[i];
|
|
2668
|
+
const importPath = orchidCore.getImportPath(dbPath, path);
|
|
2669
|
+
imports += `
|
|
2670
|
+
import { ${className} } from '${importPath}';`;
|
|
2671
|
+
tablesList += `${i === 0 && prependComma ? "," : ""}
|
|
2672
|
+
${spaces} ${key}: ${className},`;
|
|
2673
|
+
if (i === tablesArr.length - 1 && !tablesListNewLine) {
|
|
2674
|
+
tablesList += `
|
|
2675
|
+
${spaces}`;
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
if (!imports.length)
|
|
2679
|
+
return;
|
|
2680
|
+
let importPos = 0;
|
|
2681
|
+
for (const node of statements) {
|
|
2682
|
+
if (node.kind === SyntaxKind.ImportDeclaration) {
|
|
2683
|
+
importPos = node.end;
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
return {
|
|
2687
|
+
imports: { pos: importPos, text: imports },
|
|
2688
|
+
tablesList: { pos: object.properties.end, text: tablesList }
|
|
2689
|
+
};
|
|
2690
|
+
};
|
|
2691
|
+
const getTablesListSpaces = (content, object) => {
|
|
2692
|
+
var _a;
|
|
2693
|
+
const lines = content.slice(0, object.end).split("\n");
|
|
2694
|
+
const last = lines[lines.length - 1];
|
|
2695
|
+
return ((_a = last.match(/^\s+/)) == null ? void 0 : _a[0]) || "";
|
|
2696
|
+
};
|
|
2697
|
+
const getOrchidOrmArgs = (importName, statements) => {
|
|
2698
|
+
for (const v of statements) {
|
|
2699
|
+
if (v.kind !== SyntaxKind.VariableStatement)
|
|
2700
|
+
continue;
|
|
2701
|
+
for (const node of v.declarationList.declarations) {
|
|
2702
|
+
const call = node.initializer;
|
|
2703
|
+
if ((call == null ? void 0 : call.kind) !== SyntaxKind.CallExpression)
|
|
2704
|
+
continue;
|
|
2705
|
+
if (call.expression.getText() !== importName)
|
|
2706
|
+
continue;
|
|
2707
|
+
if (call.arguments.length !== 2) {
|
|
2708
|
+
throw new Error(
|
|
2709
|
+
"Invalid number of arguments when initializing orchid orm"
|
|
2710
|
+
);
|
|
2711
|
+
}
|
|
2712
|
+
const object = call.arguments[1];
|
|
2713
|
+
if ((object == null ? void 0 : object.kind) !== SyntaxKind.ObjectLiteralExpression) {
|
|
2714
|
+
throw new Error(
|
|
2715
|
+
"Second argument of orchidORM must be an object literal"
|
|
2716
|
+
);
|
|
2717
|
+
}
|
|
2718
|
+
return { config: call.arguments[0], tablesList: object };
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
throw new Error("List of tables is not found in main file");
|
|
2722
|
+
};
|
|
2723
|
+
const addChange = (content, changes, at, text, end = at) => {
|
|
2724
|
+
if (changes.length === 0) {
|
|
2725
|
+
changes.push([0, at], text, [end, content.length]);
|
|
2726
|
+
} else {
|
|
2727
|
+
const last = changes[changes.length - 1];
|
|
2728
|
+
last[1] = at;
|
|
2729
|
+
changes.push(text, [end, content.length]);
|
|
2730
|
+
}
|
|
2731
|
+
};
|
|
2732
|
+
const replaceContent = (content, changes, from, to, text) => {
|
|
2733
|
+
addChange(content, changes, from, text, to);
|
|
2734
|
+
};
|
|
2735
|
+
const applyChanges = (content, changes) => {
|
|
2736
|
+
return changes.length ? changes.map(
|
|
2737
|
+
(item) => typeof item === "string" ? item : content.slice(item[0], item[1])
|
|
2738
|
+
).join("") : content;
|
|
2739
|
+
};
|
|
2740
|
+
|
|
2741
|
+
const pull = async (options, config) => {
|
|
2742
|
+
if (!config.dbPath || !config.baseTable) {
|
|
2743
|
+
throw new Error(
|
|
2744
|
+
`\`${config.dbPath ? "baseTable" : "dbPath"}\` setting must be set in the migrations config for pull command`
|
|
2745
|
+
);
|
|
2746
|
+
}
|
|
2747
|
+
const baseTablePath = config.baseTable.getFilePath();
|
|
2748
|
+
const baseTableExportedAs = config.baseTable.exportAs;
|
|
2749
|
+
const adapter = new pqb.Adapter(options[0]);
|
|
2750
|
+
const currentSchema = adapter.schema || "public";
|
|
2751
|
+
const ctx = rakeDb.makeStructureToAstCtx(config, currentSchema);
|
|
2752
|
+
const asts = await rakeDb.structureToAst(ctx, adapter);
|
|
2753
|
+
const { tableInfos, fkeys } = getTableInfosAndFKeys(asts, config);
|
|
2754
|
+
const exclusiveWriteOptions = { flag: "wx" };
|
|
2755
|
+
const pendingFileWrites = [];
|
|
2756
|
+
const tables = {};
|
|
2757
|
+
const extensions = [];
|
|
2758
|
+
const domains = [];
|
|
2759
|
+
let firstTable;
|
|
2760
|
+
for (const ast of asts) {
|
|
2761
|
+
switch (ast.type) {
|
|
2762
|
+
case "table": {
|
|
2763
|
+
const table = appCodeGenTable(
|
|
2764
|
+
tableInfos,
|
|
2765
|
+
fkeys,
|
|
2766
|
+
ast,
|
|
2767
|
+
baseTablePath,
|
|
2768
|
+
baseTableExportedAs
|
|
2769
|
+
);
|
|
2770
|
+
tables[table.key] = table;
|
|
2771
|
+
if (!firstTable)
|
|
2772
|
+
firstTable = table;
|
|
2773
|
+
pendingFileWrites.push([
|
|
2774
|
+
table.path,
|
|
2775
|
+
table.content,
|
|
2776
|
+
exclusiveWriteOptions
|
|
2777
|
+
]);
|
|
2778
|
+
break;
|
|
2779
|
+
}
|
|
2780
|
+
case "extension": {
|
|
2781
|
+
extensions.push({
|
|
2782
|
+
name: ast.schema ? `${ast.schema}.${ast.name}` : ast.name,
|
|
2783
|
+
version: ast.version
|
|
2784
|
+
});
|
|
2785
|
+
break;
|
|
2786
|
+
}
|
|
2787
|
+
case "domain": {
|
|
2788
|
+
domains.push(ast);
|
|
2789
|
+
break;
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
if (!firstTable && !extensions.length && !domains.length) {
|
|
2794
|
+
await adapter.close();
|
|
2795
|
+
return;
|
|
2796
|
+
}
|
|
2797
|
+
let dbPath = path.resolve(config.basePath, config.dbPath);
|
|
2798
|
+
if (!dbPath.endsWith(".ts"))
|
|
2799
|
+
dbPath += ".ts";
|
|
2800
|
+
const content = await appCodeGenUpdateDbFile(
|
|
2801
|
+
dbPath,
|
|
2802
|
+
tables,
|
|
2803
|
+
extensions,
|
|
2804
|
+
domains
|
|
2805
|
+
);
|
|
2806
|
+
if (content)
|
|
2807
|
+
pendingFileWrites.push([dbPath, content]);
|
|
2808
|
+
if (firstTable) {
|
|
2809
|
+
await fs.mkdir(path.dirname(firstTable.path), { recursive: true });
|
|
2810
|
+
}
|
|
2811
|
+
await Promise.all(
|
|
2812
|
+
pendingFileWrites.map(
|
|
2813
|
+
([path2, content2, options2]) => fs.writeFile(path2, content2, options2).then(() => {
|
|
2814
|
+
var _a;
|
|
2815
|
+
(_a = config.logger) == null ? void 0 : _a.log(`Created ${orchidCore.pathToLog(path2)}`);
|
|
2816
|
+
})
|
|
2817
|
+
)
|
|
2818
|
+
);
|
|
2819
|
+
const version = await rakeDb.makeFileVersion({}, config);
|
|
2820
|
+
await generate(options, config, ["pull"], { adapter, version });
|
|
2821
|
+
const silentAdapter = adapter;
|
|
2822
|
+
silentAdapter.silentArrays = adapter.arrays;
|
|
2823
|
+
await rakeDb.saveMigratedVersion(silentAdapter, version, "pull.ts", config);
|
|
2824
|
+
await adapter.close();
|
|
2825
|
+
};
|
|
2826
|
+
|
|
2827
|
+
rakeDb.rakeDbCommands.g = rakeDb.rakeDbCommands.generate = {
|
|
2828
|
+
run: generate,
|
|
2829
|
+
help: "gen migration from OrchidORM tables",
|
|
2830
|
+
helpArguments: {
|
|
2831
|
+
"no arguments": '"generated" is a default file name',
|
|
2832
|
+
"migration-name": "set migration file name",
|
|
2833
|
+
up: "auto-apply migration",
|
|
2834
|
+
"migration-name up": "with a custom name and apply it"
|
|
2835
|
+
},
|
|
2836
|
+
helpAfter: "reset"
|
|
2837
|
+
};
|
|
2838
|
+
rakeDb.rakeDbCommands.pull.run = pull;
|
|
2839
|
+
rakeDb.rakeDbCommands.pull.help = "generate ORM tables and a migration for an existing database";
|
|
2840
|
+
|
|
2841
|
+
Object.keys(rakeDb).forEach(function (k) {
|
|
2842
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
2843
|
+
enumerable: true,
|
|
2844
|
+
get: function () { return rakeDb[k]; }
|
|
2845
|
+
});
|
|
2846
|
+
});
|
|
2847
|
+
//# sourceMappingURL=migrations.js.map
|