Skip to content

Commit d0a624c

Browse files
dmealingclaude
andcommitted
docs(migrate-ts): make referential-actions doc claims match reality
Final-reviewer Minor findings: - JSDoc claimed 'a test in this file guards [FkAction == REFERENTIAL_ACTIONS] at runtime', but no such test existed. Added it (1-line set-equality assert). - Inline-comment the bare-name correlation assumption next to the find(): the corpus uses bare entity names everywhere; an FQN value would silently lose intent. Cross-language ports should match the same correlation rule. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 992f01c commit d0a624c

2 files changed

Lines changed: 24 additions & 4 deletions

File tree

server/typescript/packages/migrate-ts/src/referential-actions.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ import { SetNullNotNullableError } from "./errors.js";
2929
*
3030
* The single `as FkAction` cast in normalize() is safe because REFERENTIAL_ACTIONS
3131
* (metadata package) and FkAction (migrate-ts/src/types.ts) are the same four-value
32-
* set: "cascade" | "set-null" | "restrict" | "no-action". The comment in
33-
* relationship-constants.ts documents this invariant; a test in this file guards it
34-
* at runtime.
32+
* set: "cascade" | "set-null" | "restrict" | "no-action". The invariant is
33+
* documented in relationship-constants.ts and enforced by both the type system
34+
* (FkAction is the union literal) and a runtime-set-equality test in
35+
* referential-actions.test.ts.
3536
*/
3637
export function resolveReferentialActions(
3738
entity: MetaObject,
@@ -40,6 +41,13 @@ export function resolveReferentialActions(
4041
const target = ref.targetEntity;
4142
if (target === undefined) return { onDelete: undefined, onUpdate: undefined };
4243

44+
// Correlation is by exact-string match. Every fixture in the corpus uses
45+
// bare entity names for @objectRef and @references (no `::`-FQN form), so
46+
// bare-vs-bare matching is sufficient today. If a future author writes an
47+
// FQN value on either side, this find returns undefined and both actions
48+
// resolve to undefined (no clause emitted) — surfacing the mismatch as a
49+
// silent loss of intent rather than a wrong action. Cross-language ports
50+
// should match the same correlation rule.
4351
const rel = entity.relationships().find((r) => r.objectRef === target);
4452
if (rel === undefined) return { onDelete: undefined, onUpdate: undefined };
4553

server/typescript/packages/migrate-ts/test/unit/referential-actions.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,19 @@ import { resolveReferentialActions } from "../../src/referential-actions.js";
33
import { buildExpectedSchema } from "../../src/expected-schema.js";
44
import { diff } from "../../src/diff/index.js";
55
import { emit } from "../../src/emit/index.js";
6-
import { MetaDataLoader, InMemorySource } from "@metaobjectsdev/metadata";
6+
import { MetaDataLoader, InMemorySource, REFERENTIAL_ACTIONS } from "@metaobjectsdev/metadata";
7+
8+
// Invariant referenced by the as-FkAction cast in resolveReferentialActions:
9+
// REFERENTIAL_ACTIONS (metadata) and FkAction (migrate-ts) MUST be the same
10+
// four-value kebab-case set. Tested here so a cross-package divergence is
11+
// caught immediately rather than silently shipping wrong DDL.
12+
describe("REFERENTIAL_ACTIONS / FkAction invariant", () => {
13+
test("REFERENTIAL_ACTIONS is exactly the FkAction union literal set", () => {
14+
expect([...REFERENTIAL_ACTIONS].sort()).toEqual(
15+
["cascade", "no-action", "restrict", "set-null"],
16+
);
17+
});
18+
});
719

820
async function loadDoc(doc: unknown) {
921
return new MetaDataLoader().load([new InMemorySource(JSON.stringify(doc))]);

0 commit comments

Comments
 (0)