Skip to content

Commit 9057811

Browse files
fix(lint): relationship/delete-behavior suggestion drops set_null on master_detail (#13668)
The `relationship/delete-behavior` suggestion in `lintDataModel` told an author an undeclared `master_detail.deleteBehavior` could be `cascade`, `restrict`, or `set_null`. Since #9689 (PR #11406, maintainer ruling 2026-08-19), an authored `deleteBehavior: 'set_null'` on a `master_detail` field is a named parse-time rejection, so following the suggestion literally walked an author into a publish-time error. The message now enumerates only the two values FieldSchema actually accepts on a master_detail (cascade/restrict — matching object.form.ts's master_detail deleteBehavior options), and keeps the outcome-naming courtesy of the parse-time rejection message: it still names set_null to say plainly it is not honored on this type, and points to `lookup` for the case where children must survive the parent. The `fix` payload was already correct and is unchanged. Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC Co-authored-by: Claude <noreply@anthropic.com>
1 parent 2cce3fd commit 9057811

3 files changed

Lines changed: 32 additions & 1 deletion

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
"@objectstack/lint": patch
3+
---
4+
5+
fix(lint): `relationship/delete-behavior` suggestion no longer names `set_null` as declarable on a `master_detail`
6+
7+
`lintDataModel`'s `relationship/delete-behavior` suggestion told an author an
8+
undeclared `master_detail.deleteBehavior` could be `cascade`, `restrict`, or
9+
`set_null`. Since #9689 (PR #11406, maintainer ruling 2026-08-19), an authored
10+
`deleteBehavior: 'set_null'` on a `master_detail` field is a named parse-time
11+
rejection — a detail row cannot outlive its master, so the engine resolves
12+
every value except `restrict` to `cascade` on this type. Following the
13+
suggestion's own `set_null` mention literally walked an author into that
14+
rejection at publish time.
15+
16+
The message now enumerates only the two values `FieldSchema` actually accepts
17+
on a `master_detail` (`cascade`/`restrict` — matching the vocabulary already
18+
offered by the metadata-admin field form, `object.form.ts`'s `master_detail`
19+
`deleteBehavior` options), and keeps the same outcome-naming courtesy as the
20+
parse-time rejection message: it still names `set_null` to say plainly that it
21+
is not honored on this type, and points to `lookup` for the case where
22+
children must survive the parent. The `fix` payload (`deleteBehavior:
23+
'cascade'`) was already correct and is unchanged.

packages/cli/test/data-model-rules.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ describe('lintDataModel — relationships', () => {
4040
]);
4141
const db = issues.find((i) => i.rule === 'relationship/delete-behavior');
4242
expect(db?.severity).toBe('suggestion');
43+
// #9689 (PR #11406) made an authored `deleteBehavior: 'set_null'` on a
44+
// master_detail a named parse-time rejection — the DECLARABLE enumeration
45+
// this suggestion names must not walk an author into that rejection. The
46+
// message may still MENTION `set_null` to explain why it is excluded (the
47+
// same outcome-naming courtesy as the field.zod.ts rejection message), so
48+
// assert the declarable set directly rather than a bare substring-absence.
49+
expect(db?.message).not.toContain('cascade/restrict/set_null');
50+
expect(db?.message).toContain('(cascade/restrict');
4351
});
4452

4553
it('suggests inlineEdit on master_detail line-item children', () => {

packages/lint/src/data-model-rules.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ export function lintDataModel(objects: any[]): LintIssue[] {
604604
issues.push({
605605
severity: 'suggestion',
606606
rule: 'relationship/delete-behavior',
607-
message: `master_detail "${obj.name}.${fieldName}" → ${parent} should declare deleteBehavior (cascade/restrict/set_null)`,
607+
message: `master_detail "${obj.name}.${fieldName}" → ${parent} should declare deleteBehavior (cascade/restrictset_null is not honored on master_detail; use a lookup field if children must survive the parent)`,
608608
path: `${fieldPath}.deleteBehavior`,
609609
fix: "deleteBehavior: 'cascade'",
610610
});

0 commit comments

Comments
 (0)