Skip to content

refactor(web_core_v1_0): pass schema adapters explicitly - #10

Closed
louis-bompart wants to merge 3 commits into
unzod/5-remove-zod-runtimefrom
unzod/6-explicit-schema-adapter
Closed

louis-bompart wants to merge 3 commits into
unzod/5-remove-zod-runtimefrom
unzod/6-explicit-schema-adapter

Conversation

@louis-bompart

Copy link
Copy Markdown
Collaborator

Summary

Importing @a2ui/schema-zod used to register its adapter in a global slot, which core read from 16 call sites. The package declares "sideEffects": false, so a bundler could drop that import. The result also depended on import order. This PR removes the global slot: each adapter is now passed explicitly.

  • CatalogOptions.schemaAdapter gives each catalog the adapter for its schemas. Every schema operation on a catalog goes through requireSchemaAdapter. When the adapter is missing, the error names the catalog and the operation.
  • MessageProcessorOptions.schemaAdapter supplies the protocol schema. When it isn't set, the processor uses the adapter its catalogs share.
  • Catalog.fromJson(json, {schemaAdapter, protocolVersion?, catalogId?}) now requires an adapter. schema-zod adds parseZodCatalog(json) as a shorthand. The deprecated Catalog.fromSchema is removed.
  • linkCatalogs rejects catalogs that use different adapters.
  • An empty catalog's reference map no longer needs an adapter.
  • Removed: registerCatalogSchemaAdapter, getCatalogSchemaAdapter, installZodCatalogSchemaAdapter, and the integrity-checker functions that only forwarded to the registry.
  • The basic catalog passes zodCatalogSchemaAdapter explicitly.

Commits

  1. fix(web_core_v1_0): reject unknown @index arguments again. refactor(web_core_v1_0): remove Zod runtime dependency #9 replaced the @index schema with a hand-written one. The Zod adapter can't read that schema's keys, so {offset: 1, foo: 2} was accepted. Functions can now declare argumentKeys, and @index declares offset. This commit doesn't depend on the other two, so it could also go into refactor(web_core_v1_0): remove Zod runtime dependency #9.
  2. refactor(web_core_v1_0): pass schema adapters explicitly. This is the change described above. Core's tests no longer import Zod or @a2ui/schema-zod, which removes the build cycle: before, core's tests needed schema-zod built, and schema-zod needed core built.
    • Tests that check behavior with Zod schemas move unchanged to schema-zod/src/integration/. They import core only through @a2ui/web_core_v1_0.
    • The timing suite moves to schema-zod/tests/timing.
    • Where Zod was incidental, core's tests use a small hand-written Standard Schema.
  3. test(schema-zod): guard the schema adapter boundary.
    • An ESLint rule in core rejects imports of zod, zod-to-json-schema, json-schema-to-zod and @a2ui/schema-zod.
    • A new test bundles a consumer with esbuild, which honours "sideEffects": false, then runs the bundle and checks that it renders.

Reviewing commit by commit is easiest. In commit 2, the files under schema-zod/src/integration/ differ from their originals only in imports, new ZodCatalog(...) in place of new Catalog(...), and parseZodCatalog(...) in place of Catalog.fromJson(...).

Validation

Each commit was built from clean, then linted, format-checked and tested on its own. Lint has no errors; the existing warnings are unchanged.

Package Tests before Tests after
@a2ui/web_core_v1_0 473 250
@a2ui/schema-zod 20 256 (plus 4 in yarn test:timing)
@a2ui/catalog-basic 80 80

The totals are 573 before and 586 after: 12 new tests in core and the bundling test. Core now builds and tests with schema-zod not built at all.

Not in this PR

  • Core still needs an adapter to resolve components, because child references come from extractRefFields. Reading schemaMetadata.childRefs first would allow catalogs written with other schema libraries.
  • Core can't validate protocol messages without an adapter. A Zod-free v1.0 message validator in core would be a separate change.
  • Core's package.json still has a test:conformance script, but refactor(web_core): isolate v1.0 core package #5 removed the wireit configuration it runs.

🤖 Generated with Claude Code

louis-bompart and others added 3 commits October 27, 2026 00:07
The hand-written `@index` schema is not a Zod schema, so the Zod adapter
cannot reflect its keys and `validateFunctionArgs` stopped rejecting
unknown arguments such as `{offset: 1, foo: 2}`.

Functions can now declare `argumentKeys`. Argument validation uses them
before asking a schema adapter, and `@index` declares `offset`.
`createFunctionImplementation` carries the field through.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Importing @a2ui/schema-zod used to register its adapter in a global slot
that core read from 16 call sites. The package declared
"sideEffects": false, so a bundler could drop that import, and the
result depended on import order.

Core now holds no adapter of its own:

- `CatalogOptions.schemaAdapter` gives each catalog the adapter its
  schemas were written for. Serializing, validating against, linking and
  resolving a catalog's components use it, through `requireSchemaAdapter`,
  which names the catalog and the missing operation when it fails.
- `MessageProcessorOptions.schemaAdapter` supplies the protocol schema,
  and defaults to the adapter the catalogs share.
- `Catalog.fromJson` takes the adapter in its options. schema-zod adds
  `parseZodCatalog` as the shorthand.
- `linkCatalogs` rejects catalogs with different adapters.
- An empty catalog's reference map needs no adapter.
- The global registry, and the integrity-checker helpers that only
  forwarded to it, are removed.

schema-zod no longer registers anything on import, and the basic catalog
passes `zodCatalogSchemaAdapter` explicitly.

Core's tests no longer import Zod or schema-zod, which also removes the
build cycle where core's tests needed schema-zod and schema-zod needed
core. Tests that check behavior with Zod schemas move to
schema-zod/src/integration and the timing suite to schema-zod/tests.
Where Zod was incidental, core's tests use a small hand-written schema.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Core's ESLint config rejects imports of zod, zod-to-json-schema,
  json-schema-to-zod and @a2ui/schema-zod, so core stays schema-library
  neutral.
- A schema-zod test bundles a consumer with esbuild, which trusts
  "sideEffects": false, runs the bundle, and checks it renders. The
  consumer wires the Zod adapter only through values it uses, so the test
  shows that explicit wiring survives tree shaking.

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