rake-db 2.30.9 → 2.31.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 +172 -98
- package/dist/index.js +987 -935
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +732 -680
- package/dist/index.mjs.map +1 -1
- package/dist/node-postgres.d.ts +1 -1
- package/dist/node-postgres.js +2 -2
- package/dist/node-postgres.js.map +1 -1
- package/dist/node-postgres.mjs +1 -1
- package/dist/node-postgres.mjs.map +1 -1
- package/dist/postgres-js.d.ts +1 -1
- package/dist/postgres-js.js +2 -2
- package/dist/postgres-js.js.map +1 -1
- package/dist/postgres-js.mjs +1 -1
- package/dist/postgres-js.mjs.map +1 -1
- package/package.json +24 -21
package/dist/index.js
CHANGED
|
@@ -1,249 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var internal = require('pqb/internal');
|
|
4
4
|
var path = require('path');
|
|
5
5
|
var node_url = require('node:url');
|
|
6
|
+
var pqb = require('pqb');
|
|
6
7
|
var fs = require('fs/promises');
|
|
7
|
-
|
|
8
|
-
const ESC = "\x1B";
|
|
9
|
-
const CSI = `${ESC}[`;
|
|
10
|
-
const cursorShow = `${CSI}?25h`;
|
|
11
|
-
const cursorHide = `${CSI}?25l`;
|
|
12
|
-
const { stdin, stdout } = process;
|
|
13
|
-
const visibleChars = (s) => s.replace(
|
|
14
|
-
// eslint-disable-next-line no-control-regex
|
|
15
|
-
/[\u001B\u009B][[\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\d/#&.:=?%@~_]+)*|[a-zA-Z\d]+(?:;[-a-zA-Z\d/#&.:=?%@~_]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PRZcf-ntqry=><~]))/g,
|
|
16
|
-
""
|
|
17
|
-
).length;
|
|
18
|
-
const clear = (text) => {
|
|
19
|
-
const rows = text.split(/\r?\n/).reduce(
|
|
20
|
-
(rows2, line) => rows2 + 1 + Math.floor(Math.max(visibleChars(line) - 1, 0) / stdout.columns),
|
|
21
|
-
0
|
|
22
|
-
);
|
|
23
|
-
let clear2 = "";
|
|
24
|
-
for (let i = 0; i < rows; i++) {
|
|
25
|
-
clear2 += `${CSI}2K`;
|
|
26
|
-
if (i < rows - 1) {
|
|
27
|
-
clear2 += `${CSI}${i < rows - 1 ? "1A" : "G"}`;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return clear2;
|
|
31
|
-
};
|
|
32
|
-
const prompt = async ({
|
|
33
|
-
render,
|
|
34
|
-
onKeyPress,
|
|
35
|
-
validate,
|
|
36
|
-
value,
|
|
37
|
-
cursor: showCursor
|
|
38
|
-
}) => {
|
|
39
|
-
stdin.resume();
|
|
40
|
-
if (stdin.isTTY) stdin.setRawMode(true);
|
|
41
|
-
stdin.setEncoding("utf-8");
|
|
42
|
-
if (!showCursor) stdout.write(cursorHide);
|
|
43
|
-
return new Promise((res) => {
|
|
44
|
-
let prevText;
|
|
45
|
-
const ctx = {
|
|
46
|
-
value,
|
|
47
|
-
submitted: false,
|
|
48
|
-
render() {
|
|
49
|
-
let text = (ctx.submitted ? pqb.colors.greenBold("\u2714") : pqb.colors.yellowBold("?")) + " " + render(ctx);
|
|
50
|
-
if (ctx.submitted) text += "\n";
|
|
51
|
-
stdout.write(prevText ? clear(prevText) + "\r" + text : text);
|
|
52
|
-
prevText = text;
|
|
53
|
-
},
|
|
54
|
-
submit(value2) {
|
|
55
|
-
if (value2 !== void 0) ctx.value = value2;
|
|
56
|
-
if (ctx.value === void 0 || validate && !validate?.(ctx)) return;
|
|
57
|
-
ctx.submitted = true;
|
|
58
|
-
ctx.render();
|
|
59
|
-
close();
|
|
60
|
-
res(ctx.value);
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
const close = () => {
|
|
64
|
-
if (!showCursor) stdout.write(cursorShow);
|
|
65
|
-
if (stdin.isTTY) stdin.setRawMode(false);
|
|
66
|
-
stdin.off("data", keypress);
|
|
67
|
-
stdin.pause();
|
|
68
|
-
};
|
|
69
|
-
const keypress = (s) => {
|
|
70
|
-
if (s === "" || s === "") {
|
|
71
|
-
close?.();
|
|
72
|
-
process.exit(0);
|
|
73
|
-
}
|
|
74
|
-
if (s === "\r" || s === "\n" || s === "\r\n") {
|
|
75
|
-
ctx.submit();
|
|
76
|
-
} else {
|
|
77
|
-
onKeyPress(ctx, s);
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
stdin.on("data", keypress);
|
|
81
|
-
ctx.render();
|
|
82
|
-
});
|
|
83
|
-
};
|
|
84
|
-
const defaultActive = (s) => `${pqb.colors.blueBold("\u276F")} ${s}`;
|
|
85
|
-
const defaultInactive = (s) => ` ${s}`;
|
|
86
|
-
const promptSelect = ({
|
|
87
|
-
message,
|
|
88
|
-
options,
|
|
89
|
-
active = defaultActive,
|
|
90
|
-
inactive = defaultInactive
|
|
91
|
-
}) => prompt({
|
|
92
|
-
value: 0,
|
|
93
|
-
render(ctx) {
|
|
94
|
-
let text = `${message} ${pqb.colors.pale(
|
|
95
|
-
"Use arrows or jk. Press enter to submit."
|
|
96
|
-
)}
|
|
97
|
-
`;
|
|
98
|
-
for (let i = 0; i < options.length; i++) {
|
|
99
|
-
text += (ctx.value === i ? active : inactive)(options[i]) + "\n";
|
|
100
|
-
}
|
|
101
|
-
return text;
|
|
102
|
-
},
|
|
103
|
-
onKeyPress(ctx, s) {
|
|
104
|
-
ctx.value = s === "\x1B[H" ? 0 : s === "\x1B[F" ? options.length - 1 : s === "\x1B[A" || s === "k" ? ctx.value === 0 ? options.length - 1 : ctx.value - 1 : s === "\x1B[B" || s === "j" || s === " " ? ctx.value === options.length - 1 ? 0 : ctx.value + 1 : ctx.value;
|
|
105
|
-
ctx.render();
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
const promptConfirm = ({
|
|
109
|
-
message
|
|
110
|
-
}) => prompt({
|
|
111
|
-
value: true,
|
|
112
|
-
render(ctx) {
|
|
113
|
-
return `${pqb.colors.bright(message)}
|
|
114
|
-
${ctx.submitted ? `> ${ctx.value ? pqb.colors.greenBold("Yes") : pqb.colors.yellowBold("No")}` : pqb.colors.pale(`> (Y/n)`)}
|
|
115
|
-
`;
|
|
116
|
-
},
|
|
117
|
-
onKeyPress(ctx, s) {
|
|
118
|
-
let ok;
|
|
119
|
-
if (s === "y" || s === "Y") ok = true;
|
|
120
|
-
else if (s === "n" || s === "N") ok = false;
|
|
121
|
-
if (ok !== void 0) {
|
|
122
|
-
ctx.submit(ok);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
const promptText = ({
|
|
127
|
-
message,
|
|
128
|
-
default: def = "",
|
|
129
|
-
password,
|
|
130
|
-
min
|
|
131
|
-
}) => {
|
|
132
|
-
let showDefault = true;
|
|
133
|
-
let x = 0;
|
|
134
|
-
const renderValue = (ctx) => password ? "*".repeat(ctx.value.length) : ctx.value;
|
|
135
|
-
return prompt({
|
|
136
|
-
value: def,
|
|
137
|
-
cursor: true,
|
|
138
|
-
validate: (ctx) => !min || ctx.value.length >= min,
|
|
139
|
-
render(ctx) {
|
|
140
|
-
let text = `${pqb.colors.bright(message)}
|
|
141
|
-
> ${ctx.submitted ? renderValue(ctx) : showDefault ? pqb.colors.pale(def) + "\b".repeat(def.length) : ctx.value}`;
|
|
142
|
-
if (ctx.submitted) text += "\n";
|
|
143
|
-
return text;
|
|
144
|
-
},
|
|
145
|
-
onKeyPress(ctx, s) {
|
|
146
|
-
let value = showDefault ? "" : ctx.value;
|
|
147
|
-
if (s === "\x1B[D" && x > 0) {
|
|
148
|
-
x--;
|
|
149
|
-
stdout.write("\b");
|
|
150
|
-
} else if (s === "\x1B[C" && x < value.length) {
|
|
151
|
-
stdout.write(value[x]);
|
|
152
|
-
x++;
|
|
153
|
-
}
|
|
154
|
-
if (s !== "\x7F" && s !== "\x1B[3~" && !visibleChars(s)) return;
|
|
155
|
-
if (showDefault) {
|
|
156
|
-
showDefault = false;
|
|
157
|
-
stdout.write(" ".repeat(def.length) + "\b".repeat(def.length));
|
|
158
|
-
}
|
|
159
|
-
const prev = value;
|
|
160
|
-
const prevX = x;
|
|
161
|
-
if (s === "\x7F") {
|
|
162
|
-
if (x > 0) {
|
|
163
|
-
value = value.slice(0, x - 1) + value.slice(x);
|
|
164
|
-
x--;
|
|
165
|
-
}
|
|
166
|
-
} else if (s === "\x1B[3~") {
|
|
167
|
-
if (x < value.length) {
|
|
168
|
-
value = value.slice(0, x) + value.slice(x + 1);
|
|
169
|
-
}
|
|
170
|
-
} else {
|
|
171
|
-
value = value.slice(0, x) + s + value.slice(x);
|
|
172
|
-
x++;
|
|
173
|
-
}
|
|
174
|
-
ctx.value = value;
|
|
175
|
-
const spaces = prev.length - value.length;
|
|
176
|
-
stdout.write(
|
|
177
|
-
"\b".repeat(prevX) + renderValue(ctx) + (spaces > 0 ? " ".repeat(spaces) + "\b".repeat(spaces) : "") + "\b".repeat(value.length - x)
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
const getMaybeTransactionAdapter = (db) => "$getAdapter" in db ? db.$getAdapter() : db;
|
|
184
|
-
const runSqlInSavePoint = async (db, sql, code) => {
|
|
185
|
-
const adapter = getMaybeTransactionAdapter(db);
|
|
186
|
-
try {
|
|
187
|
-
await adapter.query(
|
|
188
|
-
adapter.isInTransaction() ? `SAVEPOINT s; ${sql}; RELEASE SAVEPOINT s` : sql
|
|
189
|
-
);
|
|
190
|
-
return "done";
|
|
191
|
-
} catch (err) {
|
|
192
|
-
if (err.code === code) {
|
|
193
|
-
if (adapter.isInTransaction()) {
|
|
194
|
-
await adapter.query(`ROLLBACK TO SAVEPOINT s`);
|
|
195
|
-
}
|
|
196
|
-
return "already";
|
|
197
|
-
}
|
|
198
|
-
throw err;
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
class CreateOrDropError extends Error {
|
|
203
|
-
constructor(message, status, cause) {
|
|
204
|
-
super(message);
|
|
205
|
-
this.status = status;
|
|
206
|
-
this.cause = cause;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
const createDatabase = async (db, {
|
|
210
|
-
database,
|
|
211
|
-
owner
|
|
212
|
-
}) => {
|
|
213
|
-
return createOrDrop(
|
|
214
|
-
db,
|
|
215
|
-
`CREATE DATABASE "${database}"${owner ? ` OWNER "${owner}"` : ""}`
|
|
216
|
-
);
|
|
217
|
-
};
|
|
218
|
-
const dropDatabase = async (db, { database }) => {
|
|
219
|
-
return createOrDrop(db, `DROP DATABASE "${database}"`);
|
|
220
|
-
};
|
|
221
|
-
const createOrDrop = async (db, sql) => {
|
|
222
|
-
try {
|
|
223
|
-
const adapter = getMaybeTransactionAdapter(db);
|
|
224
|
-
await adapter.query(sql);
|
|
225
|
-
return "done";
|
|
226
|
-
} catch (error) {
|
|
227
|
-
const err = error;
|
|
228
|
-
if (typeof err.message === "string" && err.message.includes("sslmode=require")) {
|
|
229
|
-
throw new CreateOrDropError("SSL required", "ssl-required", err);
|
|
230
|
-
}
|
|
231
|
-
if (err.code === "42P04" || err.code === "3D000") {
|
|
232
|
-
return "already";
|
|
233
|
-
}
|
|
234
|
-
if (err.code === "42501") {
|
|
235
|
-
throw new CreateOrDropError("Insufficient privilege", "forbidden", err);
|
|
236
|
-
}
|
|
237
|
-
if (typeof err.message === "string" && err.message.includes("password authentication failed")) {
|
|
238
|
-
throw new CreateOrDropError("Authentication failed", "auth-failed", err);
|
|
239
|
-
}
|
|
240
|
-
throw err;
|
|
241
|
-
}
|
|
242
|
-
};
|
|
243
|
-
const createSchema$1 = async (db, sql) => runSqlInSavePoint(db, `CREATE SCHEMA ${sql}`, "42P06");
|
|
244
|
-
const dropSchema = async (db, sql) => runSqlInSavePoint(db, `DROP SCHEMA ${sql}`, "3F000");
|
|
245
|
-
const createTable$1 = async (db, sql) => runSqlInSavePoint(db, `CREATE TABLE ${sql}`, "42P07");
|
|
246
|
-
const dropTable = async (db, sql) => runSqlInSavePoint(db, `DROP TABLE ${sql}`, "42P01");
|
|
8
|
+
var path$1 = require('node:path');
|
|
247
9
|
|
|
248
10
|
const RAKE_DB_LOCK_KEY = "8582141715823621641";
|
|
249
11
|
const getFirstWordAndRest = (input) => {
|
|
@@ -291,7 +53,7 @@ const quoteCustomType = (schema, type) => {
|
|
|
291
53
|
return s ? '"' + s + '".' + t : t;
|
|
292
54
|
};
|
|
293
55
|
const quoteSchemaTable = (arg, excludeCurrentSchema) => {
|
|
294
|
-
return
|
|
56
|
+
return internal.singleQuote(concatSchemaAndName(arg, excludeCurrentSchema));
|
|
295
57
|
};
|
|
296
58
|
const concatSchemaAndName = ({
|
|
297
59
|
schema,
|
|
@@ -332,10 +94,13 @@ const getCliParam = (args, name) => {
|
|
|
332
94
|
return;
|
|
333
95
|
};
|
|
334
96
|
|
|
335
|
-
const
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
97
|
+
const createMigrationChangeFn = (config) => {
|
|
98
|
+
const conf = config.columnTypes ? config : { columnTypes: internal.makeColumnTypes(internal.defaultSchemaConfig) };
|
|
99
|
+
return (fn) => {
|
|
100
|
+
const change = { fn, config: conf };
|
|
101
|
+
pushChange(change);
|
|
102
|
+
return change;
|
|
103
|
+
};
|
|
339
104
|
};
|
|
340
105
|
let currentChanges = [];
|
|
341
106
|
const clearChanges = () => {
|
|
@@ -346,10 +111,10 @@ const pushChange = (change) => currentChanges.push(change);
|
|
|
346
111
|
|
|
347
112
|
const versionToString = (config, version) => config.migrationId === "timestamp" ? `${version}` : `${version}`.padStart(config.migrationId.serial, "0");
|
|
348
113
|
const columnTypeToSql = (schema, item) => {
|
|
349
|
-
return item.data.isOfCustomType ? item instanceof
|
|
114
|
+
return item.data.isOfCustomType ? item instanceof internal.DomainColumn ? quoteNameFromString(schema, item.dataType) : quoteCustomType(schema, item.toSQL()) : item.toSQL();
|
|
350
115
|
};
|
|
351
116
|
const getColumnName = (item, key, snakeCase) => {
|
|
352
|
-
return item.data.name || (snakeCase ?
|
|
117
|
+
return item.data.name || (snakeCase ? internal.toSnakeCase(key) : key);
|
|
353
118
|
};
|
|
354
119
|
const columnToSql = (schema, name, item, values, hasMultiplePrimaryKeys, snakeCase) => {
|
|
355
120
|
const line = [`"${name}" ${columnTypeToSql(schema, item)}`];
|
|
@@ -396,7 +161,6 @@ const columnToSql = (schema, name, item, values, hasMultiplePrimaryKeys, snakeCa
|
|
|
396
161
|
referencesToSql(
|
|
397
162
|
schema,
|
|
398
163
|
{
|
|
399
|
-
columns: [name],
|
|
400
164
|
...foreignKey
|
|
401
165
|
},
|
|
402
166
|
snakeCase
|
|
@@ -408,11 +172,11 @@ const columnToSql = (schema, name, item, values, hasMultiplePrimaryKeys, snakeCa
|
|
|
408
172
|
};
|
|
409
173
|
const encodeColumnDefault = (def, values, column) => {
|
|
410
174
|
if (def !== void 0 && def !== null && typeof def !== "function") {
|
|
411
|
-
if (
|
|
175
|
+
if (internal.isRawSQL(def)) {
|
|
412
176
|
return `(${def.toSQL({ values })})`;
|
|
413
177
|
} else {
|
|
414
|
-
return
|
|
415
|
-
column instanceof
|
|
178
|
+
return internal.escapeForMigration(
|
|
179
|
+
column instanceof internal.ArrayColumn && Array.isArray(def) ? "{" + (column.data.item.data.encode ? def.map((x) => column.data.item.data.encode(x)) : def).join(",") + "}" : column?.data.encode ? column.data.encode(def) : def
|
|
416
180
|
);
|
|
417
181
|
}
|
|
418
182
|
}
|
|
@@ -473,7 +237,7 @@ const getConstraintName = (table, constraint, snakeCase) => {
|
|
|
473
237
|
if (constraint.references) {
|
|
474
238
|
let { columns } = constraint.references;
|
|
475
239
|
if (snakeCase) {
|
|
476
|
-
columns = columns.map(
|
|
240
|
+
columns = columns.map(internal.toSnakeCase);
|
|
477
241
|
}
|
|
478
242
|
return makeConstraintName(table, columns, "fkey");
|
|
479
243
|
}
|
|
@@ -501,14 +265,14 @@ const checkToSql = (check, values) => {
|
|
|
501
265
|
};
|
|
502
266
|
const foreignKeyToSql = (schema, item, snakeCase) => {
|
|
503
267
|
return `FOREIGN KEY (${joinColumns(
|
|
504
|
-
snakeCase ? item.columns.map(
|
|
268
|
+
snakeCase ? item.columns.map(internal.toSnakeCase) : item.columns
|
|
505
269
|
)}) ${referencesToSql(schema, item, snakeCase)}`;
|
|
506
270
|
};
|
|
507
271
|
const referencesToSql = (schema, references, snakeCase) => {
|
|
508
272
|
const [s, table] = getForeignKeyTable(schema, references.fnOrTable);
|
|
509
273
|
const sql = [
|
|
510
274
|
`REFERENCES ${quoteTable(s, table)}(${joinColumns(
|
|
511
|
-
snakeCase ? references.foreignColumns.map(
|
|
275
|
+
snakeCase ? references.foreignColumns.map(internal.toSnakeCase) : references.foreignColumns
|
|
512
276
|
)})`
|
|
513
277
|
];
|
|
514
278
|
const { options } = references;
|
|
@@ -528,10 +292,10 @@ const makeConstraintName = (table, columns, suffix) => {
|
|
|
528
292
|
const long = `${table}_${columns.join("_")}_${suffix}`;
|
|
529
293
|
if (long.length <= MAX_CONSTRAINT_NAME_LEN) return long;
|
|
530
294
|
for (let partLen = 3; partLen > 0; partLen--) {
|
|
531
|
-
const shorter = `${
|
|
532
|
-
|
|
295
|
+
const shorter = `${internal.toCamelCase(
|
|
296
|
+
internal.toSnakeCase(table).split("_").map((p) => p.slice(0, partLen)).join("_")
|
|
533
297
|
)}_${columns.map(
|
|
534
|
-
(c) =>
|
|
298
|
+
(c) => internal.toCamelCase(
|
|
535
299
|
c.split("_").map((p) => p.slice(0, partLen)).join("_")
|
|
536
300
|
)
|
|
537
301
|
).join("_")}_${suffix}`;
|
|
@@ -540,8 +304,8 @@ const makeConstraintName = (table, columns, suffix) => {
|
|
|
540
304
|
const short = `${table}_${columns.length}columns_${suffix}`;
|
|
541
305
|
if (short.length <= MAX_CONSTRAINT_NAME_LEN) return short;
|
|
542
306
|
for (let partLen = 3; partLen > 0; partLen--) {
|
|
543
|
-
const short2 = `${
|
|
544
|
-
|
|
307
|
+
const short2 = `${internal.toCamelCase(
|
|
308
|
+
internal.toSnakeCase(table).split("_").map((p) => p.slice(0, partLen)).join("_")
|
|
545
309
|
)}_${columns.length}columns_${suffix}`;
|
|
546
310
|
if (short2.length <= MAX_CONSTRAINT_NAME_LEN) return short2;
|
|
547
311
|
}
|
|
@@ -623,7 +387,7 @@ const indexesToQuery = (up, { schema, name: tableName }, indexes, snakeCase, lan
|
|
|
623
387
|
}
|
|
624
388
|
if (options.where) {
|
|
625
389
|
sql.push(
|
|
626
|
-
`WHERE ${
|
|
390
|
+
`WHERE ${internal.isRawSQL(options.where) ? options.where.toSQL({ values }) : options.where}`
|
|
627
391
|
);
|
|
628
392
|
}
|
|
629
393
|
return { text: sql.join(" "), values };
|
|
@@ -666,19 +430,19 @@ const excludesToQuery = (up, { schema, name: tableName }, excludes, snakeCase) =
|
|
|
666
430
|
include?.length && `INCLUDE (${include.map((column) => `"${column}"`).join(", ")})`,
|
|
667
431
|
options.with && `WITH (${options.with})`,
|
|
668
432
|
options.tablespace && `USING INDEX TABLESPACE ${options.tablespace}`,
|
|
669
|
-
options.where && `WHERE ${
|
|
433
|
+
options.where && `WHERE ${internal.isRawSQL(options.where) ? options.where.toSQL({ values }) : options.where}`
|
|
670
434
|
].filter((x) => !!x).join(" ");
|
|
671
435
|
return { text, values };
|
|
672
436
|
});
|
|
673
437
|
};
|
|
674
438
|
const getIndexOrExcludeMainOptions = (tableName, item, getName, snakeCase) => {
|
|
675
|
-
let include = item.options.include ?
|
|
439
|
+
let include = item.options.include ? internal.toArray(item.options.include) : void 0;
|
|
676
440
|
let { columns } = item;
|
|
677
441
|
if (snakeCase) {
|
|
678
442
|
columns = columns.map(
|
|
679
|
-
(c) => "column" in c ? { ...c, column:
|
|
443
|
+
(c) => "column" in c ? { ...c, column: internal.toSnakeCase(c.column) } : c
|
|
680
444
|
);
|
|
681
|
-
if (include) include = include.map(
|
|
445
|
+
if (include) include = include.map(internal.toSnakeCase);
|
|
682
446
|
}
|
|
683
447
|
return {
|
|
684
448
|
columns,
|
|
@@ -690,7 +454,7 @@ const commentsToQuery = (schemaTable, comments) => {
|
|
|
690
454
|
return comments.map(({ column, comment }) => ({
|
|
691
455
|
text: `COMMENT ON COLUMN ${quoteWithSchema(
|
|
692
456
|
schemaTable
|
|
693
|
-
)}."${column}" IS ${
|
|
457
|
+
)}."${column}" IS ${internal.escapeForMigration(comment)}`,
|
|
694
458
|
values: []
|
|
695
459
|
}));
|
|
696
460
|
};
|
|
@@ -700,7 +464,7 @@ const primaryKeyToSql = (primaryKey) => {
|
|
|
700
464
|
const interpolateSqlValues = ({ text, values }) => {
|
|
701
465
|
return values?.length ? text.replace(/\$(\d+)/g, (_, n) => {
|
|
702
466
|
const i = +n - 1;
|
|
703
|
-
return
|
|
467
|
+
return internal.escapeForMigration(values[i]);
|
|
704
468
|
}) : text;
|
|
705
469
|
};
|
|
706
470
|
const nameColumnChecks = (table, column, checks) => checks.map((check, i) => ({
|
|
@@ -738,8 +502,8 @@ const migrationsSchemaTableSql = (adapter, config) => {
|
|
|
738
502
|
|
|
739
503
|
const tableMethods = {
|
|
740
504
|
enum(name) {
|
|
741
|
-
return new
|
|
742
|
-
|
|
505
|
+
return new internal.EnumColumn(
|
|
506
|
+
internal.defaultSchemaConfig,
|
|
743
507
|
name,
|
|
744
508
|
[],
|
|
745
509
|
void 0
|
|
@@ -752,7 +516,7 @@ class RakeDbError extends Error {
|
|
|
752
516
|
class NoPrimaryKey extends RakeDbError {
|
|
753
517
|
}
|
|
754
518
|
|
|
755
|
-
const createTable = async (migration, up, tableName, first, second, third) => {
|
|
519
|
+
const createTable$1 = async (migration, up, tableName, first, second, third) => {
|
|
756
520
|
let options;
|
|
757
521
|
let fn;
|
|
758
522
|
let dataFn;
|
|
@@ -761,7 +525,7 @@ const createTable = async (migration, up, tableName, first, second, third) => {
|
|
|
761
525
|
fn = second;
|
|
762
526
|
dataFn = third;
|
|
763
527
|
} else {
|
|
764
|
-
options =
|
|
528
|
+
options = internal.emptyObject;
|
|
765
529
|
fn = first;
|
|
766
530
|
dataFn = second;
|
|
767
531
|
}
|
|
@@ -771,23 +535,23 @@ const createTable = async (migration, up, tableName, first, second, third) => {
|
|
|
771
535
|
Object.create(migration.columnTypes),
|
|
772
536
|
tableMethods
|
|
773
537
|
);
|
|
774
|
-
types[
|
|
538
|
+
types[internal.snakeCaseKey] = snakeCase;
|
|
775
539
|
let shape;
|
|
776
540
|
let tableData;
|
|
777
541
|
if (fn) {
|
|
778
|
-
shape =
|
|
542
|
+
shape = internal.getColumnTypes(
|
|
779
543
|
types,
|
|
780
544
|
fn,
|
|
781
545
|
migration.options.baseTable?.nowSQL,
|
|
782
546
|
language
|
|
783
547
|
);
|
|
784
|
-
tableData =
|
|
548
|
+
tableData = internal.parseTableData(dataFn);
|
|
785
549
|
tableData.constraints?.forEach((x, i) => {
|
|
786
550
|
if (x.name || !x.check) return;
|
|
787
551
|
x.name = `${tableName}_check${i === 0 ? "" : i}`;
|
|
788
552
|
});
|
|
789
553
|
} else {
|
|
790
|
-
shape = tableData =
|
|
554
|
+
shape = tableData = internal.emptyObject;
|
|
791
555
|
}
|
|
792
556
|
const schema = migration.adapter.getSchema();
|
|
793
557
|
const ast = makeAst$4(
|
|
@@ -874,7 +638,7 @@ const astToQueries$1 = (schema, ast, snakeCase, language) => {
|
|
|
874
638
|
const { shape } = ast;
|
|
875
639
|
for (const key in shape) {
|
|
876
640
|
const item = shape[key];
|
|
877
|
-
if (!(item instanceof
|
|
641
|
+
if (!(item instanceof internal.EnumColumn)) continue;
|
|
878
642
|
queries.push(makePopulateEnumQuery(schema, item));
|
|
879
643
|
}
|
|
880
644
|
if (ast.action === "drop") {
|
|
@@ -952,7 +716,7 @@ const astToQueries$1 = (schema, ast, snakeCase, language) => {
|
|
|
952
716
|
);
|
|
953
717
|
if (ast.comment) {
|
|
954
718
|
queries.push({
|
|
955
|
-
text: `COMMENT ON TABLE ${quoteWithSchema(ast)} IS ${
|
|
719
|
+
text: `COMMENT ON TABLE ${quoteWithSchema(ast)} IS ${internal.escapeString(
|
|
956
720
|
ast.comment
|
|
957
721
|
)}`
|
|
958
722
|
});
|
|
@@ -983,16 +747,16 @@ const resetChangeTableData = () => {
|
|
|
983
747
|
};
|
|
984
748
|
const addOrDropChanges = [];
|
|
985
749
|
function add(item, options) {
|
|
986
|
-
|
|
750
|
+
internal.consumeColumnName();
|
|
987
751
|
setName(this, item);
|
|
988
|
-
if (item instanceof
|
|
752
|
+
if (item instanceof internal.Column) {
|
|
989
753
|
const result = addOrDrop("add", item, options);
|
|
990
754
|
if (result.type === "change") return result;
|
|
991
755
|
addOrDropChanges.push(result);
|
|
992
756
|
return addOrDropChanges.length - 1;
|
|
993
757
|
}
|
|
994
758
|
for (const key in item) {
|
|
995
|
-
if (item[key] instanceof
|
|
759
|
+
if (item[key] instanceof internal.Column) {
|
|
996
760
|
const result = {};
|
|
997
761
|
for (const key2 in item) {
|
|
998
762
|
result[key2] = {
|
|
@@ -1003,22 +767,22 @@ function add(item, options) {
|
|
|
1003
767
|
}
|
|
1004
768
|
return result;
|
|
1005
769
|
}
|
|
1006
|
-
|
|
770
|
+
internal.parseTableDataInput(changeTableData.add, item);
|
|
1007
771
|
break;
|
|
1008
772
|
}
|
|
1009
773
|
return void 0;
|
|
1010
774
|
}
|
|
1011
775
|
const drop = function(item, options) {
|
|
1012
|
-
|
|
776
|
+
internal.consumeColumnName();
|
|
1013
777
|
setName(this, item);
|
|
1014
|
-
if (item instanceof
|
|
778
|
+
if (item instanceof internal.Column) {
|
|
1015
779
|
const result = addOrDrop("drop", item, options);
|
|
1016
780
|
if (result.type === "change") return result;
|
|
1017
781
|
addOrDropChanges.push(result);
|
|
1018
782
|
return addOrDropChanges.length - 1;
|
|
1019
783
|
}
|
|
1020
784
|
for (const key in item) {
|
|
1021
|
-
if (item[key] instanceof
|
|
785
|
+
if (item[key] instanceof internal.Column) {
|
|
1022
786
|
const result = {};
|
|
1023
787
|
for (const key2 in item) {
|
|
1024
788
|
result[key2] = {
|
|
@@ -1029,13 +793,13 @@ const drop = function(item, options) {
|
|
|
1029
793
|
}
|
|
1030
794
|
return result;
|
|
1031
795
|
}
|
|
1032
|
-
|
|
796
|
+
internal.parseTableDataInput(changeTableData.drop, item);
|
|
1033
797
|
break;
|
|
1034
798
|
}
|
|
1035
799
|
return void 0;
|
|
1036
800
|
};
|
|
1037
801
|
const addOrDrop = (type, item, options) => {
|
|
1038
|
-
if (item instanceof
|
|
802
|
+
if (item instanceof internal.UnknownColumn) {
|
|
1039
803
|
const empty = columnTypeToColumnChange({
|
|
1040
804
|
type: "change",
|
|
1041
805
|
to: {}
|
|
@@ -1060,7 +824,7 @@ const addOrDrop = (type, item, options) => {
|
|
|
1060
824
|
};
|
|
1061
825
|
};
|
|
1062
826
|
const columnTypeToColumnChange = (item, name) => {
|
|
1063
|
-
if (item instanceof
|
|
827
|
+
if (item instanceof internal.Column) {
|
|
1064
828
|
let column = item;
|
|
1065
829
|
const foreignKeys = column.data.foreignKeys;
|
|
1066
830
|
if (foreignKeys?.some((it) => "fn" in it)) {
|
|
@@ -1082,9 +846,9 @@ const setName = (self, item) => {
|
|
|
1082
846
|
var _a, _b;
|
|
1083
847
|
const name = self[nameKey];
|
|
1084
848
|
if (!name) return;
|
|
1085
|
-
if ("column" in item && item.column instanceof
|
|
849
|
+
if ("column" in item && item.column instanceof internal.Column) {
|
|
1086
850
|
(_a = item.column.data).name ?? (_a.name = name);
|
|
1087
|
-
} else if (item instanceof
|
|
851
|
+
} else if (item instanceof internal.Column) {
|
|
1088
852
|
(_b = item.data).name ?? (_b.name = name);
|
|
1089
853
|
} else {
|
|
1090
854
|
item.name ?? (item.name = name);
|
|
@@ -1092,9 +856,9 @@ const setName = (self, item) => {
|
|
|
1092
856
|
};
|
|
1093
857
|
const tableChangeMethods = {
|
|
1094
858
|
...tableMethods,
|
|
1095
|
-
...
|
|
859
|
+
...internal.tableDataMethods,
|
|
1096
860
|
name(name) {
|
|
1097
|
-
|
|
861
|
+
internal.setCurrentColumnName(name);
|
|
1098
862
|
const types = Object.create(this);
|
|
1099
863
|
types[nameKey] = name;
|
|
1100
864
|
return types;
|
|
@@ -1102,7 +866,7 @@ const tableChangeMethods = {
|
|
|
1102
866
|
add,
|
|
1103
867
|
drop,
|
|
1104
868
|
change(from, to, using) {
|
|
1105
|
-
|
|
869
|
+
internal.consumeColumnName();
|
|
1106
870
|
const f = columnTypeToColumnChange(from);
|
|
1107
871
|
const t = columnTypeToColumnChange(to);
|
|
1108
872
|
setName(this, f);
|
|
@@ -1160,13 +924,13 @@ const tableChangeMethods = {
|
|
|
1160
924
|
const changeTable = async (migration, up, tableName, options, fn) => {
|
|
1161
925
|
const snakeCase = "snakeCase" in options ? options.snakeCase : migration.options.snakeCase;
|
|
1162
926
|
const language = "language" in options ? options.language : migration.options.language;
|
|
1163
|
-
|
|
927
|
+
internal.setDefaultLanguage(language);
|
|
1164
928
|
resetChangeTableData();
|
|
1165
929
|
const tableChanger = Object.create(
|
|
1166
930
|
migration.columnTypes
|
|
1167
931
|
);
|
|
1168
932
|
Object.assign(tableChanger, tableChangeMethods);
|
|
1169
|
-
tableChanger[
|
|
933
|
+
tableChanger[internal.snakeCaseKey] = snakeCase;
|
|
1170
934
|
addOrDropChanges.length = 0;
|
|
1171
935
|
const changeData = fn?.(tableChanger) || {};
|
|
1172
936
|
const schema = migration.adapter.getSchema();
|
|
@@ -1193,7 +957,7 @@ const makeAst$3 = (schema, up, name, changeData, changeTableData2, options) => {
|
|
|
1193
957
|
if (typeof item === "number") {
|
|
1194
958
|
consumedChanges[item] = true;
|
|
1195
959
|
item = addOrDropChanges[item];
|
|
1196
|
-
} else if (item instanceof
|
|
960
|
+
} else if (item instanceof internal.Column) {
|
|
1197
961
|
item = addOrDrop("add", item);
|
|
1198
962
|
}
|
|
1199
963
|
if ("type" in item) {
|
|
@@ -1223,7 +987,7 @@ const makeAst$3 = (schema, up, name, changeData, changeTableData2, options) => {
|
|
|
1223
987
|
if (!name2) {
|
|
1224
988
|
throw new Error(`Column in ...t.${change.type}() must have a name`);
|
|
1225
989
|
}
|
|
1226
|
-
const arr = shape[name2] ?
|
|
990
|
+
const arr = shape[name2] ? internal.toArray(shape[name2]) : [];
|
|
1227
991
|
arr[up ? "push" : "unshift"](
|
|
1228
992
|
up ? change : { ...change, type: change.type === "add" ? "drop" : "add" }
|
|
1229
993
|
);
|
|
@@ -1243,7 +1007,7 @@ const astToQueries = (schema, ast, snakeCase, language) => {
|
|
|
1243
1007
|
const queries = [];
|
|
1244
1008
|
if (ast.comment !== void 0) {
|
|
1245
1009
|
queries.push({
|
|
1246
|
-
text: `COMMENT ON TABLE ${quoteWithSchema(ast)} IS ${ast.comment === null ? "NULL" :
|
|
1010
|
+
text: `COMMENT ON TABLE ${quoteWithSchema(ast)} IS ${ast.comment === null ? "NULL" : internal.escapeString(
|
|
1247
1011
|
typeof ast.comment === "string" ? ast.comment : ast.comment[1]
|
|
1248
1012
|
)}`
|
|
1249
1013
|
});
|
|
@@ -1284,14 +1048,14 @@ const astToQueries = (schema, ast, snakeCase, language) => {
|
|
|
1284
1048
|
addPrimaryKeys.name = ast.add.primaryKey.name;
|
|
1285
1049
|
const { columns } = ast.add.primaryKey;
|
|
1286
1050
|
addPrimaryKeys.columns.push(
|
|
1287
|
-
...snakeCase ? columns.map(
|
|
1051
|
+
...snakeCase ? columns.map(internal.toSnakeCase) : columns
|
|
1288
1052
|
);
|
|
1289
1053
|
}
|
|
1290
1054
|
if (ast.drop.primaryKey) {
|
|
1291
1055
|
dropPrimaryKeys.name = ast.drop.primaryKey.name;
|
|
1292
1056
|
const { columns } = ast.drop.primaryKey;
|
|
1293
1057
|
dropPrimaryKeys.columns.push(
|
|
1294
|
-
...snakeCase ? columns.map(
|
|
1058
|
+
...snakeCase ? columns.map(internal.toSnakeCase) : columns
|
|
1295
1059
|
);
|
|
1296
1060
|
}
|
|
1297
1061
|
const alterTable = [];
|
|
@@ -1379,7 +1143,7 @@ const astToQueries = (schema, ast, snakeCase, language) => {
|
|
|
1379
1143
|
`ADD ${primaryKeyToSql(
|
|
1380
1144
|
snakeCase ? {
|
|
1381
1145
|
name: addPrimaryKeys.name,
|
|
1382
|
-
columns: addPrimaryKeys.columns.map(
|
|
1146
|
+
columns: addPrimaryKeys.columns.map(internal.toSnakeCase)
|
|
1383
1147
|
} : addPrimaryKeys
|
|
1384
1148
|
)}`
|
|
1385
1149
|
);
|
|
@@ -1425,7 +1189,7 @@ const alterTableSql = (tableName, lines, values) => ({
|
|
|
1425
1189
|
const handlePrerequisitesForTableItem = (schema, key, item, queries, addPrimaryKeys, dropPrimaryKeys, snakeCase) => {
|
|
1426
1190
|
if ("item" in item) {
|
|
1427
1191
|
const { item: column } = item;
|
|
1428
|
-
if (column instanceof
|
|
1192
|
+
if (column instanceof internal.EnumColumn) {
|
|
1429
1193
|
queries.push(makePopulateEnumQuery(schema, column));
|
|
1430
1194
|
}
|
|
1431
1195
|
}
|
|
@@ -1438,21 +1202,21 @@ const handlePrerequisitesForTableItem = (schema, key, item, queries, addPrimaryK
|
|
|
1438
1202
|
dropPrimaryKeys.columns.push(getColumnName(item.item, key, snakeCase));
|
|
1439
1203
|
}
|
|
1440
1204
|
} else if (item.type === "change") {
|
|
1441
|
-
if (item.from.column instanceof
|
|
1205
|
+
if (item.from.column instanceof internal.EnumColumn) {
|
|
1442
1206
|
queries.push(makePopulateEnumQuery(schema, item.from.column));
|
|
1443
1207
|
}
|
|
1444
|
-
if (item.to.column instanceof
|
|
1208
|
+
if (item.to.column instanceof internal.EnumColumn) {
|
|
1445
1209
|
queries.push(makePopulateEnumQuery(schema, item.to.column));
|
|
1446
1210
|
}
|
|
1447
1211
|
if (item.from.primaryKey) {
|
|
1448
1212
|
dropPrimaryKeys.columns.push(
|
|
1449
|
-
item.from.column ? getColumnName(item.from.column, key, snakeCase) : snakeCase ?
|
|
1213
|
+
item.from.column ? getColumnName(item.from.column, key, snakeCase) : snakeCase ? internal.toSnakeCase(key) : key
|
|
1450
1214
|
);
|
|
1451
1215
|
dropPrimaryKeys.change = true;
|
|
1452
1216
|
}
|
|
1453
1217
|
if (item.to.primaryKey) {
|
|
1454
1218
|
addPrimaryKeys.columns.push(
|
|
1455
|
-
item.to.column ? getColumnName(item.to.column, key, snakeCase) : snakeCase ?
|
|
1219
|
+
item.to.column ? getColumnName(item.to.column, key, snakeCase) : snakeCase ? internal.toSnakeCase(key) : key
|
|
1456
1220
|
);
|
|
1457
1221
|
addPrimaryKeys.change = true;
|
|
1458
1222
|
}
|
|
@@ -1490,13 +1254,13 @@ const handleTableItemChange = (schema, key, item, ast, alterTable, renameItems,
|
|
|
1490
1254
|
let changeType = false;
|
|
1491
1255
|
if (to.type && (from.type !== to.type || from.collate !== to.collate)) {
|
|
1492
1256
|
changeType = true;
|
|
1493
|
-
const type = !to.column || to.column.data.isOfCustomType ? to.column && to.column instanceof
|
|
1494
|
-
const using = item.using?.usingUp ? ` USING ${item.using.usingUp.toSQL({ values })}` : to.column instanceof
|
|
1257
|
+
const type = !to.column || to.column.data.isOfCustomType ? to.column && to.column instanceof internal.DomainColumn ? quoteNameFromString(schema, to.type) : quoteCustomType(schema, to.type) : to.type;
|
|
1258
|
+
const using = item.using?.usingUp ? ` USING ${item.using.usingUp.toSQL({ values })}` : to.column instanceof internal.EnumColumn ? ` USING "${name}"::text::${type}` : to.column instanceof internal.ArrayColumn ? ` USING "${name}"::text[]::${type}` : "";
|
|
1495
1259
|
alterTable.push(
|
|
1496
1260
|
`ALTER COLUMN "${name}" TYPE ${type}${to.collate ? ` COLLATE ${quoteNameFromString(schema, to.collate)}` : ""}${using}`
|
|
1497
1261
|
);
|
|
1498
1262
|
}
|
|
1499
|
-
if (typeof from.identity !== typeof to.identity || !
|
|
1263
|
+
if (typeof from.identity !== typeof to.identity || !internal.deepCompare(from.identity, to.identity)) {
|
|
1500
1264
|
if (from.identity) {
|
|
1501
1265
|
alterTable.push(`ALTER COLUMN "${name}" DROP IDENTITY`);
|
|
1502
1266
|
}
|
|
@@ -1556,7 +1320,7 @@ const handleTableItemChange = (schema, key, item, ast, alterTable, renameItems,
|
|
|
1556
1320
|
references: {
|
|
1557
1321
|
columns: [name],
|
|
1558
1322
|
...fromFkey,
|
|
1559
|
-
foreignColumns: snakeCase ? fromFkey.foreignColumns.map(
|
|
1323
|
+
foreignColumns: snakeCase ? fromFkey.foreignColumns.map(internal.toSnakeCase) : fromFkey.foreignColumns
|
|
1560
1324
|
}
|
|
1561
1325
|
});
|
|
1562
1326
|
}
|
|
@@ -1567,7 +1331,7 @@ const handleTableItemChange = (schema, key, item, ast, alterTable, renameItems,
|
|
|
1567
1331
|
references: {
|
|
1568
1332
|
columns: [name],
|
|
1569
1333
|
...toFkey,
|
|
1570
|
-
foreignColumns: snakeCase ? toFkey.foreignColumns.map(
|
|
1334
|
+
foreignColumns: snakeCase ? toFkey.foreignColumns.map(internal.toSnakeCase) : toFkey.foreignColumns
|
|
1571
1335
|
}
|
|
1572
1336
|
});
|
|
1573
1337
|
}
|
|
@@ -1587,7 +1351,7 @@ const handleTableItemChange = (schema, key, item, ast, alterTable, renameItems,
|
|
|
1587
1351
|
}
|
|
1588
1352
|
} else if (item.type === "rename") {
|
|
1589
1353
|
renameItems.push(
|
|
1590
|
-
snakeCase ? renameColumnSql(
|
|
1354
|
+
snakeCase ? renameColumnSql(internal.toSnakeCase(key), internal.toSnakeCase(item.name)) : renameColumnSql(key, item.name)
|
|
1591
1355
|
);
|
|
1592
1356
|
}
|
|
1593
1357
|
};
|
|
@@ -1596,7 +1360,7 @@ const pushIndexesOrExcludes = (key, from, to, name, add2, drop2) => {
|
|
|
1596
1360
|
for (let i = 0; i < len; i++) {
|
|
1597
1361
|
const fromItem = from[key]?.[i];
|
|
1598
1362
|
const toItem = to[key]?.[i];
|
|
1599
|
-
if ((fromItem || toItem) && (!fromItem || !toItem || !
|
|
1363
|
+
if ((fromItem || toItem) && (!fromItem || !toItem || !internal.deepCompare(fromItem, toItem))) {
|
|
1600
1364
|
if (fromItem) {
|
|
1601
1365
|
drop2.push({
|
|
1602
1366
|
...fromItem,
|
|
@@ -1628,7 +1392,7 @@ const getChangeColumnName = (what, change, key, snakeCase) => {
|
|
|
1628
1392
|
return change.name || (change[what].column ? (
|
|
1629
1393
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1630
1394
|
getColumnName(change[what].column, key, snakeCase)
|
|
1631
|
-
) : snakeCase ?
|
|
1395
|
+
) : snakeCase ? internal.toSnakeCase(key) : key);
|
|
1632
1396
|
};
|
|
1633
1397
|
const renameColumnSql = (from, to) => {
|
|
1634
1398
|
return `RENAME COLUMN "${from}" TO "${to}"`;
|
|
@@ -1642,7 +1406,7 @@ const createView = async (migration, up, name, options, sql) => {
|
|
|
1642
1406
|
};
|
|
1643
1407
|
const makeAst$2 = (schema, up, fullName, options, sql) => {
|
|
1644
1408
|
if (typeof sql === "string") {
|
|
1645
|
-
sql =
|
|
1409
|
+
sql = internal.raw({ raw: sql });
|
|
1646
1410
|
}
|
|
1647
1411
|
const [s, name] = getSchemaAndTableFromName(schema, fullName);
|
|
1648
1412
|
return {
|
|
@@ -1675,7 +1439,7 @@ const astToQuery$1 = (ast) => {
|
|
|
1675
1439
|
if (options?.with) {
|
|
1676
1440
|
const list = [];
|
|
1677
1441
|
if (options.with.checkOption)
|
|
1678
|
-
list.push(`check_option = ${
|
|
1442
|
+
list.push(`check_option = ${internal.singleQuote(options.with.checkOption)}`);
|
|
1679
1443
|
if (options.with.securityBarrier) list.push(`security_barrier = true`);
|
|
1680
1444
|
if (options.with.securityInvoker) list.push(`security_invoker = true`);
|
|
1681
1445
|
sql.push(`WITH ( ${list.join(", ")} )`);
|
|
@@ -1965,7 +1729,7 @@ const buildQuery = (ast, objectType, privileges, grantable, action) => {
|
|
|
1965
1729
|
const createMigrationInterface = (tx, up, config) => {
|
|
1966
1730
|
const adapter = Object.create(tx);
|
|
1967
1731
|
const { query, arrays } = adapter;
|
|
1968
|
-
const log =
|
|
1732
|
+
const log = internal.logParamToLogObject(config.logger || console, config.log);
|
|
1969
1733
|
adapter.query = (text, values) => {
|
|
1970
1734
|
return wrapWithEnhancingError(
|
|
1971
1735
|
text,
|
|
@@ -1981,27 +1745,37 @@ const createMigrationInterface = (tx, up, config) => {
|
|
|
1981
1745
|
);
|
|
1982
1746
|
};
|
|
1983
1747
|
Object.assign(adapter, { silentQuery: query, silentArrays: arrays });
|
|
1984
|
-
const
|
|
1985
|
-
|
|
1986
|
-
columnTypes: config.columnTypes
|
|
1987
|
-
});
|
|
1988
|
-
const { prototype: proto } = Migration;
|
|
1989
|
-
for (const key of Object.getOwnPropertyNames(proto)) {
|
|
1990
|
-
db[key] = proto[key];
|
|
1991
|
-
}
|
|
1992
|
-
return Object.assign(db, {
|
|
1748
|
+
const dbPerColumnTypes = /* @__PURE__ */ new Map();
|
|
1749
|
+
return {
|
|
1993
1750
|
adapter,
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1751
|
+
getDb(columnTypes) {
|
|
1752
|
+
let db = dbPerColumnTypes.get(columnTypes);
|
|
1753
|
+
if (!db) {
|
|
1754
|
+
db = pqb.createDbWithAdapter({
|
|
1755
|
+
adapter,
|
|
1756
|
+
columnTypes
|
|
1757
|
+
});
|
|
1758
|
+
const { prototype: proto } = Migration;
|
|
1759
|
+
for (const key of Object.getOwnPropertyNames(proto)) {
|
|
1760
|
+
db[key] = proto[key];
|
|
1761
|
+
}
|
|
1762
|
+
return Object.assign(db, {
|
|
1763
|
+
adapter,
|
|
1764
|
+
log,
|
|
1765
|
+
up,
|
|
1766
|
+
options: config
|
|
1767
|
+
});
|
|
1768
|
+
}
|
|
1769
|
+
return db;
|
|
1770
|
+
}
|
|
1771
|
+
};
|
|
1998
1772
|
};
|
|
1999
1773
|
class Migration {
|
|
2000
1774
|
createTable(tableName, first, second, third) {
|
|
2001
|
-
return createTable(this, this.up, tableName, first, second, third);
|
|
1775
|
+
return createTable$1(this, this.up, tableName, first, second, third);
|
|
2002
1776
|
}
|
|
2003
1777
|
dropTable(tableName, first, second, third) {
|
|
2004
|
-
return createTable(this, !this.up, tableName, first, second, third);
|
|
1778
|
+
return createTable$1(this, !this.up, tableName, first, second, third);
|
|
2005
1779
|
}
|
|
2006
1780
|
changeTable(tableName, cbOrOptions, cb) {
|
|
2007
1781
|
const [fn, options] = typeof cbOrOptions === "function" ? [cbOrOptions, {}] : [cb, cbOrOptions];
|
|
@@ -2334,7 +2108,7 @@ class Migration {
|
|
|
2334
2108
|
* @param schemaName - name of the schema
|
|
2335
2109
|
*/
|
|
2336
2110
|
createSchema(schemaName) {
|
|
2337
|
-
return createSchema(this, this.up, schemaName);
|
|
2111
|
+
return createSchema$1(this, this.up, schemaName);
|
|
2338
2112
|
}
|
|
2339
2113
|
/**
|
|
2340
2114
|
* Renames a database schema, renames it backwards on roll back.
|
|
@@ -2361,7 +2135,7 @@ class Migration {
|
|
|
2361
2135
|
* @param schemaName - name of the schema
|
|
2362
2136
|
*/
|
|
2363
2137
|
dropSchema(schemaName) {
|
|
2364
|
-
return createSchema(this, !this.up, schemaName);
|
|
2138
|
+
return createSchema$1(this, !this.up, schemaName);
|
|
2365
2139
|
}
|
|
2366
2140
|
/**
|
|
2367
2141
|
* `createExtension` creates a database extension, and removes it on rollback.
|
|
@@ -2508,7 +2282,6 @@ class Migration {
|
|
|
2508
2282
|
enumName
|
|
2509
2283
|
);
|
|
2510
2284
|
const ast = {
|
|
2511
|
-
type: "renameEnumValues",
|
|
2512
2285
|
schema,
|
|
2513
2286
|
name,
|
|
2514
2287
|
values
|
|
@@ -2735,7 +2508,7 @@ class Migration {
|
|
|
2735
2508
|
return createCollation(this, !this.up, name, options);
|
|
2736
2509
|
}
|
|
2737
2510
|
createView(name, ...args) {
|
|
2738
|
-
const [options, sql] = args.length === 2 ? args : [
|
|
2511
|
+
const [options, sql] = args.length === 2 ? args : [internal.emptyObject, args[0]];
|
|
2739
2512
|
return createView(
|
|
2740
2513
|
this,
|
|
2741
2514
|
this.up,
|
|
@@ -2745,7 +2518,7 @@ class Migration {
|
|
|
2745
2518
|
);
|
|
2746
2519
|
}
|
|
2747
2520
|
dropView(name, ...args) {
|
|
2748
|
-
const [options, sql] = args.length === 2 ? args : [
|
|
2521
|
+
const [options, sql] = args.length === 2 ? args : [internal.emptyObject, args[0]];
|
|
2749
2522
|
return createView(
|
|
2750
2523
|
this,
|
|
2751
2524
|
!this.up,
|
|
@@ -2811,7 +2584,7 @@ class Migration {
|
|
|
2811
2584
|
);
|
|
2812
2585
|
const values = [
|
|
2813
2586
|
table,
|
|
2814
|
-
this.options.snakeCase ?
|
|
2587
|
+
this.options.snakeCase ? internal.toSnakeCase(columnName) : columnName
|
|
2815
2588
|
];
|
|
2816
2589
|
if (schema) {
|
|
2817
2590
|
text += ' AND "table_schema" = $3';
|
|
@@ -2857,7 +2630,7 @@ class Migration {
|
|
|
2857
2630
|
this,
|
|
2858
2631
|
this.up,
|
|
2859
2632
|
name,
|
|
2860
|
-
params.from ||
|
|
2633
|
+
params.from || internal.emptyObject,
|
|
2861
2634
|
params.to
|
|
2862
2635
|
);
|
|
2863
2636
|
}
|
|
@@ -2922,12 +2695,9 @@ const addCheck = (migration, up, tableName, check) => {
|
|
|
2922
2695
|
...t.add(t.check(check))
|
|
2923
2696
|
}));
|
|
2924
2697
|
};
|
|
2925
|
-
const createSchema = async (migration, up, name) => {
|
|
2698
|
+
const createSchema$1 = async (migration, up, name) => {
|
|
2926
2699
|
const ast = {
|
|
2927
|
-
|
|
2928
|
-
action: up ? "create" : "drop",
|
|
2929
|
-
name
|
|
2930
|
-
};
|
|
2700
|
+
action: up ? "create" : "drop"};
|
|
2931
2701
|
await migration.adapter.query(
|
|
2932
2702
|
`${ast.action === "create" ? "CREATE" : "DROP"} SCHEMA "${name}"`
|
|
2933
2703
|
);
|
|
@@ -2938,7 +2708,6 @@ const createExtension = async (migration, up, fullName, options) => {
|
|
|
2938
2708
|
fullName
|
|
2939
2709
|
);
|
|
2940
2710
|
const ast = {
|
|
2941
|
-
type: "extension",
|
|
2942
2711
|
action: up ? "create" : "drop",
|
|
2943
2712
|
schema,
|
|
2944
2713
|
name,
|
|
@@ -2958,17 +2727,15 @@ const createEnum = async (migration, up, name, values, options = {}) => {
|
|
|
2958
2727
|
name
|
|
2959
2728
|
);
|
|
2960
2729
|
const ast = {
|
|
2961
|
-
type: "enum",
|
|
2962
2730
|
action: up ? "create" : "drop",
|
|
2963
2731
|
schema,
|
|
2964
2732
|
name: enumName,
|
|
2965
|
-
values,
|
|
2966
2733
|
...options
|
|
2967
2734
|
};
|
|
2968
2735
|
let query;
|
|
2969
2736
|
const quotedName = quoteWithSchema(ast);
|
|
2970
2737
|
if (ast.action === "create") {
|
|
2971
|
-
query = `CREATE TYPE ${quotedName} AS ENUM (${values.map(
|
|
2738
|
+
query = `CREATE TYPE ${quotedName} AS ENUM (${values.map(internal.escapeForMigration).join(", ")})`;
|
|
2972
2739
|
} else {
|
|
2973
2740
|
query = `DROP TYPE${ast.dropIfExists ? " IF EXISTS" : ""} ${quotedName}${ast.cascade ? " CASCADE" : ""}`;
|
|
2974
2741
|
}
|
|
@@ -2980,7 +2747,6 @@ const createDomain = async (migration, up, name, fn) => {
|
|
|
2980
2747
|
name
|
|
2981
2748
|
);
|
|
2982
2749
|
const ast = {
|
|
2983
|
-
type: "domain",
|
|
2984
2750
|
action: up ? "create" : "drop",
|
|
2985
2751
|
schema,
|
|
2986
2752
|
name: domainName,
|
|
@@ -3013,7 +2779,6 @@ const createCollation = async (migration, up, name, options) => {
|
|
|
3013
2779
|
name
|
|
3014
2780
|
);
|
|
3015
2781
|
const ast = {
|
|
3016
|
-
type: "collation",
|
|
3017
2782
|
action: up ? "create" : "drop",
|
|
3018
2783
|
schema,
|
|
3019
2784
|
name: collationName,
|
|
@@ -3059,7 +2824,6 @@ const renameType = async (migration, from, to, kind) => {
|
|
|
3059
2824
|
migration.up ? to : from
|
|
3060
2825
|
);
|
|
3061
2826
|
const ast = {
|
|
3062
|
-
type: "renameType",
|
|
3063
2827
|
kind,
|
|
3064
2828
|
fromSchema,
|
|
3065
2829
|
from: f,
|
|
@@ -3098,7 +2862,6 @@ const addOrDropEnumValues = async (migration, up, enumName, values, options) =>
|
|
|
3098
2862
|
);
|
|
3099
2863
|
const quotedName = quoteTable(schema, name);
|
|
3100
2864
|
const ast = {
|
|
3101
|
-
type: "enumValues",
|
|
3102
2865
|
action: up ? "add" : "drop",
|
|
3103
2866
|
schema,
|
|
3104
2867
|
name,
|
|
@@ -3111,7 +2874,7 @@ const addOrDropEnumValues = async (migration, up, enumName, values, options) =>
|
|
|
3111
2874
|
await Promise.all(
|
|
3112
2875
|
(ast.place === "after" ? [...ast.values].reverse() : ast.values).map(
|
|
3113
2876
|
(value) => migration.adapter.query(
|
|
3114
|
-
`ALTER TYPE ${quoteTable(ast.schema, ast.name)} ADD VALUE${ast.ifNotExists ? " IF NOT EXISTS" : ""} ${
|
|
2877
|
+
`ALTER TYPE ${quoteTable(ast.schema, ast.name)} ADD VALUE${ast.ifNotExists ? " IF NOT EXISTS" : ""} ${internal.singleQuote(value)}${ast.place && ast.relativeTo ? ` ${ast.place.toUpperCase()} ${internal.singleQuote(ast.relativeTo)}` : ""}`
|
|
3115
2878
|
)
|
|
3116
2879
|
)
|
|
3117
2880
|
);
|
|
@@ -3125,7 +2888,7 @@ const addOrDropEnumValues = async (migration, up, enumName, values, options) =>
|
|
|
3125
2888
|
migration,
|
|
3126
2889
|
ast,
|
|
3127
2890
|
existingValues.filter((v) => !ast.values.includes(v)),
|
|
3128
|
-
(quotedName2, table, column) => `Cannot drop ${quotedName2} enum values [${ast.values.map(
|
|
2891
|
+
(quotedName2, table, column) => `Cannot drop ${quotedName2} enum values [${ast.values.map(internal.singleQuote).join(
|
|
3129
2892
|
", "
|
|
3130
2893
|
)}]: table ${table} has a row with such value in the column "${column}"`
|
|
3131
2894
|
);
|
|
@@ -3141,17 +2904,15 @@ const changeEnumValues = async (migration, enumName, fromValues, toValues) => {
|
|
|
3141
2904
|
toValues = values;
|
|
3142
2905
|
}
|
|
3143
2906
|
const ast = {
|
|
3144
|
-
type: "changeEnumValues",
|
|
3145
2907
|
schema,
|
|
3146
2908
|
name,
|
|
3147
|
-
fromValues,
|
|
3148
2909
|
toValues
|
|
3149
2910
|
};
|
|
3150
2911
|
await recreateEnum(
|
|
3151
2912
|
migration,
|
|
3152
2913
|
ast,
|
|
3153
2914
|
ast.toValues,
|
|
3154
|
-
(quotedName, table, column) => `Cannot change ${quotedName} enum values from [${fromValues.map(
|
|
2915
|
+
(quotedName, table, column) => `Cannot change ${quotedName} enum values from [${fromValues.map(internal.singleQuote).join(", ")}] to [${toValues.map(internal.singleQuote).join(
|
|
3155
2916
|
", "
|
|
3156
2917
|
)}]: table ${table} has a row with removed value in the column "${column}"`
|
|
3157
2918
|
);
|
|
@@ -3170,10 +2931,10 @@ const recreateEnum = async (migration, { schema, name }, values, errorMessage) =
|
|
|
3170
2931
|
) AS "columns"
|
|
3171
2932
|
FROM pg_class c
|
|
3172
2933
|
JOIN pg_catalog.pg_namespace n ON n.oid = relnamespace
|
|
3173
|
-
JOIN pg_type bt ON bt.typname = ${
|
|
2934
|
+
JOIN pg_type bt ON bt.typname = ${internal.singleQuote(name)}
|
|
3174
2935
|
JOIN pg_type t ON t.oid = bt.oid OR t.typelem = bt.oid
|
|
3175
2936
|
JOIN pg_attribute a ON a.attrelid = c.oid AND a.atttypid = t.oid
|
|
3176
|
-
JOIN pg_namespace tn ON tn.oid = t.typnamespace AND tn.nspname = ${
|
|
2937
|
+
JOIN pg_namespace tn ON tn.oid = t.typnamespace AND tn.nspname = ${internal.singleQuote(
|
|
3177
2938
|
schema ?? defaultSchema
|
|
3178
2939
|
)}
|
|
3179
2940
|
WHERE c.relkind IN (${relKinds.map((c) => `'${c}'`).join(", ")})
|
|
@@ -3187,7 +2948,7 @@ GROUP BY n.nspname, c.relname`
|
|
|
3187
2948
|
);
|
|
3188
2949
|
sql.push(
|
|
3189
2950
|
`DROP TYPE ${quotedName}`,
|
|
3190
|
-
`CREATE TYPE ${quotedName} AS ENUM (${values.map(
|
|
2951
|
+
`CREATE TYPE ${quotedName} AS ENUM (${values.map(internal.singleQuote).join(", ")})`
|
|
3191
2952
|
);
|
|
3192
2953
|
await migration.adapter.query(sql.join(";\n"));
|
|
3193
2954
|
for (const t of tables) {
|
|
@@ -3217,7 +2978,7 @@ const writeMigrationFile = async (config, version, name, migrationCode) => {
|
|
|
3217
2978
|
config.migrationsPath,
|
|
3218
2979
|
`${version}_${name.replaceAll(" ", "-")}.ts`
|
|
3219
2980
|
);
|
|
3220
|
-
const importPath =
|
|
2981
|
+
const importPath = internal.getImportPath(
|
|
3221
2982
|
filePath,
|
|
3222
2983
|
path.join(config.basePath, config.dbScript)
|
|
3223
2984
|
);
|
|
@@ -3226,7 +2987,7 @@ const writeMigrationFile = async (config, version, name, migrationCode) => {
|
|
|
3226
2987
|
`import { change } from '${importPath}';
|
|
3227
2988
|
${migrationCode}`
|
|
3228
2989
|
);
|
|
3229
|
-
config.logger?.log(`Created ${
|
|
2990
|
+
config.logger?.log(`Created ${internal.pathToLog(filePath)}`);
|
|
3230
2991
|
};
|
|
3231
2992
|
const newMigration = async (config, name) => {
|
|
3232
2993
|
const version = await makeFileVersion({}, config);
|
|
@@ -3408,7 +3169,7 @@ const getMigrations = async (ctx, config, up, allowDuplicates, getVersion = getM
|
|
|
3408
3169
|
function getMigrationsFromConfig(config, allowDuplicates, getVersion = getMigrationVersionOrThrow) {
|
|
3409
3170
|
const result = [];
|
|
3410
3171
|
const versions = {};
|
|
3411
|
-
const { migrations
|
|
3172
|
+
const { migrations } = config;
|
|
3412
3173
|
for (const key in migrations) {
|
|
3413
3174
|
const version = getVersion(config, path.basename(key));
|
|
3414
3175
|
if (versions[version] && !allowDuplicates) {
|
|
@@ -3418,7 +3179,7 @@ function getMigrationsFromConfig(config, allowDuplicates, getVersion = getMigrat
|
|
|
3418
3179
|
}
|
|
3419
3180
|
versions[version] = key;
|
|
3420
3181
|
result.push({
|
|
3421
|
-
path:
|
|
3182
|
+
path: key,
|
|
3422
3183
|
version,
|
|
3423
3184
|
load: migrations[key]
|
|
3424
3185
|
});
|
|
@@ -3468,7 +3229,7 @@ async function getMigrationsFromFiles(config, allowDuplicates, getVersion = getM
|
|
|
3468
3229
|
}
|
|
3469
3230
|
data.renameTo = {
|
|
3470
3231
|
to: config.migrationId,
|
|
3471
|
-
map: () => renameMigrationsMap(
|
|
3232
|
+
map: () => renameMigrationsMap(migrationsPath, file.name)
|
|
3472
3233
|
};
|
|
3473
3234
|
return data;
|
|
3474
3235
|
} else {
|
|
@@ -3507,8 +3268,8 @@ Run \`**db command** rebase\` to reorganize files with duplicated versions.`
|
|
|
3507
3268
|
result.migrations.sort(sortMigrationsAsc);
|
|
3508
3269
|
return result;
|
|
3509
3270
|
}
|
|
3510
|
-
const renameMigrationsMap = async (
|
|
3511
|
-
const filePath = path.join(
|
|
3271
|
+
const renameMigrationsMap = async (migrationsPath, fileName) => {
|
|
3272
|
+
const filePath = path.join(migrationsPath, fileName);
|
|
3512
3273
|
const json = await fs.readFile(filePath, "utf-8");
|
|
3513
3274
|
let data;
|
|
3514
3275
|
try {
|
|
@@ -3559,11 +3320,76 @@ function getDigitsPrefix(name) {
|
|
|
3559
3320
|
return value;
|
|
3560
3321
|
}
|
|
3561
3322
|
|
|
3562
|
-
const
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3323
|
+
const getMaybeTransactionAdapter = (db) => "$getAdapter" in db ? db.$getAdapter() : db;
|
|
3324
|
+
const runSqlInSavePoint = async (db, sql, code) => {
|
|
3325
|
+
const adapter = getMaybeTransactionAdapter(db);
|
|
3326
|
+
try {
|
|
3327
|
+
await adapter.query(
|
|
3328
|
+
adapter.isInTransaction() ? `SAVEPOINT s; ${sql}; RELEASE SAVEPOINT s` : sql
|
|
3329
|
+
);
|
|
3330
|
+
return "done";
|
|
3331
|
+
} catch (err) {
|
|
3332
|
+
if (err.code === code) {
|
|
3333
|
+
if (adapter.isInTransaction()) {
|
|
3334
|
+
await adapter.query(`ROLLBACK TO SAVEPOINT s`);
|
|
3335
|
+
}
|
|
3336
|
+
return "already";
|
|
3337
|
+
}
|
|
3338
|
+
throw err;
|
|
3339
|
+
}
|
|
3340
|
+
};
|
|
3341
|
+
|
|
3342
|
+
class CreateOrDropError extends Error {
|
|
3343
|
+
constructor(message, status, cause) {
|
|
3344
|
+
super(message);
|
|
3345
|
+
this.status = status;
|
|
3346
|
+
this.cause = cause;
|
|
3347
|
+
}
|
|
3348
|
+
}
|
|
3349
|
+
const createDatabase = async (db, {
|
|
3350
|
+
database,
|
|
3351
|
+
owner
|
|
3352
|
+
}) => {
|
|
3353
|
+
return createOrDrop(
|
|
3354
|
+
db,
|
|
3355
|
+
`CREATE DATABASE "${database}"${owner ? ` OWNER "${owner}"` : ""}`
|
|
3356
|
+
);
|
|
3357
|
+
};
|
|
3358
|
+
const dropDatabase = async (db, { database }) => {
|
|
3359
|
+
return createOrDrop(db, `DROP DATABASE "${database}"`);
|
|
3360
|
+
};
|
|
3361
|
+
const createOrDrop = async (db, sql) => {
|
|
3362
|
+
try {
|
|
3363
|
+
const adapter = getMaybeTransactionAdapter(db);
|
|
3364
|
+
await adapter.query(sql);
|
|
3365
|
+
return "done";
|
|
3366
|
+
} catch (error) {
|
|
3367
|
+
const err = error;
|
|
3368
|
+
if (typeof err.message === "string" && err.message.includes("sslmode=require")) {
|
|
3369
|
+
throw new CreateOrDropError("SSL required", "ssl-required", err);
|
|
3370
|
+
}
|
|
3371
|
+
if (err.code === "42P04" || err.code === "3D000") {
|
|
3372
|
+
return "already";
|
|
3373
|
+
}
|
|
3374
|
+
if (err.code === "42501") {
|
|
3375
|
+
throw new CreateOrDropError("Insufficient privilege", "forbidden", err);
|
|
3376
|
+
}
|
|
3377
|
+
if (typeof err.message === "string" && err.message.includes("password authentication failed")) {
|
|
3378
|
+
throw new CreateOrDropError("Authentication failed", "auth-failed", err);
|
|
3379
|
+
}
|
|
3380
|
+
throw err;
|
|
3381
|
+
}
|
|
3382
|
+
};
|
|
3383
|
+
const createSchema = async (db, sql) => runSqlInSavePoint(db, `CREATE SCHEMA ${sql}`, "42P06");
|
|
3384
|
+
const dropSchema = async (db, sql) => runSqlInSavePoint(db, `DROP SCHEMA ${sql}`, "3F000");
|
|
3385
|
+
const createTable = async (db, sql) => runSqlInSavePoint(db, `CREATE TABLE ${sql}`, "42P07");
|
|
3386
|
+
const dropTable = async (db, sql) => runSqlInSavePoint(db, `DROP TABLE ${sql}`, "42P01");
|
|
3387
|
+
|
|
3388
|
+
const saveMigratedVersion = async (db, version, name, config) => {
|
|
3389
|
+
await db.silentArrays(
|
|
3390
|
+
`INSERT INTO ${migrationsSchemaTableSql(
|
|
3391
|
+
db,
|
|
3392
|
+
config
|
|
3567
3393
|
)}(version, name) VALUES ($1, $2)`,
|
|
3568
3394
|
[version, name]
|
|
3569
3395
|
);
|
|
@@ -3572,12 +3398,12 @@ const createMigrationsSchemaAndTable = async (db, config) => {
|
|
|
3572
3398
|
const adapter = getMaybeTransactionAdapter(db);
|
|
3573
3399
|
const { schema, table } = getMigrationsSchemaAndTable(adapter, config);
|
|
3574
3400
|
if (schema) {
|
|
3575
|
-
const res2 = await createSchema
|
|
3401
|
+
const res2 = await createSchema(db, schema);
|
|
3576
3402
|
if (res2 === "done") {
|
|
3577
3403
|
config.logger?.log(`Created schema "${schema}"`);
|
|
3578
3404
|
}
|
|
3579
3405
|
}
|
|
3580
|
-
const res = await createTable
|
|
3406
|
+
const res = await createTable(
|
|
3581
3407
|
db,
|
|
3582
3408
|
`${schema ? `"${schema}"."${table}"` : `"${table}"`} (version TEXT NOT NULL, name TEXT NOT NULL)`
|
|
3583
3409
|
);
|
|
@@ -3602,53 +3428,62 @@ const deleteMigratedVersion = async (adapter, version, name, config) => {
|
|
|
3602
3428
|
class NoMigrationsTableError extends Error {
|
|
3603
3429
|
}
|
|
3604
3430
|
const getMigratedVersionsMap = async (ctx, adapter, config, renameTo) => {
|
|
3431
|
+
const table = migrationsSchemaTableSql(adapter, config);
|
|
3432
|
+
const inTransaction = "isInTransaction" in adapter && adapter.isInTransaction();
|
|
3433
|
+
let result;
|
|
3605
3434
|
try {
|
|
3606
|
-
|
|
3607
|
-
|
|
3435
|
+
if (inTransaction) {
|
|
3436
|
+
await adapter.query(`SAVEPOINT check_migrations_table`);
|
|
3437
|
+
}
|
|
3438
|
+
result = await adapter.arrays(
|
|
3608
3439
|
`SELECT * FROM ${table} ORDER BY version`
|
|
3609
3440
|
);
|
|
3610
|
-
if (
|
|
3611
|
-
|
|
3612
|
-
const map = {};
|
|
3613
|
-
for (const item of migrations) {
|
|
3614
|
-
const name = path.basename(item.path);
|
|
3615
|
-
map[item.version] = name.slice(getDigitsPrefix(name).length + 1);
|
|
3616
|
-
}
|
|
3617
|
-
for (const row of result.rows) {
|
|
3618
|
-
const [version] = row;
|
|
3619
|
-
const name = map[version];
|
|
3620
|
-
if (!name) {
|
|
3621
|
-
throw new Error(
|
|
3622
|
-
`Migration for version ${version} is stored in db but is not found among available migrations`
|
|
3623
|
-
);
|
|
3624
|
-
}
|
|
3625
|
-
row[1] = name;
|
|
3626
|
-
}
|
|
3627
|
-
await adapter.arrays(`ALTER TABLE ${table} ADD COLUMN name TEXT`);
|
|
3628
|
-
await Promise.all(
|
|
3629
|
-
result.rows.map(
|
|
3630
|
-
([version, name]) => adapter.arrays(`UPDATE ${table} SET name = $2 WHERE version = $1`, [
|
|
3631
|
-
version,
|
|
3632
|
-
name
|
|
3633
|
-
])
|
|
3634
|
-
)
|
|
3635
|
-
);
|
|
3636
|
-
await adapter.arrays(
|
|
3637
|
-
`ALTER TABLE ${table} ALTER COLUMN name SET NOT NULL`
|
|
3638
|
-
);
|
|
3639
|
-
}
|
|
3640
|
-
let versions = Object.fromEntries(result.rows);
|
|
3641
|
-
if (renameTo) {
|
|
3642
|
-
versions = await renameMigrations(config, adapter, versions, renameTo);
|
|
3441
|
+
if (inTransaction) {
|
|
3442
|
+
await adapter.query(`RELEASE SAVEPOINT check_migrations_table`);
|
|
3643
3443
|
}
|
|
3644
|
-
return { map: versions, sequence: result.rows.map((row) => +row[0]) };
|
|
3645
3444
|
} catch (err) {
|
|
3646
3445
|
if (err.code === "42P01") {
|
|
3446
|
+
if (inTransaction) {
|
|
3447
|
+
await adapter.query(`ROLLBACK TO SAVEPOINT check_migrations_table`);
|
|
3448
|
+
}
|
|
3647
3449
|
throw new NoMigrationsTableError();
|
|
3648
3450
|
} else {
|
|
3649
3451
|
throw err;
|
|
3650
3452
|
}
|
|
3651
3453
|
}
|
|
3454
|
+
if (!result.fields[1]) {
|
|
3455
|
+
const { migrations } = await getMigrations(ctx, config, true);
|
|
3456
|
+
const map = {};
|
|
3457
|
+
for (const item of migrations) {
|
|
3458
|
+
const name = path.basename(item.path);
|
|
3459
|
+
map[item.version] = name.slice(getDigitsPrefix(name).length + 1);
|
|
3460
|
+
}
|
|
3461
|
+
for (const row of result.rows) {
|
|
3462
|
+
const [version] = row;
|
|
3463
|
+
const name = map[version];
|
|
3464
|
+
if (!name) {
|
|
3465
|
+
throw new Error(
|
|
3466
|
+
`Migration for version ${version} is stored in db but is not found among available migrations`
|
|
3467
|
+
);
|
|
3468
|
+
}
|
|
3469
|
+
row[1] = name;
|
|
3470
|
+
}
|
|
3471
|
+
await adapter.arrays(`ALTER TABLE ${table} ADD COLUMN name TEXT`);
|
|
3472
|
+
await Promise.all(
|
|
3473
|
+
result.rows.map(
|
|
3474
|
+
([version, name]) => adapter.arrays(`UPDATE ${table} SET name = $2 WHERE version = $1`, [
|
|
3475
|
+
version,
|
|
3476
|
+
name
|
|
3477
|
+
])
|
|
3478
|
+
)
|
|
3479
|
+
);
|
|
3480
|
+
await adapter.arrays(`ALTER TABLE ${table} ALTER COLUMN name SET NOT NULL`);
|
|
3481
|
+
}
|
|
3482
|
+
let versions = Object.fromEntries(result.rows);
|
|
3483
|
+
if (renameTo) {
|
|
3484
|
+
versions = await renameMigrations(config, adapter, versions, renameTo);
|
|
3485
|
+
}
|
|
3486
|
+
return { map: versions, sequence: result.rows.map((row) => +row[0]) };
|
|
3652
3487
|
};
|
|
3653
3488
|
async function renameMigrations(config, trx, versions, renameTo) {
|
|
3654
3489
|
let first;
|
|
@@ -3679,11 +3514,35 @@ async function renameMigrations(config, trx, versions, renameTo) {
|
|
|
3679
3514
|
return updatedVersions;
|
|
3680
3515
|
}
|
|
3681
3516
|
|
|
3517
|
+
const migrateConfigDefaults = {
|
|
3518
|
+
migrationId: { serial: 4 },
|
|
3519
|
+
migrationsTable: "schemaMigrations",
|
|
3520
|
+
transaction: "single"
|
|
3521
|
+
};
|
|
3522
|
+
const handleConfigLogger = (config) => {
|
|
3523
|
+
return config.log === true ? config.logger || console : config.log === false ? void 0 : config.logger;
|
|
3524
|
+
};
|
|
3525
|
+
const processMigrateConfig = (config) => {
|
|
3526
|
+
let migrationsPath;
|
|
3527
|
+
if (!("migrations" in config)) {
|
|
3528
|
+
migrationsPath = config.migrationsPath ? config.migrationsPath : path$1.join("src", "db", "migrations");
|
|
3529
|
+
if (config.basePath && !path$1.isAbsolute(migrationsPath)) {
|
|
3530
|
+
migrationsPath = path$1.resolve(config.basePath, migrationsPath);
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3533
|
+
return {
|
|
3534
|
+
...migrateConfigDefaults,
|
|
3535
|
+
...config,
|
|
3536
|
+
migrationsPath,
|
|
3537
|
+
logger: handleConfigLogger(config)
|
|
3538
|
+
};
|
|
3539
|
+
};
|
|
3682
3540
|
const transactionIfSingle = (adapter, config, fn) => {
|
|
3683
3541
|
return config.transaction === "single" ? transaction(adapter, config, fn) : fn(adapter);
|
|
3684
3542
|
};
|
|
3685
3543
|
function makeMigrateFn(up, defaultCount, fn) {
|
|
3686
|
-
return async (db,
|
|
3544
|
+
return async (db, publicConfig, params) => {
|
|
3545
|
+
const config = processMigrateConfig(publicConfig);
|
|
3687
3546
|
const ctx = params?.ctx || {};
|
|
3688
3547
|
const set = await getMigrations(ctx, config, up);
|
|
3689
3548
|
const count = params?.count ?? defaultCount;
|
|
@@ -3726,7 +3585,16 @@ function makeMigrateFn(up, defaultCount, fn) {
|
|
|
3726
3585
|
const migrate = makeMigrateFn(
|
|
3727
3586
|
true,
|
|
3728
3587
|
Infinity,
|
|
3729
|
-
(trx, config, set, versions, count, force) => migrateOrRollback(
|
|
3588
|
+
(trx, config, set, versions, count, force) => migrateOrRollback(
|
|
3589
|
+
trx,
|
|
3590
|
+
config,
|
|
3591
|
+
set,
|
|
3592
|
+
versions,
|
|
3593
|
+
count,
|
|
3594
|
+
true,
|
|
3595
|
+
false,
|
|
3596
|
+
force
|
|
3597
|
+
)
|
|
3730
3598
|
);
|
|
3731
3599
|
const migrateAndClose = async (db, config, params) => {
|
|
3732
3600
|
const adapter = getMaybeTransactionAdapter(db);
|
|
@@ -3734,26 +3602,46 @@ const migrateAndClose = async (db, config, params) => {
|
|
|
3734
3602
|
await adapter.close();
|
|
3735
3603
|
};
|
|
3736
3604
|
async function runMigration(db, ...args) {
|
|
3737
|
-
const [
|
|
3605
|
+
const [rawConfig, migration] = args.length === 1 ? [{}, args[0]] : [args[0], args[1]];
|
|
3606
|
+
const config = {
|
|
3607
|
+
...rawConfig,
|
|
3608
|
+
logger: handleConfigLogger(rawConfig)
|
|
3609
|
+
};
|
|
3738
3610
|
const adapter = getMaybeTransactionAdapter(db);
|
|
3739
3611
|
await transaction(adapter, config, async (trx) => {
|
|
3740
3612
|
clearChanges();
|
|
3741
3613
|
const changes = await getChanges({ load: migration });
|
|
3742
|
-
|
|
3743
|
-
await applyMigration(trx, true, changes, config2);
|
|
3614
|
+
await applyMigration(trx, true, changes, config);
|
|
3744
3615
|
});
|
|
3745
3616
|
}
|
|
3746
3617
|
const rollback = makeMigrateFn(
|
|
3747
3618
|
false,
|
|
3748
3619
|
1,
|
|
3749
|
-
(trx, config, set, versions, count, force) => migrateOrRollback(
|
|
3620
|
+
(trx, config, set, versions, count, force) => migrateOrRollback(
|
|
3621
|
+
trx,
|
|
3622
|
+
config,
|
|
3623
|
+
set,
|
|
3624
|
+
versions,
|
|
3625
|
+
count,
|
|
3626
|
+
false,
|
|
3627
|
+
false,
|
|
3628
|
+
force
|
|
3629
|
+
)
|
|
3750
3630
|
);
|
|
3751
3631
|
const redo = makeMigrateFn(
|
|
3752
3632
|
true,
|
|
3753
3633
|
1,
|
|
3754
3634
|
async (trx, config, set, versions, count, force) => {
|
|
3755
3635
|
set.migrations.reverse();
|
|
3756
|
-
await migrateOrRollback(
|
|
3636
|
+
await migrateOrRollback(
|
|
3637
|
+
trx,
|
|
3638
|
+
config,
|
|
3639
|
+
set,
|
|
3640
|
+
versions,
|
|
3641
|
+
count,
|
|
3642
|
+
false,
|
|
3643
|
+
true
|
|
3644
|
+
);
|
|
3757
3645
|
set.migrations.reverse();
|
|
3758
3646
|
return migrateOrRollback(
|
|
3759
3647
|
trx,
|
|
@@ -3824,7 +3712,7 @@ const migrateOrRollback = async (trx, config, set, versions, count, up, redo2, f
|
|
|
3824
3712
|
await changeMigratedVersion(adapter, up, file, config);
|
|
3825
3713
|
(migrations ?? (migrations = [])).push(file);
|
|
3826
3714
|
if (up) {
|
|
3827
|
-
const name = path.basename(file.path);
|
|
3715
|
+
const name = path$1.basename(file.path);
|
|
3828
3716
|
versionsMap[file.version] = name;
|
|
3829
3717
|
sequence.push(+file.version);
|
|
3830
3718
|
} else {
|
|
@@ -3832,11 +3720,11 @@ const migrateOrRollback = async (trx, config, set, versions, count, up, redo2, f
|
|
|
3832
3720
|
sequence.pop();
|
|
3833
3721
|
}
|
|
3834
3722
|
config.logger?.log(
|
|
3835
|
-
`${up ? "Migrated" : "Rolled back"} ${
|
|
3723
|
+
`${up ? "Migrated" : "Rolled back"} ${internal.pathToLog(file.path)}
|
|
3836
3724
|
`
|
|
3837
3725
|
);
|
|
3838
3726
|
}
|
|
3839
|
-
migrations ?? (migrations =
|
|
3727
|
+
migrations ?? (migrations = internal.emptyArray);
|
|
3840
3728
|
const afterMigrate = config[up ? "afterMigrate" : "afterRollback"];
|
|
3841
3729
|
if (config.afterChange || afterMigrate) {
|
|
3842
3730
|
db ?? (db = getDb(trx));
|
|
@@ -3871,7 +3759,7 @@ const checkMigrationOrder = (config, set, { sequence, map }, force) => {
|
|
|
3871
3759
|
if (version > last || map[file.version]) continue;
|
|
3872
3760
|
if (!force) {
|
|
3873
3761
|
throw new Error(
|
|
3874
|
-
`Cannot migrate ${path.basename(
|
|
3762
|
+
`Cannot migrate ${path$1.basename(
|
|
3875
3763
|
file.path
|
|
3876
3764
|
)} because the higher position ${map[versionToString(config, last)]} was already migrated.
|
|
3877
3765
|
Run \`**db command** up force\` to rollback the above migrations and migrate all`
|
|
@@ -3888,7 +3776,7 @@ const getChanges = async (file, config) => {
|
|
|
3888
3776
|
let changes = file.path ? changeCache[file.path] : void 0;
|
|
3889
3777
|
if (!changes) {
|
|
3890
3778
|
const module = await file.load();
|
|
3891
|
-
const exported = module?.default &&
|
|
3779
|
+
const exported = module?.default && internal.toArray(module.default);
|
|
3892
3780
|
if (config?.forceDefaultExports && !exported) {
|
|
3893
3781
|
throw new RakeDbError(
|
|
3894
3782
|
`Missing a default export in ${file.path} migration`
|
|
@@ -3907,151 +3795,342 @@ const runMigrationInOwnTransaction = (adapter, up, changes, config) => {
|
|
|
3907
3795
|
);
|
|
3908
3796
|
};
|
|
3909
3797
|
const applyMigration = async (trx, up, changes, config) => {
|
|
3910
|
-
const
|
|
3798
|
+
const { adapter, getDb: getDb2 } = createMigrationInterface(trx, up, config);
|
|
3911
3799
|
if (changes.length) {
|
|
3912
3800
|
const from = up ? 0 : changes.length - 1;
|
|
3913
3801
|
const to = up ? changes.length : -1;
|
|
3914
3802
|
const step = up ? 1 : -1;
|
|
3915
3803
|
for (let i = from; i !== to; i += step) {
|
|
3916
|
-
|
|
3804
|
+
const change = changes[i];
|
|
3805
|
+
const db = getDb2(change.config.columnTypes);
|
|
3806
|
+
await change.fn(db, up);
|
|
3917
3807
|
}
|
|
3918
3808
|
}
|
|
3919
|
-
return
|
|
3809
|
+
return adapter;
|
|
3920
3810
|
};
|
|
3921
3811
|
const changeMigratedVersion = async (adapter, up, file, config) => {
|
|
3922
3812
|
await (up ? saveMigratedVersion : deleteMigratedVersion)(
|
|
3923
3813
|
adapter,
|
|
3924
3814
|
file.version,
|
|
3925
|
-
path.basename(file.path).slice(file.version.length + 1),
|
|
3815
|
+
path$1.basename(file.path).slice(file.version.length + 1),
|
|
3926
3816
|
config
|
|
3927
3817
|
);
|
|
3928
3818
|
};
|
|
3929
3819
|
|
|
3930
|
-
const
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
})
|
|
3941
|
-
);
|
|
3942
|
-
});
|
|
3943
|
-
if (files > 0) {
|
|
3944
|
-
config.logger?.log(
|
|
3945
|
-
`Applied ${files} recurrent migration file${files > 1 ? "s" : ""}`
|
|
3820
|
+
const rakeDbConfigDefaults = {
|
|
3821
|
+
...migrateConfigDefaults,
|
|
3822
|
+
schemaConfig: internal.defaultSchemaConfig,
|
|
3823
|
+
snakeCase: false,
|
|
3824
|
+
commands: {},
|
|
3825
|
+
log: true,
|
|
3826
|
+
logger: console,
|
|
3827
|
+
import() {
|
|
3828
|
+
throw new Error(
|
|
3829
|
+
"Add `import: (path) => import(path),` setting to `rakeDb` config"
|
|
3946
3830
|
);
|
|
3947
3831
|
}
|
|
3948
3832
|
};
|
|
3949
|
-
const readdirRecursive = async (dirPath, cb) => {
|
|
3950
|
-
const list = await fs.readdir(dirPath).catch((err) => {
|
|
3951
|
-
if (err.code !== "ENOENT") throw err;
|
|
3952
|
-
return;
|
|
3953
|
-
});
|
|
3954
|
-
if (!list) return;
|
|
3955
|
-
await Promise.all(
|
|
3956
|
-
list.map(async (item) => {
|
|
3957
|
-
const path$1 = path.join(dirPath, item);
|
|
3958
|
-
const info = await fs.stat(path$1);
|
|
3959
|
-
if (info.isDirectory()) {
|
|
3960
|
-
await readdirRecursive(path$1, cb);
|
|
3961
|
-
} else if (info.isFile() && path$1.endsWith(".sql")) {
|
|
3962
|
-
await cb(path$1);
|
|
3963
|
-
}
|
|
3964
|
-
})
|
|
3965
|
-
);
|
|
3966
|
-
};
|
|
3967
3833
|
|
|
3968
|
-
const
|
|
3969
|
-
const
|
|
3970
|
-
const
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
}
|
|
3988
|
-
);
|
|
3989
|
-
if (!res) continue;
|
|
3990
|
-
if (action === "create") {
|
|
3991
|
-
await adapter.transaction(async (tx) => {
|
|
3992
|
-
const schema = tx.getSchema();
|
|
3993
|
-
if (schema) {
|
|
3994
|
-
const quoted = `"${typeof schema === "function" ? schema() : schema}"`;
|
|
3995
|
-
const res2 = await createSchema$1(tx, quoted);
|
|
3996
|
-
if (res2 === "done") {
|
|
3997
|
-
config.logger?.log(`Created schema ${quoted}`);
|
|
3998
|
-
}
|
|
3999
|
-
}
|
|
4000
|
-
await createMigrationsSchemaAndTable(tx, config);
|
|
4001
|
-
});
|
|
4002
|
-
if (!dontClose) {
|
|
4003
|
-
await adapter.close();
|
|
4004
|
-
}
|
|
4005
|
-
}
|
|
4006
|
-
}
|
|
4007
|
-
};
|
|
4008
|
-
const resetDatabaseCommand = async (adapters, config) => {
|
|
4009
|
-
await createOrDropDatabase("drop", adapters, config);
|
|
4010
|
-
await createOrDropDatabase("create", adapters, config, true);
|
|
4011
|
-
for (const adapter of adapters) {
|
|
4012
|
-
await migrate(adapter, config);
|
|
4013
|
-
}
|
|
4014
|
-
if (config.recurrentPath) {
|
|
4015
|
-
await runRecurrentMigrations(adapters, config);
|
|
4016
|
-
}
|
|
4017
|
-
await Promise.all(adapters.map((adapter) => adapter.close()));
|
|
4018
|
-
};
|
|
4019
|
-
const run = async (adapter, config, params) => {
|
|
4020
|
-
try {
|
|
4021
|
-
const res = await params.command(adapter);
|
|
4022
|
-
config.logger?.log(
|
|
4023
|
-
res === "done" ? params.doneMessage() : params.alreadyMessage()
|
|
4024
|
-
);
|
|
4025
|
-
await adapter.close();
|
|
4026
|
-
return true;
|
|
4027
|
-
} catch (err) {
|
|
4028
|
-
if (err instanceof CreateOrDropError) {
|
|
4029
|
-
if (err.status === "ssl-required") {
|
|
4030
|
-
config.logger?.log(
|
|
4031
|
-
"SSL is required: append ?ssl=true to the database url string"
|
|
4032
|
-
);
|
|
4033
|
-
return false;
|
|
4034
|
-
}
|
|
4035
|
-
if (err.status === "forbidden" || err.status === "auth-failed") {
|
|
4036
|
-
let message = params.deniedMessage();
|
|
4037
|
-
const host = adapter.getHost();
|
|
4038
|
-
const isLocal = host === "localhost";
|
|
4039
|
-
if (!isLocal) {
|
|
4040
|
-
message += `
|
|
4041
|
-
Don't use this command for database service providers, only for a local db.`;
|
|
4042
|
-
}
|
|
4043
|
-
config.logger?.log(message);
|
|
4044
|
-
const creds = await params.askAdminCreds();
|
|
4045
|
-
if (!creds) return false;
|
|
4046
|
-
return run(adapter.reconfigure(creds), config, params);
|
|
4047
|
-
}
|
|
3834
|
+
const ESC = "\x1B";
|
|
3835
|
+
const CSI = `${ESC}[`;
|
|
3836
|
+
const cursorShow = `${CSI}?25h`;
|
|
3837
|
+
const cursorHide = `${CSI}?25l`;
|
|
3838
|
+
const { stdin, stdout } = process;
|
|
3839
|
+
const visibleChars = (s) => s.replace(
|
|
3840
|
+
// eslint-disable-next-line no-control-regex
|
|
3841
|
+
/[\u001B\u009B][[\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\d/#&.:=?%@~_]+)*|[a-zA-Z\d]+(?:;[-a-zA-Z\d/#&.:=?%@~_]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PRZcf-ntqry=><~]))/g,
|
|
3842
|
+
""
|
|
3843
|
+
).length;
|
|
3844
|
+
const clear = (text) => {
|
|
3845
|
+
const rows = text.split(/\r?\n/).reduce(
|
|
3846
|
+
(rows2, line) => rows2 + 1 + Math.floor(Math.max(visibleChars(line) - 1, 0) / stdout.columns),
|
|
3847
|
+
0
|
|
3848
|
+
);
|
|
3849
|
+
let clear2 = "";
|
|
3850
|
+
for (let i = 0; i < rows; i++) {
|
|
3851
|
+
clear2 += `${CSI}2K`;
|
|
3852
|
+
if (i < rows - 1) {
|
|
3853
|
+
clear2 += `${CSI}${i < rows - 1 ? "1A" : "G"}`;
|
|
4048
3854
|
}
|
|
4049
|
-
throw err;
|
|
4050
3855
|
}
|
|
3856
|
+
return clear2;
|
|
4051
3857
|
};
|
|
4052
|
-
const
|
|
4053
|
-
|
|
4054
|
-
|
|
3858
|
+
const prompt = async ({
|
|
3859
|
+
render,
|
|
3860
|
+
onKeyPress,
|
|
3861
|
+
validate,
|
|
3862
|
+
value,
|
|
3863
|
+
cursor: showCursor
|
|
3864
|
+
}) => {
|
|
3865
|
+
stdin.resume();
|
|
3866
|
+
if (stdin.isTTY) stdin.setRawMode(true);
|
|
3867
|
+
stdin.setEncoding("utf-8");
|
|
3868
|
+
if (!showCursor) stdout.write(cursorHide);
|
|
3869
|
+
return new Promise((res) => {
|
|
3870
|
+
let prevText;
|
|
3871
|
+
const ctx = {
|
|
3872
|
+
value,
|
|
3873
|
+
submitted: false,
|
|
3874
|
+
render() {
|
|
3875
|
+
let text = (ctx.submitted ? internal.colors.greenBold("\u2714") : internal.colors.yellowBold("?")) + " " + render(ctx);
|
|
3876
|
+
if (ctx.submitted) text += "\n";
|
|
3877
|
+
stdout.write(prevText ? clear(prevText) + "\r" + text : text);
|
|
3878
|
+
prevText = text;
|
|
3879
|
+
},
|
|
3880
|
+
submit(value2) {
|
|
3881
|
+
if (value2 !== void 0) ctx.value = value2;
|
|
3882
|
+
if (ctx.value === void 0 || validate && !validate?.(ctx)) return;
|
|
3883
|
+
ctx.submitted = true;
|
|
3884
|
+
ctx.render();
|
|
3885
|
+
close();
|
|
3886
|
+
res(ctx.value);
|
|
3887
|
+
}
|
|
3888
|
+
};
|
|
3889
|
+
const close = () => {
|
|
3890
|
+
if (!showCursor) stdout.write(cursorShow);
|
|
3891
|
+
if (stdin.isTTY) stdin.setRawMode(false);
|
|
3892
|
+
stdin.off("data", keypress);
|
|
3893
|
+
stdin.pause();
|
|
3894
|
+
};
|
|
3895
|
+
const keypress = (s) => {
|
|
3896
|
+
if (s === "" || s === "") {
|
|
3897
|
+
close?.();
|
|
3898
|
+
process.exit(0);
|
|
3899
|
+
}
|
|
3900
|
+
if (s === "\r" || s === "\n" || s === "\r\n") {
|
|
3901
|
+
ctx.submit();
|
|
3902
|
+
} else {
|
|
3903
|
+
onKeyPress(ctx, s);
|
|
3904
|
+
}
|
|
3905
|
+
};
|
|
3906
|
+
stdin.on("data", keypress);
|
|
3907
|
+
ctx.render();
|
|
3908
|
+
});
|
|
3909
|
+
};
|
|
3910
|
+
const defaultActive = (s) => `${internal.colors.blueBold("\u276F")} ${s}`;
|
|
3911
|
+
const defaultInactive = (s) => ` ${s}`;
|
|
3912
|
+
const promptSelect = ({
|
|
3913
|
+
message,
|
|
3914
|
+
options,
|
|
3915
|
+
active = defaultActive,
|
|
3916
|
+
inactive = defaultInactive
|
|
3917
|
+
}) => prompt({
|
|
3918
|
+
value: 0,
|
|
3919
|
+
render(ctx) {
|
|
3920
|
+
let text = `${message} ${internal.colors.pale(
|
|
3921
|
+
"Use arrows or jk. Press enter to submit."
|
|
3922
|
+
)}
|
|
3923
|
+
`;
|
|
3924
|
+
for (let i = 0; i < options.length; i++) {
|
|
3925
|
+
text += (ctx.value === i ? active : inactive)(options[i]) + "\n";
|
|
3926
|
+
}
|
|
3927
|
+
return text;
|
|
3928
|
+
},
|
|
3929
|
+
onKeyPress(ctx, s) {
|
|
3930
|
+
ctx.value = s === "\x1B[H" ? 0 : s === "\x1B[F" ? options.length - 1 : s === "\x1B[A" || s === "k" ? ctx.value === 0 ? options.length - 1 : ctx.value - 1 : s === "\x1B[B" || s === "j" || s === " " ? ctx.value === options.length - 1 ? 0 : ctx.value + 1 : ctx.value;
|
|
3931
|
+
ctx.render();
|
|
3932
|
+
}
|
|
3933
|
+
});
|
|
3934
|
+
const promptConfirm = ({
|
|
3935
|
+
message
|
|
3936
|
+
}) => prompt({
|
|
3937
|
+
value: true,
|
|
3938
|
+
render(ctx) {
|
|
3939
|
+
return `${internal.colors.bright(message)}
|
|
3940
|
+
${ctx.submitted ? `> ${ctx.value ? internal.colors.greenBold("Yes") : internal.colors.yellowBold("No")}` : internal.colors.pale(`> (Y/n)`)}
|
|
3941
|
+
`;
|
|
3942
|
+
},
|
|
3943
|
+
onKeyPress(ctx, s) {
|
|
3944
|
+
let ok;
|
|
3945
|
+
if (s === "y" || s === "Y") ok = true;
|
|
3946
|
+
else if (s === "n" || s === "N") ok = false;
|
|
3947
|
+
if (ok !== void 0) {
|
|
3948
|
+
ctx.submit(ok);
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
});
|
|
3952
|
+
const promptText = ({
|
|
3953
|
+
message,
|
|
3954
|
+
default: def = "",
|
|
3955
|
+
password,
|
|
3956
|
+
min
|
|
3957
|
+
}) => {
|
|
3958
|
+
let showDefault = true;
|
|
3959
|
+
let x = 0;
|
|
3960
|
+
const renderValue = (ctx) => password ? "*".repeat(ctx.value.length) : ctx.value;
|
|
3961
|
+
return prompt({
|
|
3962
|
+
value: def,
|
|
3963
|
+
cursor: true,
|
|
3964
|
+
validate: (ctx) => !min || ctx.value.length >= min,
|
|
3965
|
+
render(ctx) {
|
|
3966
|
+
let text = `${internal.colors.bright(message)}
|
|
3967
|
+
> ${ctx.submitted ? renderValue(ctx) : showDefault ? internal.colors.pale(def) + "\b".repeat(def.length) : ctx.value}`;
|
|
3968
|
+
if (ctx.submitted) text += "\n";
|
|
3969
|
+
return text;
|
|
3970
|
+
},
|
|
3971
|
+
onKeyPress(ctx, s) {
|
|
3972
|
+
let value = showDefault ? "" : ctx.value;
|
|
3973
|
+
if (s === "\x1B[D" && x > 0) {
|
|
3974
|
+
x--;
|
|
3975
|
+
stdout.write("\b");
|
|
3976
|
+
} else if (s === "\x1B[C" && x < value.length) {
|
|
3977
|
+
stdout.write(value[x]);
|
|
3978
|
+
x++;
|
|
3979
|
+
}
|
|
3980
|
+
if (s !== "\x7F" && s !== "\x1B[3~" && !visibleChars(s)) return;
|
|
3981
|
+
if (showDefault) {
|
|
3982
|
+
showDefault = false;
|
|
3983
|
+
stdout.write(" ".repeat(def.length) + "\b".repeat(def.length));
|
|
3984
|
+
}
|
|
3985
|
+
const prev = value;
|
|
3986
|
+
const prevX = x;
|
|
3987
|
+
if (s === "\x7F") {
|
|
3988
|
+
if (x > 0) {
|
|
3989
|
+
value = value.slice(0, x - 1) + value.slice(x);
|
|
3990
|
+
x--;
|
|
3991
|
+
}
|
|
3992
|
+
} else if (s === "\x1B[3~") {
|
|
3993
|
+
if (x < value.length) {
|
|
3994
|
+
value = value.slice(0, x) + value.slice(x + 1);
|
|
3995
|
+
}
|
|
3996
|
+
} else {
|
|
3997
|
+
value = value.slice(0, x) + s + value.slice(x);
|
|
3998
|
+
x++;
|
|
3999
|
+
}
|
|
4000
|
+
ctx.value = value;
|
|
4001
|
+
const spaces = prev.length - value.length;
|
|
4002
|
+
stdout.write(
|
|
4003
|
+
"\b".repeat(prevX) + renderValue(ctx) + (spaces > 0 ? " ".repeat(spaces) + "\b".repeat(spaces) : "") + "\b".repeat(value.length - x)
|
|
4004
|
+
);
|
|
4005
|
+
}
|
|
4006
|
+
});
|
|
4007
|
+
};
|
|
4008
|
+
|
|
4009
|
+
const runRecurrentMigrations = async (adapters, config) => {
|
|
4010
|
+
let dbs;
|
|
4011
|
+
let files = 0;
|
|
4012
|
+
await readdirRecursive(config.recurrentPath, async (path) => {
|
|
4013
|
+
files++;
|
|
4014
|
+
dbs ?? (dbs = adapters.map((adapter) => pqb.createDbWithAdapter({ adapter })));
|
|
4015
|
+
const sql = await fs.readFile(path, "utf-8");
|
|
4016
|
+
await Promise.all(
|
|
4017
|
+
dbs.map(async (db) => {
|
|
4018
|
+
await db.adapter.arrays(sql);
|
|
4019
|
+
})
|
|
4020
|
+
);
|
|
4021
|
+
});
|
|
4022
|
+
if (files > 0) {
|
|
4023
|
+
config.logger?.log(
|
|
4024
|
+
`Applied ${files} recurrent migration file${files > 1 ? "s" : ""}`
|
|
4025
|
+
);
|
|
4026
|
+
}
|
|
4027
|
+
};
|
|
4028
|
+
const readdirRecursive = async (dirPath, cb) => {
|
|
4029
|
+
const list = await fs.readdir(dirPath).catch((err) => {
|
|
4030
|
+
if (err.code !== "ENOENT") throw err;
|
|
4031
|
+
return;
|
|
4032
|
+
});
|
|
4033
|
+
if (!list) return;
|
|
4034
|
+
await Promise.all(
|
|
4035
|
+
list.map(async (item) => {
|
|
4036
|
+
const path$1 = path.join(dirPath, item);
|
|
4037
|
+
const info = await fs.stat(path$1);
|
|
4038
|
+
if (info.isDirectory()) {
|
|
4039
|
+
await readdirRecursive(path$1, cb);
|
|
4040
|
+
} else if (info.isFile() && path$1.endsWith(".sql")) {
|
|
4041
|
+
await cb(path$1);
|
|
4042
|
+
}
|
|
4043
|
+
})
|
|
4044
|
+
);
|
|
4045
|
+
};
|
|
4046
|
+
|
|
4047
|
+
const createDatabaseCommand = (adapters, config, dontClose) => createOrDropDatabase("create", adapters, config, dontClose);
|
|
4048
|
+
const dropDatabaseCommand = (adapters, config) => createOrDropDatabase("drop", adapters, config);
|
|
4049
|
+
const createOrDropDatabase = async (action, adapters, config, dontClose) => {
|
|
4050
|
+
const fn = action === "create" ? createDatabase : dropDatabase;
|
|
4051
|
+
for (const adapter of adapters) {
|
|
4052
|
+
const database = adapter.getDatabase();
|
|
4053
|
+
const owner = adapter.getUser();
|
|
4054
|
+
const res = await run(
|
|
4055
|
+
adapter.reconfigure({ database: "postgres" }),
|
|
4056
|
+
config,
|
|
4057
|
+
{
|
|
4058
|
+
command: (adapter2) => fn(adapter2, {
|
|
4059
|
+
database,
|
|
4060
|
+
owner
|
|
4061
|
+
}),
|
|
4062
|
+
doneMessage: () => `Database ${database} successfully ${action === "create" ? "created" : "dropped"}`,
|
|
4063
|
+
alreadyMessage: () => `Database ${database} ${action === "create" ? "already exists" : "does not exist"}`,
|
|
4064
|
+
deniedMessage: () => `Permission denied to ${action} database.`,
|
|
4065
|
+
askAdminCreds: () => askForAdminCredentials(action === "create")
|
|
4066
|
+
}
|
|
4067
|
+
);
|
|
4068
|
+
if (!res) continue;
|
|
4069
|
+
if (action === "create") {
|
|
4070
|
+
await adapter.transaction(async (tx) => {
|
|
4071
|
+
const schema = tx.getSchema();
|
|
4072
|
+
if (schema) {
|
|
4073
|
+
const quoted = `"${typeof schema === "function" ? schema() : schema}"`;
|
|
4074
|
+
const res2 = await createSchema(tx, quoted);
|
|
4075
|
+
if (res2 === "done") {
|
|
4076
|
+
config.logger?.log(`Created schema ${quoted}`);
|
|
4077
|
+
}
|
|
4078
|
+
}
|
|
4079
|
+
await createMigrationsSchemaAndTable(tx, config);
|
|
4080
|
+
});
|
|
4081
|
+
if (!dontClose) {
|
|
4082
|
+
await adapter.close();
|
|
4083
|
+
}
|
|
4084
|
+
}
|
|
4085
|
+
}
|
|
4086
|
+
};
|
|
4087
|
+
const resetDatabaseCommand = async (adapters, config) => {
|
|
4088
|
+
await createOrDropDatabase("drop", adapters, config);
|
|
4089
|
+
await createOrDropDatabase("create", adapters, config, true);
|
|
4090
|
+
for (const adapter of adapters) {
|
|
4091
|
+
await migrate(adapter, config);
|
|
4092
|
+
}
|
|
4093
|
+
if (config.recurrentPath) {
|
|
4094
|
+
await runRecurrentMigrations(adapters, config);
|
|
4095
|
+
}
|
|
4096
|
+
await Promise.all(adapters.map((adapter) => adapter.close()));
|
|
4097
|
+
};
|
|
4098
|
+
const run = async (adapter, config, params) => {
|
|
4099
|
+
try {
|
|
4100
|
+
const res = await params.command(adapter);
|
|
4101
|
+
config.logger?.log(
|
|
4102
|
+
res === "done" ? params.doneMessage() : params.alreadyMessage()
|
|
4103
|
+
);
|
|
4104
|
+
await adapter.close();
|
|
4105
|
+
return true;
|
|
4106
|
+
} catch (err) {
|
|
4107
|
+
if (err instanceof CreateOrDropError) {
|
|
4108
|
+
if (err.status === "ssl-required") {
|
|
4109
|
+
config.logger?.log(
|
|
4110
|
+
"SSL is required: append ?ssl=true to the database url string"
|
|
4111
|
+
);
|
|
4112
|
+
return false;
|
|
4113
|
+
}
|
|
4114
|
+
if (err.status === "forbidden" || err.status === "auth-failed") {
|
|
4115
|
+
let message = params.deniedMessage();
|
|
4116
|
+
const host = adapter.getHost();
|
|
4117
|
+
const isLocal = host === "localhost";
|
|
4118
|
+
if (!isLocal) {
|
|
4119
|
+
message += `
|
|
4120
|
+
Don't use this command for database service providers, only for a local db.`;
|
|
4121
|
+
}
|
|
4122
|
+
config.logger?.log(message);
|
|
4123
|
+
const creds = await params.askAdminCreds();
|
|
4124
|
+
if (!creds) return false;
|
|
4125
|
+
return run(adapter.reconfigure(creds), config, params);
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
throw err;
|
|
4129
|
+
}
|
|
4130
|
+
};
|
|
4131
|
+
const askForAdminCredentials = async (create) => {
|
|
4132
|
+
const ok = await promptConfirm({
|
|
4133
|
+
message: `Would you like to share admin credentials to ${create ? "create" : "drop"} a database?`
|
|
4055
4134
|
});
|
|
4056
4135
|
if (!ok) {
|
|
4057
4136
|
return;
|
|
@@ -4152,7 +4231,7 @@ const astToGenerateItem = (config, ast, currentSchema) => {
|
|
|
4152
4231
|
deps.push(table);
|
|
4153
4232
|
const columns = [];
|
|
4154
4233
|
for (const name in ast.shape) {
|
|
4155
|
-
const arr =
|
|
4234
|
+
const arr = internal.toArray(ast.shape[name]);
|
|
4156
4235
|
for (const item of arr) {
|
|
4157
4236
|
if (item.type === "add") {
|
|
4158
4237
|
columns.push([add, name, { column: item.item }]);
|
|
@@ -4268,7 +4347,7 @@ const astToGenerateItem = (config, ast, currentSchema) => {
|
|
|
4268
4347
|
break;
|
|
4269
4348
|
}
|
|
4270
4349
|
default:
|
|
4271
|
-
|
|
4350
|
+
internal.exhaustive(ast);
|
|
4272
4351
|
}
|
|
4273
4352
|
return {
|
|
4274
4353
|
ast,
|
|
@@ -4478,7 +4557,7 @@ const astToMigration = (currentSchema, config, asts) => {
|
|
|
4478
4557
|
code += `
|
|
4479
4558
|
change(async (db) => {
|
|
4480
4559
|
${group.map(
|
|
4481
|
-
(ast) =>
|
|
4560
|
+
(ast) => internal.codeToString(
|
|
4482
4561
|
astEncoders[ast.type](ast, config, currentSchema),
|
|
4483
4562
|
" ",
|
|
4484
4563
|
" "
|
|
@@ -4499,7 +4578,7 @@ const astEncoders = {
|
|
|
4499
4578
|
);
|
|
4500
4579
|
const isShifted = hasOptions || hasTableData;
|
|
4501
4580
|
if (isShifted) {
|
|
4502
|
-
|
|
4581
|
+
internal.addCode(code, `await db.${ast.action}Table(`);
|
|
4503
4582
|
const inner = [`${quoteSchemaTable(ast, currentSchema)},`];
|
|
4504
4583
|
code.push(inner);
|
|
4505
4584
|
code = inner;
|
|
@@ -4512,7 +4591,7 @@ const astEncoders = {
|
|
|
4512
4591
|
}
|
|
4513
4592
|
code.push("(t) => ({");
|
|
4514
4593
|
} else {
|
|
4515
|
-
|
|
4594
|
+
internal.addCode(
|
|
4516
4595
|
code,
|
|
4517
4596
|
`await db.${ast.action}Table(${quoteSchemaTable(
|
|
4518
4597
|
ast,
|
|
@@ -4534,23 +4613,23 @@ const astEncoders = {
|
|
|
4534
4613
|
for (const key in ast.shape) {
|
|
4535
4614
|
if (timestamps.hasAnyTimestamps && (key === "createdAt" || key === "updatedAt"))
|
|
4536
4615
|
continue;
|
|
4537
|
-
const line = [`${
|
|
4616
|
+
const line = [`${internal.quoteObjectKey(key, config.snakeCase)}: `];
|
|
4538
4617
|
const columnCode = ast.shape[key].toCode(toCodeCtx, key);
|
|
4539
4618
|
for (const part of columnCode) {
|
|
4540
|
-
|
|
4619
|
+
internal.addCode(line, part);
|
|
4541
4620
|
}
|
|
4542
|
-
|
|
4621
|
+
internal.addCode(line, ",");
|
|
4543
4622
|
code.push(line);
|
|
4544
4623
|
}
|
|
4545
4624
|
if (timestamps.hasAnyTimestamps) {
|
|
4546
4625
|
code.push([`...${timestampsToCode(timestamps)},`]);
|
|
4547
4626
|
}
|
|
4548
4627
|
if (isShifted) {
|
|
4549
|
-
|
|
4550
|
-
if (hasTableData)
|
|
4551
|
-
|
|
4628
|
+
internal.addCode(code, "}),");
|
|
4629
|
+
if (hasTableData) internal.pushTableDataCode(code, ast);
|
|
4630
|
+
internal.addCode(result, ");");
|
|
4552
4631
|
} else {
|
|
4553
|
-
|
|
4632
|
+
internal.addCode(result, "}));");
|
|
4554
4633
|
}
|
|
4555
4634
|
return result;
|
|
4556
4635
|
},
|
|
@@ -4563,7 +4642,7 @@ const astEncoders = {
|
|
|
4563
4642
|
});
|
|
4564
4643
|
const { comment } = ast;
|
|
4565
4644
|
if (comment !== void 0) {
|
|
4566
|
-
|
|
4645
|
+
internal.addCode(code, `await db.changeTable(`);
|
|
4567
4646
|
const inner = [
|
|
4568
4647
|
`${schemaTable},`,
|
|
4569
4648
|
`{ comment: ${JSON.stringify(ast.comment)} },`,
|
|
@@ -4572,7 +4651,7 @@ const astEncoders = {
|
|
|
4572
4651
|
code.push(inner);
|
|
4573
4652
|
code = inner;
|
|
4574
4653
|
} else {
|
|
4575
|
-
|
|
4654
|
+
internal.addCode(code, `await db.changeTable(${schemaTable}, (t) => ({`);
|
|
4576
4655
|
}
|
|
4577
4656
|
const [addTimestamps, dropTimestamps] = ["add", "drop"].map(
|
|
4578
4657
|
(type) => getHasTimestamps(
|
|
@@ -4588,29 +4667,29 @@ const astEncoders = {
|
|
|
4588
4667
|
snakeCase: config.snakeCase
|
|
4589
4668
|
};
|
|
4590
4669
|
for (const key in ast.shape) {
|
|
4591
|
-
const changes =
|
|
4670
|
+
const changes = internal.toArray(ast.shape[key]);
|
|
4592
4671
|
for (const change of changes) {
|
|
4593
4672
|
if (change.type === "add" || change.type === "drop") {
|
|
4594
4673
|
if ((addTimestamps.hasAnyTimestamps || dropTimestamps.hasAnyTimestamps) && (key === "createdAt" || key === "updatedAt"))
|
|
4595
4674
|
continue;
|
|
4596
4675
|
const recreate = changes.length > 1;
|
|
4597
4676
|
const line = [
|
|
4598
|
-
recreate ? `...t.${change.type}(t.name(${
|
|
4677
|
+
recreate ? `...t.${change.type}(t.name(${internal.singleQuote(
|
|
4599
4678
|
change.item.data.name ?? key
|
|
4600
|
-
)})` : `${
|
|
4679
|
+
)})` : `${internal.quoteObjectKey(key, config.snakeCase)}: t.${change.type}(`
|
|
4601
4680
|
];
|
|
4602
4681
|
const columnCode = change.item.toCode(toCodeCtx, key);
|
|
4603
4682
|
for (let i = 0; i < columnCode.length; i++) {
|
|
4604
4683
|
let part = columnCode[i];
|
|
4605
4684
|
if (recreate && !i) part = part.slice(1);
|
|
4606
|
-
|
|
4685
|
+
internal.addCode(line, part);
|
|
4607
4686
|
}
|
|
4608
|
-
|
|
4687
|
+
internal.addCode(line, "),");
|
|
4609
4688
|
code.push(line);
|
|
4610
4689
|
} else if (change.type === "change") {
|
|
4611
4690
|
if (!change.from.column || !change.to.column) continue;
|
|
4612
4691
|
const line = [
|
|
4613
|
-
`${
|
|
4692
|
+
`${internal.quoteObjectKey(key, config.snakeCase)}: t${change.name ? `.name(${internal.singleQuote(change.name)})` : ""}.change(`
|
|
4614
4693
|
];
|
|
4615
4694
|
const fromCode = change.from.column.toCode(
|
|
4616
4695
|
{
|
|
@@ -4623,76 +4702,76 @@ const astEncoders = {
|
|
|
4623
4702
|
key
|
|
4624
4703
|
);
|
|
4625
4704
|
for (const part of fromCode) {
|
|
4626
|
-
|
|
4705
|
+
internal.addCode(line, part);
|
|
4627
4706
|
}
|
|
4628
|
-
|
|
4707
|
+
internal.addCode(line, ", ");
|
|
4629
4708
|
const toCode = change.to.column.toCode(toCodeCtx, key);
|
|
4630
4709
|
for (const part of toCode) {
|
|
4631
|
-
|
|
4710
|
+
internal.addCode(line, part);
|
|
4632
4711
|
}
|
|
4633
4712
|
if (change.using) {
|
|
4634
|
-
|
|
4713
|
+
internal.addCode(line, ", {");
|
|
4635
4714
|
const u = [];
|
|
4636
4715
|
if (change.using.usingUp) {
|
|
4637
|
-
u.push(`usingUp: ${
|
|
4716
|
+
u.push(`usingUp: ${internal.rawSqlToCode(change.using.usingUp, "t")},`);
|
|
4638
4717
|
}
|
|
4639
4718
|
if (change.using.usingDown) {
|
|
4640
4719
|
u.push(
|
|
4641
|
-
`usingDown: ${
|
|
4720
|
+
`usingDown: ${internal.rawSqlToCode(change.using.usingDown, "t")},`
|
|
4642
4721
|
);
|
|
4643
4722
|
}
|
|
4644
|
-
|
|
4645
|
-
|
|
4723
|
+
internal.addCode(line, u);
|
|
4724
|
+
internal.addCode(line, "}");
|
|
4646
4725
|
}
|
|
4647
|
-
|
|
4726
|
+
internal.addCode(line, "),");
|
|
4648
4727
|
code.push(line);
|
|
4649
4728
|
} else if (change.type === "rename") {
|
|
4650
4729
|
code.push([
|
|
4651
|
-
`${
|
|
4730
|
+
`${internal.quoteObjectKey(key, config.snakeCase)}: t.rename(${internal.singleQuote(
|
|
4652
4731
|
change.name
|
|
4653
4732
|
)}),`
|
|
4654
4733
|
]);
|
|
4655
4734
|
} else {
|
|
4656
|
-
|
|
4735
|
+
internal.exhaustive(change.type);
|
|
4657
4736
|
}
|
|
4658
4737
|
}
|
|
4659
4738
|
}
|
|
4660
4739
|
for (const key of ["drop", "add"]) {
|
|
4661
4740
|
const timestamps = key === "add" ? addTimestamps : dropTimestamps;
|
|
4662
4741
|
if (timestamps.hasAnyTimestamps) {
|
|
4663
|
-
|
|
4742
|
+
internal.addCode(code, [`...t.${key}(${timestampsToCode(timestamps)}),`]);
|
|
4664
4743
|
}
|
|
4665
4744
|
const { primaryKey, indexes, excludes, constraints } = ast[key];
|
|
4666
4745
|
if (primaryKey) {
|
|
4667
|
-
|
|
4668
|
-
`...t.${key}(${
|
|
4746
|
+
internal.addCode(code, [
|
|
4747
|
+
`...t.${key}(${internal.primaryKeyInnerToCode(primaryKey, "t")}),`
|
|
4669
4748
|
]);
|
|
4670
4749
|
}
|
|
4671
4750
|
if (indexes) {
|
|
4672
4751
|
for (const item of indexes) {
|
|
4673
|
-
|
|
4752
|
+
internal.addCode(code, [`...t.${key}(`, internal.indexInnerToCode(item, "t"), "),"]);
|
|
4674
4753
|
}
|
|
4675
4754
|
}
|
|
4676
4755
|
if (excludes) {
|
|
4677
4756
|
for (const item of excludes) {
|
|
4678
|
-
|
|
4757
|
+
internal.addCode(code, [`...t.${key}(`, internal.excludeInnerToCode(item, "t"), "),"]);
|
|
4679
4758
|
}
|
|
4680
4759
|
}
|
|
4681
4760
|
if (constraints) {
|
|
4682
4761
|
for (const item of constraints) {
|
|
4683
|
-
|
|
4762
|
+
internal.addCode(code, [
|
|
4684
4763
|
`...t.${key}(`,
|
|
4685
|
-
|
|
4764
|
+
internal.constraintInnerToCode(item, "t", true),
|
|
4686
4765
|
"),"
|
|
4687
4766
|
]);
|
|
4688
4767
|
}
|
|
4689
4768
|
}
|
|
4690
4769
|
}
|
|
4691
4770
|
if (ast.comment !== void 0) {
|
|
4692
|
-
|
|
4693
|
-
|
|
4771
|
+
internal.addCode(code, "}),");
|
|
4772
|
+
internal.addCode(result, ");");
|
|
4694
4773
|
} else {
|
|
4695
|
-
|
|
4774
|
+
internal.addCode(result, "}));");
|
|
4696
4775
|
}
|
|
4697
4776
|
return result;
|
|
4698
4777
|
},
|
|
@@ -4700,14 +4779,14 @@ const astEncoders = {
|
|
|
4700
4779
|
const code = [];
|
|
4701
4780
|
const kind = ast.kind === "TABLE" ? "Table" : "Type";
|
|
4702
4781
|
if (ast.from === ast.to) {
|
|
4703
|
-
|
|
4782
|
+
internal.addCode(
|
|
4704
4783
|
code,
|
|
4705
|
-
`await db.change${kind}Schema(${
|
|
4784
|
+
`await db.change${kind}Schema(${internal.singleQuote(ast.to)}, ${internal.singleQuote(
|
|
4706
4785
|
ast.fromSchema ?? currentSchema
|
|
4707
|
-
)}, ${
|
|
4786
|
+
)}, ${internal.singleQuote(ast.toSchema ?? currentSchema)});`
|
|
4708
4787
|
);
|
|
4709
4788
|
} else {
|
|
4710
|
-
|
|
4789
|
+
internal.addCode(
|
|
4711
4790
|
code,
|
|
4712
4791
|
`await db.rename${kind}(${quoteSchemaTable({
|
|
4713
4792
|
schema: ast.fromSchema === currentSchema ? void 0 : ast.fromSchema,
|
|
@@ -4721,10 +4800,10 @@ const astEncoders = {
|
|
|
4721
4800
|
return code;
|
|
4722
4801
|
},
|
|
4723
4802
|
schema(ast) {
|
|
4724
|
-
return `await db.${ast.action === "create" ? "createSchema" : "dropSchema"}(${
|
|
4803
|
+
return `await db.${ast.action === "create" ? "createSchema" : "dropSchema"}(${internal.singleQuote(ast.name)});`;
|
|
4725
4804
|
},
|
|
4726
4805
|
renameSchema(ast) {
|
|
4727
|
-
return `await db.renameSchema(${
|
|
4806
|
+
return `await db.renameSchema(${internal.singleQuote(ast.from)}, ${internal.singleQuote(
|
|
4728
4807
|
ast.to
|
|
4729
4808
|
)});`;
|
|
4730
4809
|
},
|
|
@@ -4733,34 +4812,34 @@ const astEncoders = {
|
|
|
4733
4812
|
`await db.${ast.action}Extension(${quoteSchemaTable(ast, currentSchema)}`
|
|
4734
4813
|
];
|
|
4735
4814
|
if (ast.version) {
|
|
4736
|
-
|
|
4737
|
-
code.push([`version: ${
|
|
4815
|
+
internal.addCode(code, ", {");
|
|
4816
|
+
code.push([`version: ${internal.singleQuote(ast.version)},`], "}");
|
|
4738
4817
|
}
|
|
4739
|
-
|
|
4818
|
+
internal.addCode(code, ");");
|
|
4740
4819
|
return code;
|
|
4741
4820
|
},
|
|
4742
4821
|
enum(ast, _, currentSchema) {
|
|
4743
|
-
return `await db.${ast.action === "create" ? "createEnum" : "dropEnum"}(${quoteSchemaTable(ast, currentSchema)}, [${ast.values.map(
|
|
4822
|
+
return `await db.${ast.action === "create" ? "createEnum" : "dropEnum"}(${quoteSchemaTable(ast, currentSchema)}, [${ast.values.map(internal.singleQuote).join(", ")}]);`;
|
|
4744
4823
|
},
|
|
4745
4824
|
enumValues(ast, _, currentSchema) {
|
|
4746
4825
|
return `await db.${ast.action}EnumValues(${quoteSchemaTable(
|
|
4747
4826
|
ast,
|
|
4748
4827
|
currentSchema
|
|
4749
|
-
)}, [${ast.values.map(
|
|
4828
|
+
)}, [${ast.values.map(internal.singleQuote).join(", ")}]);`;
|
|
4750
4829
|
},
|
|
4751
4830
|
renameEnumValues(ast, config, currentSchema) {
|
|
4752
4831
|
return `await db.renameEnumValues(${quoteSchemaTable(
|
|
4753
4832
|
ast,
|
|
4754
4833
|
currentSchema
|
|
4755
4834
|
)}, { ${Object.entries(ast.values).map(
|
|
4756
|
-
([from, to]) => `${
|
|
4835
|
+
([from, to]) => `${internal.quoteObjectKey(from, config.snakeCase)}: ${internal.singleQuote(to)}`
|
|
4757
4836
|
).join(", ")} });`;
|
|
4758
4837
|
},
|
|
4759
4838
|
changeEnumValues(ast, _, currentSchema) {
|
|
4760
4839
|
return `await db.changeEnumValues(${quoteSchemaTable(
|
|
4761
4840
|
ast,
|
|
4762
4841
|
currentSchema
|
|
4763
|
-
)}, [${ast.fromValues.map(
|
|
4842
|
+
)}, [${ast.fromValues.map(internal.singleQuote).join(", ")}], [${ast.toValues.map(internal.singleQuote).join(", ")}]);`;
|
|
4764
4843
|
},
|
|
4765
4844
|
domain(ast, _, currentSchema) {
|
|
4766
4845
|
return `await db.${ast.action}Domain(${quoteSchemaTable(
|
|
@@ -4793,13 +4872,13 @@ const astEncoders = {
|
|
|
4793
4872
|
if (ast.references) {
|
|
4794
4873
|
return [
|
|
4795
4874
|
`await db.addForeignKey(`,
|
|
4796
|
-
[`${table},`, ...
|
|
4875
|
+
[`${table},`, ...internal.referencesArgsToCode(ast.references, ast.name, true)],
|
|
4797
4876
|
");"
|
|
4798
4877
|
];
|
|
4799
4878
|
}
|
|
4800
4879
|
const check = ast.check;
|
|
4801
4880
|
return [
|
|
4802
|
-
`await db.addCheck(${table}, ${
|
|
4881
|
+
`await db.addCheck(${table}, ${internal.rawSqlToCode(check, "t")}${ast.name ? `, ${internal.singleQuote(ast.name)}` : ""});`
|
|
4803
4882
|
];
|
|
4804
4883
|
},
|
|
4805
4884
|
renameTableItem(ast) {
|
|
@@ -4807,7 +4886,7 @@ const astEncoders = {
|
|
|
4807
4886
|
`await db.rename${ast.kind === "INDEX" ? "Index" : "Constraint"}(${quoteSchemaTable({
|
|
4808
4887
|
schema: ast.tableSchema,
|
|
4809
4888
|
name: ast.tableName
|
|
4810
|
-
})}, ${
|
|
4889
|
+
})}, ${internal.singleQuote(ast.from)}, ${internal.singleQuote(ast.to)});`
|
|
4811
4890
|
];
|
|
4812
4891
|
},
|
|
4813
4892
|
view(ast, _, currentSchema) {
|
|
@@ -4823,10 +4902,10 @@ const astEncoders = {
|
|
|
4823
4902
|
if (w?.securityInvoker)
|
|
4824
4903
|
options.push(`securityInvoker: ${w.securityInvoker},`);
|
|
4825
4904
|
if (options.length) {
|
|
4826
|
-
|
|
4905
|
+
internal.addCode(code, ", {");
|
|
4827
4906
|
code.push(options, "}");
|
|
4828
4907
|
}
|
|
4829
|
-
|
|
4908
|
+
internal.addCode(code, ", ");
|
|
4830
4909
|
if (!ast.sql._values) {
|
|
4831
4910
|
const raw = ast.sql._sql;
|
|
4832
4911
|
let sql;
|
|
@@ -4841,17 +4920,17 @@ const astEncoders = {
|
|
|
4841
4920
|
}
|
|
4842
4921
|
sql += parts[last];
|
|
4843
4922
|
}
|
|
4844
|
-
|
|
4923
|
+
internal.addCode(code, internal.backtickQuote(sql));
|
|
4845
4924
|
} else {
|
|
4846
|
-
|
|
4925
|
+
internal.addCode(code, internal.rawSqlToCode(ast.sql, "db"));
|
|
4847
4926
|
}
|
|
4848
|
-
|
|
4927
|
+
internal.addCode(code, ");");
|
|
4849
4928
|
return code;
|
|
4850
4929
|
},
|
|
4851
4930
|
role(ast) {
|
|
4852
4931
|
const params = roleParams(ast.name, ast);
|
|
4853
4932
|
const arr = [
|
|
4854
|
-
`await db.${ast.action}Role(${
|
|
4933
|
+
`await db.${ast.action}Role(${internal.singleQuote(ast.name)}${params.length ? ", {" : ");"}`
|
|
4855
4934
|
];
|
|
4856
4935
|
if (params.length) {
|
|
4857
4936
|
arr.push(params);
|
|
@@ -4860,7 +4939,7 @@ const astEncoders = {
|
|
|
4860
4939
|
return arr;
|
|
4861
4940
|
},
|
|
4862
4941
|
renameRole(ast) {
|
|
4863
|
-
return `await db.renameRole(${
|
|
4942
|
+
return `await db.renameRole(${internal.singleQuote(ast.from)}, ${internal.singleQuote(
|
|
4864
4943
|
ast.to
|
|
4865
4944
|
)});`;
|
|
4866
4945
|
},
|
|
@@ -4868,7 +4947,7 @@ const astEncoders = {
|
|
|
4868
4947
|
const from = roleParams(ast.name, ast.from, ast.to);
|
|
4869
4948
|
const to = roleParams(ast.name, ast.to, ast.from, true);
|
|
4870
4949
|
return [
|
|
4871
|
-
`await db.changeRole(${
|
|
4950
|
+
`await db.changeRole(${internal.singleQuote(ast.name)}, {`,
|
|
4872
4951
|
[...from.length ? ["from: {", from, "},"] : [], "to: {", to, "},"],
|
|
4873
4952
|
"});"
|
|
4874
4953
|
];
|
|
@@ -4877,11 +4956,11 @@ const astEncoders = {
|
|
|
4877
4956
|
const code = [`await db.changeDefaultPrivileges({`];
|
|
4878
4957
|
const props = [];
|
|
4879
4958
|
if (ast.owner) {
|
|
4880
|
-
props.push(`owner: ${
|
|
4959
|
+
props.push(`owner: ${internal.singleQuote(ast.owner)},`);
|
|
4881
4960
|
}
|
|
4882
|
-
props.push(`grantee: ${
|
|
4961
|
+
props.push(`grantee: ${internal.singleQuote(ast.grantee)},`);
|
|
4883
4962
|
if (ast.schema) {
|
|
4884
|
-
props.push(`schema: ${
|
|
4963
|
+
props.push(`schema: ${internal.singleQuote(ast.schema)},`);
|
|
4885
4964
|
}
|
|
4886
4965
|
const objectConfigToCode = (config) => {
|
|
4887
4966
|
const result = [];
|
|
@@ -4903,12 +4982,12 @@ const astEncoders = {
|
|
|
4903
4982
|
const lines = [];
|
|
4904
4983
|
if (hasPrivileges) {
|
|
4905
4984
|
lines.push(
|
|
4906
|
-
`privileges: [${privileges.map(
|
|
4985
|
+
`privileges: [${privileges.map(internal.singleQuote).join(", ")}],`
|
|
4907
4986
|
);
|
|
4908
4987
|
}
|
|
4909
4988
|
if (hasGrantable) {
|
|
4910
4989
|
lines.push(
|
|
4911
|
-
`grantablePrivileges: [${grantablePrivileges.map(
|
|
4990
|
+
`grantablePrivileges: [${grantablePrivileges.map(internal.singleQuote).join(", ")}],`
|
|
4912
4991
|
);
|
|
4913
4992
|
}
|
|
4914
4993
|
result.push(lines);
|
|
@@ -4933,7 +5012,7 @@ const astEncoders = {
|
|
|
4933
5012
|
}
|
|
4934
5013
|
}
|
|
4935
5014
|
code.push(props);
|
|
4936
|
-
|
|
5015
|
+
internal.addCode(code, "});");
|
|
4937
5016
|
return code;
|
|
4938
5017
|
}
|
|
4939
5018
|
};
|
|
@@ -4957,7 +5036,7 @@ const roleParams = (name, ast, compare, to) => {
|
|
|
4957
5036
|
if (!compare && (!value || key === "connLimit" && value === -1)) {
|
|
4958
5037
|
continue;
|
|
4959
5038
|
}
|
|
4960
|
-
value = value instanceof Date ? `'${value.toISOString()}'` : key === "config" ? JSON.stringify(value) : typeof value === "string" ?
|
|
5039
|
+
value = value instanceof Date ? `'${value.toISOString()}'` : key === "config" ? JSON.stringify(value) : typeof value === "string" ? internal.singleQuote(value) : value;
|
|
4961
5040
|
if (compare) {
|
|
4962
5041
|
const a = value === -1 || value === false ? void 0 : value;
|
|
4963
5042
|
const other = compare[key];
|
|
@@ -4974,15 +5053,15 @@ const isTimestamp = (column, type) => {
|
|
|
4974
5053
|
if (!column) return false;
|
|
4975
5054
|
const { default: def } = column.data;
|
|
4976
5055
|
return Boolean(
|
|
4977
|
-
column instanceof type && !column.data.isNullable && def && typeof def === "object" &&
|
|
5056
|
+
column instanceof type && !column.data.isNullable && def && typeof def === "object" && internal.isRawSQL(def) && (typeof def._sql === "object" ? def._sql[0][0] : def._sql) === "now()"
|
|
4978
5057
|
);
|
|
4979
5058
|
};
|
|
4980
5059
|
const getHasTimestamps = (createdAt, updatedAt) => {
|
|
4981
|
-
const timestamps = getTimestampsInfo(createdAt, updatedAt,
|
|
5060
|
+
const timestamps = getTimestampsInfo(createdAt, updatedAt, internal.TimestampTZColumn);
|
|
4982
5061
|
const timestampsNoTZ = getTimestampsInfo(
|
|
4983
5062
|
createdAt,
|
|
4984
5063
|
updatedAt,
|
|
4985
|
-
|
|
5064
|
+
internal.TimestampColumn
|
|
4986
5065
|
);
|
|
4987
5066
|
return {
|
|
4988
5067
|
hasTZTimestamps: timestamps,
|
|
@@ -5594,7 +5673,7 @@ const makeStructureToAstCtx = (config, currentSchema) => ({
|
|
|
5594
5673
|
unsupportedTypes: {},
|
|
5595
5674
|
currentSchema,
|
|
5596
5675
|
columnSchemaConfig: config.schemaConfig,
|
|
5597
|
-
columnsByType:
|
|
5676
|
+
columnsByType: internal.makeColumnsByType(config.schemaConfig)
|
|
5598
5677
|
});
|
|
5599
5678
|
const structureToAst = async (ctx, adapter, config) => {
|
|
5600
5679
|
const ast = [];
|
|
@@ -5693,7 +5772,7 @@ const makeDomainsMap = (ctx, data) => {
|
|
|
5693
5772
|
});
|
|
5694
5773
|
if (it.checks) {
|
|
5695
5774
|
column.data.checks = it.checks.map((check) => ({
|
|
5696
|
-
sql: new
|
|
5775
|
+
sql: new internal.RawSql([[check]])
|
|
5697
5776
|
}));
|
|
5698
5777
|
}
|
|
5699
5778
|
domains[`${it.schemaName}.${it.name}`] = column;
|
|
@@ -5704,7 +5783,7 @@ const getDbColumnIsSerial = (item) => {
|
|
|
5704
5783
|
if (item.type === "int2" || item.type === "int4" || item.type === "int8") {
|
|
5705
5784
|
const { default: def, schemaName, tableName, name } = item;
|
|
5706
5785
|
const seq = `${tableName}_${name}_seq`;
|
|
5707
|
-
if (def && (def === `nextval(${
|
|
5786
|
+
if (def && (def === `nextval(${internal.singleQuote(`${seq}`)}::regclass)` || def === `nextval(${internal.singleQuote(`"${seq}"`)}::regclass)` || def === `nextval(${internal.singleQuote(`${schemaName}.${seq}`)}::regclass)` || def === `nextval(${internal.singleQuote(`"${schemaName}".${seq}`)}::regclass)` || def === `nextval(${internal.singleQuote(`${schemaName}."${seq}"`)}::regclass)` || def === `nextval(${internal.singleQuote(`"${schemaName}"."${seq}"`)}::regclass)`)) {
|
|
5708
5787
|
return true;
|
|
5709
5788
|
}
|
|
5710
5789
|
}
|
|
@@ -5725,7 +5804,7 @@ const instantiateDbColumn = (ctx, data, domains, dbColumn) => {
|
|
|
5725
5804
|
const typeId = typeSchema === "pg_catalog" ? typeName : `${typeSchema}.${typeName}`;
|
|
5726
5805
|
const domainColumn = domains[typeId];
|
|
5727
5806
|
if (domainColumn) {
|
|
5728
|
-
column = new
|
|
5807
|
+
column = new internal.DomainColumn(
|
|
5729
5808
|
ctx.columnSchemaConfig,
|
|
5730
5809
|
typeName,
|
|
5731
5810
|
typeSchema,
|
|
@@ -5736,14 +5815,14 @@ const instantiateDbColumn = (ctx, data, domains, dbColumn) => {
|
|
|
5736
5815
|
(x) => x.name === typeName && x.schemaName === typeSchema
|
|
5737
5816
|
);
|
|
5738
5817
|
if (enumType) {
|
|
5739
|
-
column = new
|
|
5818
|
+
column = new internal.EnumColumn(
|
|
5740
5819
|
ctx.columnSchemaConfig,
|
|
5741
5820
|
typeSchema === ctx.currentSchema ? typeName : typeId,
|
|
5742
5821
|
enumType.values,
|
|
5743
5822
|
ctx.columnSchemaConfig.type
|
|
5744
5823
|
);
|
|
5745
5824
|
} else {
|
|
5746
|
-
column = new
|
|
5825
|
+
column = new internal.CustomTypeColumn(
|
|
5747
5826
|
ctx.columnSchemaConfig,
|
|
5748
5827
|
typeName,
|
|
5749
5828
|
typeSchema === "pg_catalog" ? void 0 : typeSchema,
|
|
@@ -5753,13 +5832,13 @@ const instantiateDbColumn = (ctx, data, domains, dbColumn) => {
|
|
|
5753
5832
|
`${dbColumn.schemaName}${dbColumn.tableName ? `.${dbColumn.tableName}` : ""}.${dbColumn.name}`
|
|
5754
5833
|
);
|
|
5755
5834
|
}
|
|
5756
|
-
|
|
5835
|
+
internal.assignDbDataToColumn(column, dbColumn);
|
|
5757
5836
|
}
|
|
5758
5837
|
}
|
|
5759
5838
|
column.data.name = void 0;
|
|
5760
5839
|
if (!column.data.isNullable) column.data.isNullable = void 0;
|
|
5761
5840
|
if (dbColumn.arrayDims) {
|
|
5762
|
-
const arr = new
|
|
5841
|
+
const arr = new internal.ArrayColumn(
|
|
5763
5842
|
ctx.columnSchemaConfig,
|
|
5764
5843
|
column,
|
|
5765
5844
|
ctx.columnSchemaConfig.type
|
|
@@ -5772,10 +5851,10 @@ const instantiateDbColumn = (ctx, data, domains, dbColumn) => {
|
|
|
5772
5851
|
};
|
|
5773
5852
|
const instantiateColumnByDbType = (ctx, type, isSerial, params) => {
|
|
5774
5853
|
let columnFn = ctx.columnsByType[!isSerial ? type : type === "int2" ? "smallserial" : type === "int4" ? "serial" : "bigserial"];
|
|
5775
|
-
if (!columnFn && params.extension === "postgis" && type === "geography" &&
|
|
5854
|
+
if (!columnFn && params.extension === "postgis" && type === "geography" && internal.PostgisGeographyPointColumn.isDefaultPoint(params.typmod)) {
|
|
5776
5855
|
columnFn = ctx.columnsByType.geographyDefaultPoint;
|
|
5777
5856
|
}
|
|
5778
|
-
return columnFn ?
|
|
5857
|
+
return columnFn ? internal.assignDbDataToColumn(columnFn(), params) : void 0;
|
|
5779
5858
|
};
|
|
5780
5859
|
const tableToAst = (ctx, data, table, action, domains) => {
|
|
5781
5860
|
const { schemaName, name: tableName } = table;
|
|
@@ -5789,7 +5868,7 @@ const tableToAst = (ctx, data, table, action, domains) => {
|
|
|
5789
5868
|
name: tableName,
|
|
5790
5869
|
shape: makeDbStructureColumnsShape(ctx, data, domains, table, tableData),
|
|
5791
5870
|
noPrimaryKey: tableData.primaryKey ? "error" : "ignore",
|
|
5792
|
-
primaryKey: primaryKey && primaryKey.columns.length > 1 ? { ...primaryKey, columns: primaryKey.columns.map(
|
|
5871
|
+
primaryKey: primaryKey && primaryKey.columns.length > 1 ? { ...primaryKey, columns: primaryKey.columns.map(internal.toCamelCase) } : void 0,
|
|
5793
5872
|
indexes: indexesOrExcludesToAst(
|
|
5794
5873
|
tableName,
|
|
5795
5874
|
tableData,
|
|
@@ -5815,14 +5894,14 @@ const indexesOrExcludesToAst = (tableName, tableData, key) => {
|
|
|
5815
5894
|
acc.push({
|
|
5816
5895
|
columns: item.columns.map((it, i) => ({
|
|
5817
5896
|
with: "exclude" in item && item.exclude ? item.exclude[i] : void 0,
|
|
5818
|
-
..."expression" in it ? { expression: it.expression } : { column:
|
|
5897
|
+
..."expression" in it ? { expression: it.expression } : { column: internal.toCamelCase(it.column) },
|
|
5819
5898
|
collate: it.collate,
|
|
5820
5899
|
opclass: it.opclass,
|
|
5821
5900
|
order: it.order
|
|
5822
5901
|
})),
|
|
5823
5902
|
options: {
|
|
5824
5903
|
...options,
|
|
5825
|
-
include: item.include?.map(
|
|
5904
|
+
include: item.include?.map(internal.toCamelCase)
|
|
5826
5905
|
}
|
|
5827
5906
|
});
|
|
5828
5907
|
}
|
|
@@ -5864,7 +5943,7 @@ const constraintToAst = (ctx, item) => {
|
|
|
5864
5943
|
if (onDelete) options.onDelete = onDelete;
|
|
5865
5944
|
}
|
|
5866
5945
|
if (check) {
|
|
5867
|
-
result.check =
|
|
5946
|
+
result.check = internal.raw({ raw: check.expression });
|
|
5868
5947
|
}
|
|
5869
5948
|
if (item.name && item.name !== getConstraintName(item.tableName, result, ctx.snakeCase)) {
|
|
5870
5949
|
result.name = item.name;
|
|
@@ -5889,7 +5968,7 @@ const viewToAst = (ctx, data, domains, view) => {
|
|
|
5889
5968
|
options.with = withOptions;
|
|
5890
5969
|
for (const pair of view.with) {
|
|
5891
5970
|
const [key, value] = pair.split("=");
|
|
5892
|
-
withOptions[
|
|
5971
|
+
withOptions[internal.toCamelCase(key)] = value === "true" ? true : value === "false" ? false : value;
|
|
5893
5972
|
}
|
|
5894
5973
|
}
|
|
5895
5974
|
return {
|
|
@@ -5898,7 +5977,7 @@ const viewToAst = (ctx, data, domains, view) => {
|
|
|
5898
5977
|
schema: view.schemaName === ctx.currentSchema ? void 0 : view.schemaName,
|
|
5899
5978
|
name: view.name,
|
|
5900
5979
|
shape,
|
|
5901
|
-
sql:
|
|
5980
|
+
sql: internal.raw({ raw: view.sql }),
|
|
5902
5981
|
options,
|
|
5903
5982
|
deps: view.deps
|
|
5904
5983
|
};
|
|
@@ -5962,12 +6041,12 @@ const dbColumnToAst = (ctx, data, domains, tableName, item, table, tableData, ch
|
|
|
5962
6041
|
const columnChecks = checks?.[item.name];
|
|
5963
6042
|
if (columnChecks) {
|
|
5964
6043
|
column.data.checks = columnChecks.map((check) => ({
|
|
5965
|
-
sql: new
|
|
6044
|
+
sql: new internal.RawSql([[check]])
|
|
5966
6045
|
}));
|
|
5967
6046
|
}
|
|
5968
|
-
const camelCaseName =
|
|
6047
|
+
const camelCaseName = internal.toCamelCase(item.name);
|
|
5969
6048
|
if (ctx.snakeCase) {
|
|
5970
|
-
const snakeCaseName =
|
|
6049
|
+
const snakeCaseName = internal.toSnakeCase(camelCaseName);
|
|
5971
6050
|
if (snakeCaseName !== item.name) column.data.name = item.name;
|
|
5972
6051
|
} else if (camelCaseName !== item.name) {
|
|
5973
6052
|
column.data.name = item.name;
|
|
@@ -6013,7 +6092,7 @@ const dbConstraintToTableConstraint = (ctx, table, item) => {
|
|
|
6013
6092
|
onDelete: fkeyActionMap[references.onDelete]
|
|
6014
6093
|
}
|
|
6015
6094
|
} : void 0,
|
|
6016
|
-
check: check ?
|
|
6095
|
+
check: check ? internal.raw({ raw: check.expression }) : void 0
|
|
6017
6096
|
};
|
|
6018
6097
|
const name = item.name && item.name !== getConstraintName(table.name, constraint, ctx.snakeCase) ? item.name : void 0;
|
|
6019
6098
|
if (name) {
|
|
@@ -6085,118 +6164,6 @@ Append \`as\` method manually to ${count > 1 ? "these" : "this"} column${count >
|
|
|
6085
6164
|
config.logger?.log("Database pulled successfully");
|
|
6086
6165
|
};
|
|
6087
6166
|
|
|
6088
|
-
const migrationConfigDefaults = {
|
|
6089
|
-
schemaConfig: pqb.defaultSchemaConfig,
|
|
6090
|
-
migrationsPath: path.join("src", "db", "migrations"),
|
|
6091
|
-
migrationId: { serial: 4 },
|
|
6092
|
-
migrationsTable: "schemaMigrations",
|
|
6093
|
-
snakeCase: false,
|
|
6094
|
-
commands: {},
|
|
6095
|
-
log: true,
|
|
6096
|
-
logger: console,
|
|
6097
|
-
import() {
|
|
6098
|
-
throw new Error(
|
|
6099
|
-
"Add `import: (path) => import(path),` setting to `rakeDb` config"
|
|
6100
|
-
);
|
|
6101
|
-
}
|
|
6102
|
-
};
|
|
6103
|
-
const ensureMigrationsPath = (config) => {
|
|
6104
|
-
if (!config.migrationsPath) {
|
|
6105
|
-
config.migrationsPath = migrationConfigDefaults.migrationsPath;
|
|
6106
|
-
}
|
|
6107
|
-
if (!path.isAbsolute(config.migrationsPath)) {
|
|
6108
|
-
config.migrationsPath = path.resolve(
|
|
6109
|
-
config.basePath,
|
|
6110
|
-
config.migrationsPath
|
|
6111
|
-
);
|
|
6112
|
-
}
|
|
6113
|
-
return config;
|
|
6114
|
-
};
|
|
6115
|
-
const ensureBasePathAndDbScript = (config, intermediateCallers2 = 0) => {
|
|
6116
|
-
if (config.basePath && config.dbScript) return config;
|
|
6117
|
-
let filePath = pqb.getStackTrace()?.[3 + intermediateCallers2]?.getFileName();
|
|
6118
|
-
if (!filePath) {
|
|
6119
|
-
throw new Error(
|
|
6120
|
-
"Failed to determine path to db script. Please set basePath option of rakeDb"
|
|
6121
|
-
);
|
|
6122
|
-
}
|
|
6123
|
-
if (filePath.startsWith("file://")) {
|
|
6124
|
-
filePath = node_url.fileURLToPath(filePath);
|
|
6125
|
-
}
|
|
6126
|
-
const ext = path.extname(filePath);
|
|
6127
|
-
if (ext !== ".ts" && ext !== ".js" && ext !== ".mjs") {
|
|
6128
|
-
throw new Error(
|
|
6129
|
-
`Add a .ts suffix to the "${path.basename(filePath)}" when calling it`
|
|
6130
|
-
);
|
|
6131
|
-
}
|
|
6132
|
-
config.basePath = path.dirname(filePath);
|
|
6133
|
-
config.dbScript = path.basename(filePath);
|
|
6134
|
-
return config;
|
|
6135
|
-
};
|
|
6136
|
-
let intermediateCallers = 0;
|
|
6137
|
-
const incrementIntermediateCaller = () => {
|
|
6138
|
-
intermediateCallers++;
|
|
6139
|
-
};
|
|
6140
|
-
const makeRakeDbConfig = (config, args) => {
|
|
6141
|
-
const ic = intermediateCallers;
|
|
6142
|
-
intermediateCallers = 0;
|
|
6143
|
-
const result = {
|
|
6144
|
-
...migrationConfigDefaults,
|
|
6145
|
-
...config,
|
|
6146
|
-
__rakeDbConfig: true
|
|
6147
|
-
};
|
|
6148
|
-
if (!result.log) {
|
|
6149
|
-
delete result.logger;
|
|
6150
|
-
}
|
|
6151
|
-
ensureBasePathAndDbScript(result, ic);
|
|
6152
|
-
ensureMigrationsPath(result);
|
|
6153
|
-
if (!result.recurrentPath) {
|
|
6154
|
-
result.recurrentPath = path.join(
|
|
6155
|
-
result.migrationsPath,
|
|
6156
|
-
"recurrent"
|
|
6157
|
-
);
|
|
6158
|
-
}
|
|
6159
|
-
if ("recurrentPath" in result && !path.isAbsolute(result.recurrentPath)) {
|
|
6160
|
-
result.recurrentPath = path.resolve(result.basePath, result.recurrentPath);
|
|
6161
|
-
}
|
|
6162
|
-
if ("baseTable" in config && config.baseTable) {
|
|
6163
|
-
const { types, snakeCase, language } = config.baseTable.prototype;
|
|
6164
|
-
result.columnTypes = types || pqb.makeColumnTypes(pqb.defaultSchemaConfig);
|
|
6165
|
-
if (snakeCase) result.snakeCase = true;
|
|
6166
|
-
if (language) result.language = language;
|
|
6167
|
-
} else {
|
|
6168
|
-
const ct = "columnTypes" in config && config.columnTypes;
|
|
6169
|
-
result.columnTypes = (typeof ct === "function" ? ct(
|
|
6170
|
-
pqb.makeColumnTypes(pqb.defaultSchemaConfig)
|
|
6171
|
-
) : ct) || pqb.makeColumnTypes(pqb.defaultSchemaConfig);
|
|
6172
|
-
}
|
|
6173
|
-
if (config.migrationId === "serial") {
|
|
6174
|
-
result.migrationId = { serial: 4 };
|
|
6175
|
-
}
|
|
6176
|
-
const transaction = getCliParam(args, "transaction");
|
|
6177
|
-
if (transaction) {
|
|
6178
|
-
if (transaction !== "single" && transaction !== "per-migration") {
|
|
6179
|
-
throw new Error(
|
|
6180
|
-
`Unsupported transaction param ${transaction}, expected single or per-migration`
|
|
6181
|
-
);
|
|
6182
|
-
}
|
|
6183
|
-
result.transaction = transaction;
|
|
6184
|
-
} else if (!result.transaction) {
|
|
6185
|
-
result.transaction = "single";
|
|
6186
|
-
}
|
|
6187
|
-
let c = rakeDbCommands;
|
|
6188
|
-
if (config.commands) {
|
|
6189
|
-
c = { ...c };
|
|
6190
|
-
const commands = config.commands;
|
|
6191
|
-
for (const key in commands) {
|
|
6192
|
-
const command = commands[key];
|
|
6193
|
-
c[key] = typeof command === "function" ? { run: command } : command;
|
|
6194
|
-
}
|
|
6195
|
-
}
|
|
6196
|
-
result.commands = c;
|
|
6197
|
-
return result;
|
|
6198
|
-
};
|
|
6199
|
-
|
|
6200
6167
|
const listMigrationsStatuses = async (adapters, config, params) => {
|
|
6201
6168
|
const ctx = {};
|
|
6202
6169
|
const [{ migrations }, ...migrated] = await Promise.all([
|
|
@@ -6243,7 +6210,7 @@ const listMigrationsStatuses = async (adapters, config, params) => {
|
|
|
6243
6210
|
green: asIs,
|
|
6244
6211
|
red: asIs,
|
|
6245
6212
|
blue: asIs
|
|
6246
|
-
} :
|
|
6213
|
+
} : internal.colors;
|
|
6247
6214
|
const log = Object.values(map).map(({ databases, migrations: migrations2 }) => {
|
|
6248
6215
|
let log2 = ` ${c.yellow("Database:")} ${databases.join(", ")}`;
|
|
6249
6216
|
if (migrations2.length === 0) {
|
|
@@ -6345,7 +6312,7 @@ const rebase = async (adapters, config) => {
|
|
|
6345
6312
|
const result = await promptSelect({
|
|
6346
6313
|
message: "Which should go first?",
|
|
6347
6314
|
options: [prev.name, file.name],
|
|
6348
|
-
active: (s) => `${
|
|
6315
|
+
active: (s) => `${internal.colors.yellow("\u276F")} ${internal.colors.yellow(s)}`
|
|
6349
6316
|
});
|
|
6350
6317
|
moveFile = result ? file : prev;
|
|
6351
6318
|
}
|
|
@@ -6360,85 +6327,275 @@ const rebase = async (adapters, config) => {
|
|
|
6360
6327
|
renames.push(values);
|
|
6361
6328
|
renamesMap[file.path] = values;
|
|
6362
6329
|
}
|
|
6363
|
-
if (moveFile === prev) {
|
|
6364
|
-
if (prev.serial < minVersionToMigrate)
|
|
6365
|
-
minVersionToMigrate = prev.serial;
|
|
6366
|
-
newVersion = prev.serial + move;
|
|
6367
|
-
let item = [prev.path, newVersion];
|
|
6368
|
-
if (renamesMap[prev.path]) {
|
|
6369
|
-
renamesMap[prev.path] = item;
|
|
6370
|
-
for (let i2 = renames.length - 1; i2 >= 0; i2--) {
|
|
6371
|
-
const rename = renames[i2];
|
|
6372
|
-
rename[1]--;
|
|
6373
|
-
renames[i2] = item;
|
|
6374
|
-
if (rename[0] === prev.path) break;
|
|
6375
|
-
renamesMap[item[0]] = item;
|
|
6376
|
-
item = rename;
|
|
6377
|
-
}
|
|
6378
|
-
} else {
|
|
6379
|
-
renames.push(item);
|
|
6380
|
-
renamesMap[prev.path] = item;
|
|
6381
|
-
}
|
|
6330
|
+
if (moveFile === prev) {
|
|
6331
|
+
if (prev.serial < minVersionToMigrate)
|
|
6332
|
+
minVersionToMigrate = prev.serial;
|
|
6333
|
+
newVersion = prev.serial + move;
|
|
6334
|
+
let item = [prev.path, newVersion];
|
|
6335
|
+
if (renamesMap[prev.path]) {
|
|
6336
|
+
renamesMap[prev.path] = item;
|
|
6337
|
+
for (let i2 = renames.length - 1; i2 >= 0; i2--) {
|
|
6338
|
+
const rename = renames[i2];
|
|
6339
|
+
rename[1]--;
|
|
6340
|
+
renames[i2] = item;
|
|
6341
|
+
if (rename[0] === prev.path) break;
|
|
6342
|
+
renamesMap[item[0]] = item;
|
|
6343
|
+
item = rename;
|
|
6344
|
+
}
|
|
6345
|
+
} else {
|
|
6346
|
+
renames.push(item);
|
|
6347
|
+
renamesMap[prev.path] = item;
|
|
6348
|
+
}
|
|
6349
|
+
}
|
|
6350
|
+
}
|
|
6351
|
+
if (file.name !== migratedName && newVersion > maxNewVersion) {
|
|
6352
|
+
maxNewVersion = newVersion;
|
|
6353
|
+
}
|
|
6354
|
+
}
|
|
6355
|
+
if (!renames.length && !migratedFiles.length) return;
|
|
6356
|
+
maxNewVersion++;
|
|
6357
|
+
renames.push(
|
|
6358
|
+
...migratedFiles.map((file, i) => {
|
|
6359
|
+
const rename = [file.path, maxNewVersion + i];
|
|
6360
|
+
renamesMap[file.path] = rename;
|
|
6361
|
+
return rename;
|
|
6362
|
+
})
|
|
6363
|
+
);
|
|
6364
|
+
if (!renames.length) return;
|
|
6365
|
+
const migrationsDown = files.filter(
|
|
6366
|
+
(file) => combinedVersionsMap[file.version] === file.name && file.serial >= minVersionToMigrate
|
|
6367
|
+
);
|
|
6368
|
+
const migrationsUp = files.reduce((files2, file) => {
|
|
6369
|
+
const rename = renamesMap[file.path];
|
|
6370
|
+
if (rename) {
|
|
6371
|
+
const version = String(rename[1]).padStart(4, "0");
|
|
6372
|
+
files2.push({
|
|
6373
|
+
...file,
|
|
6374
|
+
path: path.join(
|
|
6375
|
+
path.dirname(rename[0]),
|
|
6376
|
+
version + path.basename(rename[0]).slice(version.length)
|
|
6377
|
+
),
|
|
6378
|
+
version
|
|
6379
|
+
});
|
|
6380
|
+
} else if (!combinedVersionsMap[file.version] || file.serial >= minVersionToMigrate) {
|
|
6381
|
+
files2.push(file);
|
|
6382
|
+
}
|
|
6383
|
+
return files2;
|
|
6384
|
+
}, []).sort((a, b) => +b.version - +a.version);
|
|
6385
|
+
set.migrations = migrationsDown;
|
|
6386
|
+
const redoConfig = {
|
|
6387
|
+
...config,
|
|
6388
|
+
async afterRollback() {
|
|
6389
|
+
set.migrations = migrationsUp;
|
|
6390
|
+
},
|
|
6391
|
+
async afterMigrate() {
|
|
6392
|
+
set.migrations = migrationsDown;
|
|
6393
|
+
}
|
|
6394
|
+
};
|
|
6395
|
+
for (const adapter of adapters) {
|
|
6396
|
+
await redo(adapter, redoConfig, { ctx, count: Infinity });
|
|
6397
|
+
}
|
|
6398
|
+
for (let i = renames.length - 1; i >= 0; i--) {
|
|
6399
|
+
const [from, version] = renames[i];
|
|
6400
|
+
const prefix = String(version).padStart(4, "0");
|
|
6401
|
+
await fs.rename(
|
|
6402
|
+
from,
|
|
6403
|
+
path.join(
|
|
6404
|
+
path.dirname(from),
|
|
6405
|
+
prefix + path.basename(from).slice(prefix.length)
|
|
6406
|
+
)
|
|
6407
|
+
);
|
|
6408
|
+
}
|
|
6409
|
+
};
|
|
6410
|
+
|
|
6411
|
+
const close = (adapters) => Promise.all(adapters.map((adapter) => adapter.close()));
|
|
6412
|
+
const maybeRunRecurrent = async (adapters, config) => {
|
|
6413
|
+
config.recurrentPath && await runRecurrentMigrations(
|
|
6414
|
+
adapters,
|
|
6415
|
+
config
|
|
6416
|
+
);
|
|
6417
|
+
};
|
|
6418
|
+
const rakeDbAliases$1 = {
|
|
6419
|
+
migrate: "up",
|
|
6420
|
+
rollback: "down",
|
|
6421
|
+
s: "status",
|
|
6422
|
+
rec: "recurrent"
|
|
6423
|
+
};
|
|
6424
|
+
const upCommand = {
|
|
6425
|
+
run: (adapters, config, args) => migrateCommand(adapters, config, args).then(() => maybeRunRecurrent(adapters, config)).then(() => close(adapters)),
|
|
6426
|
+
help: "migrate pending migrations",
|
|
6427
|
+
helpArguments: {
|
|
6428
|
+
"no arguments": "migrate all pending",
|
|
6429
|
+
"a number": "run a specific number of pending migrations",
|
|
6430
|
+
force: "enforce migrating a pending file in the middle"
|
|
6431
|
+
}
|
|
6432
|
+
};
|
|
6433
|
+
const downCommand = {
|
|
6434
|
+
run: (adapters, config, args) => rollbackCommand(adapters, config, args).then(() => close(adapters)),
|
|
6435
|
+
help: "rollback migrated migrations",
|
|
6436
|
+
helpArguments: {
|
|
6437
|
+
"no arguments": "rollback one last migration",
|
|
6438
|
+
"a number": "rollback a specified number",
|
|
6439
|
+
all: "rollback all migrations"
|
|
6440
|
+
}
|
|
6441
|
+
};
|
|
6442
|
+
const statusCommand = {
|
|
6443
|
+
run(adapters, config, args) {
|
|
6444
|
+
const showUrl = args.includes("p") || args.includes("path");
|
|
6445
|
+
return listMigrationsStatuses(adapters, config, { showUrl });
|
|
6446
|
+
},
|
|
6447
|
+
help: "list migrations statuses",
|
|
6448
|
+
helpArguments: {
|
|
6449
|
+
"no arguments": `does not print file paths`,
|
|
6450
|
+
"p, path": "also print file paths"
|
|
6451
|
+
}
|
|
6452
|
+
};
|
|
6453
|
+
const recurrent = {
|
|
6454
|
+
async run(adapters, config) {
|
|
6455
|
+
if (!config.recurrentPath) return;
|
|
6456
|
+
await maybeRunRecurrent(adapters, config).then(() => close(adapters));
|
|
6457
|
+
},
|
|
6458
|
+
help: "run recurrent migrations"
|
|
6459
|
+
};
|
|
6460
|
+
const rakeDbCommands = {
|
|
6461
|
+
create: {
|
|
6462
|
+
run: (adapters, config) => createDatabaseCommand(adapters, config),
|
|
6463
|
+
help: "create databases"
|
|
6464
|
+
},
|
|
6465
|
+
drop: {
|
|
6466
|
+
run: dropDatabaseCommand,
|
|
6467
|
+
help: "drop databases"
|
|
6468
|
+
},
|
|
6469
|
+
reset: {
|
|
6470
|
+
run: (adapters, config) => resetDatabaseCommand(adapters, config),
|
|
6471
|
+
help: "drop, create and migrate databases"
|
|
6472
|
+
},
|
|
6473
|
+
up: upCommand,
|
|
6474
|
+
down: downCommand,
|
|
6475
|
+
redo: {
|
|
6476
|
+
run: (adapters, config, args) => redoCommand(adapters, config, args).then(() => maybeRunRecurrent(adapters, config)).then(() => close(adapters)),
|
|
6477
|
+
help: "rollback and migrate, run recurrent"
|
|
6478
|
+
},
|
|
6479
|
+
pull: {
|
|
6480
|
+
run: ([adapter], config) => pullDbStructure(adapter, config).then(() => close([adapter])),
|
|
6481
|
+
help: "generate a combined migration for an existing database"
|
|
6482
|
+
},
|
|
6483
|
+
new: {
|
|
6484
|
+
run(_, config, args) {
|
|
6485
|
+
const [name] = args;
|
|
6486
|
+
if (!name) throw new Error("Migration name is missing");
|
|
6487
|
+
return newMigration(config, name);
|
|
6488
|
+
},
|
|
6489
|
+
help: "create new migration file"
|
|
6490
|
+
},
|
|
6491
|
+
status: statusCommand,
|
|
6492
|
+
recurrent,
|
|
6493
|
+
rebase: {
|
|
6494
|
+
run: (adapters, config) => rebase(adapters, config).then(() => close(adapters)),
|
|
6495
|
+
help: "move local migrations below the new ones from upstream"
|
|
6496
|
+
},
|
|
6497
|
+
"change-ids": {
|
|
6498
|
+
run(adapters, config, [format, digitsArg]) {
|
|
6499
|
+
if (format !== "serial" && format !== "timestamp") {
|
|
6500
|
+
throw new Error(
|
|
6501
|
+
`Pass "serial" or "timestamp" argument to the "change-ids" command`
|
|
6502
|
+
);
|
|
6503
|
+
}
|
|
6504
|
+
const digits = digitsArg ? parseInt(digitsArg) : void 0;
|
|
6505
|
+
if (digits && isNaN(digits)) {
|
|
6506
|
+
throw new Error(`Second argument is optional and must be an integer`);
|
|
6382
6507
|
}
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6508
|
+
return changeIds(adapters, config, { format, digits });
|
|
6509
|
+
},
|
|
6510
|
+
help: "change migrations ids format",
|
|
6511
|
+
helpArguments: {
|
|
6512
|
+
serial: "change ids to 4 digit serial",
|
|
6513
|
+
"serial *number*": "change ids to serial number of custom length",
|
|
6514
|
+
timestamp: "change timestamps"
|
|
6386
6515
|
}
|
|
6387
6516
|
}
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
)
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
const
|
|
6517
|
+
};
|
|
6518
|
+
for (const key in rakeDbAliases$1) {
|
|
6519
|
+
const command = rakeDbAliases$1[key];
|
|
6520
|
+
if (command) rakeDbCommands[key] = rakeDbCommands[command];
|
|
6521
|
+
}
|
|
6522
|
+
let intermediateCallers = 0;
|
|
6523
|
+
const incrementIntermediateCaller = () => {
|
|
6524
|
+
intermediateCallers++;
|
|
6525
|
+
};
|
|
6526
|
+
const ensureBasePathAndDbScript = (config, intermediateCallers2 = 0) => {
|
|
6527
|
+
if (config.basePath && config.dbScript) return config;
|
|
6528
|
+
let filePath = internal.getStackTrace()?.[3 + intermediateCallers2]?.getFileName();
|
|
6529
|
+
if (!filePath) {
|
|
6530
|
+
throw new Error(
|
|
6531
|
+
"Failed to determine path to db script. Please set basePath option of rakeDb"
|
|
6532
|
+
);
|
|
6533
|
+
}
|
|
6534
|
+
if (filePath.startsWith("file://")) {
|
|
6535
|
+
filePath = node_url.fileURLToPath(filePath);
|
|
6536
|
+
}
|
|
6537
|
+
const ext = path.extname(filePath);
|
|
6538
|
+
if (ext !== ".ts" && ext !== ".js" && ext !== ".mjs") {
|
|
6539
|
+
throw new Error(
|
|
6540
|
+
`Add a .ts suffix to the "${path.basename(filePath)}" when calling it`
|
|
6541
|
+
);
|
|
6542
|
+
}
|
|
6543
|
+
config.basePath = path.dirname(filePath);
|
|
6544
|
+
config.dbScript = path.basename(filePath);
|
|
6545
|
+
return config;
|
|
6546
|
+
};
|
|
6547
|
+
const makeRakeDbConfig = (config, args) => {
|
|
6548
|
+
const ic = intermediateCallers;
|
|
6549
|
+
intermediateCallers = 0;
|
|
6550
|
+
const result = {
|
|
6551
|
+
...rakeDbConfigDefaults,
|
|
6420
6552
|
...config,
|
|
6421
|
-
|
|
6422
|
-
set.migrations = migrationsUp;
|
|
6423
|
-
},
|
|
6424
|
-
async afterMigrate() {
|
|
6425
|
-
set.migrations = migrationsDown;
|
|
6426
|
-
}
|
|
6553
|
+
__rakeDbConfig: true
|
|
6427
6554
|
};
|
|
6428
|
-
|
|
6429
|
-
|
|
6555
|
+
ensureBasePathAndDbScript(result, ic);
|
|
6556
|
+
Object.assign(result, processMigrateConfig(result));
|
|
6557
|
+
if (!result.recurrentPath && result.migrationsPath) {
|
|
6558
|
+
result.recurrentPath = path.join(result.migrationsPath, "recurrent");
|
|
6430
6559
|
}
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6560
|
+
if (result.recurrentPath && !path.isAbsolute(result.recurrentPath)) {
|
|
6561
|
+
result.recurrentPath = path.resolve(result.basePath, result.recurrentPath);
|
|
6562
|
+
}
|
|
6563
|
+
if ("baseTable" in config && config.baseTable) {
|
|
6564
|
+
const { types, snakeCase, language } = config.baseTable.prototype;
|
|
6565
|
+
result.columnTypes = types || internal.makeColumnTypes(internal.defaultSchemaConfig);
|
|
6566
|
+
if (snakeCase) result.snakeCase = true;
|
|
6567
|
+
if (language) result.language = language;
|
|
6568
|
+
} else {
|
|
6569
|
+
const ct = "columnTypes" in config && config.columnTypes;
|
|
6570
|
+
result.columnTypes = (typeof ct === "function" ? ct(
|
|
6571
|
+
internal.makeColumnTypes(internal.defaultSchemaConfig)
|
|
6572
|
+
) : ct) || internal.makeColumnTypes(internal.defaultSchemaConfig);
|
|
6573
|
+
}
|
|
6574
|
+
if (config.migrationId === "serial") {
|
|
6575
|
+
result.migrationId = { serial: 4 };
|
|
6576
|
+
}
|
|
6577
|
+
const transaction = getCliParam(args, "transaction");
|
|
6578
|
+
if (transaction) {
|
|
6579
|
+
if (transaction !== "single" && transaction !== "per-migration") {
|
|
6580
|
+
throw new Error(
|
|
6581
|
+
`Unsupported transaction param ${transaction}, expected single or per-migration`
|
|
6582
|
+
);
|
|
6583
|
+
}
|
|
6584
|
+
result.transaction = transaction;
|
|
6585
|
+
} else if (!result.transaction) {
|
|
6586
|
+
result.transaction = "single";
|
|
6587
|
+
}
|
|
6588
|
+
let c = rakeDbCommands;
|
|
6589
|
+
if (config.commands) {
|
|
6590
|
+
c = { ...c };
|
|
6591
|
+
const commands = config.commands;
|
|
6592
|
+
for (const key in commands) {
|
|
6593
|
+
const command = commands[key];
|
|
6594
|
+
c[key] = typeof command === "function" ? { run: command } : command;
|
|
6595
|
+
}
|
|
6441
6596
|
}
|
|
6597
|
+
result.commands = c;
|
|
6598
|
+
return result;
|
|
6442
6599
|
};
|
|
6443
6600
|
|
|
6444
6601
|
const rakeDbAliases = {
|
|
@@ -6456,9 +6613,9 @@ const rakeDbCliWithAdapter = (inputConfig, args = process.argv.slice(2)) => {
|
|
|
6456
6613
|
config = makeRakeDbConfig(inputConfig, args);
|
|
6457
6614
|
}
|
|
6458
6615
|
return {
|
|
6459
|
-
change:
|
|
6616
|
+
change: createMigrationChangeFn(config),
|
|
6460
6617
|
async run(adapter, runArgs) {
|
|
6461
|
-
const adapters =
|
|
6618
|
+
const adapters = internal.toArray(adapter);
|
|
6462
6619
|
try {
|
|
6463
6620
|
await runCommand(adapters, config, runArgs || args);
|
|
6464
6621
|
} catch (err) {
|
|
@@ -6550,120 +6707,16 @@ ${Object.entries(helpArguments).map(
|
|
|
6550
6707
|
`);
|
|
6551
6708
|
}
|
|
6552
6709
|
};
|
|
6553
|
-
const close = (adapters) => Promise.all(adapters.map((adapter) => adapter.close()));
|
|
6554
|
-
const maybeRunRecurrent = async (adapters, config) => {
|
|
6555
|
-
config.recurrentPath && await runRecurrentMigrations(
|
|
6556
|
-
adapters,
|
|
6557
|
-
config
|
|
6558
|
-
);
|
|
6559
|
-
};
|
|
6560
|
-
const upCommand = {
|
|
6561
|
-
run: (adapters, config, args) => migrateCommand(adapters, config, args).then(() => maybeRunRecurrent(adapters, config)).then(() => close(adapters)),
|
|
6562
|
-
help: "migrate pending migrations",
|
|
6563
|
-
helpArguments: {
|
|
6564
|
-
"no arguments": "migrate all pending",
|
|
6565
|
-
"a number": "run a specific number of pending migrations",
|
|
6566
|
-
force: "enforce migrating a pending file in the middle"
|
|
6567
|
-
}
|
|
6568
|
-
};
|
|
6569
|
-
const downCommand = {
|
|
6570
|
-
run: (adapters, config, args) => rollbackCommand(adapters, config, args).then(() => close(adapters)),
|
|
6571
|
-
help: "rollback migrated migrations",
|
|
6572
|
-
helpArguments: {
|
|
6573
|
-
"no arguments": "rollback one last migration",
|
|
6574
|
-
"a number": "rollback a specified number",
|
|
6575
|
-
all: "rollback all migrations"
|
|
6576
|
-
}
|
|
6577
|
-
};
|
|
6578
|
-
const statusCommand = {
|
|
6579
|
-
run(adapters, config, args) {
|
|
6580
|
-
const showUrl = args.includes("p") || args.includes("path");
|
|
6581
|
-
return listMigrationsStatuses(adapters, config, { showUrl });
|
|
6582
|
-
},
|
|
6583
|
-
help: "list migrations statuses",
|
|
6584
|
-
helpArguments: {
|
|
6585
|
-
"no arguments": `does not print file paths`,
|
|
6586
|
-
"p, path": "also print file paths"
|
|
6587
|
-
}
|
|
6588
|
-
};
|
|
6589
|
-
const recurrent = {
|
|
6590
|
-
async run(adapters, config) {
|
|
6591
|
-
if (!config.recurrentPath) return;
|
|
6592
|
-
await maybeRunRecurrent(adapters, config).then(() => close(adapters));
|
|
6593
|
-
},
|
|
6594
|
-
help: "run recurrent migrations"
|
|
6595
|
-
};
|
|
6596
|
-
const rakeDbCommands = {
|
|
6597
|
-
create: {
|
|
6598
|
-
run: (adapters, config) => createDatabaseCommand(adapters, config),
|
|
6599
|
-
help: "create databases"
|
|
6600
|
-
},
|
|
6601
|
-
drop: {
|
|
6602
|
-
run: dropDatabaseCommand,
|
|
6603
|
-
help: "drop databases"
|
|
6604
|
-
},
|
|
6605
|
-
reset: {
|
|
6606
|
-
run: (adapters, config) => resetDatabaseCommand(adapters, config),
|
|
6607
|
-
help: "drop, create and migrate databases"
|
|
6608
|
-
},
|
|
6609
|
-
up: upCommand,
|
|
6610
|
-
down: downCommand,
|
|
6611
|
-
redo: {
|
|
6612
|
-
run: (adapters, config, args) => redoCommand(adapters, config, args).then(() => maybeRunRecurrent(adapters, config)).then(() => close(adapters)),
|
|
6613
|
-
help: "rollback and migrate, run recurrent"
|
|
6614
|
-
},
|
|
6615
|
-
pull: {
|
|
6616
|
-
run: ([adapter], config) => pullDbStructure(adapter, config).then(() => close([adapter])),
|
|
6617
|
-
help: "generate a combined migration for an existing database"
|
|
6618
|
-
},
|
|
6619
|
-
new: {
|
|
6620
|
-
run(_, config, args) {
|
|
6621
|
-
const [name] = args;
|
|
6622
|
-
if (!name) throw new Error("Migration name is missing");
|
|
6623
|
-
return newMigration(config, name);
|
|
6624
|
-
},
|
|
6625
|
-
help: "create new migration file"
|
|
6626
|
-
},
|
|
6627
|
-
status: statusCommand,
|
|
6628
|
-
recurrent,
|
|
6629
|
-
rebase: {
|
|
6630
|
-
run: (adapters, config) => rebase(adapters, config).then(() => close(adapters)),
|
|
6631
|
-
help: "move local migrations below the new ones from upstream"
|
|
6632
|
-
},
|
|
6633
|
-
"change-ids": {
|
|
6634
|
-
run(adapters, config, [format, digitsArg]) {
|
|
6635
|
-
if (format !== "serial" && format !== "timestamp") {
|
|
6636
|
-
throw new Error(
|
|
6637
|
-
`Pass "serial" or "timestamp" argument to the "change-ids" command`
|
|
6638
|
-
);
|
|
6639
|
-
}
|
|
6640
|
-
const digits = digitsArg ? parseInt(digitsArg) : void 0;
|
|
6641
|
-
if (digits && isNaN(digits)) {
|
|
6642
|
-
throw new Error(`Second argument is optional and must be an integer`);
|
|
6643
|
-
}
|
|
6644
|
-
return changeIds(adapters, config, { format, digits });
|
|
6645
|
-
},
|
|
6646
|
-
help: "change migrations ids format",
|
|
6647
|
-
helpArguments: {
|
|
6648
|
-
serial: "change ids to 4 digit serial",
|
|
6649
|
-
"serial *number*": "change ids to serial number of custom length",
|
|
6650
|
-
timestamp: "change ids to timestamps"
|
|
6651
|
-
}
|
|
6652
|
-
}
|
|
6653
|
-
};
|
|
6654
|
-
for (const key in rakeDbAliases) {
|
|
6655
|
-
const command = rakeDbAliases[key];
|
|
6656
|
-
if (command) rakeDbCommands[key] = rakeDbCommands[command];
|
|
6657
|
-
}
|
|
6658
6710
|
|
|
6659
6711
|
exports.RakeDbError = RakeDbError;
|
|
6660
6712
|
exports.astToMigration = astToMigration;
|
|
6661
6713
|
exports.concatSchemaAndName = concatSchemaAndName;
|
|
6662
6714
|
exports.createDatabase = createDatabase;
|
|
6715
|
+
exports.createMigrationChangeFn = createMigrationChangeFn;
|
|
6663
6716
|
exports.createMigrationInterface = createMigrationInterface;
|
|
6664
6717
|
exports.createMigrationsSchemaAndTable = createMigrationsSchemaAndTable;
|
|
6665
|
-
exports.createSchema = createSchema
|
|
6666
|
-
exports.createTable = createTable
|
|
6718
|
+
exports.createSchema = createSchema;
|
|
6719
|
+
exports.createTable = createTable;
|
|
6667
6720
|
exports.dbColumnToAst = dbColumnToAst;
|
|
6668
6721
|
exports.dropDatabase = dropDatabase;
|
|
6669
6722
|
exports.dropSchema = dropSchema;
|
|
@@ -6682,14 +6735,13 @@ exports.instantiateDbColumn = instantiateDbColumn;
|
|
|
6682
6735
|
exports.introspectDbSchema = introspectDbSchema;
|
|
6683
6736
|
exports.makeDomainsMap = makeDomainsMap;
|
|
6684
6737
|
exports.makeFileVersion = makeFileVersion;
|
|
6685
|
-
exports.makeRakeDbConfig = makeRakeDbConfig;
|
|
6686
6738
|
exports.makeStructureToAstCtx = makeStructureToAstCtx;
|
|
6687
6739
|
exports.migrate = migrate;
|
|
6688
6740
|
exports.migrateAndClose = migrateAndClose;
|
|
6689
|
-
exports.migrationConfigDefaults = migrationConfigDefaults;
|
|
6690
6741
|
exports.promptSelect = promptSelect;
|
|
6691
6742
|
exports.rakeDbCliWithAdapter = rakeDbCliWithAdapter;
|
|
6692
6743
|
exports.rakeDbCommands = rakeDbCommands;
|
|
6744
|
+
exports.rakeDbConfigDefaults = rakeDbConfigDefaults;
|
|
6693
6745
|
exports.redo = redo;
|
|
6694
6746
|
exports.rollback = rollback;
|
|
6695
6747
|
exports.runMigration = runMigration;
|