Skip to content

refactor(web_core_v1_0): build catalog JSON Schema in core - #14

Closed
louis-bompart wants to merge 3 commits into
unzod/9-catalog-basic-zod4from
unzod/10-schema-zod-v4-json-schema
Closed

louis-bompart wants to merge 3 commits into
unzod/9-catalog-basic-zod4from
unzod/10-schema-zod-v4-json-schema

Conversation

@louis-bompart

Copy link
Copy Markdown
Collaborator

Summary

The basic catalog gets validationSchema back, and Zod 4 catalogs defined in code get toJson, validationSchema and inline catalogs. To avoid writing the JSON Schema code a second time for Zod 4, this PR moves the library-neutral part of it from @a2ui/schema-zod into core.

What moves into core

Five new modules in @a2ui/web_core_v1_0/src/catalog/, about 1,500 lines. The JSON parts came from @a2ui/schema-zod's schema_serializer.ts, schema_generator.ts, schema_loader.ts and spec_shape.ts.

Module Contents
catalog_document.ts The document model, toJson, retainedDefs and the unions
validation_schema.ts validationSchema and cleanSchemaNode
catalog_refs.ts $ref resolution across a document and its peers, and hasCrossDocumentRefs
json_schema_rules.ts Standard definitions by protocol version, and schemaRequiresArgs
entry_definitions.ts The definitions that JSON-loaded entries came from

Adapter contract

Member Change
toJsonSchema(schema) Added. Converts one schema. REF: description pointers stay in, and core turns them into $refs.
reproduceDefinitions(catalog) Added, optional. Supplies the definitions a library's models reproduce exactly. Only the Zod 3 spec() models use it.
commonTypeRefDescriptions Added, optional. The descriptions the adapter's common type mirrors carry.
serializeCatalog, generateValidationSchema, retainedDefs Removed. Core does this now.
schemaToJson, cleanSchemaNode Removed. These were the Zod-shaped pair that MessageProcessor called for legacy inline catalogs; it now uses toJsonSchema and core's cleanSchemaNode.

A catalog that carries its published document (CatalogOptions.document, from #13) builds its model from that document, so it needs no schema conversion. This is how the basic catalog gets validationSchema back.

Commits

  1. refactor(web_core_v1_0): build catalog JSON Schema in core. This is the move. @a2ui/schema-zod keeps only the Zod 3 parts: the conversion, the spec() shaper (now behind reproduceDefinitions) and the JSON-to-Zod loader, which imports the shared $ref handling from core. The 260 @a2ui/schema-zod tests pass unchanged. They include the integration tests that moved there in refactor(web_core_v1_0): pass schema adapters explicitly #10, such as peer catalogs, serialization and validation schemas.
  2. feat(schema-zod-v4): convert Zod 4 schemas to JSON Schema. toJsonSchema is built on z.toJSONSchema with io: 'input'. A test checks that the Zod 4 and Zod 3 adapters produce identical toJson and validationSchema for the same catalog.
  3. feat(catalog-basic): restore validationSchema on Zod 4.
    • Function descriptions: the generator now writes each function's description even when it isn't reproducing the document. A function description is part of its API, and the validation schema reads it.
    • Parity test: basicCatalog.validationSchema equals what the Zod 3 adapter builds from the published document, except for $defs.theme. The published document declares no theme; the catalog adds its own BasicCatalogThemeSchema, as it did on Zod 3.

Things to review

  • New public API in core. Core's catalog barrel now exports the shared JSON helpers that adapters need: inlinePeerAndLocalRefs, PeerScope, resolveJsonPointer, buildComponentUnion, setLoadedDefinition, standardDefsForVersion and others. That's the cost of letting any adapter reuse them.
  • @a2ui/schema-zod no longer exports inlinePeerAndLocalRefs. Core exports it instead. Nothing in the repository imported it from @a2ui/schema-zod.
  • MIRROR_REF_DESCRIPTIONS became an adapter member rather than being computed from core's standard definitions. Two of the 18 mirror descriptions (DynamicBoolean, Surface) differ from the standard text, so computing them in core would have changed the output.

Validation

Each commit was built from clean, then linted, format-checked and tested. The first commit was also tested with schema-zod-v4 and catalog-basic as they are on #13: 13/13 and 102/102. Lint has no errors.

Package Tests on #13 Tests here
@a2ui/web_core_v1_0 261 261
@a2ui/schema-zod 260 (+4 timing) 260 (+4 timing)
@a2ui/schema-zod-v4 13 16
@a2ui/catalog-basic 102 103

🤖 Generated with Claude Code

louis-bompart and others added 3 commits October 27, 2026 01:17
Assembling a catalog document and bundling its validation schema is
JSON work: `$ref` handling, peer catalogs, common type bundling, unions
and the protocol's rules about function arguments. It lived in
@a2ui/schema-zod, so every other schema adapter would have had to
rewrite it. It now lives in core:

- catalog_document.ts: the document model, `toJson` and `retainedDefs`
- validation_schema.ts: `validationSchema` and `cleanSchemaNode`
- catalog_refs.ts: `$ref` resolution across a document and its peers,
  with `hasCrossDocumentRefs`
- json_schema_rules.ts: standard definitions by protocol version, and
  `schemaRequiresArgs`
- entry_definitions.ts: the definitions JSON-loaded entries came from

An adapter now only converts one schema (`toJsonSchema`). It may also
reproduce definitions its models record exactly (`reproduceDefinitions`,
the Zod 3 `spec()` models), and name the descriptions its common type
mirrors carry (`commonTypeRefDescriptions`). `serializeCatalog`,
`generateValidationSchema`, `retainedDefs`, `schemaToJson` and
`cleanSchemaNode` leave the contract.

A catalog that carries its published document builds its model from that
document, so its `validationSchema` needs no conversion at all.

@a2ui/schema-zod keeps the Zod 3 parts: the conversion, the `spec()`
shaper and the JSON-to-Zod loader. Its 260 tests pass unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Zod 4 adapter implements `toJsonSchema` with `z.toJSONSchema`,
describing the values a payload may carry (`io: 'input'`), and names the
descriptions its common type mirrors carry. Core then writes `toJson`,
`validationSchema` and inline catalogs for Zod 4 catalogs defined in
code. The `REF:` descriptions of the common types survive the
conversion, so they come out as references to common_types.json.

A test checks that the Zod 4 and Zod 3 adapters write the same
`toJson` and `validationSchema` for the same catalog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The basic catalog carries its published document, from which core now
builds `validationSchema` without converting any schema.

The generator writes each function's `description` whether or not it
reproduces the document; it is part of the function's API, and the
validation schema reads it.

A test checks that the validation schema equals the one the Zod 3
adapter builds from the published document, apart from the theme: the
document declares none, and the catalog adds its own
`BasicCatalogThemeSchema`.

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