@noormdev/sdk 1.0.0-alpha.34 → 1.0.0-alpha.35
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/dist/{chunk-DE3NJ22A.js → chunk-WFVWNXTV.js} +3 -3
- package/dist/chunk-WFVWNXTV.js.map +1 -0
- package/dist/index.d.ts +43 -3
- package/dist/index.js +270 -109
- package/dist/index.js.map +1 -1
- package/dist/{storage-WQURRPCA.js → storage-HVPYW65B.js} +3 -3
- package/dist/{storage-WQURRPCA.js.map → storage-HVPYW65B.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-DE3NJ22A.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createRequire } from 'module';
|
|
2
2
|
import { processFile, DtReader, isTemplate, FORMAT_VERSION, DT_EXTENSIONS, encryptWithPassphrase, ENCODED_TYPES } from './chunk-5AYPF5D5.js';
|
|
3
3
|
import './chunk-UOFJT5PY.js';
|
|
4
|
-
import { initializeVault, getVaultStatus, setVaultSecret, getVaultSecret, getAllVaultSecrets, listVaultSecretKeys, deleteVaultSecret, vaultSecretExists, getVaultKey, noormDb, getNoormTables, encryptVaultKey } from './chunk-
|
|
5
|
-
import { makeNestedConfig, gigabytes, observer, attempt,
|
|
4
|
+
import { initializeVault, getVaultStatus, setVaultSecret, getVaultSecret, getAllVaultSecrets, listVaultSecretKeys, deleteVaultSecret, vaultSecretExists, getVaultKey, noormDb, getNoormTables, encryptVaultKey } from './chunk-WFVWNXTV.js';
|
|
5
|
+
import { makeNestedConfig, gigabytes, observer, attempt, attemptSync, retry, clone, merge, ObserverRelay } from './chunk-DLQES4PM.js';
|
|
6
6
|
import { dist_default } from './chunk-TBRUDUBQ.js';
|
|
7
7
|
import { require_dist } from './chunk-YJBKNUTP.js';
|
|
8
8
|
import { __commonJS, __export, __toESM } from './chunk-D2XW2UOP.js';
|
|
@@ -16938,6 +16938,16 @@ function isTvp(value) {
|
|
|
16938
16938
|
}
|
|
16939
16939
|
|
|
16940
16940
|
// src/sdk/sql.ts
|
|
16941
|
+
function quoteIdent(dialect, name) {
|
|
16942
|
+
const parts = name.includes(".") ? name.split(".", 2) : [name];
|
|
16943
|
+
if (dialect === "postgres") {
|
|
16944
|
+
return parts.map((p) => '"' + p.replace(/"/g, '""') + '"').join(".");
|
|
16945
|
+
}
|
|
16946
|
+
if (dialect === "mssql") {
|
|
16947
|
+
return parts.map((p) => "[" + p.replace(/]/g, "]]") + "]").join(".");
|
|
16948
|
+
}
|
|
16949
|
+
return parts.map((p) => "`" + p.replace(/`/g, "``") + "`").join(".");
|
|
16950
|
+
}
|
|
16941
16951
|
function buildProcCall(dialect, name, params) {
|
|
16942
16952
|
if (dialect === "sqlite") {
|
|
16943
16953
|
throw new Error("SQLite does not support stored procedures.");
|
|
@@ -16945,7 +16955,7 @@ function buildProcCall(dialect, name, params) {
|
|
|
16945
16955
|
if (params && hasTvpParam(params) && dialect !== "mssql") {
|
|
16946
16956
|
throw new Error("Table-valued parameters (TVP) are only supported on MSSQL.");
|
|
16947
16957
|
}
|
|
16948
|
-
const rawName = sql.raw(name);
|
|
16958
|
+
const rawName = sql.raw(quoteIdent(dialect, name));
|
|
16949
16959
|
if (!params || Array.isArray(params) && params.length === 0 || !Array.isArray(params) && Object.keys(params).length === 0) {
|
|
16950
16960
|
if (dialect === "mssql") {
|
|
16951
16961
|
return sql`EXEC ${rawName}`;
|
|
@@ -16967,8 +16977,8 @@ function buildFuncCall(dialect, name, column, params) {
|
|
|
16967
16977
|
if (params && hasTvpParam(params) && dialect !== "mssql") {
|
|
16968
16978
|
throw new Error("Table-valued parameters (TVP) are only supported on MSSQL.");
|
|
16969
16979
|
}
|
|
16970
|
-
const rawName = sql.raw(name);
|
|
16971
|
-
const rawCol = sql.raw(column);
|
|
16980
|
+
const rawName = sql.raw(quoteIdent(dialect, name));
|
|
16981
|
+
const rawCol = sql.raw(quoteIdent(dialect, column));
|
|
16972
16982
|
if (!params || Array.isArray(params) && params.length === 0 || !Array.isArray(params) && Object.keys(params).length === 0) {
|
|
16973
16983
|
return sql`SELECT ${rawName}() AS ${rawCol}`;
|
|
16974
16984
|
}
|
|
@@ -16977,7 +16987,7 @@ function buildFuncCall(dialect, name, column, params) {
|
|
|
16977
16987
|
}
|
|
16978
16988
|
if (dialect === "postgres" && !Array.isArray(params)) {
|
|
16979
16989
|
const parts = Object.entries(params).map(
|
|
16980
|
-
([key, val]) => sql`${sql.raw(key)} => ${val}`
|
|
16990
|
+
([key, val]) => sql`${sql.raw(quoteIdent("postgres", key))} => ${val}`
|
|
16981
16991
|
);
|
|
16982
16992
|
return sql`SELECT ${rawName}(${sql.join(parts)}) AS ${rawCol}`;
|
|
16983
16993
|
}
|
|
@@ -17004,7 +17014,7 @@ function buildTvfCall(dialect, name, params) {
|
|
|
17004
17014
|
if (params && hasTvpParam(params) && dialect !== "mssql") {
|
|
17005
17015
|
throw new Error("Table-valued parameters (TVP) are only supported on MSSQL.");
|
|
17006
17016
|
}
|
|
17007
|
-
const rawName = sql.raw(name);
|
|
17017
|
+
const rawName = sql.raw(quoteIdent(dialect, name));
|
|
17008
17018
|
if (!params || Array.isArray(params) && params.length === 0 || !Array.isArray(params) && Object.keys(params).length === 0) {
|
|
17009
17019
|
return sql`SELECT * FROM ${rawName}()`;
|
|
17010
17020
|
}
|
|
@@ -17013,7 +17023,7 @@ function buildTvfCall(dialect, name, params) {
|
|
|
17013
17023
|
}
|
|
17014
17024
|
if (dialect === "postgres" && !Array.isArray(params)) {
|
|
17015
17025
|
const parts = Object.entries(params).map(
|
|
17016
|
-
([key, val]) => sql`${sql.raw(key)} => ${val}`
|
|
17026
|
+
([key, val]) => sql`${sql.raw(quoteIdent("postgres", key))} => ${val}`
|
|
17017
17027
|
);
|
|
17018
17028
|
return sql`SELECT * FROM ${rawName}(${sql.join(parts)})`;
|
|
17019
17029
|
}
|
|
@@ -17040,7 +17050,7 @@ function buildPostgresProc(rawName, params) {
|
|
|
17040
17050
|
return sql`CALL ${rawName}(${joined})`;
|
|
17041
17051
|
}
|
|
17042
17052
|
const parts = Object.entries(params).map(
|
|
17043
|
-
([key, val]) => sql`${sql.raw(key)} => ${val}`
|
|
17053
|
+
([key, val]) => sql`${sql.raw(quoteIdent("postgres", key))} => ${val}`
|
|
17044
17054
|
);
|
|
17045
17055
|
return sql`CALL ${rawName}(${sql.join(parts)})`;
|
|
17046
17056
|
}
|
|
@@ -20233,9 +20243,16 @@ var ChangesNamespace = class {
|
|
|
20233
20243
|
/**
|
|
20234
20244
|
* Apply a specific change.
|
|
20235
20245
|
*
|
|
20246
|
+
* Pass `dryRun: true` to render the change to `tmp/` without
|
|
20247
|
+
* touching the database, or `preview: true` to emit rendered SQL.
|
|
20248
|
+
*
|
|
20236
20249
|
* @example
|
|
20237
20250
|
* ```typescript
|
|
20238
20251
|
* const result = await ctx.noorm.changes.apply('2024-01-15-add-users')
|
|
20252
|
+
* const dry = await ctx.noorm.changes.apply(
|
|
20253
|
+
* '2024-01-15-add-users',
|
|
20254
|
+
* { dryRun: true },
|
|
20255
|
+
* )
|
|
20239
20256
|
* ```
|
|
20240
20257
|
*/
|
|
20241
20258
|
async apply(name, options) {
|
|
@@ -20244,9 +20261,16 @@ var ChangesNamespace = class {
|
|
|
20244
20261
|
/**
|
|
20245
20262
|
* Revert a specific change.
|
|
20246
20263
|
*
|
|
20264
|
+
* Pass `dryRun: true` to render the revert files to `tmp/` without
|
|
20265
|
+
* touching the database, or `preview: true` to emit rendered SQL.
|
|
20266
|
+
*
|
|
20247
20267
|
* @example
|
|
20248
20268
|
* ```typescript
|
|
20249
20269
|
* const result = await ctx.noorm.changes.revert('2024-01-15-add-users')
|
|
20270
|
+
* const dry = await ctx.noorm.changes.revert(
|
|
20271
|
+
* '2024-01-15-add-users',
|
|
20272
|
+
* { dryRun: true },
|
|
20273
|
+
* )
|
|
20250
20274
|
* ```
|
|
20251
20275
|
*/
|
|
20252
20276
|
async revert(name, options) {
|
|
@@ -20256,25 +20280,37 @@ var ChangesNamespace = class {
|
|
|
20256
20280
|
/**
|
|
20257
20281
|
* Apply all pending changes.
|
|
20258
20282
|
*
|
|
20283
|
+
* Pass `dryRun: true` to render each change to `tmp/` without
|
|
20284
|
+
* touching the database. Pass `preview: true` to emit rendered
|
|
20285
|
+
* SQL (also without DB writes). When omitted, both default to
|
|
20286
|
+
* `false` and changes are applied normally.
|
|
20287
|
+
*
|
|
20259
20288
|
* @example
|
|
20260
20289
|
* ```typescript
|
|
20261
20290
|
* const result = await ctx.noorm.changes.ff()
|
|
20291
|
+
* const dry = await ctx.noorm.changes.ff({ dryRun: true })
|
|
20292
|
+
* const forced = await ctx.noorm.changes.ff({ force: true })
|
|
20262
20293
|
* ```
|
|
20263
20294
|
*/
|
|
20264
|
-
async ff() {
|
|
20265
|
-
return this.#getManager().ff();
|
|
20295
|
+
async ff(options) {
|
|
20296
|
+
return this.#getManager().ff(options);
|
|
20266
20297
|
}
|
|
20267
20298
|
/**
|
|
20268
20299
|
* Apply the next N pending changes (default 1).
|
|
20269
20300
|
*
|
|
20301
|
+
* Pass `dryRun: true` to render the changes to `tmp/` without
|
|
20302
|
+
* touching the database. Pass `preview: true` to emit rendered
|
|
20303
|
+
* SQL (also without DB writes).
|
|
20304
|
+
*
|
|
20270
20305
|
* @example
|
|
20271
20306
|
* ```typescript
|
|
20272
20307
|
* const result = await ctx.noorm.changes.next()
|
|
20273
20308
|
* const result = await ctx.noorm.changes.next(3)
|
|
20309
|
+
* const dry = await ctx.noorm.changes.next(2, { dryRun: true })
|
|
20274
20310
|
* ```
|
|
20275
20311
|
*/
|
|
20276
|
-
async next(count = 1) {
|
|
20277
|
-
return this.#getManager().next(count);
|
|
20312
|
+
async next(count = 1, options) {
|
|
20313
|
+
return this.#getManager().next(count, options);
|
|
20278
20314
|
}
|
|
20279
20315
|
// ─────────────────────────────────────────────────────
|
|
20280
20316
|
// Status & history (connected)
|
|
@@ -20405,6 +20441,48 @@ var ChangesNamespace = class {
|
|
|
20405
20441
|
return this.#manager;
|
|
20406
20442
|
}
|
|
20407
20443
|
};
|
|
20444
|
+
function splitMssqlBatches(content) {
|
|
20445
|
+
const batches = content.split(/^\s*GO\s*$/mi);
|
|
20446
|
+
return batches.map((b) => b.trim()).filter((b) => b.length > 0 && !isCommentOnly(b));
|
|
20447
|
+
}
|
|
20448
|
+
function isCommentOnly(batch) {
|
|
20449
|
+
for (const line of batch.split("\n")) {
|
|
20450
|
+
const trimmed = line.trim();
|
|
20451
|
+
if (trimmed.length > 0 && !trimmed.startsWith("--")) {
|
|
20452
|
+
return false;
|
|
20453
|
+
}
|
|
20454
|
+
}
|
|
20455
|
+
return true;
|
|
20456
|
+
}
|
|
20457
|
+
async function executeSqlBody(context, sqlContent) {
|
|
20458
|
+
if (context.dialect !== "mssql") {
|
|
20459
|
+
const [, execErr] = await attempt(() => sql.raw(sqlContent).execute(context.db));
|
|
20460
|
+
if (execErr) {
|
|
20461
|
+
return getSqlErrorMessage(execErr);
|
|
20462
|
+
}
|
|
20463
|
+
return null;
|
|
20464
|
+
}
|
|
20465
|
+
const batches = splitMssqlBatches(sqlContent);
|
|
20466
|
+
if (batches.length === 0) {
|
|
20467
|
+
return null;
|
|
20468
|
+
}
|
|
20469
|
+
if (batches.length === 1) {
|
|
20470
|
+
const [, execErr] = await attempt(() => sql.raw(batches[0]).execute(context.db));
|
|
20471
|
+
if (execErr) {
|
|
20472
|
+
return getSqlErrorMessage(execErr);
|
|
20473
|
+
}
|
|
20474
|
+
return null;
|
|
20475
|
+
}
|
|
20476
|
+
for (let i = 0; i < batches.length; i++) {
|
|
20477
|
+
const [, execErr] = await attempt(() => sql.raw(batches[i]).execute(context.db));
|
|
20478
|
+
if (execErr) {
|
|
20479
|
+
return `[batch ${i + 1} of ${batches.length}] ${getSqlErrorMessage(execErr)}`;
|
|
20480
|
+
}
|
|
20481
|
+
}
|
|
20482
|
+
return null;
|
|
20483
|
+
}
|
|
20484
|
+
|
|
20485
|
+
// src/core/runner/runner.ts
|
|
20408
20486
|
var SQL_EXTENSIONS2 = [".sql", ".sql.tmpl"];
|
|
20409
20487
|
var FILE_HEADER_TEMPLATE = `-- ============================================================
|
|
20410
20488
|
-- File: %FILE%
|
|
@@ -20770,14 +20848,14 @@ async function executeSingleFileWithUpdate(context, filepath, checksum, options,
|
|
|
20770
20848
|
return result2;
|
|
20771
20849
|
}
|
|
20772
20850
|
}
|
|
20773
|
-
const
|
|
20851
|
+
const execErrMsg = await executeSqlBody(context, sqlContent);
|
|
20774
20852
|
const durationMs = performance.now() - start;
|
|
20775
|
-
if (
|
|
20853
|
+
if (execErrMsg) {
|
|
20776
20854
|
const result2 = {
|
|
20777
20855
|
filepath,
|
|
20778
20856
|
checksum: finalChecksum,
|
|
20779
20857
|
status: "failed",
|
|
20780
|
-
error:
|
|
20858
|
+
error: execErrMsg,
|
|
20781
20859
|
durationMs
|
|
20782
20860
|
};
|
|
20783
20861
|
await tracker.updateFileExecution(
|
|
@@ -20785,13 +20863,13 @@ async function executeSingleFileWithUpdate(context, filepath, checksum, options,
|
|
|
20785
20863
|
relFilepath,
|
|
20786
20864
|
"failed",
|
|
20787
20865
|
Math.round(durationMs),
|
|
20788
|
-
|
|
20866
|
+
execErrMsg
|
|
20789
20867
|
);
|
|
20790
20868
|
observer.emit("file:after", {
|
|
20791
20869
|
filepath,
|
|
20792
20870
|
status: "failed",
|
|
20793
20871
|
durationMs,
|
|
20794
|
-
error:
|
|
20872
|
+
error: execErrMsg
|
|
20795
20873
|
});
|
|
20796
20874
|
return result2;
|
|
20797
20875
|
}
|
|
@@ -20894,14 +20972,14 @@ async function executeSingleFile(context, filepath, options, tracker, operationI
|
|
|
20894
20972
|
});
|
|
20895
20973
|
return result2;
|
|
20896
20974
|
}
|
|
20897
|
-
const
|
|
20975
|
+
const execErrMsg = await executeSqlBody(context, sqlContent);
|
|
20898
20976
|
const durationMs = performance.now() - start;
|
|
20899
|
-
if (
|
|
20977
|
+
if (execErrMsg) {
|
|
20900
20978
|
const result2 = {
|
|
20901
20979
|
filepath,
|
|
20902
20980
|
checksum,
|
|
20903
20981
|
status: "failed",
|
|
20904
|
-
error:
|
|
20982
|
+
error: execErrMsg,
|
|
20905
20983
|
durationMs
|
|
20906
20984
|
};
|
|
20907
20985
|
await tracker.recordExecution({
|
|
@@ -20909,14 +20987,14 @@ async function executeSingleFile(context, filepath, options, tracker, operationI
|
|
|
20909
20987
|
filepath: relFilepath,
|
|
20910
20988
|
checksum,
|
|
20911
20989
|
status: "failed",
|
|
20912
|
-
errorMessage:
|
|
20990
|
+
errorMessage: execErrMsg,
|
|
20913
20991
|
durationMs: Math.round(durationMs)
|
|
20914
20992
|
});
|
|
20915
20993
|
observer.emit("file:after", {
|
|
20916
20994
|
filepath,
|
|
20917
20995
|
status: "failed",
|
|
20918
20996
|
durationMs,
|
|
20919
|
-
error:
|
|
20997
|
+
error: execErrMsg
|
|
20920
20998
|
});
|
|
20921
20999
|
return result2;
|
|
20922
21000
|
}
|
|
@@ -23442,10 +23520,10 @@ var { quote, qualifiedName } = createDialectQuoting({
|
|
|
23442
23520
|
escape: '""'
|
|
23443
23521
|
});
|
|
23444
23522
|
var postgresTeardownOperations = {
|
|
23445
|
-
disableForeignKeyChecks() {
|
|
23523
|
+
disableForeignKeyChecks(_tables) {
|
|
23446
23524
|
return "SET session_replication_role = 'replica'";
|
|
23447
23525
|
},
|
|
23448
|
-
enableForeignKeyChecks() {
|
|
23526
|
+
enableForeignKeyChecks(_tables) {
|
|
23449
23527
|
return "SET session_replication_role = 'origin'";
|
|
23450
23528
|
},
|
|
23451
23529
|
truncateTable(tableName, schema, restartIdentity = true) {
|
|
@@ -23480,10 +23558,10 @@ var { quote: quote2, qualifiedName: qualifiedName2 } = createDialectQuoting({
|
|
|
23480
23558
|
escape: "``"
|
|
23481
23559
|
});
|
|
23482
23560
|
var mysqlTeardownOperations = {
|
|
23483
|
-
disableForeignKeyChecks() {
|
|
23561
|
+
disableForeignKeyChecks(_tables) {
|
|
23484
23562
|
return "SET FOREIGN_KEY_CHECKS = 0";
|
|
23485
23563
|
},
|
|
23486
|
-
enableForeignKeyChecks() {
|
|
23564
|
+
enableForeignKeyChecks(_tables) {
|
|
23487
23565
|
return "SET FOREIGN_KEY_CHECKS = 1";
|
|
23488
23566
|
},
|
|
23489
23567
|
truncateTable(tableName, schema, _restartIdentity = true) {
|
|
@@ -23516,10 +23594,16 @@ var { quote: quote3, qualifiedName: qualifiedName3 } = createDialectQuoting({
|
|
|
23516
23594
|
escape: "]]"
|
|
23517
23595
|
});
|
|
23518
23596
|
var mssqlTeardownOperations = {
|
|
23519
|
-
disableForeignKeyChecks() {
|
|
23597
|
+
disableForeignKeyChecks(tables) {
|
|
23598
|
+
if (tables && tables.length > 0) {
|
|
23599
|
+
return tables.map((t) => `ALTER TABLE ${qualifiedName3(t)} NOCHECK CONSTRAINT ALL`);
|
|
23600
|
+
}
|
|
23520
23601
|
return "EXEC sp_MSforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'";
|
|
23521
23602
|
},
|
|
23522
|
-
enableForeignKeyChecks() {
|
|
23603
|
+
enableForeignKeyChecks(tables) {
|
|
23604
|
+
if (tables && tables.length > 0) {
|
|
23605
|
+
return tables.map((t) => `ALTER TABLE ${qualifiedName3(t)} CHECK CONSTRAINT ALL`);
|
|
23606
|
+
}
|
|
23523
23607
|
return "EXEC sp_MSforeachtable 'ALTER TABLE ? CHECK CONSTRAINT ALL'";
|
|
23524
23608
|
},
|
|
23525
23609
|
truncateTable(tableName, schema, restartIdentity = true) {
|
|
@@ -23558,10 +23642,10 @@ var { quote: quote4 } = createDialectQuoting({
|
|
|
23558
23642
|
escape: '""'
|
|
23559
23643
|
});
|
|
23560
23644
|
var sqliteTeardownOperations = {
|
|
23561
|
-
disableForeignKeyChecks() {
|
|
23645
|
+
disableForeignKeyChecks(_tables) {
|
|
23562
23646
|
return "PRAGMA foreign_keys = OFF";
|
|
23563
23647
|
},
|
|
23564
|
-
enableForeignKeyChecks() {
|
|
23648
|
+
enableForeignKeyChecks(_tables) {
|
|
23565
23649
|
return "PRAGMA foreign_keys = ON";
|
|
23566
23650
|
},
|
|
23567
23651
|
truncateTable(tableName, _schema, _restartIdentity = false) {
|
|
@@ -23611,6 +23695,13 @@ function isNoormTable2(name) {
|
|
|
23611
23695
|
if (name.startsWith("__noorm_")) return true;
|
|
23612
23696
|
return false;
|
|
23613
23697
|
}
|
|
23698
|
+
function pushFlat(out, value) {
|
|
23699
|
+
if (Array.isArray(value)) {
|
|
23700
|
+
out.push(...value);
|
|
23701
|
+
return;
|
|
23702
|
+
}
|
|
23703
|
+
out.push(value);
|
|
23704
|
+
}
|
|
23614
23705
|
async function truncateData(db, dialect, options = {}) {
|
|
23615
23706
|
const startTime = performance.now();
|
|
23616
23707
|
const ops = getTeardownOperations(dialect);
|
|
@@ -23640,11 +23731,13 @@ async function truncateData(db, dialect, options = {}) {
|
|
|
23640
23731
|
}
|
|
23641
23732
|
truncated.push(tableName);
|
|
23642
23733
|
}
|
|
23643
|
-
|
|
23644
|
-
|
|
23645
|
-
|
|
23734
|
+
if (truncated.length > 0) {
|
|
23735
|
+
pushFlat(statements, ops.disableForeignKeyChecks(truncated));
|
|
23736
|
+
for (const tableName of truncated) {
|
|
23737
|
+
statements.push(ops.truncateTable(tableName, void 0, options.restartIdentity ?? true));
|
|
23738
|
+
}
|
|
23739
|
+
pushFlat(statements, ops.enableForeignKeyChecks(truncated));
|
|
23646
23740
|
}
|
|
23647
|
-
statements.push(ops.enableForeignKeyChecks());
|
|
23648
23741
|
if (!options.dryRun) {
|
|
23649
23742
|
for (const stmt of statements) {
|
|
23650
23743
|
if (stmt.startsWith("--")) continue;
|
|
@@ -23716,6 +23809,18 @@ async function teardownSchema(db, dialect, options = {}) {
|
|
|
23716
23809
|
dropped.foreignKeys.push(fk.name);
|
|
23717
23810
|
statements.push(ops.dropForeignKey(fk.name, tableName, fk.schema));
|
|
23718
23811
|
}
|
|
23812
|
+
if (!options.keepProcedures) {
|
|
23813
|
+
for (const proc of procedures) {
|
|
23814
|
+
dropped.procedures.push(proc.name);
|
|
23815
|
+
statements.push(ops.dropProcedure(proc.name, proc.schema));
|
|
23816
|
+
}
|
|
23817
|
+
}
|
|
23818
|
+
if (!options.keepFunctions) {
|
|
23819
|
+
for (const fn of functions) {
|
|
23820
|
+
dropped.functions.push(fn.name);
|
|
23821
|
+
statements.push(ops.dropFunction(fn.name, fn.schema));
|
|
23822
|
+
}
|
|
23823
|
+
}
|
|
23719
23824
|
if (!options.keepViews) {
|
|
23720
23825
|
for (const view of views) {
|
|
23721
23826
|
dropped.views.push(view.name);
|
|
@@ -23735,18 +23840,6 @@ async function teardownSchema(db, dialect, options = {}) {
|
|
|
23735
23840
|
dropped.tables.push(tableName);
|
|
23736
23841
|
statements.push(ops.dropTable(tableName, table.schema));
|
|
23737
23842
|
}
|
|
23738
|
-
if (!options.keepFunctions) {
|
|
23739
|
-
for (const fn of functions) {
|
|
23740
|
-
dropped.functions.push(fn.name);
|
|
23741
|
-
statements.push(ops.dropFunction(fn.name, fn.schema));
|
|
23742
|
-
}
|
|
23743
|
-
}
|
|
23744
|
-
if (!options.keepProcedures) {
|
|
23745
|
-
for (const proc of procedures) {
|
|
23746
|
-
dropped.procedures.push(proc.name);
|
|
23747
|
-
statements.push(ops.dropProcedure(proc.name, proc.schema));
|
|
23748
|
-
}
|
|
23749
|
-
}
|
|
23750
23843
|
const skipTypesDueToKeptRoutines = dialect === "mssql" && (options.keepFunctions || options.keepProcedures);
|
|
23751
23844
|
if (!options.keepTypes && !skipTypesDueToKeptRoutines) {
|
|
23752
23845
|
const sortedTypes = [...types].sort((a, b) => {
|
|
@@ -24406,25 +24499,60 @@ async function copyVaultSecrets(sourceConfig, destConfig, keys, identityHash, pr
|
|
|
24406
24499
|
// src/sdk/namespaces/vault.ts
|
|
24407
24500
|
var VaultNamespace = class {
|
|
24408
24501
|
#state;
|
|
24502
|
+
#cryptoIdentity = null;
|
|
24409
24503
|
constructor(state) {
|
|
24410
24504
|
this.#state = state;
|
|
24411
24505
|
}
|
|
24506
|
+
/**
|
|
24507
|
+
* Load the cryptographic identity (with publicKey + identityHash) on
|
|
24508
|
+
* demand. The Context's state.identity is the audit identity (name +
|
|
24509
|
+
* email only); the crypto fields needed for vault encryption live in
|
|
24510
|
+
* `~/.noorm/identity.json` (or a NOORM_IDENTITY_* env override).
|
|
24511
|
+
*
|
|
24512
|
+
* Cached after the first call so repeated vault ops don't re-read disk.
|
|
24513
|
+
*/
|
|
24514
|
+
async #getCryptoIdentity() {
|
|
24515
|
+
if (this.#cryptoIdentity) return this.#cryptoIdentity;
|
|
24516
|
+
const loaded = await loadIdentityMetadata();
|
|
24517
|
+
if (!loaded) {
|
|
24518
|
+
throw new Error(
|
|
24519
|
+
"Vault operations require a cryptographic identity at ~/.noorm/identity.json. Run `noorm identity init` or set NOORM_IDENTITY_* env vars in CI."
|
|
24520
|
+
);
|
|
24521
|
+
}
|
|
24522
|
+
this.#cryptoIdentity = loaded;
|
|
24523
|
+
return loaded;
|
|
24524
|
+
}
|
|
24412
24525
|
// ─────────────────────────────────────────────────────
|
|
24413
24526
|
// Lifecycle
|
|
24414
24527
|
// ─────────────────────────────────────────────────────
|
|
24415
24528
|
/**
|
|
24416
24529
|
* Initialize the vault for this database.
|
|
24417
24530
|
*
|
|
24531
|
+
* Idempotent. Returns the vault key on first init; returns [null, null]
|
|
24532
|
+
* on subsequent calls when the vault already exists. Returns [null, Error]
|
|
24533
|
+
* only on real failures (DB errors, encryption errors).
|
|
24534
|
+
*
|
|
24535
|
+
* The `vault:initialized` observer event fires only on first init, never
|
|
24536
|
+
* on repeat calls.
|
|
24537
|
+
*
|
|
24418
24538
|
* @example
|
|
24419
24539
|
* ```typescript
|
|
24420
|
-
* const [vaultKey, err] = await ctx.noorm.vault.init()
|
|
24540
|
+
* const [vaultKey, err] = await ctx.noorm.vault.init();
|
|
24541
|
+
* if (err) throw err;
|
|
24542
|
+
* if (vaultKey) {
|
|
24543
|
+
* // first-time init — set initial secrets, etc.
|
|
24544
|
+
* }
|
|
24545
|
+
* else {
|
|
24546
|
+
* // already initialized — vault.get / vault.set with private key
|
|
24547
|
+
* }
|
|
24421
24548
|
* ```
|
|
24422
24549
|
*/
|
|
24423
24550
|
async init() {
|
|
24551
|
+
const crypto = await this.#getCryptoIdentity();
|
|
24424
24552
|
return initializeVault(
|
|
24425
24553
|
this.#kysely,
|
|
24426
|
-
|
|
24427
|
-
|
|
24554
|
+
crypto.identityHash,
|
|
24555
|
+
crypto.publicKey,
|
|
24428
24556
|
this.#dialect
|
|
24429
24557
|
);
|
|
24430
24558
|
}
|
|
@@ -24437,9 +24565,10 @@ var VaultNamespace = class {
|
|
|
24437
24565
|
* ```
|
|
24438
24566
|
*/
|
|
24439
24567
|
async status() {
|
|
24568
|
+
const crypto = await this.#getCryptoIdentity();
|
|
24440
24569
|
return getVaultStatus(
|
|
24441
24570
|
this.#kysely,
|
|
24442
|
-
|
|
24571
|
+
crypto.identityHash,
|
|
24443
24572
|
this.#dialect
|
|
24444
24573
|
);
|
|
24445
24574
|
}
|
|
@@ -24576,13 +24705,14 @@ var VaultNamespace = class {
|
|
|
24576
24705
|
* ```
|
|
24577
24706
|
*/
|
|
24578
24707
|
async copy(destConfig, keys, privateKey, options) {
|
|
24708
|
+
const crypto = await this.#getCryptoIdentity();
|
|
24579
24709
|
return copyVaultSecrets(
|
|
24580
24710
|
this.#state.config,
|
|
24581
24711
|
destConfig,
|
|
24582
24712
|
keys,
|
|
24583
|
-
|
|
24713
|
+
crypto.identityHash,
|
|
24584
24714
|
privateKey,
|
|
24585
|
-
|
|
24715
|
+
crypto.publicKey,
|
|
24586
24716
|
options
|
|
24587
24717
|
);
|
|
24588
24718
|
}
|
|
@@ -24595,21 +24725,14 @@ var VaultNamespace = class {
|
|
|
24595
24725
|
}
|
|
24596
24726
|
return this.#state.connection.db;
|
|
24597
24727
|
}
|
|
24598
|
-
get #identityHash() {
|
|
24599
|
-
const identity = this.#state.identity;
|
|
24600
|
-
return identity["identityHash"] ?? "";
|
|
24601
|
-
}
|
|
24602
|
-
get #publicKey() {
|
|
24603
|
-
const identity = this.#state.identity;
|
|
24604
|
-
return identity["publicKey"] ?? "";
|
|
24605
|
-
}
|
|
24606
24728
|
get #dialect() {
|
|
24607
24729
|
return this.#state.config.connection.dialect;
|
|
24608
24730
|
}
|
|
24609
24731
|
async #getVaultKey(privateKey) {
|
|
24732
|
+
const crypto = await this.#getCryptoIdentity();
|
|
24610
24733
|
return getVaultKey(
|
|
24611
24734
|
this.#kysely,
|
|
24612
|
-
|
|
24735
|
+
crypto.identityHash,
|
|
24613
24736
|
privateKey,
|
|
24614
24737
|
this.#dialect
|
|
24615
24738
|
);
|
|
@@ -24695,7 +24818,7 @@ function isSameServer(source, dest) {
|
|
|
24695
24818
|
}
|
|
24696
24819
|
return true;
|
|
24697
24820
|
}
|
|
24698
|
-
function
|
|
24821
|
+
function quoteIdent2(name) {
|
|
24699
24822
|
return `"${name.replace(/"/g, '""')}"`;
|
|
24700
24823
|
}
|
|
24701
24824
|
var postgresTransferOperations = {
|
|
@@ -24712,20 +24835,20 @@ var postgresTransferOperations = {
|
|
|
24712
24835
|
return null;
|
|
24713
24836
|
},
|
|
24714
24837
|
getResetSequenceSql(table, column, schema) {
|
|
24715
|
-
const fullTable = schema ? `${
|
|
24838
|
+
const fullTable = schema ? `${quoteIdent2(schema)}.${quoteIdent2(table)}` : quoteIdent2(table);
|
|
24716
24839
|
return `
|
|
24717
24840
|
SELECT setval(
|
|
24718
24841
|
pg_get_serial_sequence('${schema ? schema + "." : ""}${table}', '${column}'),
|
|
24719
|
-
COALESCE((SELECT MAX(${
|
|
24842
|
+
COALESCE((SELECT MAX(${quoteIdent2(column)}) FROM ${fullTable}), 0) + 1,
|
|
24720
24843
|
false
|
|
24721
24844
|
)
|
|
24722
24845
|
`.trim();
|
|
24723
24846
|
},
|
|
24724
24847
|
buildConflictInsert(table, columns, primaryKey, strategy) {
|
|
24725
|
-
const quotedCols = columns.map(
|
|
24848
|
+
const quotedCols = columns.map(quoteIdent2).join(", ");
|
|
24726
24849
|
const placeholders = columns.map((_, i) => `$${i + 1}`).join(", ");
|
|
24727
|
-
const pkCols = primaryKey.map(
|
|
24728
|
-
let insertSql = `INSERT INTO ${
|
|
24850
|
+
const pkCols = primaryKey.map(quoteIdent2).join(", ");
|
|
24851
|
+
let insertSql = `INSERT INTO ${quoteIdent2(table)} (${quotedCols}) OVERRIDING SYSTEM VALUE VALUES (${placeholders})`;
|
|
24729
24852
|
switch (strategy) {
|
|
24730
24853
|
case "fail":
|
|
24731
24854
|
break;
|
|
@@ -24735,7 +24858,7 @@ var postgresTransferOperations = {
|
|
|
24735
24858
|
case "update": {
|
|
24736
24859
|
const updateCols = columns.filter((c) => !primaryKey.includes(c));
|
|
24737
24860
|
if (updateCols.length > 0) {
|
|
24738
|
-
const setClauses = updateCols.map((c) => `${
|
|
24861
|
+
const setClauses = updateCols.map((c) => `${quoteIdent2(c)} = EXCLUDED.${quoteIdent2(c)}`).join(", ");
|
|
24739
24862
|
insertSql += ` ON CONFLICT (${pkCols}) DO UPDATE SET ${setClauses}`;
|
|
24740
24863
|
} else {
|
|
24741
24864
|
insertSql += ` ON CONFLICT (${pkCols}) DO NOTHING`;
|
|
@@ -24744,7 +24867,7 @@ var postgresTransferOperations = {
|
|
|
24744
24867
|
}
|
|
24745
24868
|
case "replace":
|
|
24746
24869
|
{
|
|
24747
|
-
const setClauses = columns.map((c) => `${
|
|
24870
|
+
const setClauses = columns.map((c) => `${quoteIdent2(c)} = EXCLUDED.${quoteIdent2(c)}`).join(", ");
|
|
24748
24871
|
insertSql += ` ON CONFLICT (${pkCols}) DO UPDATE SET ${setClauses}`;
|
|
24749
24872
|
}
|
|
24750
24873
|
break;
|
|
@@ -24752,9 +24875,9 @@ var postgresTransferOperations = {
|
|
|
24752
24875
|
return insertSql;
|
|
24753
24876
|
},
|
|
24754
24877
|
buildDirectTransfer(srcDb, srcTable, dstTable, columns, srcSchema = "public", dstSchema = "public") {
|
|
24755
|
-
const quotedCols = columns.map(
|
|
24756
|
-
const srcFull = `${
|
|
24757
|
-
const dstFull = `${
|
|
24878
|
+
const quotedCols = columns.map(quoteIdent2).join(", ");
|
|
24879
|
+
const srcFull = `${quoteIdent2(srcSchema)}.${quoteIdent2(srcTable)}`;
|
|
24880
|
+
const dstFull = `${quoteIdent2(dstSchema)}.${quoteIdent2(dstTable)}`;
|
|
24758
24881
|
return `INSERT INTO ${dstFull} (${quotedCols}) OVERRIDING SYSTEM VALUE SELECT ${quotedCols} FROM ${srcFull}`;
|
|
24759
24882
|
},
|
|
24760
24883
|
async executeDisableFK(db) {
|
|
@@ -24764,7 +24887,7 @@ var postgresTransferOperations = {
|
|
|
24764
24887
|
await sql.raw(this.getEnableFKSql()).execute(db);
|
|
24765
24888
|
}
|
|
24766
24889
|
};
|
|
24767
|
-
function
|
|
24890
|
+
function quoteIdent3(name) {
|
|
24768
24891
|
return `\`${name.replace(/`/g, "``")}\``;
|
|
24769
24892
|
}
|
|
24770
24893
|
var mysqlTransferOperations = {
|
|
@@ -24781,32 +24904,32 @@ var mysqlTransferOperations = {
|
|
|
24781
24904
|
return null;
|
|
24782
24905
|
},
|
|
24783
24906
|
getResetSequenceSql(table, _column, _schema) {
|
|
24784
|
-
return `ALTER TABLE ${
|
|
24907
|
+
return `ALTER TABLE ${quoteIdent3(table)} AUTO_INCREMENT = 1`;
|
|
24785
24908
|
},
|
|
24786
24909
|
buildConflictInsert(table, columns, primaryKey, strategy) {
|
|
24787
|
-
const quotedCols = columns.map(
|
|
24910
|
+
const quotedCols = columns.map(quoteIdent3).join(", ");
|
|
24788
24911
|
const placeholders = columns.map(() => "?").join(", ");
|
|
24789
24912
|
switch (strategy) {
|
|
24790
24913
|
case "fail":
|
|
24791
|
-
return `INSERT INTO ${
|
|
24914
|
+
return `INSERT INTO ${quoteIdent3(table)} (${quotedCols}) VALUES (${placeholders})`;
|
|
24792
24915
|
case "skip":
|
|
24793
|
-
return `INSERT IGNORE INTO ${
|
|
24916
|
+
return `INSERT IGNORE INTO ${quoteIdent3(table)} (${quotedCols}) VALUES (${placeholders})`;
|
|
24794
24917
|
case "update": {
|
|
24795
24918
|
const updateCols = columns.filter((c) => !primaryKey.includes(c));
|
|
24796
24919
|
if (updateCols.length > 0) {
|
|
24797
|
-
const setClauses = updateCols.map((c) => `${
|
|
24798
|
-
return `INSERT INTO ${
|
|
24920
|
+
const setClauses = updateCols.map((c) => `${quoteIdent3(c)} = VALUES(${quoteIdent3(c)})`).join(", ");
|
|
24921
|
+
return `INSERT INTO ${quoteIdent3(table)} (${quotedCols}) VALUES (${placeholders}) ON DUPLICATE KEY UPDATE ${setClauses}`;
|
|
24799
24922
|
}
|
|
24800
|
-
return `INSERT IGNORE INTO ${
|
|
24923
|
+
return `INSERT IGNORE INTO ${quoteIdent3(table)} (${quotedCols}) VALUES (${placeholders})`;
|
|
24801
24924
|
}
|
|
24802
24925
|
case "replace":
|
|
24803
|
-
return `REPLACE INTO ${
|
|
24926
|
+
return `REPLACE INTO ${quoteIdent3(table)} (${quotedCols}) VALUES (${placeholders})`;
|
|
24804
24927
|
}
|
|
24805
24928
|
},
|
|
24806
24929
|
buildDirectTransfer(srcDb, srcTable, dstTable, columns, _srcSchema, _dstSchema) {
|
|
24807
|
-
const quotedCols = columns.map(
|
|
24808
|
-
const srcFull = `${
|
|
24809
|
-
const dstFull =
|
|
24930
|
+
const quotedCols = columns.map(quoteIdent3).join(", ");
|
|
24931
|
+
const srcFull = `${quoteIdent3(srcDb)}.${quoteIdent3(srcTable)}`;
|
|
24932
|
+
const dstFull = quoteIdent3(dstTable);
|
|
24810
24933
|
return `INSERT INTO ${dstFull} (${quotedCols}) SELECT ${quotedCols} FROM ${srcFull}`;
|
|
24811
24934
|
},
|
|
24812
24935
|
async executeDisableFK(db) {
|
|
@@ -24816,7 +24939,7 @@ var mysqlTransferOperations = {
|
|
|
24816
24939
|
await sql.raw(this.getEnableFKSql()).execute(db);
|
|
24817
24940
|
}
|
|
24818
24941
|
};
|
|
24819
|
-
function
|
|
24942
|
+
function quoteIdent4(name) {
|
|
24820
24943
|
return `[${name.replace(/\]/g, "]]")}]`;
|
|
24821
24944
|
}
|
|
24822
24945
|
var mssqlTransferOperations = {
|
|
@@ -24827,27 +24950,27 @@ var mssqlTransferOperations = {
|
|
|
24827
24950
|
return "-- FK enable per-table";
|
|
24828
24951
|
},
|
|
24829
24952
|
getEnableIdentityInsertSql(table) {
|
|
24830
|
-
return `SET IDENTITY_INSERT ${
|
|
24953
|
+
return `SET IDENTITY_INSERT ${quoteIdent4(table)} ON`;
|
|
24831
24954
|
},
|
|
24832
24955
|
getDisableIdentityInsertSql(table) {
|
|
24833
|
-
return `SET IDENTITY_INSERT ${
|
|
24956
|
+
return `SET IDENTITY_INSERT ${quoteIdent4(table)} OFF`;
|
|
24834
24957
|
},
|
|
24835
24958
|
getResetSequenceSql(table, _column, _schema) {
|
|
24836
24959
|
return `DBCC CHECKIDENT ('${table}', RESEED)`;
|
|
24837
24960
|
},
|
|
24838
24961
|
buildConflictInsert(table, columns, primaryKey, strategy) {
|
|
24839
|
-
const quotedCols = columns.map(
|
|
24962
|
+
const quotedCols = columns.map(quoteIdent4).join(", ");
|
|
24840
24963
|
const placeholders = columns.map((_, i) => `@p${i}`).join(", ");
|
|
24841
24964
|
switch (strategy) {
|
|
24842
24965
|
case "fail":
|
|
24843
|
-
return `INSERT INTO ${
|
|
24966
|
+
return `INSERT INTO ${quoteIdent4(table)} (${quotedCols}) VALUES (${placeholders})`;
|
|
24844
24967
|
case "skip":
|
|
24845
24968
|
case "update":
|
|
24846
24969
|
case "replace": {
|
|
24847
|
-
const pkConditions = primaryKey.map((pk) => `target.${
|
|
24848
|
-
const sourceValues = columns.map((c, i) => `@p${i} AS ${
|
|
24970
|
+
const pkConditions = primaryKey.map((pk) => `target.${quoteIdent4(pk)} = source.${quoteIdent4(pk)}`).join(" AND ");
|
|
24971
|
+
const sourceValues = columns.map((c, i) => `@p${i} AS ${quoteIdent4(c)}`).join(", ");
|
|
24849
24972
|
let mergeSql = `
|
|
24850
|
-
MERGE INTO ${
|
|
24973
|
+
MERGE INTO ${quoteIdent4(table)} AS target
|
|
24851
24974
|
USING (SELECT ${sourceValues}) AS source
|
|
24852
24975
|
ON (${pkConditions})
|
|
24853
24976
|
`.trim();
|
|
@@ -24855,12 +24978,12 @@ var mssqlTransferOperations = {
|
|
|
24855
24978
|
mergeSql += `
|
|
24856
24979
|
WHEN NOT MATCHED THEN
|
|
24857
24980
|
INSERT (${quotedCols})
|
|
24858
|
-
VALUES (${columns.map((c) => `source.${
|
|
24981
|
+
VALUES (${columns.map((c) => `source.${quoteIdent4(c)}`).join(", ")})
|
|
24859
24982
|
`;
|
|
24860
24983
|
} else if (strategy === "update") {
|
|
24861
24984
|
const updateCols = columns.filter((c) => !primaryKey.includes(c));
|
|
24862
24985
|
if (updateCols.length > 0) {
|
|
24863
|
-
const setClauses = updateCols.map((c) => `target.${
|
|
24986
|
+
const setClauses = updateCols.map((c) => `target.${quoteIdent4(c)} = source.${quoteIdent4(c)}`).join(", ");
|
|
24864
24987
|
mergeSql += `
|
|
24865
24988
|
WHEN MATCHED THEN
|
|
24866
24989
|
UPDATE SET ${setClauses}
|
|
@@ -24869,16 +24992,16 @@ var mssqlTransferOperations = {
|
|
|
24869
24992
|
mergeSql += `
|
|
24870
24993
|
WHEN NOT MATCHED THEN
|
|
24871
24994
|
INSERT (${quotedCols})
|
|
24872
|
-
VALUES (${columns.map((c) => `source.${
|
|
24995
|
+
VALUES (${columns.map((c) => `source.${quoteIdent4(c)}`).join(", ")})
|
|
24873
24996
|
`;
|
|
24874
24997
|
} else {
|
|
24875
|
-
const setClauses = columns.map((c) => `target.${
|
|
24998
|
+
const setClauses = columns.map((c) => `target.${quoteIdent4(c)} = source.${quoteIdent4(c)}`).join(", ");
|
|
24876
24999
|
mergeSql += `
|
|
24877
25000
|
WHEN MATCHED THEN
|
|
24878
25001
|
UPDATE SET ${setClauses}
|
|
24879
25002
|
WHEN NOT MATCHED THEN
|
|
24880
25003
|
INSERT (${quotedCols})
|
|
24881
|
-
VALUES (${columns.map((c) => `source.${
|
|
25004
|
+
VALUES (${columns.map((c) => `source.${quoteIdent4(c)}`).join(", ")})
|
|
24882
25005
|
`;
|
|
24883
25006
|
}
|
|
24884
25007
|
mergeSql += ";";
|
|
@@ -24887,19 +25010,19 @@ var mssqlTransferOperations = {
|
|
|
24887
25010
|
}
|
|
24888
25011
|
},
|
|
24889
25012
|
buildDirectTransfer(srcDb, srcTable, dstTable, columns, srcSchema = "dbo", dstSchema = "dbo") {
|
|
24890
|
-
const quotedCols = columns.map(
|
|
24891
|
-
const srcFull = `${
|
|
24892
|
-
const dstFull = `${
|
|
25013
|
+
const quotedCols = columns.map(quoteIdent4).join(", ");
|
|
25014
|
+
const srcFull = `${quoteIdent4(srcDb)}.${quoteIdent4(srcSchema)}.${quoteIdent4(srcTable)}`;
|
|
25015
|
+
const dstFull = `${quoteIdent4(dstSchema)}.${quoteIdent4(dstTable)}`;
|
|
24893
25016
|
return `INSERT INTO ${dstFull} (${quotedCols}) SELECT ${quotedCols} FROM ${srcFull}`;
|
|
24894
25017
|
},
|
|
24895
25018
|
async executeDisableFK(db, tables) {
|
|
24896
25019
|
for (const table of tables) {
|
|
24897
|
-
await sql.raw(`ALTER TABLE ${
|
|
25020
|
+
await sql.raw(`ALTER TABLE ${quoteIdent4(table)} NOCHECK CONSTRAINT ALL`).execute(db);
|
|
24898
25021
|
}
|
|
24899
25022
|
},
|
|
24900
25023
|
async executeEnableFK(db, tables) {
|
|
24901
25024
|
for (const table of tables) {
|
|
24902
|
-
await sql.raw(`ALTER TABLE ${
|
|
25025
|
+
await sql.raw(`ALTER TABLE ${quoteIdent4(table)} WITH CHECK CHECK CONSTRAINT ALL`).execute(db);
|
|
24903
25026
|
}
|
|
24904
25027
|
}
|
|
24905
25028
|
};
|
|
@@ -26439,10 +26562,10 @@ async function transferTableCrossDialect(ctx, plan, transferPlan, options) {
|
|
|
26439
26562
|
}, null];
|
|
26440
26563
|
}
|
|
26441
26564
|
async function fetchBatch(db, dialect, table, columns, limit, offset, _schema) {
|
|
26442
|
-
const
|
|
26443
|
-
const columnList = columns.map(
|
|
26565
|
+
const quoteIdent5 = dialect === "mssql" ? (c) => `[${c}]` : dialect === "mysql" ? (c) => `\`${c}\`` : (c) => `"${c}"`;
|
|
26566
|
+
const columnList = columns.map(quoteIdent5).join(", ");
|
|
26444
26567
|
if (dialect === "mssql") {
|
|
26445
|
-
const orderCol =
|
|
26568
|
+
const orderCol = quoteIdent5(columns[0]);
|
|
26446
26569
|
const result2 = await sql`
|
|
26447
26570
|
SELECT ${sql.raw(columnList)}
|
|
26448
26571
|
FROM ${sql.table(table)}
|
|
@@ -27108,9 +27231,9 @@ async function exportTableWithWorkers(ctx) {
|
|
|
27108
27231
|
totalRows = Number(firstRow?.["cnt"] ?? 0);
|
|
27109
27232
|
}
|
|
27110
27233
|
const columns = dtSchema.columns.map((c) => c.name);
|
|
27111
|
-
const
|
|
27112
|
-
const columnList = columns.map(
|
|
27113
|
-
const orderCol =
|
|
27234
|
+
const quoteIdent5 = getQuoteIdent(dialect);
|
|
27235
|
+
const columnList = columns.map(quoteIdent5).join(", ");
|
|
27236
|
+
const orderCol = quoteIdent5(columns[0]);
|
|
27114
27237
|
let globalIndex = 0;
|
|
27115
27238
|
let loaded = 0;
|
|
27116
27239
|
let processed = 0;
|
|
@@ -27868,10 +27991,40 @@ var Context = class {
|
|
|
27868
27991
|
throw new Error("SQLite does not support stored procedures.");
|
|
27869
27992
|
}
|
|
27870
27993
|
const params = args[0];
|
|
27994
|
+
if (this.dialect === "postgres") {
|
|
27995
|
+
return this.#executeProcPostgres(name, params);
|
|
27996
|
+
}
|
|
27871
27997
|
const query = buildProcCall(this.dialect, name, params);
|
|
27872
27998
|
const result = await query.execute(this.kysely);
|
|
27873
27999
|
return result.rows ?? [];
|
|
27874
28000
|
}
|
|
28001
|
+
/**
|
|
28002
|
+
* Execute a stored procedure on PostgreSQL with FUNCTION fallback.
|
|
28003
|
+
*
|
|
28004
|
+
* PostgreSQL distinguishes between PROCEDURE and FUNCTION objects:
|
|
28005
|
+
* `CALL` only works against true procedures and raises SQLSTATE 42809
|
|
28006
|
+
* (`<name>(...) is not a procedure`) when the target is a function.
|
|
28007
|
+
*
|
|
28008
|
+
* The noorm playbook tells schema authors to use `CREATE PROCEDURE`
|
|
28009
|
+
* for void-returning ops and `CREATE FUNCTION` for row-returning ops,
|
|
28010
|
+
* and `ctx.proc()` is expected to handle both. So if `CALL` fails
|
|
28011
|
+
* with the wrong-object-type error, we retry with
|
|
28012
|
+
* `SELECT * FROM <name>(...)`, which works for both scalar and
|
|
28013
|
+
* set-returning PG functions.
|
|
28014
|
+
*/
|
|
28015
|
+
async #executeProcPostgres(name, params) {
|
|
28016
|
+
const callQuery = buildProcCall("postgres", name, params);
|
|
28017
|
+
const [callResult, callErr] = await attempt(() => callQuery.execute(this.kysely));
|
|
28018
|
+
if (!callErr) {
|
|
28019
|
+
return callResult.rows ?? [];
|
|
28020
|
+
}
|
|
28021
|
+
if (!isFunctionNotProcedureError(callErr)) {
|
|
28022
|
+
throw callErr;
|
|
28023
|
+
}
|
|
28024
|
+
const tvfQuery = buildTvfCall("postgres", name, params);
|
|
28025
|
+
const tvfResult = await tvfQuery.execute(this.kysely);
|
|
28026
|
+
return tvfResult.rows ?? [];
|
|
28027
|
+
}
|
|
27875
28028
|
/**
|
|
27876
28029
|
* Call a database function and return the scalar result.
|
|
27877
28030
|
*
|
|
@@ -27987,6 +28140,14 @@ var Context = class {
|
|
|
27987
28140
|
return ready;
|
|
27988
28141
|
}
|
|
27989
28142
|
};
|
|
28143
|
+
function isFunctionNotProcedureError(err) {
|
|
28144
|
+
if (!err || typeof err !== "object") return false;
|
|
28145
|
+
const obj = err;
|
|
28146
|
+
if (obj.code !== "42809" && obj.code !== "42883") return false;
|
|
28147
|
+
const msg = String(obj.message ?? "");
|
|
28148
|
+
const hint = String(obj.hint ?? "");
|
|
28149
|
+
return msg.includes("is not a procedure") || msg.includes("procedure") || hint.includes("use SELECT");
|
|
28150
|
+
}
|
|
27990
28151
|
|
|
27991
28152
|
// src/sdk/index.ts
|
|
27992
28153
|
function toSettingsProvider(manager) {
|