fix: rewrite defineLinks @example to pass validation#2
Conversation
The public @example showed `'posts[]': { to: 'posts' }` as a validated link path. After housekeeping #10 hardened validateResourceDefinition to reject bare terminal `[]` segments, copying this example verbatim throws `Array segment 'posts[]' cannot be terminal.` at runtime. Rewrite the example to be self-contained: show UserSchema with a `posts` field of shape `Type.Array(Type.Object({ href: Type.String() }))` and use the `'posts[].href'` link path, matching the canonical idiom used in examples/petshop-api.ts. Addresses FINDING-01 from code review. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
feffef
left a comment
There was a problem hiding this comment.
Opus Reviewer (on behalf of @feffef): LGTM — the rewritten @example is correct and well-scoped. (Cannot formally approve: GitHub blocks self-approval on own PRs.)
Correctness (mentally simulated against validateResourceDefinition):
- Path
posts[].hrefon the inlineUserSchemaresolves as:posts(Array) → unwrap items →{ href: String }→href(String). The terminal-array guard at src/link-definition.ts:248 is not triggered (finalPropertyishref), andTypeGuard.IsString(resolved)is true. The example PASSES validation. to: 'posts'is in the declared names list;links: {}on the posts resource (only a commented-out negative example) is a valid empty record.
Idiom consistency: 'posts[].href' matches the canonical 'pets[].href' pattern in examples/petshop-api.ts:91.
Tutorial quality: Major improvement over the original. Showing posts: Type.Array(Type.Object({ href: Type.String() })) alongside the link path posts[].href makes the schema-shape-to-link-path relationship unambiguous — exactly the "implicit schema trap" the solution doc flagged.
Scope / side effects: Only the @example JSDoc block for defineLinks was touched. Signature, @param tags, ApiDefinition JSDoc, and the rest of the file are unchanged. No CHANGELOG entry needed (example-only edits are explicitly exempt per AGENTS.md).
Minor nit (non-blocking): The original had three didactic comments in the posts resource (✓ validated, ✗ TS error, ✗ runtime error) illustrating all three validation layers. The rewrite keeps only the TS-error case. Not worth blocking on — the users block's "Validated at compile and runtime" comment covers the concept.
Approach B from the solution doc was applied faithfully. Ship it.
Finding
FINDING-01 | WARNING | Style / Documentation
Location:
src/link-definition.ts:128-146(JSDoc) vssrc/link-definition.ts:242-255(validation)The public
@exampleondefineLinksshows'posts[]': { to: 'posts' }— a bare array-terminal link path.validateResourceDefinitionwas recently hardened (housekeeping #10, marked DONE) to reject terminal[]segments with the messageArray segment 'posts[]' cannot be terminal.Concrete impact: if a user reads the JSDoc, copies the example into their own API definition, and runs it, the call throws at runtime with the validator error — before their code ever makes an HTTP request. The tutorial-style example is the opposite of helpful: it's a trap.
Approach chosen: B — Rewrite example to be self-contained
The implicit schema dependency was the real trap. The previous minimal-patch fix (
posts[]→posts[].href) would compile but leave readers unsure why the suffix is required. The rewrite explicitly shows the schema shape (posts: Type.Array(Type.Object({ href: ... }))) so the'posts[].href'path is self-documenting, matching the canonical idiom used inexamples/petshop-api.ts.Alternatives considered
'posts[]'→'posts[].href'only. Rejected because the reader still has no visibility into what schema shape enables the path — they'd likely hit the same class of error the first time they write a different path. The rewrite removes the implicit knowledge assumption.Test plan
npx jest— all existing tests passnpm run typecheck— compilation succeeds'posts[].href'on the rewritten schema resolves toType.String()terminal;validateResourceDefinitionaccepts it.Review checklist