@rebasepro/server-postgres 0.10.1-canary.ed8caed → 0.10.1-canary.g4db1bb1
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/auth/schema-version.d.ts +106 -0
- package/dist/collections/validate-relations.d.ts +53 -0
- package/dist/data-transformer.d.ts +3 -3
- package/dist/{ensure-collection-tables-BVvtkkRm.js → ensure-collection-tables-DGMYK0fr.js} +5 -5
- package/dist/ensure-collection-tables-DGMYK0fr.js.map +1 -0
- package/dist/index.es.js +610 -313
- package/dist/index.es.js.map +1 -1
- package/dist/services/RelationService.d.ts +9 -8
- package/dist/services/cdc/junction-tables.d.ts +38 -0
- package/dist/services/nested-path.d.ts +3 -3
- package/dist/services/realtimeService.d.ts +19 -0
- package/dist/services/row-pipeline.d.ts +2 -2
- package/dist/{src-lcfUP4xg.js → src-3VmUJ8Xn.js} +135 -247
- package/dist/src-3VmUJ8Xn.js.map +1 -0
- package/dist/{src-CBgtrPhJ.js → src-D5xBTl32.js} +12 -2
- package/dist/src-D5xBTl32.js.map +1 -0
- package/dist/utils/drizzle-conditions.d.ts +35 -23
- package/package.json +6 -6
- package/src/PostgresBootstrapper.ts +15 -2
- package/src/auth/ensure-tables.ts +23 -0
- package/src/auth/schema-version.ts +260 -0
- package/src/cli-errors.ts +1 -1
- package/src/cli-helpers.ts +4 -3
- package/src/collections/PostgresCollectionRegistry.ts +9 -4
- package/src/collections/buildRegistry.ts +7 -0
- package/src/collections/validate-relations.ts +280 -0
- package/src/data-transformer.ts +28 -38
- package/src/schema/doctor.ts +8 -8
- package/src/schema/generate-drizzle-schema-logic.ts +49 -101
- package/src/schema/generate-postgres-ddl-logic.ts +9 -9
- package/src/schema/introspect-db-logic.ts +19 -23
- package/src/services/FetchService.ts +12 -12
- package/src/services/PersistService.ts +23 -27
- package/src/services/RelationService.ts +65 -83
- package/src/services/cdc/junction-tables.ts +91 -0
- package/src/services/nested-path.ts +24 -9
- package/src/services/realtimeService.ts +60 -0
- package/src/services/row-pipeline.ts +5 -6
- package/src/utils/drizzle-conditions.ts +177 -382
- package/dist/ensure-collection-tables-BVvtkkRm.js.map +0 -1
- package/dist/src-CBgtrPhJ.js.map +0 -1
- package/dist/src-lcfUP4xg.js.map +0 -1
|
@@ -2,7 +2,7 @@ import { createRequire as __createRequire } from "module";
|
|
|
2
2
|
import "process";
|
|
3
3
|
__createRequire(import.meta.url);
|
|
4
4
|
import { r as __require, t as __commonJSMin } from "./chunk-DSJWtz9O.js";
|
|
5
|
-
import {
|
|
5
|
+
import { d as isPostgresCollectionConfig, f as NULL_OPS, h as EntityRelation, l as isManyToMany, m as toCanonicalOp, n as getDataSourceCapabilities, o as ANONYMOUS_USER_ID, p as REST_TO_CANONICAL, s as policy, u as getDeclaredSubcollections } from "./src-D5xBTl32.js";
|
|
6
6
|
//#region ../common/src/util/common.ts
|
|
7
7
|
var DEFAULT_ONE_OF_TYPE = "type";
|
|
8
8
|
var DEFAULT_ONE_OF_VALUE = "value";
|
|
@@ -1405,164 +1405,143 @@ function enumToObjectEntries(enumValues) {
|
|
|
1405
1405
|
});
|
|
1406
1406
|
}
|
|
1407
1407
|
//#endregion
|
|
1408
|
-
//#region ../common/src/util/
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1408
|
+
//#region ../common/src/util/resolve-relation.ts
|
|
1409
|
+
/**
|
|
1410
|
+
* Fill in a relation's defaults.
|
|
1411
|
+
*
|
|
1412
|
+
* This replaces `sanitizeRelation`, which had to work out *which kind of link
|
|
1413
|
+
* you meant* from whichever optional fields happened to be set — 194 lines of
|
|
1414
|
+
* it, including a pass that inspected the target collection's own relations to
|
|
1415
|
+
* decide whether a `many`/`inverse` pair was a one-to-many or the far side of a
|
|
1416
|
+
* many-to-many, wrapped in a `try/catch` that fell through to the wrong answer
|
|
1417
|
+
* when it could not tell. Two consumers running that logic at different moments
|
|
1418
|
+
* could reach different conclusions about the same relation.
|
|
1419
|
+
*
|
|
1420
|
+
* With the kind declared there is nothing to work out. What remains is
|
|
1421
|
+
* defaulting — a table name, a column name — which is deterministic, depends
|
|
1422
|
+
* only on the relation and its two endpoints, and cannot fail. That is why this
|
|
1423
|
+
* function returns rather than throws, and why it needs no cache to be
|
|
1424
|
+
* consistent.
|
|
1425
|
+
*/
|
|
1426
|
+
function resolveRelation(relation, sourceCollection, propertyKey) {
|
|
1427
|
+
const target = relation.target;
|
|
1428
|
+
if (typeof target !== "function") throw new Error(`Relation${relation.relationName ? ` '${relation.relationName}'` : ""} on '${sourceCollection.slug}' has no \`target\`. Give it a thunk: \`target: () => otherCollection\`.`);
|
|
1429
|
+
const targetCollection = target();
|
|
1430
|
+
if (!targetCollection?.slug) throw new Error(`Relation${relation.relationName ? ` '${relation.relationName}'` : ""} on '${sourceCollection.slug}' has a \`target\` that did not resolve to a collection.`);
|
|
1431
|
+
const relationName = relation.relationName ?? propertyKey ?? toSnakeCase(targetCollection.slug);
|
|
1432
|
+
const shared = {
|
|
1433
|
+
relationName,
|
|
1434
|
+
target,
|
|
1435
|
+
targetSlug: targetCollection.slug,
|
|
1436
|
+
onUpdate: relation.onUpdate,
|
|
1437
|
+
onDelete: relation.onDelete,
|
|
1438
|
+
overrides: relation.overrides,
|
|
1439
|
+
validation: relation.validation
|
|
1439
1440
|
};
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
}
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
break;
|
|
1480
|
-
}
|
|
1441
|
+
const sourceName = toSnakeCase(sourceCollection.slug ?? sourceCollection.name);
|
|
1442
|
+
switch (relation.kind) {
|
|
1443
|
+
case "belongsTo": return {
|
|
1444
|
+
...shared,
|
|
1445
|
+
kind: "belongsTo",
|
|
1446
|
+
cardinality: "one",
|
|
1447
|
+
writable: true,
|
|
1448
|
+
shared: false,
|
|
1449
|
+
localKey: relation.localKey ?? generateForeignKeyName(relationName)
|
|
1450
|
+
};
|
|
1451
|
+
case "hasOne": return {
|
|
1452
|
+
...shared,
|
|
1453
|
+
kind: "hasOne",
|
|
1454
|
+
cardinality: "one",
|
|
1455
|
+
writable: true,
|
|
1456
|
+
shared: false,
|
|
1457
|
+
foreignKeyOnTarget: relation.foreignKeyOnTarget ?? generateForeignKeyName(sourceName)
|
|
1458
|
+
};
|
|
1459
|
+
case "hasMany": return {
|
|
1460
|
+
...shared,
|
|
1461
|
+
kind: "hasMany",
|
|
1462
|
+
cardinality: "many",
|
|
1463
|
+
writable: true,
|
|
1464
|
+
shared: false,
|
|
1465
|
+
foreignKeyOnTarget: relation.foreignKeyOnTarget ?? generateForeignKeyName(sourceName)
|
|
1466
|
+
};
|
|
1467
|
+
case "manyToMany": {
|
|
1468
|
+
const sourceTable = getTableName(sourceCollection);
|
|
1469
|
+
const targetTable = getTableName(targetCollection);
|
|
1470
|
+
return {
|
|
1471
|
+
...shared,
|
|
1472
|
+
kind: "manyToMany",
|
|
1473
|
+
cardinality: "many",
|
|
1474
|
+
writable: true,
|
|
1475
|
+
shared: true,
|
|
1476
|
+
through: {
|
|
1477
|
+
table: relation.through?.table ?? [sourceTable, targetTable].sort().join("_"),
|
|
1478
|
+
sourceColumn: relation.through?.sourceColumn ?? generateForeignKeyName(sourceName),
|
|
1479
|
+
targetColumn: relation.through?.targetColumn ?? generateForeignKeyName(relationName)
|
|
1481
1480
|
}
|
|
1482
|
-
} catch (e) {}
|
|
1483
|
-
if (!isManyToManyInverse && !newRelation.foreignKeyOnTarget) newRelation.foreignKeyOnTarget = generateForeignKeyName(sourceName);
|
|
1484
|
-
} else if (newRelation.cardinality === "many" && newRelation.direction === "owning") {
|
|
1485
|
-
const sourceTableName = getTableName(sourceCollection);
|
|
1486
|
-
const targetTableName = getTableName(targetCollection);
|
|
1487
|
-
newRelation.through = {
|
|
1488
|
-
table: newRelation.through?.table ?? [sourceTableName, targetTableName].sort().join("_"),
|
|
1489
|
-
sourceColumn: newRelation.through?.sourceColumn ?? generateForeignKeyName(sourceName),
|
|
1490
|
-
targetColumn: newRelation.through?.targetColumn ?? generateForeignKeyName(newRelation.relationName)
|
|
1491
1481
|
};
|
|
1492
1482
|
}
|
|
1483
|
+
case "via": return {
|
|
1484
|
+
...shared,
|
|
1485
|
+
kind: "via",
|
|
1486
|
+
cardinality: relation.cardinality,
|
|
1487
|
+
writable: false,
|
|
1488
|
+
shared: true,
|
|
1489
|
+
joinPath: relation.joinPath
|
|
1490
|
+
};
|
|
1491
|
+
default: throw new Error(`Unknown relation kind: ${JSON.stringify(relation)}`);
|
|
1493
1492
|
}
|
|
1494
|
-
if (newRelation.cardinality === "one" && newRelation.direction === "owning" && !newRelation.localKey && !newRelation.joinPath) throw new Error(`Configuration Error in relation from '${sourceCollection.name}': An 'owning' one-to-one relation requires a 'localKey'. Check the relation config for '${newRelation.relationName}'`);
|
|
1495
|
-
if (newRelation.cardinality === "one" && newRelation.direction === "inverse" && !newRelation.foreignKeyOnTarget && !newRelation.joinPath) throw new Error(`Configuration Error in relation from '${sourceCollection.name}': An 'inverse' one-to-one relation requires a 'foreignKeyOnTarget'. Check the relation config for '${newRelation.relationName}'`);
|
|
1496
|
-
if (newRelation.cardinality === "many" && newRelation.direction === "inverse" && !newRelation.foreignKeyOnTarget && !newRelation.joinPath && !newRelation.inverseRelationName) throw new Error(`Configuration Error in relation from '${sourceCollection.name}': An 'inverse' one-to-many relation requires a 'foreignKeyOnTarget'. Check the relation config for '${newRelation.relationName}'`);
|
|
1497
|
-
return newRelation;
|
|
1498
1493
|
}
|
|
1494
|
+
//#endregion
|
|
1495
|
+
//#region ../common/src/util/relations.ts
|
|
1499
1496
|
/**
|
|
1500
|
-
* Whether the target rows
|
|
1501
|
-
*
|
|
1497
|
+
* Whether the target rows are shared with other parents — a many-to-many, or a
|
|
1498
|
+
* multi-hop `via` chain.
|
|
1502
1499
|
*
|
|
1503
|
-
*
|
|
1504
|
-
*
|
|
1505
|
-
*
|
|
1506
|
-
*
|
|
1507
|
-
*
|
|
1500
|
+
* Decides what a write "through" the relation may touch: a shared target
|
|
1501
|
+
* belongs to every parent that links it, so the parent owns the *link* and not
|
|
1502
|
+
* the row. The backend enforces that (an unlink rather than a delete) and the
|
|
1503
|
+
* admin renders it (remove-from-parent rather than delete).
|
|
1504
|
+
*
|
|
1505
|
+
* Now a field on the resolved relation rather than a re-derivation, so both
|
|
1506
|
+
* sides read the same answer instead of each computing one.
|
|
1508
1507
|
*/
|
|
1509
1508
|
function isJunctionBackedRelation(relation) {
|
|
1510
|
-
return
|
|
1509
|
+
return relation.shared;
|
|
1511
1510
|
}
|
|
1512
1511
|
/** WeakMap cache — same collection instance always yields the same relation map. */
|
|
1513
1512
|
var _resolvedRelationsCache = /* @__PURE__ */ new WeakMap();
|
|
1513
|
+
/**
|
|
1514
|
+
* Every relation a collection declares, keyed by the name it is addressed by.
|
|
1515
|
+
*
|
|
1516
|
+
* A relation reaches the map from either of two places — the collection's
|
|
1517
|
+
* `relations` array, or a `relation` property that declares one inline — and is
|
|
1518
|
+
* keyed by its resolved `relationName`, which is what a nested path segment,
|
|
1519
|
+
* an `include` key and an admin tab all match against.
|
|
1520
|
+
*
|
|
1521
|
+
* Resolution no longer swallows failures. It used to wrap each relation in a
|
|
1522
|
+
* `try/catch` that dropped anything it could not work out, so a
|
|
1523
|
+
* mis-declared relation silently vanished instead of being reported; with the
|
|
1524
|
+
* kind declared, the only remaining failure is a `target` that does not resolve,
|
|
1525
|
+
* which is worth hearing about.
|
|
1526
|
+
*/
|
|
1514
1527
|
function resolveCollectionRelations(collection) {
|
|
1515
1528
|
const cached = _resolvedRelationsCache.get(collection);
|
|
1516
1529
|
if (cached) return cached;
|
|
1517
1530
|
if (!getDataSourceCapabilities(collection.engine).supportsRelations) return {};
|
|
1518
1531
|
const relations = {};
|
|
1519
|
-
const
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
});
|
|
1530
|
-
if (collection.properties) Object.entries(collection.properties).forEach(([propKey, prop]) => {
|
|
1531
|
-
const relation = resolvePropertyRelation({
|
|
1532
|
-
propertyKey: propKey,
|
|
1533
|
-
property: prop,
|
|
1534
|
-
sourceCollection: collection
|
|
1535
|
-
});
|
|
1536
|
-
if (relation) {
|
|
1537
|
-
if (relations[propKey]) return;
|
|
1538
|
-
if (!relation.relationName) relation.relationName = propKey;
|
|
1539
|
-
const normalizedRelation = sanitizeRelation(relation, collection);
|
|
1540
|
-
relations[propKey] = normalizedRelation;
|
|
1541
|
-
registeredRelationNames.add(normalizedRelation.relationName ?? propKey);
|
|
1542
|
-
}
|
|
1543
|
-
});
|
|
1532
|
+
for (const relation of collection.relations ?? []) {
|
|
1533
|
+
const resolved = resolveRelation(relation, collection);
|
|
1534
|
+
relations[resolved.relationName] = resolved;
|
|
1535
|
+
}
|
|
1536
|
+
for (const [propertyKey, property] of Object.entries(collection.properties ?? {})) {
|
|
1537
|
+
if (property?.type !== "relation") continue;
|
|
1538
|
+
const declared = property.relation;
|
|
1539
|
+
if (!declared || relations[propertyKey]) continue;
|
|
1540
|
+
relations[propertyKey] = resolveRelation(declared, collection, propertyKey);
|
|
1541
|
+
}
|
|
1544
1542
|
_resolvedRelationsCache.set(collection, relations);
|
|
1545
1543
|
return relations;
|
|
1546
1544
|
}
|
|
1547
|
-
function resolvePropertyRelation({ propertyKey, property, sourceCollection }) {
|
|
1548
|
-
if (property.type !== "relation") return void 0;
|
|
1549
|
-
const relProp = property;
|
|
1550
|
-
if (relProp.target) return {
|
|
1551
|
-
relationName: relProp.relationName || propertyKey,
|
|
1552
|
-
target: relProp.target,
|
|
1553
|
-
cardinality: relProp.cardinality || "one",
|
|
1554
|
-
direction: relProp.direction || "owning",
|
|
1555
|
-
inverseRelationName: relProp.inverseRelationName,
|
|
1556
|
-
localKey: relProp.localKey,
|
|
1557
|
-
foreignKeyOnTarget: relProp.foreignKeyOnTarget,
|
|
1558
|
-
through: relProp.through,
|
|
1559
|
-
joinPath: relProp.joinPath,
|
|
1560
|
-
onUpdate: relProp.onUpdate,
|
|
1561
|
-
onDelete: relProp.onDelete,
|
|
1562
|
-
overrides: relProp.overrides
|
|
1563
|
-
};
|
|
1564
|
-
console.warn(`Unrecognized or missing relation target for property '${propertyKey}' in collection '${sourceCollection.slug}'`);
|
|
1565
|
-
}
|
|
1566
1545
|
function getTableName(collection) {
|
|
1567
1546
|
if (getDataSourceCapabilities(collection.engine).supportsRelations) return collection.table ?? toSnakeCase(collection.slug) ?? toSnakeCase(collection.name);
|
|
1568
1547
|
return toSnakeCase(collection.slug) ?? toSnakeCase(collection.name);
|
|
@@ -1595,40 +1574,6 @@ function findRelation(resolvedRelations, key) {
|
|
|
1595
1574
|
//#endregion
|
|
1596
1575
|
//#region ../common/src/util/resolutions.ts
|
|
1597
1576
|
/**
|
|
1598
|
-
* Relation identities that only ever appear *below* the top level of
|
|
1599
|
-
* `properties` — inside a `map`, an `array`, or a `oneOf` branch.
|
|
1600
|
-
*
|
|
1601
|
-
* A relation declared at the top level is a list hanging off the record and
|
|
1602
|
-
* earns a tab. One declared inside a map is a field of that map. Both end up in
|
|
1603
|
-
* the collection's flat `relations` array after normalization, so the shape of
|
|
1604
|
-
* `properties` is the only remaining evidence of which is which.
|
|
1605
|
-
*
|
|
1606
|
-
* An identity declared in both places is *not* nested-only, and keeps its tab.
|
|
1607
|
-
*/
|
|
1608
|
-
function getNestedRelationIdentities(properties) {
|
|
1609
|
-
const topLevel = /* @__PURE__ */ new Set();
|
|
1610
|
-
const nested = /* @__PURE__ */ new Set();
|
|
1611
|
-
const walk = (props, depth) => {
|
|
1612
|
-
if (!props) return;
|
|
1613
|
-
for (const [key, property] of Object.entries(props)) {
|
|
1614
|
-
if (!property) continue;
|
|
1615
|
-
if (property.type === "relation") {
|
|
1616
|
-
const relProp = property;
|
|
1617
|
-
(depth === 0 ? topLevel : nested).add(relProp.relationName ?? key);
|
|
1618
|
-
} else if (property.type === "map") walk(property.properties, depth + 1);
|
|
1619
|
-
else if (property.type === "array") {
|
|
1620
|
-
const arrayProp = property;
|
|
1621
|
-
if (Array.isArray(arrayProp.of)) arrayProp.of.forEach((p) => walk({ entry: p }, depth + 1));
|
|
1622
|
-
else if (arrayProp.of) walk({ entry: arrayProp.of }, depth + 1);
|
|
1623
|
-
if (arrayProp.oneOf?.properties) walk(arrayProp.oneOf.properties, depth + 1);
|
|
1624
|
-
}
|
|
1625
|
-
}
|
|
1626
|
-
};
|
|
1627
|
-
walk(properties, 0);
|
|
1628
|
-
for (const identity of topLevel) nested.delete(identity);
|
|
1629
|
-
return nested;
|
|
1630
|
-
}
|
|
1631
|
-
/**
|
|
1632
1577
|
* The lists rendered inside an entity view of `collection` — its tabs.
|
|
1633
1578
|
*
|
|
1634
1579
|
* The single derivation. There used to be two that disagreed: this one, and a
|
|
@@ -1655,14 +1600,12 @@ function getEntityChildViews(collection) {
|
|
|
1655
1600
|
if (capabilities.supportsSubcollections && declaredSubcollections) return asSubcollections(declaredSubcollections() ?? []);
|
|
1656
1601
|
if (!capabilities.supportsRelations) return [];
|
|
1657
1602
|
const resolvedRelations = resolveCollectionRelations(collection);
|
|
1658
|
-
const nestedOnly = getNestedRelationIdentities(collection.properties);
|
|
1659
1603
|
const views = [];
|
|
1660
1604
|
const seen = /* @__PURE__ */ new Set();
|
|
1661
1605
|
for (const [relationKey, relation] of Object.entries(resolvedRelations)) {
|
|
1662
1606
|
if (relation.cardinality !== "many") continue;
|
|
1663
1607
|
const identity = relation.relationName ?? relationKey;
|
|
1664
1608
|
if (seen.has(identity)) continue;
|
|
1665
|
-
if (nestedOnly.has(identity)) continue;
|
|
1666
1609
|
let target;
|
|
1667
1610
|
try {
|
|
1668
1611
|
target = relation.target();
|
|
@@ -1671,7 +1614,7 @@ function getEntityChildViews(collection) {
|
|
|
1671
1614
|
}
|
|
1672
1615
|
if (!target) continue;
|
|
1673
1616
|
seen.add(identity);
|
|
1674
|
-
const customName = Object.entries(collection.properties ?? {}).find(([propKey, p]) => p.type === "relation" && (p.relationName ?? propKey) === identity)?.[1]?.name;
|
|
1617
|
+
const customName = Object.entries(collection.properties ?? {}).find(([propKey, p]) => p.type === "relation" && (p.relation?.relationName ?? propKey) === identity)?.[1]?.name;
|
|
1675
1618
|
const base = {
|
|
1676
1619
|
...target,
|
|
1677
1620
|
slug: relationKey,
|
|
@@ -2254,8 +2197,8 @@ function resolveJunctionSpecs(collections) {
|
|
|
2254
2197
|
for (const collection of collections) {
|
|
2255
2198
|
const resolved = resolveCollectionRelations(collection);
|
|
2256
2199
|
for (const relation of Object.values(resolved)) {
|
|
2257
|
-
if (!relation
|
|
2258
|
-
const targetCollection =
|
|
2200
|
+
if (!isManyToMany(relation)) continue;
|
|
2201
|
+
const targetCollection = relation.target();
|
|
2259
2202
|
if (!targetCollection) continue;
|
|
2260
2203
|
const rawName = relation.through.table;
|
|
2261
2204
|
const table = rawName.includes(".") ? rawName.split(".").pop() : rawName;
|
|
@@ -3297,88 +3240,33 @@ var CollectionRegistry = class {
|
|
|
3297
3240
|
if (!result.dataSource) result.dataSource = resolved.key;
|
|
3298
3241
|
if (!result.engine) result.engine = resolved.engine;
|
|
3299
3242
|
}
|
|
3300
|
-
|
|
3301
|
-
const relResult = result;
|
|
3302
|
-
const manualRelations = getDataSourceCapabilities(result.engine).supportsRelations ? relResult.relations ?? [] : [];
|
|
3303
|
-
const mergedRelationsRaw = [...extractedRelations];
|
|
3304
|
-
for (const manual of manualRelations) {
|
|
3305
|
-
const name = manual.relationName;
|
|
3306
|
-
if (!name) mergedRelationsRaw.push(manual);
|
|
3307
|
-
else {
|
|
3308
|
-
const existingIndex = mergedRelationsRaw.findIndex((r) => r.relationName === name);
|
|
3309
|
-
if (existingIndex === -1) mergedRelationsRaw.push(manual);
|
|
3310
|
-
else mergedRelationsRaw[existingIndex] = {
|
|
3311
|
-
...manual,
|
|
3312
|
-
...mergedRelationsRaw[existingIndex]
|
|
3313
|
-
};
|
|
3314
|
-
}
|
|
3315
|
-
}
|
|
3316
|
-
let mergedRelations = mergedRelationsRaw;
|
|
3317
|
-
if (getDataSourceCapabilities(result.engine).supportsRelations) {
|
|
3318
|
-
mergedRelations = mergedRelationsRaw.map((r) => {
|
|
3319
|
-
try {
|
|
3320
|
-
return sanitizeRelation(r, result, (slug) => this.get(slug));
|
|
3321
|
-
} catch {
|
|
3322
|
-
return r;
|
|
3323
|
-
}
|
|
3324
|
-
});
|
|
3325
|
-
relResult.relations = mergedRelations;
|
|
3326
|
-
}
|
|
3327
|
-
result.properties = this.normalizeProperties(result.properties, mergedRelations);
|
|
3243
|
+
result.properties = this.normalizeProperties(result.properties, result);
|
|
3328
3244
|
return result;
|
|
3329
3245
|
}
|
|
3330
|
-
|
|
3331
|
-
* Extract Relation[] from properties that have inline relation config (i.e. `target` is set).
|
|
3332
|
-
* This allows developers to define relations directly on properties without a separate
|
|
3333
|
-
* `relations[]` entry on the collection.
|
|
3334
|
-
*/
|
|
3335
|
-
extractRelationsFromProperties(properties) {
|
|
3336
|
-
const relations = [];
|
|
3337
|
-
for (const [key, property] of Object.entries(properties)) if (property.type === "relation") {
|
|
3338
|
-
const relProp = property;
|
|
3339
|
-
const target = relProp.target ?? relProp.relation?.target;
|
|
3340
|
-
if (target) {
|
|
3341
|
-
const relationName = relProp.relationName ?? relProp.relation?.relationName ?? key;
|
|
3342
|
-
relations.push({
|
|
3343
|
-
relationName,
|
|
3344
|
-
target,
|
|
3345
|
-
cardinality: relProp.cardinality ?? relProp.relation?.cardinality ?? "one",
|
|
3346
|
-
direction: relProp.direction ?? relProp.relation?.direction ?? "owning",
|
|
3347
|
-
inverseRelationName: relProp.inverseRelationName ?? relProp.relation?.inverseRelationName,
|
|
3348
|
-
localKey: relProp.localKey ?? relProp.relation?.localKey,
|
|
3349
|
-
foreignKeyOnTarget: relProp.foreignKeyOnTarget ?? relProp.relation?.foreignKeyOnTarget,
|
|
3350
|
-
through: relProp.through ?? relProp.relation?.through,
|
|
3351
|
-
joinPath: relProp.joinPath ?? relProp.relation?.joinPath,
|
|
3352
|
-
onUpdate: relProp.onUpdate ?? relProp.relation?.onUpdate,
|
|
3353
|
-
onDelete: relProp.onDelete ?? relProp.relation?.onDelete,
|
|
3354
|
-
overrides: relProp.overrides ?? relProp.relation?.overrides
|
|
3355
|
-
});
|
|
3356
|
-
}
|
|
3357
|
-
} else if (property.type === "map" && property.properties) relations.push(...this.extractRelationsFromProperties(property.properties));
|
|
3358
|
-
return relations;
|
|
3359
|
-
}
|
|
3360
|
-
normalizeProperties(properties, relations) {
|
|
3246
|
+
normalizeProperties(properties, collection) {
|
|
3361
3247
|
const newProperties = {};
|
|
3362
|
-
for (const key in properties) newProperties[key] = this.normalizeProperty(key, properties[key],
|
|
3248
|
+
for (const key in properties) newProperties[key] = this.normalizeProperty(key, properties[key], collection);
|
|
3363
3249
|
return newProperties;
|
|
3364
3250
|
}
|
|
3365
|
-
normalizeProperty(key, property,
|
|
3251
|
+
normalizeProperty(key, property, collection) {
|
|
3366
3252
|
const newProperty = { ...property };
|
|
3367
|
-
if (newProperty.type === "map" && newProperty.properties) newProperty.properties = this.normalizeProperties(newProperty.properties,
|
|
3253
|
+
if (newProperty.type === "map" && newProperty.properties) newProperty.properties = this.normalizeProperties(newProperty.properties, collection);
|
|
3368
3254
|
else if (newProperty.type === "array") {
|
|
3369
3255
|
const arrayProp = newProperty;
|
|
3370
|
-
if (arrayProp.of) if (Array.isArray(arrayProp.of)) arrayProp.of = arrayProp.of.map((p, i) => this.normalizeProperty(`${key}[${i}]`, p,
|
|
3371
|
-
else arrayProp.of = this.normalizeProperty(`${key}.of`, arrayProp.of,
|
|
3372
|
-
else if (arrayProp.oneOf && arrayProp.oneOf.properties) arrayProp.oneOf.properties = this.normalizeProperties(arrayProp.oneOf.properties,
|
|
3256
|
+
if (arrayProp.of) if (Array.isArray(arrayProp.of)) arrayProp.of = arrayProp.of.map((p, i) => this.normalizeProperty(`${key}[${i}]`, p, collection));
|
|
3257
|
+
else arrayProp.of = this.normalizeProperty(`${key}.of`, arrayProp.of, collection);
|
|
3258
|
+
else if (arrayProp.oneOf && arrayProp.oneOf.properties) arrayProp.oneOf.properties = this.normalizeProperties(arrayProp.oneOf.properties, collection);
|
|
3373
3259
|
} else if ((newProperty.type === "string" || newProperty.type === "number") && newProperty.enum) {
|
|
3374
3260
|
const stringOrNumberProperty = newProperty;
|
|
3375
3261
|
if (typeof stringOrNumberProperty.enum === "object" && !Array.isArray(stringOrNumberProperty.enum)) stringOrNumberProperty.enum = enumToObjectEntries(stringOrNumberProperty.enum)?.filter((value) => value && (value.id || value.id === 0) && value.label) ?? [];
|
|
3376
3262
|
} else if (newProperty.type === "relation") {
|
|
3377
3263
|
const relationProperty = newProperty;
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3264
|
+
if (relationProperty.relation) relationProperty.resolvedRelation = resolveRelation(relationProperty.relation, collection, key);
|
|
3265
|
+
else {
|
|
3266
|
+
const declared = resolveCollectionRelations(collection)[key];
|
|
3267
|
+
if (declared) relationProperty.resolvedRelation = declared;
|
|
3268
|
+
else console.warn(`Relation property '${key}' on '${collection.slug}' declares no \`relation\`, and the collection has no relation of that name.`);
|
|
3269
|
+
}
|
|
3382
3270
|
}
|
|
3383
3271
|
return newProperty;
|
|
3384
3272
|
}
|
|
@@ -4103,4 +3991,4 @@ async function detectJunctionTables(executeSql) {
|
|
|
4103
3991
|
//#endregion
|
|
4104
3992
|
export { DEFAULT_ONE_OF_TYPE as A, createRelationRefWithData as C, mergeDeep as D, getPolicyNamesForRule as E, camelCase as O, createRelationRef as S, updateDateAutoValues as T, getTableVarName as _, getJunctionCollectionConfig as a, getDeclaredPrimaryKeys as b, getEffectiveSecurityRules as c, securityRuleToConditions as d, findAnonymousGrants as f, getTableName as g, getEnumVarName as h, CollectionRegistry as i, DEFAULT_ONE_OF_VALUE as j, toSnakeCase as k, buildPropertyCallbacks as l, getColumnName as m, detectJunctionTables as n, getJunctionSecurityRules as o, findRelation as p, buildSdkData as r, resolveJunctionSpecs as s, classifyTable as t, policyToPostgres as u, resolveCollectionRelations as v, normalizeToEntityRelation as w, parseIdValues as x, buildCompositeId as y };
|
|
4105
3993
|
|
|
4106
|
-
//# sourceMappingURL=src-
|
|
3994
|
+
//# sourceMappingURL=src-3VmUJ8Xn.js.map
|