From 79007b38f4f09813e3d61a493fd24410064ec944 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 3 Sep 2026 18:43:33 +0000 Subject: [PATCH] docs(spec): describe() for SpecialOperator $null and $exists (#14048) SpecialOperatorSchema declared both members as bare z.boolean().optional() with a JSDoc comment and no .describe(), so the reference page's Description column -- filled from prop.description, the JSON-Schema projection of a Zod .describe() -- rendered both cells empty. The published page therefore said nothing about the operator pair whose meaning was the subject of a six-site correction campaign. Each member gains a .describe(); the JSDoc stays. Regenerating with check:generated --fix touched exactly two rows of content/docs/references/data/filter.mdx and nothing else. Prose only: no accept/reject or shape change, the JSON-Schema delta is a description string on two properties. Wording written against scripts/check-corpus-claim-drift.mjs rather than into it: its exists-key-presence row reads 4 sites before this diff and 4 after the page was regenerated. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_0174WZTU6XcFcS7g2kykC53i --- .changeset/spec-special-operator-describe.md | 29 ++++++++++++++++++++ content/docs/references/data/filter.mdx | 4 +-- packages/spec/src/data/filter.zod.ts | 14 ++++++++-- 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 .changeset/spec-special-operator-describe.md diff --git a/.changeset/spec-special-operator-describe.md b/.changeset/spec-special-operator-describe.md new file mode 100644 index 0000000000..464d06afa2 --- /dev/null +++ b/.changeset/spec-special-operator-describe.md @@ -0,0 +1,29 @@ +--- +'@objectstack/spec': patch +--- + +docs(spec): `SpecialOperator` gains the `.describe()` that puts `$null` / `$exists` on the reference page (#14048) + +`SpecialOperatorSchema` declared both members as bare `z.boolean().optional()` with a +JSDoc comment and no `.describe()`. `content/docs/references/data/filter.mdx` fills its +Description column from `prop.description` — the JSON-Schema projection of a Zod +`.describe()` — so both cells rendered **empty**, and the published reference page said +nothing whatsoever about the two operators whose meaning was the subject of a six-site +correction campaign (#13539, #13709). A reader could not learn from that page that +`$exists` asks whether the field HAS A VALUE. + +Each member now carries a `.describe()`; the JSDoc stays as the source of truth it +already was and the describe restates it. The regenerated page gains exactly two +Description cells (`filter.mdx:138-139`) and nothing else. + +Prose only. No accept/reject or shape change: both members were and stay +`z.boolean().optional()`, so the only JSON-Schema delta is a `description` string on two +properties. Verified on a freshly built `dist`: `check:generated` reported +`content/docs/references/**` as the single stale artifact and `--fix` regenerated only +`filter.mdx`; `check:api-surface`, `check:export-origins` and `check:authorable-surface` +stayed green with no new export. + +The wording was written against `scripts/check-corpus-claim-drift.mjs` rather than into +it: that shrink-only ratchet watches `content/docs/**` for `$exists` prose, its +`exists-key-presence` row reads `exists-key-presence 4` both before this diff and after +the page was regenerated, so the new prose adds zero claim sites. diff --git a/content/docs/references/data/filter.mdx b/content/docs/references/data/filter.mdx index 0de8978293..9108f33569 100644 --- a/content/docs/references/data/filter.mdx +++ b/content/docs/references/data/filter.mdx @@ -135,8 +135,8 @@ Type: `[FilterArray](#filterarray)[]` | Property | Type | Required | Description | | :--- | :--- | :--- | :--- | -| **$null** | `boolean` | optional | | -| **$exists** | `boolean` | optional | | +| **$null** | `boolean` | optional | Is-null check. `true` matches rows where the field is null, `false` matches rows where it is not null. Lowered to `IS NULL` (true) / `IS NOT NULL` (false) on the SQL family and to `{ field: null }` (true) / `{ $ne: null }` (false) on MongoDB. | +| **$exists** | `boolean` | optional | Has-a-value check — the exact inverse of `$null`. `true` matches rows where the field holds a value (`!= null`), `false` matches rows where it holds none. Portable across every backend the platform ships: lowered to `IS NOT NULL` (true) / `IS NULL` (false) on the SQL family and to `{ $ne: null }` (true) / `{ $eq: null }` (false) on MongoDB. | --- diff --git a/packages/spec/src/data/filter.zod.ts b/packages/spec/src/data/filter.zod.ts index 5ee9861d85..88b8ae966b 100644 --- a/packages/spec/src/data/filter.zod.ts +++ b/packages/spec/src/data/filter.zod.ts @@ -1025,14 +1025,24 @@ export function likePatternToGlobPattern(pattern: string): string { */ export const SpecialOperatorSchema = lazySchema(() => z.object({ /** Is null check - SQL: IS NULL (true) / IS NOT NULL (false) | MongoDB: field: null */ - $null: z.boolean().optional(), + $null: z.boolean().optional().describe( + 'Is-null check. `true` matches rows where the field is null, `false` matches rows ' + + 'where it is not null. Lowered to `IS NULL` (true) / `IS NOT NULL` (false) on the ' + + 'SQL family and to `{ field: null }` (true) / `{ $ne: null }` (false) on MongoDB.' + ), /** * Field HAS A VALUE (`!= null`) — the inverse of `$null`, never key presence. * Lowered to `IS NOT NULL` (true) / `IS NULL` (false) on SQL and to * `{$ne: null}` / `{$eq: null}` on MongoDB. */ - $exists: z.boolean().optional(), + $exists: z.boolean().optional().describe( + 'Has-a-value check — the exact inverse of `$null`. `true` matches rows where the ' + + 'field holds a value (`!= null`), `false` matches rows where it holds none. ' + + 'Portable across every backend the platform ships: lowered to `IS NOT NULL` (true) / ' + + '`IS NULL` (false) on the SQL family and to `{ $ne: null }` (true) / ' + + '`{ $eq: null }` (false) on MongoDB.' + ), })); // ============================================================================