@bdkinc/knex-ibmi 0.5.9 → 0.5.11
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/README.md +476 -453
- package/dist/cli.cjs +58 -19
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +65 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +65 -22
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -473,7 +473,8 @@ var IBMiQueryCompiler = class extends QueryCompiler {
|
|
|
473
473
|
updateSql: baseUpdateSql,
|
|
474
474
|
selectColumns,
|
|
475
475
|
whereClause: where,
|
|
476
|
-
tableName: this.tableName
|
|
476
|
+
tableName: this.tableName,
|
|
477
|
+
setBindingCount: updates.map((fragment) => (fragment.match(/\?/g) || []).length).reduce((sum, count) => sum + count, 0)
|
|
477
478
|
}
|
|
478
479
|
};
|
|
479
480
|
}
|
|
@@ -538,6 +539,9 @@ import { Readable } from "stream";
|
|
|
538
539
|
import fs from "fs";
|
|
539
540
|
import path from "path";
|
|
540
541
|
import { pathToFileURL } from "url";
|
|
542
|
+
function buildTsRuntimeHelpMessage(fileName) {
|
|
543
|
+
return `TypeScript migration '${fileName}' requires a TypeScript runtime loader. Run with a TS-capable runtime (for example: \`node --import tsx\`) or precompile migrations to JavaScript.`;
|
|
544
|
+
}
|
|
541
545
|
var IBMiMigrationRunner = class {
|
|
542
546
|
constructor(knex2, config) {
|
|
543
547
|
__publicField(this, "knex");
|
|
@@ -547,9 +551,13 @@ var IBMiMigrationRunner = class {
|
|
|
547
551
|
directory: "./migrations",
|
|
548
552
|
tableName: "KNEX_MIGRATIONS",
|
|
549
553
|
schemaName: void 0,
|
|
550
|
-
extension: "js",
|
|
551
554
|
...config
|
|
552
555
|
};
|
|
556
|
+
if (typeof config?.extension === "string") {
|
|
557
|
+
console.warn(
|
|
558
|
+
"\u26A0\uFE0F IBMiMigrationRunner config 'extension' is ignored for discovery. The runner always discovers .js/.ts/.mjs/.cjs migration files."
|
|
559
|
+
);
|
|
560
|
+
}
|
|
553
561
|
}
|
|
554
562
|
getFullTableName() {
|
|
555
563
|
return this.config.schemaName ? `${this.config.schemaName}.${this.config.tableName}` : this.config.tableName;
|
|
@@ -596,7 +604,18 @@ var IBMiMigrationRunner = class {
|
|
|
596
604
|
try {
|
|
597
605
|
const migrationPath = this.getMigrationPath(migrationFile);
|
|
598
606
|
const fileUrl = pathToFileURL(migrationPath).href;
|
|
599
|
-
|
|
607
|
+
let migration;
|
|
608
|
+
try {
|
|
609
|
+
const moduleNs = await import(`${fileUrl}?t=${Date.now()}`);
|
|
610
|
+
migration = moduleNs.default ?? moduleNs;
|
|
611
|
+
} catch (importError) {
|
|
612
|
+
const isTsMigration = migrationFile.toLowerCase().endsWith(".ts");
|
|
613
|
+
const message = String(importError?.message || importError || "");
|
|
614
|
+
if (isTsMigration && (message.includes("Unknown file extension") || message.includes("Cannot use import statement") || message.includes("Unexpected token"))) {
|
|
615
|
+
throw new Error(buildTsRuntimeHelpMessage(migrationFile));
|
|
616
|
+
}
|
|
617
|
+
throw importError;
|
|
618
|
+
}
|
|
600
619
|
if (!migration.up || typeof migration.up !== "function") {
|
|
601
620
|
throw new Error(`Migration ${migrationFile} has no 'up' function`);
|
|
602
621
|
}
|
|
@@ -644,7 +663,18 @@ var IBMiMigrationRunner = class {
|
|
|
644
663
|
try {
|
|
645
664
|
const migrationPath = this.getMigrationPath(migrationFile);
|
|
646
665
|
const fileUrl = pathToFileURL(migrationPath).href;
|
|
647
|
-
|
|
666
|
+
let migration;
|
|
667
|
+
try {
|
|
668
|
+
const moduleNs = await import(`${fileUrl}?t=${Date.now()}`);
|
|
669
|
+
migration = moduleNs.default ?? moduleNs;
|
|
670
|
+
} catch (importError) {
|
|
671
|
+
const isTsMigration = migrationFile.toLowerCase().endsWith(".ts");
|
|
672
|
+
const message = String(importError?.message || importError || "");
|
|
673
|
+
if (isTsMigration && (message.includes("Unknown file extension") || message.includes("Cannot use import statement") || message.includes("Unexpected token"))) {
|
|
674
|
+
throw new Error(buildTsRuntimeHelpMessage(migrationFile));
|
|
675
|
+
}
|
|
676
|
+
throw importError;
|
|
677
|
+
}
|
|
648
678
|
if (migration.down && typeof migration.down === "function") {
|
|
649
679
|
console.log(` \u26A1 Executing rollback...`);
|
|
650
680
|
await migration.down(this.knex);
|
|
@@ -715,17 +745,12 @@ var IBMiMigrationRunner = class {
|
|
|
715
745
|
}
|
|
716
746
|
}
|
|
717
747
|
getMigrationFiles() {
|
|
718
|
-
const { directory
|
|
748
|
+
const { directory } = this.config;
|
|
719
749
|
if (!fs.existsSync(directory)) {
|
|
720
750
|
throw new Error(`Migration directory does not exist: ${directory}`);
|
|
721
751
|
}
|
|
722
752
|
const validExtensions = ["js", "ts", "mjs", "cjs"];
|
|
723
|
-
return fs.readdirSync(directory).filter((file) => {
|
|
724
|
-
if (extension && extension !== "js") {
|
|
725
|
-
return file.endsWith(`.${extension}`);
|
|
726
|
-
}
|
|
727
|
-
return validExtensions.some((ext) => file.endsWith(`.${ext}`));
|
|
728
|
-
}).sort();
|
|
753
|
+
return fs.readdirSync(directory).filter((file) => validExtensions.some((ext) => file.endsWith(`.${ext}`))).sort();
|
|
729
754
|
}
|
|
730
755
|
getMigrationPath(filename) {
|
|
731
756
|
return path.resolve(this.config.directory, filename);
|
|
@@ -969,7 +994,13 @@ var DB2Client = class extends knex.Client {
|
|
|
969
994
|
*/
|
|
970
995
|
async executeUpdateReturning(connection, obj) {
|
|
971
996
|
const { _ibmiUpdateReturning } = obj;
|
|
972
|
-
const {
|
|
997
|
+
const {
|
|
998
|
+
updateSql,
|
|
999
|
+
selectColumns,
|
|
1000
|
+
whereClause,
|
|
1001
|
+
tableName,
|
|
1002
|
+
setBindingCount
|
|
1003
|
+
} = _ibmiUpdateReturning;
|
|
973
1004
|
this.printDebug(
|
|
974
1005
|
"Executing UPDATE with returning using transaction approach"
|
|
975
1006
|
);
|
|
@@ -981,10 +1012,8 @@ var DB2Client = class extends knex.Client {
|
|
|
981
1012
|
};
|
|
982
1013
|
await this.executeStatementQuery(connection, updateObj);
|
|
983
1014
|
const selectSql = whereClause ? `select ${selectColumns} from ${tableName} ${whereClause}` : `select ${selectColumns} from ${tableName}`;
|
|
984
|
-
const
|
|
985
|
-
const
|
|
986
|
-
const setBindingCount = (setClausePart.match(/\?/g) || []).length;
|
|
987
|
-
const whereBindings = obj.bindings ? obj.bindings.slice(setBindingCount) : [];
|
|
1015
|
+
const inferredSetBindingCount = typeof setBindingCount === "number" ? setBindingCount : (updateSql.split(" where ")[0].match(/\?/g) || []).length;
|
|
1016
|
+
const whereBindings = obj.bindings ? obj.bindings.slice(inferredSetBindingCount) : [];
|
|
988
1017
|
const selectObj = {
|
|
989
1018
|
sql: selectSql,
|
|
990
1019
|
bindings: whereBindings,
|
|
@@ -1390,11 +1419,25 @@ var DB2Client = class extends knex.Client {
|
|
|
1390
1419
|
validateResponse(obj) {
|
|
1391
1420
|
if (!obj.response) {
|
|
1392
1421
|
this.printDebug("response undefined " + this.safeStringify(obj));
|
|
1393
|
-
return
|
|
1422
|
+
return this.processSqlMethod({
|
|
1423
|
+
...obj,
|
|
1424
|
+
response: { rows: [], rowCount: 0 }
|
|
1425
|
+
});
|
|
1394
1426
|
}
|
|
1395
1427
|
if (!obj.response.rows) {
|
|
1396
|
-
|
|
1397
|
-
|
|
1428
|
+
const usesRowCountOnly = !obj.select && (obj.sqlMethod === "del" /* DELETE */ || obj.sqlMethod === "delete" /* DELETE_ALT */ || obj.sqlMethod === "update" /* UPDATE */ || obj.sqlMethod === "counter" /* COUNTER */);
|
|
1429
|
+
if (usesRowCountOnly) {
|
|
1430
|
+
return null;
|
|
1431
|
+
}
|
|
1432
|
+
this.printWarn("rows undefined " + this.safeStringify(obj));
|
|
1433
|
+
return this.processSqlMethod({
|
|
1434
|
+
...obj,
|
|
1435
|
+
response: {
|
|
1436
|
+
...obj.response,
|
|
1437
|
+
rows: [],
|
|
1438
|
+
rowCount: obj.response.rowCount ?? 0
|
|
1439
|
+
}
|
|
1440
|
+
});
|
|
1398
1441
|
}
|
|
1399
1442
|
return null;
|
|
1400
1443
|
}
|
|
@@ -1439,8 +1482,7 @@ var DB2Client = class extends knex.Client {
|
|
|
1439
1482
|
return queryObject;
|
|
1440
1483
|
} catch (retryError) {
|
|
1441
1484
|
this.printError(`Retry failed: ${retryError.message}`);
|
|
1442
|
-
|
|
1443
|
-
return queryObject;
|
|
1485
|
+
throw this.wrapError(retryError, `${method}_retry`, queryObject);
|
|
1444
1486
|
}
|
|
1445
1487
|
}
|
|
1446
1488
|
/**
|
|
@@ -1485,7 +1527,8 @@ var DB2Client = class extends knex.Client {
|
|
|
1485
1527
|
return errorMessage.includes("sql") || errorMessage.includes("syntax") || errorMessage.includes("table") || errorMessage.includes("column");
|
|
1486
1528
|
}
|
|
1487
1529
|
processSqlMethod(obj) {
|
|
1488
|
-
const
|
|
1530
|
+
const rows = obj.response?.rows ?? [];
|
|
1531
|
+
const rowCount = obj.response?.rowCount;
|
|
1489
1532
|
switch (obj.sqlMethod) {
|
|
1490
1533
|
case "select" /* SELECT */:
|
|
1491
1534
|
return rows;
|