Skip to content

Import zod as a namespace everywhere and lint against the z import - #1541

Merged
thesiti92 merged 4 commits into
mainfrom
zod-namespace-imports
Nov 12, 2026
Merged

thesiti92 merged 4 commits into
mainfrom
zod-namespace-imports

Conversation

@thesiti92

@thesiti92 thesiti92 commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Problem

@dev.fast/whiteboard-document and @dev.fast/board-protocol import zod as import { z } from "zod". In zod 4 that binds the z namespace object, which includes export * as locales, so a consumer's bundler keeps all 64 zod/v4/locales/* files. cloudboard's agents Worker carries about 267 KB of locales from these two packages alone; changing cloudboard's own imports did nothing while the packages still import { z }.

Measured with esbuild 0.28.1 (--bundle --minify --format=esm) against zod 4.6.6, on a one-schema entry file:

Import Bundle Locale bytes
import { z } from "zod" 453,983 263,172 (63 files)
import z from "zod" 453,983 263,172 (63 files)
import * as z from "zod" 89,935 2,688 (en only)
import * as z from "zod/v4" 89,935 2,688
named (object, string, ...) 89,935 2,688

Change

import * as z from "zod" in every file in the repo that imported { z } (118 files), not only the two published packages and @dev.fast/json. That includes tests, the diffr TypeScript packages, scripts/review-cli-release.mjs and the header the review-protocol generator writes for the Code OSS overlay. Import lines only; the API and z.infer types are unchanged.

A new local oxlint rule, zod-imports/namespace (tools/oxlint/zod-imports), fails on the z named import and the default import of zod and zod/*. It is a custom rule because the built-in no-restricted-imports cannot do this job here: with importNames it also rejects import * as z, and the four folder overrides that already set no-restricted-imports replace a top-level entry. diffr/** is outside lint, so the rule does not cover it.

AGENTS.md notes zod as the exception to "prefer named imports over namespace imports".

Verification

Bundling each built dist/index.js the same way:

Package Before After Locale bytes after
whiteboard-document 648,473 292,500 2,688 (en)
board-protocol 502,859 146,492 2,688 (en)

pnpm lint and pnpm format:check pass, and the rule was probed in each override folder. Typecheck passes for every package except review-desktop and @diffr/claude-code, which could not be checked locally (no Code OSS node_modules, no claude-code module). All test packages pass except three tests in packages/review that fail the same way on origin/main at 4404ef7: store-upgrade.test.ts (also the failure in this PR's first CI run), cli-install.test.ts and authoring-capabilities.test.ts.

Follow-up for consumers

Publish whiteboard-document and board-protocol together with bumped versions, then bump both pins in cloudboard (apps/api, apps/web).

`import { z } from "zod"` binds zod's `z` namespace object, which carries
`locales`, so bundlers keep all 64 locale files. `import * as z` lets them
shake everything but the default English locale.
@thesiti92 thesiti92 changed the title Import zod as a namespace in the published document packages Import zod as a namespace everywhere and lint against the z import Nov 12, 2026
@thesiti92
thesiti92 enabled auto-merge (squash) November 12, 2026 21:57
@thesiti92
thesiti92 merged commit 1e79bbb into main Nov 12, 2026
13 checks passed
@thesiti92
thesiti92 deleted the zod-namespace-imports branch November 12, 2026 22:06
thesiti92 added a commit that referenced this pull request Nov 13, 2026
…are-protocol 0.6.1 (#1542)

Patch versions for the zod namespace imports in #1541, the only change
to any of the three packages since 0.3.0, 0.2.0 and 0.6.0. Published
builds stop pulling every zod locale into a consumer's bundle; the API
is unchanged.

board-protocol 0.2.1 declares whiteboard-document 0.3.1, so those two
are published together. review-share-protocol is included because
cloudboard's api Worker also bundles it, and one `{ z }` importer is
enough to keep the locales.

All three are already on npm, published from this branch.
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.

2 participants