@dbsp/core 1.10.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 +91 -838
- package/dist/index.js +152 -1015
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -58,6 +58,9 @@ __reExport(intent_ast_exports, types_star);
|
|
|
58
58
|
import * as types_star from "@dbsp/types";
|
|
59
59
|
|
|
60
60
|
// src/model-impl.ts
|
|
61
|
+
function hasExternalSchema(schemaName) {
|
|
62
|
+
return schemaName != null && schemaName.trim().length > 0;
|
|
63
|
+
}
|
|
61
64
|
var ModelIRImpl = class {
|
|
62
65
|
tables;
|
|
63
66
|
externalTables;
|
|
@@ -178,7 +181,7 @@ var ModelIRImpl = class {
|
|
|
178
181
|
}
|
|
179
182
|
for (const table of this.tables.values()) {
|
|
180
183
|
for (const fk of table.foreignKeys) {
|
|
181
|
-
if (!this.tables.has(fk.references.table) && !this.externalTables.has(fk.references.table)) {
|
|
184
|
+
if (!hasExternalSchema(fk.references.schema) && !this.tables.has(fk.references.table) && !this.externalTables.has(fk.references.table)) {
|
|
182
185
|
errors.push(
|
|
183
186
|
`Table "${table.name}" has FK referencing non-existent table "${fk.references.table}"`
|
|
184
187
|
);
|
|
@@ -623,11 +626,25 @@ function createTablesProxy(model, tableNames, options) {
|
|
|
623
626
|
}
|
|
624
627
|
|
|
625
628
|
// src/dx/schema.ts
|
|
629
|
+
function normalizeReferenceSchema(schemaName) {
|
|
630
|
+
if (schemaName == null) return void 0;
|
|
631
|
+
const t = schemaName.trim();
|
|
632
|
+
return t.length > 0 ? t : void 0;
|
|
633
|
+
}
|
|
634
|
+
function hasExternalSchema2(schemaName) {
|
|
635
|
+
return normalizeReferenceSchema(schemaName) !== void 0;
|
|
636
|
+
}
|
|
637
|
+
function normalizeRefOptions(options) {
|
|
638
|
+
const schemaName = normalizeReferenceSchema(options.schema);
|
|
639
|
+
if (schemaName === options.schema) return options;
|
|
640
|
+
const { schema: _schema, ...rest } = options;
|
|
641
|
+
return schemaName === void 0 ? rest : { ...rest, schema: schemaName };
|
|
642
|
+
}
|
|
626
643
|
function ref(target, options) {
|
|
627
644
|
return {
|
|
628
645
|
__brand: "ref",
|
|
629
646
|
target,
|
|
630
|
-
options: options
|
|
647
|
+
options: options ? normalizeRefOptions(options) : {}
|
|
631
648
|
};
|
|
632
649
|
}
|
|
633
650
|
function isRef(value) {
|
|
@@ -653,6 +670,7 @@ function schema(definition, constraints, options, extras) {
|
|
|
653
670
|
);
|
|
654
671
|
return {
|
|
655
672
|
definition,
|
|
673
|
+
...constraints !== void 0 ? { constraints } : {},
|
|
656
674
|
model,
|
|
657
675
|
tableNames,
|
|
658
676
|
tables,
|
|
@@ -669,6 +687,13 @@ var SchemaValidationError = class extends Error {
|
|
|
669
687
|
table;
|
|
670
688
|
column;
|
|
671
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
|
+
}
|
|
672
697
|
function schemaToModelIR(definition, constraints, extras, options) {
|
|
673
698
|
if (typeof options?.defaultPkColumnName === "string" && options.defaultPkColumnName.trim().length === 0) {
|
|
674
699
|
throw new SchemaValidationError(
|
|
@@ -721,21 +746,21 @@ function validateRefs(definition, tableNames) {
|
|
|
721
746
|
for (const [tableName, tableDef] of Object.entries(definition)) {
|
|
722
747
|
for (const [columnName, columnDef] of Object.entries(tableDef)) {
|
|
723
748
|
if (isRef(columnDef)) {
|
|
724
|
-
if (!tableSet.has(columnDef.target)) {
|
|
749
|
+
if (!hasExternalSchema2(columnDef.options.schema) && !tableSet.has(columnDef.target)) {
|
|
725
750
|
throw new SchemaValidationError(
|
|
726
751
|
`Foreign key '${columnName}' references non-existent table '${columnDef.target}'`,
|
|
727
752
|
tableName,
|
|
728
753
|
columnName
|
|
729
754
|
);
|
|
730
755
|
}
|
|
731
|
-
if (columnDef.target === tableName && !columnDef.options.roles) {
|
|
756
|
+
if (!hasExternalSchema2(columnDef.options.schema) && columnDef.target === tableName && !columnDef.options.roles) {
|
|
732
757
|
throw new SchemaValidationError(
|
|
733
758
|
`Self-referential FK '${columnName}' must have 'roles' option with parent/children names`,
|
|
734
759
|
tableName,
|
|
735
760
|
columnName
|
|
736
761
|
);
|
|
737
762
|
}
|
|
738
|
-
if (columnDef.target !== tableName && columnDef.options.roles) {
|
|
763
|
+
if ((hasExternalSchema2(columnDef.options.schema) || columnDef.target !== tableName) && columnDef.options.roles) {
|
|
739
764
|
throw new SchemaValidationError(
|
|
740
765
|
`'roles' option is only valid for self-referential FKs, but '${columnName}' references '${columnDef.target}'`,
|
|
741
766
|
tableName,
|
|
@@ -751,14 +776,6 @@ function validateFkTargets(tables) {
|
|
|
751
776
|
const tableMap = new Map(tables.map((t) => [t.name, t]));
|
|
752
777
|
for (const table of tables) {
|
|
753
778
|
for (const fk of table.foreignKeys) {
|
|
754
|
-
const target = tableMap.get(fk.references.table);
|
|
755
|
-
if (!target) {
|
|
756
|
-
throw new SchemaValidationError(
|
|
757
|
-
`Foreign key in '${table.name}' references non-existent table '${fk.references.table}'`,
|
|
758
|
-
table.name,
|
|
759
|
-
fk.columns[0]
|
|
760
|
-
);
|
|
761
|
-
}
|
|
762
779
|
for (const srcCol of fk.columns) {
|
|
763
780
|
if (!table.columns.some((c) => c.name === srcCol)) {
|
|
764
781
|
throw new SchemaValidationError(
|
|
@@ -782,6 +799,15 @@ function validateFkTargets(tables) {
|
|
|
782
799
|
fk.columns[0]
|
|
783
800
|
);
|
|
784
801
|
}
|
|
802
|
+
if (hasExternalSchema2(fk.references.schema)) continue;
|
|
803
|
+
const target = tableMap.get(fk.references.table);
|
|
804
|
+
if (!target) {
|
|
805
|
+
throw new SchemaValidationError(
|
|
806
|
+
`Foreign key in '${table.name}' references non-existent table '${fk.references.table}'`,
|
|
807
|
+
table.name,
|
|
808
|
+
fk.columns[0]
|
|
809
|
+
);
|
|
810
|
+
}
|
|
785
811
|
for (const refCol of fk.references.columns) {
|
|
786
812
|
if (!target.columns.some((c) => c.name === refCol)) {
|
|
787
813
|
throw new SchemaValidationError(
|
|
@@ -955,6 +981,14 @@ function getReferencedColumnType(targetDef, referencedCol, definition, visited)
|
|
|
955
981
|
}
|
|
956
982
|
function buildRefColumn(columnName, columnDef, definition) {
|
|
957
983
|
const targetDef = definition[columnDef.target];
|
|
984
|
+
const externalSchema = normalizeReferenceSchema(columnDef.options.schema);
|
|
985
|
+
if (externalSchema !== void 0) {
|
|
986
|
+
throw new SchemaValidationError(
|
|
987
|
+
`Cannot infer column type for foreign key column '${columnName}' to external table '${externalSchema}.${columnDef.target}'. Declare the source column with an explicit type and add the external foreign key at the table level with SchemaConstraints.foreignKeys.`,
|
|
988
|
+
void 0,
|
|
989
|
+
columnName
|
|
990
|
+
);
|
|
991
|
+
}
|
|
958
992
|
const targetCol = columnDef.options.references?.length === 1 ? columnDef.options.references[0] : void 0;
|
|
959
993
|
const inferredType = targetCol && targetDef ? getReferencedColumnType(targetDef, targetCol, definition) ?? getTargetPkType(definition, columnDef.target) : getTargetPkType(definition, columnDef.target);
|
|
960
994
|
const col2 = {
|
|
@@ -972,7 +1006,8 @@ function buildRefColumn(columnName, columnDef, definition) {
|
|
|
972
1006
|
columns: [columnName],
|
|
973
1007
|
references: {
|
|
974
1008
|
table: columnDef.target,
|
|
975
|
-
columns: columnDef.options.references ?? ["id"]
|
|
1009
|
+
columns: columnDef.options.references ?? ["id"],
|
|
1010
|
+
...externalSchema !== void 0 ? { schema: externalSchema } : {}
|
|
976
1011
|
}
|
|
977
1012
|
};
|
|
978
1013
|
if (columnDef.options.onDelete) fk.onDelete = columnDef.options.onDelete;
|
|
@@ -1028,7 +1063,7 @@ function buildPseudoColumns(tableName, refsByTable, finalPk) {
|
|
|
1028
1063
|
const refs = refsByTable.get(tableName) ?? [];
|
|
1029
1064
|
const pkColumn = typeof finalPk === "string" ? finalPk : finalPk?.[0] ?? "id";
|
|
1030
1065
|
for (const ref3 of refs) {
|
|
1031
|
-
if (ref3.options.roles && ref3.target === tableName) {
|
|
1066
|
+
if (!hasExternalSchema2(ref3.options.schema) && ref3.options.roles && ref3.target === tableName) {
|
|
1032
1067
|
pseudoColumns.push(
|
|
1033
1068
|
createPseudoColumnMetadata(
|
|
1034
1069
|
tableName,
|
|
@@ -1067,13 +1102,18 @@ function buildTableConstraints(tableName, constraints) {
|
|
|
1067
1102
|
}
|
|
1068
1103
|
if (tableConstraints.indexes) {
|
|
1069
1104
|
for (const idx of tableConstraints.indexes) {
|
|
1105
|
+
validateSchemaIndexOptions(tableName, idx);
|
|
1070
1106
|
const indexIR = {
|
|
1071
1107
|
name: idx.name ?? `idx_${tableName}_${idx.columns.join("_")}`,
|
|
1072
1108
|
columns: idx.columns,
|
|
1073
1109
|
unique: idx.unique ?? false
|
|
1074
1110
|
};
|
|
1111
|
+
if (idx.nullsNotDistinct !== void 0) {
|
|
1112
|
+
indexIR.nullsNotDistinct = idx.nullsNotDistinct;
|
|
1113
|
+
}
|
|
1075
1114
|
if (idx.method) indexIR.method = idx.method;
|
|
1076
1115
|
if (idx.where) indexIR.where = idx.where;
|
|
1116
|
+
if (idx.include !== void 0) indexIR.include = idx.include;
|
|
1077
1117
|
if (idx.opclass) indexIR.opclass = idx.opclass;
|
|
1078
1118
|
if (idx.with) indexIR.with = idx.with;
|
|
1079
1119
|
extraIndexes.push(indexIR);
|
|
@@ -1095,11 +1135,13 @@ function buildTableConstraints(tableName, constraints) {
|
|
|
1095
1135
|
tableName
|
|
1096
1136
|
);
|
|
1097
1137
|
}
|
|
1138
|
+
const externalSchema = normalizeReferenceSchema(fkRef.options.schema);
|
|
1098
1139
|
const fk = {
|
|
1099
1140
|
columns: [...fkRef.options.columns],
|
|
1100
1141
|
references: {
|
|
1101
1142
|
table: fkRef.target,
|
|
1102
|
-
columns: fkRef.options.references ? [...fkRef.options.references] : ["id"]
|
|
1143
|
+
columns: fkRef.options.references ? [...fkRef.options.references] : ["id"],
|
|
1144
|
+
...externalSchema !== void 0 ? { schema: externalSchema } : {}
|
|
1103
1145
|
}
|
|
1104
1146
|
};
|
|
1105
1147
|
if (fkRef.options.onDelete) fk.onDelete = fkRef.options.onDelete;
|
|
@@ -1147,6 +1189,7 @@ function buildRelations(_definition, refsByTable, tableNames, constraints) {
|
|
|
1147
1189
|
for (const tableName of tableNames) {
|
|
1148
1190
|
const refs = refsByTable.get(tableName) || [];
|
|
1149
1191
|
for (const ref3 of refs) {
|
|
1192
|
+
if (hasExternalSchema2(ref3.options.schema)) continue;
|
|
1150
1193
|
if (ref3.options.roles) {
|
|
1151
1194
|
const roles = ref3.options.roles;
|
|
1152
1195
|
relations.push({
|
|
@@ -1267,6 +1310,7 @@ function addCompositeConstraintRelations(relations, tableNames, constraints) {
|
|
|
1267
1310
|
const foreignKeys = constraints[tableName]?.foreignKeys;
|
|
1268
1311
|
if (!foreignKeys) continue;
|
|
1269
1312
|
for (const fkRef of foreignKeys) {
|
|
1313
|
+
if (hasExternalSchema2(fkRef.options.schema)) continue;
|
|
1270
1314
|
if (!tableSet.has(fkRef.target)) continue;
|
|
1271
1315
|
const columns = fkRef.options.columns;
|
|
1272
1316
|
if (!columns?.length) continue;
|
|
@@ -1338,38 +1382,102 @@ async function getSchemaFromDb(adapter, options) {
|
|
|
1338
1382
|
const model = introspectionResult;
|
|
1339
1383
|
const introspectedAt = introspectionResult.introspectedAt;
|
|
1340
1384
|
const fkLookup = /* @__PURE__ */ new Map();
|
|
1385
|
+
const compositeExternalFkLookup = /* @__PURE__ */ new Map();
|
|
1341
1386
|
for (const table of model.tables.values()) {
|
|
1342
1387
|
const tableFks = /* @__PURE__ */ new Map();
|
|
1343
1388
|
for (const fk of table.foreignKeys) {
|
|
1389
|
+
const externalSchema = normalizeReferenceSchema(fk.references.schema);
|
|
1390
|
+
if (externalSchema !== void 0 && fk.columns.length > 1) {
|
|
1391
|
+
const tableCompositeFks = compositeExternalFkLookup.get(table.name) ?? [];
|
|
1392
|
+
tableCompositeFks.push({
|
|
1393
|
+
...fk,
|
|
1394
|
+
references: {
|
|
1395
|
+
...fk.references,
|
|
1396
|
+
schema: externalSchema
|
|
1397
|
+
}
|
|
1398
|
+
});
|
|
1399
|
+
compositeExternalFkLookup.set(table.name, tableCompositeFks);
|
|
1400
|
+
continue;
|
|
1401
|
+
}
|
|
1344
1402
|
const fkColumn = fk.columns[0];
|
|
1345
1403
|
if (!fkColumn) continue;
|
|
1346
1404
|
const column = table.columns.find((c) => c.name === fkColumn);
|
|
1347
1405
|
tableFks.set(fkColumn, {
|
|
1348
1406
|
target: fk.references.table,
|
|
1407
|
+
refs: fk.references.columns,
|
|
1408
|
+
...externalSchema !== void 0 ? { schema: externalSchema } : {},
|
|
1349
1409
|
nullable: column?.nullable ?? true,
|
|
1350
|
-
unique: column?.unique ?? false
|
|
1410
|
+
unique: column?.unique ?? false,
|
|
1411
|
+
...fk.onDelete !== void 0 ? { onDelete: fk.onDelete } : {},
|
|
1412
|
+
...fk.onUpdate !== void 0 ? { onUpdate: fk.onUpdate } : {}
|
|
1351
1413
|
});
|
|
1352
1414
|
}
|
|
1353
1415
|
fkLookup.set(table.name, tableFks);
|
|
1354
1416
|
}
|
|
1355
1417
|
const definition = {};
|
|
1418
|
+
const constraints = {};
|
|
1356
1419
|
for (const table of model.tables.values()) {
|
|
1357
1420
|
const tableDef = {};
|
|
1358
1421
|
const tableFks = fkLookup.get(table.name) ?? /* @__PURE__ */ new Map();
|
|
1422
|
+
const compositeExternalFks = compositeExternalFkLookup.get(table.name) ?? [];
|
|
1359
1423
|
for (const column of table.columns) {
|
|
1360
1424
|
const fk = tableFks.get(column.name);
|
|
1361
1425
|
if (fk) {
|
|
1426
|
+
if (fk.schema !== void 0) {
|
|
1427
|
+
const sourceColumn = {
|
|
1428
|
+
type: columnTypeToJsType(column.type),
|
|
1429
|
+
nullable: fk.nullable
|
|
1430
|
+
};
|
|
1431
|
+
if (fk.unique) sourceColumn.unique = true;
|
|
1432
|
+
tableDef[column.name] = sourceColumn;
|
|
1433
|
+
constraints[table.name] ??= {};
|
|
1434
|
+
const tableConstraints = constraints[table.name];
|
|
1435
|
+
tableConstraints.foreignKeys ??= [];
|
|
1436
|
+
const foreignKeys = tableConstraints.foreignKeys;
|
|
1437
|
+
foreignKeys.push(
|
|
1438
|
+
ref(fk.target, {
|
|
1439
|
+
schema: fk.schema,
|
|
1440
|
+
columns: [column.name],
|
|
1441
|
+
references: fk.refs,
|
|
1442
|
+
...fk.onDelete !== void 0 ? { onDelete: fk.onDelete } : {},
|
|
1443
|
+
...fk.onUpdate !== void 0 ? { onUpdate: fk.onUpdate } : {}
|
|
1444
|
+
})
|
|
1445
|
+
);
|
|
1446
|
+
continue;
|
|
1447
|
+
}
|
|
1448
|
+
const usesDefaultReferences = fk.refs.length === 1 && fk.refs[0] === "id";
|
|
1362
1449
|
tableDef[column.name] = ref(fk.target, {
|
|
1363
1450
|
nullable: fk.nullable,
|
|
1364
|
-
unique: fk.unique
|
|
1451
|
+
unique: fk.unique,
|
|
1452
|
+
...!usesDefaultReferences ? { references: fk.refs } : {},
|
|
1453
|
+
...fk.onDelete !== void 0 && fk.onDelete !== "NO ACTION" ? { onDelete: fk.onDelete } : {},
|
|
1454
|
+
...fk.onUpdate !== void 0 && fk.onUpdate !== "NO ACTION" ? { onUpdate: fk.onUpdate } : {}
|
|
1365
1455
|
});
|
|
1366
1456
|
} else {
|
|
1367
1457
|
tableDef[column.name] = columnTypeToJsType(column.type);
|
|
1368
1458
|
}
|
|
1369
1459
|
}
|
|
1460
|
+
for (const fk of compositeExternalFks) {
|
|
1461
|
+
const externalSchema = fk.references.schema;
|
|
1462
|
+
if (externalSchema === void 0) continue;
|
|
1463
|
+
constraints[table.name] ??= {};
|
|
1464
|
+
const tableConstraints = constraints[table.name];
|
|
1465
|
+
tableConstraints.foreignKeys ??= [];
|
|
1466
|
+
const foreignKeys = tableConstraints.foreignKeys;
|
|
1467
|
+
foreignKeys.push(
|
|
1468
|
+
ref(fk.references.table, {
|
|
1469
|
+
schema: externalSchema,
|
|
1470
|
+
columns: fk.columns,
|
|
1471
|
+
references: fk.references.columns,
|
|
1472
|
+
...fk.onDelete !== void 0 ? { onDelete: fk.onDelete } : {},
|
|
1473
|
+
...fk.onUpdate !== void 0 ? { onUpdate: fk.onUpdate } : {}
|
|
1474
|
+
})
|
|
1475
|
+
);
|
|
1476
|
+
}
|
|
1370
1477
|
definition[table.name] = tableDef;
|
|
1371
1478
|
}
|
|
1372
1479
|
const tableNames = Object.keys(definition);
|
|
1480
|
+
const generatedConstraints = Object.keys(constraints).length > 0 ? constraints : void 0;
|
|
1373
1481
|
const tables = createTablesProxy(
|
|
1374
1482
|
model,
|
|
1375
1483
|
tableNames
|
|
@@ -1380,6 +1488,9 @@ async function getSchemaFromDb(adapter, options) {
|
|
|
1380
1488
|
tableNames,
|
|
1381
1489
|
tables
|
|
1382
1490
|
};
|
|
1491
|
+
if (generatedConstraints !== void 0) {
|
|
1492
|
+
result.constraints = generatedConstraints;
|
|
1493
|
+
}
|
|
1383
1494
|
if (adapter.dbCasing !== void 0) {
|
|
1384
1495
|
result.dbCasing = adapter.dbCasing;
|
|
1385
1496
|
}
|
|
@@ -1390,12 +1501,6 @@ async function getSchemaFromDb(adapter, options) {
|
|
|
1390
1501
|
}
|
|
1391
1502
|
|
|
1392
1503
|
// src/conventions.ts
|
|
1393
|
-
var DEFAULT_CONVENTIONS = {
|
|
1394
|
-
fkPattern: "{singular}Id",
|
|
1395
|
-
pluralize: true,
|
|
1396
|
-
timestamps: ["createdAt", "updatedAt"],
|
|
1397
|
-
fkAutoIndex: true
|
|
1398
|
-
};
|
|
1399
1504
|
var IRREGULAR_PLURALS = {
|
|
1400
1505
|
people: "person",
|
|
1401
1506
|
children: "child",
|
|
@@ -1454,257 +1559,6 @@ function capitalize(name) {
|
|
|
1454
1559
|
function decapitalize(name) {
|
|
1455
1560
|
return name.charAt(0).toLowerCase() + name.slice(1);
|
|
1456
1561
|
}
|
|
1457
|
-
function getSelfRefInverseName(belongsToName) {
|
|
1458
|
-
if (belongsToName === "parent") return "children";
|
|
1459
|
-
return pluralize(belongsToName);
|
|
1460
|
-
}
|
|
1461
|
-
function detectForeignKeys(tableName, table, conventions, tableNames) {
|
|
1462
|
-
const fks = [];
|
|
1463
|
-
const pattern = conventions.fkPattern;
|
|
1464
|
-
for (const [colName, colDef] of Object.entries(table)) {
|
|
1465
|
-
if (colDef.references) {
|
|
1466
|
-
const targetTable = colDef.references.table;
|
|
1467
|
-
if (tableNames.has(targetTable)) {
|
|
1468
|
-
const inferredName = colName.endsWith("Id") ? colName.slice(0, -2) : singularize(targetTable);
|
|
1469
|
-
const isSelfRef = targetTable === tableName;
|
|
1470
|
-
const detectedFK = {
|
|
1471
|
-
column: colName,
|
|
1472
|
-
targetTable,
|
|
1473
|
-
inferredName,
|
|
1474
|
-
explicit: true,
|
|
1475
|
-
targetColumn: colDef.references.column ?? "id"
|
|
1476
|
-
};
|
|
1477
|
-
if (isSelfRef) {
|
|
1478
|
-
detectedFK.parentRole = colDef.references.parentRole ?? inferredName;
|
|
1479
|
-
detectedFK.childRole = colDef.references.childRole ?? getSelfRefInverseName(inferredName);
|
|
1480
|
-
}
|
|
1481
|
-
fks.push(detectedFK);
|
|
1482
|
-
}
|
|
1483
|
-
continue;
|
|
1484
|
-
}
|
|
1485
|
-
for (const candidateTable of tableNames) {
|
|
1486
|
-
if (candidateTable === tableName) continue;
|
|
1487
|
-
const singular = singularize(candidateTable);
|
|
1488
|
-
const expectedColumn = pattern.replace("{singular}", singular);
|
|
1489
|
-
if (colName === expectedColumn) {
|
|
1490
|
-
fks.push({
|
|
1491
|
-
column: colName,
|
|
1492
|
-
targetTable: candidateTable,
|
|
1493
|
-
inferredName: singular,
|
|
1494
|
-
explicit: false,
|
|
1495
|
-
targetColumn: "id"
|
|
1496
|
-
});
|
|
1497
|
-
break;
|
|
1498
|
-
}
|
|
1499
|
-
}
|
|
1500
|
-
if (colName.endsWith("Id")) {
|
|
1501
|
-
const prefix = colName.slice(0, -2);
|
|
1502
|
-
const singular = singularize(tableName);
|
|
1503
|
-
if (["parent", "manager", "supervisor", "owner", singular].includes(prefix)) {
|
|
1504
|
-
if (!fks.some((fk) => fk.column === colName)) {
|
|
1505
|
-
fks.push({
|
|
1506
|
-
column: colName,
|
|
1507
|
-
targetTable: tableName,
|
|
1508
|
-
inferredName: prefix,
|
|
1509
|
-
explicit: false,
|
|
1510
|
-
targetColumn: "id",
|
|
1511
|
-
// Auto-infer roles for convention-based self-ref FKs
|
|
1512
|
-
parentRole: prefix,
|
|
1513
|
-
childRole: getSelfRefInverseName(prefix)
|
|
1514
|
-
});
|
|
1515
|
-
}
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
return fks;
|
|
1520
|
-
}
|
|
1521
|
-
function isBusinessColumn(colName, colDef, timestamps) {
|
|
1522
|
-
if (colDef.primaryKey) return false;
|
|
1523
|
-
if (timestamps.includes(colName)) return false;
|
|
1524
|
-
if (colDef.references) return false;
|
|
1525
|
-
if (colName.endsWith("Id")) return false;
|
|
1526
|
-
if (["id", "createdBy", "updatedBy", "deletedAt"].includes(colName))
|
|
1527
|
-
return false;
|
|
1528
|
-
return true;
|
|
1529
|
-
}
|
|
1530
|
-
function detectManyToMany(tables, conventions, tableNames) {
|
|
1531
|
-
const results = [];
|
|
1532
|
-
for (const [tableName, table] of Object.entries(tables)) {
|
|
1533
|
-
const fks = detectForeignKeys(tableName, table, conventions, tableNames);
|
|
1534
|
-
if (fks.length !== 2) continue;
|
|
1535
|
-
const hasBusinessColumns = Object.entries(table).some(
|
|
1536
|
-
([colName, colDef]) => isBusinessColumn(colName, colDef, conventions.timestamps)
|
|
1537
|
-
);
|
|
1538
|
-
if (hasBusinessColumns) continue;
|
|
1539
|
-
const fkA = fks[0];
|
|
1540
|
-
const fkB = fks[1];
|
|
1541
|
-
if (fkA && fkB) {
|
|
1542
|
-
results.push({
|
|
1543
|
-
junction: tableName,
|
|
1544
|
-
tableA: fkA.targetTable,
|
|
1545
|
-
tableB: fkB.targetTable,
|
|
1546
|
-
fkA: fkA.column,
|
|
1547
|
-
fkB: fkB.column
|
|
1548
|
-
});
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1551
|
-
return results;
|
|
1552
|
-
}
|
|
1553
|
-
function inferRelationsFromSchema(tables, conventions, explicitRelations = {}) {
|
|
1554
|
-
const result = { ...explicitRelations };
|
|
1555
|
-
const tableNames = new Set(Object.keys(tables));
|
|
1556
|
-
const manyToManys = detectManyToMany(tables, conventions, tableNames);
|
|
1557
|
-
const junctionTables = new Set(manyToManys.map((m) => m.junction));
|
|
1558
|
-
for (const m2m of manyToManys) {
|
|
1559
|
-
const { junction, tableA, tableB, fkA, fkB } = m2m;
|
|
1560
|
-
const relNameAtoB = conventions.pluralize ? pluralize(singularize(tableB)) : tableB;
|
|
1561
|
-
const relNameBtoA = conventions.pluralize ? pluralize(singularize(tableA)) : tableA;
|
|
1562
|
-
const keyAtoB = `${tableA}.${relNameAtoB}`;
|
|
1563
|
-
const keyBtoA = `${tableB}.${relNameBtoA}`;
|
|
1564
|
-
if (!(keyAtoB in result)) {
|
|
1565
|
-
const rel = {
|
|
1566
|
-
kind: "manyToMany",
|
|
1567
|
-
target: tableB,
|
|
1568
|
-
through: junction,
|
|
1569
|
-
sourceFk: fkA,
|
|
1570
|
-
targetFk: fkB
|
|
1571
|
-
};
|
|
1572
|
-
result[keyAtoB] = rel;
|
|
1573
|
-
}
|
|
1574
|
-
if (!(keyBtoA in result)) {
|
|
1575
|
-
const rel = {
|
|
1576
|
-
kind: "manyToMany",
|
|
1577
|
-
target: tableA,
|
|
1578
|
-
through: junction,
|
|
1579
|
-
sourceFk: fkB,
|
|
1580
|
-
targetFk: fkA
|
|
1581
|
-
};
|
|
1582
|
-
result[keyBtoA] = rel;
|
|
1583
|
-
}
|
|
1584
|
-
}
|
|
1585
|
-
for (const [tableName, table] of Object.entries(tables)) {
|
|
1586
|
-
if (junctionTables.has(tableName)) continue;
|
|
1587
|
-
const fks = detectForeignKeys(tableName, table, conventions, tableNames);
|
|
1588
|
-
for (const fk of fks) {
|
|
1589
|
-
if (junctionTables.has(fk.targetTable)) continue;
|
|
1590
|
-
const belongsToKey = `${tableName}.${fk.inferredName}`;
|
|
1591
|
-
if (!(belongsToKey in result)) {
|
|
1592
|
-
const rel = {
|
|
1593
|
-
kind: "belongsTo",
|
|
1594
|
-
target: fk.targetTable,
|
|
1595
|
-
foreignKey: fk.column,
|
|
1596
|
-
targetKey: fk.targetColumn
|
|
1597
|
-
};
|
|
1598
|
-
result[belongsToKey] = rel;
|
|
1599
|
-
}
|
|
1600
|
-
const isSelfRef = fk.targetTable === tableName;
|
|
1601
|
-
const hasManyName = isSelfRef ? getSelfRefInverseName(fk.inferredName) : (() => {
|
|
1602
|
-
const hasCustomAlias = fk.inferredName !== singularize(fk.targetTable);
|
|
1603
|
-
if (hasCustomAlias) {
|
|
1604
|
-
return conventions.pluralize ? pluralize(fk.inferredName) : fk.inferredName;
|
|
1605
|
-
}
|
|
1606
|
-
return conventions.pluralize ? pluralize(singularize(tableName)) : tableName;
|
|
1607
|
-
})();
|
|
1608
|
-
const hasManyKey = `${fk.targetTable}.${hasManyName}`;
|
|
1609
|
-
if (!(hasManyKey in result)) {
|
|
1610
|
-
const rel = {
|
|
1611
|
-
kind: "hasMany",
|
|
1612
|
-
target: tableName,
|
|
1613
|
-
foreignKey: fk.column,
|
|
1614
|
-
sourceKey: "id"
|
|
1615
|
-
};
|
|
1616
|
-
result[hasManyKey] = rel;
|
|
1617
|
-
}
|
|
1618
|
-
}
|
|
1619
|
-
}
|
|
1620
|
-
return result;
|
|
1621
|
-
}
|
|
1622
|
-
|
|
1623
|
-
// src/schema-dsl.ts
|
|
1624
|
-
function defineSchema(tables, config) {
|
|
1625
|
-
const relations = config?.relations ?? {};
|
|
1626
|
-
const hints = config?.hints ?? {};
|
|
1627
|
-
const conventions = config?.conventions ?? {};
|
|
1628
|
-
const indexes = config?.indexes ?? {};
|
|
1629
|
-
const defaultFilters = config?.defaultFilters ?? {};
|
|
1630
|
-
const resolvedConventions = {
|
|
1631
|
-
...DEFAULT_CONVENTIONS,
|
|
1632
|
-
...conventions
|
|
1633
|
-
};
|
|
1634
|
-
const allRelations = inferRelationsFromSchema(
|
|
1635
|
-
tables,
|
|
1636
|
-
resolvedConventions,
|
|
1637
|
-
relations
|
|
1638
|
-
);
|
|
1639
|
-
validateRelations(tables, relations);
|
|
1640
|
-
validateHints(allRelations, hints);
|
|
1641
|
-
validateDefaultFilters(tables, defaultFilters);
|
|
1642
|
-
return {
|
|
1643
|
-
tables,
|
|
1644
|
-
relations: allRelations,
|
|
1645
|
-
hints,
|
|
1646
|
-
conventions: resolvedConventions,
|
|
1647
|
-
indexes,
|
|
1648
|
-
defaultFilters
|
|
1649
|
-
};
|
|
1650
|
-
}
|
|
1651
|
-
function validateRelations(tables, relations) {
|
|
1652
|
-
const tableNames = new Set(Object.keys(tables));
|
|
1653
|
-
for (const [key, rel] of Object.entries(relations)) {
|
|
1654
|
-
const sourceTable = key.split(".")[0] ?? key;
|
|
1655
|
-
if (!tableNames.has(sourceTable)) {
|
|
1656
|
-
throw new SchemaValidationError2(
|
|
1657
|
-
`Relation '${key}' references non-existent source table '${sourceTable}'`
|
|
1658
|
-
);
|
|
1659
|
-
}
|
|
1660
|
-
if (!tableNames.has(rel.target)) {
|
|
1661
|
-
throw new SchemaValidationError2(
|
|
1662
|
-
`Relation '${key}' references non-existent target table '${rel.target}'`
|
|
1663
|
-
);
|
|
1664
|
-
}
|
|
1665
|
-
if (rel.kind === "manyToMany" && !tableNames.has(rel.through)) {
|
|
1666
|
-
throw new SchemaValidationError2(
|
|
1667
|
-
`Relation '${key}' references non-existent junction table '${rel.through}'`
|
|
1668
|
-
);
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
function validateHints(relations, hints) {
|
|
1673
|
-
for (const path of Object.keys(hints)) {
|
|
1674
|
-
if (!(path in relations)) {
|
|
1675
|
-
throw new SchemaValidationError2(
|
|
1676
|
-
`Hint path '${path}' does not match any relation. Available: ${Object.keys(relations).join(", ")}`
|
|
1677
|
-
);
|
|
1678
|
-
}
|
|
1679
|
-
}
|
|
1680
|
-
}
|
|
1681
|
-
function validateDefaultFilters(tables, defaultFilters) {
|
|
1682
|
-
const tableNames = new Set(Object.keys(tables));
|
|
1683
|
-
for (const tableName of Object.keys(defaultFilters)) {
|
|
1684
|
-
if (!tableNames.has(tableName)) {
|
|
1685
|
-
throw new SchemaValidationError2(
|
|
1686
|
-
`Default filter for non-existent table '${tableName}'. Available: ${[...tableNames].join(", ")}`
|
|
1687
|
-
);
|
|
1688
|
-
}
|
|
1689
|
-
}
|
|
1690
|
-
}
|
|
1691
|
-
var SchemaValidationError2 = class extends Error {
|
|
1692
|
-
constructor(message) {
|
|
1693
|
-
super(message);
|
|
1694
|
-
this.name = "SchemaValidationError";
|
|
1695
|
-
}
|
|
1696
|
-
};
|
|
1697
|
-
|
|
1698
|
-
// src/schema-dsl-types.ts
|
|
1699
|
-
function isBelongsTo(rel) {
|
|
1700
|
-
return rel.kind === "belongsTo";
|
|
1701
|
-
}
|
|
1702
|
-
function isHasMany(rel) {
|
|
1703
|
-
return rel.kind === "hasMany";
|
|
1704
|
-
}
|
|
1705
|
-
function isManyToMany(rel) {
|
|
1706
|
-
return rel.kind === "manyToMany";
|
|
1707
|
-
}
|
|
1708
1562
|
|
|
1709
1563
|
// src/planner.ts
|
|
1710
1564
|
import { resolveJsonAggOrderKey, toColumnList } from "@dbsp/types";
|
|
@@ -6327,7 +6181,7 @@ function hydrateJsonAggIncludes(results, planReport) {
|
|
|
6327
6181
|
if (typeof row !== "object" || row === null) {
|
|
6328
6182
|
continue;
|
|
6329
6183
|
}
|
|
6330
|
-
const
|
|
6184
|
+
const record = row;
|
|
6331
6185
|
for (const [relationName, info] of relationInfo) {
|
|
6332
6186
|
const candidates = [relationName];
|
|
6333
6187
|
if (info.includeAlias && info.includeAlias !== relationName) {
|
|
@@ -6340,17 +6194,17 @@ function hydrateJsonAggIncludes(results, planReport) {
|
|
|
6340
6194
|
/_([a-z])/g,
|
|
6341
6195
|
(_, c) => c.toUpperCase()
|
|
6342
6196
|
);
|
|
6343
|
-
if (snakeJson in
|
|
6197
|
+
if (snakeJson in record) {
|
|
6344
6198
|
actualColumnName = snakeJson;
|
|
6345
6199
|
break;
|
|
6346
6200
|
}
|
|
6347
|
-
if (camelJson in
|
|
6201
|
+
if (camelJson in record) {
|
|
6348
6202
|
actualColumnName = camelJson;
|
|
6349
6203
|
break;
|
|
6350
6204
|
}
|
|
6351
6205
|
}
|
|
6352
6206
|
if (actualColumnName) {
|
|
6353
|
-
const jsonValue =
|
|
6207
|
+
const jsonValue = record[actualColumnName];
|
|
6354
6208
|
let parsed;
|
|
6355
6209
|
if (typeof jsonValue === "string") {
|
|
6356
6210
|
try {
|
|
@@ -6369,8 +6223,8 @@ function hydrateJsonAggIncludes(results, planReport) {
|
|
|
6369
6223
|
parsed = parsed.length > 0 ? parsed[0] : null;
|
|
6370
6224
|
}
|
|
6371
6225
|
const outputKey = info.includeAlias ?? relationName;
|
|
6372
|
-
|
|
6373
|
-
delete
|
|
6226
|
+
record[outputKey] = parsed;
|
|
6227
|
+
delete record[actualColumnName];
|
|
6374
6228
|
}
|
|
6375
6229
|
}
|
|
6376
6230
|
}
|
|
@@ -8299,12 +8153,12 @@ var ResultHydrator = class {
|
|
|
8299
8153
|
if (typeof row !== "object" || row === null) {
|
|
8300
8154
|
continue;
|
|
8301
8155
|
}
|
|
8302
|
-
const
|
|
8156
|
+
const record = row;
|
|
8303
8157
|
const valuesByPath = /* @__PURE__ */ new Map();
|
|
8304
|
-
for (const key of Object.keys(
|
|
8158
|
+
for (const key of Object.keys(record)) {
|
|
8305
8159
|
const info = findLongestJoinInfo(key, joinInfos);
|
|
8306
8160
|
if (!info) continue;
|
|
8307
|
-
const value =
|
|
8161
|
+
const value = record[key];
|
|
8308
8162
|
let entry = valuesByPath.get(info.relationPath);
|
|
8309
8163
|
if (!entry) {
|
|
8310
8164
|
entry = { values: {}, allNull: true };
|
|
@@ -8316,13 +8170,13 @@ var ResultHydrator = class {
|
|
|
8316
8170
|
value
|
|
8317
8171
|
);
|
|
8318
8172
|
if (value !== null && value !== void 0) entry.allNull = false;
|
|
8319
|
-
delete
|
|
8173
|
+
delete record[key];
|
|
8320
8174
|
}
|
|
8321
8175
|
for (const info of infosByDepth) {
|
|
8322
8176
|
const entry = valuesByPath.get(info.relationPath);
|
|
8323
8177
|
if (!entry) continue;
|
|
8324
8178
|
assignNestedValue(
|
|
8325
|
-
|
|
8179
|
+
record,
|
|
8326
8180
|
info.segments,
|
|
8327
8181
|
entry.allNull ? null : entry.values
|
|
8328
8182
|
);
|
|
@@ -8552,10 +8406,10 @@ var ResultHydrator = class {
|
|
|
8552
8406
|
return obj[columns[0]];
|
|
8553
8407
|
}
|
|
8554
8408
|
const values = columns.map((k) => obj[k]);
|
|
8555
|
-
if (values.some((
|
|
8409
|
+
if (values.some((v) => v === void 0 || v === null)) {
|
|
8556
8410
|
return void 0;
|
|
8557
8411
|
}
|
|
8558
|
-
const parts = values.map((
|
|
8412
|
+
const parts = values.map((v) => String(v));
|
|
8559
8413
|
if (parts.some((p) => p.includes(COMPOSITE_KEY_SEP))) {
|
|
8560
8414
|
return JSON.stringify(parts);
|
|
8561
8415
|
}
|
|
@@ -8570,7 +8424,7 @@ var ResultHydrator = class {
|
|
|
8570
8424
|
return obj[columns[0]];
|
|
8571
8425
|
}
|
|
8572
8426
|
const values = columns.map((k) => obj[k]);
|
|
8573
|
-
return values.some((
|
|
8427
|
+
return values.some((v) => v === void 0 || v === null) ? void 0 : values;
|
|
8574
8428
|
}
|
|
8575
8429
|
};
|
|
8576
8430
|
|
|
@@ -10283,7 +10137,7 @@ function generateCreateIndexSQL(tableName, schemaName, opts) {
|
|
|
10283
10137
|
parts.push("NULLS NOT DISTINCT");
|
|
10284
10138
|
}
|
|
10285
10139
|
if (opts.with && Object.keys(opts.with).length > 0) {
|
|
10286
|
-
const withClauses = Object.entries(opts.with).map(([k,
|
|
10140
|
+
const withClauses = Object.entries(opts.with).map(([k, v]) => `${k} = ${v}`).join(", ");
|
|
10287
10141
|
parts.push(`WITH (${withClauses})`);
|
|
10288
10142
|
}
|
|
10289
10143
|
if (opts.where) parts.push(`WHERE ${opts.where}`);
|
|
@@ -10329,16 +10183,13 @@ function buildIndexAPI(tableName, schemaName, adapter, requireAdapter2) {
|
|
|
10329
10183
|
"indexes.list() requires an adapter."
|
|
10330
10184
|
);
|
|
10331
10185
|
}
|
|
10332
|
-
if (adapter.listIndexes) {
|
|
10333
|
-
|
|
10334
|
-
|
|
10335
|
-
|
|
10336
|
-
|
|
10337
|
-
const rows = await adapter.executeRaw(sql2, []);
|
|
10338
|
-
return rows;
|
|
10186
|
+
if (!adapter.listIndexes) {
|
|
10187
|
+
throw new InvalidOperationError(
|
|
10188
|
+
"indexes.list",
|
|
10189
|
+
"indexes.list() requires an adapter that implements listIndexes()."
|
|
10190
|
+
);
|
|
10339
10191
|
}
|
|
10340
|
-
|
|
10341
|
-
return [];
|
|
10192
|
+
return adapter.listIndexes(tableName, schemaName, options);
|
|
10342
10193
|
},
|
|
10343
10194
|
async exists(name) {
|
|
10344
10195
|
if (!adapter) {
|
|
@@ -10960,705 +10811,6 @@ function rangeContainedBy(fieldOrColumn, valueOrRange, rangeType = "daterange")
|
|
|
10960
10811
|
};
|
|
10961
10812
|
}
|
|
10962
10813
|
|
|
10963
|
-
// src/dx/schema-bridge.ts
|
|
10964
|
-
import { buildRelationKeyFields, toColumnList as toColumnList3 } from "@dbsp/types";
|
|
10965
|
-
import * as v from "valibot";
|
|
10966
|
-
function generatedTypeToColumnType(genType) {
|
|
10967
|
-
switch (genType) {
|
|
10968
|
-
case "string":
|
|
10969
|
-
case "text":
|
|
10970
|
-
return "string";
|
|
10971
|
-
case "number":
|
|
10972
|
-
case "decimal":
|
|
10973
|
-
return "number";
|
|
10974
|
-
case "integer":
|
|
10975
|
-
return "integer";
|
|
10976
|
-
case "bigint":
|
|
10977
|
-
return "bigint";
|
|
10978
|
-
case "boolean":
|
|
10979
|
-
return "boolean";
|
|
10980
|
-
case "date":
|
|
10981
|
-
return "date";
|
|
10982
|
-
case "timestamp":
|
|
10983
|
-
case "datetime":
|
|
10984
|
-
return "datetime";
|
|
10985
|
-
case "json":
|
|
10986
|
-
return "json";
|
|
10987
|
-
case "jsonb":
|
|
10988
|
-
return "jsonb";
|
|
10989
|
-
case "time":
|
|
10990
|
-
return "time";
|
|
10991
|
-
case "uuid":
|
|
10992
|
-
return "uuid";
|
|
10993
|
-
case "daterange":
|
|
10994
|
-
return "daterange";
|
|
10995
|
-
case "tstzrange":
|
|
10996
|
-
return "tstzrange";
|
|
10997
|
-
case "int4range":
|
|
10998
|
-
return "int4range";
|
|
10999
|
-
case "tsrange":
|
|
11000
|
-
return "tsrange";
|
|
11001
|
-
case "int8range":
|
|
11002
|
-
return "int8range";
|
|
11003
|
-
case "numrange":
|
|
11004
|
-
return "numrange";
|
|
11005
|
-
}
|
|
11006
|
-
}
|
|
11007
|
-
function mapRelationType2(kind) {
|
|
11008
|
-
switch (kind) {
|
|
11009
|
-
case "belongsTo":
|
|
11010
|
-
return "belongsTo";
|
|
11011
|
-
case "hasMany":
|
|
11012
|
-
return "hasMany";
|
|
11013
|
-
case "manyToMany":
|
|
11014
|
-
return "belongsToMany";
|
|
11015
|
-
}
|
|
11016
|
-
}
|
|
11017
|
-
function sourceTableFromQualifiedName(qualifiedName) {
|
|
11018
|
-
const dotIndex = qualifiedName.indexOf(".");
|
|
11019
|
-
return dotIndex > 0 ? qualifiedName.slice(0, dotIndex) : qualifiedName;
|
|
11020
|
-
}
|
|
11021
|
-
function relationNameFromQualifiedName(qualifiedName) {
|
|
11022
|
-
const dotIndex = qualifiedName.indexOf(".");
|
|
11023
|
-
return dotIndex > 0 ? qualifiedName.slice(dotIndex + 1) : qualifiedName;
|
|
11024
|
-
}
|
|
11025
|
-
function columnListsEqual(left, right) {
|
|
11026
|
-
const leftColumns = toColumnList3(left);
|
|
11027
|
-
const rightColumns = toColumnList3(right);
|
|
11028
|
-
return leftColumns.length === rightColumns.length && leftColumns.every((column, index) => column === rightColumns[index]);
|
|
11029
|
-
}
|
|
11030
|
-
function generatedReferencedColumns(key) {
|
|
11031
|
-
const columns = toColumnList3(key);
|
|
11032
|
-
return columns.length > 0 ? columns : ["id"];
|
|
11033
|
-
}
|
|
11034
|
-
function findRelationForeignKey(sourceTable, genRelation, tables) {
|
|
11035
|
-
switch (genRelation.kind) {
|
|
11036
|
-
case "belongsTo":
|
|
11037
|
-
return tables.get(sourceTable)?.foreignKeys.find(
|
|
11038
|
-
(fk) => fk.references.table === genRelation.target && columnListsEqual(fk.columns, genRelation.foreignKey)
|
|
11039
|
-
);
|
|
11040
|
-
case "hasMany":
|
|
11041
|
-
return tables.get(genRelation.target)?.foreignKeys.find(
|
|
11042
|
-
(fk) => fk.references.table === sourceTable && columnListsEqual(fk.columns, genRelation.foreignKey)
|
|
11043
|
-
);
|
|
11044
|
-
case "manyToMany":
|
|
11045
|
-
return void 0;
|
|
11046
|
-
}
|
|
11047
|
-
}
|
|
11048
|
-
function isGeneratedTableWithConfig(table) {
|
|
11049
|
-
const columns = table.columns;
|
|
11050
|
-
return typeof columns === "object" && columns !== null && typeof columns.type !== "string";
|
|
11051
|
-
}
|
|
11052
|
-
function buildTableIRFromDefinition(tableName, genTable, fkAutoIndex) {
|
|
11053
|
-
const columns = [];
|
|
11054
|
-
const foreignKeys = [];
|
|
11055
|
-
const indexes = [];
|
|
11056
|
-
const primaryKeys = [];
|
|
11057
|
-
const tableColumns = isGeneratedTableWithConfig(genTable) ? genTable.columns : genTable;
|
|
11058
|
-
const indexedColumns = /* @__PURE__ */ new Set();
|
|
11059
|
-
for (const [colName, colDef] of Object.entries(tableColumns)) {
|
|
11060
|
-
const col2 = {
|
|
11061
|
-
name: colName,
|
|
11062
|
-
type: generatedTypeToColumnType(colDef.type),
|
|
11063
|
-
nullable: colDef.nullable ?? false,
|
|
11064
|
-
default: colDef.default
|
|
11065
|
-
};
|
|
11066
|
-
if (colDef.unique !== void 0) {
|
|
11067
|
-
col2.unique = colDef.unique;
|
|
11068
|
-
}
|
|
11069
|
-
if (colDef.autoIncrement !== void 0) {
|
|
11070
|
-
col2.autoIncrement = colDef.autoIncrement;
|
|
11071
|
-
}
|
|
11072
|
-
columns.push(col2);
|
|
11073
|
-
if (colDef.primaryKey) {
|
|
11074
|
-
primaryKeys.push(colName);
|
|
11075
|
-
}
|
|
11076
|
-
if (colDef.references) {
|
|
11077
|
-
const fk = {
|
|
11078
|
-
columns: [colName],
|
|
11079
|
-
references: {
|
|
11080
|
-
table: colDef.references.table,
|
|
11081
|
-
columns: [colDef.references.column ?? "id"]
|
|
11082
|
-
}
|
|
11083
|
-
};
|
|
11084
|
-
if (colDef.references.onDelete) {
|
|
11085
|
-
fk.onDelete = colDef.references.onDelete;
|
|
11086
|
-
}
|
|
11087
|
-
foreignKeys.push(fk);
|
|
11088
|
-
}
|
|
11089
|
-
if (colDef.index) {
|
|
11090
|
-
const indexName = typeof colDef.index === "string" ? colDef.index : `idx_${tableName}_${colName}`;
|
|
11091
|
-
indexes.push({
|
|
11092
|
-
name: indexName,
|
|
11093
|
-
columns: [colName],
|
|
11094
|
-
unique: false
|
|
11095
|
-
});
|
|
11096
|
-
indexedColumns.add(colName);
|
|
11097
|
-
}
|
|
11098
|
-
if (fkAutoIndex && colDef.references && !colDef.index) {
|
|
11099
|
-
indexes.push({
|
|
11100
|
-
name: `idx_${tableName}_${colName}`,
|
|
11101
|
-
columns: [colName],
|
|
11102
|
-
unique: false
|
|
11103
|
-
});
|
|
11104
|
-
indexedColumns.add(colName);
|
|
11105
|
-
}
|
|
11106
|
-
}
|
|
11107
|
-
const pseudoColumns = [];
|
|
11108
|
-
for (const fk of foreignKeys) {
|
|
11109
|
-
const fkColumn = fk.columns[0];
|
|
11110
|
-
const targetColumn = fk.references.columns[0];
|
|
11111
|
-
if (fk.references.table === tableName && fkColumn !== void 0 && targetColumn !== void 0) {
|
|
11112
|
-
const colDef = tableColumns[fkColumn];
|
|
11113
|
-
const inferredName = fkColumn.endsWith("Id") ? fkColumn.slice(0, -2) : "parent";
|
|
11114
|
-
const parentRole = colDef?.references?.parentRole ?? inferredName;
|
|
11115
|
-
const childRole = colDef?.references?.childRole ?? (parentRole === "parent" ? "children" : `${parentRole}s`);
|
|
11116
|
-
pseudoColumns.push(
|
|
11117
|
-
createPseudoColumnMetadata(
|
|
11118
|
-
tableName,
|
|
11119
|
-
fkColumn,
|
|
11120
|
-
targetColumn,
|
|
11121
|
-
parentRole,
|
|
11122
|
-
childRole
|
|
11123
|
-
)
|
|
11124
|
-
);
|
|
11125
|
-
}
|
|
11126
|
-
}
|
|
11127
|
-
let primaryKey;
|
|
11128
|
-
const configuredPrimaryKey = isGeneratedTableWithConfig(genTable) ? genTable.primaryKey : void 0;
|
|
11129
|
-
if (configuredPrimaryKey !== void 0) {
|
|
11130
|
-
primaryKey = configuredPrimaryKey;
|
|
11131
|
-
} else if (primaryKeys.length > 0) {
|
|
11132
|
-
primaryKey = primaryKeys.length === 1 ? primaryKeys[0] : primaryKeys;
|
|
11133
|
-
} else {
|
|
11134
|
-
const fkColumns = foreignKeys.flatMap((fk) => fk.columns);
|
|
11135
|
-
if (fkColumns.length > 0) {
|
|
11136
|
-
primaryKey = fkColumns.length === 1 ? fkColumns[0] : fkColumns;
|
|
11137
|
-
} else {
|
|
11138
|
-
const hasId = columns.some((c) => c.name === "id");
|
|
11139
|
-
primaryKey = hasId ? "id" : void 0;
|
|
11140
|
-
}
|
|
11141
|
-
}
|
|
11142
|
-
if (isGeneratedTableWithConfig(genTable)) {
|
|
11143
|
-
for (const fk of genTable.foreignKeys ?? []) {
|
|
11144
|
-
const foreignKey = {
|
|
11145
|
-
columns: [...fk.columns],
|
|
11146
|
-
references: {
|
|
11147
|
-
table: fk.references.table,
|
|
11148
|
-
columns: [...fk.references.columns]
|
|
11149
|
-
}
|
|
11150
|
-
};
|
|
11151
|
-
if (fk.onDelete) foreignKey.onDelete = fk.onDelete;
|
|
11152
|
-
if (fk.onUpdate) foreignKey.onUpdate = fk.onUpdate;
|
|
11153
|
-
foreignKeys.push(foreignKey);
|
|
11154
|
-
}
|
|
11155
|
-
for (const index of genTable.indexes ?? []) {
|
|
11156
|
-
indexes.push({
|
|
11157
|
-
columns: [...index.columns],
|
|
11158
|
-
unique: index.unique ?? false,
|
|
11159
|
-
...index.name !== void 0 && { name: index.name }
|
|
11160
|
-
});
|
|
11161
|
-
}
|
|
11162
|
-
}
|
|
11163
|
-
const frozenColumns = Object.freeze(columns);
|
|
11164
|
-
return Object.freeze({
|
|
11165
|
-
name: tableName,
|
|
11166
|
-
columns: frozenColumns,
|
|
11167
|
-
...primaryKey !== void 0 ? { primaryKey } : {},
|
|
11168
|
-
foreignKeys: Object.freeze(foreignKeys),
|
|
11169
|
-
indexes: Object.freeze(indexes),
|
|
11170
|
-
...pseudoColumns.length > 0 && {
|
|
11171
|
-
pseudoColumns: Object.freeze(pseudoColumns)
|
|
11172
|
-
}
|
|
11173
|
-
});
|
|
11174
|
-
}
|
|
11175
|
-
function buildRelationIR(qualifiedName, genRelation, hints, relationFk) {
|
|
11176
|
-
const sourceTable = sourceTableFromQualifiedName(qualifiedName);
|
|
11177
|
-
const relationName = relationNameFromQualifiedName(qualifiedName);
|
|
11178
|
-
const hint = hints[qualifiedName];
|
|
11179
|
-
const relCardinality = genRelation.kind === "hasMany" ? genRelation.cardinality : void 0;
|
|
11180
|
-
const cardinality = hint?.cardinality === "one" ? "one" : relCardinality === "one" ? "one" : genRelation.kind === "belongsTo" ? "one" : "many";
|
|
11181
|
-
const optionality = genRelation.kind === "belongsTo" ? "optional" : "optional";
|
|
11182
|
-
let relationType = mapRelationType2(genRelation.kind);
|
|
11183
|
-
if (genRelation.kind === "hasMany" && cardinality === "one") {
|
|
11184
|
-
relationType = "hasOne";
|
|
11185
|
-
}
|
|
11186
|
-
const baseRelation = {
|
|
11187
|
-
name: relationName,
|
|
11188
|
-
source: sourceTable,
|
|
11189
|
-
target: genRelation.target,
|
|
11190
|
-
type: relationType,
|
|
11191
|
-
cardinality,
|
|
11192
|
-
optionality,
|
|
11193
|
-
includeStrategy: genRelation.includeStrategy ?? "auto",
|
|
11194
|
-
filterStrategy: hint?.defaultStrategy ?? "auto",
|
|
11195
|
-
joinDefault: "auto"
|
|
11196
|
-
};
|
|
11197
|
-
switch (genRelation.kind) {
|
|
11198
|
-
case "belongsTo":
|
|
11199
|
-
return {
|
|
11200
|
-
...baseRelation,
|
|
11201
|
-
...buildRelationKeyFields(
|
|
11202
|
-
relationFk ?? {
|
|
11203
|
-
columns: genRelation.foreignKey,
|
|
11204
|
-
references: {
|
|
11205
|
-
table: genRelation.target,
|
|
11206
|
-
columns: generatedReferencedColumns(genRelation.targetKey)
|
|
11207
|
-
}
|
|
11208
|
-
},
|
|
11209
|
-
"belongsTo",
|
|
11210
|
-
{
|
|
11211
|
-
foreignKeyShape: genRelation.foreignKey,
|
|
11212
|
-
...genRelation.targetKey !== void 0 ? { referencedKeyShape: genRelation.targetKey } : {}
|
|
11213
|
-
}
|
|
11214
|
-
)
|
|
11215
|
-
};
|
|
11216
|
-
case "hasMany":
|
|
11217
|
-
return {
|
|
11218
|
-
...baseRelation,
|
|
11219
|
-
...buildRelationKeyFields(
|
|
11220
|
-
relationFk ?? {
|
|
11221
|
-
columns: genRelation.foreignKey,
|
|
11222
|
-
references: {
|
|
11223
|
-
table: sourceTable,
|
|
11224
|
-
columns: generatedReferencedColumns(genRelation.sourceKey)
|
|
11225
|
-
}
|
|
11226
|
-
},
|
|
11227
|
-
"inverse",
|
|
11228
|
-
{
|
|
11229
|
-
foreignKeyShape: genRelation.foreignKey,
|
|
11230
|
-
...genRelation.sourceKey !== void 0 ? { referencedKeyShape: genRelation.sourceKey } : {}
|
|
11231
|
-
}
|
|
11232
|
-
)
|
|
11233
|
-
};
|
|
11234
|
-
case "manyToMany":
|
|
11235
|
-
return {
|
|
11236
|
-
...baseRelation,
|
|
11237
|
-
through: genRelation.through,
|
|
11238
|
-
foreignKey: genRelation.sourceFk,
|
|
11239
|
-
otherKey: genRelation.targetFk
|
|
11240
|
-
};
|
|
11241
|
-
}
|
|
11242
|
-
}
|
|
11243
|
-
function buildModelFromSchema(schema2) {
|
|
11244
|
-
const tables = /* @__PURE__ */ new Map();
|
|
11245
|
-
const relations = /* @__PURE__ */ new Map();
|
|
11246
|
-
const fkAutoIndex = schema2.conventions.fkAutoIndex;
|
|
11247
|
-
for (const [tableName, genTable] of Object.entries(schema2.tables)) {
|
|
11248
|
-
tables.set(
|
|
11249
|
-
tableName,
|
|
11250
|
-
buildTableIRFromDefinition(tableName, genTable, fkAutoIndex)
|
|
11251
|
-
);
|
|
11252
|
-
}
|
|
11253
|
-
for (const [qualifiedName, genRelation] of Object.entries(schema2.relations)) {
|
|
11254
|
-
const sourceTable = sourceTableFromQualifiedName(qualifiedName);
|
|
11255
|
-
relations.set(
|
|
11256
|
-
qualifiedName,
|
|
11257
|
-
buildRelationIR(
|
|
11258
|
-
qualifiedName,
|
|
11259
|
-
genRelation,
|
|
11260
|
-
schema2.hints,
|
|
11261
|
-
findRelationForeignKey(sourceTable, genRelation, tables)
|
|
11262
|
-
)
|
|
11263
|
-
);
|
|
11264
|
-
}
|
|
11265
|
-
return new ModelIRImpl(tables, relations);
|
|
11266
|
-
}
|
|
11267
|
-
function buildModelFromResolvedSchema(schema2) {
|
|
11268
|
-
const generatedSchema = assertResolvedSchemaToGeneratedSchema(schema2);
|
|
11269
|
-
return buildModelFromSchema(generatedSchema);
|
|
11270
|
-
}
|
|
11271
|
-
function isGeneratedSchema(value) {
|
|
11272
|
-
if (typeof value !== "object" || value === null) {
|
|
11273
|
-
return false;
|
|
11274
|
-
}
|
|
11275
|
-
const obj = value;
|
|
11276
|
-
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;
|
|
11277
|
-
}
|
|
11278
|
-
var RESOLVED_SCHEMA_ONLY_TYPES = /* @__PURE__ */ new Set(["time", "jsonb"]);
|
|
11279
|
-
var GENERATED_SCHEMA_ONLY_TYPES = /* @__PURE__ */ new Set(["number", "datetime"]);
|
|
11280
|
-
function hasResolvedSchemaOnlyTypes(tables) {
|
|
11281
|
-
for (const table of Object.values(tables)) {
|
|
11282
|
-
for (const column of Object.values(table)) {
|
|
11283
|
-
if (column?.type && RESOLVED_SCHEMA_ONLY_TYPES.has(column.type)) {
|
|
11284
|
-
return true;
|
|
11285
|
-
}
|
|
11286
|
-
}
|
|
11287
|
-
}
|
|
11288
|
-
return false;
|
|
11289
|
-
}
|
|
11290
|
-
function hasGeneratedSchemaOnlyTypes(tables) {
|
|
11291
|
-
for (const table of Object.values(tables)) {
|
|
11292
|
-
for (const column of Object.values(table)) {
|
|
11293
|
-
if (column?.type && GENERATED_SCHEMA_ONLY_TYPES.has(column.type)) {
|
|
11294
|
-
return true;
|
|
11295
|
-
}
|
|
11296
|
-
}
|
|
11297
|
-
}
|
|
11298
|
-
return false;
|
|
11299
|
-
}
|
|
11300
|
-
function isResolvedSchema(value) {
|
|
11301
|
-
if (!isGeneratedSchema(value)) {
|
|
11302
|
-
return false;
|
|
11303
|
-
}
|
|
11304
|
-
if (hasResolvedSchemaOnlyTypes(
|
|
11305
|
-
value.tables
|
|
11306
|
-
)) {
|
|
11307
|
-
return true;
|
|
11308
|
-
}
|
|
11309
|
-
if (hasGeneratedSchemaOnlyTypes(
|
|
11310
|
-
value.tables
|
|
11311
|
-
)) {
|
|
11312
|
-
return false;
|
|
11313
|
-
}
|
|
11314
|
-
return false;
|
|
11315
|
-
}
|
|
11316
|
-
function normalizeSchema(input) {
|
|
11317
|
-
if (!isGeneratedSchema(input)) {
|
|
11318
|
-
throw new Error(
|
|
11319
|
-
"Invalid schema: must have tables, relations, hints, and conventions properties"
|
|
11320
|
-
);
|
|
11321
|
-
}
|
|
11322
|
-
if (isResolvedSchema(input)) {
|
|
11323
|
-
const result = resolvedSchemaToGeneratedSchema(input);
|
|
11324
|
-
if (!result.success) {
|
|
11325
|
-
const messages = result.errors.map((e) => e.message).join(", ");
|
|
11326
|
-
throw new Error(`Schema conversion failed: ${messages}`);
|
|
11327
|
-
}
|
|
11328
|
-
return result.schema;
|
|
11329
|
-
}
|
|
11330
|
-
return input;
|
|
11331
|
-
}
|
|
11332
|
-
var SchemaColumnTypeSchema = v.picklist([
|
|
11333
|
-
"uuid",
|
|
11334
|
-
"string",
|
|
11335
|
-
"text",
|
|
11336
|
-
"integer",
|
|
11337
|
-
"bigint",
|
|
11338
|
-
"decimal",
|
|
11339
|
-
"boolean",
|
|
11340
|
-
"timestamp",
|
|
11341
|
-
"date",
|
|
11342
|
-
"time",
|
|
11343
|
-
"json",
|
|
11344
|
-
"jsonb",
|
|
11345
|
-
"daterange",
|
|
11346
|
-
"tstzrange",
|
|
11347
|
-
"int4range",
|
|
11348
|
-
"tsrange",
|
|
11349
|
-
"int8range",
|
|
11350
|
-
"numrange"
|
|
11351
|
-
]);
|
|
11352
|
-
var PROTO_POLLUTION_KEYS = ["__proto__", "constructor", "prototype"];
|
|
11353
|
-
function safeRecord(valueSchema) {
|
|
11354
|
-
return v.pipe(
|
|
11355
|
-
v.unknown(),
|
|
11356
|
-
v.check((input) => {
|
|
11357
|
-
if (typeof input !== "object" || input === null) return true;
|
|
11358
|
-
return !Object.keys(input).some(
|
|
11359
|
-
(k) => PROTO_POLLUTION_KEYS.includes(k)
|
|
11360
|
-
);
|
|
11361
|
-
}, "Schema keys must not include prototype-pollution names (__proto__, constructor, prototype)"),
|
|
11362
|
-
v.record(v.string(), valueSchema)
|
|
11363
|
-
);
|
|
11364
|
-
}
|
|
11365
|
-
var ForeignKeyReferenceSchema = v.object({
|
|
11366
|
-
table: v.string(),
|
|
11367
|
-
column: v.optional(v.string()),
|
|
11368
|
-
onDelete: v.optional(
|
|
11369
|
-
v.picklist(["CASCADE", "SET NULL", "RESTRICT", "NO ACTION"])
|
|
11370
|
-
),
|
|
11371
|
-
index: v.optional(v.boolean()),
|
|
11372
|
-
parentRole: v.optional(v.string()),
|
|
11373
|
-
childRole: v.optional(v.string())
|
|
11374
|
-
});
|
|
11375
|
-
var StringOrStringArraySchema = v.union([v.string(), v.array(v.string())]);
|
|
11376
|
-
var ColumnDefinitionSchema = v.object({
|
|
11377
|
-
type: SchemaColumnTypeSchema,
|
|
11378
|
-
primaryKey: v.optional(v.boolean()),
|
|
11379
|
-
nullable: v.optional(v.boolean()),
|
|
11380
|
-
unique: v.optional(v.boolean()),
|
|
11381
|
-
autoIncrement: v.optional(v.boolean()),
|
|
11382
|
-
default: v.optional(v.union([v.string(), v.number(), v.boolean()])),
|
|
11383
|
-
references: v.optional(ForeignKeyReferenceSchema),
|
|
11384
|
-
index: v.optional(v.union([v.boolean(), v.string()]))
|
|
11385
|
-
});
|
|
11386
|
-
var FlatTableDefinitionSchema = safeRecord(ColumnDefinitionSchema);
|
|
11387
|
-
var TableDefWithConfigSchema = v.object({
|
|
11388
|
-
columns: FlatTableDefinitionSchema,
|
|
11389
|
-
primaryKey: v.optional(StringOrStringArraySchema),
|
|
11390
|
-
foreignKeys: v.optional(
|
|
11391
|
-
v.array(
|
|
11392
|
-
v.object({
|
|
11393
|
-
columns: v.array(v.string()),
|
|
11394
|
-
references: v.object({
|
|
11395
|
-
table: v.string(),
|
|
11396
|
-
columns: v.array(v.string())
|
|
11397
|
-
}),
|
|
11398
|
-
onDelete: v.optional(
|
|
11399
|
-
v.picklist(["CASCADE", "SET NULL", "RESTRICT", "NO ACTION"])
|
|
11400
|
-
),
|
|
11401
|
-
onUpdate: v.optional(
|
|
11402
|
-
v.picklist(["CASCADE", "SET NULL", "RESTRICT", "NO ACTION"])
|
|
11403
|
-
)
|
|
11404
|
-
})
|
|
11405
|
-
)
|
|
11406
|
-
),
|
|
11407
|
-
indexes: v.optional(
|
|
11408
|
-
v.array(
|
|
11409
|
-
v.object({
|
|
11410
|
-
columns: v.array(v.string()),
|
|
11411
|
-
unique: v.optional(v.boolean()),
|
|
11412
|
-
name: v.optional(v.string())
|
|
11413
|
-
})
|
|
11414
|
-
)
|
|
11415
|
-
)
|
|
11416
|
-
});
|
|
11417
|
-
var TableDefinitionSchema = v.union([
|
|
11418
|
-
TableDefWithConfigSchema,
|
|
11419
|
-
FlatTableDefinitionSchema
|
|
11420
|
-
]);
|
|
11421
|
-
var TablesDefinitionSchema = safeRecord(TableDefinitionSchema);
|
|
11422
|
-
var IncludeStrategySchema = v.optional(
|
|
11423
|
-
v.picklist(["join", "subquery", "cte", "lateral", "json_agg", "auto"])
|
|
11424
|
-
);
|
|
11425
|
-
var BelongsToRelationSchema = v.object({
|
|
11426
|
-
kind: v.literal("belongsTo"),
|
|
11427
|
-
target: v.string(),
|
|
11428
|
-
foreignKey: StringOrStringArraySchema,
|
|
11429
|
-
targetKey: v.optional(StringOrStringArraySchema),
|
|
11430
|
-
includeStrategy: IncludeStrategySchema
|
|
11431
|
-
});
|
|
11432
|
-
var HasManyRelationSchema = v.object({
|
|
11433
|
-
kind: v.literal("hasMany"),
|
|
11434
|
-
target: v.string(),
|
|
11435
|
-
foreignKey: StringOrStringArraySchema,
|
|
11436
|
-
sourceKey: v.optional(StringOrStringArraySchema),
|
|
11437
|
-
includeStrategy: IncludeStrategySchema
|
|
11438
|
-
});
|
|
11439
|
-
var ManyToManyRelationSchema = v.object({
|
|
11440
|
-
kind: v.literal("manyToMany"),
|
|
11441
|
-
target: v.string(),
|
|
11442
|
-
through: v.string(),
|
|
11443
|
-
sourceFk: v.string(),
|
|
11444
|
-
targetFk: v.string(),
|
|
11445
|
-
includeStrategy: IncludeStrategySchema
|
|
11446
|
-
});
|
|
11447
|
-
var RelationDefinitionSchema = v.variant("kind", [
|
|
11448
|
-
BelongsToRelationSchema,
|
|
11449
|
-
HasManyRelationSchema,
|
|
11450
|
-
ManyToManyRelationSchema
|
|
11451
|
-
]);
|
|
11452
|
-
var RelationsDefinitionSchema = safeRecord(RelationDefinitionSchema);
|
|
11453
|
-
var HintDefinitionSchema = v.object({
|
|
11454
|
-
defaultStrategy: v.optional(v.picklist(["exists", "join"])),
|
|
11455
|
-
cardinality: v.optional(v.picklist(["one", "many"]))
|
|
11456
|
-
});
|
|
11457
|
-
var HintsDefinitionSchema = safeRecord(HintDefinitionSchema);
|
|
11458
|
-
var ConventionsDefinitionSchema = v.object({
|
|
11459
|
-
fkPattern: v.string(),
|
|
11460
|
-
pluralize: v.boolean(),
|
|
11461
|
-
timestamps: v.array(v.string()),
|
|
11462
|
-
fkAutoIndex: v.boolean()
|
|
11463
|
-
});
|
|
11464
|
-
var IndexDefinitionSchema = v.object({
|
|
11465
|
-
columns: v.array(v.string()),
|
|
11466
|
-
unique: v.optional(v.boolean()),
|
|
11467
|
-
name: v.optional(v.string())
|
|
11468
|
-
});
|
|
11469
|
-
var IndexesDefinitionSchema = safeRecord(v.array(IndexDefinitionSchema));
|
|
11470
|
-
var ResolvedSchemaValidation = v.object({
|
|
11471
|
-
tables: TablesDefinitionSchema,
|
|
11472
|
-
relations: RelationsDefinitionSchema,
|
|
11473
|
-
hints: HintsDefinitionSchema,
|
|
11474
|
-
conventions: ConventionsDefinitionSchema,
|
|
11475
|
-
indexes: v.optional(IndexesDefinitionSchema)
|
|
11476
|
-
});
|
|
11477
|
-
function mapSchemaColumnType(schemaType) {
|
|
11478
|
-
switch (schemaType) {
|
|
11479
|
-
case "uuid":
|
|
11480
|
-
return "uuid";
|
|
11481
|
-
case "string":
|
|
11482
|
-
return "string";
|
|
11483
|
-
case "text":
|
|
11484
|
-
return "text";
|
|
11485
|
-
case "integer":
|
|
11486
|
-
return "integer";
|
|
11487
|
-
case "bigint":
|
|
11488
|
-
return "bigint";
|
|
11489
|
-
case "decimal":
|
|
11490
|
-
return "decimal";
|
|
11491
|
-
case "boolean":
|
|
11492
|
-
return "boolean";
|
|
11493
|
-
case "timestamp":
|
|
11494
|
-
return "timestamp";
|
|
11495
|
-
case "date":
|
|
11496
|
-
return "date";
|
|
11497
|
-
case "time":
|
|
11498
|
-
return "time";
|
|
11499
|
-
case "json":
|
|
11500
|
-
return "json";
|
|
11501
|
-
case "jsonb":
|
|
11502
|
-
return "jsonb";
|
|
11503
|
-
case "daterange":
|
|
11504
|
-
return "daterange";
|
|
11505
|
-
case "tstzrange":
|
|
11506
|
-
return "tstzrange";
|
|
11507
|
-
case "int4range":
|
|
11508
|
-
return "int4range";
|
|
11509
|
-
case "tsrange":
|
|
11510
|
-
return "tsrange";
|
|
11511
|
-
case "int8range":
|
|
11512
|
-
return "int8range";
|
|
11513
|
-
case "numrange":
|
|
11514
|
-
return "numrange";
|
|
11515
|
-
}
|
|
11516
|
-
}
|
|
11517
|
-
function convertColumn(col2) {
|
|
11518
|
-
const result = {
|
|
11519
|
-
type: mapSchemaColumnType(col2.type)
|
|
11520
|
-
};
|
|
11521
|
-
if (col2.primaryKey !== void 0) {
|
|
11522
|
-
result.primaryKey = col2.primaryKey;
|
|
11523
|
-
}
|
|
11524
|
-
if (col2.nullable !== void 0) {
|
|
11525
|
-
result.nullable = col2.nullable;
|
|
11526
|
-
}
|
|
11527
|
-
if (col2.unique !== void 0) {
|
|
11528
|
-
result.unique = col2.unique;
|
|
11529
|
-
}
|
|
11530
|
-
if (col2.autoIncrement !== void 0) {
|
|
11531
|
-
result.autoIncrement = col2.autoIncrement;
|
|
11532
|
-
}
|
|
11533
|
-
if (col2.default !== void 0) {
|
|
11534
|
-
result.default = col2.default;
|
|
11535
|
-
}
|
|
11536
|
-
if (col2.references) {
|
|
11537
|
-
result.references = {
|
|
11538
|
-
table: col2.references.table,
|
|
11539
|
-
...col2.references.column !== void 0 ? { column: col2.references.column } : {},
|
|
11540
|
-
...col2.references.onDelete ? { onDelete: col2.references.onDelete } : {},
|
|
11541
|
-
...col2.references.index !== void 0 ? { index: col2.references.index } : {},
|
|
11542
|
-
...col2.references.parentRole ? { parentRole: col2.references.parentRole } : {},
|
|
11543
|
-
...col2.references.childRole ? { childRole: col2.references.childRole } : {}
|
|
11544
|
-
};
|
|
11545
|
-
}
|
|
11546
|
-
return result;
|
|
11547
|
-
}
|
|
11548
|
-
function convertRelation(rel) {
|
|
11549
|
-
switch (rel.kind) {
|
|
11550
|
-
case "belongsTo": {
|
|
11551
|
-
const result = {
|
|
11552
|
-
kind: "belongsTo",
|
|
11553
|
-
target: rel.target,
|
|
11554
|
-
foreignKey: rel.foreignKey
|
|
11555
|
-
};
|
|
11556
|
-
if (rel.targetKey !== void 0) {
|
|
11557
|
-
result.targetKey = rel.targetKey;
|
|
11558
|
-
}
|
|
11559
|
-
if (rel.includeStrategy !== void 0) {
|
|
11560
|
-
result.includeStrategy = rel.includeStrategy;
|
|
11561
|
-
}
|
|
11562
|
-
return result;
|
|
11563
|
-
}
|
|
11564
|
-
case "hasMany": {
|
|
11565
|
-
const result = {
|
|
11566
|
-
kind: "hasMany",
|
|
11567
|
-
target: rel.target,
|
|
11568
|
-
foreignKey: rel.foreignKey
|
|
11569
|
-
};
|
|
11570
|
-
if (rel.sourceKey !== void 0) {
|
|
11571
|
-
result.sourceKey = rel.sourceKey;
|
|
11572
|
-
}
|
|
11573
|
-
if (rel.includeStrategy !== void 0) {
|
|
11574
|
-
result.includeStrategy = rel.includeStrategy;
|
|
11575
|
-
}
|
|
11576
|
-
return result;
|
|
11577
|
-
}
|
|
11578
|
-
case "manyToMany": {
|
|
11579
|
-
const result = {
|
|
11580
|
-
kind: "manyToMany",
|
|
11581
|
-
target: rel.target,
|
|
11582
|
-
through: rel.through,
|
|
11583
|
-
sourceFk: rel.sourceFk,
|
|
11584
|
-
targetFk: rel.targetFk
|
|
11585
|
-
};
|
|
11586
|
-
if (rel.includeStrategy !== void 0) {
|
|
11587
|
-
result.includeStrategy = rel.includeStrategy;
|
|
11588
|
-
}
|
|
11589
|
-
return result;
|
|
11590
|
-
}
|
|
11591
|
-
}
|
|
11592
|
-
}
|
|
11593
|
-
function convertHint(hint) {
|
|
11594
|
-
const result = {};
|
|
11595
|
-
if (hint.defaultStrategy !== void 0) {
|
|
11596
|
-
result.defaultStrategy = hint.defaultStrategy;
|
|
11597
|
-
}
|
|
11598
|
-
if (hint.cardinality !== void 0) {
|
|
11599
|
-
result.cardinality = hint.cardinality;
|
|
11600
|
-
}
|
|
11601
|
-
return result;
|
|
11602
|
-
}
|
|
11603
|
-
function resolvedSchemaToGeneratedSchema(input) {
|
|
11604
|
-
const parseResult = v.safeParse(ResolvedSchemaValidation, input);
|
|
11605
|
-
if (!parseResult.success) {
|
|
11606
|
-
return {
|
|
11607
|
-
success: false,
|
|
11608
|
-
errors: parseResult.issues
|
|
11609
|
-
};
|
|
11610
|
-
}
|
|
11611
|
-
const validated = parseResult.output;
|
|
11612
|
-
const tables = /* @__PURE__ */ Object.create(null);
|
|
11613
|
-
for (const [tableName, tableDef] of Object.entries(validated.tables)) {
|
|
11614
|
-
const convertedTable = /* @__PURE__ */ Object.create(null);
|
|
11615
|
-
const tableObj = tableDef;
|
|
11616
|
-
const isWithConfig = Array.isArray(tableObj.primaryKey);
|
|
11617
|
-
const columns = isWithConfig ? tableObj.columns : tableObj;
|
|
11618
|
-
for (const [colName, colDef] of Object.entries(columns)) {
|
|
11619
|
-
convertedTable[colName] = convertColumn(
|
|
11620
|
-
colDef
|
|
11621
|
-
);
|
|
11622
|
-
}
|
|
11623
|
-
tables[tableName] = convertedTable;
|
|
11624
|
-
}
|
|
11625
|
-
const relations = /* @__PURE__ */ Object.create(null);
|
|
11626
|
-
for (const [relName, relDef] of Object.entries(validated.relations)) {
|
|
11627
|
-
relations[relName] = convertRelation(relDef);
|
|
11628
|
-
}
|
|
11629
|
-
const hints = /* @__PURE__ */ Object.create(null);
|
|
11630
|
-
for (const [hintName, hintDef] of Object.entries(validated.hints)) {
|
|
11631
|
-
hints[hintName] = convertHint(hintDef);
|
|
11632
|
-
}
|
|
11633
|
-
const conventions = {
|
|
11634
|
-
fkPattern: validated.conventions.fkPattern,
|
|
11635
|
-
pluralize: validated.conventions.pluralize,
|
|
11636
|
-
timestamps: validated.conventions.timestamps,
|
|
11637
|
-
fkAutoIndex: validated.conventions.fkAutoIndex
|
|
11638
|
-
};
|
|
11639
|
-
return {
|
|
11640
|
-
success: true,
|
|
11641
|
-
schema: {
|
|
11642
|
-
tables,
|
|
11643
|
-
relations,
|
|
11644
|
-
hints,
|
|
11645
|
-
conventions
|
|
11646
|
-
}
|
|
11647
|
-
};
|
|
11648
|
-
}
|
|
11649
|
-
function assertResolvedSchemaToGeneratedSchema(input) {
|
|
11650
|
-
const result = resolvedSchemaToGeneratedSchema(input);
|
|
11651
|
-
if (!result.success) {
|
|
11652
|
-
const messages = result.errors.map((e) => {
|
|
11653
|
-
const path = e.path?.map((p) => p.key).join(".") || "root";
|
|
11654
|
-
return `[${path}] ${e.message} (expected: ${e.expected}, received: ${e.received})`;
|
|
11655
|
-
}).join("\n");
|
|
11656
|
-
throw new Error(`Schema validation failed:
|
|
11657
|
-
${messages}`);
|
|
11658
|
-
}
|
|
11659
|
-
return result.schema;
|
|
11660
|
-
}
|
|
11661
|
-
|
|
11662
10814
|
// src/dialects/index.ts
|
|
11663
10815
|
var POSTGRESQL_CAPABILITIES = {
|
|
11664
10816
|
name: "postgresql",
|
|
@@ -13039,7 +12191,6 @@ export {
|
|
|
13039
12191
|
ColumnNotFoundError,
|
|
13040
12192
|
CteBuilder,
|
|
13041
12193
|
CteQueryBuilder,
|
|
13042
|
-
DEFAULT_CONVENTIONS,
|
|
13043
12194
|
DEFAULT_FEATURE_CHECKERS,
|
|
13044
12195
|
DUCKDB_CAPABILITIES,
|
|
13045
12196
|
DeleteBuilder,
|
|
@@ -13062,12 +12213,11 @@ export {
|
|
|
13062
12213
|
RawCteQueryBuilder,
|
|
13063
12214
|
RecursiveShapeMismatchError,
|
|
13064
12215
|
RelationNotFoundError,
|
|
13065
|
-
ResolvedSchemaValidation,
|
|
13066
12216
|
ResultHydrator,
|
|
13067
12217
|
SQLITE_CAPABILITIES,
|
|
13068
12218
|
SQL_RAW_MARKER,
|
|
13069
12219
|
SchemaValidationError as SchemaError,
|
|
13070
|
-
|
|
12220
|
+
SchemaValidationError,
|
|
13071
12221
|
SubqueryBuilder,
|
|
13072
12222
|
SubqueryExpression,
|
|
13073
12223
|
TABLE_META,
|
|
@@ -13106,7 +12256,6 @@ export {
|
|
|
13106
12256
|
assertParamsLength,
|
|
13107
12257
|
assertParamsType,
|
|
13108
12258
|
assertParamsValue,
|
|
13109
|
-
assertResolvedSchemaToGeneratedSchema,
|
|
13110
12259
|
assertSQLColumn,
|
|
13111
12260
|
assertSQLEquals,
|
|
13112
12261
|
assertSQLJoin,
|
|
@@ -13114,8 +12263,6 @@ export {
|
|
|
13114
12263
|
assertSuccess,
|
|
13115
12264
|
assertTypeSupported,
|
|
13116
12265
|
batchValues,
|
|
13117
|
-
buildModelFromResolvedSchema,
|
|
13118
|
-
buildModelFromSchema,
|
|
13119
12266
|
capitalize,
|
|
13120
12267
|
caseWhen,
|
|
13121
12268
|
cast,
|
|
@@ -13137,11 +12284,8 @@ export {
|
|
|
13137
12284
|
decapitalize,
|
|
13138
12285
|
defaultLogger,
|
|
13139
12286
|
defineModel,
|
|
13140
|
-
defineSchema,
|
|
13141
12287
|
denseRank,
|
|
13142
12288
|
deriveRelationPathFromIntentPath,
|
|
13143
|
-
detectForeignKeys,
|
|
13144
|
-
detectManyToMany,
|
|
13145
12289
|
distinct,
|
|
13146
12290
|
emitWarning,
|
|
13147
12291
|
eq,
|
|
@@ -13164,13 +12308,11 @@ export {
|
|
|
13164
12308
|
inArray,
|
|
13165
12309
|
inSubquery,
|
|
13166
12310
|
inferForeignKey,
|
|
13167
|
-
inferRelationsFromSchema,
|
|
13168
12311
|
export_isAdjacencyTraversal as isAdjacencyTraversal,
|
|
13169
12312
|
export_isAggregateWindowFunction as isAggregateWindowFunction,
|
|
13170
12313
|
isAliasedColumn,
|
|
13171
12314
|
isAllColumns,
|
|
13172
12315
|
isBatchValuesRef,
|
|
13173
|
-
isBelongsTo,
|
|
13174
12316
|
isCardinalityShorthand,
|
|
13175
12317
|
export_isCoalesceExpression as isCoalesceExpression,
|
|
13176
12318
|
export_isColumnAliasExpression as isColumnAliasExpression,
|
|
@@ -13181,11 +12323,8 @@ export {
|
|
|
13181
12323
|
isDistinctFrom,
|
|
13182
12324
|
export_isEdgeTableTraversal as isEdgeTableTraversal,
|
|
13183
12325
|
isExpressionSpec,
|
|
13184
|
-
isGeneratedSchema,
|
|
13185
|
-
isHasMany,
|
|
13186
12326
|
export_isInsertIntent as isInsertIntent,
|
|
13187
12327
|
isKnownDialect,
|
|
13188
|
-
isManyToMany,
|
|
13189
12328
|
export_isMutationIntent as isMutationIntent,
|
|
13190
12329
|
isNotNull,
|
|
13191
12330
|
isNull,
|
|
@@ -13200,7 +12339,6 @@ export {
|
|
|
13200
12339
|
isRelationObjectDef,
|
|
13201
12340
|
isRelationRef,
|
|
13202
12341
|
isRelationTupleDef,
|
|
13203
|
-
isResolvedSchema,
|
|
13204
12342
|
export_isSelectAggregate as isSelectAggregate,
|
|
13205
12343
|
export_isSelectAll as isSelectAll,
|
|
13206
12344
|
export_isSelectFields as isSelectFields,
|
|
@@ -13240,7 +12378,6 @@ export {
|
|
|
13240
12378
|
neq,
|
|
13241
12379
|
none,
|
|
13242
12380
|
normalizeSQL,
|
|
13243
|
-
normalizeSchema,
|
|
13244
12381
|
not,
|
|
13245
12382
|
notExists,
|
|
13246
12383
|
nqlRaw,
|
|
@@ -13273,7 +12410,6 @@ export {
|
|
|
13273
12410
|
requiresDatabase,
|
|
13274
12411
|
resetLogger,
|
|
13275
12412
|
resolveQueryIndex,
|
|
13276
|
-
resolvedSchemaToGeneratedSchema,
|
|
13277
12413
|
rowNumber,
|
|
13278
12414
|
runAssertions,
|
|
13279
12415
|
schema,
|
|
@@ -13298,6 +12434,7 @@ export {
|
|
|
13298
12434
|
validateAssertionBlocks,
|
|
13299
12435
|
validateRecursiveInclude,
|
|
13300
12436
|
validateRecursiveShape,
|
|
12437
|
+
validateSchemaIndexOptions,
|
|
13301
12438
|
validateTypeName,
|
|
13302
12439
|
wAvg,
|
|
13303
12440
|
wCount,
|