@dbsp/core 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2946,13 +2946,13 @@ function supportsExecution(adapter) {
2946
2946
  return "execute" in adapter && "executeOne" in adapter && typeof adapter.execute === "function";
2947
2947
  }
2948
2948
  function supportsStreaming(adapter) {
2949
- return "stream" in adapter && typeof adapter.stream === "function";
2949
+ return adapter.capabilities?.supportsStreaming === true && "stream" in adapter && typeof adapter.stream === "function";
2950
2950
  }
2951
2951
  function supportsIntrospection(adapter) {
2952
2952
  return "introspect" in adapter && typeof adapter.introspect === "function";
2953
2953
  }
2954
2954
  function supportsTransactions(adapter) {
2955
- return "transaction" in adapter && "withSchema" in adapter && typeof adapter.transaction === "function";
2955
+ return adapter.capabilities?.supportsTransactions === true && "transaction" in adapter && "withSchema" in adapter && typeof adapter.transaction === "function";
2956
2956
  }
2957
2957
  function supportsRawSql(adapter) {
2958
2958
  return "executeRaw" in adapter && typeof adapter.executeRaw === "function";
@@ -8518,6 +8518,13 @@ function buildSetOperationIntent(op2, all, left, right) {
8518
8518
  }
8519
8519
 
8520
8520
  // src/dx/stream-impl.ts
8521
+ function createUnsupportedStreamingError() {
8522
+ return new ExecutionError({
8523
+ operation: "stream()",
8524
+ reason: "The adapter declares supportsStreaming: false for this ORM instance.",
8525
+ fix: "Use an adapter configuration that supports streaming."
8526
+ });
8527
+ }
8521
8528
  function stream(builder, options) {
8522
8529
  const adapter = builder.getConfiguredAdapter();
8523
8530
  const adapterOptions = options?.chunkSize !== void 0 ? { chunkSize: options.chunkSize } : void 0;
@@ -8537,6 +8544,9 @@ function stream(builder, options) {
8537
8544
  return this;
8538
8545
  },
8539
8546
  async next() {
8547
+ if (!supportsStreaming(adapter)) {
8548
+ throw createUnsupportedStreamingError();
8549
+ }
8540
8550
  if (!hooksFired) {
8541
8551
  hooksFired = true;
8542
8552
  if (hookStore && hasHooks(hookStore)) {
@@ -10078,6 +10088,31 @@ function generateVacuumSQL(tableName, schemaName, options) {
10078
10088
  const mod = modifiers.length > 0 ? `(${modifiers.join(", ")}) ` : "";
10079
10089
  return `VACUUM ${mod}${buildQualifiedTable(tableName, schemaName)}`;
10080
10090
  }
10091
+ function createUnsupportedTransactionError() {
10092
+ return new ExecutionError({
10093
+ operation: "transaction()",
10094
+ reason: "The adapter does not declare capabilities.supportsTransactions: true for this ORM instance.",
10095
+ fix: "Use an adapter that implements transaction() and withSchema(), and declare adapter.capabilities.supportsTransactions: true."
10096
+ });
10097
+ }
10098
+ function adapterTransactionState(adapter, operation, statement) {
10099
+ const inTransaction = adapter.inTransaction;
10100
+ if (typeof inTransaction !== "boolean") {
10101
+ throw new InvalidOperationError(
10102
+ operation,
10103
+ `${statement} requires an adapter that exposes inTransaction: boolean; dbsp refuses to run it when transaction state is unknown.`
10104
+ );
10105
+ }
10106
+ return inTransaction;
10107
+ }
10108
+ function assertOutsideTransaction(adapter, operation, statement) {
10109
+ if (adapterTransactionState(adapter, operation, statement)) {
10110
+ throw new InvalidOperationError(
10111
+ operation,
10112
+ `${statement} cannot run inside a transaction block`
10113
+ );
10114
+ }
10115
+ }
10081
10116
  function generateAlterColumnSQL(tableName, column, schemaName, options) {
10082
10117
  const tbl = buildQualifiedTable(tableName, schemaName);
10083
10118
  const col2 = quoteIdent(column);
@@ -10156,24 +10191,19 @@ function buildIndexAPI(tableName, schemaName, adapter, requireAdapter2) {
10156
10191
  return {
10157
10192
  async create(opts) {
10158
10193
  const a = requireAdapter2();
10159
- if (opts.concurrently && a.inTransaction) {
10160
- throw new InvalidOperationError(
10161
- "createIndex",
10162
- "CREATE INDEX CONCURRENTLY cannot run inside a transaction block"
10163
- );
10194
+ if (opts.concurrently) {
10195
+ assertOutsideTransaction(a, "createIndex", "CREATE INDEX CONCURRENTLY");
10164
10196
  }
10165
10197
  const sql2 = a.generateCreateIndex ? a.generateCreateIndex(tableName, opts, schemaName) : generateCreateIndexSQL(tableName, schemaName, opts);
10166
10198
  await a.executeDDL?.(sql2);
10167
10199
  },
10168
10200
  async drop(name, options) {
10169
10201
  const a = requireAdapter2();
10170
- if (options?.concurrently && a.inTransaction) {
10171
- throw new InvalidOperationError(
10172
- "dropIndex",
10173
- "DROP INDEX CONCURRENTLY cannot run inside a transaction block"
10174
- );
10202
+ if (options?.concurrently) {
10203
+ assertOutsideTransaction(a, "dropIndex", "DROP INDEX CONCURRENTLY");
10175
10204
  }
10176
- const sql2 = a.generateDropIndex ? a.generateDropIndex(name, options) : generateDropIndexSQL(name, schemaName, options);
10205
+ const scopedOptions = schemaName ? { ...options, schema: options?.schema ?? schemaName } : options;
10206
+ const sql2 = a.generateDropIndex ? a.generateDropIndex(name, scopedOptions) : generateDropIndexSQL(name, schemaName, options);
10177
10207
  await a.executeDDL?.(sql2);
10178
10208
  },
10179
10209
  async list(options) {
@@ -10226,12 +10256,7 @@ function buildTableDDL(tableName, schemaName, adapter) {
10226
10256
  },
10227
10257
  async vacuum(options) {
10228
10258
  const a = requireAdapter2();
10229
- if (a.inTransaction) {
10230
- throw new InvalidOperationError(
10231
- "vacuum",
10232
- "VACUUM cannot run inside a transaction block"
10233
- );
10234
- }
10259
+ assertOutsideTransaction(a, "vacuum", "VACUUM");
10235
10260
  const sql2 = a.generateVacuum ? a.generateVacuum(tableName, schemaName, options) : generateVacuumSQL(tableName, schemaName, options);
10236
10261
  await a.executeDDL?.(sql2);
10237
10262
  },
@@ -10563,31 +10588,47 @@ function createOrmInstance(model, strictMode, relationHints, adapter, schemaName
10563
10588
  // =====================================================================
10564
10589
  // Transaction Methods (DX-025)
10565
10590
  // =====================================================================
10566
- async transaction(fn2) {
10591
+ // NOT `async`, and that is load-bearing. An async method awaits whatever it
10592
+ // returns and re-wraps it in a fresh Promise — which would mean the language
10593
+ // itself attaches to the adapter's promise, and an adapter that needs to know
10594
+ // whether the CALLER awaited a nested transaction would see every one of them
10595
+ // as awaited, by core, before the caller ever touched it. So the adapter's
10596
+ // promise is passed through untouched. The guards still reject rather than
10597
+ // throwing synchronously, because that is what callers already rely on.
10598
+ transaction(fn2) {
10567
10599
  if (!adapter) {
10568
- throw new Error(
10569
- "transaction() requires an adapter. Pass an adapter when creating the ORM."
10600
+ return Promise.reject(
10601
+ new Error(
10602
+ "transaction() requires an adapter. Pass an adapter when creating the ORM."
10603
+ )
10570
10604
  );
10571
10605
  }
10572
- return adapter.transaction(async (txAdapter) => {
10573
- const txOrm = createOrmInstance(
10574
- model,
10575
- strictMode,
10576
- relationHints,
10577
- txAdapter,
10578
- schemaName,
10579
- dialectCapabilities,
10580
- schemaDefinition,
10581
- globalPlanOptions,
10582
- defaultFilters,
10583
- hookStore,
10584
- onHookError,
10585
- true,
10586
- // inTransaction
10587
- tablesProxy
10588
- );
10589
- return fn2(txOrm);
10590
- });
10606
+ if (!supportsTransactions(adapter)) {
10607
+ return Promise.reject(createUnsupportedTransactionError());
10608
+ }
10609
+ try {
10610
+ return adapter.transaction(async (txAdapter) => {
10611
+ const txOrm = createOrmInstance(
10612
+ model,
10613
+ strictMode,
10614
+ relationHints,
10615
+ txAdapter,
10616
+ schemaName,
10617
+ dialectCapabilities,
10618
+ schemaDefinition,
10619
+ globalPlanOptions,
10620
+ defaultFilters,
10621
+ hookStore,
10622
+ onHookError,
10623
+ true,
10624
+ // inTransaction
10625
+ tablesProxy
10626
+ );
10627
+ return fn2(txOrm);
10628
+ });
10629
+ } catch (error) {
10630
+ return Promise.reject(error);
10631
+ }
10591
10632
  },
10592
10633
  // =====================================================================
10593
10634
  // Raw SQL Execution (DX-027)
@@ -10666,12 +10707,20 @@ function createOrmInstance(model, strictMode, relationHints, adapter, schemaName
10666
10707
  "executeDDL() requires an adapter that supports DDL execution."
10667
10708
  );
10668
10709
  }
10710
+ if (options?.concurrently) {
10711
+ assertOutsideTransaction(
10712
+ adapter,
10713
+ "dropIndex",
10714
+ "DROP INDEX CONCURRENTLY"
10715
+ );
10716
+ }
10669
10717
  validateIdentifier(name, "index");
10670
10718
  const sc = options?.schema ?? schemaName;
10671
10719
  if (sc) {
10672
10720
  validateIdentifier(sc, "schema");
10673
10721
  }
10674
- const sql2 = adapter.generateDropIndex ? adapter.generateDropIndex(name, options) : (() => {
10722
+ const scopedOptions = sc ? { ...options, schema: sc } : options;
10723
+ const sql2 = adapter.generateDropIndex ? adapter.generateDropIndex(name, scopedOptions) : (() => {
10675
10724
  const parts = ["DROP INDEX"];
10676
10725
  if (options?.concurrently) parts.push("CONCURRENTLY");
10677
10726
  if (options?.ifExists) parts.push("IF EXISTS");