@noego/proper 0.0.9 → 0.1.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/bin/cli.js +179 -52
- package/bin/cli.js.map +1 -1
- package/bin/cli.mjs +181 -53
- package/bin/cli.mjs.map +1 -1
- package/bin/index.d.mts +104 -2
- package/bin/index.d.ts +104 -2
- package/bin/index.js +181 -52
- package/bin/index.js.map +1 -1
- package/bin/index.mjs +178 -52
- package/bin/index.mjs.map +1 -1
- package/lib/runner.js.map +1 -1
- package/lib/runner.mjs.map +1 -1
- package/package.json +5 -3
package/bin/cli.js
CHANGED
|
@@ -124,9 +124,6 @@ function migration_filter(_0) {
|
|
|
124
124
|
|
|
125
125
|
// framework/MigrationRunner.ts
|
|
126
126
|
var import_fs3 = __toESM(require("fs"));
|
|
127
|
-
var import_promise = __toESM(require("mysql2/promise"));
|
|
128
|
-
var sqlite = __toESM(require("sqlite"));
|
|
129
|
-
var sqlite3 = __toESM(require("sqlite3"));
|
|
130
127
|
|
|
131
128
|
// framework/MigrationDirectoryReader.ts
|
|
132
129
|
var import_fs = __toESM(require("fs"));
|
|
@@ -418,9 +415,10 @@ var MigrationDirectoryReader = class {
|
|
|
418
415
|
/**
|
|
419
416
|
* Resolves the appropriate file for a migration based on dialect.
|
|
420
417
|
* Priority: dialect-specific file > generic file
|
|
418
|
+
* File extensions: `.mysql.up.sql`, `.sqlite.up.sql`, `.pg.up.sql`.
|
|
421
419
|
*/
|
|
422
420
|
resolveFile(baseName, direction) {
|
|
423
|
-
const dialectExt = this.dialect === "sql" ? "mysql" :
|
|
421
|
+
const dialectExt = this.dialect === "sql" ? "mysql" : this.dialect;
|
|
424
422
|
const dialectFile = import_path.default.join(this.directory, `${baseName}.${dialectExt}.${direction}.sql`);
|
|
425
423
|
if (import_fs.default.existsSync(dialectFile)) return dialectFile;
|
|
426
424
|
const genericFile = import_path.default.join(this.directory, `${baseName}.${direction}.sql`);
|
|
@@ -431,14 +429,14 @@ var MigrationDirectoryReader = class {
|
|
|
431
429
|
* Checks if a file path is dialect-specific (contains .mysql. or .sqlite. in the name)
|
|
432
430
|
*/
|
|
433
431
|
isDialectSpecific(filePath) {
|
|
434
|
-
return /\.(mysql|sqlite)\.(up|down)\.sql$/i.test(filePath);
|
|
432
|
+
return /\.(mysql|sqlite|pg)\.(up|down)\.sql$/i.test(filePath);
|
|
435
433
|
}
|
|
436
434
|
loadMigrations(table, connection) {
|
|
437
435
|
import_fs.default.existsSync(this.directory) || import_fs.default.mkdirSync(this.directory);
|
|
438
436
|
const dir_content = import_fs.default.readdirSync(this.directory, { withFileTypes: true }).filter((file) => file.isFile()).map((file) => file.name);
|
|
439
437
|
const uniqueKeys = /* @__PURE__ */ new Set();
|
|
440
438
|
dir_content.forEach((file) => {
|
|
441
|
-
const key = file.replace(/(?:\.(mysql|sqlite))?\.(up|down)\.(sql|js)/i, "").toLowerCase();
|
|
439
|
+
const key = file.replace(/(?:\.(mysql|sqlite|pg))?\.(up|down)\.(sql|js)/i, "").toLowerCase();
|
|
442
440
|
uniqueKeys.add(key);
|
|
443
441
|
});
|
|
444
442
|
const migration_sorter = {};
|
|
@@ -510,6 +508,12 @@ var MigrationSetup = class {
|
|
|
510
508
|
up TEXT,
|
|
511
509
|
down TEXT,
|
|
512
510
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
511
|
+
)` : this.config.database === "pg" ? `CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
512
|
+
id SERIAL PRIMARY KEY,
|
|
513
|
+
migration_key TEXT,
|
|
514
|
+
up TEXT,
|
|
515
|
+
down TEXT,
|
|
516
|
+
created_at TIMESTAMPTZ DEFAULT now()
|
|
513
517
|
)` : `CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
514
518
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
515
519
|
migration_key VARCHAR(255),
|
|
@@ -554,31 +558,35 @@ function MySqlDialectParser(sql) {
|
|
|
554
558
|
}
|
|
555
559
|
return result;
|
|
556
560
|
}
|
|
557
|
-
function
|
|
558
|
-
const
|
|
559
|
-
let result = "";
|
|
560
|
-
let isInSqliteBlock = true;
|
|
561
|
-
const startSqliteRegex = /^\s*--\s*\[\s*sqlite\s*\]\s*$/i;
|
|
561
|
+
function markerDialectParser(names) {
|
|
562
|
+
const startRegex = new RegExp(`^\\s*--\\s*\\[\\s*(${names.join("|")})\\s*\\]\\s*$`, "i");
|
|
562
563
|
const anyDialectRegex = /^\s*--\s*\[\s*\w+\s*\]\s*$/i;
|
|
563
|
-
|
|
564
|
-
const
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
564
|
+
return function(sql) {
|
|
565
|
+
const lines = sql.split("\n");
|
|
566
|
+
let result = "";
|
|
567
|
+
let capturing = true;
|
|
568
|
+
for (const line of lines) {
|
|
569
|
+
const trimmed = line.trim();
|
|
570
|
+
if (startRegex.test(trimmed)) {
|
|
571
|
+
capturing = true;
|
|
572
|
+
result += line + "\n";
|
|
573
|
+
continue;
|
|
574
|
+
} else if (anyDialectRegex.test(trimmed)) {
|
|
575
|
+
capturing = false;
|
|
576
|
+
continue;
|
|
577
|
+
}
|
|
578
|
+
if (!capturing && line.toLowerCase().includes("create index")) {
|
|
579
|
+
capturing = true;
|
|
580
|
+
}
|
|
581
|
+
if (capturing) {
|
|
582
|
+
result += line + "\n";
|
|
583
|
+
}
|
|
578
584
|
}
|
|
579
|
-
|
|
580
|
-
|
|
585
|
+
return result;
|
|
586
|
+
};
|
|
581
587
|
}
|
|
588
|
+
var SqliteDialectParser = markerDialectParser(["sqlite"]);
|
|
589
|
+
var PgDialectParser = markerDialectParser(["pg", "postgres", "postgresql"]);
|
|
582
590
|
|
|
583
591
|
// framework/SQLRunner.ts
|
|
584
592
|
var BaseSQLRunner = class {
|
|
@@ -794,12 +802,122 @@ ${sql}
|
|
|
794
802
|
});
|
|
795
803
|
}
|
|
796
804
|
};
|
|
805
|
+
var PgRunner = class _PgRunner extends BaseSQLRunner {
|
|
806
|
+
constructor(connection) {
|
|
807
|
+
super();
|
|
808
|
+
this.connection = connection;
|
|
809
|
+
}
|
|
810
|
+
/** `?` -> `$1`, `$2`, ... outside of string literals / comments. */
|
|
811
|
+
static toPositional(sql) {
|
|
812
|
+
let out = "";
|
|
813
|
+
let n = 0;
|
|
814
|
+
let inSingle = false;
|
|
815
|
+
let inDouble = false;
|
|
816
|
+
let inLineComment = false;
|
|
817
|
+
let inBlockComment = false;
|
|
818
|
+
for (let i = 0; i < sql.length; i++) {
|
|
819
|
+
const ch = sql[i];
|
|
820
|
+
const next = sql[i + 1];
|
|
821
|
+
if (inLineComment) {
|
|
822
|
+
out += ch;
|
|
823
|
+
if (ch === "\n") inLineComment = false;
|
|
824
|
+
continue;
|
|
825
|
+
}
|
|
826
|
+
if (inBlockComment) {
|
|
827
|
+
out += ch;
|
|
828
|
+
if (ch === "*" && next === "/") {
|
|
829
|
+
out += next;
|
|
830
|
+
i++;
|
|
831
|
+
inBlockComment = false;
|
|
832
|
+
}
|
|
833
|
+
continue;
|
|
834
|
+
}
|
|
835
|
+
if (inSingle) {
|
|
836
|
+
out += ch;
|
|
837
|
+
if (ch === "'") inSingle = false;
|
|
838
|
+
continue;
|
|
839
|
+
}
|
|
840
|
+
if (inDouble) {
|
|
841
|
+
out += ch;
|
|
842
|
+
if (ch === '"') inDouble = false;
|
|
843
|
+
continue;
|
|
844
|
+
}
|
|
845
|
+
if (ch === "-" && next === "-") {
|
|
846
|
+
out += ch;
|
|
847
|
+
inLineComment = true;
|
|
848
|
+
continue;
|
|
849
|
+
}
|
|
850
|
+
if (ch === "/" && next === "*") {
|
|
851
|
+
out += ch + next;
|
|
852
|
+
i++;
|
|
853
|
+
inBlockComment = true;
|
|
854
|
+
continue;
|
|
855
|
+
}
|
|
856
|
+
if (ch === "'") {
|
|
857
|
+
out += ch;
|
|
858
|
+
inSingle = true;
|
|
859
|
+
continue;
|
|
860
|
+
}
|
|
861
|
+
if (ch === '"') {
|
|
862
|
+
out += ch;
|
|
863
|
+
inDouble = true;
|
|
864
|
+
continue;
|
|
865
|
+
}
|
|
866
|
+
if (ch === "?") {
|
|
867
|
+
out += `$${++n}`;
|
|
868
|
+
continue;
|
|
869
|
+
}
|
|
870
|
+
out += ch;
|
|
871
|
+
}
|
|
872
|
+
return out;
|
|
873
|
+
}
|
|
874
|
+
run(sql, params) {
|
|
875
|
+
return __async(this, null, function* () {
|
|
876
|
+
if (params.length > 0) {
|
|
877
|
+
return yield this.connection.query(_PgRunner.toPositional(sql), params);
|
|
878
|
+
}
|
|
879
|
+
return yield this.connection.query(sql);
|
|
880
|
+
});
|
|
881
|
+
}
|
|
882
|
+
_query(_0) {
|
|
883
|
+
return __async(this, arguments, function* (sql, params = []) {
|
|
884
|
+
const result = yield this.run(sql, params);
|
|
885
|
+
return [result.rows, result];
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
_execute(_0) {
|
|
889
|
+
return __async(this, arguments, function* (sql, params = []) {
|
|
890
|
+
var _a;
|
|
891
|
+
const result = yield this.run(sql, params);
|
|
892
|
+
return [{ changes: (_a = result.rowCount) != null ? _a : 0, lastID: void 0 }, result];
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
_end() {
|
|
896
|
+
return __async(this, null, function* () {
|
|
897
|
+
if (this.connection && typeof this.connection.end === "function") {
|
|
898
|
+
yield this.connection.end();
|
|
899
|
+
}
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
};
|
|
797
903
|
|
|
798
904
|
// framework/MigrationRunner.ts
|
|
799
905
|
function toError(error) {
|
|
800
906
|
if (error instanceof Error) return error;
|
|
801
907
|
return new Error(String(error));
|
|
802
908
|
}
|
|
909
|
+
function makeRunner(database, conn) {
|
|
910
|
+
switch (database) {
|
|
911
|
+
case "sql":
|
|
912
|
+
return new SQLRunner(conn);
|
|
913
|
+
case "sqlite":
|
|
914
|
+
return new SQLiteRunner(conn);
|
|
915
|
+
case "pg":
|
|
916
|
+
return new PgRunner(conn);
|
|
917
|
+
default:
|
|
918
|
+
throw ConfigurationError.unknownDatabaseType(database);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
803
921
|
var MigrationRunnerFactory = class _MigrationRunnerFactory {
|
|
804
922
|
static isSQLRunner(conn) {
|
|
805
923
|
return !!conn && typeof conn.query === "function" && typeof conn.execute === "function" && typeof conn.end === "function";
|
|
@@ -816,6 +934,7 @@ var MigrationRunnerFactory = class _MigrationRunnerFactory {
|
|
|
816
934
|
}
|
|
817
935
|
static createConnection(config) {
|
|
818
936
|
return __async(this, null, function* () {
|
|
937
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
819
938
|
let conn = null;
|
|
820
939
|
switch (config.database) {
|
|
821
940
|
case "sql":
|
|
@@ -826,7 +945,8 @@ var MigrationRunnerFactory = class _MigrationRunnerFactory {
|
|
|
826
945
|
password: process.env.SQL_PASSWORD
|
|
827
946
|
}, config.sql);
|
|
828
947
|
try {
|
|
829
|
-
|
|
948
|
+
const mysql = yield import("mysql2/promise");
|
|
949
|
+
conn = yield ((_b = (_a = mysql.default) == null ? void 0 : _a.createConnection) != null ? _b : mysql.createConnection)(settings);
|
|
830
950
|
return conn;
|
|
831
951
|
} catch (error) {
|
|
832
952
|
throw DatabaseConnectionError.connectionFailed("sql", toError(error).message);
|
|
@@ -836,14 +956,32 @@ var MigrationRunnerFactory = class _MigrationRunnerFactory {
|
|
|
836
956
|
throw ConfigurationError.missingDatabaseConfiguration("sqlite");
|
|
837
957
|
}
|
|
838
958
|
try {
|
|
839
|
-
|
|
959
|
+
const sqlite = yield import("sqlite");
|
|
960
|
+
const sqlite3 = yield import("sqlite3");
|
|
961
|
+
conn = yield ((_d = (_c = sqlite.default) == null ? void 0 : _c.open) != null ? _d : sqlite.open)({
|
|
840
962
|
filename: config.sqlite.database,
|
|
841
|
-
driver: sqlite3.Database
|
|
963
|
+
driver: (_f = (_e = sqlite3.default) == null ? void 0 : _e.Database) != null ? _f : sqlite3.Database
|
|
842
964
|
});
|
|
843
965
|
return conn;
|
|
844
966
|
} catch (error) {
|
|
845
967
|
throw DatabaseConnectionError.connectionFailed("sqlite", toError(error).message);
|
|
846
968
|
}
|
|
969
|
+
case "pg":
|
|
970
|
+
if (!config.pg && !process.env.DATABASE_URL) {
|
|
971
|
+
throw ConfigurationError.missingDatabaseConfiguration("pg");
|
|
972
|
+
}
|
|
973
|
+
try {
|
|
974
|
+
const pgcfg = (_g = config.pg) != null ? _g : {};
|
|
975
|
+
const connectionString = (_h = pgcfg.connectionString) != null ? _h : process.env.DATABASE_URL;
|
|
976
|
+
const settings2 = connectionString ? { connectionString, ssl: pgcfg.ssl } : __spreadProps(__spreadValues({}, pgcfg), { password: (_i = pgcfg.password) != null ? _i : process.env.PG_PASSWORD });
|
|
977
|
+
const pg = yield import("pg");
|
|
978
|
+
const Client = (_k = (_j = pg.default) == null ? void 0 : _j.Client) != null ? _k : pg.Client;
|
|
979
|
+
conn = new Client(settings2);
|
|
980
|
+
yield conn.connect();
|
|
981
|
+
return conn;
|
|
982
|
+
} catch (error) {
|
|
983
|
+
throw DatabaseConnectionError.connectionFailed("pg", toError(error).message);
|
|
984
|
+
}
|
|
847
985
|
default:
|
|
848
986
|
throw ConfigurationError.unknownDatabaseType(config.database);
|
|
849
987
|
}
|
|
@@ -864,16 +1002,7 @@ var MigrationRunnerFactory = class _MigrationRunnerFactory {
|
|
|
864
1002
|
sqlrunner = conn;
|
|
865
1003
|
driverConnection = null;
|
|
866
1004
|
} else {
|
|
867
|
-
|
|
868
|
-
case "sql":
|
|
869
|
-
sqlrunner = new SQLRunner(conn);
|
|
870
|
-
break;
|
|
871
|
-
case "sqlite":
|
|
872
|
-
sqlrunner = new SQLiteRunner(conn);
|
|
873
|
-
break;
|
|
874
|
-
default:
|
|
875
|
-
throw ConfigurationError.unknownDatabaseType(config.database);
|
|
876
|
-
}
|
|
1005
|
+
sqlrunner = makeRunner(config.database, conn);
|
|
877
1006
|
}
|
|
878
1007
|
const setup = new MigrationSetup(sqlrunner, config);
|
|
879
1008
|
const read_strategy = this.getReadStategy(config);
|
|
@@ -885,17 +1014,7 @@ var MigrationRunnerFactory = class _MigrationRunnerFactory {
|
|
|
885
1014
|
createEmpty(config) {
|
|
886
1015
|
return __async(this, null, function* () {
|
|
887
1016
|
const conn = null;
|
|
888
|
-
|
|
889
|
-
switch (config.database) {
|
|
890
|
-
case "sql":
|
|
891
|
-
sqlrunner = new SQLRunner(conn);
|
|
892
|
-
break;
|
|
893
|
-
case "sqlite":
|
|
894
|
-
sqlrunner = new SQLiteRunner(conn);
|
|
895
|
-
break;
|
|
896
|
-
default:
|
|
897
|
-
throw ConfigurationError.unknownDatabaseType(config.database);
|
|
898
|
-
}
|
|
1017
|
+
const sqlrunner = makeRunner(config.database, conn);
|
|
899
1018
|
const setup = new MigrationSetup(sqlrunner, config);
|
|
900
1019
|
const read_strategy = this.getReadStategy(config);
|
|
901
1020
|
const migration_files = new MigrationDirectoryReader(config.migration_folder, read_strategy, sqlrunner, config.database);
|
|
@@ -908,6 +1027,8 @@ var MigrationRunnerFactory = class _MigrationRunnerFactory {
|
|
|
908
1027
|
return MySqlDialectParser;
|
|
909
1028
|
case "sqlite":
|
|
910
1029
|
return SqliteDialectParser;
|
|
1030
|
+
case "pg":
|
|
1031
|
+
return PgDialectParser;
|
|
911
1032
|
default:
|
|
912
1033
|
throw ConfigurationError.unknownDatabaseType(config.database);
|
|
913
1034
|
}
|
|
@@ -1094,6 +1215,8 @@ var FileMigrationConfigReader = class {
|
|
|
1094
1215
|
config.database = "sql";
|
|
1095
1216
|
} else if (config.sqlite) {
|
|
1096
1217
|
config.database = "sqlite";
|
|
1218
|
+
} else if (config.pg) {
|
|
1219
|
+
config.database = "pg";
|
|
1097
1220
|
} else {
|
|
1098
1221
|
throw ConfigurationError.missingRequiredProperty("database");
|
|
1099
1222
|
}
|
|
@@ -1376,6 +1499,10 @@ function runSeedsWithRunner(runner, migrationConfig, direction, options) {
|
|
|
1376
1499
|
|
|
1377
1500
|
// cli.ts
|
|
1378
1501
|
var args = MigrationCLIFactory.setup(process.argv);
|
|
1502
|
+
if (args.flags.help) {
|
|
1503
|
+
printUsage();
|
|
1504
|
+
process.exit(0);
|
|
1505
|
+
}
|
|
1379
1506
|
if (!args.commands || args.commands.length === 0) {
|
|
1380
1507
|
console.error("Error: No command specified");
|
|
1381
1508
|
printUsage();
|