@noormdev/sdk 1.0.0-alpha.34 → 1.0.0-alpha.36
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 +288 -111
- package/dist/index.js.map +1 -1
- package/dist/{mssql-3NNVV77C.js → mssql-NIABT3Z4.js} +6 -4
- package/dist/mssql-NIABT3Z4.js.map +1 -0
- 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/mssql-3NNVV77C.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';
|
|
@@ -15797,7 +15797,7 @@ async function getDialectFactory(dialect) {
|
|
|
15797
15797
|
case "mysql":
|
|
15798
15798
|
return (await import('./mysql-UPMQUBLE.js')).createMysqlConnection;
|
|
15799
15799
|
case "mssql":
|
|
15800
|
-
return (await import('./mssql-
|
|
15800
|
+
return (await import('./mssql-NIABT3Z4.js')).createMssqlConnection;
|
|
15801
15801
|
default:
|
|
15802
15802
|
throw new Error(`Unsupported dialect: ${dialect}`);
|
|
15803
15803
|
}
|
|
@@ -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) {
|
|
@@ -23548,6 +23632,15 @@ var mssqlTeardownOperations = {
|
|
|
23548
23632
|
},
|
|
23549
23633
|
dropForeignKey(constraintName, tableName, schema) {
|
|
23550
23634
|
return `ALTER TABLE ${qualifiedName3(tableName, schema)} DROP CONSTRAINT ${quote3(constraintName)}`;
|
|
23635
|
+
},
|
|
23636
|
+
dropCheckConstraints() {
|
|
23637
|
+
return [
|
|
23638
|
+
"DECLARE @noorm_drop_checks NVARCHAR(MAX) = N'';",
|
|
23639
|
+
"SELECT @noorm_drop_checks += N'ALTER TABLE ' + QUOTENAME(SCHEMA_NAME(t.schema_id)) + N'.' + QUOTENAME(t.name) + N' DROP CONSTRAINT ' + QUOTENAME(cc.name) + N';'",
|
|
23640
|
+
"FROM sys.check_constraints cc INNER JOIN sys.tables t ON cc.parent_object_id = t.object_id",
|
|
23641
|
+
"WHERE SCHEMA_NAME(t.schema_id) <> 'noorm';",
|
|
23642
|
+
"EXEC sp_executesql @noorm_drop_checks;"
|
|
23643
|
+
].join("\n");
|
|
23551
23644
|
}
|
|
23552
23645
|
};
|
|
23553
23646
|
|
|
@@ -23558,10 +23651,10 @@ var { quote: quote4 } = createDialectQuoting({
|
|
|
23558
23651
|
escape: '""'
|
|
23559
23652
|
});
|
|
23560
23653
|
var sqliteTeardownOperations = {
|
|
23561
|
-
disableForeignKeyChecks() {
|
|
23654
|
+
disableForeignKeyChecks(_tables) {
|
|
23562
23655
|
return "PRAGMA foreign_keys = OFF";
|
|
23563
23656
|
},
|
|
23564
|
-
enableForeignKeyChecks() {
|
|
23657
|
+
enableForeignKeyChecks(_tables) {
|
|
23565
23658
|
return "PRAGMA foreign_keys = ON";
|
|
23566
23659
|
},
|
|
23567
23660
|
truncateTable(tableName, _schema, _restartIdentity = false) {
|
|
@@ -23611,6 +23704,13 @@ function isNoormTable2(name) {
|
|
|
23611
23704
|
if (name.startsWith("__noorm_")) return true;
|
|
23612
23705
|
return false;
|
|
23613
23706
|
}
|
|
23707
|
+
function pushFlat(out, value) {
|
|
23708
|
+
if (Array.isArray(value)) {
|
|
23709
|
+
out.push(...value);
|
|
23710
|
+
return;
|
|
23711
|
+
}
|
|
23712
|
+
out.push(value);
|
|
23713
|
+
}
|
|
23614
23714
|
async function truncateData(db, dialect, options = {}) {
|
|
23615
23715
|
const startTime = performance.now();
|
|
23616
23716
|
const ops = getTeardownOperations(dialect);
|
|
@@ -23640,11 +23740,13 @@ async function truncateData(db, dialect, options = {}) {
|
|
|
23640
23740
|
}
|
|
23641
23741
|
truncated.push(tableName);
|
|
23642
23742
|
}
|
|
23643
|
-
|
|
23644
|
-
|
|
23645
|
-
|
|
23743
|
+
if (truncated.length > 0) {
|
|
23744
|
+
pushFlat(statements, ops.disableForeignKeyChecks(truncated));
|
|
23745
|
+
for (const tableName of truncated) {
|
|
23746
|
+
statements.push(ops.truncateTable(tableName, void 0, options.restartIdentity ?? true));
|
|
23747
|
+
}
|
|
23748
|
+
pushFlat(statements, ops.enableForeignKeyChecks(truncated));
|
|
23646
23749
|
}
|
|
23647
|
-
statements.push(ops.enableForeignKeyChecks());
|
|
23648
23750
|
if (!options.dryRun) {
|
|
23649
23751
|
for (const stmt of statements) {
|
|
23650
23752
|
if (stmt.startsWith("--")) continue;
|
|
@@ -23716,6 +23818,21 @@ async function teardownSchema(db, dialect, options = {}) {
|
|
|
23716
23818
|
dropped.foreignKeys.push(fk.name);
|
|
23717
23819
|
statements.push(ops.dropForeignKey(fk.name, tableName, fk.schema));
|
|
23718
23820
|
}
|
|
23821
|
+
if (!options.keepFunctions && ops.dropCheckConstraints) {
|
|
23822
|
+
statements.push(ops.dropCheckConstraints());
|
|
23823
|
+
}
|
|
23824
|
+
if (!options.keepProcedures) {
|
|
23825
|
+
for (const proc of procedures) {
|
|
23826
|
+
dropped.procedures.push(proc.name);
|
|
23827
|
+
statements.push(ops.dropProcedure(proc.name, proc.schema));
|
|
23828
|
+
}
|
|
23829
|
+
}
|
|
23830
|
+
if (!options.keepFunctions) {
|
|
23831
|
+
for (const fn of functions) {
|
|
23832
|
+
dropped.functions.push(fn.name);
|
|
23833
|
+
statements.push(ops.dropFunction(fn.name, fn.schema));
|
|
23834
|
+
}
|
|
23835
|
+
}
|
|
23719
23836
|
if (!options.keepViews) {
|
|
23720
23837
|
for (const view of views) {
|
|
23721
23838
|
dropped.views.push(view.name);
|
|
@@ -23735,18 +23852,6 @@ async function teardownSchema(db, dialect, options = {}) {
|
|
|
23735
23852
|
dropped.tables.push(tableName);
|
|
23736
23853
|
statements.push(ops.dropTable(tableName, table.schema));
|
|
23737
23854
|
}
|
|
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
23855
|
const skipTypesDueToKeptRoutines = dialect === "mssql" && (options.keepFunctions || options.keepProcedures);
|
|
23751
23856
|
if (!options.keepTypes && !skipTypesDueToKeptRoutines) {
|
|
23752
23857
|
const sortedTypes = [...types].sort((a, b) => {
|
|
@@ -24058,7 +24163,11 @@ var DbNamespace = class {
|
|
|
24058
24163
|
*/
|
|
24059
24164
|
async reset() {
|
|
24060
24165
|
checkProtectedConfig(this.#state.config, "reset");
|
|
24061
|
-
await this
|
|
24166
|
+
await teardownSchema(this.#kysely, this.#dialect, {
|
|
24167
|
+
configName: this.#state.config.name,
|
|
24168
|
+
executedBy: formatIdentity(this.#state.identity),
|
|
24169
|
+
postScript: this.#state.settings.teardown?.postScript
|
|
24170
|
+
});
|
|
24062
24171
|
if (this.#buildFn) {
|
|
24063
24172
|
await this.#buildFn({ force: true });
|
|
24064
24173
|
}
|
|
@@ -24406,25 +24515,60 @@ async function copyVaultSecrets(sourceConfig, destConfig, keys, identityHash, pr
|
|
|
24406
24515
|
// src/sdk/namespaces/vault.ts
|
|
24407
24516
|
var VaultNamespace = class {
|
|
24408
24517
|
#state;
|
|
24518
|
+
#cryptoIdentity = null;
|
|
24409
24519
|
constructor(state) {
|
|
24410
24520
|
this.#state = state;
|
|
24411
24521
|
}
|
|
24522
|
+
/**
|
|
24523
|
+
* Load the cryptographic identity (with publicKey + identityHash) on
|
|
24524
|
+
* demand. The Context's state.identity is the audit identity (name +
|
|
24525
|
+
* email only); the crypto fields needed for vault encryption live in
|
|
24526
|
+
* `~/.noorm/identity.json` (or a NOORM_IDENTITY_* env override).
|
|
24527
|
+
*
|
|
24528
|
+
* Cached after the first call so repeated vault ops don't re-read disk.
|
|
24529
|
+
*/
|
|
24530
|
+
async #getCryptoIdentity() {
|
|
24531
|
+
if (this.#cryptoIdentity) return this.#cryptoIdentity;
|
|
24532
|
+
const loaded = await loadIdentityMetadata();
|
|
24533
|
+
if (!loaded) {
|
|
24534
|
+
throw new Error(
|
|
24535
|
+
"Vault operations require a cryptographic identity at ~/.noorm/identity.json. Run `noorm identity init` or set NOORM_IDENTITY_* env vars in CI."
|
|
24536
|
+
);
|
|
24537
|
+
}
|
|
24538
|
+
this.#cryptoIdentity = loaded;
|
|
24539
|
+
return loaded;
|
|
24540
|
+
}
|
|
24412
24541
|
// ─────────────────────────────────────────────────────
|
|
24413
24542
|
// Lifecycle
|
|
24414
24543
|
// ─────────────────────────────────────────────────────
|
|
24415
24544
|
/**
|
|
24416
24545
|
* Initialize the vault for this database.
|
|
24417
24546
|
*
|
|
24547
|
+
* Idempotent. Returns the vault key on first init; returns [null, null]
|
|
24548
|
+
* on subsequent calls when the vault already exists. Returns [null, Error]
|
|
24549
|
+
* only on real failures (DB errors, encryption errors).
|
|
24550
|
+
*
|
|
24551
|
+
* The `vault:initialized` observer event fires only on first init, never
|
|
24552
|
+
* on repeat calls.
|
|
24553
|
+
*
|
|
24418
24554
|
* @example
|
|
24419
24555
|
* ```typescript
|
|
24420
|
-
* const [vaultKey, err] = await ctx.noorm.vault.init()
|
|
24556
|
+
* const [vaultKey, err] = await ctx.noorm.vault.init();
|
|
24557
|
+
* if (err) throw err;
|
|
24558
|
+
* if (vaultKey) {
|
|
24559
|
+
* // first-time init — set initial secrets, etc.
|
|
24560
|
+
* }
|
|
24561
|
+
* else {
|
|
24562
|
+
* // already initialized — vault.get / vault.set with private key
|
|
24563
|
+
* }
|
|
24421
24564
|
* ```
|
|
24422
24565
|
*/
|
|
24423
24566
|
async init() {
|
|
24567
|
+
const crypto = await this.#getCryptoIdentity();
|
|
24424
24568
|
return initializeVault(
|
|
24425
24569
|
this.#kysely,
|
|
24426
|
-
|
|
24427
|
-
|
|
24570
|
+
crypto.identityHash,
|
|
24571
|
+
crypto.publicKey,
|
|
24428
24572
|
this.#dialect
|
|
24429
24573
|
);
|
|
24430
24574
|
}
|
|
@@ -24437,9 +24581,10 @@ var VaultNamespace = class {
|
|
|
24437
24581
|
* ```
|
|
24438
24582
|
*/
|
|
24439
24583
|
async status() {
|
|
24584
|
+
const crypto = await this.#getCryptoIdentity();
|
|
24440
24585
|
return getVaultStatus(
|
|
24441
24586
|
this.#kysely,
|
|
24442
|
-
|
|
24587
|
+
crypto.identityHash,
|
|
24443
24588
|
this.#dialect
|
|
24444
24589
|
);
|
|
24445
24590
|
}
|
|
@@ -24576,13 +24721,14 @@ var VaultNamespace = class {
|
|
|
24576
24721
|
* ```
|
|
24577
24722
|
*/
|
|
24578
24723
|
async copy(destConfig, keys, privateKey, options) {
|
|
24724
|
+
const crypto = await this.#getCryptoIdentity();
|
|
24579
24725
|
return copyVaultSecrets(
|
|
24580
24726
|
this.#state.config,
|
|
24581
24727
|
destConfig,
|
|
24582
24728
|
keys,
|
|
24583
|
-
|
|
24729
|
+
crypto.identityHash,
|
|
24584
24730
|
privateKey,
|
|
24585
|
-
|
|
24731
|
+
crypto.publicKey,
|
|
24586
24732
|
options
|
|
24587
24733
|
);
|
|
24588
24734
|
}
|
|
@@ -24595,21 +24741,14 @@ var VaultNamespace = class {
|
|
|
24595
24741
|
}
|
|
24596
24742
|
return this.#state.connection.db;
|
|
24597
24743
|
}
|
|
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
24744
|
get #dialect() {
|
|
24607
24745
|
return this.#state.config.connection.dialect;
|
|
24608
24746
|
}
|
|
24609
24747
|
async #getVaultKey(privateKey) {
|
|
24748
|
+
const crypto = await this.#getCryptoIdentity();
|
|
24610
24749
|
return getVaultKey(
|
|
24611
24750
|
this.#kysely,
|
|
24612
|
-
|
|
24751
|
+
crypto.identityHash,
|
|
24613
24752
|
privateKey,
|
|
24614
24753
|
this.#dialect
|
|
24615
24754
|
);
|
|
@@ -24695,7 +24834,7 @@ function isSameServer(source, dest) {
|
|
|
24695
24834
|
}
|
|
24696
24835
|
return true;
|
|
24697
24836
|
}
|
|
24698
|
-
function
|
|
24837
|
+
function quoteIdent2(name) {
|
|
24699
24838
|
return `"${name.replace(/"/g, '""')}"`;
|
|
24700
24839
|
}
|
|
24701
24840
|
var postgresTransferOperations = {
|
|
@@ -24712,20 +24851,20 @@ var postgresTransferOperations = {
|
|
|
24712
24851
|
return null;
|
|
24713
24852
|
},
|
|
24714
24853
|
getResetSequenceSql(table, column, schema) {
|
|
24715
|
-
const fullTable = schema ? `${
|
|
24854
|
+
const fullTable = schema ? `${quoteIdent2(schema)}.${quoteIdent2(table)}` : quoteIdent2(table);
|
|
24716
24855
|
return `
|
|
24717
24856
|
SELECT setval(
|
|
24718
24857
|
pg_get_serial_sequence('${schema ? schema + "." : ""}${table}', '${column}'),
|
|
24719
|
-
COALESCE((SELECT MAX(${
|
|
24858
|
+
COALESCE((SELECT MAX(${quoteIdent2(column)}) FROM ${fullTable}), 0) + 1,
|
|
24720
24859
|
false
|
|
24721
24860
|
)
|
|
24722
24861
|
`.trim();
|
|
24723
24862
|
},
|
|
24724
24863
|
buildConflictInsert(table, columns, primaryKey, strategy) {
|
|
24725
|
-
const quotedCols = columns.map(
|
|
24864
|
+
const quotedCols = columns.map(quoteIdent2).join(", ");
|
|
24726
24865
|
const placeholders = columns.map((_, i) => `$${i + 1}`).join(", ");
|
|
24727
|
-
const pkCols = primaryKey.map(
|
|
24728
|
-
let insertSql = `INSERT INTO ${
|
|
24866
|
+
const pkCols = primaryKey.map(quoteIdent2).join(", ");
|
|
24867
|
+
let insertSql = `INSERT INTO ${quoteIdent2(table)} (${quotedCols}) OVERRIDING SYSTEM VALUE VALUES (${placeholders})`;
|
|
24729
24868
|
switch (strategy) {
|
|
24730
24869
|
case "fail":
|
|
24731
24870
|
break;
|
|
@@ -24735,7 +24874,7 @@ var postgresTransferOperations = {
|
|
|
24735
24874
|
case "update": {
|
|
24736
24875
|
const updateCols = columns.filter((c) => !primaryKey.includes(c));
|
|
24737
24876
|
if (updateCols.length > 0) {
|
|
24738
|
-
const setClauses = updateCols.map((c) => `${
|
|
24877
|
+
const setClauses = updateCols.map((c) => `${quoteIdent2(c)} = EXCLUDED.${quoteIdent2(c)}`).join(", ");
|
|
24739
24878
|
insertSql += ` ON CONFLICT (${pkCols}) DO UPDATE SET ${setClauses}`;
|
|
24740
24879
|
} else {
|
|
24741
24880
|
insertSql += ` ON CONFLICT (${pkCols}) DO NOTHING`;
|
|
@@ -24744,7 +24883,7 @@ var postgresTransferOperations = {
|
|
|
24744
24883
|
}
|
|
24745
24884
|
case "replace":
|
|
24746
24885
|
{
|
|
24747
|
-
const setClauses = columns.map((c) => `${
|
|
24886
|
+
const setClauses = columns.map((c) => `${quoteIdent2(c)} = EXCLUDED.${quoteIdent2(c)}`).join(", ");
|
|
24748
24887
|
insertSql += ` ON CONFLICT (${pkCols}) DO UPDATE SET ${setClauses}`;
|
|
24749
24888
|
}
|
|
24750
24889
|
break;
|
|
@@ -24752,9 +24891,9 @@ var postgresTransferOperations = {
|
|
|
24752
24891
|
return insertSql;
|
|
24753
24892
|
},
|
|
24754
24893
|
buildDirectTransfer(srcDb, srcTable, dstTable, columns, srcSchema = "public", dstSchema = "public") {
|
|
24755
|
-
const quotedCols = columns.map(
|
|
24756
|
-
const srcFull = `${
|
|
24757
|
-
const dstFull = `${
|
|
24894
|
+
const quotedCols = columns.map(quoteIdent2).join(", ");
|
|
24895
|
+
const srcFull = `${quoteIdent2(srcSchema)}.${quoteIdent2(srcTable)}`;
|
|
24896
|
+
const dstFull = `${quoteIdent2(dstSchema)}.${quoteIdent2(dstTable)}`;
|
|
24758
24897
|
return `INSERT INTO ${dstFull} (${quotedCols}) OVERRIDING SYSTEM VALUE SELECT ${quotedCols} FROM ${srcFull}`;
|
|
24759
24898
|
},
|
|
24760
24899
|
async executeDisableFK(db) {
|
|
@@ -24764,7 +24903,7 @@ var postgresTransferOperations = {
|
|
|
24764
24903
|
await sql.raw(this.getEnableFKSql()).execute(db);
|
|
24765
24904
|
}
|
|
24766
24905
|
};
|
|
24767
|
-
function
|
|
24906
|
+
function quoteIdent3(name) {
|
|
24768
24907
|
return `\`${name.replace(/`/g, "``")}\``;
|
|
24769
24908
|
}
|
|
24770
24909
|
var mysqlTransferOperations = {
|
|
@@ -24781,32 +24920,32 @@ var mysqlTransferOperations = {
|
|
|
24781
24920
|
return null;
|
|
24782
24921
|
},
|
|
24783
24922
|
getResetSequenceSql(table, _column, _schema) {
|
|
24784
|
-
return `ALTER TABLE ${
|
|
24923
|
+
return `ALTER TABLE ${quoteIdent3(table)} AUTO_INCREMENT = 1`;
|
|
24785
24924
|
},
|
|
24786
24925
|
buildConflictInsert(table, columns, primaryKey, strategy) {
|
|
24787
|
-
const quotedCols = columns.map(
|
|
24926
|
+
const quotedCols = columns.map(quoteIdent3).join(", ");
|
|
24788
24927
|
const placeholders = columns.map(() => "?").join(", ");
|
|
24789
24928
|
switch (strategy) {
|
|
24790
24929
|
case "fail":
|
|
24791
|
-
return `INSERT INTO ${
|
|
24930
|
+
return `INSERT INTO ${quoteIdent3(table)} (${quotedCols}) VALUES (${placeholders})`;
|
|
24792
24931
|
case "skip":
|
|
24793
|
-
return `INSERT IGNORE INTO ${
|
|
24932
|
+
return `INSERT IGNORE INTO ${quoteIdent3(table)} (${quotedCols}) VALUES (${placeholders})`;
|
|
24794
24933
|
case "update": {
|
|
24795
24934
|
const updateCols = columns.filter((c) => !primaryKey.includes(c));
|
|
24796
24935
|
if (updateCols.length > 0) {
|
|
24797
|
-
const setClauses = updateCols.map((c) => `${
|
|
24798
|
-
return `INSERT INTO ${
|
|
24936
|
+
const setClauses = updateCols.map((c) => `${quoteIdent3(c)} = VALUES(${quoteIdent3(c)})`).join(", ");
|
|
24937
|
+
return `INSERT INTO ${quoteIdent3(table)} (${quotedCols}) VALUES (${placeholders}) ON DUPLICATE KEY UPDATE ${setClauses}`;
|
|
24799
24938
|
}
|
|
24800
|
-
return `INSERT IGNORE INTO ${
|
|
24939
|
+
return `INSERT IGNORE INTO ${quoteIdent3(table)} (${quotedCols}) VALUES (${placeholders})`;
|
|
24801
24940
|
}
|
|
24802
24941
|
case "replace":
|
|
24803
|
-
return `REPLACE INTO ${
|
|
24942
|
+
return `REPLACE INTO ${quoteIdent3(table)} (${quotedCols}) VALUES (${placeholders})`;
|
|
24804
24943
|
}
|
|
24805
24944
|
},
|
|
24806
24945
|
buildDirectTransfer(srcDb, srcTable, dstTable, columns, _srcSchema, _dstSchema) {
|
|
24807
|
-
const quotedCols = columns.map(
|
|
24808
|
-
const srcFull = `${
|
|
24809
|
-
const dstFull =
|
|
24946
|
+
const quotedCols = columns.map(quoteIdent3).join(", ");
|
|
24947
|
+
const srcFull = `${quoteIdent3(srcDb)}.${quoteIdent3(srcTable)}`;
|
|
24948
|
+
const dstFull = quoteIdent3(dstTable);
|
|
24810
24949
|
return `INSERT INTO ${dstFull} (${quotedCols}) SELECT ${quotedCols} FROM ${srcFull}`;
|
|
24811
24950
|
},
|
|
24812
24951
|
async executeDisableFK(db) {
|
|
@@ -24816,7 +24955,7 @@ var mysqlTransferOperations = {
|
|
|
24816
24955
|
await sql.raw(this.getEnableFKSql()).execute(db);
|
|
24817
24956
|
}
|
|
24818
24957
|
};
|
|
24819
|
-
function
|
|
24958
|
+
function quoteIdent4(name) {
|
|
24820
24959
|
return `[${name.replace(/\]/g, "]]")}]`;
|
|
24821
24960
|
}
|
|
24822
24961
|
var mssqlTransferOperations = {
|
|
@@ -24827,27 +24966,27 @@ var mssqlTransferOperations = {
|
|
|
24827
24966
|
return "-- FK enable per-table";
|
|
24828
24967
|
},
|
|
24829
24968
|
getEnableIdentityInsertSql(table) {
|
|
24830
|
-
return `SET IDENTITY_INSERT ${
|
|
24969
|
+
return `SET IDENTITY_INSERT ${quoteIdent4(table)} ON`;
|
|
24831
24970
|
},
|
|
24832
24971
|
getDisableIdentityInsertSql(table) {
|
|
24833
|
-
return `SET IDENTITY_INSERT ${
|
|
24972
|
+
return `SET IDENTITY_INSERT ${quoteIdent4(table)} OFF`;
|
|
24834
24973
|
},
|
|
24835
24974
|
getResetSequenceSql(table, _column, _schema) {
|
|
24836
24975
|
return `DBCC CHECKIDENT ('${table}', RESEED)`;
|
|
24837
24976
|
},
|
|
24838
24977
|
buildConflictInsert(table, columns, primaryKey, strategy) {
|
|
24839
|
-
const quotedCols = columns.map(
|
|
24978
|
+
const quotedCols = columns.map(quoteIdent4).join(", ");
|
|
24840
24979
|
const placeholders = columns.map((_, i) => `@p${i}`).join(", ");
|
|
24841
24980
|
switch (strategy) {
|
|
24842
24981
|
case "fail":
|
|
24843
|
-
return `INSERT INTO ${
|
|
24982
|
+
return `INSERT INTO ${quoteIdent4(table)} (${quotedCols}) VALUES (${placeholders})`;
|
|
24844
24983
|
case "skip":
|
|
24845
24984
|
case "update":
|
|
24846
24985
|
case "replace": {
|
|
24847
|
-
const pkConditions = primaryKey.map((pk) => `target.${
|
|
24848
|
-
const sourceValues = columns.map((c, i) => `@p${i} AS ${
|
|
24986
|
+
const pkConditions = primaryKey.map((pk) => `target.${quoteIdent4(pk)} = source.${quoteIdent4(pk)}`).join(" AND ");
|
|
24987
|
+
const sourceValues = columns.map((c, i) => `@p${i} AS ${quoteIdent4(c)}`).join(", ");
|
|
24849
24988
|
let mergeSql = `
|
|
24850
|
-
MERGE INTO ${
|
|
24989
|
+
MERGE INTO ${quoteIdent4(table)} AS target
|
|
24851
24990
|
USING (SELECT ${sourceValues}) AS source
|
|
24852
24991
|
ON (${pkConditions})
|
|
24853
24992
|
`.trim();
|
|
@@ -24855,12 +24994,12 @@ var mssqlTransferOperations = {
|
|
|
24855
24994
|
mergeSql += `
|
|
24856
24995
|
WHEN NOT MATCHED THEN
|
|
24857
24996
|
INSERT (${quotedCols})
|
|
24858
|
-
VALUES (${columns.map((c) => `source.${
|
|
24997
|
+
VALUES (${columns.map((c) => `source.${quoteIdent4(c)}`).join(", ")})
|
|
24859
24998
|
`;
|
|
24860
24999
|
} else if (strategy === "update") {
|
|
24861
25000
|
const updateCols = columns.filter((c) => !primaryKey.includes(c));
|
|
24862
25001
|
if (updateCols.length > 0) {
|
|
24863
|
-
const setClauses = updateCols.map((c) => `target.${
|
|
25002
|
+
const setClauses = updateCols.map((c) => `target.${quoteIdent4(c)} = source.${quoteIdent4(c)}`).join(", ");
|
|
24864
25003
|
mergeSql += `
|
|
24865
25004
|
WHEN MATCHED THEN
|
|
24866
25005
|
UPDATE SET ${setClauses}
|
|
@@ -24869,16 +25008,16 @@ var mssqlTransferOperations = {
|
|
|
24869
25008
|
mergeSql += `
|
|
24870
25009
|
WHEN NOT MATCHED THEN
|
|
24871
25010
|
INSERT (${quotedCols})
|
|
24872
|
-
VALUES (${columns.map((c) => `source.${
|
|
25011
|
+
VALUES (${columns.map((c) => `source.${quoteIdent4(c)}`).join(", ")})
|
|
24873
25012
|
`;
|
|
24874
25013
|
} else {
|
|
24875
|
-
const setClauses = columns.map((c) => `target.${
|
|
25014
|
+
const setClauses = columns.map((c) => `target.${quoteIdent4(c)} = source.${quoteIdent4(c)}`).join(", ");
|
|
24876
25015
|
mergeSql += `
|
|
24877
25016
|
WHEN MATCHED THEN
|
|
24878
25017
|
UPDATE SET ${setClauses}
|
|
24879
25018
|
WHEN NOT MATCHED THEN
|
|
24880
25019
|
INSERT (${quotedCols})
|
|
24881
|
-
VALUES (${columns.map((c) => `source.${
|
|
25020
|
+
VALUES (${columns.map((c) => `source.${quoteIdent4(c)}`).join(", ")})
|
|
24882
25021
|
`;
|
|
24883
25022
|
}
|
|
24884
25023
|
mergeSql += ";";
|
|
@@ -24887,19 +25026,19 @@ var mssqlTransferOperations = {
|
|
|
24887
25026
|
}
|
|
24888
25027
|
},
|
|
24889
25028
|
buildDirectTransfer(srcDb, srcTable, dstTable, columns, srcSchema = "dbo", dstSchema = "dbo") {
|
|
24890
|
-
const quotedCols = columns.map(
|
|
24891
|
-
const srcFull = `${
|
|
24892
|
-
const dstFull = `${
|
|
25029
|
+
const quotedCols = columns.map(quoteIdent4).join(", ");
|
|
25030
|
+
const srcFull = `${quoteIdent4(srcDb)}.${quoteIdent4(srcSchema)}.${quoteIdent4(srcTable)}`;
|
|
25031
|
+
const dstFull = `${quoteIdent4(dstSchema)}.${quoteIdent4(dstTable)}`;
|
|
24893
25032
|
return `INSERT INTO ${dstFull} (${quotedCols}) SELECT ${quotedCols} FROM ${srcFull}`;
|
|
24894
25033
|
},
|
|
24895
25034
|
async executeDisableFK(db, tables) {
|
|
24896
25035
|
for (const table of tables) {
|
|
24897
|
-
await sql.raw(`ALTER TABLE ${
|
|
25036
|
+
await sql.raw(`ALTER TABLE ${quoteIdent4(table)} NOCHECK CONSTRAINT ALL`).execute(db);
|
|
24898
25037
|
}
|
|
24899
25038
|
},
|
|
24900
25039
|
async executeEnableFK(db, tables) {
|
|
24901
25040
|
for (const table of tables) {
|
|
24902
|
-
await sql.raw(`ALTER TABLE ${
|
|
25041
|
+
await sql.raw(`ALTER TABLE ${quoteIdent4(table)} WITH CHECK CHECK CONSTRAINT ALL`).execute(db);
|
|
24903
25042
|
}
|
|
24904
25043
|
}
|
|
24905
25044
|
};
|
|
@@ -26439,10 +26578,10 @@ async function transferTableCrossDialect(ctx, plan, transferPlan, options) {
|
|
|
26439
26578
|
}, null];
|
|
26440
26579
|
}
|
|
26441
26580
|
async function fetchBatch(db, dialect, table, columns, limit, offset, _schema) {
|
|
26442
|
-
const
|
|
26443
|
-
const columnList = columns.map(
|
|
26581
|
+
const quoteIdent5 = dialect === "mssql" ? (c) => `[${c}]` : dialect === "mysql" ? (c) => `\`${c}\`` : (c) => `"${c}"`;
|
|
26582
|
+
const columnList = columns.map(quoteIdent5).join(", ");
|
|
26444
26583
|
if (dialect === "mssql") {
|
|
26445
|
-
const orderCol =
|
|
26584
|
+
const orderCol = quoteIdent5(columns[0]);
|
|
26446
26585
|
const result2 = await sql`
|
|
26447
26586
|
SELECT ${sql.raw(columnList)}
|
|
26448
26587
|
FROM ${sql.table(table)}
|
|
@@ -27108,9 +27247,9 @@ async function exportTableWithWorkers(ctx) {
|
|
|
27108
27247
|
totalRows = Number(firstRow?.["cnt"] ?? 0);
|
|
27109
27248
|
}
|
|
27110
27249
|
const columns = dtSchema.columns.map((c) => c.name);
|
|
27111
|
-
const
|
|
27112
|
-
const columnList = columns.map(
|
|
27113
|
-
const orderCol =
|
|
27250
|
+
const quoteIdent5 = getQuoteIdent(dialect);
|
|
27251
|
+
const columnList = columns.map(quoteIdent5).join(", ");
|
|
27252
|
+
const orderCol = quoteIdent5(columns[0]);
|
|
27114
27253
|
let globalIndex = 0;
|
|
27115
27254
|
let loaded = 0;
|
|
27116
27255
|
let processed = 0;
|
|
@@ -27868,10 +28007,40 @@ var Context = class {
|
|
|
27868
28007
|
throw new Error("SQLite does not support stored procedures.");
|
|
27869
28008
|
}
|
|
27870
28009
|
const params = args[0];
|
|
28010
|
+
if (this.dialect === "postgres") {
|
|
28011
|
+
return this.#executeProcPostgres(name, params);
|
|
28012
|
+
}
|
|
27871
28013
|
const query = buildProcCall(this.dialect, name, params);
|
|
27872
28014
|
const result = await query.execute(this.kysely);
|
|
27873
28015
|
return result.rows ?? [];
|
|
27874
28016
|
}
|
|
28017
|
+
/**
|
|
28018
|
+
* Execute a stored procedure on PostgreSQL with FUNCTION fallback.
|
|
28019
|
+
*
|
|
28020
|
+
* PostgreSQL distinguishes between PROCEDURE and FUNCTION objects:
|
|
28021
|
+
* `CALL` only works against true procedures and raises SQLSTATE 42809
|
|
28022
|
+
* (`<name>(...) is not a procedure`) when the target is a function.
|
|
28023
|
+
*
|
|
28024
|
+
* The noorm playbook tells schema authors to use `CREATE PROCEDURE`
|
|
28025
|
+
* for void-returning ops and `CREATE FUNCTION` for row-returning ops,
|
|
28026
|
+
* and `ctx.proc()` is expected to handle both. So if `CALL` fails
|
|
28027
|
+
* with the wrong-object-type error, we retry with
|
|
28028
|
+
* `SELECT * FROM <name>(...)`, which works for both scalar and
|
|
28029
|
+
* set-returning PG functions.
|
|
28030
|
+
*/
|
|
28031
|
+
async #executeProcPostgres(name, params) {
|
|
28032
|
+
const callQuery = buildProcCall("postgres", name, params);
|
|
28033
|
+
const [callResult, callErr] = await attempt(() => callQuery.execute(this.kysely));
|
|
28034
|
+
if (!callErr) {
|
|
28035
|
+
return callResult.rows ?? [];
|
|
28036
|
+
}
|
|
28037
|
+
if (!isFunctionNotProcedureError(callErr)) {
|
|
28038
|
+
throw callErr;
|
|
28039
|
+
}
|
|
28040
|
+
const tvfQuery = buildTvfCall("postgres", name, params);
|
|
28041
|
+
const tvfResult = await tvfQuery.execute(this.kysely);
|
|
28042
|
+
return tvfResult.rows ?? [];
|
|
28043
|
+
}
|
|
27875
28044
|
/**
|
|
27876
28045
|
* Call a database function and return the scalar result.
|
|
27877
28046
|
*
|
|
@@ -27987,6 +28156,14 @@ var Context = class {
|
|
|
27987
28156
|
return ready;
|
|
27988
28157
|
}
|
|
27989
28158
|
};
|
|
28159
|
+
function isFunctionNotProcedureError(err) {
|
|
28160
|
+
if (!err || typeof err !== "object") return false;
|
|
28161
|
+
const obj = err;
|
|
28162
|
+
if (obj.code !== "42809" && obj.code !== "42883") return false;
|
|
28163
|
+
const msg = String(obj.message ?? "");
|
|
28164
|
+
const hint = String(obj.hint ?? "");
|
|
28165
|
+
return msg.includes("is not a procedure") || msg.includes("procedure") || hint.includes("use SELECT");
|
|
28166
|
+
}
|
|
27990
28167
|
|
|
27991
28168
|
// src/sdk/index.ts
|
|
27992
28169
|
function toSettingsProvider(manager) {
|