rake-db 2.28.1 → 2.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +281 -308
- package/dist/index.js +978 -826
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +974 -823
- package/dist/index.mjs.map +1 -1
- package/dist/node-postgres.d.ts +2 -6
- package/dist/node-postgres.js +10 -36
- package/dist/node-postgres.js.map +1 -1
- package/dist/node-postgres.mjs +11 -36
- package/dist/node-postgres.mjs.map +1 -1
- package/dist/postgres-js.d.ts +3 -7
- package/dist/postgres-js.js +10 -36
- package/dist/postgres-js.js.map +1 -1
- package/dist/postgres-js.mjs +11 -36
- package/dist/postgres-js.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,19 +1,250 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { colors, singleQuote, isRawSQL, escapeForMigration, ArrayColumn, toSnakeCase, toCamelCase, DomainColumn, toArray, EnumColumn, defaultSchemaConfig, snakeCaseKey, getColumnTypes, parseTableData, emptyObject, escapeString, tableDataMethods, setCurrentColumnName, consumeColumnName, Column, parseTableDataInput, UnknownColumn, setDefaultLanguage, deepCompare, raw, logParamToLogObject, createDbWithAdapter, getImportPath, pathToLog, emptyArray, exhaustive, codeToString, addCode, quoteObjectKey, pushTableDataCode, rawSqlToCode, primaryKeyInnerToCode, indexInnerToCode, excludeInnerToCode, constraintInnerToCode, referencesArgsToCode, backtickQuote, TimestampTZColumn, TimestampColumn, makeColumnsByType, RawSql, CustomTypeColumn, assignDbDataToColumn, PostgisGeographyPointColumn, makeColumnTypes, getStackTrace } from 'pqb';
|
|
2
2
|
import path, { join } from 'path';
|
|
3
|
-
import {
|
|
3
|
+
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
4
4
|
import fs, { mkdir, writeFile, readdir, stat, readFile } from 'fs/promises';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
}
|
|
6
|
+
const ESC = "\x1B";
|
|
7
|
+
const CSI = `${ESC}[`;
|
|
8
|
+
const cursorShow = `${CSI}?25h`;
|
|
9
|
+
const cursorHide = `${CSI}?25l`;
|
|
10
|
+
const { stdin, stdout } = process;
|
|
11
|
+
const visibleChars = (s) => s.replace(
|
|
12
|
+
// eslint-disable-next-line no-control-regex
|
|
13
|
+
/[\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,
|
|
14
|
+
""
|
|
15
|
+
).length;
|
|
16
|
+
const clear = (text) => {
|
|
17
|
+
const rows = text.split(/\r?\n/).reduce(
|
|
18
|
+
(rows2, line) => rows2 + 1 + Math.floor(Math.max(visibleChars(line) - 1, 0) / stdout.columns),
|
|
19
|
+
0
|
|
20
|
+
);
|
|
21
|
+
let clear2 = "";
|
|
22
|
+
for (let i = 0; i < rows; i++) {
|
|
23
|
+
clear2 += `${CSI}2K`;
|
|
24
|
+
if (i < rows - 1) {
|
|
25
|
+
clear2 += `${CSI}${i < rows - 1 ? "1A" : "G"}`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return clear2;
|
|
29
|
+
};
|
|
30
|
+
const prompt = async ({
|
|
31
|
+
render,
|
|
32
|
+
onKeyPress,
|
|
33
|
+
validate,
|
|
34
|
+
value,
|
|
35
|
+
cursor: showCursor
|
|
36
|
+
}) => {
|
|
37
|
+
stdin.resume();
|
|
38
|
+
if (stdin.isTTY) stdin.setRawMode(true);
|
|
39
|
+
stdin.setEncoding("utf-8");
|
|
40
|
+
if (!showCursor) stdout.write(cursorHide);
|
|
41
|
+
return new Promise((res) => {
|
|
42
|
+
let prevText;
|
|
43
|
+
const ctx = {
|
|
44
|
+
value,
|
|
45
|
+
submitted: false,
|
|
46
|
+
render() {
|
|
47
|
+
let text = (ctx.submitted ? colors.greenBold("\u2714") : colors.yellowBold("?")) + " " + render(ctx);
|
|
48
|
+
if (ctx.submitted) text += "\n";
|
|
49
|
+
stdout.write(prevText ? clear(prevText) + "\r" + text : text);
|
|
50
|
+
prevText = text;
|
|
51
|
+
},
|
|
52
|
+
submit(value2) {
|
|
53
|
+
if (value2 !== void 0) ctx.value = value2;
|
|
54
|
+
if (ctx.value === void 0 || validate && !validate?.(ctx)) return;
|
|
55
|
+
ctx.submitted = true;
|
|
56
|
+
ctx.render();
|
|
57
|
+
close();
|
|
58
|
+
res(ctx.value);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const close = () => {
|
|
62
|
+
if (!showCursor) stdout.write(cursorShow);
|
|
63
|
+
if (stdin.isTTY) stdin.setRawMode(false);
|
|
64
|
+
stdin.off("data", keypress);
|
|
65
|
+
stdin.pause();
|
|
66
|
+
};
|
|
67
|
+
const keypress = (s) => {
|
|
68
|
+
if (s === "" || s === "") {
|
|
69
|
+
close?.();
|
|
70
|
+
process.exit(0);
|
|
71
|
+
}
|
|
72
|
+
if (s === "\r" || s === "\n" || s === "\r\n") {
|
|
73
|
+
ctx.submit();
|
|
74
|
+
} else {
|
|
75
|
+
onKeyPress(ctx, s);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
stdin.on("data", keypress);
|
|
79
|
+
ctx.render();
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
const defaultActive = (s) => `${colors.blueBold("\u276F")} ${s}`;
|
|
83
|
+
const defaultInactive = (s) => ` ${s}`;
|
|
84
|
+
const promptSelect = ({
|
|
85
|
+
message,
|
|
86
|
+
options,
|
|
87
|
+
active = defaultActive,
|
|
88
|
+
inactive = defaultInactive
|
|
89
|
+
}) => prompt({
|
|
90
|
+
value: 0,
|
|
91
|
+
render(ctx) {
|
|
92
|
+
let text = `${message} ${colors.pale(
|
|
93
|
+
"Use arrows or jk. Press enter to submit."
|
|
94
|
+
)}
|
|
95
|
+
`;
|
|
96
|
+
for (let i = 0; i < options.length; i++) {
|
|
97
|
+
text += (ctx.value === i ? active : inactive)(options[i]) + "\n";
|
|
98
|
+
}
|
|
99
|
+
return text;
|
|
100
|
+
},
|
|
101
|
+
onKeyPress(ctx, s) {
|
|
102
|
+
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;
|
|
103
|
+
ctx.render();
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
const promptConfirm = ({
|
|
107
|
+
message
|
|
108
|
+
}) => prompt({
|
|
109
|
+
value: true,
|
|
110
|
+
render(ctx) {
|
|
111
|
+
return `${colors.bright(message)}
|
|
112
|
+
${ctx.submitted ? `> ${ctx.value ? colors.greenBold("Yes") : colors.yellowBold("No")}` : colors.pale(`> (Y/n)`)}
|
|
113
|
+
`;
|
|
114
|
+
},
|
|
115
|
+
onKeyPress(ctx, s) {
|
|
116
|
+
let ok;
|
|
117
|
+
if (s === "y" || s === "Y") ok = true;
|
|
118
|
+
else if (s === "n" || s === "N") ok = false;
|
|
119
|
+
if (ok !== void 0) {
|
|
120
|
+
ctx.submit(ok);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
const promptText = ({
|
|
125
|
+
message,
|
|
126
|
+
default: def = "",
|
|
127
|
+
password,
|
|
128
|
+
min
|
|
129
|
+
}) => {
|
|
130
|
+
let showDefault = true;
|
|
131
|
+
let x = 0;
|
|
132
|
+
const renderValue = (ctx) => password ? "*".repeat(ctx.value.length) : ctx.value;
|
|
133
|
+
return prompt({
|
|
134
|
+
value: def,
|
|
135
|
+
cursor: true,
|
|
136
|
+
validate: (ctx) => !min || ctx.value.length >= min,
|
|
137
|
+
render(ctx) {
|
|
138
|
+
let text = `${colors.bright(message)}
|
|
139
|
+
> ${ctx.submitted ? renderValue(ctx) : showDefault ? colors.pale(def) + "\b".repeat(def.length) : ctx.value}`;
|
|
140
|
+
if (ctx.submitted) text += "\n";
|
|
141
|
+
return text;
|
|
142
|
+
},
|
|
143
|
+
onKeyPress(ctx, s) {
|
|
144
|
+
let value = showDefault ? "" : ctx.value;
|
|
145
|
+
if (s === "\x1B[D" && x > 0) {
|
|
146
|
+
x--;
|
|
147
|
+
stdout.write("\b");
|
|
148
|
+
} else if (s === "\x1B[C" && x < value.length) {
|
|
149
|
+
stdout.write(value[x]);
|
|
150
|
+
x++;
|
|
151
|
+
}
|
|
152
|
+
if (s !== "\x7F" && s !== "\x1B[3~" && !visibleChars(s)) return;
|
|
153
|
+
if (showDefault) {
|
|
154
|
+
showDefault = false;
|
|
155
|
+
stdout.write(" ".repeat(def.length) + "\b".repeat(def.length));
|
|
156
|
+
}
|
|
157
|
+
const prev = value;
|
|
158
|
+
const prevX = x;
|
|
159
|
+
if (s === "\x7F") {
|
|
160
|
+
if (x > 0) {
|
|
161
|
+
value = value.slice(0, x - 1) + value.slice(x);
|
|
162
|
+
x--;
|
|
163
|
+
}
|
|
164
|
+
} else if (s === "\x1B[3~") {
|
|
165
|
+
if (x < value.length) {
|
|
166
|
+
value = value.slice(0, x) + value.slice(x + 1);
|
|
167
|
+
}
|
|
168
|
+
} else {
|
|
169
|
+
value = value.slice(0, x) + s + value.slice(x);
|
|
170
|
+
x++;
|
|
171
|
+
}
|
|
172
|
+
ctx.value = value;
|
|
173
|
+
const spaces = prev.length - value.length;
|
|
174
|
+
stdout.write(
|
|
175
|
+
"\b".repeat(prevX) + renderValue(ctx) + (spaces > 0 ? " ".repeat(spaces) + "\b".repeat(spaces) : "") + "\b".repeat(value.length - x)
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
};
|
|
10
180
|
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
181
|
+
const getNonTransactionAdapter = (db) => "$adapter" in db ? db.$adapter : db;
|
|
182
|
+
const getMaybeTransactionAdapter = (db) => "$qb" in db ? db.$qb.internal.transactionStorage.getStore()?.adapter || db.$adapter : db;
|
|
183
|
+
const ensureTransaction = (db, fn) => {
|
|
184
|
+
const adapter = getMaybeTransactionAdapter(db);
|
|
185
|
+
return adapter.isInTransaction() ? fn(adapter) : adapter.transaction(void 0, fn);
|
|
186
|
+
};
|
|
187
|
+
const runSqlInSavePoint = async (db, sql, code) => {
|
|
188
|
+
const adapter = getMaybeTransactionAdapter(db);
|
|
189
|
+
try {
|
|
190
|
+
await adapter.query(
|
|
191
|
+
adapter.isInTransaction() ? `SAVEPOINT s; ${sql}; RELEASE SAVEPOINT s` : sql
|
|
192
|
+
);
|
|
193
|
+
return "done";
|
|
194
|
+
} catch (err) {
|
|
195
|
+
if (err.code === code) {
|
|
196
|
+
if (adapter.isInTransaction()) {
|
|
197
|
+
await adapter.query(`ROLLBACK TO SAVEPOINT s`);
|
|
198
|
+
}
|
|
199
|
+
return "already";
|
|
200
|
+
}
|
|
201
|
+
throw err;
|
|
202
|
+
}
|
|
14
203
|
};
|
|
15
|
-
|
|
16
|
-
|
|
204
|
+
|
|
205
|
+
class CreateOrDropError extends Error {
|
|
206
|
+
constructor(message, status, cause) {
|
|
207
|
+
super(message);
|
|
208
|
+
this.status = status;
|
|
209
|
+
this.cause = cause;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const createDatabase = async (db, {
|
|
213
|
+
database,
|
|
214
|
+
owner
|
|
215
|
+
}) => {
|
|
216
|
+
return createOrDrop(
|
|
217
|
+
db,
|
|
218
|
+
`CREATE DATABASE "${database}"${owner ? ` OWNER "${owner}"` : ""}`
|
|
219
|
+
);
|
|
220
|
+
};
|
|
221
|
+
const dropDatabase = async (db, { database }) => {
|
|
222
|
+
return createOrDrop(db, `DROP DATABASE "${database}"`);
|
|
223
|
+
};
|
|
224
|
+
const createOrDrop = async (db, sql) => {
|
|
225
|
+
try {
|
|
226
|
+
const adapter = getNonTransactionAdapter(db);
|
|
227
|
+
await adapter.query(sql);
|
|
228
|
+
return "done";
|
|
229
|
+
} catch (error) {
|
|
230
|
+
const err = error;
|
|
231
|
+
if (typeof err.message === "string" && err.message.includes("sslmode=require")) {
|
|
232
|
+
throw new CreateOrDropError("SSL required", "ssl-required", err);
|
|
233
|
+
}
|
|
234
|
+
if (err.code === "42P04" || err.code === "3D000") {
|
|
235
|
+
return "already";
|
|
236
|
+
}
|
|
237
|
+
if (err.code === "42501") {
|
|
238
|
+
throw new CreateOrDropError("Insufficient privilege", "forbidden", err);
|
|
239
|
+
}
|
|
240
|
+
if (typeof err.message === "string" && err.message.includes("password authentication failed")) {
|
|
241
|
+
throw new CreateOrDropError("Authentication failed", "auth-failed", err);
|
|
242
|
+
}
|
|
243
|
+
throw err;
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
const createSchema$1 = async (db, sql) => runSqlInSavePoint(db, `CREATE SCHEMA ${sql}`, "42P06");
|
|
247
|
+
const createTable$1 = async (db, sql) => runSqlInSavePoint(db, `CREATE TABLE ${sql}`, "42P07");
|
|
17
248
|
|
|
18
249
|
const RAKE_DB_LOCK_KEY = "8582141715823621641";
|
|
19
250
|
const getFirstWordAndRest = (input) => {
|
|
@@ -49,15 +280,18 @@ const quoteWithSchema = ({
|
|
|
49
280
|
name
|
|
50
281
|
}) => quoteTable(schema, name);
|
|
51
282
|
const quoteTable = (schema, table) => schema ? `"${schema}"."${table}"` : `"${table}"`;
|
|
52
|
-
const getSchemaAndTableFromName = (name) => {
|
|
283
|
+
const getSchemaAndTableFromName = (config, name) => {
|
|
53
284
|
const i = name.indexOf(".");
|
|
54
|
-
return i !== -1 ? [name.slice(0, i), name.slice(i + 1)] : [
|
|
285
|
+
return i !== -1 ? [name.slice(0, i), name.slice(i + 1)] : [
|
|
286
|
+
typeof config.schema === "function" ? config.schema() : config.schema,
|
|
287
|
+
name
|
|
288
|
+
];
|
|
55
289
|
};
|
|
56
|
-
const quoteNameFromString = (string) => {
|
|
57
|
-
return quoteTable(...getSchemaAndTableFromName(string));
|
|
290
|
+
const quoteNameFromString = (config, string) => {
|
|
291
|
+
return quoteTable(...getSchemaAndTableFromName(config, string));
|
|
58
292
|
};
|
|
59
|
-
const quoteCustomType = (s) => {
|
|
60
|
-
const [schema, type] = getSchemaAndTableFromName(s);
|
|
293
|
+
const quoteCustomType = (config, s) => {
|
|
294
|
+
const [schema, type] = getSchemaAndTableFromName(config, s);
|
|
61
295
|
return schema ? '"' + schema + '".' + type : type;
|
|
62
296
|
};
|
|
63
297
|
const quoteSchemaTable = (arg, excludeCurrentSchema) => {
|
|
@@ -69,8 +303,8 @@ const concatSchemaAndName = ({
|
|
|
69
303
|
}, excludeCurrentSchema) => {
|
|
70
304
|
return schema && schema !== excludeCurrentSchema ? `${schema}.${name}` : name;
|
|
71
305
|
};
|
|
72
|
-
const makePopulateEnumQuery = (item) => {
|
|
73
|
-
const [schema, name] = getSchemaAndTableFromName(item.enumName);
|
|
306
|
+
const makePopulateEnumQuery = (config, item) => {
|
|
307
|
+
const [schema, name] = getSchemaAndTableFromName(config, item.enumName);
|
|
74
308
|
return {
|
|
75
309
|
text: `SELECT unnest(enum_range(NULL::${quoteTable(schema, name)}))::text`,
|
|
76
310
|
then(result) {
|
|
@@ -94,115 +328,35 @@ const getCliParam = (args, name) => {
|
|
|
94
328
|
return;
|
|
95
329
|
};
|
|
96
330
|
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
migrationsTable: "schemaMigrations",
|
|
102
|
-
snakeCase: false,
|
|
103
|
-
commands: {},
|
|
104
|
-
log: true,
|
|
105
|
-
logger: console,
|
|
106
|
-
import() {
|
|
107
|
-
throw new Error(
|
|
108
|
-
"Add `import: (path) => import(path),` setting to `rakeDb` config"
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
const ensureMigrationsPath = (config) => {
|
|
113
|
-
if (!config.migrationsPath) {
|
|
114
|
-
config.migrationsPath = migrationConfigDefaults.migrationsPath;
|
|
115
|
-
}
|
|
116
|
-
if (!path.isAbsolute(config.migrationsPath)) {
|
|
117
|
-
config.migrationsPath = path.resolve(
|
|
118
|
-
config.basePath,
|
|
119
|
-
config.migrationsPath
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
return config;
|
|
123
|
-
};
|
|
124
|
-
const ensureBasePathAndDbScript = (config, intermediateCallers = 0) => {
|
|
125
|
-
if (config.basePath && config.dbScript) return config;
|
|
126
|
-
let filePath = getStackTrace()?.[3 + intermediateCallers]?.getFileName();
|
|
127
|
-
if (!filePath) {
|
|
128
|
-
throw new Error(
|
|
129
|
-
"Failed to determine path to db script. Please set basePath option of rakeDb"
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
if (filePath.startsWith("file://")) {
|
|
133
|
-
filePath = fileURLToPath(filePath);
|
|
134
|
-
}
|
|
135
|
-
const ext = path.extname(filePath);
|
|
136
|
-
if (ext !== ".ts" && ext !== ".js" && ext !== ".mjs") {
|
|
137
|
-
throw new Error(
|
|
138
|
-
`Add a .ts suffix to the "${path.basename(filePath)}" when calling it`
|
|
139
|
-
);
|
|
140
|
-
}
|
|
141
|
-
config.basePath = path.dirname(filePath);
|
|
142
|
-
config.dbScript = path.basename(filePath);
|
|
143
|
-
return config;
|
|
331
|
+
const makeChange = (config) => (fn) => {
|
|
332
|
+
const change = { fn, config };
|
|
333
|
+
pushChange(change);
|
|
334
|
+
return change;
|
|
144
335
|
};
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
delete result.logger;
|
|
149
|
-
}
|
|
150
|
-
ensureBasePathAndDbScript(result, 1);
|
|
151
|
-
ensureMigrationsPath(result);
|
|
152
|
-
if (!result.recurrentPath) {
|
|
153
|
-
result.recurrentPath = path.join(
|
|
154
|
-
result.migrationsPath,
|
|
155
|
-
"recurrent"
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
if ("recurrentPath" in result && !path.isAbsolute(result.recurrentPath)) {
|
|
159
|
-
result.recurrentPath = path.resolve(result.basePath, result.recurrentPath);
|
|
160
|
-
}
|
|
161
|
-
if ("baseTable" in config && config.baseTable) {
|
|
162
|
-
const { types, snakeCase, language } = config.baseTable.prototype;
|
|
163
|
-
result.columnTypes = types || makeColumnTypes(defaultSchemaConfig);
|
|
164
|
-
if (snakeCase) result.snakeCase = true;
|
|
165
|
-
if (language) result.language = language;
|
|
166
|
-
} else {
|
|
167
|
-
const ct = "columnTypes" in config && config.columnTypes;
|
|
168
|
-
result.columnTypes = (typeof ct === "function" ? ct(
|
|
169
|
-
makeColumnTypes(defaultSchemaConfig)
|
|
170
|
-
) : ct) || makeColumnTypes(defaultSchemaConfig);
|
|
171
|
-
}
|
|
172
|
-
if (config.migrationId === "serial") {
|
|
173
|
-
result.migrationId = { serial: 4 };
|
|
174
|
-
}
|
|
175
|
-
const transaction = getCliParam(args, "transaction");
|
|
176
|
-
if (transaction) {
|
|
177
|
-
if (transaction !== "single" && transaction !== "per-migration") {
|
|
178
|
-
throw new Error(
|
|
179
|
-
`Unsupported transaction param ${transaction}, expected single or per-migration`
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
result.transaction = transaction;
|
|
183
|
-
} else if (!result.transaction) {
|
|
184
|
-
result.transaction = "single";
|
|
185
|
-
}
|
|
186
|
-
return result;
|
|
336
|
+
let currentChanges = [];
|
|
337
|
+
const clearChanges = () => {
|
|
338
|
+
currentChanges = [];
|
|
187
339
|
};
|
|
340
|
+
const getCurrentChanges = () => currentChanges;
|
|
341
|
+
const pushChange = (change) => currentChanges.push(change);
|
|
188
342
|
|
|
189
343
|
const versionToString = (config, version) => config.migrationId === "timestamp" ? `${version}` : `${version}`.padStart(config.migrationId.serial, "0");
|
|
190
|
-
const columnTypeToSql = (item) => {
|
|
191
|
-
return item.data.isOfCustomType ? item instanceof DomainColumn ? quoteNameFromString(item.dataType) : quoteCustomType(item.toSQL()) : item.toSQL();
|
|
344
|
+
const columnTypeToSql = (config, item) => {
|
|
345
|
+
return item.data.isOfCustomType ? item instanceof DomainColumn ? quoteNameFromString(config, item.dataType) : quoteCustomType(config, item.toSQL()) : item.toSQL();
|
|
192
346
|
};
|
|
193
347
|
const getColumnName = (item, key, snakeCase) => {
|
|
194
348
|
return item.data.name || (snakeCase ? toSnakeCase(key) : key);
|
|
195
349
|
};
|
|
196
|
-
const columnToSql = (name, item, values, hasMultiplePrimaryKeys, snakeCase) => {
|
|
197
|
-
const line = [`"${name}" ${columnTypeToSql(item)}`];
|
|
350
|
+
const columnToSql = (config, name, item, values, hasMultiplePrimaryKeys, snakeCase) => {
|
|
351
|
+
const line = [`"${name}" ${columnTypeToSql(config, item)}`];
|
|
198
352
|
if (item.data.compression) {
|
|
199
353
|
line.push(`COMPRESSION ${item.data.compression}`);
|
|
200
354
|
}
|
|
201
355
|
if (item.data.collate) {
|
|
202
|
-
line.push(`COLLATE ${quoteNameFromString(item.data.collate)}`);
|
|
356
|
+
line.push(`COLLATE ${quoteNameFromString(config, item.data.collate)}`);
|
|
203
357
|
}
|
|
204
358
|
if (item.data.identity) {
|
|
205
|
-
line.push(identityToSql(item.data.identity));
|
|
359
|
+
line.push(identityToSql(config, item.data.identity));
|
|
206
360
|
} else if (item.data.generated) {
|
|
207
361
|
line.push(
|
|
208
362
|
`GENERATED ALWAYS AS (${item.data.generated.toSQL({
|
|
@@ -236,6 +390,7 @@ const columnToSql = (name, item, values, hasMultiplePrimaryKeys, snakeCase) => {
|
|
|
236
390
|
}
|
|
237
391
|
line.push(
|
|
238
392
|
referencesToSql(
|
|
393
|
+
config,
|
|
239
394
|
{
|
|
240
395
|
columns: [name],
|
|
241
396
|
...foreignKey
|
|
@@ -259,11 +414,11 @@ const encodeColumnDefault = (def, values, column) => {
|
|
|
259
414
|
}
|
|
260
415
|
return null;
|
|
261
416
|
};
|
|
262
|
-
const identityToSql = (identity) => {
|
|
263
|
-
const options = sequenceOptionsToSql(identity);
|
|
417
|
+
const identityToSql = (config, identity) => {
|
|
418
|
+
const options = sequenceOptionsToSql(config, identity);
|
|
264
419
|
return `GENERATED ${identity.always ? "ALWAYS" : "BY DEFAULT"} AS IDENTITY${options ? ` (${options})` : ""}`;
|
|
265
420
|
};
|
|
266
|
-
const sequenceOptionsToSql = (item) => {
|
|
421
|
+
const sequenceOptionsToSql = (config, item) => {
|
|
267
422
|
const line = [];
|
|
268
423
|
if (item.dataType) line.push(`AS ${item.dataType}`);
|
|
269
424
|
if (item.increment !== void 0) line.push(`INCREMENT BY ${item.increment}`);
|
|
@@ -273,7 +428,7 @@ const sequenceOptionsToSql = (item) => {
|
|
|
273
428
|
if (item.cache !== void 0) line.push(`CACHE ${item.cache}`);
|
|
274
429
|
if (item.cycle) line.push(`CYCLE`);
|
|
275
430
|
if (item.ownedBy) {
|
|
276
|
-
const [schema, table] = getSchemaAndTableFromName(item.ownedBy);
|
|
431
|
+
const [schema, table] = getSchemaAndTableFromName(config, item.ownedBy);
|
|
277
432
|
line.push(`OWNED BY ${quoteTable(schema, table)}`);
|
|
278
433
|
}
|
|
279
434
|
return line.join(" ");
|
|
@@ -303,9 +458,9 @@ const addColumnComment = (comments, name, item) => {
|
|
|
303
458
|
comments.push({ column: name, comment: item.data.comment });
|
|
304
459
|
}
|
|
305
460
|
};
|
|
306
|
-
const getForeignKeyTable = (fnOrTable) => {
|
|
461
|
+
const getForeignKeyTable = (config, fnOrTable) => {
|
|
307
462
|
if (typeof fnOrTable === "string") {
|
|
308
|
-
return getSchemaAndTableFromName(fnOrTable);
|
|
463
|
+
return getSchemaAndTableFromName(config, fnOrTable);
|
|
309
464
|
}
|
|
310
465
|
const item = new (fnOrTable())();
|
|
311
466
|
return [item.schema, item.table];
|
|
@@ -322,7 +477,7 @@ const getConstraintName = (table, constraint, snakeCase) => {
|
|
|
322
477
|
if (constraint.identity) return `${table}_identity`;
|
|
323
478
|
return `${table}_constraint`;
|
|
324
479
|
};
|
|
325
|
-
const constraintToSql = ({ name }, up, constraint, values, snakeCase) => {
|
|
480
|
+
const constraintToSql = (config, { name }, up, constraint, values, snakeCase) => {
|
|
326
481
|
const constraintName = constraint.name || getConstraintName(name, constraint, snakeCase);
|
|
327
482
|
if (!up) {
|
|
328
483
|
const { dropMode } = constraint;
|
|
@@ -330,7 +485,7 @@ const constraintToSql = ({ name }, up, constraint, values, snakeCase) => {
|
|
|
330
485
|
}
|
|
331
486
|
const sql = [`CONSTRAINT "${constraintName}"`];
|
|
332
487
|
if (constraint.references) {
|
|
333
|
-
sql.push(foreignKeyToSql(constraint.references, snakeCase));
|
|
488
|
+
sql.push(foreignKeyToSql(config, constraint.references, snakeCase));
|
|
334
489
|
}
|
|
335
490
|
if (constraint.check) {
|
|
336
491
|
sql.push(checkToSql(constraint.check, values));
|
|
@@ -340,13 +495,13 @@ const constraintToSql = ({ name }, up, constraint, values, snakeCase) => {
|
|
|
340
495
|
const checkToSql = (check, values) => {
|
|
341
496
|
return `CHECK (${check.toSQL({ values })})`;
|
|
342
497
|
};
|
|
343
|
-
const foreignKeyToSql = (item, snakeCase) => {
|
|
498
|
+
const foreignKeyToSql = (config, item, snakeCase) => {
|
|
344
499
|
return `FOREIGN KEY (${joinColumns(
|
|
345
500
|
snakeCase ? item.columns.map(toSnakeCase) : item.columns
|
|
346
|
-
)}) ${referencesToSql(item, snakeCase)}`;
|
|
501
|
+
)}) ${referencesToSql(config, item, snakeCase)}`;
|
|
347
502
|
};
|
|
348
|
-
const referencesToSql = (references, snakeCase) => {
|
|
349
|
-
const [schema, table] = getForeignKeyTable(references.fnOrTable);
|
|
503
|
+
const referencesToSql = (config, references, snakeCase) => {
|
|
504
|
+
const [schema, table] = getForeignKeyTable(config, references.fnOrTable);
|
|
350
505
|
const sql = [
|
|
351
506
|
`REFERENCES ${quoteTable(schema, table)}(${joinColumns(
|
|
352
507
|
snakeCase ? references.foreignColumns.map(toSnakeCase) : references.foreignColumns
|
|
@@ -397,7 +552,7 @@ const getIndexOrExcludeName = (table, columns, suffix) => makeConstraintName(
|
|
|
397
552
|
);
|
|
398
553
|
const getIndexName = (table, columns) => getIndexOrExcludeName(table, columns, "idx");
|
|
399
554
|
const getExcludeName = (table, columns) => getIndexOrExcludeName(table, columns, "exclude");
|
|
400
|
-
const indexesToQuery = (up, { schema, name: tableName }, indexes, snakeCase, language) => {
|
|
555
|
+
const indexesToQuery = (config, up, { schema, name: tableName }, indexes, snakeCase, language) => {
|
|
401
556
|
return indexes.map((index) => {
|
|
402
557
|
const { options } = index;
|
|
403
558
|
const { columns, include, name } = getIndexOrExcludeMainOptions(
|
|
@@ -426,7 +581,7 @@ const indexesToQuery = (up, { schema, name: tableName }, indexes, snakeCase, lan
|
|
|
426
581
|
const columnsSql = columns.map((column) => {
|
|
427
582
|
let sql2 = [
|
|
428
583
|
"expression" in column ? `(${column.expression})` : `"${column.column}"`,
|
|
429
|
-
column.collate && `COLLATE ${quoteNameFromString(column.collate)}`,
|
|
584
|
+
column.collate && `COLLATE ${quoteNameFromString(config, column.collate)}`,
|
|
430
585
|
column.opclass,
|
|
431
586
|
column.order
|
|
432
587
|
].filter((x) => !!x).join(" ");
|
|
@@ -470,7 +625,7 @@ const indexesToQuery = (up, { schema, name: tableName }, indexes, snakeCase, lan
|
|
|
470
625
|
return { text: sql.join(" "), values };
|
|
471
626
|
});
|
|
472
627
|
};
|
|
473
|
-
const excludesToQuery = (up, { schema, name: tableName }, excludes, snakeCase) => {
|
|
628
|
+
const excludesToQuery = (config, up, { schema, name: tableName }, excludes, snakeCase) => {
|
|
474
629
|
return excludes.map((exclude) => {
|
|
475
630
|
const { options } = exclude;
|
|
476
631
|
const { columns, include, name } = getIndexOrExcludeMainOptions(
|
|
@@ -490,7 +645,7 @@ const excludesToQuery = (up, { schema, name: tableName }, excludes, snakeCase) =
|
|
|
490
645
|
const columnList = columns.map(
|
|
491
646
|
(column) => [
|
|
492
647
|
"expression" in column ? `(${column.expression})` : `"${column.column}"`,
|
|
493
|
-
column.collate && `COLLATE ${quoteNameFromString(column.collate)}`,
|
|
648
|
+
column.collate && `COLLATE ${quoteNameFromString(config, column.collate)}`,
|
|
494
649
|
column.opclass,
|
|
495
650
|
column.order,
|
|
496
651
|
`WITH ${column.with}`
|
|
@@ -559,9 +714,16 @@ const cmpRawSql = (a, b) => {
|
|
|
559
714
|
};
|
|
560
715
|
const getMigrationsSchemaAndTable = (config) => {
|
|
561
716
|
const [tableSchema, table] = getSchemaAndTableFromName(
|
|
717
|
+
config,
|
|
562
718
|
config.migrationsTable
|
|
563
719
|
);
|
|
564
|
-
|
|
720
|
+
let schema = tableSchema;
|
|
721
|
+
if (!schema) {
|
|
722
|
+
schema = typeof config.schema === "function" ? config.schema() : config.schema;
|
|
723
|
+
if (schema === "public") {
|
|
724
|
+
schema = void 0;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
565
727
|
return { schema, table };
|
|
566
728
|
};
|
|
567
729
|
const migrationsSchemaTableSql = (config) => {
|
|
@@ -580,6 +742,11 @@ const tableMethods = {
|
|
|
580
742
|
}
|
|
581
743
|
};
|
|
582
744
|
|
|
745
|
+
class RakeDbError extends Error {
|
|
746
|
+
}
|
|
747
|
+
class NoPrimaryKey extends RakeDbError {
|
|
748
|
+
}
|
|
749
|
+
|
|
583
750
|
const createTable = async (migration, up, tableName, first, second, third) => {
|
|
584
751
|
let options;
|
|
585
752
|
let fn;
|
|
@@ -618,6 +785,7 @@ const createTable = async (migration, up, tableName, first, second, third) => {
|
|
|
618
785
|
shape = tableData = emptyObject;
|
|
619
786
|
}
|
|
620
787
|
const ast = makeAst$2(
|
|
788
|
+
migration.options,
|
|
621
789
|
up,
|
|
622
790
|
tableName,
|
|
623
791
|
shape,
|
|
@@ -626,7 +794,7 @@ const createTable = async (migration, up, tableName, first, second, third) => {
|
|
|
626
794
|
migration.options.noPrimaryKey
|
|
627
795
|
);
|
|
628
796
|
fn && validatePrimaryKey(ast);
|
|
629
|
-
const queries = astToQueries$1(ast, snakeCase, language);
|
|
797
|
+
const queries = astToQueries$1(migration.options, ast, snakeCase, language);
|
|
630
798
|
for (const { then, ...query } of queries) {
|
|
631
799
|
const result = await migration.adapter.arrays(interpolateSqlValues(query));
|
|
632
800
|
then?.(result);
|
|
@@ -646,7 +814,7 @@ const createTable = async (migration, up, tableName, first, second, third) => {
|
|
|
646
814
|
}
|
|
647
815
|
};
|
|
648
816
|
};
|
|
649
|
-
const makeAst$2 = (up, tableName, shape, tableData, options, noPrimaryKey) => {
|
|
817
|
+
const makeAst$2 = (config, up, tableName, shape, tableData, options, noPrimaryKey) => {
|
|
650
818
|
const shapePKeys = [];
|
|
651
819
|
for (const key in shape) {
|
|
652
820
|
const column = shape[key];
|
|
@@ -655,7 +823,7 @@ const makeAst$2 = (up, tableName, shape, tableData, options, noPrimaryKey) => {
|
|
|
655
823
|
}
|
|
656
824
|
}
|
|
657
825
|
const { primaryKey } = tableData;
|
|
658
|
-
const [schema, table] = getSchemaAndTableFromName(tableName);
|
|
826
|
+
const [schema, table] = getSchemaAndTableFromName(config, tableName);
|
|
659
827
|
return {
|
|
660
828
|
type: "table",
|
|
661
829
|
action: up ? "create" : "drop",
|
|
@@ -695,13 +863,13 @@ You can suppress this error by setting { noPrimaryKey: true } after a table name
|
|
|
695
863
|
}
|
|
696
864
|
}
|
|
697
865
|
};
|
|
698
|
-
const astToQueries$1 = (ast, snakeCase, language) => {
|
|
866
|
+
const astToQueries$1 = (config, ast, snakeCase, language) => {
|
|
699
867
|
const queries = [];
|
|
700
868
|
const { shape } = ast;
|
|
701
869
|
for (const key in shape) {
|
|
702
870
|
const item = shape[key];
|
|
703
871
|
if (!(item instanceof EnumColumn)) continue;
|
|
704
|
-
queries.push(makePopulateEnumQuery(item));
|
|
872
|
+
queries.push(makePopulateEnumQuery(config, item));
|
|
705
873
|
}
|
|
706
874
|
if (ast.action === "drop") {
|
|
707
875
|
queries.push({
|
|
@@ -722,7 +890,14 @@ const astToQueries$1 = (ast, snakeCase, language) => {
|
|
|
722
890
|
addColumnComment(comments, name, item);
|
|
723
891
|
lines.push(
|
|
724
892
|
`
|
|
725
|
-
${columnToSql(
|
|
893
|
+
${columnToSql(
|
|
894
|
+
config,
|
|
895
|
+
name,
|
|
896
|
+
item,
|
|
897
|
+
values,
|
|
898
|
+
!!ast.primaryKey,
|
|
899
|
+
snakeCase
|
|
900
|
+
)}`
|
|
726
901
|
);
|
|
727
902
|
}
|
|
728
903
|
if (ast.primaryKey) {
|
|
@@ -740,6 +915,7 @@ const astToQueries$1 = (ast, snakeCase, language) => {
|
|
|
740
915
|
lines.push(
|
|
741
916
|
`
|
|
742
917
|
${constraintToSql(
|
|
918
|
+
config,
|
|
743
919
|
ast,
|
|
744
920
|
true,
|
|
745
921
|
{
|
|
@@ -764,8 +940,8 @@ const astToQueries$1 = (ast, snakeCase, language) => {
|
|
|
764
940
|
)`,
|
|
765
941
|
values
|
|
766
942
|
},
|
|
767
|
-
...indexesToQuery(true, ast, indexes, snakeCase, language),
|
|
768
|
-
...excludesToQuery(true, ast, excludes, snakeCase),
|
|
943
|
+
...indexesToQuery(config, true, ast, indexes, snakeCase, language),
|
|
944
|
+
...excludesToQuery(config, true, ast, excludes, snakeCase),
|
|
769
945
|
...commentsToQuery(ast, comments)
|
|
770
946
|
);
|
|
771
947
|
if (ast.comment) {
|
|
@@ -987,14 +1163,21 @@ const changeTable = async (migration, up, tableName, options, fn) => {
|
|
|
987
1163
|
tableChanger[snakeCaseKey] = snakeCase;
|
|
988
1164
|
addOrDropChanges.length = 0;
|
|
989
1165
|
const changeData = fn?.(tableChanger) || {};
|
|
990
|
-
const ast = makeAst$1(
|
|
991
|
-
|
|
1166
|
+
const ast = makeAst$1(
|
|
1167
|
+
migration.options,
|
|
1168
|
+
up,
|
|
1169
|
+
tableName,
|
|
1170
|
+
changeData,
|
|
1171
|
+
changeTableData,
|
|
1172
|
+
options
|
|
1173
|
+
);
|
|
1174
|
+
const queries = astToQueries(migration.options, ast, snakeCase, language);
|
|
992
1175
|
for (const query of queries) {
|
|
993
1176
|
const result = await migration.adapter.arrays(interpolateSqlValues(query));
|
|
994
1177
|
query.then?.(result);
|
|
995
1178
|
}
|
|
996
1179
|
};
|
|
997
|
-
const makeAst$1 = (up, name, changeData, changeTableData2, options) => {
|
|
1180
|
+
const makeAst$1 = (config, up, name, changeData, changeTableData2, options) => {
|
|
998
1181
|
const { comment } = options;
|
|
999
1182
|
const shape = {};
|
|
1000
1183
|
const consumedChanges = {};
|
|
@@ -1039,7 +1222,7 @@ const makeAst$1 = (up, name, changeData, changeTableData2, options) => {
|
|
|
1039
1222
|
);
|
|
1040
1223
|
shape[name2] = arr;
|
|
1041
1224
|
}
|
|
1042
|
-
const [schema, table] = getSchemaAndTableFromName(name);
|
|
1225
|
+
const [schema, table] = getSchemaAndTableFromName(config, name);
|
|
1043
1226
|
return {
|
|
1044
1227
|
type: "changeTable",
|
|
1045
1228
|
schema,
|
|
@@ -1049,7 +1232,7 @@ const makeAst$1 = (up, name, changeData, changeTableData2, options) => {
|
|
|
1049
1232
|
...up ? changeTableData2 : { add: changeTableData2.drop, drop: changeTableData2.add }
|
|
1050
1233
|
};
|
|
1051
1234
|
};
|
|
1052
|
-
const astToQueries = (ast, snakeCase, language) => {
|
|
1235
|
+
const astToQueries = (config, ast, snakeCase, language) => {
|
|
1053
1236
|
const queries = [];
|
|
1054
1237
|
if (ast.comment !== void 0) {
|
|
1055
1238
|
queries.push({
|
|
@@ -1069,6 +1252,7 @@ const astToQueries = (ast, snakeCase, language) => {
|
|
|
1069
1252
|
if (Array.isArray(item)) {
|
|
1070
1253
|
for (const it of item) {
|
|
1071
1254
|
handlePrerequisitesForTableItem(
|
|
1255
|
+
config,
|
|
1072
1256
|
key,
|
|
1073
1257
|
it,
|
|
1074
1258
|
queries,
|
|
@@ -1079,6 +1263,7 @@ const astToQueries = (ast, snakeCase, language) => {
|
|
|
1079
1263
|
}
|
|
1080
1264
|
} else {
|
|
1081
1265
|
handlePrerequisitesForTableItem(
|
|
1266
|
+
config,
|
|
1082
1267
|
key,
|
|
1083
1268
|
item,
|
|
1084
1269
|
queries,
|
|
@@ -1117,6 +1302,7 @@ const astToQueries = (ast, snakeCase, language) => {
|
|
|
1117
1302
|
if (Array.isArray(item)) {
|
|
1118
1303
|
for (const it of item) {
|
|
1119
1304
|
handleTableItemChange(
|
|
1305
|
+
config,
|
|
1120
1306
|
key,
|
|
1121
1307
|
it,
|
|
1122
1308
|
ast,
|
|
@@ -1136,6 +1322,7 @@ const astToQueries = (ast, snakeCase, language) => {
|
|
|
1136
1322
|
}
|
|
1137
1323
|
} else {
|
|
1138
1324
|
handleTableItemChange(
|
|
1325
|
+
config,
|
|
1139
1326
|
key,
|
|
1140
1327
|
item,
|
|
1141
1328
|
ast,
|
|
@@ -1168,7 +1355,14 @@ const astToQueries = (ast, snakeCase, language) => {
|
|
|
1168
1355
|
prependAlterTable.push(
|
|
1169
1356
|
...dropConstraints.map(
|
|
1170
1357
|
(foreignKey) => `
|
|
1171
|
-
DROP ${constraintToSql(
|
|
1358
|
+
DROP ${constraintToSql(
|
|
1359
|
+
config,
|
|
1360
|
+
ast,
|
|
1361
|
+
false,
|
|
1362
|
+
foreignKey,
|
|
1363
|
+
values,
|
|
1364
|
+
snakeCase
|
|
1365
|
+
)}`
|
|
1172
1366
|
)
|
|
1173
1367
|
);
|
|
1174
1368
|
alterTable.unshift(...prependAlterTable);
|
|
@@ -1186,7 +1380,14 @@ const astToQueries = (ast, snakeCase, language) => {
|
|
|
1186
1380
|
alterTable.push(
|
|
1187
1381
|
...addConstraints.map(
|
|
1188
1382
|
(foreignKey) => `
|
|
1189
|
-
ADD ${constraintToSql(
|
|
1383
|
+
ADD ${constraintToSql(
|
|
1384
|
+
config,
|
|
1385
|
+
ast,
|
|
1386
|
+
true,
|
|
1387
|
+
foreignKey,
|
|
1388
|
+
values,
|
|
1389
|
+
snakeCase
|
|
1390
|
+
)}`
|
|
1190
1391
|
)
|
|
1191
1392
|
);
|
|
1192
1393
|
const tableName = quoteWithSchema(ast);
|
|
@@ -1202,10 +1403,14 @@ const astToQueries = (ast, snakeCase, language) => {
|
|
|
1202
1403
|
if (alterTable.length) {
|
|
1203
1404
|
queries.push(alterTableSql(tableName, alterTable, values));
|
|
1204
1405
|
}
|
|
1205
|
-
queries.push(
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
queries.push(
|
|
1406
|
+
queries.push(
|
|
1407
|
+
...indexesToQuery(config, false, ast, dropIndexes, snakeCase, language)
|
|
1408
|
+
);
|
|
1409
|
+
queries.push(
|
|
1410
|
+
...indexesToQuery(config, true, ast, addIndexes, snakeCase, language)
|
|
1411
|
+
);
|
|
1412
|
+
queries.push(...excludesToQuery(config, false, ast, dropExcludes, snakeCase));
|
|
1413
|
+
queries.push(...excludesToQuery(config, true, ast, addExcludes, snakeCase));
|
|
1209
1414
|
queries.push(...commentsToQuery(ast, comments));
|
|
1210
1415
|
return queries;
|
|
1211
1416
|
};
|
|
@@ -1214,11 +1419,11 @@ const alterTableSql = (tableName, lines, values) => ({
|
|
|
1214
1419
|
${lines.join(",\n ")}`,
|
|
1215
1420
|
values
|
|
1216
1421
|
});
|
|
1217
|
-
const handlePrerequisitesForTableItem = (key, item, queries, addPrimaryKeys, dropPrimaryKeys, snakeCase) => {
|
|
1422
|
+
const handlePrerequisitesForTableItem = (config, key, item, queries, addPrimaryKeys, dropPrimaryKeys, snakeCase) => {
|
|
1218
1423
|
if ("item" in item) {
|
|
1219
1424
|
const { item: column } = item;
|
|
1220
1425
|
if (column instanceof EnumColumn) {
|
|
1221
|
-
queries.push(makePopulateEnumQuery(column));
|
|
1426
|
+
queries.push(makePopulateEnumQuery(config, column));
|
|
1222
1427
|
}
|
|
1223
1428
|
}
|
|
1224
1429
|
if (item.type === "add") {
|
|
@@ -1231,10 +1436,10 @@ const handlePrerequisitesForTableItem = (key, item, queries, addPrimaryKeys, dro
|
|
|
1231
1436
|
}
|
|
1232
1437
|
} else if (item.type === "change") {
|
|
1233
1438
|
if (item.from.column instanceof EnumColumn) {
|
|
1234
|
-
queries.push(makePopulateEnumQuery(item.from.column));
|
|
1439
|
+
queries.push(makePopulateEnumQuery(config, item.from.column));
|
|
1235
1440
|
}
|
|
1236
1441
|
if (item.to.column instanceof EnumColumn) {
|
|
1237
|
-
queries.push(makePopulateEnumQuery(item.to.column));
|
|
1442
|
+
queries.push(makePopulateEnumQuery(config, item.to.column));
|
|
1238
1443
|
}
|
|
1239
1444
|
if (item.from.primaryKey) {
|
|
1240
1445
|
dropPrimaryKeys.columns.push(
|
|
@@ -1250,7 +1455,7 @@ const handlePrerequisitesForTableItem = (key, item, queries, addPrimaryKeys, dro
|
|
|
1250
1455
|
}
|
|
1251
1456
|
}
|
|
1252
1457
|
};
|
|
1253
|
-
const handleTableItemChange = (key, item, ast, alterTable, renameItems, values, addPrimaryKeys, addIndexes, dropIndexes, addExcludes, dropExcludes, addConstraints, dropConstraints, comments, snakeCase) => {
|
|
1458
|
+
const handleTableItemChange = (config, key, item, ast, alterTable, renameItems, values, addPrimaryKeys, addIndexes, dropIndexes, addExcludes, dropExcludes, addConstraints, dropConstraints, comments, snakeCase) => {
|
|
1254
1459
|
if (item.type === "add") {
|
|
1255
1460
|
const column = item.item;
|
|
1256
1461
|
const name = getColumnName(column, key, snakeCase);
|
|
@@ -1259,6 +1464,7 @@ const handleTableItemChange = (key, item, ast, alterTable, renameItems, values,
|
|
|
1259
1464
|
addColumnComment(comments, name, column);
|
|
1260
1465
|
alterTable.push(
|
|
1261
1466
|
`ADD COLUMN ${columnToSql(
|
|
1467
|
+
config,
|
|
1262
1468
|
name,
|
|
1263
1469
|
column,
|
|
1264
1470
|
values,
|
|
@@ -1281,10 +1487,10 @@ const handleTableItemChange = (key, item, ast, alterTable, renameItems, values,
|
|
|
1281
1487
|
let changeType = false;
|
|
1282
1488
|
if (to.type && (from.type !== to.type || from.collate !== to.collate)) {
|
|
1283
1489
|
changeType = true;
|
|
1284
|
-
const type = !to.column || to.column.data.isOfCustomType ? to.column && to.column instanceof DomainColumn ? quoteNameFromString(to.type) : quoteCustomType(to.type) : to.type;
|
|
1490
|
+
const type = !to.column || to.column.data.isOfCustomType ? to.column && to.column instanceof DomainColumn ? quoteNameFromString(config, to.type) : quoteCustomType(config, to.type) : to.type;
|
|
1285
1491
|
const using = item.using?.usingUp ? ` USING ${item.using.usingUp.toSQL({ values })}` : to.column instanceof EnumColumn ? ` USING "${name}"::text::${type}` : to.column instanceof ArrayColumn ? ` USING "${name}"::text[]::${type}` : "";
|
|
1286
1492
|
alterTable.push(
|
|
1287
|
-
`ALTER COLUMN "${name}" TYPE ${type}${to.collate ? ` COLLATE ${quoteNameFromString(to.collate)}` : ""}${using}`
|
|
1493
|
+
`ALTER COLUMN "${name}" TYPE ${type}${to.collate ? ` COLLATE ${quoteNameFromString(config, to.collate)}` : ""}${using}`
|
|
1288
1494
|
);
|
|
1289
1495
|
}
|
|
1290
1496
|
if (typeof from.identity !== typeof to.identity || !deepCompare(from.identity, to.identity)) {
|
|
@@ -1293,7 +1499,7 @@ const handleTableItemChange = (key, item, ast, alterTable, renameItems, values,
|
|
|
1293
1499
|
}
|
|
1294
1500
|
if (to.identity) {
|
|
1295
1501
|
alterTable.push(
|
|
1296
|
-
`ALTER COLUMN "${name}" ADD ${identityToSql(to.identity)}`
|
|
1502
|
+
`ALTER COLUMN "${name}" ADD ${identityToSql(config, to.identity)}`
|
|
1297
1503
|
);
|
|
1298
1504
|
}
|
|
1299
1505
|
}
|
|
@@ -1426,15 +1632,15 @@ const renameColumnSql = (from, to) => {
|
|
|
1426
1632
|
};
|
|
1427
1633
|
|
|
1428
1634
|
const createView = async (migration, up, name, options, sql) => {
|
|
1429
|
-
const ast = makeAst(up, name, options, sql);
|
|
1635
|
+
const ast = makeAst(migration.options, up, name, options, sql);
|
|
1430
1636
|
const query = astToQuery(ast);
|
|
1431
1637
|
await migration.adapter.arrays(interpolateSqlValues(query));
|
|
1432
1638
|
};
|
|
1433
|
-
const makeAst = (up, fullName, options, sql) => {
|
|
1639
|
+
const makeAst = (config, up, fullName, options, sql) => {
|
|
1434
1640
|
if (typeof sql === "string") {
|
|
1435
1641
|
sql = raw({ raw: sql });
|
|
1436
1642
|
}
|
|
1437
|
-
const [schema, name] = getSchemaAndTableFromName(fullName);
|
|
1643
|
+
const [schema, name] = getSchemaAndTableFromName(config, fullName);
|
|
1438
1644
|
return {
|
|
1439
1645
|
type: "view",
|
|
1440
1646
|
action: up ? "create" : "drop",
|
|
@@ -2026,7 +2232,7 @@ class Migration {
|
|
|
2026
2232
|
* @param values - object where keys are for old names, values are for new names
|
|
2027
2233
|
*/
|
|
2028
2234
|
async renameEnumValues(enumName, values) {
|
|
2029
|
-
const [schema, name] = getSchemaAndTableFromName(enumName);
|
|
2235
|
+
const [schema, name] = getSchemaAndTableFromName(this.options, enumName);
|
|
2030
2236
|
const ast = {
|
|
2031
2237
|
type: "renameEnumValues",
|
|
2032
2238
|
schema,
|
|
@@ -2290,9 +2496,16 @@ class Migration {
|
|
|
2290
2496
|
* @param tableName - name of the table
|
|
2291
2497
|
*/
|
|
2292
2498
|
async tableExists(tableName) {
|
|
2499
|
+
let text = `SELECT 1 FROM "information_schema"."tables" WHERE "table_name" = $1`;
|
|
2500
|
+
const [schema, table] = getSchemaAndTableFromName(this.options, tableName);
|
|
2501
|
+
const values = [table];
|
|
2502
|
+
if (schema) {
|
|
2503
|
+
text += ' AND "table_schema" = $2';
|
|
2504
|
+
values.push(schema);
|
|
2505
|
+
}
|
|
2293
2506
|
return queryExists(this, {
|
|
2294
|
-
text
|
|
2295
|
-
values
|
|
2507
|
+
text,
|
|
2508
|
+
values
|
|
2296
2509
|
});
|
|
2297
2510
|
}
|
|
2298
2511
|
/**
|
|
@@ -2314,12 +2527,19 @@ class Migration {
|
|
|
2314
2527
|
* @param columnName - name of the column
|
|
2315
2528
|
*/
|
|
2316
2529
|
async columnExists(tableName, columnName) {
|
|
2530
|
+
let text = `SELECT 1 FROM "information_schema"."columns" WHERE "table_name" = $1 AND "column_name" = $2`;
|
|
2531
|
+
const [schema, table] = getSchemaAndTableFromName(this.options, tableName);
|
|
2532
|
+
const values = [
|
|
2533
|
+
table,
|
|
2534
|
+
this.options.snakeCase ? toSnakeCase(columnName) : columnName
|
|
2535
|
+
];
|
|
2536
|
+
if (schema) {
|
|
2537
|
+
text += ' AND "table_schema" = $3';
|
|
2538
|
+
values.push(schema);
|
|
2539
|
+
}
|
|
2317
2540
|
return queryExists(this, {
|
|
2318
|
-
text
|
|
2319
|
-
values
|
|
2320
|
-
tableName,
|
|
2321
|
-
this.options.snakeCase ? toSnakeCase(columnName) : columnName
|
|
2322
|
-
]
|
|
2541
|
+
text,
|
|
2542
|
+
values
|
|
2323
2543
|
});
|
|
2324
2544
|
}
|
|
2325
2545
|
/**
|
|
@@ -2399,7 +2619,7 @@ const createSchema = async (migration, up, name) => {
|
|
|
2399
2619
|
);
|
|
2400
2620
|
};
|
|
2401
2621
|
const createExtension = async (migration, up, fullName, options) => {
|
|
2402
|
-
const [schema, name] = getSchemaAndTableFromName(fullName);
|
|
2622
|
+
const [schema, name] = getSchemaAndTableFromName(migration.options, fullName);
|
|
2403
2623
|
const ast = {
|
|
2404
2624
|
type: "extension",
|
|
2405
2625
|
action: up ? "create" : "drop",
|
|
@@ -2416,7 +2636,7 @@ const createExtension = async (migration, up, fullName, options) => {
|
|
|
2416
2636
|
await migration.adapter.query(query);
|
|
2417
2637
|
};
|
|
2418
2638
|
const createEnum = async (migration, up, name, values, options = {}) => {
|
|
2419
|
-
const [schema, enumName] = getSchemaAndTableFromName(name);
|
|
2639
|
+
const [schema, enumName] = getSchemaAndTableFromName(migration.options, name);
|
|
2420
2640
|
const ast = {
|
|
2421
2641
|
type: "enum",
|
|
2422
2642
|
action: up ? "create" : "drop",
|
|
@@ -2435,7 +2655,10 @@ const createEnum = async (migration, up, name, values, options = {}) => {
|
|
|
2435
2655
|
await migration.adapter.query(query);
|
|
2436
2656
|
};
|
|
2437
2657
|
const createDomain = async (migration, up, name, fn) => {
|
|
2438
|
-
const [schema, domainName] = getSchemaAndTableFromName(
|
|
2658
|
+
const [schema, domainName] = getSchemaAndTableFromName(
|
|
2659
|
+
migration.options,
|
|
2660
|
+
name
|
|
2661
|
+
);
|
|
2439
2662
|
const ast = {
|
|
2440
2663
|
type: "domain",
|
|
2441
2664
|
action: up ? "create" : "drop",
|
|
@@ -2448,7 +2671,10 @@ const createDomain = async (migration, up, name, fn) => {
|
|
|
2448
2671
|
const quotedName = quoteWithSchema(ast);
|
|
2449
2672
|
if (ast.action === "create") {
|
|
2450
2673
|
const column = ast.baseType;
|
|
2451
|
-
query = `CREATE DOMAIN ${quotedName} AS ${columnTypeToSql(
|
|
2674
|
+
query = `CREATE DOMAIN ${quotedName} AS ${columnTypeToSql(
|
|
2675
|
+
migration.options,
|
|
2676
|
+
column
|
|
2677
|
+
)}${column.data.collate ? `
|
|
2452
2678
|
COLLATE "${column.data.collate}"` : ""}${column.data.default !== void 0 ? `
|
|
2453
2679
|
DEFAULT ${encodeColumnDefault(column.data.default, values)}` : ""}${!column.data.isNullable || column.data.checks ? "\n" : ""}${[
|
|
2454
2680
|
!column.data.isNullable && "NOT NULL",
|
|
@@ -2465,7 +2691,10 @@ DEFAULT ${encodeColumnDefault(column.data.default, values)}` : ""}${!column.data
|
|
|
2465
2691
|
);
|
|
2466
2692
|
};
|
|
2467
2693
|
const createCollation = async (migration, up, name, options) => {
|
|
2468
|
-
const [schema, collationName] = getSchemaAndTableFromName(
|
|
2694
|
+
const [schema, collationName] = getSchemaAndTableFromName(
|
|
2695
|
+
migration.options,
|
|
2696
|
+
name
|
|
2697
|
+
);
|
|
2469
2698
|
const ast = {
|
|
2470
2699
|
type: "collation",
|
|
2471
2700
|
action: up ? "create" : "drop",
|
|
@@ -2478,7 +2707,10 @@ const createCollation = async (migration, up, name, options) => {
|
|
|
2478
2707
|
if (ast.action === "create") {
|
|
2479
2708
|
query = `CREATE COLLATION${ast.createIfNotExists ? " IF NOT EXISTS" : ""} ${quotedName} `;
|
|
2480
2709
|
if (ast.fromExisting) {
|
|
2481
|
-
query += `FROM ${quoteNameFromString(
|
|
2710
|
+
query += `FROM ${quoteNameFromString(
|
|
2711
|
+
migration.options,
|
|
2712
|
+
ast.fromExisting
|
|
2713
|
+
)}`;
|
|
2482
2714
|
} else {
|
|
2483
2715
|
const config = [];
|
|
2484
2716
|
if (ast.locale) config.push(`locale = '${ast.locale}'`);
|
|
@@ -2501,8 +2733,14 @@ const queryExists = (db, sql) => {
|
|
|
2501
2733
|
return db.adapter.query(sql.text, sql.values).then(({ rowCount }) => rowCount > 0);
|
|
2502
2734
|
};
|
|
2503
2735
|
const renameType = async (migration, from, to, kind) => {
|
|
2504
|
-
const [fromSchema, f] = getSchemaAndTableFromName(
|
|
2505
|
-
|
|
2736
|
+
const [fromSchema, f] = getSchemaAndTableFromName(
|
|
2737
|
+
migration.options,
|
|
2738
|
+
migration.up ? from : to
|
|
2739
|
+
);
|
|
2740
|
+
const [toSchema, t] = getSchemaAndTableFromName(
|
|
2741
|
+
migration.options,
|
|
2742
|
+
migration.up ? to : from
|
|
2743
|
+
);
|
|
2506
2744
|
const ast = {
|
|
2507
2745
|
type: "renameType",
|
|
2508
2746
|
kind,
|
|
@@ -2523,7 +2761,10 @@ const renameType = async (migration, from, to, kind) => {
|
|
|
2523
2761
|
}
|
|
2524
2762
|
};
|
|
2525
2763
|
const renameTableItem = async (migration, tableName, from, to, kind) => {
|
|
2526
|
-
const [schema, table] = getSchemaAndTableFromName(
|
|
2764
|
+
const [schema, table] = getSchemaAndTableFromName(
|
|
2765
|
+
migration.options,
|
|
2766
|
+
tableName
|
|
2767
|
+
);
|
|
2527
2768
|
const [f, t] = migration.up ? [from, to] : [to, from];
|
|
2528
2769
|
await migration.adapter.query(
|
|
2529
2770
|
kind === "INDEX" ? `ALTER INDEX ${quoteTable(schema, f)} RENAME TO "${t}"` : `ALTER TABLE ${quoteTable(
|
|
@@ -2533,7 +2774,7 @@ const renameTableItem = async (migration, tableName, from, to, kind) => {
|
|
|
2533
2774
|
);
|
|
2534
2775
|
};
|
|
2535
2776
|
const addOrDropEnumValues = async (migration, up, enumName, values, options) => {
|
|
2536
|
-
const [schema, name] = getSchemaAndTableFromName(enumName);
|
|
2777
|
+
const [schema, name] = getSchemaAndTableFromName(migration.options, enumName);
|
|
2537
2778
|
const quotedName = quoteTable(schema, name);
|
|
2538
2779
|
const ast = {
|
|
2539
2780
|
type: "enumValues",
|
|
@@ -2569,7 +2810,7 @@ const addOrDropEnumValues = async (migration, up, enumName, values, options) =>
|
|
|
2569
2810
|
);
|
|
2570
2811
|
};
|
|
2571
2812
|
const changeEnumValues = async (migration, enumName, fromValues, toValues) => {
|
|
2572
|
-
const [schema, name] = getSchemaAndTableFromName(enumName);
|
|
2813
|
+
const [schema, name] = getSchemaAndTableFromName(migration.options, enumName);
|
|
2573
2814
|
if (!migration.up) {
|
|
2574
2815
|
const values = fromValues;
|
|
2575
2816
|
fromValues = toValues;
|
|
@@ -2592,7 +2833,8 @@ const changeEnumValues = async (migration, enumName, fromValues, toValues) => {
|
|
|
2592
2833
|
);
|
|
2593
2834
|
};
|
|
2594
2835
|
const recreateEnum = async (migration, { schema, name }, values, errorMessage) => {
|
|
2595
|
-
const
|
|
2836
|
+
const configSchema = migration.options.schema;
|
|
2837
|
+
const defaultSchema = (typeof configSchema === "function" ? configSchema() : void 0) ?? "public";
|
|
2596
2838
|
const quotedName = quoteTable(schema, name);
|
|
2597
2839
|
const relKinds = ["r", "m"];
|
|
2598
2840
|
const { rows: tables } = await migration.adapter.query(
|
|
@@ -2662,8 +2904,7 @@ ${migrationCode}`
|
|
|
2662
2904
|
);
|
|
2663
2905
|
config.logger?.log(`Created ${pathToLog(filePath)}`);
|
|
2664
2906
|
};
|
|
2665
|
-
const newMigration = async (config,
|
|
2666
|
-
if (!name) throw new Error("Migration name is missing");
|
|
2907
|
+
const newMigration = async (config, name) => {
|
|
2667
2908
|
const version = await makeFileVersion({}, config);
|
|
2668
2909
|
await writeMigrationFile(config, version, name, makeContent(name));
|
|
2669
2910
|
};
|
|
@@ -2719,16 +2960,9 @@ const fileNamesToChangeMigrationId = {
|
|
|
2719
2960
|
timestamp: ".rename-to-timestamp.json"
|
|
2720
2961
|
};
|
|
2721
2962
|
const fileNamesToChangeMigrationIdMap = Object.fromEntries(
|
|
2722
|
-
Object.entries(fileNamesToChangeMigrationId).map(([
|
|
2963
|
+
Object.entries(fileNamesToChangeMigrationId).map(([, name]) => [name, true])
|
|
2723
2964
|
);
|
|
2724
|
-
const changeIds = async (adapters, config,
|
|
2725
|
-
if (arg !== "serial" && arg !== "timestamp") {
|
|
2726
|
-
throw new Error(
|
|
2727
|
-
`Pass "serial" or "timestamp" argument to the "change-ids" command`
|
|
2728
|
-
);
|
|
2729
|
-
}
|
|
2730
|
-
let digits = digitsArg && parseInt(digitsArg);
|
|
2731
|
-
if (!digits || isNaN(digits)) digits = 4;
|
|
2965
|
+
const changeIds = async (adapters, config, { format, digits = 4 }) => {
|
|
2732
2966
|
const data = await getMigrations({}, config, true, false, (_, filePath) => {
|
|
2733
2967
|
const fileName = path.basename(filePath);
|
|
2734
2968
|
const match = fileName.match(/^(\d+)\D/);
|
|
@@ -2740,9 +2974,9 @@ const changeIds = async (adapters, config, [arg, digitsArg]) => {
|
|
|
2740
2974
|
return match[1];
|
|
2741
2975
|
});
|
|
2742
2976
|
if (data.renameTo) {
|
|
2743
|
-
if (
|
|
2977
|
+
if (format === "serial" && typeof data.renameTo.to === "object" && digits === data.renameTo.to.serial || format === "timestamp" && data.renameTo.to === "timestamp") {
|
|
2744
2978
|
config.logger?.log(
|
|
2745
|
-
config.migrations ? "`renameMigrations` setting is already set" : `${fileNamesToChangeMigrationId[
|
|
2979
|
+
config.migrations ? "`renameMigrations` setting is already set" : `${fileNamesToChangeMigrationId[format]} already exists`
|
|
2746
2980
|
);
|
|
2747
2981
|
return;
|
|
2748
2982
|
}
|
|
@@ -2755,15 +2989,15 @@ const changeIds = async (adapters, config, [arg, digitsArg]) => {
|
|
|
2755
2989
|
);
|
|
2756
2990
|
}
|
|
2757
2991
|
}
|
|
2758
|
-
const version =
|
|
2992
|
+
const version = format === "timestamp" ? parseInt(generateTimeStamp()) : 1;
|
|
2759
2993
|
const rename = Object.fromEntries(
|
|
2760
2994
|
data.migrations.map((item, i) => [path.basename(item.path), version + i])
|
|
2761
2995
|
);
|
|
2762
2996
|
if (config.migrations) {
|
|
2763
|
-
const to =
|
|
2997
|
+
const to = format === "timestamp" ? `'${format}'` : `{ serial: ${digits} }`;
|
|
2764
2998
|
config.logger?.log(
|
|
2765
2999
|
`Save the following settings into your rake-db config under the \`migrations\` setting, it will instruct rake-db to rename migration entries during the next deploy:
|
|
2766
|
-
${
|
|
3000
|
+
${format !== "serial" || digits !== 4 ? `
|
|
2767
3001
|
migrationId: ${to},` : ""}
|
|
2768
3002
|
renameMigrations: {
|
|
2769
3003
|
to: ${to},
|
|
@@ -2772,14 +3006,14 @@ renameMigrations: {
|
|
|
2772
3006
|
);
|
|
2773
3007
|
} else {
|
|
2774
3008
|
await fs.writeFile(
|
|
2775
|
-
path.join(config.migrationsPath, fileNamesToChangeMigrationId[
|
|
3009
|
+
path.join(config.migrationsPath, fileNamesToChangeMigrationId[format]),
|
|
2776
3010
|
JSON.stringify(rename, null, 2)
|
|
2777
3011
|
);
|
|
2778
3012
|
}
|
|
2779
3013
|
const values = data.migrations.map(
|
|
2780
3014
|
(item, i) => {
|
|
2781
3015
|
let newVersion = String(version + i);
|
|
2782
|
-
if (
|
|
3016
|
+
if (format === "serial") newVersion = newVersion.padStart(digits, "0");
|
|
2783
3017
|
const name = path.basename(item.path).slice(item.version.length + 1);
|
|
2784
3018
|
return [item.version, name, newVersion];
|
|
2785
3019
|
}
|
|
@@ -2816,9 +3050,9 @@ After setting \`renameMigrations\` (see above) and renaming the files, run the d
|
|
|
2816
3050
|
})
|
|
2817
3051
|
);
|
|
2818
3052
|
config.logger?.log(
|
|
2819
|
-
`Migration files were renamed, a config file ${fileNamesToChangeMigrationId[
|
|
3053
|
+
`Migration files were renamed, a config file ${fileNamesToChangeMigrationId[format]} for renaming migrations after deploy was created, and migrations in local db were renamed successfully.
|
|
2820
3054
|
|
|
2821
|
-
${
|
|
3055
|
+
${format === "timestamp" || digits !== 4 ? `Set \`migrationId\`: ${format === "timestamp" ? `'timestamp'` : `{ serial: ${digits} }`}` : `Remove \`migrationId\``} setting in the rake-db config`
|
|
2822
3056
|
);
|
|
2823
3057
|
};
|
|
2824
3058
|
const renameMigrationVersionsInDb = async (config, adapter, values) => {
|
|
@@ -2996,35 +3230,26 @@ const saveMigratedVersion = async (db, version, name, config) => {
|
|
|
2996
3230
|
[version, name]
|
|
2997
3231
|
);
|
|
2998
3232
|
};
|
|
2999
|
-
const
|
|
3000
|
-
const { schema } = getMigrationsSchemaAndTable(config);
|
|
3233
|
+
const createMigrationsSchemaAndTable = async (adapter, config) => {
|
|
3234
|
+
const { schema, table } = getMigrationsSchemaAndTable(config);
|
|
3001
3235
|
if (schema) {
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
config.logger?.log(`Created schema ${schema}`);
|
|
3005
|
-
} catch (err) {
|
|
3006
|
-
if (err.code !== "42P06") {
|
|
3007
|
-
throw err;
|
|
3008
|
-
}
|
|
3236
|
+
const res2 = await createSchema$1(adapter, schema);
|
|
3237
|
+
if (res2 === "done") {
|
|
3238
|
+
config.logger?.log(`Created schema "${schema}"`);
|
|
3009
3239
|
}
|
|
3010
3240
|
}
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3241
|
+
const res = await createTable$1(
|
|
3242
|
+
adapter,
|
|
3243
|
+
`${schema ? `"${schema}"."${table}"` : `"${table}"`} (version TEXT NOT NULL, name TEXT NOT NULL)`
|
|
3244
|
+
);
|
|
3245
|
+
if (res === "done") {
|
|
3246
|
+
config.logger?.log(
|
|
3247
|
+
`Created migration versions table ${schema ? `"${schema}".` : ""}"${table}"`
|
|
3016
3248
|
);
|
|
3017
|
-
config.logger?.log("Created versions table");
|
|
3018
|
-
} catch (err) {
|
|
3019
|
-
if (err.code === "42P07") {
|
|
3020
|
-
config.logger?.log("Versions table exists");
|
|
3021
|
-
} else {
|
|
3022
|
-
throw err;
|
|
3023
|
-
}
|
|
3024
3249
|
}
|
|
3025
3250
|
};
|
|
3026
|
-
const deleteMigratedVersion = async (
|
|
3027
|
-
const res = await
|
|
3251
|
+
const deleteMigratedVersion = async (adapter, version, name, config) => {
|
|
3252
|
+
const res = await adapter.silentArrays(
|
|
3028
3253
|
`DELETE FROM ${migrationsSchemaTableSql(
|
|
3029
3254
|
config
|
|
3030
3255
|
)} WHERE version = $1 AND name = $2`,
|
|
@@ -3114,91 +3339,76 @@ async function renameMigrations(config, trx, versions, renameTo) {
|
|
|
3114
3339
|
return updatedVersions;
|
|
3115
3340
|
}
|
|
3116
3341
|
|
|
3117
|
-
const transactionIfSingle = (
|
|
3118
|
-
return
|
|
3119
|
-
};
|
|
3120
|
-
function makeMigrateFn(up, fn) {
|
|
3121
|
-
return async (params) => {
|
|
3122
|
-
const ctx = params
|
|
3123
|
-
const set = await getMigrations(ctx,
|
|
3124
|
-
const count = params
|
|
3125
|
-
const force = params
|
|
3342
|
+
const transactionIfSingle = (adapter, config, fn) => {
|
|
3343
|
+
return !adapter.isInTransaction() && config.transaction === "single" ? transaction(adapter, fn) : fn(adapter);
|
|
3344
|
+
};
|
|
3345
|
+
function makeMigrateFn(up, defaultCount, fn) {
|
|
3346
|
+
return async (db, config, params) => {
|
|
3347
|
+
const ctx = params?.ctx || {};
|
|
3348
|
+
const set = await getMigrations(ctx, config, up);
|
|
3349
|
+
const count = params?.count ?? defaultCount;
|
|
3350
|
+
const force = params?.force ?? false;
|
|
3351
|
+
const adapter = getMaybeTransactionAdapter(db);
|
|
3126
3352
|
let migrations;
|
|
3127
3353
|
try {
|
|
3128
|
-
await transactionIfSingle(
|
|
3354
|
+
await transactionIfSingle(adapter, config, async (trx) => {
|
|
3129
3355
|
const versions = await getMigratedVersionsMap(
|
|
3130
3356
|
ctx,
|
|
3131
3357
|
trx,
|
|
3132
|
-
|
|
3358
|
+
config,
|
|
3133
3359
|
set.renameTo
|
|
3134
3360
|
);
|
|
3135
|
-
migrations = await fn(trx,
|
|
3361
|
+
migrations = await fn(trx, config, set, versions, count, force);
|
|
3136
3362
|
});
|
|
3137
3363
|
} catch (err) {
|
|
3138
3364
|
if (err instanceof NoMigrationsTableError) {
|
|
3139
|
-
await transactionIfSingle(
|
|
3140
|
-
await
|
|
3365
|
+
await transactionIfSingle(adapter, config, async (trx) => {
|
|
3366
|
+
await createMigrationsSchemaAndTable(trx, config);
|
|
3141
3367
|
const versions = await getMigratedVersionsMap(
|
|
3142
3368
|
ctx,
|
|
3143
3369
|
trx,
|
|
3144
|
-
|
|
3370
|
+
config,
|
|
3145
3371
|
set.renameTo
|
|
3146
3372
|
);
|
|
3147
|
-
migrations = await fn(
|
|
3148
|
-
trx,
|
|
3149
|
-
params.config,
|
|
3150
|
-
set,
|
|
3151
|
-
versions,
|
|
3152
|
-
count,
|
|
3153
|
-
force
|
|
3154
|
-
);
|
|
3373
|
+
migrations = await fn(trx, config, set, versions, count, force);
|
|
3155
3374
|
});
|
|
3156
3375
|
} else {
|
|
3157
3376
|
throw err;
|
|
3158
3377
|
}
|
|
3159
3378
|
}
|
|
3160
|
-
|
|
3161
|
-
adapter
|
|
3379
|
+
config.afterChangeCommit?.({
|
|
3380
|
+
adapter,
|
|
3162
3381
|
up,
|
|
3163
3382
|
migrations
|
|
3164
3383
|
});
|
|
3165
3384
|
};
|
|
3166
3385
|
}
|
|
3167
|
-
const makeMigrateCommand = (migrateFn, defaultCount) => {
|
|
3168
|
-
return async (adapters, config, args) => {
|
|
3169
|
-
const arg = args[0];
|
|
3170
|
-
let force = arg === "force";
|
|
3171
|
-
let count = defaultCount;
|
|
3172
|
-
if (arg === "force") {
|
|
3173
|
-
force = true;
|
|
3174
|
-
} else {
|
|
3175
|
-
force = false;
|
|
3176
|
-
const num = arg === "all" ? Infinity : parseInt(arg || "");
|
|
3177
|
-
if (!isNaN(num)) {
|
|
3178
|
-
count = num;
|
|
3179
|
-
}
|
|
3180
|
-
}
|
|
3181
|
-
for (const adapter of adapters) {
|
|
3182
|
-
await migrateFn({ ctx: {}, adapter, config, count, force });
|
|
3183
|
-
}
|
|
3184
|
-
};
|
|
3185
|
-
};
|
|
3186
3386
|
const migrate = makeMigrateFn(
|
|
3187
3387
|
true,
|
|
3388
|
+
Infinity,
|
|
3188
3389
|
(trx, config, set, versions, count, force) => migrateOrRollback(trx, config, set, versions, count, true, false, force)
|
|
3189
3390
|
);
|
|
3190
|
-
const migrateAndClose = async (params) => {
|
|
3191
|
-
|
|
3192
|
-
await params
|
|
3391
|
+
const migrateAndClose = async (db, config, params) => {
|
|
3392
|
+
const adapter = getMaybeTransactionAdapter(db);
|
|
3393
|
+
await migrate(adapter, config, params);
|
|
3394
|
+
await adapter.close();
|
|
3395
|
+
};
|
|
3396
|
+
const runMigration = async (db, migration) => {
|
|
3397
|
+
await ensureTransaction(db, async (trx) => {
|
|
3398
|
+
clearChanges();
|
|
3399
|
+
const changes = await getChanges({ load: migration });
|
|
3400
|
+
const config = changes[0]?.config;
|
|
3401
|
+
await applyMigration(trx, true, changes, config);
|
|
3402
|
+
});
|
|
3193
3403
|
};
|
|
3194
|
-
const migrateCommand = makeMigrateCommand(migrate, Infinity);
|
|
3195
3404
|
const rollback = makeMigrateFn(
|
|
3196
3405
|
false,
|
|
3406
|
+
1,
|
|
3197
3407
|
(trx, config, set, versions, count, force) => migrateOrRollback(trx, config, set, versions, count, false, false, force)
|
|
3198
3408
|
);
|
|
3199
|
-
const rollbackCommand = makeMigrateCommand(rollback, 1);
|
|
3200
3409
|
const redo = makeMigrateFn(
|
|
3201
3410
|
true,
|
|
3411
|
+
1,
|
|
3202
3412
|
async (trx, config, set, versions, count, force) => {
|
|
3203
3413
|
set.migrations.reverse();
|
|
3204
3414
|
await migrateOrRollback(trx, config, set, versions, count, false, true);
|
|
@@ -3216,7 +3426,6 @@ const redo = makeMigrateFn(
|
|
|
3216
3426
|
);
|
|
3217
3427
|
}
|
|
3218
3428
|
);
|
|
3219
|
-
const redoCommand = makeMigrateCommand(redo, 1);
|
|
3220
3429
|
const getDb = (adapter) => createDbWithAdapter({ adapter });
|
|
3221
3430
|
const migrateOrRollback = async (trx, config, set, versions, count, up, redo2, force, skipLock) => {
|
|
3222
3431
|
const { sequence, map: versionsMap } = versions;
|
|
@@ -3255,7 +3464,7 @@ const migrateOrRollback = async (trx, config, set, versions, count, up, redo2, f
|
|
|
3255
3464
|
}
|
|
3256
3465
|
let loggedAboutStarting = false;
|
|
3257
3466
|
let migrations;
|
|
3258
|
-
const migrationRunner = config.transaction === "single" ?
|
|
3467
|
+
const migrationRunner = trx.isInTransaction() || config.transaction === "single" ? applyMigration : runMigrationInOwnTransaction;
|
|
3259
3468
|
for (const file of set.migrations) {
|
|
3260
3469
|
if (up && versionsMap[file.version] || !up && !versionsMap[file.version]) {
|
|
3261
3470
|
continue;
|
|
@@ -3323,347 +3532,53 @@ const checkMigrationOrder = (config, set, { sequence, map }, force) => {
|
|
|
3323
3532
|
`Cannot migrate ${path.basename(
|
|
3324
3533
|
file.path
|
|
3325
3534
|
)} because the higher position ${map[versionToString(config, last)]} was already migrated.
|
|
3326
|
-
Run \`**db command** up force\` to rollback the above migrations and migrate all`
|
|
3327
|
-
);
|
|
3328
|
-
}
|
|
3329
|
-
return version;
|
|
3330
|
-
}
|
|
3331
|
-
}
|
|
3332
|
-
return;
|
|
3333
|
-
};
|
|
3334
|
-
const changeCache = {};
|
|
3335
|
-
const getChanges = async (file, config) => {
|
|
3336
|
-
clearChanges();
|
|
3337
|
-
let changes = file.path ? changeCache[file.path] : void 0;
|
|
3338
|
-
if (!changes) {
|
|
3339
|
-
const module = await file.load();
|
|
3340
|
-
const exported = module?.default && toArray(module.default);
|
|
3341
|
-
if (config?.forceDefaultExports && !exported) {
|
|
3342
|
-
throw new RakeDbError(
|
|
3343
|
-
`Missing a default export in ${file.path} migration`
|
|
3344
|
-
);
|
|
3345
|
-
}
|
|
3346
|
-
changes = exported || getCurrentChanges();
|
|
3347
|
-
if (file.path) changeCache[file.path] = changes;
|
|
3348
|
-
}
|
|
3349
|
-
return changes;
|
|
3350
|
-
};
|
|
3351
|
-
const runMigrationInOwnTransaction = (adapter, ...rest) => {
|
|
3352
|
-
return transaction(adapter, (trx) => runMigration(trx, ...rest));
|
|
3353
|
-
};
|
|
3354
|
-
const runMigration = async (trx, up, changes, config) => {
|
|
3355
|
-
const db = createMigrationInterface(trx, up, config);
|
|
3356
|
-
if (changes.length) {
|
|
3357
|
-
const from = up ? 0 : changes.length - 1;
|
|
3358
|
-
const to = up ? changes.length : -1;
|
|
3359
|
-
const step = up ? 1 : -1;
|
|
3360
|
-
for (let i = from; i !== to; i += step) {
|
|
3361
|
-
await changes[i].fn(db, up);
|
|
3362
|
-
}
|
|
3363
|
-
}
|
|
3364
|
-
return db.adapter;
|
|
3365
|
-
};
|
|
3366
|
-
const changeMigratedVersion = async (adapter, up, file, config) => {
|
|
3367
|
-
await (up ? saveMigratedVersion : deleteMigratedVersion)(
|
|
3368
|
-
adapter,
|
|
3369
|
-
file.version,
|
|
3370
|
-
path.basename(file.path).slice(file.version.length + 1),
|
|
3371
|
-
config
|
|
3372
|
-
);
|
|
3373
|
-
};
|
|
3374
|
-
|
|
3375
|
-
const ESC = "\x1B";
|
|
3376
|
-
const CSI = `${ESC}[`;
|
|
3377
|
-
const cursorShow = `${CSI}?25h`;
|
|
3378
|
-
const cursorHide = `${CSI}?25l`;
|
|
3379
|
-
const { stdin, stdout } = process;
|
|
3380
|
-
const visibleChars = (s) => s.replace(
|
|
3381
|
-
// eslint-disable-next-line no-control-regex
|
|
3382
|
-
/[\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,
|
|
3383
|
-
""
|
|
3384
|
-
).length;
|
|
3385
|
-
const clear = (text) => {
|
|
3386
|
-
const rows = text.split(/\r?\n/).reduce(
|
|
3387
|
-
(rows2, line) => rows2 + 1 + Math.floor(Math.max(visibleChars(line) - 1, 0) / stdout.columns),
|
|
3388
|
-
0
|
|
3389
|
-
);
|
|
3390
|
-
let clear2 = "";
|
|
3391
|
-
for (let i = 0; i < rows; i++) {
|
|
3392
|
-
clear2 += `${CSI}2K`;
|
|
3393
|
-
if (i < rows - 1) {
|
|
3394
|
-
clear2 += `${CSI}${i < rows - 1 ? "1A" : "G"}`;
|
|
3395
|
-
}
|
|
3396
|
-
}
|
|
3397
|
-
return clear2;
|
|
3398
|
-
};
|
|
3399
|
-
const prompt = async ({
|
|
3400
|
-
render,
|
|
3401
|
-
onKeyPress,
|
|
3402
|
-
validate,
|
|
3403
|
-
value,
|
|
3404
|
-
cursor: showCursor
|
|
3405
|
-
}) => {
|
|
3406
|
-
stdin.resume();
|
|
3407
|
-
if (stdin.isTTY) stdin.setRawMode(true);
|
|
3408
|
-
stdin.setEncoding("utf-8");
|
|
3409
|
-
if (!showCursor) stdout.write(cursorHide);
|
|
3410
|
-
return new Promise((res) => {
|
|
3411
|
-
let prevText;
|
|
3412
|
-
const ctx = {
|
|
3413
|
-
value,
|
|
3414
|
-
submitted: false,
|
|
3415
|
-
render() {
|
|
3416
|
-
let text = (ctx.submitted ? colors.greenBold("\u2714") : colors.yellowBold("?")) + " " + render(ctx);
|
|
3417
|
-
if (ctx.submitted) text += "\n";
|
|
3418
|
-
stdout.write(prevText ? clear(prevText) + "\r" + text : text);
|
|
3419
|
-
prevText = text;
|
|
3420
|
-
},
|
|
3421
|
-
submit(value2) {
|
|
3422
|
-
if (value2 !== void 0) ctx.value = value2;
|
|
3423
|
-
if (ctx.value === void 0 || validate && !validate?.(ctx)) return;
|
|
3424
|
-
ctx.submitted = true;
|
|
3425
|
-
ctx.render();
|
|
3426
|
-
close();
|
|
3427
|
-
res(ctx.value);
|
|
3428
|
-
}
|
|
3429
|
-
};
|
|
3430
|
-
const close = () => {
|
|
3431
|
-
if (!showCursor) stdout.write(cursorShow);
|
|
3432
|
-
if (stdin.isTTY) stdin.setRawMode(false);
|
|
3433
|
-
stdin.off("data", keypress);
|
|
3434
|
-
stdin.pause();
|
|
3435
|
-
};
|
|
3436
|
-
const keypress = (s) => {
|
|
3437
|
-
if (s === "" || s === "") {
|
|
3438
|
-
close?.();
|
|
3439
|
-
process.exit(0);
|
|
3440
|
-
}
|
|
3441
|
-
if (s === "\r" || s === "\n" || s === "\r\n") {
|
|
3442
|
-
ctx.submit();
|
|
3443
|
-
} else {
|
|
3444
|
-
onKeyPress(ctx, s);
|
|
3445
|
-
}
|
|
3446
|
-
};
|
|
3447
|
-
stdin.on("data", keypress);
|
|
3448
|
-
ctx.render();
|
|
3449
|
-
});
|
|
3450
|
-
};
|
|
3451
|
-
const defaultActive = (s) => `${colors.blueBold("\u276F")} ${s}`;
|
|
3452
|
-
const defaultInactive = (s) => ` ${s}`;
|
|
3453
|
-
const promptSelect = ({
|
|
3454
|
-
message,
|
|
3455
|
-
options,
|
|
3456
|
-
active = defaultActive,
|
|
3457
|
-
inactive = defaultInactive
|
|
3458
|
-
}) => prompt({
|
|
3459
|
-
value: 0,
|
|
3460
|
-
render(ctx) {
|
|
3461
|
-
let text = `${message} ${colors.pale(
|
|
3462
|
-
"Use arrows or jk. Press enter to submit."
|
|
3463
|
-
)}
|
|
3464
|
-
`;
|
|
3465
|
-
for (let i = 0; i < options.length; i++) {
|
|
3466
|
-
text += (ctx.value === i ? active : inactive)(options[i]) + "\n";
|
|
3467
|
-
}
|
|
3468
|
-
return text;
|
|
3469
|
-
},
|
|
3470
|
-
onKeyPress(ctx, s) {
|
|
3471
|
-
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;
|
|
3472
|
-
ctx.render();
|
|
3473
|
-
}
|
|
3474
|
-
});
|
|
3475
|
-
const promptConfirm = ({
|
|
3476
|
-
message
|
|
3477
|
-
}) => prompt({
|
|
3478
|
-
value: true,
|
|
3479
|
-
render(ctx) {
|
|
3480
|
-
return `${colors.bright(message)}
|
|
3481
|
-
${ctx.submitted ? `> ${ctx.value ? colors.greenBold("Yes") : colors.yellowBold("No")}` : colors.pale(`> (Y/n)`)}
|
|
3482
|
-
`;
|
|
3483
|
-
},
|
|
3484
|
-
onKeyPress(ctx, s) {
|
|
3485
|
-
let ok;
|
|
3486
|
-
if (s === "y" || s === "Y") ok = true;
|
|
3487
|
-
else if (s === "n" || s === "N") ok = false;
|
|
3488
|
-
if (ok !== void 0) {
|
|
3489
|
-
ctx.submit(ok);
|
|
3490
|
-
}
|
|
3491
|
-
}
|
|
3492
|
-
});
|
|
3493
|
-
const promptText = ({
|
|
3494
|
-
message,
|
|
3495
|
-
default: def = "",
|
|
3496
|
-
password,
|
|
3497
|
-
min
|
|
3498
|
-
}) => {
|
|
3499
|
-
let showDefault = true;
|
|
3500
|
-
let x = 0;
|
|
3501
|
-
const renderValue = (ctx) => password ? "*".repeat(ctx.value.length) : ctx.value;
|
|
3502
|
-
return prompt({
|
|
3503
|
-
value: def,
|
|
3504
|
-
cursor: true,
|
|
3505
|
-
validate: (ctx) => !min || ctx.value.length >= min,
|
|
3506
|
-
render(ctx) {
|
|
3507
|
-
let text = `${colors.bright(message)}
|
|
3508
|
-
> ${ctx.submitted ? renderValue(ctx) : showDefault ? colors.pale(def) + "\b".repeat(def.length) : ctx.value}`;
|
|
3509
|
-
if (ctx.submitted) text += "\n";
|
|
3510
|
-
return text;
|
|
3511
|
-
},
|
|
3512
|
-
onKeyPress(ctx, s) {
|
|
3513
|
-
let value = showDefault ? "" : ctx.value;
|
|
3514
|
-
if (s === "\x1B[D" && x > 0) {
|
|
3515
|
-
x--;
|
|
3516
|
-
stdout.write("\b");
|
|
3517
|
-
} else if (s === "\x1B[C" && x < value.length) {
|
|
3518
|
-
stdout.write(value[x]);
|
|
3519
|
-
x++;
|
|
3520
|
-
}
|
|
3521
|
-
if (s !== "\x7F" && s !== "\x1B[3~" && !visibleChars(s)) return;
|
|
3522
|
-
if (showDefault) {
|
|
3523
|
-
showDefault = false;
|
|
3524
|
-
stdout.write(" ".repeat(def.length) + "\b".repeat(def.length));
|
|
3525
|
-
}
|
|
3526
|
-
const prev = value;
|
|
3527
|
-
const prevX = x;
|
|
3528
|
-
if (s === "\x7F") {
|
|
3529
|
-
if (x > 0) {
|
|
3530
|
-
value = value.slice(0, x - 1) + value.slice(x);
|
|
3531
|
-
x--;
|
|
3532
|
-
}
|
|
3533
|
-
} else if (s === "\x1B[3~") {
|
|
3534
|
-
if (x < value.length) {
|
|
3535
|
-
value = value.slice(0, x) + value.slice(x + 1);
|
|
3536
|
-
}
|
|
3537
|
-
} else {
|
|
3538
|
-
value = value.slice(0, x) + s + value.slice(x);
|
|
3539
|
-
x++;
|
|
3540
|
-
}
|
|
3541
|
-
ctx.value = value;
|
|
3542
|
-
const spaces = prev.length - value.length;
|
|
3543
|
-
stdout.write(
|
|
3544
|
-
"\b".repeat(prevX) + renderValue(ctx) + (spaces > 0 ? " ".repeat(spaces) + "\b".repeat(spaces) : "") + "\b".repeat(value.length - x)
|
|
3545
|
-
);
|
|
3546
|
-
}
|
|
3547
|
-
});
|
|
3548
|
-
};
|
|
3549
|
-
|
|
3550
|
-
const execute = async (adapter, sql) => {
|
|
3551
|
-
try {
|
|
3552
|
-
await adapter.query(sql);
|
|
3553
|
-
return "ok";
|
|
3554
|
-
} catch (error) {
|
|
3555
|
-
const err = error;
|
|
3556
|
-
if (typeof err.message === "string" && err.message.includes("sslmode=require")) {
|
|
3557
|
-
return "ssl required";
|
|
3558
|
-
}
|
|
3559
|
-
if (err.code === "42P04" || err.code === "3D000") {
|
|
3560
|
-
return "already";
|
|
3561
|
-
} else if (err.code === "42501" || typeof err.message === "string" && err.message.includes("password authentication failed")) {
|
|
3562
|
-
return "forbidden";
|
|
3563
|
-
} else {
|
|
3564
|
-
return { error };
|
|
3565
|
-
}
|
|
3566
|
-
} finally {
|
|
3567
|
-
await adapter.close();
|
|
3568
|
-
}
|
|
3569
|
-
};
|
|
3570
|
-
const createOrDrop = async (adapter, adminAdapter, config, args) => {
|
|
3571
|
-
const params = {
|
|
3572
|
-
database: adapter.getDatabase(),
|
|
3573
|
-
user: adapter.getUser()
|
|
3574
|
-
};
|
|
3575
|
-
const result = await execute(
|
|
3576
|
-
adminAdapter.reconfigure({ database: "postgres" }),
|
|
3577
|
-
args.sql(params)
|
|
3578
|
-
);
|
|
3579
|
-
if (result === "ok") {
|
|
3580
|
-
config.logger?.log(args.successMessage(params));
|
|
3581
|
-
} else if (result === "already") {
|
|
3582
|
-
config.logger?.log(args.alreadyMessage(params));
|
|
3583
|
-
} else if (result === "ssl required") {
|
|
3584
|
-
config.logger?.log(
|
|
3585
|
-
"SSL is required: append ?ssl=true to the database url string"
|
|
3586
|
-
);
|
|
3587
|
-
return;
|
|
3588
|
-
} else if (result === "forbidden") {
|
|
3589
|
-
let message = `Permission denied to ${args.create ? "create" : "drop"} database.`;
|
|
3590
|
-
const host = adminAdapter.getHost();
|
|
3591
|
-
const isLocal = host === "localhost";
|
|
3592
|
-
if (!isLocal) {
|
|
3593
|
-
message += `
|
|
3594
|
-
Don't use this command for database service providers, only for a local db.`;
|
|
3595
|
-
}
|
|
3596
|
-
config.logger?.log(message);
|
|
3597
|
-
const params2 = await askForAdminCredentials(args.create);
|
|
3598
|
-
if (!params2) return;
|
|
3599
|
-
await createOrDrop(adapter, adminAdapter.reconfigure(params2), config, args);
|
|
3600
|
-
return;
|
|
3601
|
-
} else {
|
|
3602
|
-
throw result.error;
|
|
3603
|
-
}
|
|
3604
|
-
if (!args.create) return;
|
|
3605
|
-
const newlyConnectedAdapter = adapter.reconfigure({});
|
|
3606
|
-
await createMigrationsTable(newlyConnectedAdapter, config);
|
|
3607
|
-
await newlyConnectedAdapter.close();
|
|
3608
|
-
};
|
|
3609
|
-
const createDb = async (adapters, config) => {
|
|
3610
|
-
for (const adapter of adapters) {
|
|
3611
|
-
await createOrDrop(adapter, adapter, config, {
|
|
3612
|
-
sql({ database, user }) {
|
|
3613
|
-
return `CREATE DATABASE "${database}"${user ? ` OWNER "${user}"` : ""}`;
|
|
3614
|
-
},
|
|
3615
|
-
successMessage({ database }) {
|
|
3616
|
-
return `Database ${database} successfully created`;
|
|
3617
|
-
},
|
|
3618
|
-
alreadyMessage({ database }) {
|
|
3619
|
-
return `Database ${database} already exists`;
|
|
3620
|
-
},
|
|
3621
|
-
create: true
|
|
3622
|
-
});
|
|
3623
|
-
}
|
|
3624
|
-
};
|
|
3625
|
-
const dropDb = async (adapters, config) => {
|
|
3626
|
-
for (const adapter of adapters) {
|
|
3627
|
-
await createOrDrop(adapter, adapter, config, {
|
|
3628
|
-
sql({ database }) {
|
|
3629
|
-
return `DROP DATABASE "${database}"`;
|
|
3630
|
-
},
|
|
3631
|
-
successMessage({ database }) {
|
|
3632
|
-
return `Database ${database} was successfully dropped`;
|
|
3633
|
-
},
|
|
3634
|
-
alreadyMessage({ database }) {
|
|
3635
|
-
return `Database ${database} does not exist`;
|
|
3535
|
+
Run \`**db command** up force\` to rollback the above migrations and migrate all`
|
|
3536
|
+
);
|
|
3636
3537
|
}
|
|
3637
|
-
|
|
3538
|
+
return version;
|
|
3539
|
+
}
|
|
3638
3540
|
}
|
|
3541
|
+
return;
|
|
3639
3542
|
};
|
|
3640
|
-
const
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3543
|
+
const changeCache = {};
|
|
3544
|
+
const getChanges = async (file, config) => {
|
|
3545
|
+
clearChanges();
|
|
3546
|
+
let changes = file.path ? changeCache[file.path] : void 0;
|
|
3547
|
+
if (!changes) {
|
|
3548
|
+
const module = await file.load();
|
|
3549
|
+
const exported = module?.default && toArray(module.default);
|
|
3550
|
+
if (config?.forceDefaultExports && !exported) {
|
|
3551
|
+
throw new RakeDbError(
|
|
3552
|
+
`Missing a default export in ${file.path} migration`
|
|
3553
|
+
);
|
|
3554
|
+
}
|
|
3555
|
+
changes = exported || getCurrentChanges();
|
|
3556
|
+
if (file.path) changeCache[file.path] = changes;
|
|
3645
3557
|
}
|
|
3558
|
+
return changes;
|
|
3646
3559
|
};
|
|
3647
|
-
const
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3560
|
+
const runMigrationInOwnTransaction = (adapter, ...rest) => {
|
|
3561
|
+
return transaction(adapter, (trx) => applyMigration(trx, ...rest));
|
|
3562
|
+
};
|
|
3563
|
+
const applyMigration = async (trx, up, changes, config) => {
|
|
3564
|
+
const db = createMigrationInterface(trx, up, config);
|
|
3565
|
+
if (changes.length) {
|
|
3566
|
+
const from = up ? 0 : changes.length - 1;
|
|
3567
|
+
const to = up ? changes.length : -1;
|
|
3568
|
+
const step = up ? 1 : -1;
|
|
3569
|
+
for (let i = from; i !== to; i += step) {
|
|
3570
|
+
await changes[i].fn(db, up);
|
|
3571
|
+
}
|
|
3653
3572
|
}
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
return {
|
|
3664
|
-
user,
|
|
3665
|
-
password: password || void 0
|
|
3666
|
-
};
|
|
3573
|
+
return db.adapter;
|
|
3574
|
+
};
|
|
3575
|
+
const changeMigratedVersion = async (adapter, up, file, config) => {
|
|
3576
|
+
await (up ? saveMigratedVersion : deleteMigratedVersion)(
|
|
3577
|
+
adapter,
|
|
3578
|
+
file.version,
|
|
3579
|
+
path.basename(file.path).slice(file.version.length + 1),
|
|
3580
|
+
config
|
|
3581
|
+
);
|
|
3667
3582
|
};
|
|
3668
3583
|
|
|
3669
3584
|
const runRecurrentMigrations = async (adapters, config) => {
|
|
@@ -3704,6 +3619,131 @@ const readdirRecursive = async (dirPath, cb) => {
|
|
|
3704
3619
|
);
|
|
3705
3620
|
};
|
|
3706
3621
|
|
|
3622
|
+
const createDatabaseCommand = (adapters, config, dontClose) => createOrDropDatabase("create", adapters, config, dontClose);
|
|
3623
|
+
const dropDatabaseCommand = (adapters, config) => createOrDropDatabase("drop", adapters, config);
|
|
3624
|
+
const createOrDropDatabase = async (action, adapters, config, dontClose) => {
|
|
3625
|
+
const fn = action === "create" ? createDatabase : dropDatabase;
|
|
3626
|
+
for (const adapter of adapters) {
|
|
3627
|
+
const database = adapter.getDatabase();
|
|
3628
|
+
const owner = adapter.getUser();
|
|
3629
|
+
const res = await run(
|
|
3630
|
+
adapter.reconfigure({ database: "postgres" }),
|
|
3631
|
+
config,
|
|
3632
|
+
{
|
|
3633
|
+
command: (adapter2) => fn(adapter2, {
|
|
3634
|
+
database,
|
|
3635
|
+
owner
|
|
3636
|
+
}),
|
|
3637
|
+
doneMessage: () => `Database ${database} successfully ${action === "create" ? "created" : "dropped"}`,
|
|
3638
|
+
alreadyMessage: () => `Database ${database} ${action === "create" ? "already exists" : "does not exist"}`,
|
|
3639
|
+
deniedMessage: () => `Permission denied to ${action} database.`,
|
|
3640
|
+
askAdminCreds: () => askForAdminCredentials(action === "create")
|
|
3641
|
+
}
|
|
3642
|
+
);
|
|
3643
|
+
if (!res) continue;
|
|
3644
|
+
if (action === "create") {
|
|
3645
|
+
await adapter.transaction(void 0, async (tx) => {
|
|
3646
|
+
if (config.schema) {
|
|
3647
|
+
const quoted = `"${config.schema}"`;
|
|
3648
|
+
const res2 = await createSchema$1(tx, quoted);
|
|
3649
|
+
if (res2 === "done") {
|
|
3650
|
+
config.logger?.log(`Created schema ${quoted}`);
|
|
3651
|
+
}
|
|
3652
|
+
}
|
|
3653
|
+
await createMigrationsSchemaAndTable(tx, config);
|
|
3654
|
+
});
|
|
3655
|
+
if (!dontClose) {
|
|
3656
|
+
await adapter.close();
|
|
3657
|
+
}
|
|
3658
|
+
}
|
|
3659
|
+
}
|
|
3660
|
+
};
|
|
3661
|
+
const resetDatabaseCommand = async (adapters, config) => {
|
|
3662
|
+
await createOrDropDatabase("create", adapters, config);
|
|
3663
|
+
await createOrDropDatabase("drop", adapters, config, true);
|
|
3664
|
+
for (const adapter of adapters) {
|
|
3665
|
+
await migrate(adapter, config);
|
|
3666
|
+
}
|
|
3667
|
+
if (config.recurrentPath) {
|
|
3668
|
+
await runRecurrentMigrations(adapters, config);
|
|
3669
|
+
}
|
|
3670
|
+
await Promise.all(adapters.map((adapter) => adapter.close()));
|
|
3671
|
+
};
|
|
3672
|
+
const run = async (adapter, config, params) => {
|
|
3673
|
+
try {
|
|
3674
|
+
const res = await params.command(adapter);
|
|
3675
|
+
config.logger?.log(
|
|
3676
|
+
res === "done" ? params.doneMessage() : params.alreadyMessage()
|
|
3677
|
+
);
|
|
3678
|
+
await adapter.close();
|
|
3679
|
+
return true;
|
|
3680
|
+
} catch (err) {
|
|
3681
|
+
if (err instanceof CreateOrDropError) {
|
|
3682
|
+
if (err.status === "ssl-required") {
|
|
3683
|
+
config.logger?.log(
|
|
3684
|
+
"SSL is required: append ?ssl=true to the database url string"
|
|
3685
|
+
);
|
|
3686
|
+
return false;
|
|
3687
|
+
}
|
|
3688
|
+
if (err.status === "forbidden" || err.status === "auth-failed") {
|
|
3689
|
+
let message = params.deniedMessage();
|
|
3690
|
+
const host = adapter.getHost();
|
|
3691
|
+
const isLocal = host === "localhost";
|
|
3692
|
+
if (!isLocal) {
|
|
3693
|
+
message += `
|
|
3694
|
+
Don't use this command for database service providers, only for a local db.`;
|
|
3695
|
+
}
|
|
3696
|
+
config.logger?.log(message);
|
|
3697
|
+
const creds = await params.askAdminCreds();
|
|
3698
|
+
if (!creds) return false;
|
|
3699
|
+
return run(adapter.reconfigure(creds), config, params);
|
|
3700
|
+
}
|
|
3701
|
+
}
|
|
3702
|
+
throw err;
|
|
3703
|
+
}
|
|
3704
|
+
};
|
|
3705
|
+
const askForAdminCredentials = async (create) => {
|
|
3706
|
+
const ok = await promptConfirm({
|
|
3707
|
+
message: `Would you like to share admin credentials to ${create ? "create" : "drop"} a database?`
|
|
3708
|
+
});
|
|
3709
|
+
if (!ok) {
|
|
3710
|
+
return;
|
|
3711
|
+
}
|
|
3712
|
+
const user = await promptText({
|
|
3713
|
+
message: "Enter admin user:",
|
|
3714
|
+
default: "postgres",
|
|
3715
|
+
min: 1
|
|
3716
|
+
});
|
|
3717
|
+
const password = await promptText({
|
|
3718
|
+
message: "Enter admin password:",
|
|
3719
|
+
password: true
|
|
3720
|
+
});
|
|
3721
|
+
return {
|
|
3722
|
+
user,
|
|
3723
|
+
password: password || void 0
|
|
3724
|
+
};
|
|
3725
|
+
};
|
|
3726
|
+
|
|
3727
|
+
const makeMigrateOrRollback = (fn) => async (adapters, config, args) => {
|
|
3728
|
+
const arg = args[0];
|
|
3729
|
+
let force;
|
|
3730
|
+
let count;
|
|
3731
|
+
if (arg === "force") {
|
|
3732
|
+
force = true;
|
|
3733
|
+
} else {
|
|
3734
|
+
const num = arg === "all" ? Infinity : parseInt(arg || "");
|
|
3735
|
+
if (!isNaN(num)) {
|
|
3736
|
+
count = num;
|
|
3737
|
+
}
|
|
3738
|
+
}
|
|
3739
|
+
for (const adapter of adapters) {
|
|
3740
|
+
await fn(adapter, config, { ctx: {}, count, force });
|
|
3741
|
+
}
|
|
3742
|
+
};
|
|
3743
|
+
const migrateCommand = makeMigrateOrRollback(migrate);
|
|
3744
|
+
const rollbackCommand = makeMigrateOrRollback(rollback);
|
|
3745
|
+
const redoCommand = makeMigrateOrRollback(redo);
|
|
3746
|
+
|
|
3707
3747
|
const astToGenerateItems = (config, asts, currentSchema) => {
|
|
3708
3748
|
return asts.map((ast) => astToGenerateItem(config, ast, currentSchema));
|
|
3709
3749
|
};
|
|
@@ -3715,7 +3755,10 @@ const astToGenerateItem = (config, ast, currentSchema) => {
|
|
|
3715
3755
|
const resolveType = (type) => {
|
|
3716
3756
|
let dep = typeSchemaCache.get(type);
|
|
3717
3757
|
if (!dep) {
|
|
3718
|
-
const [schema = currentSchema, name] = getSchemaAndTableFromName(
|
|
3758
|
+
const [schema = currentSchema, name] = getSchemaAndTableFromName(
|
|
3759
|
+
config,
|
|
3760
|
+
type
|
|
3761
|
+
);
|
|
3719
3762
|
dep = `${schema}.${name}`;
|
|
3720
3763
|
typeSchemaCache.set(type, dep);
|
|
3721
3764
|
}
|
|
@@ -3905,7 +3948,10 @@ const analyzeTableColumns = (config, currentSchema, schema, table, deps, resolve
|
|
|
3905
3948
|
config.snakeCase
|
|
3906
3949
|
)
|
|
3907
3950
|
);
|
|
3908
|
-
const [s = currentSchema, t] = getForeignKeyTable(
|
|
3951
|
+
const [s = currentSchema, t] = getForeignKeyTable(
|
|
3952
|
+
config,
|
|
3953
|
+
fkey.fnOrTable
|
|
3954
|
+
);
|
|
3909
3955
|
const foreignTable = `${s}.${t}`;
|
|
3910
3956
|
if (foreignTable !== table) {
|
|
3911
3957
|
deps.push(foreignTable);
|
|
@@ -3950,6 +3996,7 @@ const analyzeTableData = (config, currentSchema, schema, table, keys, deps, data
|
|
|
3950
3996
|
);
|
|
3951
3997
|
if (constraint.references) {
|
|
3952
3998
|
const [s = currentSchema, t] = getForeignKeyTable(
|
|
3999
|
+
config,
|
|
3953
4000
|
constraint.references.fnOrTable
|
|
3954
4001
|
);
|
|
3955
4002
|
deps.push(`${s}.${t}`);
|
|
@@ -5411,36 +5458,239 @@ const checkIfIsOuterRecursiveFkey = (data, table, references) => {
|
|
|
5411
5458
|
break;
|
|
5412
5459
|
}
|
|
5413
5460
|
}
|
|
5414
|
-
return false;
|
|
5415
|
-
};
|
|
5461
|
+
return false;
|
|
5462
|
+
};
|
|
5463
|
+
|
|
5464
|
+
const pullDbStructure = async (adapter, config) => {
|
|
5465
|
+
const currentSchema = adapter.searchPath || "public";
|
|
5466
|
+
const ctx = makeStructureToAstCtx(config, currentSchema);
|
|
5467
|
+
const ast = await structureToAst(ctx, adapter, config);
|
|
5468
|
+
const result = astToMigration(currentSchema, config, ast);
|
|
5469
|
+
if (!result) return;
|
|
5470
|
+
const version = await makeFileVersion({}, config);
|
|
5471
|
+
await writeMigrationFile(config, version, "pull", result);
|
|
5472
|
+
const silentQueries = Object.assign(adapter, {
|
|
5473
|
+
silentQuery: adapter.query,
|
|
5474
|
+
silentArrays: adapter.arrays
|
|
5475
|
+
});
|
|
5476
|
+
await saveMigratedVersion(silentQueries, version, "pull", config);
|
|
5477
|
+
const unsupportedEntries = Object.entries(ctx.unsupportedTypes);
|
|
5478
|
+
const len = unsupportedEntries.length;
|
|
5479
|
+
if (len) {
|
|
5480
|
+
let count = 0;
|
|
5481
|
+
config.logger?.warn(
|
|
5482
|
+
`Found unsupported types:
|
|
5483
|
+
${unsupportedEntries.map(([type, columns]) => {
|
|
5484
|
+
count += columns.length;
|
|
5485
|
+
return `- ${type} is used for column${columns.length > 1 ? "s" : ""} ${columns.join(", ")}`;
|
|
5486
|
+
}).join("\n")}
|
|
5487
|
+
Append \`as\` method manually to ${count > 1 ? "these" : "this"} column${count > 1 ? "s" : ""} to treat ${count > 1 ? "them" : "it"} as other column type`
|
|
5488
|
+
);
|
|
5489
|
+
}
|
|
5490
|
+
config.logger?.log("Database pulled successfully");
|
|
5491
|
+
};
|
|
5492
|
+
|
|
5493
|
+
const migrationConfigDefaults = {
|
|
5494
|
+
schemaConfig: defaultSchemaConfig,
|
|
5495
|
+
migrationsPath: path.join("src", "db", "migrations"),
|
|
5496
|
+
migrationId: { serial: 4 },
|
|
5497
|
+
migrationsTable: "schemaMigrations",
|
|
5498
|
+
snakeCase: false,
|
|
5499
|
+
commands: {},
|
|
5500
|
+
log: true,
|
|
5501
|
+
logger: console,
|
|
5502
|
+
import() {
|
|
5503
|
+
throw new Error(
|
|
5504
|
+
"Add `import: (path) => import(path),` setting to `rakeDb` config"
|
|
5505
|
+
);
|
|
5506
|
+
}
|
|
5507
|
+
};
|
|
5508
|
+
const ensureMigrationsPath = (config) => {
|
|
5509
|
+
if (!config.migrationsPath) {
|
|
5510
|
+
config.migrationsPath = migrationConfigDefaults.migrationsPath;
|
|
5511
|
+
}
|
|
5512
|
+
if (!path.isAbsolute(config.migrationsPath)) {
|
|
5513
|
+
config.migrationsPath = path.resolve(
|
|
5514
|
+
config.basePath,
|
|
5515
|
+
config.migrationsPath
|
|
5516
|
+
);
|
|
5517
|
+
}
|
|
5518
|
+
return config;
|
|
5519
|
+
};
|
|
5520
|
+
const ensureBasePathAndDbScript = (config, intermediateCallers2 = 0) => {
|
|
5521
|
+
if (config.basePath && config.dbScript) return config;
|
|
5522
|
+
let filePath = getStackTrace()?.[3 + intermediateCallers2]?.getFileName();
|
|
5523
|
+
if (!filePath) {
|
|
5524
|
+
throw new Error(
|
|
5525
|
+
"Failed to determine path to db script. Please set basePath option of rakeDb"
|
|
5526
|
+
);
|
|
5527
|
+
}
|
|
5528
|
+
if (filePath.startsWith("file://")) {
|
|
5529
|
+
filePath = fileURLToPath(filePath);
|
|
5530
|
+
}
|
|
5531
|
+
const ext = path.extname(filePath);
|
|
5532
|
+
if (ext !== ".ts" && ext !== ".js" && ext !== ".mjs") {
|
|
5533
|
+
throw new Error(
|
|
5534
|
+
`Add a .ts suffix to the "${path.basename(filePath)}" when calling it`
|
|
5535
|
+
);
|
|
5536
|
+
}
|
|
5537
|
+
config.basePath = path.dirname(filePath);
|
|
5538
|
+
config.dbScript = path.basename(filePath);
|
|
5539
|
+
return config;
|
|
5540
|
+
};
|
|
5541
|
+
let intermediateCallers = 0;
|
|
5542
|
+
const incrementIntermediateCaller = () => {
|
|
5543
|
+
intermediateCallers++;
|
|
5544
|
+
};
|
|
5545
|
+
const makeRakeDbConfig = (config, args) => {
|
|
5546
|
+
const ic = intermediateCallers;
|
|
5547
|
+
intermediateCallers = 0;
|
|
5548
|
+
const result = {
|
|
5549
|
+
...migrationConfigDefaults,
|
|
5550
|
+
...config,
|
|
5551
|
+
__rakeDbConfig: true
|
|
5552
|
+
};
|
|
5553
|
+
if (!result.log) {
|
|
5554
|
+
delete result.logger;
|
|
5555
|
+
}
|
|
5556
|
+
ensureBasePathAndDbScript(result, ic);
|
|
5557
|
+
ensureMigrationsPath(result);
|
|
5558
|
+
if (!result.recurrentPath) {
|
|
5559
|
+
result.recurrentPath = path.join(
|
|
5560
|
+
result.migrationsPath,
|
|
5561
|
+
"recurrent"
|
|
5562
|
+
);
|
|
5563
|
+
}
|
|
5564
|
+
if ("recurrentPath" in result && !path.isAbsolute(result.recurrentPath)) {
|
|
5565
|
+
result.recurrentPath = path.resolve(result.basePath, result.recurrentPath);
|
|
5566
|
+
}
|
|
5567
|
+
if ("baseTable" in config && config.baseTable) {
|
|
5568
|
+
const { types, snakeCase, language } = config.baseTable.prototype;
|
|
5569
|
+
result.columnTypes = types || makeColumnTypes(defaultSchemaConfig);
|
|
5570
|
+
if (snakeCase) result.snakeCase = true;
|
|
5571
|
+
if (language) result.language = language;
|
|
5572
|
+
} else {
|
|
5573
|
+
const ct = "columnTypes" in config && config.columnTypes;
|
|
5574
|
+
result.columnTypes = (typeof ct === "function" ? ct(
|
|
5575
|
+
makeColumnTypes(defaultSchemaConfig)
|
|
5576
|
+
) : ct) || makeColumnTypes(defaultSchemaConfig);
|
|
5577
|
+
}
|
|
5578
|
+
if (config.migrationId === "serial") {
|
|
5579
|
+
result.migrationId = { serial: 4 };
|
|
5580
|
+
}
|
|
5581
|
+
const transaction = getCliParam(args, "transaction");
|
|
5582
|
+
if (transaction) {
|
|
5583
|
+
if (transaction !== "single" && transaction !== "per-migration") {
|
|
5584
|
+
throw new Error(
|
|
5585
|
+
`Unsupported transaction param ${transaction}, expected single or per-migration`
|
|
5586
|
+
);
|
|
5587
|
+
}
|
|
5588
|
+
result.transaction = transaction;
|
|
5589
|
+
} else if (!result.transaction) {
|
|
5590
|
+
result.transaction = "single";
|
|
5591
|
+
}
|
|
5592
|
+
let c = rakeDbCommands;
|
|
5593
|
+
if (config.commands) {
|
|
5594
|
+
c = { ...c };
|
|
5595
|
+
const commands = config.commands;
|
|
5596
|
+
for (const key in commands) {
|
|
5597
|
+
const command = commands[key];
|
|
5598
|
+
c[key] = typeof command === "function" ? { run: command } : command;
|
|
5599
|
+
}
|
|
5600
|
+
}
|
|
5601
|
+
result.commands = c;
|
|
5602
|
+
return result;
|
|
5603
|
+
};
|
|
5604
|
+
|
|
5605
|
+
const listMigrationsStatuses = async (adapters, config, params) => {
|
|
5606
|
+
const ctx = {};
|
|
5607
|
+
const [{ migrations }, ...migrated] = await Promise.all([
|
|
5608
|
+
getMigrations(ctx, config, true),
|
|
5609
|
+
...adapters.map((adapter) => getMigratedVersionsMap(ctx, adapter, config))
|
|
5610
|
+
]);
|
|
5611
|
+
const map = {};
|
|
5612
|
+
let maxVersionLength = 12;
|
|
5613
|
+
let maxNameLength = 4;
|
|
5614
|
+
for (let i = 0; i < adapters.length; i++) {
|
|
5615
|
+
const list = migrated[i];
|
|
5616
|
+
const key = Object.entries(list.map).map(([version, up]) => `${version}${up ? "t" : "f"}`).join("");
|
|
5617
|
+
const database = adapters[i].getDatabase();
|
|
5618
|
+
if (map[key]) {
|
|
5619
|
+
map[key].databases.push(database);
|
|
5620
|
+
continue;
|
|
5621
|
+
}
|
|
5622
|
+
map[key] = {
|
|
5623
|
+
databases: [database],
|
|
5624
|
+
migrations: migrations.map((item) => {
|
|
5625
|
+
if (item.version.length > maxVersionLength) {
|
|
5626
|
+
maxVersionLength = item.version.length;
|
|
5627
|
+
}
|
|
5628
|
+
const name = path.parse(item.path).name.slice(item.version.length + 1).replace(
|
|
5629
|
+
/([a-z])([A-Z])/g,
|
|
5630
|
+
(_, a, b) => `${a} ${b.toLocaleLowerCase()}`
|
|
5631
|
+
).replace(/[-_](.)/g, (_, char) => ` ${char.toLocaleLowerCase()}`).replace(/^\w/, (match) => match.toLocaleUpperCase());
|
|
5632
|
+
if (name.length > maxNameLength) {
|
|
5633
|
+
maxNameLength = name.length;
|
|
5634
|
+
}
|
|
5635
|
+
return {
|
|
5636
|
+
up: !!list.map[item.version],
|
|
5637
|
+
version: item.version,
|
|
5638
|
+
name,
|
|
5639
|
+
url: pathToFileURL(item.path)
|
|
5640
|
+
};
|
|
5641
|
+
})
|
|
5642
|
+
};
|
|
5643
|
+
}
|
|
5644
|
+
const showUrl = params?.showUrl;
|
|
5645
|
+
const asIs = (s) => s;
|
|
5646
|
+
const c = typeof config.log === "object" && config.log.colors === false ? {
|
|
5647
|
+
yellow: asIs,
|
|
5648
|
+
green: asIs,
|
|
5649
|
+
red: asIs,
|
|
5650
|
+
blue: asIs
|
|
5651
|
+
} : colors;
|
|
5652
|
+
const log = Object.values(map).map(({ databases, migrations: migrations2 }) => {
|
|
5653
|
+
let log2 = ` ${c.yellow("Database:")} ${databases.join(", ")}`;
|
|
5654
|
+
if (migrations2.length === 0) {
|
|
5655
|
+
return log2 + `
|
|
5416
5656
|
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
await saveMigratedVersion(silentQueries, version, "pull", config);
|
|
5430
|
-
const unsupportedEntries = Object.entries(ctx.unsupportedTypes);
|
|
5431
|
-
const len = unsupportedEntries.length;
|
|
5432
|
-
if (len) {
|
|
5433
|
-
let count = 0;
|
|
5434
|
-
config.logger?.warn(
|
|
5435
|
-
`Found unsupported types:
|
|
5436
|
-
${unsupportedEntries.map(([type, columns]) => {
|
|
5437
|
-
count += columns.length;
|
|
5438
|
-
return `- ${type} is used for column${columns.length > 1 ? "s" : ""} ${columns.join(", ")}`;
|
|
5439
|
-
}).join("\n")}
|
|
5440
|
-
Append \`as\` method manually to ${count > 1 ? "these" : "this"} column${count > 1 ? "s" : ""} to treat ${count > 1 ? "them" : "it"} as other column type`
|
|
5657
|
+
No migrations available`;
|
|
5658
|
+
}
|
|
5659
|
+
const lineSeparator = c.yellow(
|
|
5660
|
+
makeChars(14 + maxVersionLength + maxNameLength, "-")
|
|
5661
|
+
);
|
|
5662
|
+
const columnSeparator = c.yellow("|");
|
|
5663
|
+
log2 += "\n\n " + c.yellow(
|
|
5664
|
+
`Status | Migration ID${makeChars(
|
|
5665
|
+
maxVersionLength - 12,
|
|
5666
|
+
" "
|
|
5667
|
+
)} | Name
|
|
5668
|
+
${lineSeparator}`
|
|
5441
5669
|
);
|
|
5670
|
+
for (const migration of migrations2) {
|
|
5671
|
+
log2 += `
|
|
5672
|
+
${migration.up ? ` ${c.green("Up")} ` : c.red("Down")} ${columnSeparator} ${c.blue(migration.version)}${makeChars(
|
|
5673
|
+
maxVersionLength - migration.version.length,
|
|
5674
|
+
" "
|
|
5675
|
+
)} ${columnSeparator} ${migration.name}`;
|
|
5676
|
+
if (showUrl) {
|
|
5677
|
+
log2 += `
|
|
5678
|
+
${migration.url}
|
|
5679
|
+
`;
|
|
5680
|
+
}
|
|
5681
|
+
}
|
|
5682
|
+
return log2 += showUrl ? lineSeparator : `
|
|
5683
|
+
${lineSeparator}`;
|
|
5684
|
+
}).join("\n\n");
|
|
5685
|
+
(config.logger ?? console).log(log);
|
|
5686
|
+
await Promise.all(adapters.map((adapter) => adapter.close()));
|
|
5687
|
+
};
|
|
5688
|
+
const makeChars = (count, char) => {
|
|
5689
|
+
let chars = "";
|
|
5690
|
+
for (let i = 0; i < count; i++) {
|
|
5691
|
+
chars += char;
|
|
5442
5692
|
}
|
|
5443
|
-
|
|
5693
|
+
return chars;
|
|
5444
5694
|
};
|
|
5445
5695
|
|
|
5446
5696
|
const rebase = async (adapters, config) => {
|
|
@@ -5581,11 +5831,7 @@ const rebase = async (adapters, config) => {
|
|
|
5581
5831
|
}
|
|
5582
5832
|
};
|
|
5583
5833
|
for (const adapter of adapters) {
|
|
5584
|
-
await redo({
|
|
5585
|
-
ctx,
|
|
5586
|
-
adapter,
|
|
5587
|
-
config: redoConfig
|
|
5588
|
-
});
|
|
5834
|
+
await redo(adapter, redoConfig, { ctx, count: Infinity });
|
|
5589
5835
|
}
|
|
5590
5836
|
for (let i = renames.length - 1; i >= 0; i--) {
|
|
5591
5837
|
const [from, version] = renames[i];
|
|
@@ -5600,111 +5846,52 @@ const rebase = async (adapters, config) => {
|
|
|
5600
5846
|
}
|
|
5601
5847
|
};
|
|
5602
5848
|
|
|
5603
|
-
const listMigrationsStatuses = async (adapters, config, args) => {
|
|
5604
|
-
const ctx = {};
|
|
5605
|
-
const [{ migrations }, ...migrated] = await Promise.all([
|
|
5606
|
-
getMigrations(ctx, config, true),
|
|
5607
|
-
...adapters.map((adapter) => getMigratedVersionsMap(ctx, adapter, config))
|
|
5608
|
-
]);
|
|
5609
|
-
const map = {};
|
|
5610
|
-
let maxVersionLength = 12;
|
|
5611
|
-
let maxNameLength = 4;
|
|
5612
|
-
for (let i = 0; i < adapters.length; i++) {
|
|
5613
|
-
const list = migrated[i];
|
|
5614
|
-
const key = Object.entries(list.map).map(([version, up]) => `${version}${up ? "t" : "f"}`).join("");
|
|
5615
|
-
const database = adapters[i].getDatabase();
|
|
5616
|
-
if (map[key]) {
|
|
5617
|
-
map[key].databases.push(database);
|
|
5618
|
-
continue;
|
|
5619
|
-
}
|
|
5620
|
-
map[key] = {
|
|
5621
|
-
databases: [database],
|
|
5622
|
-
migrations: migrations.map((item) => {
|
|
5623
|
-
if (item.version.length > maxVersionLength) {
|
|
5624
|
-
maxVersionLength = item.version.length;
|
|
5625
|
-
}
|
|
5626
|
-
const name = path.parse(item.path).name.slice(item.version.length + 1).replace(
|
|
5627
|
-
/([a-z])([A-Z])/g,
|
|
5628
|
-
(_, a, b) => `${a} ${b.toLocaleLowerCase()}`
|
|
5629
|
-
).replace(/[-_](.)/g, (_, char) => ` ${char.toLocaleLowerCase()}`).replace(/^\w/, (match) => match.toLocaleUpperCase());
|
|
5630
|
-
if (name.length > maxNameLength) {
|
|
5631
|
-
maxNameLength = name.length;
|
|
5632
|
-
}
|
|
5633
|
-
return {
|
|
5634
|
-
up: !!list.map[item.version],
|
|
5635
|
-
version: item.version,
|
|
5636
|
-
name,
|
|
5637
|
-
url: pathToFileURL(item.path)
|
|
5638
|
-
};
|
|
5639
|
-
})
|
|
5640
|
-
};
|
|
5641
|
-
}
|
|
5642
|
-
const showUrl = args.includes("p") || args.includes("path");
|
|
5643
|
-
const asIs = (s) => s;
|
|
5644
|
-
const c = typeof config.log === "object" && config.log.colors === false ? {
|
|
5645
|
-
yellow: asIs,
|
|
5646
|
-
green: asIs,
|
|
5647
|
-
red: asIs,
|
|
5648
|
-
blue: asIs
|
|
5649
|
-
} : colors;
|
|
5650
|
-
const log = Object.values(map).map(({ databases, migrations: migrations2 }) => {
|
|
5651
|
-
let log2 = ` ${c.yellow("Database:")} ${databases.join(", ")}`;
|
|
5652
|
-
if (migrations2.length === 0) {
|
|
5653
|
-
return log2 + `
|
|
5654
|
-
|
|
5655
|
-
No migrations available`;
|
|
5656
|
-
}
|
|
5657
|
-
const lineSeparator = c.yellow(
|
|
5658
|
-
makeChars(14 + maxVersionLength + maxNameLength, "-")
|
|
5659
|
-
);
|
|
5660
|
-
const columnSeparator = c.yellow("|");
|
|
5661
|
-
log2 += "\n\n " + c.yellow(
|
|
5662
|
-
`Status | Migration ID${makeChars(
|
|
5663
|
-
maxVersionLength - 12,
|
|
5664
|
-
" "
|
|
5665
|
-
)} | Name
|
|
5666
|
-
${lineSeparator}`
|
|
5667
|
-
);
|
|
5668
|
-
for (const migration of migrations2) {
|
|
5669
|
-
log2 += `
|
|
5670
|
-
${migration.up ? ` ${c.green("Up")} ` : c.red("Down")} ${columnSeparator} ${c.blue(migration.version)}${makeChars(
|
|
5671
|
-
maxVersionLength - migration.version.length,
|
|
5672
|
-
" "
|
|
5673
|
-
)} ${columnSeparator} ${migration.name}`;
|
|
5674
|
-
if (showUrl) {
|
|
5675
|
-
log2 += `
|
|
5676
|
-
${migration.url}
|
|
5677
|
-
`;
|
|
5678
|
-
}
|
|
5679
|
-
}
|
|
5680
|
-
return log2 += showUrl ? lineSeparator : `
|
|
5681
|
-
${lineSeparator}`;
|
|
5682
|
-
}).join("\n\n");
|
|
5683
|
-
(config.logger ?? console).log(log);
|
|
5684
|
-
await Promise.all(adapters.map((adapter) => adapter.close()));
|
|
5685
|
-
};
|
|
5686
|
-
const makeChars = (count, char) => {
|
|
5687
|
-
let chars = "";
|
|
5688
|
-
for (let i = 0; i < count; i++) {
|
|
5689
|
-
chars += char;
|
|
5690
|
-
}
|
|
5691
|
-
return chars;
|
|
5692
|
-
};
|
|
5693
|
-
|
|
5694
5849
|
const rakeDbAliases = {
|
|
5695
5850
|
migrate: "up",
|
|
5696
5851
|
rollback: "down",
|
|
5697
5852
|
s: "status",
|
|
5698
5853
|
rec: "recurrent"
|
|
5699
5854
|
};
|
|
5700
|
-
const
|
|
5855
|
+
const rakeDbCliWithAdapter = (inputConfig, args = process.argv.slice(2)) => {
|
|
5856
|
+
let config;
|
|
5857
|
+
if ("__rakeDbConfig" in inputConfig) {
|
|
5858
|
+
config = inputConfig;
|
|
5859
|
+
} else {
|
|
5860
|
+
incrementIntermediateCaller();
|
|
5861
|
+
config = makeRakeDbConfig(inputConfig, args);
|
|
5862
|
+
}
|
|
5863
|
+
return {
|
|
5864
|
+
change: makeChange(config),
|
|
5865
|
+
async run(adapter, runArgs) {
|
|
5866
|
+
const adapters = toArray(adapter);
|
|
5867
|
+
try {
|
|
5868
|
+
await runCommand(adapters, config, runArgs || args);
|
|
5869
|
+
} catch (err) {
|
|
5870
|
+
if (err instanceof RakeDbError) {
|
|
5871
|
+
config.logger?.error(err.message);
|
|
5872
|
+
process.exit(1);
|
|
5873
|
+
}
|
|
5874
|
+
throw err;
|
|
5875
|
+
}
|
|
5876
|
+
}
|
|
5877
|
+
};
|
|
5878
|
+
};
|
|
5879
|
+
const setRakeDbCliRunFn = (rakeDbCli, mapper) => {
|
|
5880
|
+
rakeDbCli.run = (adapter, inputConfig, args) => {
|
|
5881
|
+
const { change, run } = rakeDbCli(inputConfig, args);
|
|
5882
|
+
run(mapper(adapter));
|
|
5883
|
+
return change;
|
|
5884
|
+
};
|
|
5885
|
+
};
|
|
5886
|
+
setRakeDbCliRunFn(rakeDbCliWithAdapter, (x) => x);
|
|
5887
|
+
const runCommand = async (adapters, config, args) => {
|
|
5701
5888
|
let arg = args[0]?.split(":")[0];
|
|
5702
5889
|
if (rakeDbAliases[arg]) {
|
|
5703
5890
|
args = [...args];
|
|
5704
5891
|
arg = args[0] = rakeDbAliases[arg];
|
|
5705
5892
|
}
|
|
5706
5893
|
args.shift();
|
|
5707
|
-
const command =
|
|
5894
|
+
const command = config.commands[arg]?.run;
|
|
5708
5895
|
if (command) {
|
|
5709
5896
|
await command(adapters, config, args);
|
|
5710
5897
|
} else if (config.logger) {
|
|
@@ -5712,8 +5899,8 @@ const runCommand = async (adapters, config, args = process.argv.slice(2)) => {
|
|
|
5712
5899
|
let max = 0;
|
|
5713
5900
|
let maxArgs = 0;
|
|
5714
5901
|
const addedCommands = /* @__PURE__ */ new Map();
|
|
5715
|
-
for (let key in
|
|
5716
|
-
const command2 =
|
|
5902
|
+
for (let key in config.commands) {
|
|
5903
|
+
const command2 = config.commands[key];
|
|
5717
5904
|
const added = addedCommands.get(command2);
|
|
5718
5905
|
if (added) key = added[0] += `, ${key}`;
|
|
5719
5906
|
if (key.length > max) max = key.length;
|
|
@@ -5724,7 +5911,11 @@ const runCommand = async (adapters, config, args = process.argv.slice(2)) => {
|
|
|
5724
5911
|
...Object.keys(command2.helpArguments).map((key2) => key2.length + 5)
|
|
5725
5912
|
);
|
|
5726
5913
|
}
|
|
5727
|
-
const helpBlock = [
|
|
5914
|
+
const helpBlock = [
|
|
5915
|
+
key,
|
|
5916
|
+
command2.help || "undocumented custom command",
|
|
5917
|
+
command2.helpArguments
|
|
5918
|
+
];
|
|
5728
5919
|
addedCommands.set(command2, helpBlock);
|
|
5729
5920
|
if (command2.helpAfter) {
|
|
5730
5921
|
const i = commandsHelp.findIndex(([key2]) => key2 === command2.helpAfter);
|
|
@@ -5760,15 +5951,16 @@ ${Object.entries(helpArguments).map(
|
|
|
5760
5951
|
}).join("\n\n")}
|
|
5761
5952
|
`);
|
|
5762
5953
|
}
|
|
5763
|
-
return {
|
|
5764
|
-
adapters,
|
|
5765
|
-
config,
|
|
5766
|
-
args
|
|
5767
|
-
};
|
|
5768
5954
|
};
|
|
5769
5955
|
const close = (adapters) => Promise.all(adapters.map((adapter) => adapter.close()));
|
|
5956
|
+
const maybeRunRecurrent = async (adapters, config) => {
|
|
5957
|
+
config.recurrentPath && await runRecurrentMigrations(
|
|
5958
|
+
adapters,
|
|
5959
|
+
config
|
|
5960
|
+
);
|
|
5961
|
+
};
|
|
5770
5962
|
const upCommand = {
|
|
5771
|
-
run: (adapters, config, args) => migrateCommand(adapters, config, args).then(() =>
|
|
5963
|
+
run: (adapters, config, args) => migrateCommand(adapters, config, args).then(() => maybeRunRecurrent(adapters, config)).then(() => close(adapters)),
|
|
5772
5964
|
help: "migrate pending migrations",
|
|
5773
5965
|
helpArguments: {
|
|
5774
5966
|
"no arguments": "migrate all pending",
|
|
@@ -5786,36 +5978,40 @@ const downCommand = {
|
|
|
5786
5978
|
}
|
|
5787
5979
|
};
|
|
5788
5980
|
const statusCommand = {
|
|
5789
|
-
run
|
|
5981
|
+
run(adapters, config, args) {
|
|
5982
|
+
const showUrl = args.includes("p") || args.includes("path");
|
|
5983
|
+
return listMigrationsStatuses(adapters, config, { showUrl });
|
|
5984
|
+
},
|
|
5790
5985
|
help: "list migrations statuses",
|
|
5791
5986
|
helpArguments: {
|
|
5792
5987
|
"no arguments": `does not print file paths`,
|
|
5793
5988
|
"p, path": "also print file paths"
|
|
5794
5989
|
}
|
|
5795
5990
|
};
|
|
5796
|
-
const
|
|
5797
|
-
run
|
|
5991
|
+
const recurrent = {
|
|
5992
|
+
async run(adapters, config) {
|
|
5993
|
+
if (!config.recurrentPath) return;
|
|
5994
|
+
await maybeRunRecurrent(adapters, config).then(() => close(adapters));
|
|
5995
|
+
},
|
|
5798
5996
|
help: "run recurrent migrations"
|
|
5799
5997
|
};
|
|
5800
5998
|
const rakeDbCommands = {
|
|
5801
5999
|
create: {
|
|
5802
|
-
run:
|
|
6000
|
+
run: (adapters, config) => createDatabaseCommand(adapters, config),
|
|
5803
6001
|
help: "create databases"
|
|
5804
6002
|
},
|
|
5805
6003
|
drop: {
|
|
5806
|
-
run:
|
|
6004
|
+
run: dropDatabaseCommand,
|
|
5807
6005
|
help: "drop databases"
|
|
5808
6006
|
},
|
|
5809
6007
|
reset: {
|
|
5810
|
-
run: (adapters, config) =>
|
|
6008
|
+
run: (adapters, config) => resetDatabaseCommand(adapters, config),
|
|
5811
6009
|
help: "drop, create and migrate databases"
|
|
5812
6010
|
},
|
|
5813
6011
|
up: upCommand,
|
|
5814
|
-
migrate: upCommand,
|
|
5815
6012
|
down: downCommand,
|
|
5816
|
-
rollback: downCommand,
|
|
5817
6013
|
redo: {
|
|
5818
|
-
run: (adapters, config, args) => redoCommand(adapters, config, args).then(() =>
|
|
6014
|
+
run: (adapters, config, args) => redoCommand(adapters, config, args).then(() => maybeRunRecurrent(adapters, config)).then(() => close(adapters)),
|
|
5819
6015
|
help: "rollback and migrate, run recurrent"
|
|
5820
6016
|
},
|
|
5821
6017
|
pull: {
|
|
@@ -5823,19 +6019,32 @@ const rakeDbCommands = {
|
|
|
5823
6019
|
help: "generate a combined migration for an existing database"
|
|
5824
6020
|
},
|
|
5825
6021
|
new: {
|
|
5826
|
-
run
|
|
6022
|
+
run(_, config, args) {
|
|
6023
|
+
const [name] = args;
|
|
6024
|
+
if (!name) throw new Error("Migration name is missing");
|
|
6025
|
+
return newMigration(config, name);
|
|
6026
|
+
},
|
|
5827
6027
|
help: "create new migration file"
|
|
5828
6028
|
},
|
|
5829
|
-
s: statusCommand,
|
|
5830
6029
|
status: statusCommand,
|
|
5831
|
-
|
|
5832
|
-
recurrent: recurrentCommand,
|
|
6030
|
+
recurrent,
|
|
5833
6031
|
rebase: {
|
|
5834
6032
|
run: (adapters, config) => rebase(adapters, config).then(() => close(adapters)),
|
|
5835
6033
|
help: "move local migrations below the new ones from upstream"
|
|
5836
6034
|
},
|
|
5837
6035
|
"change-ids": {
|
|
5838
|
-
run
|
|
6036
|
+
run(adapters, config, [format, digitsArg]) {
|
|
6037
|
+
if (format !== "serial" && format !== "timestamp") {
|
|
6038
|
+
throw new Error(
|
|
6039
|
+
`Pass "serial" or "timestamp" argument to the "change-ids" command`
|
|
6040
|
+
);
|
|
6041
|
+
}
|
|
6042
|
+
const digits = digitsArg ? parseInt(digitsArg) : void 0;
|
|
6043
|
+
if (digits && isNaN(digits)) {
|
|
6044
|
+
throw new Error(`Second argument is optional and must be an integer`);
|
|
6045
|
+
}
|
|
6046
|
+
return changeIds(adapters, config, { format, digits });
|
|
6047
|
+
},
|
|
5839
6048
|
help: "change migrations ids format",
|
|
5840
6049
|
helpArguments: {
|
|
5841
6050
|
serial: "change ids to 4 digit serial",
|
|
@@ -5844,68 +6053,10 @@ const rakeDbCommands = {
|
|
|
5844
6053
|
}
|
|
5845
6054
|
}
|
|
5846
6055
|
};
|
|
6056
|
+
for (const key in rakeDbAliases) {
|
|
6057
|
+
const command = rakeDbAliases[key];
|
|
6058
|
+
if (command) rakeDbCommands[key] = rakeDbCommands[command];
|
|
6059
|
+
}
|
|
5847
6060
|
|
|
5848
|
-
|
|
5849
|
-
const config = processRakeDbConfig(partialConfig, args);
|
|
5850
|
-
const promise = runCommand(
|
|
5851
|
-
adapters,
|
|
5852
|
-
config,
|
|
5853
|
-
args
|
|
5854
|
-
).catch((err) => {
|
|
5855
|
-
if (err instanceof RakeDbError) {
|
|
5856
|
-
config.logger?.error(err.message);
|
|
5857
|
-
process.exit(1);
|
|
5858
|
-
}
|
|
5859
|
-
throw err;
|
|
5860
|
-
});
|
|
5861
|
-
return Object.assign(makeChange(config), {
|
|
5862
|
-
promise
|
|
5863
|
-
});
|
|
5864
|
-
};
|
|
5865
|
-
rakeDbWithAdapters.lazy = (adapters, partialConfig) => {
|
|
5866
|
-
const config = processRakeDbConfig(partialConfig);
|
|
5867
|
-
return {
|
|
5868
|
-
change: makeChange(config),
|
|
5869
|
-
run(args, conf) {
|
|
5870
|
-
return runCommand(adapters, conf ? { ...config, ...conf } : config, args);
|
|
5871
|
-
}
|
|
5872
|
-
};
|
|
5873
|
-
};
|
|
5874
|
-
const makeChange = (config) => (fn) => {
|
|
5875
|
-
const change = { fn, config };
|
|
5876
|
-
pushChange(change);
|
|
5877
|
-
return change;
|
|
5878
|
-
};
|
|
5879
|
-
|
|
5880
|
-
const migrateFiles = async (db, files) => {
|
|
5881
|
-
const qb = db.$qb;
|
|
5882
|
-
await qb.ensureTransaction(async () => {
|
|
5883
|
-
const adapter = qb.internal.transactionStorage.getStore()?.adapter;
|
|
5884
|
-
for (const load of files) {
|
|
5885
|
-
clearChanges();
|
|
5886
|
-
const changes = await getChanges({ load });
|
|
5887
|
-
const config = changes[0]?.config;
|
|
5888
|
-
await runMigration(adapter, true, changes, config);
|
|
5889
|
-
}
|
|
5890
|
-
});
|
|
5891
|
-
};
|
|
5892
|
-
const makeMigrateAdapter = (config) => {
|
|
5893
|
-
const conf = ensureMigrationsPath(ensureBasePathAndDbScript(config || {}));
|
|
5894
|
-
return async (adapter, params) => {
|
|
5895
|
-
await migrateAndClose({
|
|
5896
|
-
adapter,
|
|
5897
|
-
...params,
|
|
5898
|
-
config: {
|
|
5899
|
-
...conf,
|
|
5900
|
-
columnTypes: conf.columnTypes || makeColumnTypes(defaultSchemaConfig),
|
|
5901
|
-
migrationId: conf.migrationId || migrationConfigDefaults.migrationId,
|
|
5902
|
-
migrationsTable: conf.migrationsTable || migrationConfigDefaults.migrationsTable,
|
|
5903
|
-
import: conf.import || migrationConfigDefaults.import,
|
|
5904
|
-
transaction: conf.transaction || "single"
|
|
5905
|
-
}
|
|
5906
|
-
});
|
|
5907
|
-
};
|
|
5908
|
-
};
|
|
5909
|
-
|
|
5910
|
-
export { RakeDbError, astToMigration, concatSchemaAndName, createMigrationInterface, dbColumnToAst, encodeColumnDefault, getConstraintName, getDbStructureTableData, getDbTableColumnsChecks, getExcludeName, getIndexName, getMigrationsSchemaAndTable, getSchemaAndTableFromName, instantiateDbColumn, introspectDbSchema, makeChange, makeDomainsMap, makeFileVersion, makeMigrateAdapter, makeStructureToAstCtx, migrate, migrateAndClose, migrateFiles, migrationConfigDefaults, processRakeDbConfig, promptSelect, rakeDbCommands, rakeDbWithAdapters, runCommand, saveMigratedVersion, structureToAst, tableToAst, writeMigrationFile };
|
|
6061
|
+
export { RakeDbError, astToMigration, concatSchemaAndName, createMigrationInterface, dbColumnToAst, encodeColumnDefault, getConstraintName, getDbStructureTableData, getDbTableColumnsChecks, getExcludeName, getIndexName, getMigrationsSchemaAndTable, getSchemaAndTableFromName, incrementIntermediateCaller, instantiateDbColumn, introspectDbSchema, makeDomainsMap, makeFileVersion, makeRakeDbConfig, makeStructureToAstCtx, migrate, migrateAndClose, migrationConfigDefaults, promptSelect, rakeDbCliWithAdapter, rakeDbCommands, redo, rollback, runMigration, saveMigratedVersion, setRakeDbCliRunFn, structureToAst, tableToAst, writeMigrationFile };
|
|
5911
6062
|
//# sourceMappingURL=index.mjs.map
|