Skip to content

refactor(web_core_v1_0): read component structure from catalog metadata - #11

Closed
louis-bompart wants to merge 2 commits into
unzod/6-explicit-schema-adapterfrom
unzod/7-describe-component
Closed

louis-bompart wants to merge 2 commits into
unzod/6-explicit-schema-adapterfrom
unzod/7-describe-component

Conversation

@louis-bompart

Copy link
Copy Markdown
Collaborator

Summary

Core used to ask the catalog's schema adapter about a component's schema wherever it needed an answer:

  • child references, on every resolve;
  • property behavior, in each binder;
  • declared keys, in each payload check;
  • the integrity checks' reference map.

The adapter had to be there at runtime, and each answer came from the schema library's internals (_def.typeName for Zod 3).

Now the catalog holds that information as plain data:

  • Catalog.getComponentMetadata(name) returns a component's CompleteComponentSchemaMetadata: child references, behavior, and the new propertyKeys.
    • Complete schemaMetadata on the component is used as is.
    • Otherwise the catalog calls its adapter's new describeComponent once and keeps the result. Fields the component does carry take precedence.
  • Core reads only metadata: NodeResolver, GenericBinder, PayloadValidator, A2uiController and componentRefMap never ask the adapter for structure.
  • A catalog whose components carry complete metadata renders without a schema adapter. A core test renders one, with no adapter on the catalog and only a protocol schema supplied to the processor.

Validation is unchanged: core still calls schema['~standard'].validate directly, so error messages come from the schema library.

Adapter contract

describeComponent replaces the per-call reflection members: extractRefFields, getSchemaBehavior, buildComponentRefMap, analyzeChildRefSchema, isChildSchema, isChildListSchema and isChildOrChildListSchema. It also drops extractRefDefName, which core never called. Core's scrapeSchemaBehavior and buildComponentRefMap exports go too.

What remains is tooling (parseCatalog, serializeCatalog, generateValidationSchema, linkEntry, retainedDefs, hasCrossDocumentRefs, schemaToJson, cleanSchemaNode), the protocol schema, envelope validation, and getKnownSchemaKeys for function arguments.

A behavior change to review

The Zod adapter used to read child references two ways:

  • The resolver (extractRefFields) recognized Zod markers and REF: pointers.
  • The integrity checks (buildComponentRefMap) also recognized bare definition names, such as z.string().describe('ChildComponentId').

So a property named only that way was checked for cycles and dangling references, but never resolved as a child.

With a single metadata source, describeZodComponent combines both readings, and the resolver's kind wins where both read a property. Such properties now resolve as children. Generated catalogs, including the basic catalog, use markers, so they are unaffected; the parity test below checks that for the basic catalog.

Commits

  1. refactor(web_core_v1_0): read component structure from catalog metadata: the core change, describeZodComponent, and removal of the now-unused Zod reflection helpers. The basic catalog still works at this commit: its metadata lacks propertyKeys, so it falls back to describeComponent.
  2. feat(catalog-basic): ship complete component metadata: the generator emits propertyKeys, and the regenerated file differs only by those arrays. A test checks that every component's metadata is complete and matches what the Zod adapter derives from its schema.

Validation

Each commit was built from clean, then linted, format-checked and tested on its own. Lint has no errors, and the warning counts went down slightly.

Package Tests on #10 Tests here
@a2ui/web_core_v1_0 250 256
@a2ui/schema-zod 256 (+4 timing) 260 (+4 timing)
@a2ui/catalog-basic 80 99

Not in this PR

  • Function arguments still go through the adapter's getKnownSchemaKeys unless the function declares argumentKeys.
  • Protocol validation still needs an adapter that supplies getProtocolSchema.

🤖 Generated with Claude Code

louis-bompart and others added 2 commits October 27, 2026 00:35
Core used to ask the catalog's schema adapter about a component's schema
wherever it needed an answer: child references on every resolve,
property behavior in each binder, declared keys in each payload check,
and the reference map. The adapter had to be present at runtime, and its
answers depended on the schema library's private representation.

`Catalog.getComponentMetadata(name)` now answers those questions from
plain data. A component that ships complete `schemaMetadata` (behavior
and the new `propertyKeys`) is used as is. Otherwise the catalog asks its
adapter's new `describeComponent` once and keeps the result, with the
fields the component does carry taking precedence. The resolver, the
binder, the payload validator, the Lit controller and `componentRefMap`
read that metadata. A catalog whose components carry complete metadata
renders without a schema adapter.

`describeComponent` replaces the adapter's per-call reflection:
`extractRefFields`, `getSchemaBehavior`, `buildComponentRefMap`,
`analyzeChildRefSchema`, the `isChild*` checks and the unused
`extractRefDefName`. Core's `scrapeSchemaBehavior` and
`buildComponentRefMap` exports go with them.

The Zod adapter's `describeZodComponent` reads child references the way
both of its former readings did: the resolver's, by marker and `REF:`
pointer, and the integrity checks', which also accepts a bare definition
name such as `describe('ChildComponentId')`. Where both read a property,
the resolver's kind wins. Before, a property named only by definition was
checked as a child reference but never resolved as one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The generator now emits `propertyKeys`, the properties each generated Zod
object declares, so every basic catalog component carries complete
`schemaMetadata` and the catalog never asks its schema adapter to
describe one.

A test checks that each component's metadata is complete, and that its
child references and property keys match what the Zod adapter derives
from the component's schema.

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

Copy link
Copy Markdown
Collaborator Author

Closing: this earlier attempt at moving web_core off Zod 3 is superseded by the regrouped 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