@noego/proper 0.0.8 → 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 +185 -52
- package/bin/cli.js.map +1 -1
- package/bin/cli.mjs +187 -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 +187 -52
- package/bin/index.js.map +1 -1
- package/bin/index.mjs +184 -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.mjs
CHANGED
|
@@ -429,9 +429,10 @@ var init_MigrationDirectoryReader = __esm({
|
|
|
429
429
|
/**
|
|
430
430
|
* Resolves the appropriate file for a migration based on dialect.
|
|
431
431
|
* Priority: dialect-specific file > generic file
|
|
432
|
+
* File extensions: `.mysql.up.sql`, `.sqlite.up.sql`, `.pg.up.sql`.
|
|
432
433
|
*/
|
|
433
434
|
resolveFile(baseName, direction) {
|
|
434
|
-
const dialectExt = this.dialect === "sql" ? "mysql" :
|
|
435
|
+
const dialectExt = this.dialect === "sql" ? "mysql" : this.dialect;
|
|
435
436
|
const dialectFile = path.join(this.directory, `${baseName}.${dialectExt}.${direction}.sql`);
|
|
436
437
|
if (fs.existsSync(dialectFile)) return dialectFile;
|
|
437
438
|
const genericFile = path.join(this.directory, `${baseName}.${direction}.sql`);
|
|
@@ -442,14 +443,14 @@ var init_MigrationDirectoryReader = __esm({
|
|
|
442
443
|
* Checks if a file path is dialect-specific (contains .mysql. or .sqlite. in the name)
|
|
443
444
|
*/
|
|
444
445
|
isDialectSpecific(filePath) {
|
|
445
|
-
return /\.(mysql|sqlite)\.(up|down)\.sql$/i.test(filePath);
|
|
446
|
+
return /\.(mysql|sqlite|pg)\.(up|down)\.sql$/i.test(filePath);
|
|
446
447
|
}
|
|
447
448
|
loadMigrations(table, connection) {
|
|
448
449
|
fs.existsSync(this.directory) || fs.mkdirSync(this.directory);
|
|
449
450
|
const dir_content = fs.readdirSync(this.directory, { withFileTypes: true }).filter((file) => file.isFile()).map((file) => file.name);
|
|
450
451
|
const uniqueKeys = /* @__PURE__ */ new Set();
|
|
451
452
|
dir_content.forEach((file) => {
|
|
452
|
-
const key = file.replace(/(?:\.(mysql|sqlite))?\.(up|down)\.(sql|js)/i, "").toLowerCase();
|
|
453
|
+
const key = file.replace(/(?:\.(mysql|sqlite|pg))?\.(up|down)\.(sql|js)/i, "").toLowerCase();
|
|
453
454
|
uniqueKeys.add(key);
|
|
454
455
|
});
|
|
455
456
|
const migration_sorter = {};
|
|
@@ -526,6 +527,12 @@ var init_MigrationSetup = __esm({
|
|
|
526
527
|
up TEXT,
|
|
527
528
|
down TEXT,
|
|
528
529
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
530
|
+
)` : this.config.database === "pg" ? `CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
531
|
+
id SERIAL PRIMARY KEY,
|
|
532
|
+
migration_key TEXT,
|
|
533
|
+
up TEXT,
|
|
534
|
+
down TEXT,
|
|
535
|
+
created_at TIMESTAMPTZ DEFAULT now()
|
|
529
536
|
)` : `CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
530
537
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
531
538
|
migration_key VARCHAR(255),
|
|
@@ -572,33 +579,38 @@ function MySqlDialectParser(sql) {
|
|
|
572
579
|
}
|
|
573
580
|
return result;
|
|
574
581
|
}
|
|
575
|
-
function
|
|
576
|
-
const
|
|
577
|
-
let result = "";
|
|
578
|
-
let isInSqliteBlock = true;
|
|
579
|
-
const startSqliteRegex = /^\s*--\s*\[\s*sqlite\s*\]\s*$/i;
|
|
582
|
+
function markerDialectParser(names) {
|
|
583
|
+
const startRegex = new RegExp(`^\\s*--\\s*\\[\\s*(${names.join("|")})\\s*\\]\\s*$`, "i");
|
|
580
584
|
const anyDialectRegex = /^\s*--\s*\[\s*\w+\s*\]\s*$/i;
|
|
581
|
-
|
|
582
|
-
const
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
585
|
+
return function(sql) {
|
|
586
|
+
const lines = sql.split("\n");
|
|
587
|
+
let result = "";
|
|
588
|
+
let capturing = true;
|
|
589
|
+
for (const line of lines) {
|
|
590
|
+
const trimmed = line.trim();
|
|
591
|
+
if (startRegex.test(trimmed)) {
|
|
592
|
+
capturing = true;
|
|
593
|
+
result += line + "\n";
|
|
594
|
+
continue;
|
|
595
|
+
} else if (anyDialectRegex.test(trimmed)) {
|
|
596
|
+
capturing = false;
|
|
597
|
+
continue;
|
|
598
|
+
}
|
|
599
|
+
if (!capturing && line.toLowerCase().includes("create index")) {
|
|
600
|
+
capturing = true;
|
|
601
|
+
}
|
|
602
|
+
if (capturing) {
|
|
603
|
+
result += line + "\n";
|
|
604
|
+
}
|
|
596
605
|
}
|
|
597
|
-
|
|
598
|
-
|
|
606
|
+
return result;
|
|
607
|
+
};
|
|
599
608
|
}
|
|
609
|
+
var SqliteDialectParser, PgDialectParser;
|
|
600
610
|
var init_MigrationDialectParser = __esm({
|
|
601
611
|
"framework/MigrationDialectParser.ts"() {
|
|
612
|
+
SqliteDialectParser = markerDialectParser(["sqlite"]);
|
|
613
|
+
PgDialectParser = markerDialectParser(["pg", "postgres", "postgresql"]);
|
|
602
614
|
}
|
|
603
615
|
});
|
|
604
616
|
|
|
@@ -606,7 +618,7 @@ var init_MigrationDialectParser = __esm({
|
|
|
606
618
|
function isPromiseLike(value) {
|
|
607
619
|
return !!value && typeof value.then === "function";
|
|
608
620
|
}
|
|
609
|
-
var BaseSQLRunner, SQLRunner, SQLiteRunner;
|
|
621
|
+
var BaseSQLRunner, SQLRunner, SQLiteRunner, PgRunner;
|
|
610
622
|
var init_SQLRunner = __esm({
|
|
611
623
|
"framework/SQLRunner.ts"() {
|
|
612
624
|
BaseSQLRunner = class {
|
|
@@ -819,18 +831,125 @@ ${sql}
|
|
|
819
831
|
});
|
|
820
832
|
}
|
|
821
833
|
};
|
|
834
|
+
PgRunner = class _PgRunner extends BaseSQLRunner {
|
|
835
|
+
constructor(connection) {
|
|
836
|
+
super();
|
|
837
|
+
this.connection = connection;
|
|
838
|
+
}
|
|
839
|
+
/** `?` -> `$1`, `$2`, ... outside of string literals / comments. */
|
|
840
|
+
static toPositional(sql) {
|
|
841
|
+
let out = "";
|
|
842
|
+
let n = 0;
|
|
843
|
+
let inSingle = false;
|
|
844
|
+
let inDouble = false;
|
|
845
|
+
let inLineComment = false;
|
|
846
|
+
let inBlockComment = false;
|
|
847
|
+
for (let i = 0; i < sql.length; i++) {
|
|
848
|
+
const ch = sql[i];
|
|
849
|
+
const next = sql[i + 1];
|
|
850
|
+
if (inLineComment) {
|
|
851
|
+
out += ch;
|
|
852
|
+
if (ch === "\n") inLineComment = false;
|
|
853
|
+
continue;
|
|
854
|
+
}
|
|
855
|
+
if (inBlockComment) {
|
|
856
|
+
out += ch;
|
|
857
|
+
if (ch === "*" && next === "/") {
|
|
858
|
+
out += next;
|
|
859
|
+
i++;
|
|
860
|
+
inBlockComment = false;
|
|
861
|
+
}
|
|
862
|
+
continue;
|
|
863
|
+
}
|
|
864
|
+
if (inSingle) {
|
|
865
|
+
out += ch;
|
|
866
|
+
if (ch === "'") inSingle = false;
|
|
867
|
+
continue;
|
|
868
|
+
}
|
|
869
|
+
if (inDouble) {
|
|
870
|
+
out += ch;
|
|
871
|
+
if (ch === '"') inDouble = false;
|
|
872
|
+
continue;
|
|
873
|
+
}
|
|
874
|
+
if (ch === "-" && next === "-") {
|
|
875
|
+
out += ch;
|
|
876
|
+
inLineComment = true;
|
|
877
|
+
continue;
|
|
878
|
+
}
|
|
879
|
+
if (ch === "/" && next === "*") {
|
|
880
|
+
out += ch + next;
|
|
881
|
+
i++;
|
|
882
|
+
inBlockComment = true;
|
|
883
|
+
continue;
|
|
884
|
+
}
|
|
885
|
+
if (ch === "'") {
|
|
886
|
+
out += ch;
|
|
887
|
+
inSingle = true;
|
|
888
|
+
continue;
|
|
889
|
+
}
|
|
890
|
+
if (ch === '"') {
|
|
891
|
+
out += ch;
|
|
892
|
+
inDouble = true;
|
|
893
|
+
continue;
|
|
894
|
+
}
|
|
895
|
+
if (ch === "?") {
|
|
896
|
+
out += `$${++n}`;
|
|
897
|
+
continue;
|
|
898
|
+
}
|
|
899
|
+
out += ch;
|
|
900
|
+
}
|
|
901
|
+
return out;
|
|
902
|
+
}
|
|
903
|
+
run(sql, params) {
|
|
904
|
+
return __async(this, null, function* () {
|
|
905
|
+
if (params.length > 0) {
|
|
906
|
+
return yield this.connection.query(_PgRunner.toPositional(sql), params);
|
|
907
|
+
}
|
|
908
|
+
return yield this.connection.query(sql);
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
_query(_0) {
|
|
912
|
+
return __async(this, arguments, function* (sql, params = []) {
|
|
913
|
+
const result = yield this.run(sql, params);
|
|
914
|
+
return [result.rows, result];
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
_execute(_0) {
|
|
918
|
+
return __async(this, arguments, function* (sql, params = []) {
|
|
919
|
+
var _a;
|
|
920
|
+
const result = yield this.run(sql, params);
|
|
921
|
+
return [{ changes: (_a = result.rowCount) != null ? _a : 0, lastID: void 0 }, result];
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
_end() {
|
|
925
|
+
return __async(this, null, function* () {
|
|
926
|
+
if (this.connection && typeof this.connection.end === "function") {
|
|
927
|
+
yield this.connection.end();
|
|
928
|
+
}
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
};
|
|
822
932
|
}
|
|
823
933
|
});
|
|
824
934
|
|
|
825
935
|
// framework/MigrationRunner.ts
|
|
826
936
|
import fs3 from "fs";
|
|
827
|
-
import mysql from "mysql2/promise";
|
|
828
|
-
import * as sqlite from "sqlite";
|
|
829
|
-
import * as sqlite3 from "sqlite3";
|
|
830
937
|
function toError(error) {
|
|
831
938
|
if (error instanceof Error) return error;
|
|
832
939
|
return new Error(String(error));
|
|
833
940
|
}
|
|
941
|
+
function makeRunner(database, conn) {
|
|
942
|
+
switch (database) {
|
|
943
|
+
case "sql":
|
|
944
|
+
return new SQLRunner(conn);
|
|
945
|
+
case "sqlite":
|
|
946
|
+
return new SQLiteRunner(conn);
|
|
947
|
+
case "pg":
|
|
948
|
+
return new PgRunner(conn);
|
|
949
|
+
default:
|
|
950
|
+
throw ConfigurationError.unknownDatabaseType(database);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
834
953
|
var MigrationRunnerFactory, MySQLMigrationRunner, FileMigrationConfigReader, MigrationCreator;
|
|
835
954
|
var init_MigrationRunner = __esm({
|
|
836
955
|
"framework/MigrationRunner.ts"() {
|
|
@@ -856,6 +975,7 @@ var init_MigrationRunner = __esm({
|
|
|
856
975
|
}
|
|
857
976
|
static createConnection(config) {
|
|
858
977
|
return __async(this, null, function* () {
|
|
978
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
859
979
|
let conn = null;
|
|
860
980
|
switch (config.database) {
|
|
861
981
|
case "sql":
|
|
@@ -866,7 +986,8 @@ var init_MigrationRunner = __esm({
|
|
|
866
986
|
password: process.env.SQL_PASSWORD
|
|
867
987
|
}, config.sql);
|
|
868
988
|
try {
|
|
869
|
-
|
|
989
|
+
const mysql = yield import("mysql2/promise");
|
|
990
|
+
conn = yield ((_b = (_a = mysql.default) == null ? void 0 : _a.createConnection) != null ? _b : mysql.createConnection)(settings);
|
|
870
991
|
return conn;
|
|
871
992
|
} catch (error) {
|
|
872
993
|
throw DatabaseConnectionError.connectionFailed("sql", toError(error).message);
|
|
@@ -876,14 +997,32 @@ var init_MigrationRunner = __esm({
|
|
|
876
997
|
throw ConfigurationError.missingDatabaseConfiguration("sqlite");
|
|
877
998
|
}
|
|
878
999
|
try {
|
|
879
|
-
|
|
1000
|
+
const sqlite = yield import("sqlite");
|
|
1001
|
+
const sqlite3 = yield import("sqlite3");
|
|
1002
|
+
conn = yield ((_d = (_c = sqlite.default) == null ? void 0 : _c.open) != null ? _d : sqlite.open)({
|
|
880
1003
|
filename: config.sqlite.database,
|
|
881
|
-
driver: sqlite3.Database
|
|
1004
|
+
driver: (_f = (_e = sqlite3.default) == null ? void 0 : _e.Database) != null ? _f : sqlite3.Database
|
|
882
1005
|
});
|
|
883
1006
|
return conn;
|
|
884
1007
|
} catch (error) {
|
|
885
1008
|
throw DatabaseConnectionError.connectionFailed("sqlite", toError(error).message);
|
|
886
1009
|
}
|
|
1010
|
+
case "pg":
|
|
1011
|
+
if (!config.pg && !process.env.DATABASE_URL) {
|
|
1012
|
+
throw ConfigurationError.missingDatabaseConfiguration("pg");
|
|
1013
|
+
}
|
|
1014
|
+
try {
|
|
1015
|
+
const pgcfg = (_g = config.pg) != null ? _g : {};
|
|
1016
|
+
const connectionString = (_h = pgcfg.connectionString) != null ? _h : process.env.DATABASE_URL;
|
|
1017
|
+
const settings2 = connectionString ? { connectionString, ssl: pgcfg.ssl } : __spreadProps(__spreadValues({}, pgcfg), { password: (_i = pgcfg.password) != null ? _i : process.env.PG_PASSWORD });
|
|
1018
|
+
const pg = yield import("pg");
|
|
1019
|
+
const Client = (_k = (_j = pg.default) == null ? void 0 : _j.Client) != null ? _k : pg.Client;
|
|
1020
|
+
conn = new Client(settings2);
|
|
1021
|
+
yield conn.connect();
|
|
1022
|
+
return conn;
|
|
1023
|
+
} catch (error) {
|
|
1024
|
+
throw DatabaseConnectionError.connectionFailed("pg", toError(error).message);
|
|
1025
|
+
}
|
|
887
1026
|
default:
|
|
888
1027
|
throw ConfigurationError.unknownDatabaseType(config.database);
|
|
889
1028
|
}
|
|
@@ -904,16 +1043,7 @@ var init_MigrationRunner = __esm({
|
|
|
904
1043
|
sqlrunner = conn;
|
|
905
1044
|
driverConnection = null;
|
|
906
1045
|
} else {
|
|
907
|
-
|
|
908
|
-
case "sql":
|
|
909
|
-
sqlrunner = new SQLRunner(conn);
|
|
910
|
-
break;
|
|
911
|
-
case "sqlite":
|
|
912
|
-
sqlrunner = new SQLiteRunner(conn);
|
|
913
|
-
break;
|
|
914
|
-
default:
|
|
915
|
-
throw ConfigurationError.unknownDatabaseType(config.database);
|
|
916
|
-
}
|
|
1046
|
+
sqlrunner = makeRunner(config.database, conn);
|
|
917
1047
|
}
|
|
918
1048
|
const setup = new MigrationSetup(sqlrunner, config);
|
|
919
1049
|
const read_strategy = this.getReadStategy(config);
|
|
@@ -925,17 +1055,7 @@ var init_MigrationRunner = __esm({
|
|
|
925
1055
|
createEmpty(config) {
|
|
926
1056
|
return __async(this, null, function* () {
|
|
927
1057
|
const conn = null;
|
|
928
|
-
|
|
929
|
-
switch (config.database) {
|
|
930
|
-
case "sql":
|
|
931
|
-
sqlrunner = new SQLRunner(conn);
|
|
932
|
-
break;
|
|
933
|
-
case "sqlite":
|
|
934
|
-
sqlrunner = new SQLiteRunner(conn);
|
|
935
|
-
break;
|
|
936
|
-
default:
|
|
937
|
-
throw ConfigurationError.unknownDatabaseType(config.database);
|
|
938
|
-
}
|
|
1058
|
+
const sqlrunner = makeRunner(config.database, conn);
|
|
939
1059
|
const setup = new MigrationSetup(sqlrunner, config);
|
|
940
1060
|
const read_strategy = this.getReadStategy(config);
|
|
941
1061
|
const migration_files = new MigrationDirectoryReader(config.migration_folder, read_strategy, sqlrunner, config.database);
|
|
@@ -948,6 +1068,8 @@ var init_MigrationRunner = __esm({
|
|
|
948
1068
|
return MySqlDialectParser;
|
|
949
1069
|
case "sqlite":
|
|
950
1070
|
return SqliteDialectParser;
|
|
1071
|
+
case "pg":
|
|
1072
|
+
return PgDialectParser;
|
|
951
1073
|
default:
|
|
952
1074
|
throw ConfigurationError.unknownDatabaseType(config.database);
|
|
953
1075
|
}
|
|
@@ -1134,6 +1256,8 @@ var init_MigrationRunner = __esm({
|
|
|
1134
1256
|
config.database = "sql";
|
|
1135
1257
|
} else if (config.sqlite) {
|
|
1136
1258
|
config.database = "sqlite";
|
|
1259
|
+
} else if (config.pg) {
|
|
1260
|
+
config.database = "pg";
|
|
1137
1261
|
} else {
|
|
1138
1262
|
throw ConfigurationError.missingRequiredProperty("database");
|
|
1139
1263
|
}
|
|
@@ -1189,8 +1313,10 @@ var init_MigrationRunner = __esm({
|
|
|
1189
1313
|
// framework/SeedRunner.ts
|
|
1190
1314
|
import fs4 from "fs";
|
|
1191
1315
|
import path2 from "path";
|
|
1316
|
+
import { pathToFileURL } from "url";
|
|
1192
1317
|
import Ajv from "ajv";
|
|
1193
1318
|
import addFormats from "ajv-formats";
|
|
1319
|
+
import { tsImport } from "tsx/esm/api";
|
|
1194
1320
|
function resolveAlias(name, aliasMap) {
|
|
1195
1321
|
var _a;
|
|
1196
1322
|
if (!aliasMap) return name;
|
|
@@ -1327,6 +1453,10 @@ function runSqlSeed(runner, resolved, direction) {
|
|
|
1327
1453
|
function loadSeedModule(modulePath) {
|
|
1328
1454
|
return __async(this, null, function* () {
|
|
1329
1455
|
const resolved = path2.resolve(modulePath);
|
|
1456
|
+
if (resolved.endsWith(".ts")) {
|
|
1457
|
+
const fileUrl = pathToFileURL(resolved).href;
|
|
1458
|
+
return tsImport(fileUrl, fileUrl);
|
|
1459
|
+
}
|
|
1330
1460
|
return import(resolved);
|
|
1331
1461
|
});
|
|
1332
1462
|
}
|
|
@@ -1426,6 +1556,10 @@ var require_cli = __commonJS({
|
|
|
1426
1556
|
init_errors();
|
|
1427
1557
|
init_SeedRunner();
|
|
1428
1558
|
var args = MigrationCLIFactory.setup(process.argv);
|
|
1559
|
+
if (args.flags.help) {
|
|
1560
|
+
printUsage();
|
|
1561
|
+
process.exit(0);
|
|
1562
|
+
}
|
|
1429
1563
|
if (!args.commands || args.commands.length === 0) {
|
|
1430
1564
|
console.error("Error: No command specified");
|
|
1431
1565
|
printUsage();
|