Symptom
In 3.6.x, consuming @zenstackhq/server/nuxt from a project on a newer h3 (e.g. Nuxt 4 uses h3@1.15.9) produces a TS2345:
Argument of type 'H3Event<EventHandlerRequest>' is not assignable to parameter of type 'H3Event<EventHandlerRequest>'.
Type is missing the following properties: fetch, $fetch, waitUntil, captureError
Two H3Event types with the same name, structurally incompatible. Worked in 3.5.6.
Root cause
The published packages/server/dist/nuxt.d.mts inlines H3Event (and its transitive graph) from whatever h3 version sits in zenstack's own node_modules at build time — currently 1.15.5. So downstream projects on newer h3 end up with a stale structural copy.
The source is fine — packages/server/src/adapter/nuxt/handler.ts does import { type H3Event } from 'h3'. The issue is the build pipeline.
What changed in 3.6.0
Build tool was swapped from tsup → tsdown. tsup emitted declarations via tsc, preserving import ... from 'h3'. tsdown (via rolldown-plugin-dts) bundles declarations by default, and with no external list / no dts.resolve: false, it inlines types from any dep that isn't marked external.
Why h3 isn't external
packages/server/package.json lists h3 only as a devDependency, and the shared packages/config/tsdown-config/src/index.ts doesn't add it to external. Same likely applies to other adapter deps (nuxt, next, express, fastify, hono, elysia, @sveltejs/kit) — worth checking.
Suggested fix
One of:
- Add
h3 (and the other adapter deps) to peerDependencies in packages/server/package.json, so tsdown treats them as external.
- Or mark them
external explicitly in the server's tsdown.config.ts.
- Or disable dts bundling (
dts: { resolve: false }) for this package.
Repro
Nuxt 4 project with @zenstackhq/server@3.6.1 + h3@1.15.9; pass the handler's event into any function typed with the real H3Event from h3. Downgrading to 3.5.6 or narrowing the consumer's param type to { headers: Headers } avoids the error.
Symptom
In 3.6.x, consuming
@zenstackhq/server/nuxtfrom a project on a newerh3(e.g. Nuxt 4 usesh3@1.15.9) produces a TS2345:Two
H3Eventtypes with the same name, structurally incompatible. Worked in 3.5.6.Root cause
The published
packages/server/dist/nuxt.d.mtsinlinesH3Event(and its transitive graph) from whateverh3version sits in zenstack's ownnode_modulesat build time — currently1.15.5. So downstream projects on newer h3 end up with a stale structural copy.The source is fine —
packages/server/src/adapter/nuxt/handler.tsdoesimport { type H3Event } from 'h3'. The issue is the build pipeline.What changed in 3.6.0
Build tool was swapped from
tsup→tsdown.tsupemitted declarations viatsc, preservingimport ... from 'h3'.tsdown(viarolldown-plugin-dts) bundles declarations by default, and with noexternallist / nodts.resolve: false, it inlines types from any dep that isn't marked external.Why h3 isn't external
packages/server/package.jsonlistsh3only as adevDependency, and the sharedpackages/config/tsdown-config/src/index.tsdoesn't add it toexternal. Same likely applies to other adapter deps (nuxt,next,express,fastify,hono,elysia,@sveltejs/kit) — worth checking.Suggested fix
One of:
h3(and the other adapter deps) topeerDependenciesinpackages/server/package.json, so tsdown treats them as external.externalexplicitly in the server'stsdown.config.ts.dts: { resolve: false }) for this package.Repro
Nuxt 4 project with
@zenstackhq/server@3.6.1+ h3@1.15.9; pass the handler's event into any function typed with the realH3Eventfromh3. Downgrading to 3.5.6 or narrowing the consumer's param type to{ headers: Headers }avoids the error.