Skip to content

feat(routing): accept zod 4 route schemas - #68

Merged
UberMouse merged 1 commit into
masterfrom
zod4-peer
Sep 1, 2026
Merged

UberMouse merged 1 commit into
masterfrom
zod4-peer

Conversation

@UberMouse

@UberMouse UberMouse commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Why

koordinates is moving its zod schemas to zod 4 (via the zod/v4 subpath of zod 3.25 first, then a real bump). Route paramsSchema/querySchema are typed here as zod 3's Z.ZodObject<any>, which a zod 4 schema does not satisfy, so the moment @kx/routes passes zod 4 schemas every route's params and query degrade to { [x: string]: any } and ~45 typecheck errors appear across its consumers.

What

  • createRoute no longer imports zod. Schemas are typed against a structural RouteSchema (_output, parse, merge), which is exactly what routing uses and which both zod 3 and zod 4 classic schemas expose. RouteSchema is exported (root, routing, createRoute barrels) so consumers' emitted declarations can name it.
  • peerDependencies.zod widens from ^3.x to ^3.x || ^4.x. Nothing changes for zod 3 callers; existing routing specs are untouched and still pass.
  • New createRoute.zod4.spec.ts drives simpleRoute with zod/v4 schemas: typed params/query, and a parent-merged parse that rejects bad params. The dev zod moves to 3.25.76 so that subpath exists in-repo.
  • xstate-tree.api.md regenerated (api-extractor --local).

Verification

  • npm run lint -- --fix: 0 errors.
  • npm test: 135/135 (one Link › preloading timing test flaked once and passed on re-run; unrelated).
  • npm run build and npm run api-extractor -- --local: clean.
  • npm run test-examples fails on master already (App.tsx / TodosMachine.tsx inState and useIsRouteActive.spec event.params); this branch adds no new errors there.
  • Validated against kawaka by dropping the built lib/xstate-tree.d.ts over the installed 5.6.0: @kx/routes on zod/v4 typechecks clean and its 209 tests pass, and the downstream route-typing errors clear.

Notes

  • _output is deprecated in zod 4 in favour of z.output<>, but it is still declared on every classic schema and is the only version-independent type marker available. If zod 5 drops it, RouteSchema is the single place to update.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Xa9BAPFheAQLJwta16v67z

Route `paramsSchema`/`querySchema` were typed as zod 3's `Z.ZodObject<any>`, which
zod 4 schemas do not satisfy, so a consumer moving its schemas to zod 4 (or the
`zod/v4` subpath of zod 3.25) lost every route's params/query types. 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.

`createRoute.zod4.spec.ts` drives `simpleRoute` with `zod/v4` schemas (typed
params/query, and a parent-merged parse rejecting bad params) 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
@UberMouse
UberMouse merged commit 9573278 into master Sep 1, 2026
1 check passed
@UberMouse
UberMouse deleted the zod4-peer branch September 1, 2026 23:54
github-actions Bot pushed a commit that referenced this pull request Sep 2, 2026
# [4.12.0](v4.11.1...v4.12.0) (2026-09-02)

### build

* typecheck with TypeScript 5.0.2 and skipLibCheck, as master does ([a89f290](a89f290))

### feat

* **routing:** accept zod 4 route schemas ([4a27d80](4a27d80)), closes [#68](#68)
* **routing:** accept zod 4 route schemas (4.x) ([b11d273](b11d273))
github-actions Bot pushed a commit that referenced this pull request Sep 2, 2026
# [5.7.0](v5.6.0...v5.7.0) (2026-09-02)

### chore

* **release:** revert the half-published 5.7.0 release commit ([727baa4](727baa4))
* **release:** revert the half-published 5.7.0 release commit ([81b6c78](81b6c78)), closes [#68](#68) [#68](#68)

### feat

* **routing:** accept zod 4 route schemas ([9573278](9573278))
* **routing:** accept zod 4 route schemas ([90a2303](90a2303))
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 5.7.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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant