Skip to content

feat(routing): accept zod 4 route schemas (4.x) - #69

Merged
UberMouse merged 2 commits into
4.xfrom
zod4-peer-4x
Sep 2, 2026
Merged

UberMouse merged 2 commits into
4.xfrom
zod4-peer-4x

Conversation

@UberMouse

@UberMouse UberMouse commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Why

4.x port of #68 (master). koordinates hosts its remaining v4 machines under a v5 routing root and hands v5 routes to v4 APIs (useIsRouteActive in v4RoutingShim.spec, a v4 consumer in browse-data's standalone dataset sheet spec). That cross-line assignability only holds while both lines spell AnyRoute.paramsSchema identically, so once 5.x moves to the structural RouteSchema, 4.x has to as well or those call sites fail with RouteSchema<any> is missing _cached, _getCached, _parse, shape, and 49 more.

What

Same change as #68, applied to 4.x:

  • createRoute drops its zod import; schemas are typed against the structural RouteSchema (_output, parse, merge), exported from the root, routing and createRoute barrels.
  • peerDependencies.zod widens from ^3.x to ^3.x || ^4.x.
  • createRoute.zod4.spec.ts drives simpleRoute with zod/v4 schemas; dev zod moves to 3.25.76 so that subpath exists in-repo.
  • xstate-tree.api.md regenerated.

Verification

  • npm run lint -- --fix: 0 errors.
  • npm test: 120/120.
  • npm run build and npm run api-extractor -- --local: clean.
  • Validated in koordinates by dropping the built lib/xstate-tree.d.ts over the installed 4.11.1 alongside feat(routing): accept zod 4 route schemas #68's over 5.6.0: @kx/xstate typechecks clean again.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Xa9BAPFheAQLJwta16v67z

UberMouse and others added 2 commits September 2, 2026 11:03
4.x port of the same change on master (PR #68). Route `paramsSchema`/`querySchema`
were typed as zod 3's `Z.ZodObject<any>`, which zod 4 schemas do not satisfy. Routing
only ever calls `parse` and `merge` on a schema and reads its `_output` marker, and
both zod majors expose all three, so the schema type is now the structural
`RouteSchema` and the `zod` import is gone from the routing source. The peer range
widens to `^3.x || ^4.x`; nothing changes for zod 3 callers.

The 4.x line needs this as well as 5.x because a consumer that hosts v4 machines
under a v5 routing root (kawaka's `hostV4Machine`) hands v5 routes to v4 APIs such as
`useIsRouteActive`; that assignability only held while both lines spelled the schema
type identically.

`createRoute.zod4.spec.ts` drives `simpleRoute` with `zod/v4` schemas so the
compatibility is tested rather than assumed; the dev `zod` moves to 3.25.76 to make
that subpath available in-repo.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xa9BAPFheAQLJwta16v67z
`test-examples` runs `tsc --noEmit` over src and examples, which now includes
`createRoute.zod4.spec.ts`. That spec imports `zod/v4`, whose declarations use
`const` type parameters (TypeScript 5.0) and `NoInfer` (5.4), so the 4.x line's
TypeScript ^4.7 fails to parse them and 5.0 still cannot check them. master
already typechecks with TypeScript 5.0.2 and `skipLibCheck: true`; this brings 4.x
to the same configuration. Only in-repo typechecking changes; the published
declarations no longer mention zod at all.

lint, test, test-examples, build and api-extractor all pass locally with this.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xa9BAPFheAQLJwta16v67z
@UberMouse

Copy link
Copy Markdown
Collaborator Author

CI failed at test-examples: tsc --noEmit includes createRoute.zod4.spec.ts, whose zod/v4 import pulls in declarations that use const type parameters (TS 5.0) and NoInfer (TS 5.4). The 4.x line was on TypeScript ^4.7 with no skipLibCheck, so it could neither parse nor check them; master is on 5.0.2 with skipLibCheck: true and passed.

a89f290 brings 4.x to master's configuration (TypeScript 5.0.2 + skipLibCheck). Only in-repo typechecking changes; the published declarations no longer reference zod. lint / test / test-examples / build / api-extractor all pass locally.

The alternative was excluding the spec from the root tsconfig and leaving TS 4.x alone; say if you would rather do that.

@UberMouse
UberMouse merged commit b11d273 into 4.x Sep 2, 2026
1 check passed
@UberMouse
UberMouse deleted the zod4-peer-4x branch September 2, 2026 00:00
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 4.12.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant