@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/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-DE3NJ22A.js';
5
- import { makeNestedConfig, gigabytes, observer, attempt, retry, attemptSync, clone, merge, ObserverRelay } from './chunk-DLQES4PM.js';
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 [, execErr] = await attempt(() => sql.raw(sqlContent).execute(context.db));
20851
+ const execErrMsg = await executeSqlBody(context, sqlContent);
20774
20852
  const durationMs = performance.now() - start;
20775
- if (execErr) {
20853
+ if (execErrMsg) {
20776
20854
  const result2 = {
20777
20855
  filepath,
20778
20856
  checksum: finalChecksum,
20779
20857
  status: "failed",
20780
- error: getSqlErrorMessage(execErr),
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
- getSqlErrorMessage(execErr)
20866
+ execErrMsg
20789
20867
  );
20790
20868
  observer.emit("file:after", {
20791
20869
  filepath,
20792
20870
  status: "failed",
20793
20871
  durationMs,
20794
- error: getSqlErrorMessage(execErr)
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 [, execErr] = await attempt(() => sql.raw(sqlContent).execute(context.db));
20975
+ const execErrMsg = await executeSqlBody(context, sqlContent);
20898
20976
  const durationMs = performance.now() - start;
20899
- if (execErr) {
20977
+ if (execErrMsg) {
20900
20978
  const result2 = {
20901
20979
  filepath,
20902
20980
  checksum,
20903
20981
  status: "failed",
20904
- error: getSqlErrorMessage(execErr),
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: getSqlErrorMessage(execErr),
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: getSqlErrorMessage(execErr)
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
- statements.push(ops.disableForeignKeyChecks());
23644
- for (const tableName of truncated) {
23645
- statements.push(ops.truncateTable(tableName, void 0, options.restartIdentity ?? true));
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
- this.#identityHash,
24427
- this.#publicKey,
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
- this.#identityHash,
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
- this.#identityHash,
24713
+ crypto.identityHash,
24584
24714
  privateKey,
24585
- this.#publicKey,
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
- this.#identityHash,
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 quoteIdent(name) {
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 ? `${quoteIdent(schema)}.${quoteIdent(table)}` : quoteIdent(table);
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(${quoteIdent(column)}) FROM ${fullTable}), 0) + 1,
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(quoteIdent).join(", ");
24848
+ const quotedCols = columns.map(quoteIdent2).join(", ");
24726
24849
  const placeholders = columns.map((_, i) => `$${i + 1}`).join(", ");
24727
- const pkCols = primaryKey.map(quoteIdent).join(", ");
24728
- let insertSql = `INSERT INTO ${quoteIdent(table)} (${quotedCols}) OVERRIDING SYSTEM VALUE VALUES (${placeholders})`;
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) => `${quoteIdent(c)} = EXCLUDED.${quoteIdent(c)}`).join(", ");
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) => `${quoteIdent(c)} = EXCLUDED.${quoteIdent(c)}`).join(", ");
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(quoteIdent).join(", ");
24756
- const srcFull = `${quoteIdent(srcSchema)}.${quoteIdent(srcTable)}`;
24757
- const dstFull = `${quoteIdent(dstSchema)}.${quoteIdent(dstTable)}`;
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 quoteIdent2(name) {
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 ${quoteIdent2(table)} AUTO_INCREMENT = 1`;
24907
+ return `ALTER TABLE ${quoteIdent3(table)} AUTO_INCREMENT = 1`;
24785
24908
  },
24786
24909
  buildConflictInsert(table, columns, primaryKey, strategy) {
24787
- const quotedCols = columns.map(quoteIdent2).join(", ");
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 ${quoteIdent2(table)} (${quotedCols}) VALUES (${placeholders})`;
24914
+ return `INSERT INTO ${quoteIdent3(table)} (${quotedCols}) VALUES (${placeholders})`;
24792
24915
  case "skip":
24793
- return `INSERT IGNORE INTO ${quoteIdent2(table)} (${quotedCols}) VALUES (${placeholders})`;
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) => `${quoteIdent2(c)} = VALUES(${quoteIdent2(c)})`).join(", ");
24798
- return `INSERT INTO ${quoteIdent2(table)} (${quotedCols}) VALUES (${placeholders}) ON DUPLICATE KEY UPDATE ${setClauses}`;
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 ${quoteIdent2(table)} (${quotedCols}) VALUES (${placeholders})`;
24923
+ return `INSERT IGNORE INTO ${quoteIdent3(table)} (${quotedCols}) VALUES (${placeholders})`;
24801
24924
  }
24802
24925
  case "replace":
24803
- return `REPLACE INTO ${quoteIdent2(table)} (${quotedCols}) VALUES (${placeholders})`;
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(quoteIdent2).join(", ");
24808
- const srcFull = `${quoteIdent2(srcDb)}.${quoteIdent2(srcTable)}`;
24809
- const dstFull = quoteIdent2(dstTable);
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 quoteIdent3(name) {
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 ${quoteIdent3(table)} ON`;
24953
+ return `SET IDENTITY_INSERT ${quoteIdent4(table)} ON`;
24831
24954
  },
24832
24955
  getDisableIdentityInsertSql(table) {
24833
- return `SET IDENTITY_INSERT ${quoteIdent3(table)} OFF`;
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(quoteIdent3).join(", ");
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 ${quoteIdent3(table)} (${quotedCols}) VALUES (${placeholders})`;
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.${quoteIdent3(pk)} = source.${quoteIdent3(pk)}`).join(" AND ");
24848
- const sourceValues = columns.map((c, i) => `@p${i} AS ${quoteIdent3(c)}`).join(", ");
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 ${quoteIdent3(table)} AS target
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.${quoteIdent3(c)}`).join(", ")})
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.${quoteIdent3(c)} = source.${quoteIdent3(c)}`).join(", ");
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.${quoteIdent3(c)}`).join(", ")})
24995
+ VALUES (${columns.map((c) => `source.${quoteIdent4(c)}`).join(", ")})
24873
24996
  `;
24874
24997
  } else {
24875
- const setClauses = columns.map((c) => `target.${quoteIdent3(c)} = source.${quoteIdent3(c)}`).join(", ");
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.${quoteIdent3(c)}`).join(", ")})
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(quoteIdent3).join(", ");
24891
- const srcFull = `${quoteIdent3(srcDb)}.${quoteIdent3(srcSchema)}.${quoteIdent3(srcTable)}`;
24892
- const dstFull = `${quoteIdent3(dstSchema)}.${quoteIdent3(dstTable)}`;
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 ${quoteIdent3(table)} NOCHECK CONSTRAINT ALL`).execute(db);
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 ${quoteIdent3(table)} WITH CHECK CHECK CONSTRAINT ALL`).execute(db);
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 quoteIdent4 = dialect === "mssql" ? (c) => `[${c}]` : dialect === "mysql" ? (c) => `\`${c}\`` : (c) => `"${c}"`;
26443
- const columnList = columns.map(quoteIdent4).join(", ");
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 = quoteIdent4(columns[0]);
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 quoteIdent4 = getQuoteIdent(dialect);
27112
- const columnList = columns.map(quoteIdent4).join(", ");
27113
- const orderCol = quoteIdent4(columns[0]);
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) {