@metaobjectsdev/migrate-ts 1.0.3 → 1.0.4
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.
|
@@ -35,7 +35,12 @@ export declare function isRequired(field: MetaData): boolean;
|
|
|
35
35
|
* omits actions when the DB value is "no-action", so the expected side does the same
|
|
36
36
|
* to keep round-trip diffs clean.
|
|
37
37
|
*
|
|
38
|
-
*
|
|
38
|
+
* When more than one relationship targets the same entity (Match.homeTeam /
|
|
39
|
+
* awayTeam both -> Team), each is correlated to its OWN identity.reference via
|
|
40
|
+
* the shared relationship<->reference ladder (#368 round 2) — never the first
|
|
41
|
+
* match. When the correlation is genuinely ambiguous, it contributes nothing
|
|
42
|
+
* rather than an arbitrary — possibly wrong — action (see the tier-2/tier-3
|
|
43
|
+
* bodies below for the exact rules).
|
|
39
44
|
*
|
|
40
45
|
* The single `as FkAction` cast in normalize() is safe because REFERENTIAL_ACTIONS
|
|
41
46
|
* (metadata package) and FkAction (migrate-ts/src/types.ts) are the same four-value
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"referential-actions.d.ts","sourceRoot":"","sources":["../src/referential-actions.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"referential-actions.d.ts","sourceRoot":"","sources":["../src/referential-actions.ts"],"names":[],"mappings":"AAAA,OAAO,EAUL,KAAK,UAAU,EAEf,KAAK,qBAAqB,EAC1B,KAAK,QAAQ,EACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAO3C,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,EAAE,CAO/D;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAKhF;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAOnD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,qBAAqB,GACzB;IAAE,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAA;CAAE,CA8FpE;AAiFD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,qBAAqB,EAC1B,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAC9B,cAAc,EAAE,MAAM,GACrB,IAAI,CAeN"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ON_DELETE_DEFAULT_BY_SUBTYPE, ON_UPDATE_DEFAULT, FIELD_ATTR_REQUIRED, IDENTITY_ATTR_FIELDS, TYPE_VALIDATOR, VALIDATOR_SUBTYPE_REQUIRED, refMatchesObject, resolveObjectRef, } from "@metaobjectsdev/metadata";
|
|
1
|
+
import { ON_DELETE_DEFAULT_BY_SUBTYPE, ON_UPDATE_DEFAULT, FIELD_ATTR_REQUIRED, IDENTITY_ATTR_FIELDS, TYPE_VALIDATOR, VALIDATOR_SUBTYPE_REQUIRED, refMatchesObject, resolveObjectRef, resolveRelationshipReference, } from "@metaobjectsdev/metadata";
|
|
2
2
|
import { SetNullNotNullableError } from "./errors.js";
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
// Shared field helpers — exported for use by expected-schema.ts
|
|
@@ -59,7 +59,12 @@ export function isRequired(field) {
|
|
|
59
59
|
* omits actions when the DB value is "no-action", so the expected side does the same
|
|
60
60
|
* to keep round-trip diffs clean.
|
|
61
61
|
*
|
|
62
|
-
*
|
|
62
|
+
* When more than one relationship targets the same entity (Match.homeTeam /
|
|
63
|
+
* awayTeam both -> Team), each is correlated to its OWN identity.reference via
|
|
64
|
+
* the shared relationship<->reference ladder (#368 round 2) — never the first
|
|
65
|
+
* match. When the correlation is genuinely ambiguous, it contributes nothing
|
|
66
|
+
* rather than an arbitrary — possibly wrong — action (see the tier-2/tier-3
|
|
67
|
+
* bodies below for the exact rules).
|
|
63
68
|
*
|
|
64
69
|
* The single `as FkAction` cast in normalize() is safe because REFERENTIAL_ACTIONS
|
|
65
70
|
* (metadata package) and FkAction (migrate-ts/src/types.ts) are the same four-value
|
|
@@ -93,6 +98,18 @@ export function resolveReferentialActions(entity, ref) {
|
|
|
93
98
|
// When the target does not resolve (dangling @references — normally a
|
|
94
99
|
// load error), fall back to the legacy exact-string match so behavior on
|
|
95
100
|
// partially-valid trees is unchanged.
|
|
101
|
+
//
|
|
102
|
+
// #368 (round 2): `entity` may declare MORE THAN ONE identity.reference
|
|
103
|
+
// onto this same target (Match.homeTeamRef / awayTeamRef both -> Team).
|
|
104
|
+
// Matching `r` on the target alone can't say which of those references
|
|
105
|
+
// `r` supplies actions FOR — every FK past the first silently inherited
|
|
106
|
+
// the first relationship's actions. Resolve it with the INVERSE of the
|
|
107
|
+
// relationship->reference ladder (resolveRelationshipReference): `r`
|
|
108
|
+
// belongs to `ref` iff the ladder, applied to `r`, resolves back to
|
|
109
|
+
// `ref` itself — not merely "resolves to *some* reference on this
|
|
110
|
+
// target". `r` and `ref` are always declared on the same `entity`, the
|
|
111
|
+
// exact shape the ladder is built for, so this is a direct inversion,
|
|
112
|
+
// not a second parallel rule.
|
|
96
113
|
// (3) Failing that, correlate the REVERSE relationship declared on the
|
|
97
114
|
// TARGET entity (the documented parent-side authoring shape).
|
|
98
115
|
let rel = entity.relationships().find((r) => {
|
|
@@ -105,7 +122,9 @@ export function resolveReferentialActions(entity, ref) {
|
|
|
105
122
|
return objectRef === target;
|
|
106
123
|
const relOwner = r.parent ?? entity;
|
|
107
124
|
const relOwnerPkg = relOwner.package ?? relOwner.fileDefaultPackage ?? "";
|
|
108
|
-
|
|
125
|
+
if (!refMatchesObject(targetObj, objectRef, relOwnerPkg))
|
|
126
|
+
return false;
|
|
127
|
+
return resolveRelationshipReference(entity, r.name, objectRef, r.sourceRefField) === ref;
|
|
109
128
|
});
|
|
110
129
|
// When the tier-3 satisfiability guard fires, the reverse relationship's
|
|
111
130
|
// AUTHORED @onUpdate still applies (only the inferred contributions drop).
|
|
@@ -160,9 +179,19 @@ export function resolveReferentialActions(entity, ref) {
|
|
|
160
179
|
* same target, the reverse relationship cannot say WHICH FK carries the
|
|
161
180
|
* ownership edge, so it contributes to none of them (arming every FK could
|
|
162
181
|
* cascade through an edge the author never designated).
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
182
|
+
* - When the TARGET entity declares more than one non-@through relationship
|
|
183
|
+
* back at `entity` (rare — e.g. a "posts" composition and a separate
|
|
184
|
+
* "latestPost" association both @objectRef-ing Post), no candidate is
|
|
185
|
+
* preferred: this is the tier-2 ambiguity's mirror image (multiple
|
|
186
|
+
* RELATIONSHIPS rather than multiple REFERENCES), and it cannot be
|
|
187
|
+
* resolved by the relationship->reference ladder — that ladder picks among
|
|
188
|
+
* references declared on the SAME object as the relationship, whereas here
|
|
189
|
+
* the candidate relationships live on `targetObj` while `ref` lives on
|
|
190
|
+
* `entity`, a different object, so the ladder has no candidates to apply
|
|
191
|
+
* to. Previously this used the FIRST match (the same silently-wrong-schema
|
|
192
|
+
* defect as tier 2); it now fails closed like the guard above, once the
|
|
193
|
+
* ambiguity guard above has already established `ref` is the entity's only
|
|
194
|
+
* candidate reference to this target.
|
|
166
195
|
*/
|
|
167
196
|
function findReverseRelationship(entity, ref, targetObj) {
|
|
168
197
|
const root = entity.parent;
|
|
@@ -184,7 +213,11 @@ function findReverseRelationship(entity, ref, targetObj) {
|
|
|
184
213
|
return undefined;
|
|
185
214
|
// The reverse relationship's bare @objectRef resolves in ITS declaring
|
|
186
215
|
// owner's package (normally the target entity's own package).
|
|
187
|
-
|
|
216
|
+
//
|
|
217
|
+
// Fail closed on ambiguity rather than taking the first match: if more than
|
|
218
|
+
// one non-@through relationship on targetObj resolves back to `entity`,
|
|
219
|
+
// none of them is preferred (see the class doc above).
|
|
220
|
+
const reverseCandidates = targetObj.relationships().filter((r) => {
|
|
188
221
|
if (r.through !== undefined)
|
|
189
222
|
return false; // M:N — junction path, not this FK
|
|
190
223
|
const objectRef = r.objectRef;
|
|
@@ -194,6 +227,7 @@ function findReverseRelationship(entity, ref, targetObj) {
|
|
|
194
227
|
const relOwnerPkg = relOwner.package ?? relOwner.fileDefaultPackage ?? "";
|
|
195
228
|
return refMatchesObject(entity, objectRef, relOwnerPkg);
|
|
196
229
|
});
|
|
230
|
+
return reverseCandidates.length === 1 ? reverseCandidates[0] : undefined;
|
|
197
231
|
}
|
|
198
232
|
function normalize(a) {
|
|
199
233
|
if (a === undefined)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"referential-actions.js","sourceRoot":"","sources":["../src/referential-actions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,0BAA0B,EAC1B,gBAAgB,EAChB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"referential-actions.js","sourceRoot":"","sources":["../src/referential-actions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,0BAA0B,EAC1B,gBAAgB,EAChB,gBAAgB,EAChB,4BAA4B,GAK7B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAEtD,8EAA8E;AAC9E,gEAAgE;AAChE,8EAA8E;AAE9E,MAAM,UAAU,kBAAkB,CAAC,QAAkB;IACnD,kFAAkF;IAClF,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAChD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3E,6EAA6E;IAC7E,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACpG,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAkB,EAAE,IAAY;IACxD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;IACxC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAe;IACxC,uFAAuF;IACvF,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAC7C,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAClD,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC,IAAI,CAC1B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,IAAI,CAAC,CAAC,OAAO,KAAK,0BAA0B,CAC7E,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAAkB,EAClB,GAA0B;IAE1B,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC;IAChC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAE9E,kEAAkE;IAClE,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC;IACjC,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC;IAEjC,uEAAuE;IACvE,4EAA4E;IAC5E,6EAA6E;IAC7E,6EAA6E;IAC7E,4EAA4E;IAC5E,0CAA0C;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC;IACtC,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,kBAAkB,IAAI,EAAE,CAAC;IAC1E,MAAM,SAAS,GACb,IAAI,KAAK,SAAS,CAAC,CAAC,CAAE,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,IAA+B,CAAC,CAAC,CAAC,SAAS,CAAC;IAEhH,2EAA2E;IAC3E,wEAAwE;IACxE,uEAAuE;IACvE,0EAA0E;IAC1E,6EAA6E;IAC7E,0EAA0E;IAC1E,6EAA6E;IAC7E,0CAA0C;IAC1C,EAAE;IACF,4EAA4E;IAC5E,4EAA4E;IAC5E,2EAA2E;IAC3E,4EAA4E;IAC5E,2EAA2E;IAC3E,yEAAyE;IACzE,wEAAwE;IACxE,sEAAsE;IACtE,2EAA2E;IAC3E,0EAA0E;IAC1E,kCAAkC;IAClC,uEAAuE;IACvE,kEAAkE;IAClE,IAAI,GAAG,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;QAC1C,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAC1C,MAAM,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;QAC9B,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAC1C,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,SAAS,KAAK,MAAM,CAAC;QACzD,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC;QACpC,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,kBAAkB,IAAI,EAAE,CAAC;QAC1E,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC;YAAE,OAAO,KAAK,CAAC;QACvE,OAAO,4BAA4B,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,cAAc,CAAC,KAAK,GAAG,CAAC;IAC3F,CAAC,CAAC,CAAC;IACH,yEAAyE;IACzE,2EAA2E;IAC3E,IAAI,yBAA6C,CAAC;IAClD,IAAI,GAAG,KAAK,SAAS,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QACjD,MAAM,OAAO,GAAG,uBAAuB,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAChE,2EAA2E;QAC3E,uEAAuE;QACvE,0EAA0E;QAC1E,0EAA0E;QAC1E,wEAAwE;QACxE,2EAA2E;QAC3E,yEAAyE;QACzE,wEAAwE;QACxE,wEAAwE;QACxE,0DAA0D;QAC1D,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,4BAA4B,GAChC,OAAO,CAAC,QAAQ,KAAK,SAAS;gBAC9B,4BAA4B,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,UAAU;gBAC5D,kBAAkB,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;oBACtC,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;oBACxC,OAAO,KAAK,KAAK,SAAS,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;gBAClD,CAAC,CAAC,CAAC;YACL,IAAI,4BAA4B,EAAE,CAAC;gBACjC,yBAAyB,GAAG,OAAO,CAAC,QAAQ,CAAC;YAC/C,CAAC;iBAAM,CAAC;gBACN,GAAG,GAAG,OAAO,CAAC;YAChB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GACf,WAAW;QACX,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,IAAI,4BAA4B,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAClF,MAAM,WAAW,GACf,WAAW;QACX,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC;IAE1E,OAAO;QACL,QAAQ,EAAE,SAAS,CAAC,WAAW,CAAC;QAChC,QAAQ,EAAE,SAAS,CAAC,WAAW,CAAC;KACjC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,SAAS,uBAAuB,CAC9B,MAAkB,EAClB,GAA0B,EAC1B,SAAqB;IAErB,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3B,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAEzC,wEAAwE;IACxE,uCAAuC;IACvC,MAAM,YAAY,GAAG,MAAM,CAAC,mBAAmB,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QAC7D,IAAI,CAAC,CAAC,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAC7B,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC;QACzB,IAAI,CAAC,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAClC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC;QACjC,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,kBAAkB,IAAI,EAAE,CAAC;QACjE,OAAO,gBAAgB,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;IAChE,CAAC,CAAC,CAAC;IACH,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,OAAO,SAAS,CAAC;IAE3E,uEAAuE;IACvE,8DAA8D;IAC9D,EAAE;IACF,4EAA4E;IAC5E,wEAAwE;IACxE,uDAAuD;IACvD,MAAM,iBAAiB,GAAG,SAAS,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QAC/D,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC,CAAC,mCAAmC;QAC9E,MAAM,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;QAC9B,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAC1C,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,IAAI,SAAS,CAAC;QACvC,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,kBAAkB,IAAI,EAAE,CAAC;QAC1E,OAAO,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IACH,OAAO,iBAAiB,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3E,CAAC;AAED,SAAS,SAAS,CAAC,CAAqB;IACtC,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACtC,+EAA+E;IAC/E,+EAA+E;IAC/E,gFAAgF;IAChF,6EAA6E;IAC7E,IAAI,CAAC,KAAK,WAAW;QAAE,OAAO,SAAS,CAAC;IACxC,OAAO,CAAa,CAAC;AACvB,CAAC;AAED,8EAA8E;AAC9E,4BAA4B;AAC5B,8EAA8E;AAE9E;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAAkB,EAClB,GAA0B,EAC1B,QAA8B,EAC9B,cAAsB;IAEtB,IAAI,QAAQ,KAAK,UAAU;QAAE,OAAO;IAEpC,MAAM,cAAc,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACxC,IAAI,KAAK,KAAK,SAAS,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7C,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,uBAAuB,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,SAAS,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metaobjectsdev/migrate-ts",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Schema migration tooling for MetaObjects: diff metadata vs DB and emit SQL for Postgres and SQLite.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@iarna/toml": "^2.2.5",
|
|
48
|
-
"@metaobjectsdev/metadata": "1.0.
|
|
48
|
+
"@metaobjectsdev/metadata": "1.0.4"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"kysely": ">=0.27.0 <0.30.0",
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
VALIDATOR_SUBTYPE_REQUIRED,
|
|
8
8
|
refMatchesObject,
|
|
9
9
|
resolveObjectRef,
|
|
10
|
+
resolveRelationshipReference,
|
|
10
11
|
type MetaObject,
|
|
11
12
|
type MetaRelationship,
|
|
12
13
|
type MetaReferenceIdentity,
|
|
@@ -76,7 +77,12 @@ export function isRequired(field: MetaData): boolean {
|
|
|
76
77
|
* omits actions when the DB value is "no-action", so the expected side does the same
|
|
77
78
|
* to keep round-trip diffs clean.
|
|
78
79
|
*
|
|
79
|
-
*
|
|
80
|
+
* When more than one relationship targets the same entity (Match.homeTeam /
|
|
81
|
+
* awayTeam both -> Team), each is correlated to its OWN identity.reference via
|
|
82
|
+
* the shared relationship<->reference ladder (#368 round 2) — never the first
|
|
83
|
+
* match. When the correlation is genuinely ambiguous, it contributes nothing
|
|
84
|
+
* rather than an arbitrary — possibly wrong — action (see the tier-2/tier-3
|
|
85
|
+
* bodies below for the exact rules).
|
|
80
86
|
*
|
|
81
87
|
* The single `as FkAction` cast in normalize() is safe because REFERENTIAL_ACTIONS
|
|
82
88
|
* (metadata package) and FkAction (migrate-ts/src/types.ts) are the same four-value
|
|
@@ -116,6 +122,18 @@ export function resolveReferentialActions(
|
|
|
116
122
|
// When the target does not resolve (dangling @references — normally a
|
|
117
123
|
// load error), fall back to the legacy exact-string match so behavior on
|
|
118
124
|
// partially-valid trees is unchanged.
|
|
125
|
+
//
|
|
126
|
+
// #368 (round 2): `entity` may declare MORE THAN ONE identity.reference
|
|
127
|
+
// onto this same target (Match.homeTeamRef / awayTeamRef both -> Team).
|
|
128
|
+
// Matching `r` on the target alone can't say which of those references
|
|
129
|
+
// `r` supplies actions FOR — every FK past the first silently inherited
|
|
130
|
+
// the first relationship's actions. Resolve it with the INVERSE of the
|
|
131
|
+
// relationship->reference ladder (resolveRelationshipReference): `r`
|
|
132
|
+
// belongs to `ref` iff the ladder, applied to `r`, resolves back to
|
|
133
|
+
// `ref` itself — not merely "resolves to *some* reference on this
|
|
134
|
+
// target". `r` and `ref` are always declared on the same `entity`, the
|
|
135
|
+
// exact shape the ladder is built for, so this is a direct inversion,
|
|
136
|
+
// not a second parallel rule.
|
|
119
137
|
// (3) Failing that, correlate the REVERSE relationship declared on the
|
|
120
138
|
// TARGET entity (the documented parent-side authoring shape).
|
|
121
139
|
let rel = entity.relationships().find((r) => {
|
|
@@ -125,7 +143,8 @@ export function resolveReferentialActions(
|
|
|
125
143
|
if (targetObj === undefined) return objectRef === target;
|
|
126
144
|
const relOwner = r.parent ?? entity;
|
|
127
145
|
const relOwnerPkg = relOwner.package ?? relOwner.fileDefaultPackage ?? "";
|
|
128
|
-
|
|
146
|
+
if (!refMatchesObject(targetObj, objectRef, relOwnerPkg)) return false;
|
|
147
|
+
return resolveRelationshipReference(entity, r.name, objectRef, r.sourceRefField) === ref;
|
|
129
148
|
});
|
|
130
149
|
// When the tier-3 satisfiability guard fires, the reverse relationship's
|
|
131
150
|
// AUTHORED @onUpdate still applies (only the inferred contributions drop).
|
|
@@ -185,9 +204,19 @@ export function resolveReferentialActions(
|
|
|
185
204
|
* same target, the reverse relationship cannot say WHICH FK carries the
|
|
186
205
|
* ownership edge, so it contributes to none of them (arming every FK could
|
|
187
206
|
* cascade through an edge the author never designated).
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
207
|
+
* - When the TARGET entity declares more than one non-@through relationship
|
|
208
|
+
* back at `entity` (rare — e.g. a "posts" composition and a separate
|
|
209
|
+
* "latestPost" association both @objectRef-ing Post), no candidate is
|
|
210
|
+
* preferred: this is the tier-2 ambiguity's mirror image (multiple
|
|
211
|
+
* RELATIONSHIPS rather than multiple REFERENCES), and it cannot be
|
|
212
|
+
* resolved by the relationship->reference ladder — that ladder picks among
|
|
213
|
+
* references declared on the SAME object as the relationship, whereas here
|
|
214
|
+
* the candidate relationships live on `targetObj` while `ref` lives on
|
|
215
|
+
* `entity`, a different object, so the ladder has no candidates to apply
|
|
216
|
+
* to. Previously this used the FIRST match (the same silently-wrong-schema
|
|
217
|
+
* defect as tier 2); it now fails closed like the guard above, once the
|
|
218
|
+
* ambiguity guard above has already established `ref` is the entity's only
|
|
219
|
+
* candidate reference to this target.
|
|
191
220
|
*/
|
|
192
221
|
function findReverseRelationship(
|
|
193
222
|
entity: MetaObject,
|
|
@@ -211,7 +240,11 @@ function findReverseRelationship(
|
|
|
211
240
|
|
|
212
241
|
// The reverse relationship's bare @objectRef resolves in ITS declaring
|
|
213
242
|
// owner's package (normally the target entity's own package).
|
|
214
|
-
|
|
243
|
+
//
|
|
244
|
+
// Fail closed on ambiguity rather than taking the first match: if more than
|
|
245
|
+
// one non-@through relationship on targetObj resolves back to `entity`,
|
|
246
|
+
// none of them is preferred (see the class doc above).
|
|
247
|
+
const reverseCandidates = targetObj.relationships().filter((r) => {
|
|
215
248
|
if (r.through !== undefined) return false; // M:N — junction path, not this FK
|
|
216
249
|
const objectRef = r.objectRef;
|
|
217
250
|
if (objectRef === undefined) return false;
|
|
@@ -219,6 +252,7 @@ function findReverseRelationship(
|
|
|
219
252
|
const relOwnerPkg = relOwner.package ?? relOwner.fileDefaultPackage ?? "";
|
|
220
253
|
return refMatchesObject(entity, objectRef, relOwnerPkg);
|
|
221
254
|
});
|
|
255
|
+
return reverseCandidates.length === 1 ? reverseCandidates[0] : undefined;
|
|
222
256
|
}
|
|
223
257
|
|
|
224
258
|
function normalize(a: string | undefined): FkAction | undefined {
|