Skip to content

refactor(web_core): validate catalog entries through Standard Schema - #30

Closed
louis-bompart wants to merge 1 commit into
claude/zod-scope/loaded-entry-viewsfrom
claude/zod-scope/standard-validation
Closed

louis-bompart wants to merge 1 commit into
claude/zod-scope/loaded-entry-viewsfrom
claude/zod-scope/standard-validation

Conversation

@louis-bompart

Copy link
Copy Markdown
Collaborator

Description

This PR is the first half of Layer 4, stacked on #29. The core now validates catalog entries and themes as synchronous Standard Schema validators instead of through the Zod API. The schema compiled from a catalog definition no longer has to be a Zod schema for the core to use it, which the compiler seam in the second half of Layer 4 needs.

  • componentSchemaOf, functionSchemaOf and themeSchemaOf return an A2uiValidator instead of a Zod type. The loader still compiles to Zod 3, which implements Standard Schema.
  • validateEntry replaces safeParseEntry. It validates with the schema compiled from the entry's document, then with the entry's own Zod 3 or library schema, through validateA2uiSchema, and returns the Standard Schema result. A JSON Schema object adds nothing to the document's check, as before.
  • PayloadValidator formats issues with formatA2uiSchemaIssue, which formats a Zod issue exactly as formatZodIssue does. The function invoker writes the issues as indented JSON, as a Zod error's message did.
  • Inspection takes an InspectableSchema: an entry's own EntrySchema, or a validator compiled from a definition. GenericBinder binds a compiled validator through its definition (hasDefinitionView). Its constructor's parameter type widens, so existing callers are unaffected.

What changes for callers. For an entry whose own schema comes from another library, A2uiValidationError.details and the details of a function argument error now hold that library's issues as it reports them. Before, they were converted to Zod issues. This matches what the protocol validators of #26 expose. The changelog says so.

The common-type checks in PayloadValidator (accessibility attributes, component metadata) still use their Zod mirrors. They belong to the core, not to a catalog, and move with the core's own Zod later.

The second half of Layer 4 comes next: Catalog.fromJson() takes a compiler that turns a resolved definition into a validator, with an Ajv test compiler.

Validation

  • yarn build
  • node --test "dist/**/*.test.js": 1285 passing, 0 failing, 21 todo
  • node tests/conformance/conformance_test.mjs: all vectors passing
  • yarn lint: 0 errors
  • yarn format:check
  • yarn test in typescript/catalogs/{mcp,vegachart}, typescript/renderers/{lit,react} and typescript/agents/a2ui_agent. Angular passes apart from test:closure-compiler, which needs Java 21.
  • Validation unchanged. I validated 10,497 payloads with the code at refactor(web_core): inspect loaded entries through their definitions #29's tip and with this PR, and the results are identical: the same accepted values, and the same formatted messages for the 10,140 rejections. The payloads cover every component and function of the 61 catalog documents in the repository and of the code basic catalogs v0.9 and v1.0: an empty object, null, a string, an unknown key, and eight kinds of value for each declared property.
  • Unchanged from refactor(web_core): inspect loaded entries through their definitions #29: the compiled Zod schemas of those catalogs (1,790 entries) and their binding views (5,625 results).
  • validateEntry tests cover:
    • checks only the own schema expresses;
    • the document's failure reported first;
    • the own schema's defaults in the result;
    • a library schema validated through Standard Schema;
    • a JSON Schema object adding nothing.

Part of a2ui-project#2160

Pre-launch Checklist

One time:

For this PR:

  • I have updated the relevant CHANGELOG.md file.
  • I updated/added relevant documentation.
  • My code changes (if any) have tests.
  • If my branch is on a fork, I have verified that scripts/e2e_test.sh passes.

🤖 Generated with Claude Code

The core now validates a catalog entry or theme as a synchronous Standard
Schema validator rather than through the Zod API, so the schema compiled
from a catalog definition no longer has to be a Zod schema for the core to
use it.

componentSchemaOf, functionSchemaOf and themeSchemaOf return an A2uiValidator.
validateEntry replaces safeParseEntry: it validates with the document's
schema, then with the entry's own Zod 3 or library schema, and returns the
Standard Schema result. PayloadValidator formats its issues with
formatA2uiSchemaIssue, which formats a Zod issue exactly as formatZodIssue
does, and the function invoker writes them as a Zod error's message did.

Inspection takes an InspectableSchema, an entry's own schema or a validator
compiled from a definition, and GenericBinder binds such a validator
through its definition.

For every component and function of the 61 catalog documents in the
repository and the code basic catalogs, 10,497 payloads validate with the
same results and messages as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@louis-bompart

Copy link
Copy Markdown
Collaborator Author

Superseded by the regrouped stack on upstream main: this change is now part of #51 (series #45 to #54). The branch is kept for reference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant