sasat 0.22.0 → 0.22.2

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.
@@ -0,0 +1,604 @@
1
+ #!/usr/bin/env node
2
+ import { A as writeYmlFile, C as Directory, E as defaultConf, O as mkDirIfNotExist, S as capitalizeFirstLetter, T as config, _ as Console, a as getDbClient, f as getMigrationFileNames, g as defaultGQLOption, h as columnTypeToGqlPrimitive, i as compileMigrationFiles, k as writeCurrentSchema, l as defaultColumnOption, n as DataStoreHandler, p as CodeGen_v2, r as createCurrentMigrationDataStore, t as migrate, u as SqlString, w as DBColumnTypes, x as camelize } from "../migrate-Cbj2OVbY.mjs";
3
+ import * as fs$1 from "node:fs";
4
+ import fs from "node:fs";
5
+ import path, { join } from "node:path";
6
+ import { cac } from "cac";
7
+ //#region src/cli/commands/createMigration.ts
8
+ const getMigrationFile = (className) => `import { SasatMigration, MigrationStore } from "sasat";
9
+
10
+ export default class ${capitalizeFirstLetter(className)} implements SasatMigration {
11
+
12
+ up: (store: MigrationStore) => void = store => {
13
+
14
+ };
15
+
16
+ down: (store: MigrationStore) => void = store => {
17
+ throw new Error('Down is not implemented on ${className}');
18
+ };
19
+ }
20
+ `;
21
+ const createMigrationFile = (migrationName) => {
22
+ const date = /* @__PURE__ */ new Date();
23
+ const pad = (val) => val.toString().padStart(2, "0");
24
+ const fileName = date.getFullYear() + pad(date.getMonth() + 1) + pad(date.getDate()) + `_` + pad(date.getHours()) + pad(date.getMinutes()) + pad(date.getSeconds()) + migrationName;
25
+ const outDir = join(config().migration.dir);
26
+ mkDirIfNotExist(outDir);
27
+ fs$1.writeFileSync(join(outDir, fileName) + ".ts", getMigrationFile(migrationName));
28
+ return fileName;
29
+ };
30
+ const createMigration = (args) => {
31
+ if (!args) {
32
+ Console.error("missing argument migration name");
33
+ return;
34
+ }
35
+ if (!/^[$A-Za-z_][0-9A-Za-z_]+$/.test(args)) {
36
+ Console.error("migration name should be match /^[$A-Za-z_][0-9A-Za-z_]+$/");
37
+ return;
38
+ }
39
+ Console.success(createMigrationFile(args) + " Successfully created");
40
+ };
41
+ //#endregion
42
+ //#region src/db/sql/createTable/createTableParser.ts
43
+ const splitArray = (array, callback) => {
44
+ const indexes = [];
45
+ array.forEach((it, i) => {
46
+ if (callback(it)) indexes.push(i);
47
+ });
48
+ let prev = 0;
49
+ const result = [];
50
+ indexes.forEach((it) => {
51
+ result.push(array.slice(prev, it));
52
+ prev = it + 1;
53
+ });
54
+ result.push(array.slice(prev, array.length));
55
+ return result;
56
+ };
57
+ const isParenToken = (token) => {
58
+ return token.kind === "Paren";
59
+ };
60
+ var CreateTableParser = class {
61
+ constructor(tokens) {
62
+ this.tokens = tokens;
63
+ this.parse = () => {
64
+ const parenStart = this.findIndex("separator", "(", this.tokens);
65
+ this.result.tableName = this.tokens[parenStart - 1].value;
66
+ splitArray(this.resolveParen().find((it) => it.kind === "Paren").tokens, (token) => token.kind === "separator" && token.value === ",").forEach((it) => {
67
+ const kindIncludes = (kind) => !!it.find((it) => it.kind === kind);
68
+ if (kindIncludes("PRIMARY")) return this.parsePrimary(it);
69
+ if (kindIncludes("UNIQUE")) return this.parseUnique(it);
70
+ if (kindIncludes("FOREIGN")) return this.parseFkey(it);
71
+ if (kindIncludes("KEY") || kindIncludes("INDEX")) return this.parseIndex(it);
72
+ const kind = it[0].kind;
73
+ if (kind === "identifier" || kind === "string") return this.parseColumn(it);
74
+ throw new Error("fail to parse sql");
75
+ });
76
+ return this.result;
77
+ };
78
+ this.normalizeFieldName = (fieldName) => {
79
+ return /^[0-9].*/.test(fieldName) ? "_" + fieldName : fieldName;
80
+ };
81
+ this.result = {
82
+ tableName: "",
83
+ columns: [],
84
+ primaryKey: [],
85
+ uniqueKeys: [],
86
+ indexes: [],
87
+ gqlOption: defaultGQLOption(),
88
+ virtualRelations: []
89
+ };
90
+ }
91
+ resolveParen() {
92
+ const resolveParen = (tokens) => {
93
+ const result = [];
94
+ for (let i = 0; i < tokens.length; i++) {
95
+ const token = tokens[i];
96
+ if (token.kind === "separator" && token.value === "(") {
97
+ const endParen = this.findEndOfParenIndex(tokens, i);
98
+ result.push({
99
+ kind: "Paren",
100
+ tokens: resolveParen(tokens.slice(i + 1, endParen)),
101
+ value: ""
102
+ });
103
+ i = endParen;
104
+ continue;
105
+ }
106
+ result.push(token);
107
+ }
108
+ return result;
109
+ };
110
+ return resolveParen(this.tokens);
111
+ }
112
+ parseColumn(tokens) {
113
+ const columnName = tokens[0].value;
114
+ const type = tokens[1].value.toLowerCase();
115
+ const gqlType = columnTypeToGqlPrimitive(type);
116
+ const defaultTokenIndex = tokens.findIndex((it) => it.kind === "DEFAULT");
117
+ const getDefaultValue = () => {
118
+ if (defaultTokenIndex === -1) return void 0;
119
+ const next = tokens[defaultTokenIndex + 1];
120
+ if (next.kind === "NULL") return void 0;
121
+ if (next.kind === "number" || gqlType === "Float" || gqlType === "Int") return +next.value;
122
+ if (next.kind === "string") return next.value;
123
+ };
124
+ const defaultCurrentTimeStamp = defaultTokenIndex !== -1 && tokens[defaultTokenIndex + 1].kind === "identifier" && tokens[defaultTokenIndex + 1].value.toUpperCase() === "CURRENT_TIMESTAMP";
125
+ const isOnUpdate = () => {
126
+ return tokens[tokens.findIndex((it) => it.kind === "UPDATE") + 1].value.toUpperCase() === "CURRENT_TIMESTAMP";
127
+ };
128
+ const isNotNull = () => {
129
+ let prevIsNot = false;
130
+ return tokens.some((it) => {
131
+ if (prevIsNot && it.kind === "NULL") return true;
132
+ prevIsNot = it.kind === "NOT";
133
+ return false;
134
+ });
135
+ };
136
+ const identifiers = tokens.filter((it) => it.kind === "identifier");
137
+ const length = tokens[2] && isParenToken(tokens[2]) ? tokens[2].tokens[0]?.value : void 0;
138
+ const scale = tokens[2] && isParenToken(tokens[2]) ? tokens[2].tokens[1]?.value : void 0;
139
+ const column = {
140
+ hasReference: false,
141
+ columnName,
142
+ fieldName: this.normalizeFieldName(camelize(tokens[0].value)),
143
+ type,
144
+ notNull: isNotNull(),
145
+ default: getDefaultValue(),
146
+ zerofill: identifiers.some((it) => it.value.toLowerCase() === "zerofill"),
147
+ signed: identifiers.some((it) => it.value.toLowerCase() === "unsigned") ? false : identifiers.some((it) => it.value.toLowerCase() === "signed") ? true : void 0,
148
+ autoIncrement: tokens.some((it) => it.kind === "AUTO_INCREMENT"),
149
+ length: length !== void 0 ? +length : void 0,
150
+ scale: scale !== void 0 ? +scale : void 0,
151
+ defaultCurrentTimeStamp,
152
+ onUpdateCurrentTimeStamp: isOnUpdate(),
153
+ option: defaultColumnOption
154
+ };
155
+ if (column.default === ".nan" || Number.isNaN(column.default)) console.error(column);
156
+ this.result.columns.push(column);
157
+ if (tokens.some((it) => it.kind === "PRIMARY")) this.result.primaryKey = [columnName];
158
+ if (tokens.some((it) => it.kind === "UNIQUE")) this.result.uniqueKeys.push([columnName]);
159
+ }
160
+ parsePrimary(tokens) {
161
+ const paren = tokens[tokens.findIndex((it) => it.kind === "KEY") + 1];
162
+ this.result.primaryKey = paren.tokens.filter((it) => it.kind !== "separator").map((it) => it.value);
163
+ }
164
+ parseUnique(tokens) {
165
+ const paren = tokens.find((it) => it.kind === "Paren");
166
+ this.result.uniqueKeys.push(paren.tokens.filter((it) => it.kind !== "separator").map((it) => it.value));
167
+ }
168
+ parseIndex(tokens) {
169
+ const paren = tokens.find((it) => it.kind === "Paren");
170
+ this.result.indexes.push({
171
+ constraintName: tokens[1].value,
172
+ columns: paren.tokens.filter((it) => it.kind !== "separator" && it.kind !== "Paren").map((it) => it.value)
173
+ });
174
+ }
175
+ parseFkey(tokens) {
176
+ const columnName = tokens[tokens.findIndex((it) => it.kind === "FOREIGN") + 2].tokens[0].value;
177
+ const refIndex = tokens.findIndex((it) => it.kind === "REFERENCES" && it.value === "REFERENCES");
178
+ const targetTable = tokens[refIndex + 1].value;
179
+ const targetColumn = tokens[refIndex + 2].tokens[0].value;
180
+ let onDelete;
181
+ let onUpdate;
182
+ tokens.map((it, i) => it.kind === "ON" ? i : 0).filter((it) => it !== 0).forEach((it) => {
183
+ const action = () => {
184
+ let name = tokens[it + 2].value.toUpperCase();
185
+ if (name === "SET" || name === "NO") name += tokens[it + 3].value.toUpperCase();
186
+ return name;
187
+ };
188
+ if (tokens[it + 1].kind === "DELETE") onDelete = action();
189
+ if (tokens[it + 1].kind === "UPDATE") onUpdate = action();
190
+ });
191
+ const isColumnUnique = this.result.uniqueKeys.filter((it) => it.length === 1).find((it) => it[0] === columnName);
192
+ const sameTableRefs = this.result.columns.filter((it) => it.hasReference && it.reference.parentTable === targetTable);
193
+ const reference = {
194
+ parentTable: targetTable,
195
+ parentColumn: targetColumn,
196
+ columnName,
197
+ relation: isColumnUnique ? "OneOrZero" : "Many",
198
+ relationName: sameTableRefs.length !== 0 ? targetTable + sameTableRefs.length : void 0,
199
+ onUpdate,
200
+ onDelete
201
+ };
202
+ this.result.columns = this.result.columns.map((it) => it.columnName === columnName ? {
203
+ ...it,
204
+ hasReference: true,
205
+ reference
206
+ } : it);
207
+ }
208
+ findIndex(kind, value, tokens) {
209
+ return tokens.findIndex((it) => it.kind === kind && value === it.value);
210
+ }
211
+ findEndOfParenIndex(tokens, startParenIndex) {
212
+ let opened = 1;
213
+ for (let i = startParenIndex + 1; i < tokens.length; i++) {
214
+ const token = tokens[i];
215
+ if (token.kind === "separator") {
216
+ if (token.value === ")") {
217
+ opened -= 1;
218
+ if (opened === 0) return i;
219
+ } else if (token.value === "(") opened += 1;
220
+ }
221
+ }
222
+ throw new Error("Closing Parenthesis Not Found");
223
+ }
224
+ };
225
+ //#endregion
226
+ //#region src/db/sql/createTable/lexer/lexer2.ts
227
+ var Lexer2 = class {
228
+ constructor(str, rules, separators, operators, whiteSpaces = /([ \t\n])/) {
229
+ this.rules = rules;
230
+ this.separators = separators;
231
+ this.operators = operators;
232
+ this.whiteSpaces = whiteSpaces;
233
+ this.index = 0;
234
+ this.tokens = [];
235
+ this.chars = str.split("");
236
+ }
237
+ isTerminated(value, terminators) {
238
+ const separator = (value) => this.separators.includes(value);
239
+ const operator = (value) => this.operators.some((it) => it.startsWith(value));
240
+ const whiteSpace = (value) => this.whiteSpaces.test(value);
241
+ return terminators.some((it) => {
242
+ switch (it) {
243
+ case "operator": return operator(value);
244
+ case "separator": return separator(value);
245
+ case "whitespace": return whiteSpace(value);
246
+ default: return false;
247
+ }
248
+ });
249
+ }
250
+ lex() {
251
+ let value = this.read();
252
+ do
253
+ value = this.exec(value);
254
+ while (value.hasNext);
255
+ return this.tokens;
256
+ }
257
+ findOperator(current) {
258
+ const operator = (value) => ({
259
+ kind: "operator",
260
+ value
261
+ });
262
+ if (!current.hasNext) return this.operators.includes(current.value) ? operator(current.value) : void 0;
263
+ let operators = this.operators.filter((it) => it.startsWith(current.value));
264
+ let state = current.value;
265
+ if (operators.length === 1) return operator(state);
266
+ while (operators.length !== 0) {
267
+ if (!current.hasNext) return operator(state);
268
+ current = this.read();
269
+ state += current.value;
270
+ operators = operators.filter((it) => it.startsWith(state));
271
+ if (operators.length === 1) return operator(state);
272
+ }
273
+ if (state.length > 1) return operator(state.slice(0, -1));
274
+ }
275
+ exec(current) {
276
+ const currentIndex = this.index;
277
+ if (this.whiteSpaces.test(current.value)) return this.read();
278
+ if (this.separators.includes(current.value)) {
279
+ this.tokens.push({
280
+ kind: "separator",
281
+ value: current.value
282
+ });
283
+ return this.read();
284
+ }
285
+ const op = this.findOperator(current);
286
+ if (op) {
287
+ this.tokens.push(op);
288
+ this.index = currentIndex + op.value.length - 1;
289
+ return this.read();
290
+ }
291
+ this.index = currentIndex;
292
+ for (let i = 0; i < this.rules.length; i++) {
293
+ const rule = this.rules[i];
294
+ if (!rule.start.test(current.value)) continue;
295
+ let terminated = false;
296
+ let value;
297
+ const next = () => {
298
+ value = this.read();
299
+ terminated = this.isTerminated(value.value, rule.terminator);
300
+ return {
301
+ terminated,
302
+ ...value
303
+ };
304
+ };
305
+ const result = rule.fn(current.value, next);
306
+ if (!result) {
307
+ this.index = currentIndex;
308
+ continue;
309
+ }
310
+ this.tokens.push(result);
311
+ if (terminated && value) return value;
312
+ return this.read();
313
+ }
314
+ throw new Error("No Rule Matched");
315
+ }
316
+ read() {
317
+ const char = this.chars[this.index] || "";
318
+ this.index += 1;
319
+ return {
320
+ hasNext: this.chars.length > this.index,
321
+ value: char
322
+ };
323
+ }
324
+ };
325
+ //#endregion
326
+ //#region src/db/sql/createTable/lexer/rules.ts
327
+ const createStringLiteralRule = (literalInitializer) => {
328
+ return {
329
+ start: literalInitializer,
330
+ terminator: [],
331
+ fn: (start, next) => {
332
+ let literal = "";
333
+ let isEscape = false;
334
+ let v;
335
+ do {
336
+ v = next();
337
+ if (!isEscape && v.value === start) return {
338
+ kind: "string",
339
+ value: literal
340
+ };
341
+ literal += v.value;
342
+ isEscape = !isEscape && v.value === "\\";
343
+ } while (v.hasNext);
344
+ throw new Error("Non Terminated String");
345
+ }
346
+ };
347
+ };
348
+ const numberLiteral = {
349
+ start: /[0-9]/,
350
+ terminator: [
351
+ "separator",
352
+ "whitespace",
353
+ "operator"
354
+ ],
355
+ fn: (start, next) => {
356
+ let literal = start;
357
+ let v;
358
+ do {
359
+ v = next();
360
+ if (v.terminated) break;
361
+ literal += v.value;
362
+ } while (v.hasNext);
363
+ if (!Number.isFinite(+literal)) throw new Error("fail to read number");
364
+ return {
365
+ kind: "number",
366
+ value: literal
367
+ };
368
+ }
369
+ };
370
+ const createKeywordRule = (keywords, ignoreCase = false) => {
371
+ return {
372
+ start: /./,
373
+ terminator: ["whitespace", "separator"],
374
+ fn: (start, next) => {
375
+ let str = ignoreCase ? start.toUpperCase() : start;
376
+ let words = keywords.map((it) => typeof it === "string" ? {
377
+ kind: "keyword",
378
+ value: it
379
+ } : {
380
+ ...it,
381
+ value: it.value
382
+ });
383
+ if (ignoreCase) words = words.map((it) => ({
384
+ ...it,
385
+ value: it.value.toUpperCase()
386
+ }));
387
+ let v;
388
+ while (true) {
389
+ v = next();
390
+ if (v.terminated && words.find((it) => it.value === str)) return {
391
+ kind: words.find((it) => it.value === str).kind,
392
+ value: str
393
+ };
394
+ str += ignoreCase ? v.value.toUpperCase() : v.value;
395
+ words = words.filter((it) => it.value.startsWith(str));
396
+ if (words.length === 0) return;
397
+ }
398
+ }
399
+ };
400
+ };
401
+ const Rules = {
402
+ createStringLiteralRule,
403
+ numberLiteral,
404
+ createKeywordRule,
405
+ identifier: {
406
+ start: /[^0-9]/,
407
+ terminator: [
408
+ "separator",
409
+ "whitespace",
410
+ "operator"
411
+ ],
412
+ fn: (start, next) => {
413
+ let value = start;
414
+ let v;
415
+ do {
416
+ v = next();
417
+ if (v.terminated) break;
418
+ value += v.value;
419
+ } while (v.hasNext);
420
+ return {
421
+ kind: "identifier",
422
+ value
423
+ };
424
+ }
425
+ }
426
+ };
427
+ //#endregion
428
+ //#region src/db/sql/createTable/lexer/createSimpleLexer.ts
429
+ const createSimpleLexer = (str, keywords, ignoreKeywordCase, separators, operators = []) => new Lexer2(str, [
430
+ Rules.createStringLiteralRule(/['"`]/),
431
+ Rules.numberLiteral,
432
+ Rules.createKeywordRule(keywords, ignoreKeywordCase),
433
+ Rules.identifier
434
+ ], separators, operators);
435
+ //#endregion
436
+ //#region src/db/sql/createTable/lexer/createTableLexer.ts
437
+ const separators = [
438
+ "(",
439
+ ")",
440
+ ","
441
+ ];
442
+ const keywords = [
443
+ "CREATE",
444
+ "TABLE",
445
+ "PRIMARY",
446
+ "KEY",
447
+ "UNIQUE",
448
+ "FOREIGN",
449
+ "NOT",
450
+ "NULL",
451
+ "DEFAULT",
452
+ "AUTO_INCREMENT",
453
+ "ON",
454
+ "UPDATE",
455
+ "DELETE",
456
+ "REFERENCES",
457
+ "CONSTRAINT"
458
+ ].map((it) => ({
459
+ kind: it,
460
+ value: it
461
+ }));
462
+ const createTableLexer = (str) => {
463
+ return createSimpleLexer(str, keywords, true, separators, ["="]);
464
+ };
465
+ //#endregion
466
+ //#region src/db/sql/createTable/createTableSerializer.ts
467
+ const serializeCreateTable = (str) => {
468
+ return new CreateTableParser(createTableLexer(str).lex()).parse();
469
+ };
470
+ //#endregion
471
+ //#region src/cli/commands/dumpDb.ts
472
+ const dumpDB = async () => {
473
+ const con = getDbClient();
474
+ try {
475
+ const tables = await con.rawQuery("show tables").then((it) => it.flatMap((it) => Object.values(it)));
476
+ const serialized = await Promise.all(tables.map((table) => {
477
+ return con.rawQuery("show create table " + SqlString.escapeId(table)).then((it) => it[0]["Create Table"]).then(serializeCreateTable);
478
+ }));
479
+ const supportedTypes = Object.values(DBColumnTypes);
480
+ const store = { tables: serialized.filter((it) => {
481
+ if (it.primaryKey.length === 0) {
482
+ Console.error(`table ${it.tableName} skipped, reason: missing primary key`);
483
+ return false;
484
+ }
485
+ const notSupported = it.columns.find((it) => !supportedTypes.includes(it.type));
486
+ if (notSupported) {
487
+ Console.error(`table ${it.tableName} skipped, reason: ${it.tableName}.${notSupported.columnName} column type "${notSupported.type}" is Not Supported`);
488
+ return false;
489
+ }
490
+ return true;
491
+ }) };
492
+ writeYmlFile(config().migration.dir, "initialSchema.yml", store);
493
+ } catch (e) {
494
+ Console.error(e.message);
495
+ throw e;
496
+ } finally {
497
+ await con.release();
498
+ }
499
+ };
500
+ //#endregion
501
+ //#region src/cli/commands/getCurrentStore.ts
502
+ async function getCurrentStore() {
503
+ await compileMigrationFiles();
504
+ const files = getMigrationFileNames();
505
+ return (await createCurrentMigrationDataStore(files.find((it) => it === config().migration.target) || files[files.length - 1])).serialize();
506
+ }
507
+ //#endregion
508
+ //#region src/cli/commands/erDiagram.ts
509
+ const writeDiagram = async () => {
510
+ try {
511
+ const store = new DataStoreHandler(await getCurrentStore());
512
+ const result = `erDiagram
513
+ ${store.tables.map((it) => processTable(store, it)).join("\n")}
514
+ `;
515
+ fs.writeFileSync(path.join(config().migration.out, Directory.paths.GENERATED, "er-diagram.mermaid"), result);
516
+ } catch (e) {
517
+ Console.error(e.message);
518
+ throw e;
519
+ }
520
+ };
521
+ function getRefType(parent, rel) {
522
+ const left = parent.isNullable() ? "|o" : "||";
523
+ const getRight = () => {
524
+ switch (rel) {
525
+ case "One": return "||";
526
+ case "Many": return "o{";
527
+ case "OneOrZero": return "|o";
528
+ }
529
+ };
530
+ return `${left} -- ${getRight()}`;
531
+ }
532
+ function processTable(store, table) {
533
+ const rel = table.columns.filter((it) => it.isReference()).map((it) => {
534
+ const rel = it;
535
+ const ref = rel.data.reference;
536
+ const parent = store.table(ref.parentTable).column(ref.parentColumn);
537
+ return `${ref.parentTable} ${getRefType(parent, ref.relation)} ${table.tableName} : ${ref.relationName ?? `"${rel.data.reference.parentTable}__${rel.table.tableName}"`}`;
538
+ });
539
+ return `${table.tableName} {
540
+ ${table.columns.map((it) => ` ${it.columnName()} ${it.dataType()}`).join("\n")}
541
+ }
542
+ ${rel.join("\n")}
543
+ `;
544
+ }
545
+ //#endregion
546
+ //#region src/cli/commands/generate.ts
547
+ const generate = async () => {
548
+ try {
549
+ await compileMigrationFiles();
550
+ const files = getMigrationFileNames();
551
+ const targetFile = files.find((it) => it === config().migration.target) || files[files.length - 1];
552
+ const store = await getCurrentStore();
553
+ const storeHandler = new DataStoreHandler(store);
554
+ writeCurrentSchema(store);
555
+ await new CodeGen_v2(storeHandler).generate();
556
+ Console.success(`code generated. DIR: ${config().migration.out}\nmigration target: ${targetFile}`);
557
+ } catch (e) {
558
+ Console.error(e.message);
559
+ throw e;
560
+ }
561
+ };
562
+ //#endregion
563
+ //#region src/cli/commands/init.ts
564
+ const init = () => {
565
+ if (fs$1.existsSync("./sasat.yml")) {
566
+ Console.error("sasat.yml already exist");
567
+ return;
568
+ }
569
+ writeYmlFile("./", "sasat.yml", defaultConf);
570
+ Console.success("sasat.yml created");
571
+ };
572
+ //#endregion
573
+ //#region src/cli/commands/migrationBuild.ts
574
+ const migrationBuild = async () => {
575
+ Console.log("--migration build started--");
576
+ await compileMigrationFiles();
577
+ Console.success("Done!");
578
+ };
579
+ //#endregion
580
+ //#region src/cli/index.ts
581
+ const index = cac();
582
+ try {
583
+ index.usage("yarn sasat <command> [options]\n").command("migrate", "execute migration").option("-g, --generateFiles", "migrate with generate files").option("-d, --dry", "dry run").option("-s, --silent", "do not print logs").option("-b, --skipBuild", "skip compile migration files").action(async (options) => {
584
+ const client = getDbClient();
585
+ await migrate(client, options).catch((e) => {
586
+ console.error(e);
587
+ process.exit(1);
588
+ });
589
+ await client.release();
590
+ });
591
+ index.command("migration:build", "compile migration files").action(migrationBuild);
592
+ index.command("generate", "generate files").action(generate);
593
+ index.command("generate:er", "generate mermaid er diagram").action(writeDiagram);
594
+ index.command("migration:create [name]", "generate new migration file").action(createMigration);
595
+ index.command("dump-db", "dump database schema").action(dumpDB);
596
+ index.command("init").action(init);
597
+ index.parse();
598
+ if (!index.matchedCommand) index.outputHelp();
599
+ } catch (e) {
600
+ console.error(e);
601
+ process.exit(1);
602
+ }
603
+ //#endregion
604
+ export {};