@dbsp/core 1.11.1 → 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
@@ -687,6 +687,13 @@ var SchemaValidationError = class extends Error {
687
687
  table;
688
688
  column;
689
689
  };
690
+ function validateSchemaIndexOptions(tableName, idx) {
691
+ if (idx.nullsNotDistinct === true && idx.unique !== true) {
692
+ throw new SchemaValidationError(
693
+ `Index "${idx.name ?? `idx_${tableName}_${idx.columns.join("_")}`}" on "${tableName}" cannot use nullsNotDistinct unless unique is true`
694
+ );
695
+ }
696
+ }
690
697
  function schemaToModelIR(definition, constraints, extras, options) {
691
698
  if (typeof options?.defaultPkColumnName === "string" && options.defaultPkColumnName.trim().length === 0) {
692
699
  throw new SchemaValidationError(
@@ -1095,13 +1102,18 @@ function buildTableConstraints(tableName, constraints) {
1095
1102
  }
1096
1103
  if (tableConstraints.indexes) {
1097
1104
  for (const idx of tableConstraints.indexes) {
1105
+ validateSchemaIndexOptions(tableName, idx);
1098
1106
  const indexIR = {
1099
1107
  name: idx.name ?? `idx_${tableName}_${idx.columns.join("_")}`,
1100
1108
  columns: idx.columns,
1101
1109
  unique: idx.unique ?? false
1102
1110
  };
1111
+ if (idx.nullsNotDistinct !== void 0) {
1112
+ indexIR.nullsNotDistinct = idx.nullsNotDistinct;
1113
+ }
1103
1114
  if (idx.method) indexIR.method = idx.method;
1104
1115
  if (idx.where) indexIR.where = idx.where;
1116
+ if (idx.include !== void 0) indexIR.include = idx.include;
1105
1117
  if (idx.opclass) indexIR.opclass = idx.opclass;
1106
1118
  if (idx.with) indexIR.with = idx.with;
1107
1119
  extraIndexes.push(indexIR);
@@ -1489,12 +1501,6 @@ async function getSchemaFromDb(adapter, options) {
1489
1501
  }
1490
1502
 
1491
1503
  // src/conventions.ts
1492
- var DEFAULT_CONVENTIONS = {
1493
- fkPattern: "{singular}Id",
1494
- pluralize: true,
1495
- timestamps: ["createdAt", "updatedAt"],
1496
- fkAutoIndex: true
1497
- };
1498
1504
  var IRREGULAR_PLURALS = {
1499
1505
  people: "person",
1500
1506
  children: "child",
@@ -1553,257 +1559,6 @@ function capitalize(name) {
1553
1559
  function decapitalize(name) {
1554
1560
  return name.charAt(0).toLowerCase() + name.slice(1);
1555
1561
  }
1556
- function getSelfRefInverseName(belongsToName) {
1557
- if (belongsToName === "parent") return "children";
1558
- return pluralize(belongsToName);
1559
- }
1560
- function detectForeignKeys(tableName, table, conventions, tableNames) {
1561
- const fks = [];
1562
- const pattern = conventions.fkPattern;
1563
- for (const [colName, colDef] of Object.entries(table)) {
1564
- if (colDef.references) {
1565
- const targetTable = colDef.references.table;
1566
- if (colDef.references.schema === void 0 && tableNames.has(targetTable)) {
1567
- const inferredName = colName.endsWith("Id") ? colName.slice(0, -2) : singularize(targetTable);
1568
- const isSelfRef = targetTable === tableName;
1569
- const detectedFK = {
1570
- column: colName,
1571
- targetTable,
1572
- inferredName,
1573
- explicit: true,
1574
- targetColumn: colDef.references.column ?? "id"
1575
- };
1576
- if (isSelfRef) {
1577
- detectedFK.parentRole = colDef.references.parentRole ?? inferredName;
1578
- detectedFK.childRole = colDef.references.childRole ?? getSelfRefInverseName(inferredName);
1579
- }
1580
- fks.push(detectedFK);
1581
- }
1582
- continue;
1583
- }
1584
- for (const candidateTable of tableNames) {
1585
- if (candidateTable === tableName) continue;
1586
- const singular = singularize(candidateTable);
1587
- const expectedColumn = pattern.replace("{singular}", singular);
1588
- if (colName === expectedColumn) {
1589
- fks.push({
1590
- column: colName,
1591
- targetTable: candidateTable,
1592
- inferredName: singular,
1593
- explicit: false,
1594
- targetColumn: "id"
1595
- });
1596
- break;
1597
- }
1598
- }
1599
- if (colName.endsWith("Id")) {
1600
- const prefix = colName.slice(0, -2);
1601
- const singular = singularize(tableName);
1602
- if (["parent", "manager", "supervisor", "owner", singular].includes(prefix)) {
1603
- if (!fks.some((fk) => fk.column === colName)) {
1604
- fks.push({
1605
- column: colName,
1606
- targetTable: tableName,
1607
- inferredName: prefix,
1608
- explicit: false,
1609
- targetColumn: "id",
1610
- // Auto-infer roles for convention-based self-ref FKs
1611
- parentRole: prefix,
1612
- childRole: getSelfRefInverseName(prefix)
1613
- });
1614
- }
1615
- }
1616
- }
1617
- }
1618
- return fks;
1619
- }
1620
- function isBusinessColumn(colName, colDef, timestamps) {
1621
- if (colDef.primaryKey) return false;
1622
- if (timestamps.includes(colName)) return false;
1623
- if (colDef.references) return false;
1624
- if (colName.endsWith("Id")) return false;
1625
- if (["id", "createdBy", "updatedBy", "deletedAt"].includes(colName))
1626
- return false;
1627
- return true;
1628
- }
1629
- function detectManyToMany(tables, conventions, tableNames) {
1630
- const results = [];
1631
- for (const [tableName, table] of Object.entries(tables)) {
1632
- const fks = detectForeignKeys(tableName, table, conventions, tableNames);
1633
- if (fks.length !== 2) continue;
1634
- const hasBusinessColumns = Object.entries(table).some(
1635
- ([colName, colDef]) => isBusinessColumn(colName, colDef, conventions.timestamps)
1636
- );
1637
- if (hasBusinessColumns) continue;
1638
- const fkA = fks[0];
1639
- const fkB = fks[1];
1640
- if (fkA && fkB) {
1641
- results.push({
1642
- junction: tableName,
1643
- tableA: fkA.targetTable,
1644
- tableB: fkB.targetTable,
1645
- fkA: fkA.column,
1646
- fkB: fkB.column
1647
- });
1648
- }
1649
- }
1650
- return results;
1651
- }
1652
- function inferRelationsFromSchema(tables, conventions, explicitRelations = {}) {
1653
- const result = { ...explicitRelations };
1654
- const tableNames = new Set(Object.keys(tables));
1655
- const manyToManys = detectManyToMany(tables, conventions, tableNames);
1656
- const junctionTables = new Set(manyToManys.map((m) => m.junction));
1657
- for (const m2m of manyToManys) {
1658
- const { junction, tableA, tableB, fkA, fkB } = m2m;
1659
- const relNameAtoB = conventions.pluralize ? pluralize(singularize(tableB)) : tableB;
1660
- const relNameBtoA = conventions.pluralize ? pluralize(singularize(tableA)) : tableA;
1661
- const keyAtoB = `${tableA}.${relNameAtoB}`;
1662
- const keyBtoA = `${tableB}.${relNameBtoA}`;
1663
- if (!(keyAtoB in result)) {
1664
- const rel = {
1665
- kind: "manyToMany",
1666
- target: tableB,
1667
- through: junction,
1668
- sourceFk: fkA,
1669
- targetFk: fkB
1670
- };
1671
- result[keyAtoB] = rel;
1672
- }
1673
- if (!(keyBtoA in result)) {
1674
- const rel = {
1675
- kind: "manyToMany",
1676
- target: tableA,
1677
- through: junction,
1678
- sourceFk: fkB,
1679
- targetFk: fkA
1680
- };
1681
- result[keyBtoA] = rel;
1682
- }
1683
- }
1684
- for (const [tableName, table] of Object.entries(tables)) {
1685
- if (junctionTables.has(tableName)) continue;
1686
- const fks = detectForeignKeys(tableName, table, conventions, tableNames);
1687
- for (const fk of fks) {
1688
- if (junctionTables.has(fk.targetTable)) continue;
1689
- const belongsToKey = `${tableName}.${fk.inferredName}`;
1690
- if (!(belongsToKey in result)) {
1691
- const rel = {
1692
- kind: "belongsTo",
1693
- target: fk.targetTable,
1694
- foreignKey: fk.column,
1695
- targetKey: fk.targetColumn
1696
- };
1697
- result[belongsToKey] = rel;
1698
- }
1699
- const isSelfRef = fk.targetTable === tableName;
1700
- const hasManyName = isSelfRef ? getSelfRefInverseName(fk.inferredName) : (() => {
1701
- const hasCustomAlias = fk.inferredName !== singularize(fk.targetTable);
1702
- if (hasCustomAlias) {
1703
- return conventions.pluralize ? pluralize(fk.inferredName) : fk.inferredName;
1704
- }
1705
- return conventions.pluralize ? pluralize(singularize(tableName)) : tableName;
1706
- })();
1707
- const hasManyKey = `${fk.targetTable}.${hasManyName}`;
1708
- if (!(hasManyKey in result)) {
1709
- const rel = {
1710
- kind: "hasMany",
1711
- target: tableName,
1712
- foreignKey: fk.column,
1713
- sourceKey: "id"
1714
- };
1715
- result[hasManyKey] = rel;
1716
- }
1717
- }
1718
- }
1719
- return result;
1720
- }
1721
-
1722
- // src/schema-dsl.ts
1723
- function defineSchema(tables, config) {
1724
- const relations = config?.relations ?? {};
1725
- const hints = config?.hints ?? {};
1726
- const conventions = config?.conventions ?? {};
1727
- const indexes = config?.indexes ?? {};
1728
- const defaultFilters = config?.defaultFilters ?? {};
1729
- const resolvedConventions = {
1730
- ...DEFAULT_CONVENTIONS,
1731
- ...conventions
1732
- };
1733
- const allRelations = inferRelationsFromSchema(
1734
- tables,
1735
- resolvedConventions,
1736
- relations
1737
- );
1738
- validateRelations(tables, relations);
1739
- validateHints(allRelations, hints);
1740
- validateDefaultFilters(tables, defaultFilters);
1741
- return {
1742
- tables,
1743
- relations: allRelations,
1744
- hints,
1745
- conventions: resolvedConventions,
1746
- indexes,
1747
- defaultFilters
1748
- };
1749
- }
1750
- function validateRelations(tables, relations) {
1751
- const tableNames = new Set(Object.keys(tables));
1752
- for (const [key, rel] of Object.entries(relations)) {
1753
- const sourceTable = key.split(".")[0] ?? key;
1754
- if (!tableNames.has(sourceTable)) {
1755
- throw new SchemaValidationError2(
1756
- `Relation '${key}' references non-existent source table '${sourceTable}'`
1757
- );
1758
- }
1759
- if (!tableNames.has(rel.target)) {
1760
- throw new SchemaValidationError2(
1761
- `Relation '${key}' references non-existent target table '${rel.target}'`
1762
- );
1763
- }
1764
- if (rel.kind === "manyToMany" && !tableNames.has(rel.through)) {
1765
- throw new SchemaValidationError2(
1766
- `Relation '${key}' references non-existent junction table '${rel.through}'`
1767
- );
1768
- }
1769
- }
1770
- }
1771
- function validateHints(relations, hints) {
1772
- for (const path of Object.keys(hints)) {
1773
- if (!(path in relations)) {
1774
- throw new SchemaValidationError2(
1775
- `Hint path '${path}' does not match any relation. Available: ${Object.keys(relations).join(", ")}`
1776
- );
1777
- }
1778
- }
1779
- }
1780
- function validateDefaultFilters(tables, defaultFilters) {
1781
- const tableNames = new Set(Object.keys(tables));
1782
- for (const tableName of Object.keys(defaultFilters)) {
1783
- if (!tableNames.has(tableName)) {
1784
- throw new SchemaValidationError2(
1785
- `Default filter for non-existent table '${tableName}'. Available: ${[...tableNames].join(", ")}`
1786
- );
1787
- }
1788
- }
1789
- }
1790
- var SchemaValidationError2 = class extends Error {
1791
- constructor(message) {
1792
- super(message);
1793
- this.name = "SchemaValidationError";
1794
- }
1795
- };
1796
-
1797
- // src/schema-dsl-types.ts
1798
- function isBelongsTo(rel) {
1799
- return rel.kind === "belongsTo";
1800
- }
1801
- function isHasMany(rel) {
1802
- return rel.kind === "hasMany";
1803
- }
1804
- function isManyToMany(rel) {
1805
- return rel.kind === "manyToMany";
1806
- }
1807
1562
 
1808
1563
  // src/planner.ts
1809
1564
  import { resolveJsonAggOrderKey, toColumnList } from "@dbsp/types";
@@ -3191,13 +2946,13 @@ function supportsExecution(adapter) {
3191
2946
  return "execute" in adapter && "executeOne" in adapter && typeof adapter.execute === "function";
3192
2947
  }
3193
2948
  function supportsStreaming(adapter) {
3194
- return "stream" in adapter && typeof adapter.stream === "function";
2949
+ return adapter.capabilities?.supportsStreaming === true && "stream" in adapter && typeof adapter.stream === "function";
3195
2950
  }
3196
2951
  function supportsIntrospection(adapter) {
3197
2952
  return "introspect" in adapter && typeof adapter.introspect === "function";
3198
2953
  }
3199
2954
  function supportsTransactions(adapter) {
3200
- 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";
3201
2956
  }
3202
2957
  function supportsRawSql(adapter) {
3203
2958
  return "executeRaw" in adapter && typeof adapter.executeRaw === "function";
@@ -6426,7 +6181,7 @@ function hydrateJsonAggIncludes(results, planReport) {
6426
6181
  if (typeof row !== "object" || row === null) {
6427
6182
  continue;
6428
6183
  }
6429
- const record2 = row;
6184
+ const record = row;
6430
6185
  for (const [relationName, info] of relationInfo) {
6431
6186
  const candidates = [relationName];
6432
6187
  if (info.includeAlias && info.includeAlias !== relationName) {
@@ -6439,17 +6194,17 @@ function hydrateJsonAggIncludes(results, planReport) {
6439
6194
  /_([a-z])/g,
6440
6195
  (_, c) => c.toUpperCase()
6441
6196
  );
6442
- if (snakeJson in record2) {
6197
+ if (snakeJson in record) {
6443
6198
  actualColumnName = snakeJson;
6444
6199
  break;
6445
6200
  }
6446
- if (camelJson in record2) {
6201
+ if (camelJson in record) {
6447
6202
  actualColumnName = camelJson;
6448
6203
  break;
6449
6204
  }
6450
6205
  }
6451
6206
  if (actualColumnName) {
6452
- const jsonValue = record2[actualColumnName];
6207
+ const jsonValue = record[actualColumnName];
6453
6208
  let parsed;
6454
6209
  if (typeof jsonValue === "string") {
6455
6210
  try {
@@ -6468,8 +6223,8 @@ function hydrateJsonAggIncludes(results, planReport) {
6468
6223
  parsed = parsed.length > 0 ? parsed[0] : null;
6469
6224
  }
6470
6225
  const outputKey = info.includeAlias ?? relationName;
6471
- record2[outputKey] = parsed;
6472
- delete record2[actualColumnName];
6226
+ record[outputKey] = parsed;
6227
+ delete record[actualColumnName];
6473
6228
  }
6474
6229
  }
6475
6230
  }
@@ -8398,12 +8153,12 @@ var ResultHydrator = class {
8398
8153
  if (typeof row !== "object" || row === null) {
8399
8154
  continue;
8400
8155
  }
8401
- const record2 = row;
8156
+ const record = row;
8402
8157
  const valuesByPath = /* @__PURE__ */ new Map();
8403
- for (const key of Object.keys(record2)) {
8158
+ for (const key of Object.keys(record)) {
8404
8159
  const info = findLongestJoinInfo(key, joinInfos);
8405
8160
  if (!info) continue;
8406
- const value = record2[key];
8161
+ const value = record[key];
8407
8162
  let entry = valuesByPath.get(info.relationPath);
8408
8163
  if (!entry) {
8409
8164
  entry = { values: {}, allNull: true };
@@ -8415,13 +8170,13 @@ var ResultHydrator = class {
8415
8170
  value
8416
8171
  );
8417
8172
  if (value !== null && value !== void 0) entry.allNull = false;
8418
- delete record2[key];
8173
+ delete record[key];
8419
8174
  }
8420
8175
  for (const info of infosByDepth) {
8421
8176
  const entry = valuesByPath.get(info.relationPath);
8422
8177
  if (!entry) continue;
8423
8178
  assignNestedValue(
8424
- record2,
8179
+ record,
8425
8180
  info.segments,
8426
8181
  entry.allNull ? null : entry.values
8427
8182
  );
@@ -8651,10 +8406,10 @@ var ResultHydrator = class {
8651
8406
  return obj[columns[0]];
8652
8407
  }
8653
8408
  const values = columns.map((k) => obj[k]);
8654
- if (values.some((v2) => v2 === void 0 || v2 === null)) {
8409
+ if (values.some((v) => v === void 0 || v === null)) {
8655
8410
  return void 0;
8656
8411
  }
8657
- const parts = values.map((v2) => String(v2));
8412
+ const parts = values.map((v) => String(v));
8658
8413
  if (parts.some((p) => p.includes(COMPOSITE_KEY_SEP))) {
8659
8414
  return JSON.stringify(parts);
8660
8415
  }
@@ -8669,7 +8424,7 @@ var ResultHydrator = class {
8669
8424
  return obj[columns[0]];
8670
8425
  }
8671
8426
  const values = columns.map((k) => obj[k]);
8672
- return values.some((v2) => v2 === void 0 || v2 === null) ? void 0 : values;
8427
+ return values.some((v) => v === void 0 || v === null) ? void 0 : values;
8673
8428
  }
8674
8429
  };
8675
8430
 
@@ -8763,6 +8518,13 @@ function buildSetOperationIntent(op2, all, left, right) {
8763
8518
  }
8764
8519
 
8765
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
+ }
8766
8528
  function stream(builder, options) {
8767
8529
  const adapter = builder.getConfiguredAdapter();
8768
8530
  const adapterOptions = options?.chunkSize !== void 0 ? { chunkSize: options.chunkSize } : void 0;
@@ -8782,6 +8544,9 @@ function stream(builder, options) {
8782
8544
  return this;
8783
8545
  },
8784
8546
  async next() {
8547
+ if (!supportsStreaming(adapter)) {
8548
+ throw createUnsupportedStreamingError();
8549
+ }
8785
8550
  if (!hooksFired) {
8786
8551
  hooksFired = true;
8787
8552
  if (hookStore && hasHooks(hookStore)) {
@@ -10323,6 +10088,31 @@ function generateVacuumSQL(tableName, schemaName, options) {
10323
10088
  const mod = modifiers.length > 0 ? `(${modifiers.join(", ")}) ` : "";
10324
10089
  return `VACUUM ${mod}${buildQualifiedTable(tableName, schemaName)}`;
10325
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
+ }
10326
10116
  function generateAlterColumnSQL(tableName, column, schemaName, options) {
10327
10117
  const tbl = buildQualifiedTable(tableName, schemaName);
10328
10118
  const col2 = quoteIdent(column);
@@ -10382,7 +10172,7 @@ function generateCreateIndexSQL(tableName, schemaName, opts) {
10382
10172
  parts.push("NULLS NOT DISTINCT");
10383
10173
  }
10384
10174
  if (opts.with && Object.keys(opts.with).length > 0) {
10385
- const withClauses = Object.entries(opts.with).map(([k, v2]) => `${k} = ${v2}`).join(", ");
10175
+ const withClauses = Object.entries(opts.with).map(([k, v]) => `${k} = ${v}`).join(", ");
10386
10176
  parts.push(`WITH (${withClauses})`);
10387
10177
  }
10388
10178
  if (opts.where) parts.push(`WHERE ${opts.where}`);
@@ -10401,24 +10191,19 @@ function buildIndexAPI(tableName, schemaName, adapter, requireAdapter2) {
10401
10191
  return {
10402
10192
  async create(opts) {
10403
10193
  const a = requireAdapter2();
10404
- if (opts.concurrently && a.inTransaction) {
10405
- throw new InvalidOperationError(
10406
- "createIndex",
10407
- "CREATE INDEX CONCURRENTLY cannot run inside a transaction block"
10408
- );
10194
+ if (opts.concurrently) {
10195
+ assertOutsideTransaction(a, "createIndex", "CREATE INDEX CONCURRENTLY");
10409
10196
  }
10410
10197
  const sql2 = a.generateCreateIndex ? a.generateCreateIndex(tableName, opts, schemaName) : generateCreateIndexSQL(tableName, schemaName, opts);
10411
10198
  await a.executeDDL?.(sql2);
10412
10199
  },
10413
10200
  async drop(name, options) {
10414
10201
  const a = requireAdapter2();
10415
- if (options?.concurrently && a.inTransaction) {
10416
- throw new InvalidOperationError(
10417
- "dropIndex",
10418
- "DROP INDEX CONCURRENTLY cannot run inside a transaction block"
10419
- );
10202
+ if (options?.concurrently) {
10203
+ assertOutsideTransaction(a, "dropIndex", "DROP INDEX CONCURRENTLY");
10420
10204
  }
10421
- 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);
10422
10207
  await a.executeDDL?.(sql2);
10423
10208
  },
10424
10209
  async list(options) {
@@ -10471,12 +10256,7 @@ function buildTableDDL(tableName, schemaName, adapter) {
10471
10256
  },
10472
10257
  async vacuum(options) {
10473
10258
  const a = requireAdapter2();
10474
- if (a.inTransaction) {
10475
- throw new InvalidOperationError(
10476
- "vacuum",
10477
- "VACUUM cannot run inside a transaction block"
10478
- );
10479
- }
10259
+ assertOutsideTransaction(a, "vacuum", "VACUUM");
10480
10260
  const sql2 = a.generateVacuum ? a.generateVacuum(tableName, schemaName, options) : generateVacuumSQL(tableName, schemaName, options);
10481
10261
  await a.executeDDL?.(sql2);
10482
10262
  },
@@ -10808,31 +10588,47 @@ function createOrmInstance(model, strictMode, relationHints, adapter, schemaName
10808
10588
  // =====================================================================
10809
10589
  // Transaction Methods (DX-025)
10810
10590
  // =====================================================================
10811
- 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) {
10812
10599
  if (!adapter) {
10813
- throw new Error(
10814
- "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
+ )
10815
10604
  );
10816
10605
  }
10817
- return adapter.transaction(async (txAdapter) => {
10818
- const txOrm = createOrmInstance(
10819
- model,
10820
- strictMode,
10821
- relationHints,
10822
- txAdapter,
10823
- schemaName,
10824
- dialectCapabilities,
10825
- schemaDefinition,
10826
- globalPlanOptions,
10827
- defaultFilters,
10828
- hookStore,
10829
- onHookError,
10830
- true,
10831
- // inTransaction
10832
- tablesProxy
10833
- );
10834
- return fn2(txOrm);
10835
- });
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
+ }
10836
10632
  },
10837
10633
  // =====================================================================
10838
10634
  // Raw SQL Execution (DX-027)
@@ -10911,12 +10707,20 @@ function createOrmInstance(model, strictMode, relationHints, adapter, schemaName
10911
10707
  "executeDDL() requires an adapter that supports DDL execution."
10912
10708
  );
10913
10709
  }
10710
+ if (options?.concurrently) {
10711
+ assertOutsideTransaction(
10712
+ adapter,
10713
+ "dropIndex",
10714
+ "DROP INDEX CONCURRENTLY"
10715
+ );
10716
+ }
10914
10717
  validateIdentifier(name, "index");
10915
10718
  const sc = options?.schema ?? schemaName;
10916
10719
  if (sc) {
10917
10720
  validateIdentifier(sc, "schema");
10918
10721
  }
10919
- 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) : (() => {
10920
10724
  const parts = ["DROP INDEX"];
10921
10725
  if (options?.concurrently) parts.push("CONCURRENTLY");
10922
10726
  if (options?.ifExists) parts.push("IF EXISTS");
@@ -11056,729 +10860,6 @@ function rangeContainedBy(fieldOrColumn, valueOrRange, rangeType = "daterange")
11056
10860
  };
11057
10861
  }
11058
10862
 
11059
- // src/dx/schema-bridge.ts
11060
- import { buildRelationKeyFields, toColumnList as toColumnList3 } from "@dbsp/types";
11061
- import * as v from "valibot";
11062
- function normalizeReferenceSchema2(schemaName) {
11063
- if (schemaName == null) return void 0;
11064
- const t = schemaName.trim();
11065
- return t.length > 0 ? t : void 0;
11066
- }
11067
- function hasExternalSchema3(schemaName) {
11068
- return normalizeReferenceSchema2(schemaName) !== void 0;
11069
- }
11070
- function generatedTypeToColumnType(genType) {
11071
- switch (genType) {
11072
- case "string":
11073
- case "text":
11074
- return "string";
11075
- case "number":
11076
- case "decimal":
11077
- return "number";
11078
- case "integer":
11079
- return "integer";
11080
- case "bigint":
11081
- return "bigint";
11082
- case "boolean":
11083
- return "boolean";
11084
- case "date":
11085
- return "date";
11086
- case "timestamp":
11087
- case "datetime":
11088
- return "datetime";
11089
- case "json":
11090
- return "json";
11091
- case "jsonb":
11092
- return "jsonb";
11093
- case "time":
11094
- return "time";
11095
- case "uuid":
11096
- return "uuid";
11097
- case "daterange":
11098
- return "daterange";
11099
- case "tstzrange":
11100
- return "tstzrange";
11101
- case "int4range":
11102
- return "int4range";
11103
- case "tsrange":
11104
- return "tsrange";
11105
- case "int8range":
11106
- return "int8range";
11107
- case "numrange":
11108
- return "numrange";
11109
- }
11110
- }
11111
- function mapRelationType2(kind) {
11112
- switch (kind) {
11113
- case "belongsTo":
11114
- return "belongsTo";
11115
- case "hasMany":
11116
- return "hasMany";
11117
- case "manyToMany":
11118
- return "belongsToMany";
11119
- }
11120
- }
11121
- function sourceTableFromQualifiedName(qualifiedName) {
11122
- const dotIndex = qualifiedName.indexOf(".");
11123
- return dotIndex > 0 ? qualifiedName.slice(0, dotIndex) : qualifiedName;
11124
- }
11125
- function relationNameFromQualifiedName(qualifiedName) {
11126
- const dotIndex = qualifiedName.indexOf(".");
11127
- return dotIndex > 0 ? qualifiedName.slice(dotIndex + 1) : qualifiedName;
11128
- }
11129
- function columnListsEqual(left, right) {
11130
- const leftColumns = toColumnList3(left);
11131
- const rightColumns = toColumnList3(right);
11132
- return leftColumns.length === rightColumns.length && leftColumns.every((column, index) => column === rightColumns[index]);
11133
- }
11134
- function generatedReferencedColumns(key) {
11135
- const columns = toColumnList3(key);
11136
- return columns.length > 0 ? columns : ["id"];
11137
- }
11138
- function findRelationForeignKey(sourceTable, genRelation, tables) {
11139
- switch (genRelation.kind) {
11140
- case "belongsTo":
11141
- return tables.get(sourceTable)?.foreignKeys.find(
11142
- (fk) => !hasExternalSchema3(fk.references.schema) && fk.references.table === genRelation.target && columnListsEqual(fk.columns, genRelation.foreignKey)
11143
- );
11144
- case "hasMany":
11145
- return tables.get(genRelation.target)?.foreignKeys.find(
11146
- (fk) => !hasExternalSchema3(fk.references.schema) && fk.references.table === sourceTable && columnListsEqual(fk.columns, genRelation.foreignKey)
11147
- );
11148
- case "manyToMany":
11149
- return void 0;
11150
- }
11151
- }
11152
- function isGeneratedTableWithConfig(table) {
11153
- const columns = table.columns;
11154
- return typeof columns === "object" && columns !== null && typeof columns.type !== "string";
11155
- }
11156
- function buildTableIRFromDefinition(tableName, genTable, fkAutoIndex) {
11157
- const columns = [];
11158
- const foreignKeys = [];
11159
- const indexes = [];
11160
- const primaryKeys = [];
11161
- const tableColumns = isGeneratedTableWithConfig(genTable) ? genTable.columns : genTable;
11162
- const indexedColumns = /* @__PURE__ */ new Set();
11163
- for (const [colName, colDef] of Object.entries(tableColumns)) {
11164
- const col2 = {
11165
- name: colName,
11166
- type: generatedTypeToColumnType(colDef.type),
11167
- nullable: colDef.nullable ?? false,
11168
- default: colDef.default
11169
- };
11170
- if (colDef.unique !== void 0) {
11171
- col2.unique = colDef.unique;
11172
- }
11173
- if (colDef.autoIncrement !== void 0) {
11174
- col2.autoIncrement = colDef.autoIncrement;
11175
- }
11176
- columns.push(col2);
11177
- if (colDef.primaryKey) {
11178
- primaryKeys.push(colName);
11179
- }
11180
- if (colDef.references) {
11181
- const externalSchema = normalizeReferenceSchema2(colDef.references.schema);
11182
- const fk = {
11183
- columns: [colName],
11184
- references: {
11185
- table: colDef.references.table,
11186
- columns: [colDef.references.column ?? "id"],
11187
- ...externalSchema !== void 0 ? { schema: externalSchema } : {}
11188
- }
11189
- };
11190
- if (colDef.references.onDelete) {
11191
- fk.onDelete = colDef.references.onDelete;
11192
- }
11193
- foreignKeys.push(fk);
11194
- }
11195
- if (colDef.index) {
11196
- const indexName = typeof colDef.index === "string" ? colDef.index : `idx_${tableName}_${colName}`;
11197
- indexes.push({
11198
- name: indexName,
11199
- columns: [colName],
11200
- unique: false
11201
- });
11202
- indexedColumns.add(colName);
11203
- }
11204
- if (fkAutoIndex && colDef.references && !colDef.index) {
11205
- indexes.push({
11206
- name: `idx_${tableName}_${colName}`,
11207
- columns: [colName],
11208
- unique: false
11209
- });
11210
- indexedColumns.add(colName);
11211
- }
11212
- }
11213
- const pseudoColumns = [];
11214
- for (const fk of foreignKeys) {
11215
- const fkColumn = fk.columns[0];
11216
- const targetColumn = fk.references.columns[0];
11217
- if (fk.references.table === tableName && !hasExternalSchema3(fk.references.schema) && fkColumn !== void 0 && targetColumn !== void 0) {
11218
- const colDef = tableColumns[fkColumn];
11219
- const inferredName = fkColumn.endsWith("Id") ? fkColumn.slice(0, -2) : "parent";
11220
- const parentRole = colDef?.references?.parentRole ?? inferredName;
11221
- const childRole = colDef?.references?.childRole ?? (parentRole === "parent" ? "children" : `${parentRole}s`);
11222
- pseudoColumns.push(
11223
- createPseudoColumnMetadata(
11224
- tableName,
11225
- fkColumn,
11226
- targetColumn,
11227
- parentRole,
11228
- childRole
11229
- )
11230
- );
11231
- }
11232
- }
11233
- let primaryKey;
11234
- const configuredPrimaryKey = isGeneratedTableWithConfig(genTable) ? genTable.primaryKey : void 0;
11235
- if (configuredPrimaryKey !== void 0) {
11236
- primaryKey = configuredPrimaryKey;
11237
- } else if (primaryKeys.length > 0) {
11238
- primaryKey = primaryKeys.length === 1 ? primaryKeys[0] : primaryKeys;
11239
- } else {
11240
- const fkColumns = foreignKeys.flatMap((fk) => fk.columns);
11241
- if (fkColumns.length > 0) {
11242
- primaryKey = fkColumns.length === 1 ? fkColumns[0] : fkColumns;
11243
- } else {
11244
- const hasId = columns.some((c) => c.name === "id");
11245
- primaryKey = hasId ? "id" : void 0;
11246
- }
11247
- }
11248
- if (isGeneratedTableWithConfig(genTable)) {
11249
- for (const fk of genTable.foreignKeys ?? []) {
11250
- const externalSchema = normalizeReferenceSchema2(fk.references.schema);
11251
- const foreignKey = {
11252
- columns: [...fk.columns],
11253
- references: {
11254
- table: fk.references.table,
11255
- columns: [...fk.references.columns],
11256
- ...externalSchema !== void 0 ? { schema: externalSchema } : {}
11257
- }
11258
- };
11259
- if (fk.onDelete) foreignKey.onDelete = fk.onDelete;
11260
- if (fk.onUpdate) foreignKey.onUpdate = fk.onUpdate;
11261
- foreignKeys.push(foreignKey);
11262
- }
11263
- for (const index of genTable.indexes ?? []) {
11264
- indexes.push({
11265
- columns: [...index.columns],
11266
- unique: index.unique ?? false,
11267
- ...index.name !== void 0 && { name: index.name }
11268
- });
11269
- }
11270
- }
11271
- const frozenColumns = Object.freeze(columns);
11272
- return Object.freeze({
11273
- name: tableName,
11274
- columns: frozenColumns,
11275
- ...primaryKey !== void 0 ? { primaryKey } : {},
11276
- foreignKeys: Object.freeze(foreignKeys),
11277
- indexes: Object.freeze(indexes),
11278
- ...pseudoColumns.length > 0 && {
11279
- pseudoColumns: Object.freeze(pseudoColumns)
11280
- }
11281
- });
11282
- }
11283
- function buildRelationIR(qualifiedName, genRelation, hints, relationFk) {
11284
- const sourceTable = sourceTableFromQualifiedName(qualifiedName);
11285
- const relationName = relationNameFromQualifiedName(qualifiedName);
11286
- const hint = hints[qualifiedName];
11287
- const relCardinality = genRelation.kind === "hasMany" ? genRelation.cardinality : void 0;
11288
- const cardinality = hint?.cardinality === "one" ? "one" : relCardinality === "one" ? "one" : genRelation.kind === "belongsTo" ? "one" : "many";
11289
- const optionality = genRelation.kind === "belongsTo" ? "optional" : "optional";
11290
- let relationType = mapRelationType2(genRelation.kind);
11291
- if (genRelation.kind === "hasMany" && cardinality === "one") {
11292
- relationType = "hasOne";
11293
- }
11294
- const baseRelation = {
11295
- name: relationName,
11296
- source: sourceTable,
11297
- target: genRelation.target,
11298
- type: relationType,
11299
- cardinality,
11300
- optionality,
11301
- includeStrategy: genRelation.includeStrategy ?? "auto",
11302
- filterStrategy: hint?.defaultStrategy ?? "auto",
11303
- joinDefault: "auto"
11304
- };
11305
- switch (genRelation.kind) {
11306
- case "belongsTo":
11307
- return {
11308
- ...baseRelation,
11309
- ...buildRelationKeyFields(
11310
- relationFk ?? {
11311
- columns: genRelation.foreignKey,
11312
- references: {
11313
- table: genRelation.target,
11314
- columns: generatedReferencedColumns(genRelation.targetKey)
11315
- }
11316
- },
11317
- "belongsTo",
11318
- {
11319
- foreignKeyShape: genRelation.foreignKey,
11320
- ...genRelation.targetKey !== void 0 ? { referencedKeyShape: genRelation.targetKey } : {}
11321
- }
11322
- )
11323
- };
11324
- case "hasMany":
11325
- return {
11326
- ...baseRelation,
11327
- ...buildRelationKeyFields(
11328
- relationFk ?? {
11329
- columns: genRelation.foreignKey,
11330
- references: {
11331
- table: sourceTable,
11332
- columns: generatedReferencedColumns(genRelation.sourceKey)
11333
- }
11334
- },
11335
- "inverse",
11336
- {
11337
- foreignKeyShape: genRelation.foreignKey,
11338
- ...genRelation.sourceKey !== void 0 ? { referencedKeyShape: genRelation.sourceKey } : {}
11339
- }
11340
- )
11341
- };
11342
- case "manyToMany":
11343
- return {
11344
- ...baseRelation,
11345
- through: genRelation.through,
11346
- foreignKey: genRelation.sourceFk,
11347
- otherKey: genRelation.targetFk
11348
- };
11349
- }
11350
- }
11351
- function buildModelFromSchema(schema2) {
11352
- const tables = /* @__PURE__ */ new Map();
11353
- const relations = /* @__PURE__ */ new Map();
11354
- const fkAutoIndex = schema2.conventions.fkAutoIndex;
11355
- for (const [tableName, genTable] of Object.entries(schema2.tables)) {
11356
- tables.set(
11357
- tableName,
11358
- buildTableIRFromDefinition(tableName, genTable, fkAutoIndex)
11359
- );
11360
- }
11361
- for (const [qualifiedName, genRelation] of Object.entries(schema2.relations)) {
11362
- const sourceTable = sourceTableFromQualifiedName(qualifiedName);
11363
- relations.set(
11364
- qualifiedName,
11365
- buildRelationIR(
11366
- qualifiedName,
11367
- genRelation,
11368
- schema2.hints,
11369
- findRelationForeignKey(sourceTable, genRelation, tables)
11370
- )
11371
- );
11372
- }
11373
- return new ModelIRImpl(tables, relations);
11374
- }
11375
- function buildModelFromResolvedSchema(schema2) {
11376
- const generatedSchema = assertResolvedSchemaToGeneratedSchema(schema2);
11377
- return buildModelFromSchema(generatedSchema);
11378
- }
11379
- function isGeneratedSchema(value) {
11380
- if (typeof value !== "object" || value === null) {
11381
- return false;
11382
- }
11383
- const obj = value;
11384
- return typeof obj.tables === "object" && obj.tables !== null && typeof obj.relations === "object" && obj.relations !== null && typeof obj.hints === "object" && obj.hints !== null && typeof obj.conventions === "object" && obj.conventions !== null;
11385
- }
11386
- var RESOLVED_SCHEMA_ONLY_TYPES = /* @__PURE__ */ new Set(["time", "jsonb"]);
11387
- var GENERATED_SCHEMA_ONLY_TYPES = /* @__PURE__ */ new Set(["number", "datetime"]);
11388
- function hasResolvedSchemaOnlyTypes(tables) {
11389
- for (const table of Object.values(tables)) {
11390
- for (const column of Object.values(table)) {
11391
- if (column?.type && RESOLVED_SCHEMA_ONLY_TYPES.has(column.type)) {
11392
- return true;
11393
- }
11394
- }
11395
- }
11396
- return false;
11397
- }
11398
- function hasGeneratedSchemaOnlyTypes(tables) {
11399
- for (const table of Object.values(tables)) {
11400
- for (const column of Object.values(table)) {
11401
- if (column?.type && GENERATED_SCHEMA_ONLY_TYPES.has(column.type)) {
11402
- return true;
11403
- }
11404
- }
11405
- }
11406
- return false;
11407
- }
11408
- function isResolvedSchema(value) {
11409
- if (!isGeneratedSchema(value)) {
11410
- return false;
11411
- }
11412
- if (hasResolvedSchemaOnlyTypes(
11413
- value.tables
11414
- )) {
11415
- return true;
11416
- }
11417
- if (hasGeneratedSchemaOnlyTypes(
11418
- value.tables
11419
- )) {
11420
- return false;
11421
- }
11422
- return false;
11423
- }
11424
- function normalizeSchema(input) {
11425
- if (!isGeneratedSchema(input)) {
11426
- throw new Error(
11427
- "Invalid schema: must have tables, relations, hints, and conventions properties"
11428
- );
11429
- }
11430
- if (isResolvedSchema(input)) {
11431
- const result = resolvedSchemaToGeneratedSchema(input);
11432
- if (!result.success) {
11433
- const messages = result.errors.map((e) => e.message).join(", ");
11434
- throw new Error(`Schema conversion failed: ${messages}`);
11435
- }
11436
- return result.schema;
11437
- }
11438
- return input;
11439
- }
11440
- var SchemaColumnTypeSchema = v.picklist([
11441
- "uuid",
11442
- "string",
11443
- "text",
11444
- "integer",
11445
- "bigint",
11446
- "decimal",
11447
- "boolean",
11448
- "timestamp",
11449
- "date",
11450
- "time",
11451
- "json",
11452
- "jsonb",
11453
- "daterange",
11454
- "tstzrange",
11455
- "int4range",
11456
- "tsrange",
11457
- "int8range",
11458
- "numrange"
11459
- ]);
11460
- var PROTO_POLLUTION_KEYS = ["__proto__", "constructor", "prototype"];
11461
- function safeRecord(valueSchema) {
11462
- return v.pipe(
11463
- v.unknown(),
11464
- v.check((input) => {
11465
- if (typeof input !== "object" || input === null) return true;
11466
- return !Object.keys(input).some(
11467
- (k) => PROTO_POLLUTION_KEYS.includes(k)
11468
- );
11469
- }, "Schema keys must not include prototype-pollution names (__proto__, constructor, prototype)"),
11470
- v.record(v.string(), valueSchema)
11471
- );
11472
- }
11473
- var OptionalReferenceSchemaNameSchema = v.optional(
11474
- v.pipe(
11475
- v.string(),
11476
- v.transform((schemaName) => normalizeReferenceSchema2(schemaName))
11477
- )
11478
- );
11479
- var ForeignKeyActionValues = [
11480
- "CASCADE",
11481
- "SET NULL",
11482
- "SET DEFAULT",
11483
- "RESTRICT",
11484
- "NO ACTION"
11485
- ];
11486
- var ForeignKeyActionSchema = v.picklist(ForeignKeyActionValues);
11487
- var ForeignKeyReferenceSchema = v.object({
11488
- schema: OptionalReferenceSchemaNameSchema,
11489
- table: v.string(),
11490
- column: v.optional(v.string()),
11491
- onDelete: v.optional(ForeignKeyActionSchema),
11492
- index: v.optional(v.boolean()),
11493
- parentRole: v.optional(v.string()),
11494
- childRole: v.optional(v.string())
11495
- });
11496
- var StringOrStringArraySchema = v.union([v.string(), v.array(v.string())]);
11497
- var ColumnDefinitionSchema = v.object({
11498
- type: SchemaColumnTypeSchema,
11499
- primaryKey: v.optional(v.boolean()),
11500
- nullable: v.optional(v.boolean()),
11501
- unique: v.optional(v.boolean()),
11502
- autoIncrement: v.optional(v.boolean()),
11503
- default: v.optional(v.union([v.string(), v.number(), v.boolean()])),
11504
- references: v.optional(ForeignKeyReferenceSchema),
11505
- index: v.optional(v.union([v.boolean(), v.string()]))
11506
- });
11507
- var FlatTableDefinitionSchema = safeRecord(ColumnDefinitionSchema);
11508
- var TableDefWithConfigSchema = v.object({
11509
- columns: FlatTableDefinitionSchema,
11510
- primaryKey: v.optional(StringOrStringArraySchema),
11511
- foreignKeys: v.optional(
11512
- v.array(
11513
- v.object({
11514
- columns: v.array(v.string()),
11515
- references: v.object({
11516
- schema: OptionalReferenceSchemaNameSchema,
11517
- table: v.string(),
11518
- columns: v.array(v.string())
11519
- }),
11520
- onDelete: v.optional(ForeignKeyActionSchema),
11521
- onUpdate: v.optional(ForeignKeyActionSchema)
11522
- })
11523
- )
11524
- ),
11525
- indexes: v.optional(
11526
- v.array(
11527
- v.object({
11528
- columns: v.array(v.string()),
11529
- unique: v.optional(v.boolean()),
11530
- name: v.optional(v.string())
11531
- })
11532
- )
11533
- )
11534
- });
11535
- var TableDefinitionSchema = v.union([
11536
- TableDefWithConfigSchema,
11537
- FlatTableDefinitionSchema
11538
- ]);
11539
- var TablesDefinitionSchema = safeRecord(TableDefinitionSchema);
11540
- var IncludeStrategySchema = v.optional(
11541
- v.picklist(["join", "subquery", "cte", "lateral", "json_agg", "auto"])
11542
- );
11543
- var BelongsToRelationSchema = v.object({
11544
- kind: v.literal("belongsTo"),
11545
- target: v.string(),
11546
- foreignKey: StringOrStringArraySchema,
11547
- targetKey: v.optional(StringOrStringArraySchema),
11548
- includeStrategy: IncludeStrategySchema
11549
- });
11550
- var HasManyRelationSchema = v.object({
11551
- kind: v.literal("hasMany"),
11552
- target: v.string(),
11553
- foreignKey: StringOrStringArraySchema,
11554
- sourceKey: v.optional(StringOrStringArraySchema),
11555
- includeStrategy: IncludeStrategySchema
11556
- });
11557
- var ManyToManyRelationSchema = v.object({
11558
- kind: v.literal("manyToMany"),
11559
- target: v.string(),
11560
- through: v.string(),
11561
- sourceFk: v.string(),
11562
- targetFk: v.string(),
11563
- includeStrategy: IncludeStrategySchema
11564
- });
11565
- var RelationDefinitionSchema = v.variant("kind", [
11566
- BelongsToRelationSchema,
11567
- HasManyRelationSchema,
11568
- ManyToManyRelationSchema
11569
- ]);
11570
- var RelationsDefinitionSchema = safeRecord(RelationDefinitionSchema);
11571
- var HintDefinitionSchema = v.object({
11572
- defaultStrategy: v.optional(v.picklist(["exists", "join"])),
11573
- cardinality: v.optional(v.picklist(["one", "many"]))
11574
- });
11575
- var HintsDefinitionSchema = safeRecord(HintDefinitionSchema);
11576
- var ConventionsDefinitionSchema = v.object({
11577
- fkPattern: v.string(),
11578
- pluralize: v.boolean(),
11579
- timestamps: v.array(v.string()),
11580
- fkAutoIndex: v.boolean()
11581
- });
11582
- var IndexDefinitionSchema = v.object({
11583
- columns: v.array(v.string()),
11584
- unique: v.optional(v.boolean()),
11585
- name: v.optional(v.string())
11586
- });
11587
- var IndexesDefinitionSchema = safeRecord(v.array(IndexDefinitionSchema));
11588
- var ResolvedSchemaValidation = v.object({
11589
- tables: TablesDefinitionSchema,
11590
- relations: RelationsDefinitionSchema,
11591
- hints: HintsDefinitionSchema,
11592
- conventions: ConventionsDefinitionSchema,
11593
- indexes: v.optional(IndexesDefinitionSchema)
11594
- });
11595
- function mapSchemaColumnType(schemaType) {
11596
- switch (schemaType) {
11597
- case "uuid":
11598
- return "uuid";
11599
- case "string":
11600
- return "string";
11601
- case "text":
11602
- return "text";
11603
- case "integer":
11604
- return "integer";
11605
- case "bigint":
11606
- return "bigint";
11607
- case "decimal":
11608
- return "decimal";
11609
- case "boolean":
11610
- return "boolean";
11611
- case "timestamp":
11612
- return "timestamp";
11613
- case "date":
11614
- return "date";
11615
- case "time":
11616
- return "time";
11617
- case "json":
11618
- return "json";
11619
- case "jsonb":
11620
- return "jsonb";
11621
- case "daterange":
11622
- return "daterange";
11623
- case "tstzrange":
11624
- return "tstzrange";
11625
- case "int4range":
11626
- return "int4range";
11627
- case "tsrange":
11628
- return "tsrange";
11629
- case "int8range":
11630
- return "int8range";
11631
- case "numrange":
11632
- return "numrange";
11633
- }
11634
- }
11635
- function convertColumn(col2) {
11636
- const result = {
11637
- type: mapSchemaColumnType(col2.type)
11638
- };
11639
- if (col2.primaryKey !== void 0) {
11640
- result.primaryKey = col2.primaryKey;
11641
- }
11642
- if (col2.nullable !== void 0) {
11643
- result.nullable = col2.nullable;
11644
- }
11645
- if (col2.unique !== void 0) {
11646
- result.unique = col2.unique;
11647
- }
11648
- if (col2.autoIncrement !== void 0) {
11649
- result.autoIncrement = col2.autoIncrement;
11650
- }
11651
- if (col2.default !== void 0) {
11652
- result.default = col2.default;
11653
- }
11654
- if (col2.references) {
11655
- const externalSchema = normalizeReferenceSchema2(col2.references.schema);
11656
- result.references = {
11657
- table: col2.references.table,
11658
- ...externalSchema !== void 0 ? { schema: externalSchema } : {},
11659
- ...col2.references.column !== void 0 ? { column: col2.references.column } : {},
11660
- ...col2.references.onDelete ? { onDelete: col2.references.onDelete } : {},
11661
- ...col2.references.index !== void 0 ? { index: col2.references.index } : {},
11662
- ...col2.references.parentRole ? { parentRole: col2.references.parentRole } : {},
11663
- ...col2.references.childRole ? { childRole: col2.references.childRole } : {}
11664
- };
11665
- }
11666
- return result;
11667
- }
11668
- function convertRelation(rel) {
11669
- switch (rel.kind) {
11670
- case "belongsTo": {
11671
- const result = {
11672
- kind: "belongsTo",
11673
- target: rel.target,
11674
- foreignKey: rel.foreignKey
11675
- };
11676
- if (rel.targetKey !== void 0) {
11677
- result.targetKey = rel.targetKey;
11678
- }
11679
- if (rel.includeStrategy !== void 0) {
11680
- result.includeStrategy = rel.includeStrategy;
11681
- }
11682
- return result;
11683
- }
11684
- case "hasMany": {
11685
- const result = {
11686
- kind: "hasMany",
11687
- target: rel.target,
11688
- foreignKey: rel.foreignKey
11689
- };
11690
- if (rel.sourceKey !== void 0) {
11691
- result.sourceKey = rel.sourceKey;
11692
- }
11693
- if (rel.includeStrategy !== void 0) {
11694
- result.includeStrategy = rel.includeStrategy;
11695
- }
11696
- return result;
11697
- }
11698
- case "manyToMany": {
11699
- const result = {
11700
- kind: "manyToMany",
11701
- target: rel.target,
11702
- through: rel.through,
11703
- sourceFk: rel.sourceFk,
11704
- targetFk: rel.targetFk
11705
- };
11706
- if (rel.includeStrategy !== void 0) {
11707
- result.includeStrategy = rel.includeStrategy;
11708
- }
11709
- return result;
11710
- }
11711
- }
11712
- }
11713
- function convertHint(hint) {
11714
- const result = {};
11715
- if (hint.defaultStrategy !== void 0) {
11716
- result.defaultStrategy = hint.defaultStrategy;
11717
- }
11718
- if (hint.cardinality !== void 0) {
11719
- result.cardinality = hint.cardinality;
11720
- }
11721
- return result;
11722
- }
11723
- function resolvedSchemaToGeneratedSchema(input) {
11724
- const parseResult = v.safeParse(ResolvedSchemaValidation, input);
11725
- if (!parseResult.success) {
11726
- return {
11727
- success: false,
11728
- errors: parseResult.issues
11729
- };
11730
- }
11731
- const validated = parseResult.output;
11732
- const tables = /* @__PURE__ */ Object.create(null);
11733
- for (const [tableName, tableDef] of Object.entries(validated.tables)) {
11734
- const convertedTable = /* @__PURE__ */ Object.create(null);
11735
- const tableObj = tableDef;
11736
- const isWithConfig = Array.isArray(tableObj.primaryKey);
11737
- const columns = isWithConfig ? tableObj.columns : tableObj;
11738
- for (const [colName, colDef] of Object.entries(columns)) {
11739
- convertedTable[colName] = convertColumn(
11740
- colDef
11741
- );
11742
- }
11743
- tables[tableName] = convertedTable;
11744
- }
11745
- const relations = /* @__PURE__ */ Object.create(null);
11746
- for (const [relName, relDef] of Object.entries(validated.relations)) {
11747
- relations[relName] = convertRelation(relDef);
11748
- }
11749
- const hints = /* @__PURE__ */ Object.create(null);
11750
- for (const [hintName, hintDef] of Object.entries(validated.hints)) {
11751
- hints[hintName] = convertHint(hintDef);
11752
- }
11753
- const conventions = {
11754
- fkPattern: validated.conventions.fkPattern,
11755
- pluralize: validated.conventions.pluralize,
11756
- timestamps: validated.conventions.timestamps,
11757
- fkAutoIndex: validated.conventions.fkAutoIndex
11758
- };
11759
- return {
11760
- success: true,
11761
- schema: {
11762
- tables,
11763
- relations,
11764
- hints,
11765
- conventions
11766
- }
11767
- };
11768
- }
11769
- function assertResolvedSchemaToGeneratedSchema(input) {
11770
- const result = resolvedSchemaToGeneratedSchema(input);
11771
- if (!result.success) {
11772
- const messages = result.errors.map((e) => {
11773
- const path = e.path?.map((p) => p.key).join(".") || "root";
11774
- return `[${path}] ${e.message} (expected: ${e.expected}, received: ${e.received})`;
11775
- }).join("\n");
11776
- throw new Error(`Schema validation failed:
11777
- ${messages}`);
11778
- }
11779
- return result.schema;
11780
- }
11781
-
11782
10863
  // src/dialects/index.ts
11783
10864
  var POSTGRESQL_CAPABILITIES = {
11784
10865
  name: "postgresql",
@@ -13159,7 +12240,6 @@ export {
13159
12240
  ColumnNotFoundError,
13160
12241
  CteBuilder,
13161
12242
  CteQueryBuilder,
13162
- DEFAULT_CONVENTIONS,
13163
12243
  DEFAULT_FEATURE_CHECKERS,
13164
12244
  DUCKDB_CAPABILITIES,
13165
12245
  DeleteBuilder,
@@ -13182,12 +12262,11 @@ export {
13182
12262
  RawCteQueryBuilder,
13183
12263
  RecursiveShapeMismatchError,
13184
12264
  RelationNotFoundError,
13185
- ResolvedSchemaValidation,
13186
12265
  ResultHydrator,
13187
12266
  SQLITE_CAPABILITIES,
13188
12267
  SQL_RAW_MARKER,
13189
12268
  SchemaValidationError as SchemaError,
13190
- SchemaValidationError2 as SchemaValidationError,
12269
+ SchemaValidationError,
13191
12270
  SubqueryBuilder,
13192
12271
  SubqueryExpression,
13193
12272
  TABLE_META,
@@ -13226,7 +12305,6 @@ export {
13226
12305
  assertParamsLength,
13227
12306
  assertParamsType,
13228
12307
  assertParamsValue,
13229
- assertResolvedSchemaToGeneratedSchema,
13230
12308
  assertSQLColumn,
13231
12309
  assertSQLEquals,
13232
12310
  assertSQLJoin,
@@ -13234,8 +12312,6 @@ export {
13234
12312
  assertSuccess,
13235
12313
  assertTypeSupported,
13236
12314
  batchValues,
13237
- buildModelFromResolvedSchema,
13238
- buildModelFromSchema,
13239
12315
  capitalize,
13240
12316
  caseWhen,
13241
12317
  cast,
@@ -13257,11 +12333,8 @@ export {
13257
12333
  decapitalize,
13258
12334
  defaultLogger,
13259
12335
  defineModel,
13260
- defineSchema,
13261
12336
  denseRank,
13262
12337
  deriveRelationPathFromIntentPath,
13263
- detectForeignKeys,
13264
- detectManyToMany,
13265
12338
  distinct,
13266
12339
  emitWarning,
13267
12340
  eq,
@@ -13284,13 +12357,11 @@ export {
13284
12357
  inArray,
13285
12358
  inSubquery,
13286
12359
  inferForeignKey,
13287
- inferRelationsFromSchema,
13288
12360
  export_isAdjacencyTraversal as isAdjacencyTraversal,
13289
12361
  export_isAggregateWindowFunction as isAggregateWindowFunction,
13290
12362
  isAliasedColumn,
13291
12363
  isAllColumns,
13292
12364
  isBatchValuesRef,
13293
- isBelongsTo,
13294
12365
  isCardinalityShorthand,
13295
12366
  export_isCoalesceExpression as isCoalesceExpression,
13296
12367
  export_isColumnAliasExpression as isColumnAliasExpression,
@@ -13301,11 +12372,8 @@ export {
13301
12372
  isDistinctFrom,
13302
12373
  export_isEdgeTableTraversal as isEdgeTableTraversal,
13303
12374
  isExpressionSpec,
13304
- isGeneratedSchema,
13305
- isHasMany,
13306
12375
  export_isInsertIntent as isInsertIntent,
13307
12376
  isKnownDialect,
13308
- isManyToMany,
13309
12377
  export_isMutationIntent as isMutationIntent,
13310
12378
  isNotNull,
13311
12379
  isNull,
@@ -13320,7 +12388,6 @@ export {
13320
12388
  isRelationObjectDef,
13321
12389
  isRelationRef,
13322
12390
  isRelationTupleDef,
13323
- isResolvedSchema,
13324
12391
  export_isSelectAggregate as isSelectAggregate,
13325
12392
  export_isSelectAll as isSelectAll,
13326
12393
  export_isSelectFields as isSelectFields,
@@ -13360,7 +12427,6 @@ export {
13360
12427
  neq,
13361
12428
  none,
13362
12429
  normalizeSQL,
13363
- normalizeSchema,
13364
12430
  not,
13365
12431
  notExists,
13366
12432
  nqlRaw,
@@ -13393,7 +12459,6 @@ export {
13393
12459
  requiresDatabase,
13394
12460
  resetLogger,
13395
12461
  resolveQueryIndex,
13396
- resolvedSchemaToGeneratedSchema,
13397
12462
  rowNumber,
13398
12463
  runAssertions,
13399
12464
  schema,
@@ -13418,6 +12483,7 @@ export {
13418
12483
  validateAssertionBlocks,
13419
12484
  validateRecursiveInclude,
13420
12485
  validateRecursiveShape,
12486
+ validateSchemaIndexOptions,
13421
12487
  validateTypeName,
13422
12488
  wAvg,
13423
12489
  wCount,