@noego/proper 0.0.3 → 0.0.5
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/bin/cli.d.mts +1 -0
- package/bin/cli.d.ts +1 -0
- package/bin/cli.js +426 -39
- package/bin/cli.js.map +1 -1
- package/bin/cli.mjs +433 -39
- package/bin/cli.mjs.map +1 -1
- package/bin/index.d.mts +179 -0
- package/bin/index.d.ts +179 -0
- package/bin/index.js +430 -37
- package/bin/index.js.map +1 -1
- package/bin/index.mjs +428 -36
- package/bin/index.mjs.map +1 -1
- package/lib/runner.d.mts +51 -0
- package/lib/runner.d.ts +51 -0
- package/lib/runner.js +257 -0
- package/lib/runner.js.map +1 -0
- package/lib/runner.mjs +230 -0
- package/lib/runner.mjs.map +1 -0
- package/package.json +12 -1
- package/readme.md +295 -39
package/bin/cli.mjs
CHANGED
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
4
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
2
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
6
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
4
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
8
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
9
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10
|
+
var __spreadValues = (a, b) => {
|
|
11
|
+
for (var prop in b || (b = {}))
|
|
12
|
+
if (__hasOwnProp.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
if (__getOwnPropSymbols)
|
|
15
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
16
|
+
if (__propIsEnum.call(b, prop))
|
|
17
|
+
__defNormalProp(a, prop, b[prop]);
|
|
18
|
+
}
|
|
19
|
+
return a;
|
|
20
|
+
};
|
|
21
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
6
22
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
7
23
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
8
24
|
}) : x)(function(x) {
|
|
@@ -404,26 +420,50 @@ var init_MigrationDirectoryReader = __esm({
|
|
|
404
420
|
"framework/MigrationDirectoryReader.ts"() {
|
|
405
421
|
init_SqlMigrationBuilder();
|
|
406
422
|
MigrationDirectoryReader = class {
|
|
407
|
-
constructor(directory, read_strategy, sqlrunner) {
|
|
423
|
+
constructor(directory, read_strategy, sqlrunner, dialect = "sql") {
|
|
408
424
|
this.directory = directory;
|
|
409
425
|
this.read_strategy = read_strategy;
|
|
410
426
|
this.sqlrunner = sqlrunner;
|
|
427
|
+
this.dialect = dialect;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Resolves the appropriate file for a migration based on dialect.
|
|
431
|
+
* Priority: dialect-specific file > generic file
|
|
432
|
+
*/
|
|
433
|
+
resolveFile(baseName, direction) {
|
|
434
|
+
const dialectExt = this.dialect === "sql" ? "mysql" : "sqlite";
|
|
435
|
+
const dialectFile = path.join(this.directory, `${baseName}.${dialectExt}.${direction}.sql`);
|
|
436
|
+
if (fs.existsSync(dialectFile)) return dialectFile;
|
|
437
|
+
const genericFile = path.join(this.directory, `${baseName}.${direction}.sql`);
|
|
438
|
+
if (fs.existsSync(genericFile)) return genericFile;
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Checks if a file path is dialect-specific (contains .mysql. or .sqlite. in the name)
|
|
443
|
+
*/
|
|
444
|
+
isDialectSpecific(filePath) {
|
|
445
|
+
return /\.(mysql|sqlite)\.(up|down)\.sql$/i.test(filePath);
|
|
411
446
|
}
|
|
412
447
|
loadMigrations(table, connection) {
|
|
413
448
|
fs.existsSync(this.directory) || fs.mkdirSync(this.directory);
|
|
414
449
|
const dir_content = fs.readdirSync(this.directory, { withFileTypes: true }).filter((file) => file.isFile()).map((file) => file.name);
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
file
|
|
421
|
-
};
|
|
422
|
-
}).sort();
|
|
450
|
+
const uniqueKeys = /* @__PURE__ */ new Set();
|
|
451
|
+
dir_content.forEach((file) => {
|
|
452
|
+
const key = file.replace(/(?:\.(mysql|sqlite))?\.(up|down)\.(sql|js)/i, "").toLowerCase();
|
|
453
|
+
uniqueKeys.add(key);
|
|
454
|
+
});
|
|
423
455
|
const migration_sorter = {};
|
|
424
|
-
|
|
425
|
-
const builder =
|
|
426
|
-
this.
|
|
456
|
+
uniqueKeys.forEach((migration_key) => {
|
|
457
|
+
const builder = new SqlMigrationBuilder(migration_key);
|
|
458
|
+
const upFile = this.resolveFile(migration_key, "up");
|
|
459
|
+
const downFile = this.resolveFile(migration_key, "down");
|
|
460
|
+
if (upFile) {
|
|
461
|
+
this.loadMigration(builder, upFile);
|
|
462
|
+
}
|
|
463
|
+
if (downFile) {
|
|
464
|
+
this.loadMigration(builder, downFile);
|
|
465
|
+
}
|
|
466
|
+
migration_sorter[migration_key] = builder;
|
|
427
467
|
});
|
|
428
468
|
const keys = Object.keys(migration_sorter);
|
|
429
469
|
keys.sort();
|
|
@@ -450,12 +490,16 @@ var init_MigrationDirectoryReader = __esm({
|
|
|
450
490
|
}
|
|
451
491
|
sql_up(file) {
|
|
452
492
|
let content = fs.readFileSync(file).toString();
|
|
453
|
-
|
|
493
|
+
if (!this.isDialectSpecific(file)) {
|
|
494
|
+
content = this.read_strategy(content);
|
|
495
|
+
}
|
|
454
496
|
return content.trim();
|
|
455
497
|
}
|
|
456
498
|
sql_down(file) {
|
|
457
499
|
let content = fs.readFileSync(file).toString();
|
|
458
|
-
|
|
500
|
+
if (!this.isDialectSpecific(file)) {
|
|
501
|
+
content = this.read_strategy(content);
|
|
502
|
+
}
|
|
459
503
|
return content.trim();
|
|
460
504
|
}
|
|
461
505
|
};
|
|
@@ -559,6 +603,9 @@ var init_MigrationDialectParser = __esm({
|
|
|
559
603
|
});
|
|
560
604
|
|
|
561
605
|
// framework/SQLRunner.ts
|
|
606
|
+
function isPromiseLike(value) {
|
|
607
|
+
return !!value && typeof value.then === "function";
|
|
608
|
+
}
|
|
562
609
|
var BaseSQLRunner, SQLRunner, SQLiteRunner;
|
|
563
610
|
var init_SQLRunner = __esm({
|
|
564
611
|
"framework/SQLRunner.ts"() {
|
|
@@ -615,14 +662,85 @@ var init_SQLRunner = __esm({
|
|
|
615
662
|
super();
|
|
616
663
|
this.connection = connection;
|
|
617
664
|
}
|
|
665
|
+
prepareStatement(sql) {
|
|
666
|
+
return __async(this, null, function* () {
|
|
667
|
+
if (typeof this.connection.prepare !== "function") {
|
|
668
|
+
throw new Error("SQLite connection does not support prepare()");
|
|
669
|
+
}
|
|
670
|
+
const stmt = this.connection.prepare(sql);
|
|
671
|
+
return isPromiseLike(stmt) ? yield stmt : stmt;
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
finalizeStatement(stmt) {
|
|
675
|
+
return __async(this, null, function* () {
|
|
676
|
+
if (!stmt || typeof stmt.finalize !== "function") return;
|
|
677
|
+
const result = stmt.finalize();
|
|
678
|
+
if (isPromiseLike(result)) {
|
|
679
|
+
yield result;
|
|
680
|
+
}
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
statementAll(stmt, params) {
|
|
684
|
+
return __async(this, null, function* () {
|
|
685
|
+
if (typeof stmt.all !== "function") {
|
|
686
|
+
throw new Error("SQLite statement does not support all()");
|
|
687
|
+
}
|
|
688
|
+
if (stmt.all.length >= 2) {
|
|
689
|
+
return yield new Promise((resolve, reject) => {
|
|
690
|
+
const callback = (err, rows) => {
|
|
691
|
+
if (err) return reject(err);
|
|
692
|
+
resolve(rows || []);
|
|
693
|
+
};
|
|
694
|
+
try {
|
|
695
|
+
if (params.length > 0) {
|
|
696
|
+
stmt.all(params, callback);
|
|
697
|
+
} else {
|
|
698
|
+
stmt.all(callback);
|
|
699
|
+
}
|
|
700
|
+
} catch (error) {
|
|
701
|
+
reject(error);
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
const result = stmt.all(...params);
|
|
706
|
+
return isPromiseLike(result) ? yield result : result;
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
statementRun(stmt, params) {
|
|
710
|
+
return __async(this, null, function* () {
|
|
711
|
+
if (typeof stmt.run !== "function") {
|
|
712
|
+
throw new Error("SQLite statement does not support run()");
|
|
713
|
+
}
|
|
714
|
+
if (stmt.run.length >= 2) {
|
|
715
|
+
return yield new Promise((resolve, reject) => {
|
|
716
|
+
const callback = function(err) {
|
|
717
|
+
var _a;
|
|
718
|
+
if (err) return reject(err);
|
|
719
|
+
resolve({ changes: (_a = this == null ? void 0 : this.changes) != null ? _a : 0, lastID: this == null ? void 0 : this.lastID });
|
|
720
|
+
};
|
|
721
|
+
try {
|
|
722
|
+
if (params.length > 0) {
|
|
723
|
+
stmt.run(params, callback);
|
|
724
|
+
} else {
|
|
725
|
+
stmt.run(callback);
|
|
726
|
+
}
|
|
727
|
+
} catch (error) {
|
|
728
|
+
reject(error);
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
const result = stmt.run(...params);
|
|
733
|
+
return isPromiseLike(result) ? yield result : result;
|
|
734
|
+
});
|
|
735
|
+
}
|
|
618
736
|
_query(_0) {
|
|
619
737
|
return __async(this, arguments, function* (sql, params = []) {
|
|
620
|
-
const stmt = yield this.
|
|
738
|
+
const stmt = yield this.prepareStatement(sql);
|
|
621
739
|
try {
|
|
622
|
-
const rows = yield
|
|
740
|
+
const rows = yield this.statementAll(stmt, params);
|
|
623
741
|
return rows;
|
|
624
742
|
} finally {
|
|
625
|
-
yield
|
|
743
|
+
yield this.finalizeStatement(stmt);
|
|
626
744
|
}
|
|
627
745
|
});
|
|
628
746
|
}
|
|
@@ -636,12 +754,12 @@ ${sql}
|
|
|
636
754
|
throw err;
|
|
637
755
|
});
|
|
638
756
|
}
|
|
639
|
-
const stmt = yield this.
|
|
757
|
+
const stmt = yield this.prepareStatement(sql);
|
|
640
758
|
try {
|
|
641
|
-
const info = yield
|
|
759
|
+
const info = yield this.statementRun(stmt, params);
|
|
642
760
|
return info;
|
|
643
761
|
} finally {
|
|
644
|
-
yield
|
|
762
|
+
yield this.finalizeStatement(stmt);
|
|
645
763
|
}
|
|
646
764
|
});
|
|
647
765
|
}
|
|
@@ -657,13 +775,13 @@ ${sql}
|
|
|
657
775
|
).filter((s) => s.trim() !== "");
|
|
658
776
|
const infos = yield statements.reduce((prev, statement) => __async(this, null, function* () {
|
|
659
777
|
const infos2 = yield prev;
|
|
660
|
-
const stmt = yield this.
|
|
778
|
+
const stmt = yield this.prepareStatement(`${statement};`);
|
|
661
779
|
try {
|
|
662
|
-
const info = yield
|
|
780
|
+
const info = yield this.statementRun(stmt, params);
|
|
663
781
|
infos2.push(info);
|
|
664
782
|
return infos2;
|
|
665
783
|
} finally {
|
|
666
|
-
yield
|
|
784
|
+
yield this.finalizeStatement(stmt);
|
|
667
785
|
}
|
|
668
786
|
}), Promise.resolve([null])).then((infos2) => {
|
|
669
787
|
return infos2.filter((info) => info !== null);
|
|
@@ -712,6 +830,9 @@ var init_MigrationRunner = __esm({
|
|
|
712
830
|
init_SQLRunner();
|
|
713
831
|
init_errors();
|
|
714
832
|
MigrationRunnerFactory = class _MigrationRunnerFactory {
|
|
833
|
+
static isSQLRunner(conn) {
|
|
834
|
+
return !!conn && typeof conn.query === "function" && typeof conn.execute === "function" && typeof conn.end === "function";
|
|
835
|
+
}
|
|
715
836
|
static create(configFile, conn) {
|
|
716
837
|
return __async(this, null, function* () {
|
|
717
838
|
const configReader = new FileMigrationConfigReader(configFile);
|
|
@@ -767,21 +888,27 @@ var init_MigrationRunner = __esm({
|
|
|
767
888
|
create(config, conn) {
|
|
768
889
|
return __async(this, null, function* () {
|
|
769
890
|
let sqlrunner;
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
891
|
+
let driverConnection = conn;
|
|
892
|
+
if (_MigrationRunnerFactory.isSQLRunner(conn)) {
|
|
893
|
+
sqlrunner = conn;
|
|
894
|
+
driverConnection = null;
|
|
895
|
+
} else {
|
|
896
|
+
switch (config.database) {
|
|
897
|
+
case "sql":
|
|
898
|
+
sqlrunner = new SQLRunner(conn);
|
|
899
|
+
break;
|
|
900
|
+
case "sqlite":
|
|
901
|
+
sqlrunner = new SQLiteRunner(conn);
|
|
902
|
+
break;
|
|
903
|
+
default:
|
|
904
|
+
throw ConfigurationError.unknownDatabaseType(config.database);
|
|
905
|
+
}
|
|
779
906
|
}
|
|
780
907
|
const setup = new MigrationSetup(sqlrunner, config);
|
|
781
908
|
const read_strategy = this.getReadStategy(config);
|
|
782
|
-
const migration_files = new MigrationDirectoryReader(config.migration_folder, read_strategy, sqlrunner);
|
|
909
|
+
const migration_files = new MigrationDirectoryReader(config.migration_folder, read_strategy, sqlrunner, config.database);
|
|
783
910
|
yield setup.setup();
|
|
784
|
-
return new MySQLMigrationRunner(config, migration_files, setup, sqlrunner,
|
|
911
|
+
return new MySQLMigrationRunner(config, migration_files, setup, sqlrunner, driverConnection);
|
|
785
912
|
});
|
|
786
913
|
}
|
|
787
914
|
createEmpty(config) {
|
|
@@ -800,7 +927,7 @@ var init_MigrationRunner = __esm({
|
|
|
800
927
|
}
|
|
801
928
|
const setup = new MigrationSetup(sqlrunner, config);
|
|
802
929
|
const read_strategy = this.getReadStategy(config);
|
|
803
|
-
const migration_files = new MigrationDirectoryReader(config.migration_folder, read_strategy, sqlrunner);
|
|
930
|
+
const migration_files = new MigrationDirectoryReader(config.migration_folder, read_strategy, sqlrunner, config.database);
|
|
804
931
|
return new MySQLMigrationRunner(config, migration_files, setup, sqlrunner, conn);
|
|
805
932
|
});
|
|
806
933
|
}
|
|
@@ -945,6 +1072,11 @@ var init_MigrationRunner = __esm({
|
|
|
945
1072
|
}
|
|
946
1073
|
});
|
|
947
1074
|
}
|
|
1075
|
+
query(sql, params) {
|
|
1076
|
+
return __async(this, null, function* () {
|
|
1077
|
+
return yield this.sqlrunner.query(sql, params);
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
948
1080
|
init(config_file) {
|
|
949
1081
|
return __async(this, null, function* () {
|
|
950
1082
|
try {
|
|
@@ -1043,6 +1175,229 @@ var init_MigrationRunner = __esm({
|
|
|
1043
1175
|
}
|
|
1044
1176
|
});
|
|
1045
1177
|
|
|
1178
|
+
// framework/SeedRunner.ts
|
|
1179
|
+
import fs4 from "fs";
|
|
1180
|
+
import path2 from "path";
|
|
1181
|
+
import Ajv from "ajv";
|
|
1182
|
+
import addFormats from "ajv-formats";
|
|
1183
|
+
function resolveAlias(name, aliasMap) {
|
|
1184
|
+
var _a;
|
|
1185
|
+
if (!aliasMap) return name;
|
|
1186
|
+
return (_a = aliasMap[name]) != null ? _a : name;
|
|
1187
|
+
}
|
|
1188
|
+
function walkForFile(rootDir, fileName) {
|
|
1189
|
+
if (!fs4.existsSync(rootDir)) return null;
|
|
1190
|
+
const entries = fs4.readdirSync(rootDir, { withFileTypes: true });
|
|
1191
|
+
for (const entry of entries) {
|
|
1192
|
+
const full = path2.join(rootDir, entry.name);
|
|
1193
|
+
if (entry.isDirectory()) {
|
|
1194
|
+
const found = walkForFile(full, fileName);
|
|
1195
|
+
if (found) return found;
|
|
1196
|
+
} else if (entry.isFile() && entry.name === fileName) {
|
|
1197
|
+
return full;
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
return null;
|
|
1201
|
+
}
|
|
1202
|
+
function resolveMigrationsDir(migrationConfig, options) {
|
|
1203
|
+
var _a;
|
|
1204
|
+
const fromOptions = options.migrationsDir;
|
|
1205
|
+
const fromConfig = (_a = migrationConfig.seeds) == null ? void 0 : _a.migrationsDir;
|
|
1206
|
+
const dir = fromOptions != null ? fromOptions : fromConfig;
|
|
1207
|
+
if (!dir) {
|
|
1208
|
+
throw new Error("Seed migrationsDir not configured. Set seeds.migrationsDir in proper.json or pass it explicitly.");
|
|
1209
|
+
}
|
|
1210
|
+
return dir;
|
|
1211
|
+
}
|
|
1212
|
+
function mergeSeedConfig(migrationConfig, options) {
|
|
1213
|
+
var _a, _b, _c, _d;
|
|
1214
|
+
const names = options.names && options.names.length ? options.names : ((_a = migrationConfig.seeds) == null ? void 0 : _a.list) && migrationConfig.seeds.list.length ? migrationConfig.seeds.list : [];
|
|
1215
|
+
if (!names.length) {
|
|
1216
|
+
throw new Error("No seed names provided and no seeds.list defined in proper config");
|
|
1217
|
+
}
|
|
1218
|
+
const migrationsDir = resolveMigrationsDir(migrationConfig, options);
|
|
1219
|
+
const dataDir = (_c = options.dataDir) != null ? _c : (_b = migrationConfig.seeds) == null ? void 0 : _b.dataDir;
|
|
1220
|
+
const validate = options.validate !== void 0 ? options.validate : true;
|
|
1221
|
+
const transactional = (_d = options.transactional) != null ? _d : "none";
|
|
1222
|
+
const finalOptions = __spreadProps(__spreadValues({}, options), {
|
|
1223
|
+
migrationsDir,
|
|
1224
|
+
dataDir,
|
|
1225
|
+
validate,
|
|
1226
|
+
transactional
|
|
1227
|
+
});
|
|
1228
|
+
return { names, finalOptions };
|
|
1229
|
+
}
|
|
1230
|
+
function resolveSqlPair(name, migrationsDir) {
|
|
1231
|
+
const up = walkForFile(migrationsDir, `${name}.up.sql`);
|
|
1232
|
+
const down = walkForFile(migrationsDir, `${name}.down.sql`);
|
|
1233
|
+
if (up && down) {
|
|
1234
|
+
return { upPath: up, downPath: down };
|
|
1235
|
+
}
|
|
1236
|
+
return null;
|
|
1237
|
+
}
|
|
1238
|
+
function resolveModule(name, migrationsDir) {
|
|
1239
|
+
const ts = walkForFile(migrationsDir, `${name}.ts`);
|
|
1240
|
+
if (ts) return { kind: "ts", modulePath: ts };
|
|
1241
|
+
const js = walkForFile(migrationsDir, `${name}.js`);
|
|
1242
|
+
if (js) return { kind: "js", modulePath: js };
|
|
1243
|
+
return null;
|
|
1244
|
+
}
|
|
1245
|
+
function resolveSeed(name, migrationConfig, options) {
|
|
1246
|
+
return __async(this, null, function* () {
|
|
1247
|
+
var _a, _b;
|
|
1248
|
+
const migrationsDir = resolveMigrationsDir(migrationConfig, options);
|
|
1249
|
+
const alias = resolveAlias(name, options.aliasMap);
|
|
1250
|
+
const sqlPair = resolveSqlPair(name, migrationsDir);
|
|
1251
|
+
if (sqlPair) {
|
|
1252
|
+
return {
|
|
1253
|
+
kind: "sql",
|
|
1254
|
+
name,
|
|
1255
|
+
alias,
|
|
1256
|
+
upPath: sqlPair.upPath,
|
|
1257
|
+
downPath: sqlPair.downPath,
|
|
1258
|
+
dataPath: null,
|
|
1259
|
+
schemaPath: null
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
const module = resolveModule(name, migrationsDir);
|
|
1263
|
+
if (!module) {
|
|
1264
|
+
throw new Error(`Seed implementation not found for "${name}" under ${migrationsDir}`);
|
|
1265
|
+
}
|
|
1266
|
+
const dataDir = (_b = options.dataDir) != null ? _b : (_a = migrationConfig.seeds) == null ? void 0 : _a.dataDir;
|
|
1267
|
+
let dataPath = null;
|
|
1268
|
+
let schemaPath = null;
|
|
1269
|
+
if (dataDir) {
|
|
1270
|
+
dataPath = walkForFile(dataDir, `${alias}.json`);
|
|
1271
|
+
schemaPath = walkForFile(dataDir, `${alias}.schema.json`);
|
|
1272
|
+
}
|
|
1273
|
+
return {
|
|
1274
|
+
kind: module.kind,
|
|
1275
|
+
name,
|
|
1276
|
+
alias,
|
|
1277
|
+
upPath: module.modulePath,
|
|
1278
|
+
downPath: module.modulePath,
|
|
1279
|
+
dataPath,
|
|
1280
|
+
schemaPath
|
|
1281
|
+
};
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
function loadJson(filePath) {
|
|
1285
|
+
return __async(this, null, function* () {
|
|
1286
|
+
const content = yield fs4.promises.readFile(filePath, "utf8");
|
|
1287
|
+
return JSON.parse(content);
|
|
1288
|
+
});
|
|
1289
|
+
}
|
|
1290
|
+
function createValidator() {
|
|
1291
|
+
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
1292
|
+
addFormats(ajv);
|
|
1293
|
+
return ajv;
|
|
1294
|
+
}
|
|
1295
|
+
function validateData(schemaPath, data, validate, log) {
|
|
1296
|
+
return __async(this, null, function* () {
|
|
1297
|
+
if (!validate || !schemaPath) return;
|
|
1298
|
+
const content = yield fs4.promises.readFile(schemaPath, "utf8");
|
|
1299
|
+
const schema = JSON.parse(content);
|
|
1300
|
+
const ajv = createValidator();
|
|
1301
|
+
const validateFn = ajv.compile(schema);
|
|
1302
|
+
const ok = validateFn(data);
|
|
1303
|
+
if (!ok) {
|
|
1304
|
+
log == null ? void 0 : log(`Validation failed for seed data (${schemaPath})`);
|
|
1305
|
+
throw new Error(`Seed data validation failed: ${ajv.errorsText(validateFn.errors || [])}`);
|
|
1306
|
+
}
|
|
1307
|
+
});
|
|
1308
|
+
}
|
|
1309
|
+
function runSqlSeed(runner, resolved, direction) {
|
|
1310
|
+
return __async(this, null, function* () {
|
|
1311
|
+
const sqlPath = direction === "up" ? resolved.upPath : resolved.downPath;
|
|
1312
|
+
const sql = yield fs4.promises.readFile(sqlPath, "utf8");
|
|
1313
|
+
yield runner.query(sql);
|
|
1314
|
+
});
|
|
1315
|
+
}
|
|
1316
|
+
function runModuleSeed(runner, resolved, migrationConfig, options, direction) {
|
|
1317
|
+
return __async(this, null, function* () {
|
|
1318
|
+
const { log } = options;
|
|
1319
|
+
const module = yield import(path2.resolve(resolved.upPath));
|
|
1320
|
+
const handler = module[direction];
|
|
1321
|
+
if (typeof handler !== "function") {
|
|
1322
|
+
throw new Error(`Seed module "${resolved.name}" does not export ${direction}()`);
|
|
1323
|
+
}
|
|
1324
|
+
let data = null;
|
|
1325
|
+
if (options.preloadedData && Object.prototype.hasOwnProperty.call(options.preloadedData, resolved.name)) {
|
|
1326
|
+
data = options.preloadedData[resolved.name];
|
|
1327
|
+
} else if (resolved.dataPath) {
|
|
1328
|
+
data = yield loadJson(resolved.dataPath);
|
|
1329
|
+
}
|
|
1330
|
+
yield validateData(resolved.schemaPath, data, options.validate, log);
|
|
1331
|
+
const ctx = {
|
|
1332
|
+
data,
|
|
1333
|
+
log,
|
|
1334
|
+
dialect: migrationConfig.database || "sql"
|
|
1335
|
+
};
|
|
1336
|
+
yield handler(runner, ctx);
|
|
1337
|
+
});
|
|
1338
|
+
}
|
|
1339
|
+
function runSingleSeed(runner, migrationConfig, name, options, direction) {
|
|
1340
|
+
return __async(this, null, function* () {
|
|
1341
|
+
const resolved = yield resolveSeed(name, migrationConfig, options);
|
|
1342
|
+
if (resolved.kind === "sql") {
|
|
1343
|
+
yield runSqlSeed(runner, resolved, direction);
|
|
1344
|
+
} else {
|
|
1345
|
+
yield runModuleSeed(runner, resolved, migrationConfig, options, direction);
|
|
1346
|
+
}
|
|
1347
|
+
});
|
|
1348
|
+
}
|
|
1349
|
+
function withTransactionalMode(runner, migrationConfig, names, options, direction) {
|
|
1350
|
+
return __async(this, null, function* () {
|
|
1351
|
+
const mode = options.transactional;
|
|
1352
|
+
if (mode === "runner") {
|
|
1353
|
+
yield runner.query("BEGIN");
|
|
1354
|
+
try {
|
|
1355
|
+
for (const name of names) {
|
|
1356
|
+
yield runSingleSeed(runner, migrationConfig, name, options, direction);
|
|
1357
|
+
}
|
|
1358
|
+
yield runner.query("COMMIT");
|
|
1359
|
+
} catch (err) {
|
|
1360
|
+
try {
|
|
1361
|
+
yield runner.query("ROLLBACK");
|
|
1362
|
+
} catch (e) {
|
|
1363
|
+
}
|
|
1364
|
+
throw err;
|
|
1365
|
+
}
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
if (mode === "seed") {
|
|
1369
|
+
for (const name of names) {
|
|
1370
|
+
yield runner.query("BEGIN");
|
|
1371
|
+
try {
|
|
1372
|
+
yield runSingleSeed(runner, migrationConfig, name, options, direction);
|
|
1373
|
+
yield runner.query("COMMIT");
|
|
1374
|
+
} catch (err) {
|
|
1375
|
+
try {
|
|
1376
|
+
yield runner.query("ROLLBACK");
|
|
1377
|
+
} catch (e) {
|
|
1378
|
+
}
|
|
1379
|
+
throw err;
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1384
|
+
for (const name of names) {
|
|
1385
|
+
yield runSingleSeed(runner, migrationConfig, name, options, direction);
|
|
1386
|
+
}
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
function runSeedsWithRunner(runner, migrationConfig, direction, options) {
|
|
1390
|
+
return __async(this, null, function* () {
|
|
1391
|
+
const { names, finalOptions } = mergeSeedConfig(migrationConfig, options);
|
|
1392
|
+
yield withTransactionalMode(runner, migrationConfig, names, finalOptions, direction);
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
var init_SeedRunner = __esm({
|
|
1396
|
+
"framework/SeedRunner.ts"() {
|
|
1397
|
+
init_MigrationRunner();
|
|
1398
|
+
}
|
|
1399
|
+
});
|
|
1400
|
+
|
|
1046
1401
|
// cli.ts
|
|
1047
1402
|
import "source-map-support/register";
|
|
1048
1403
|
var require_cli = __commonJS({
|
|
@@ -1051,6 +1406,7 @@ var require_cli = __commonJS({
|
|
|
1051
1406
|
init_MigrationFilter();
|
|
1052
1407
|
init_MigrationRunner();
|
|
1053
1408
|
init_errors();
|
|
1409
|
+
init_SeedRunner();
|
|
1054
1410
|
var args = MigrationCLIFactory.setup(process.argv);
|
|
1055
1411
|
if (!args.commands || args.commands.length === 0) {
|
|
1056
1412
|
console.error("Error: No command specified");
|
|
@@ -1096,8 +1452,9 @@ var require_cli = __commonJS({
|
|
|
1096
1452
|
const migrations_rollback = yield runner.getMigrations();
|
|
1097
1453
|
let downgraded = yield migration_filter(migrations_rollback, true);
|
|
1098
1454
|
downgraded = downgraded.reverse();
|
|
1099
|
-
if (args.flags.
|
|
1100
|
-
|
|
1455
|
+
if (args.flags.all) {
|
|
1456
|
+
} else {
|
|
1457
|
+
const increment = parseInt(args.flags.increment || "1");
|
|
1101
1458
|
downgraded = downgraded.slice(0, increment);
|
|
1102
1459
|
}
|
|
1103
1460
|
console.log(`Rolling back ${downgraded.length} migration(s)`);
|
|
@@ -1169,7 +1526,7 @@ var require_cli = __commonJS({
|
|
|
1169
1526
|
throw new CLIError("Invalid format. Use --format table or --format json");
|
|
1170
1527
|
}
|
|
1171
1528
|
try {
|
|
1172
|
-
const [results] = yield runner.
|
|
1529
|
+
const [results] = yield runner.query(sql_query);
|
|
1173
1530
|
if (Array.isArray(results) && results.length > 0) {
|
|
1174
1531
|
if (format === "json") {
|
|
1175
1532
|
console.log(JSON.stringify(results, null, 2));
|
|
@@ -1189,6 +1546,40 @@ Returned ${results.length} row(s)`);
|
|
|
1189
1546
|
}
|
|
1190
1547
|
yield runner.close();
|
|
1191
1548
|
break;
|
|
1549
|
+
case "seed": {
|
|
1550
|
+
const subCommands = commands.slice(1);
|
|
1551
|
+
const actionFlag = (args.flags.action || "").toString().toLowerCase();
|
|
1552
|
+
const firstSub = (subCommands[0] || "").toString().toLowerCase();
|
|
1553
|
+
const action = actionFlag === "down" || firstSub === "down" ? "down" : "up";
|
|
1554
|
+
const positionalNames = actionFlag ? subCommands : firstSub === "up" || firstSub === "down" ? subCommands.slice(1) : subCommands;
|
|
1555
|
+
const aliasFlag = args.flags.alias;
|
|
1556
|
+
const aliasMap = {};
|
|
1557
|
+
if (aliasFlag) {
|
|
1558
|
+
const aliases = Array.isArray(aliasFlag) ? aliasFlag : [aliasFlag];
|
|
1559
|
+
for (const entry of aliases) {
|
|
1560
|
+
const eq = entry.indexOf("=");
|
|
1561
|
+
if (eq > 0) {
|
|
1562
|
+
const key = entry.slice(0, eq);
|
|
1563
|
+
const value = entry.slice(eq + 1);
|
|
1564
|
+
if (key) aliasMap[key] = value;
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
const seedOptions = {
|
|
1569
|
+
migrationsDir: args.flags.migrationsDir || args.flags["migrations-dir"],
|
|
1570
|
+
dataDir: args.flags.dataDir || args.flags["data-dir"],
|
|
1571
|
+
validate: args.flags.validate === void 0 ? true : String(args.flags.validate).toLowerCase() !== "false",
|
|
1572
|
+
transactional: args.flags.transactional,
|
|
1573
|
+
aliasMap: Object.keys(aliasMap).length ? aliasMap : void 0,
|
|
1574
|
+
names: positionalNames.length ? positionalNames : void 0,
|
|
1575
|
+
log: (msg) => console.log(msg)
|
|
1576
|
+
};
|
|
1577
|
+
const reader = new FileMigrationConfigReader(config_file);
|
|
1578
|
+
const migrationConfig = reader.loadFile();
|
|
1579
|
+
yield runSeedsWithRunner(runner, migrationConfig, action, seedOptions);
|
|
1580
|
+
yield runner.close();
|
|
1581
|
+
break;
|
|
1582
|
+
}
|
|
1192
1583
|
default:
|
|
1193
1584
|
throw CLIError.unknownCommand(command);
|
|
1194
1585
|
}
|
|
@@ -1220,12 +1611,15 @@ Commands:
|
|
|
1220
1611
|
Options:
|
|
1221
1612
|
-c, --config Specify the config file (default: proper.json)
|
|
1222
1613
|
--increment <n> Limit the number of migrations to apply or roll back
|
|
1614
|
+
--all Roll back all completed migrations (down command only)
|
|
1223
1615
|
--format <fmt> Output format for query command: 'table' (default) or 'json'
|
|
1224
1616
|
|
|
1225
1617
|
Examples:
|
|
1226
1618
|
proper up Apply all pending migrations
|
|
1227
1619
|
proper up --increment 1 Apply only the next pending migration
|
|
1228
|
-
proper down Roll back the last applied migration
|
|
1620
|
+
proper down Roll back the last applied migration (default: 1)
|
|
1621
|
+
proper down --increment 3 Roll back the last 3 applied migrations
|
|
1622
|
+
proper down --all Roll back all completed migrations
|
|
1229
1623
|
proper create my_migration Create a new migration named "my_migration"
|
|
1230
1624
|
proper init Create a new config file
|
|
1231
1625
|
proper status Show the status of all migrations
|