From c278fe494d868da9adb10204959235dc7be51f6f Mon Sep 17 00:00:00 2001 From: SerhiyGreench Date: Thu, 10 Sep 2026 20:25:37 +0200 Subject: [PATCH 1/3] fix(deps): take zod from the consumer, as an unversioned peer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `zod` was a regular dependency pinned to `^4.4.3`, so npm was free to install a second copy of Zod underneath this package whenever the consumer's own range did not overlap. That is the one arrangement this package cannot work in: every validator it is handed — `z.string()`, a `z.object()`, anything — is built by the consumer's Zod, and `schemaOf` assembles those into a `z.object()` built by whichever copy resolved here. Two copies means two sets of schema classes, and the failure is a parse that behaves oddly rather than an import that fails. It is now a peer dependency at `*`, and a devDependency for the build and the suite. `*` rather than a range because the version is genuinely the consumer's to choose: the whole runtime surface used here is `z.object()` and `schema.parse()`, which every Zod major has carried. The suite and the build pass unchanged against both 3.25.76 and 4.6.1. --- AGENTS.md | 10 ++++++++-- README.md | 6 ++++-- package-lock.json | 22 ++++++++++++---------- package.json | 7 ++++--- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ffaeef5..00e44d8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,8 +29,14 @@ validate RPC inputs. **not** `experimentalDecorators` and **not** `reflect-metadata`. Do not enable `experimentalDecorators`; it changes decorator semantics and would break the buffer/seal mechanism. -- **Single runtime dependency: `zod`.** Do not add heavyweight deps; this - package is meant to stay small. +- **No runtime dependencies. `zod` is an unversioned peer** (`"zod": "*"`), + installed here as a devDependency so the build and the suite have one. The + consumer's copy is the one that must be used: a validator handed to + `@validate` is built from *their* Zod, and a second copy nested under this + package would make `z.object()` assemble schemas from a different class + identity than the ones it was given. Keep the runtime surface to what every + Zod major has had — `z.object()` and `schema.parse()` — and do not add + heavyweight deps; this package is meant to stay small. - **Lint/format:** `oxlint` + `oxfmt`. Run `npm run format` before committing; CI checks `npm run format:check`. - Build **emits `.js`/`.d.ts`/`.js.map` next to sources**; these are diff --git a/README.md b/README.md index 80d0a9c..835f224 100644 --- a/README.md +++ b/README.md @@ -41,12 +41,14 @@ version, licence and Node floor for every package: # Requirements -Node.js ≥ 22.12. `zod` v4 is a runtime dependency. +Node.js ≥ 22.12. `zod` is a peer dependency with no version constraint: the +schemas you write and the ones this package builds from them have to come from +one copy of Zod, so the version is yours to choose and yours to install. # Install ```bash -npm i --save @imqueue/validation +npm i --save @imqueue/validation zod ``` # Usage diff --git a/package-lock.json b/package-lock.json index eb0c475..21dd3ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,20 +8,21 @@ "name": "@imqueue/validation", "version": "1.1.2", "license": "GPL-3.0-only", - "dependencies": { - "zod": "^4.4.3" - }, "devDependencies": { "@types/node": "^24.9.1", "oxfmt": "0.57.0", "oxlint": "1.72.0", - "typescript": "^7.0.2" + "typescript": "^7.0.2", + "zod": "^4.4.3" }, "engines": { "node": ">=22.12.0" }, "funding": { "url": "https://imqueue.com/" + }, + "peerDependencies": { + "zod": "*" } }, "node_modules/@oxfmt/binding-android-arm-eabi": { @@ -719,9 +720,9 @@ } }, "node_modules/@types/node": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", - "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", + "version": "24.13.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.4.tgz", + "integrity": "sha512-YJ7EqCstVTzIr0fMr7qul/977en+pQHrfmuKIo6Zr9i75Be21dr3MovcfvGtyvi2HAUrRerWps5sMO9I7WaxDw==", "dev": true, "license": "MIT", "dependencies": { @@ -1222,9 +1223,10 @@ "license": "MIT" }, "node_modules/zod": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", - "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.1.tgz", + "integrity": "sha512-341aRWQsve0rvronKNTqZpjmzdbUDlFuzHaI/XLg/Ej82qffDJRRfBTCuv7+9q/rMjB6LSLyEBnW4InJeMtt/Q==", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index a61ce39..3e83fc4 100644 --- a/package.json +++ b/package.json @@ -45,14 +45,15 @@ "funding": "https://imqueue.com/", "author": "imqueue.com (https://imqueue.com)", "license": "GPL-3.0-only", - "dependencies": { - "zod": "^4.4.3" + "peerDependencies": { + "zod": "*" }, "devDependencies": { "@types/node": "^24.9.1", "oxfmt": "0.57.0", "oxlint": "1.72.0", - "typescript": "^7.0.2" + "typescript": "^7.0.2", + "zod": "^4.4.3" }, "main": "index.js", "types": "index.d.ts", From 45bdfc7d2dc3aae465ae070a24c8e523566a8f88 Mon Sep 17 00:00:00 2001 From: SerhiyGreench Date: Thu, 10 Sep 2026 20:30:26 +0200 Subject: [PATCH 2/3] chore(deps): leave the dev copy of zod unversioned too `devDependencies` named `^4.4.3`, which is a version this package has no reason to have an opinion about: nothing downstream installs it, and its only job is to give `tsc` and the suite a Zod to run against. `*` runs them against whatever is newest, which is the version a consumer is most likely to bring. `npm ci` still takes the exact copy from the lockfile, so CI stays reproducible. --- AGENTS.md | 5 +++-- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 00e44d8..e1f5490 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,8 +29,9 @@ validate RPC inputs. **not** `experimentalDecorators` and **not** `reflect-metadata`. Do not enable `experimentalDecorators`; it changes decorator semantics and would break the buffer/seal mechanism. -- **No runtime dependencies. `zod` is an unversioned peer** (`"zod": "*"`), - installed here as a devDependency so the build and the suite have one. The +- **No runtime dependencies. `zod` is an unversioned peer** (`"zod": "*"`), and + unversioned again in `devDependencies` so the build and the suite run against + whatever Zod is newest rather than against a range this package chose. The consumer's copy is the one that must be used: a validator handed to `@validate` is built from *their* Zod, and a second copy nested under this package would make `z.object()` assemble schemas from a different class diff --git a/package-lock.json b/package-lock.json index 21dd3ff..1b6c12e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "oxfmt": "0.57.0", "oxlint": "1.72.0", "typescript": "^7.0.2", - "zod": "^4.4.3" + "zod": "*" }, "engines": { "node": ">=22.12.0" diff --git a/package.json b/package.json index 3e83fc4..23f407d 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "oxfmt": "0.57.0", "oxlint": "1.72.0", "typescript": "^7.0.2", - "zod": "^4.4.3" + "zod": "*" }, "main": "index.js", "types": "index.d.ts", From 10cd5f8b90a1b060ab366352eb48a45f013f69c2 Mon Sep 17 00:00:00 2001 From: SerhiyGreench Date: Thu, 10 Sep 2026 20:38:03 +0200 Subject: [PATCH 3/3] 1.2.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1b6c12e..e189470 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@imqueue/validation", - "version": "1.1.2", + "version": "1.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@imqueue/validation", - "version": "1.1.2", + "version": "1.2.0", "license": "GPL-3.0-only", "devDependencies": { "@types/node": "^24.9.1", diff --git a/package.json b/package.json index 23f407d..23d4b52 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@imqueue/validation", - "version": "1.1.2", + "version": "1.2.0", "description": "Zod-backed field- and method-level validation via native (TC39) decorators for Node.js & TypeScript microservices — the input-validation layer of the @imqueue framework", "keywords": [ "validation",