@dbsp/core 1.11.1 → 2.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.d.ts +80 -843
- package/dist/index.js +29 -1012
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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";
|
|
@@ -6426,7 +6181,7 @@ function hydrateJsonAggIncludes(results, planReport) {
|
|
|
6426
6181
|
if (typeof row !== "object" || row === null) {
|
|
6427
6182
|
continue;
|
|
6428
6183
|
}
|
|
6429
|
-
const
|
|
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
|
|
6197
|
+
if (snakeJson in record) {
|
|
6443
6198
|
actualColumnName = snakeJson;
|
|
6444
6199
|
break;
|
|
6445
6200
|
}
|
|
6446
|
-
if (camelJson in
|
|
6201
|
+
if (camelJson in record) {
|
|
6447
6202
|
actualColumnName = camelJson;
|
|
6448
6203
|
break;
|
|
6449
6204
|
}
|
|
6450
6205
|
}
|
|
6451
6206
|
if (actualColumnName) {
|
|
6452
|
-
const jsonValue =
|
|
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
|
-
|
|
6472
|
-
delete
|
|
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
|
|
8156
|
+
const record = row;
|
|
8402
8157
|
const valuesByPath = /* @__PURE__ */ new Map();
|
|
8403
|
-
for (const key of Object.keys(
|
|
8158
|
+
for (const key of Object.keys(record)) {
|
|
8404
8159
|
const info = findLongestJoinInfo(key, joinInfos);
|
|
8405
8160
|
if (!info) continue;
|
|
8406
|
-
const value =
|
|
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
|
|
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
|
-
|
|
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((
|
|
8409
|
+
if (values.some((v) => v === void 0 || v === null)) {
|
|
8655
8410
|
return void 0;
|
|
8656
8411
|
}
|
|
8657
|
-
const parts = values.map((
|
|
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((
|
|
8427
|
+
return values.some((v) => v === void 0 || v === null) ? void 0 : values;
|
|
8673
8428
|
}
|
|
8674
8429
|
};
|
|
8675
8430
|
|
|
@@ -10382,7 +10137,7 @@ function generateCreateIndexSQL(tableName, schemaName, opts) {
|
|
|
10382
10137
|
parts.push("NULLS NOT DISTINCT");
|
|
10383
10138
|
}
|
|
10384
10139
|
if (opts.with && Object.keys(opts.with).length > 0) {
|
|
10385
|
-
const withClauses = Object.entries(opts.with).map(([k,
|
|
10140
|
+
const withClauses = Object.entries(opts.with).map(([k, v]) => `${k} = ${v}`).join(", ");
|
|
10386
10141
|
parts.push(`WITH (${withClauses})`);
|
|
10387
10142
|
}
|
|
10388
10143
|
if (opts.where) parts.push(`WHERE ${opts.where}`);
|
|
@@ -11056,729 +10811,6 @@ function rangeContainedBy(fieldOrColumn, valueOrRange, rangeType = "daterange")
|
|
|
11056
10811
|
};
|
|
11057
10812
|
}
|
|
11058
10813
|
|
|
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
10814
|
// src/dialects/index.ts
|
|
11783
10815
|
var POSTGRESQL_CAPABILITIES = {
|
|
11784
10816
|
name: "postgresql",
|
|
@@ -13159,7 +12191,6 @@ export {
|
|
|
13159
12191
|
ColumnNotFoundError,
|
|
13160
12192
|
CteBuilder,
|
|
13161
12193
|
CteQueryBuilder,
|
|
13162
|
-
DEFAULT_CONVENTIONS,
|
|
13163
12194
|
DEFAULT_FEATURE_CHECKERS,
|
|
13164
12195
|
DUCKDB_CAPABILITIES,
|
|
13165
12196
|
DeleteBuilder,
|
|
@@ -13182,12 +12213,11 @@ export {
|
|
|
13182
12213
|
RawCteQueryBuilder,
|
|
13183
12214
|
RecursiveShapeMismatchError,
|
|
13184
12215
|
RelationNotFoundError,
|
|
13185
|
-
ResolvedSchemaValidation,
|
|
13186
12216
|
ResultHydrator,
|
|
13187
12217
|
SQLITE_CAPABILITIES,
|
|
13188
12218
|
SQL_RAW_MARKER,
|
|
13189
12219
|
SchemaValidationError as SchemaError,
|
|
13190
|
-
|
|
12220
|
+
SchemaValidationError,
|
|
13191
12221
|
SubqueryBuilder,
|
|
13192
12222
|
SubqueryExpression,
|
|
13193
12223
|
TABLE_META,
|
|
@@ -13226,7 +12256,6 @@ export {
|
|
|
13226
12256
|
assertParamsLength,
|
|
13227
12257
|
assertParamsType,
|
|
13228
12258
|
assertParamsValue,
|
|
13229
|
-
assertResolvedSchemaToGeneratedSchema,
|
|
13230
12259
|
assertSQLColumn,
|
|
13231
12260
|
assertSQLEquals,
|
|
13232
12261
|
assertSQLJoin,
|
|
@@ -13234,8 +12263,6 @@ export {
|
|
|
13234
12263
|
assertSuccess,
|
|
13235
12264
|
assertTypeSupported,
|
|
13236
12265
|
batchValues,
|
|
13237
|
-
buildModelFromResolvedSchema,
|
|
13238
|
-
buildModelFromSchema,
|
|
13239
12266
|
capitalize,
|
|
13240
12267
|
caseWhen,
|
|
13241
12268
|
cast,
|
|
@@ -13257,11 +12284,8 @@ export {
|
|
|
13257
12284
|
decapitalize,
|
|
13258
12285
|
defaultLogger,
|
|
13259
12286
|
defineModel,
|
|
13260
|
-
defineSchema,
|
|
13261
12287
|
denseRank,
|
|
13262
12288
|
deriveRelationPathFromIntentPath,
|
|
13263
|
-
detectForeignKeys,
|
|
13264
|
-
detectManyToMany,
|
|
13265
12289
|
distinct,
|
|
13266
12290
|
emitWarning,
|
|
13267
12291
|
eq,
|
|
@@ -13284,13 +12308,11 @@ export {
|
|
|
13284
12308
|
inArray,
|
|
13285
12309
|
inSubquery,
|
|
13286
12310
|
inferForeignKey,
|
|
13287
|
-
inferRelationsFromSchema,
|
|
13288
12311
|
export_isAdjacencyTraversal as isAdjacencyTraversal,
|
|
13289
12312
|
export_isAggregateWindowFunction as isAggregateWindowFunction,
|
|
13290
12313
|
isAliasedColumn,
|
|
13291
12314
|
isAllColumns,
|
|
13292
12315
|
isBatchValuesRef,
|
|
13293
|
-
isBelongsTo,
|
|
13294
12316
|
isCardinalityShorthand,
|
|
13295
12317
|
export_isCoalesceExpression as isCoalesceExpression,
|
|
13296
12318
|
export_isColumnAliasExpression as isColumnAliasExpression,
|
|
@@ -13301,11 +12323,8 @@ export {
|
|
|
13301
12323
|
isDistinctFrom,
|
|
13302
12324
|
export_isEdgeTableTraversal as isEdgeTableTraversal,
|
|
13303
12325
|
isExpressionSpec,
|
|
13304
|
-
isGeneratedSchema,
|
|
13305
|
-
isHasMany,
|
|
13306
12326
|
export_isInsertIntent as isInsertIntent,
|
|
13307
12327
|
isKnownDialect,
|
|
13308
|
-
isManyToMany,
|
|
13309
12328
|
export_isMutationIntent as isMutationIntent,
|
|
13310
12329
|
isNotNull,
|
|
13311
12330
|
isNull,
|
|
@@ -13320,7 +12339,6 @@ export {
|
|
|
13320
12339
|
isRelationObjectDef,
|
|
13321
12340
|
isRelationRef,
|
|
13322
12341
|
isRelationTupleDef,
|
|
13323
|
-
isResolvedSchema,
|
|
13324
12342
|
export_isSelectAggregate as isSelectAggregate,
|
|
13325
12343
|
export_isSelectAll as isSelectAll,
|
|
13326
12344
|
export_isSelectFields as isSelectFields,
|
|
@@ -13360,7 +12378,6 @@ export {
|
|
|
13360
12378
|
neq,
|
|
13361
12379
|
none,
|
|
13362
12380
|
normalizeSQL,
|
|
13363
|
-
normalizeSchema,
|
|
13364
12381
|
not,
|
|
13365
12382
|
notExists,
|
|
13366
12383
|
nqlRaw,
|
|
@@ -13393,7 +12410,6 @@ export {
|
|
|
13393
12410
|
requiresDatabase,
|
|
13394
12411
|
resetLogger,
|
|
13395
12412
|
resolveQueryIndex,
|
|
13396
|
-
resolvedSchemaToGeneratedSchema,
|
|
13397
12413
|
rowNumber,
|
|
13398
12414
|
runAssertions,
|
|
13399
12415
|
schema,
|
|
@@ -13418,6 +12434,7 @@ export {
|
|
|
13418
12434
|
validateAssertionBlocks,
|
|
13419
12435
|
validateRecursiveInclude,
|
|
13420
12436
|
validateRecursiveShape,
|
|
12437
|
+
validateSchemaIndexOptions,
|
|
13421
12438
|
validateTypeName,
|
|
13422
12439
|
wAvg,
|
|
13423
12440
|
wCount,
|