zod-nest 3.2.5 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +30 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +30 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
# zod-nest
|
|
2
2
|
|
|
3
|
-
> Modern **Zod v4** ↔ **NestJS** ↔ **OpenAPI 3.1** integration.
|
|
3
|
+
> Modern **Zod v4** ↔ **NestJS** ↔ **OpenAPI 3.1 / 3.2** integration.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/zod-nest)
|
|
6
6
|
[](https://github.com/rodrigowbazevedo/zod-nest/actions/workflows/ci.yml)
|
|
7
7
|
[](https://codecov.io/gh/rodrigowbazevedo/zod-nest)
|
|
8
8
|
[](https://opensource.org/licenses/MIT)
|
|
9
9
|
|
|
10
|
-
Define your DTOs once with Zod, get validated request bodies, validated response bodies, and a correct OpenAPI 3.1 document — without the dual-codepath, post-process, or `@ts-ignore` baggage that comes with bolting Zod onto class-validator-shaped tooling.
|
|
10
|
+
Define your DTOs once with Zod, get validated request bodies, validated response bodies, and a correct OpenAPI 3.1 or 3.2 document — without the dual-codepath, post-process, or `@ts-ignore` baggage that comes with bolting Zod onto class-validator-shaped tooling.
|
|
11
11
|
|
|
12
12
|
## Why this exists
|
|
13
13
|
|
|
14
14
|
`zod-nest` is a fresh take on the idea pioneered by [`nestjs-zod`](https://github.com/BenLorantfy/nestjs-zod) — many thanks to that project and its maintainers; this library would not exist without it.
|
|
15
15
|
|
|
16
|
-
The difference is that `zod-nest` is Zod v4 only and OpenAPI 3.1 only. It drops `class-validator` / `class-transformer` coexistence, drops Zod v3 codepaths, drops `cleanupOpenApiDoc` as a separate post-process, and drops the 20-odd `@ts-ignore`s that the dual-version approach required. The result is a smaller surface, fully type-safe end to end, with extension points where you actually need them — exception factories, response status resolution, custom emission overrides.
|
|
16
|
+
The difference is that `zod-nest` is Zod v4 only and OpenAPI 3.1+ only (3.1 or 3.2; no 3.0). It drops `class-validator` / `class-transformer` coexistence, drops Zod v3 codepaths, drops `cleanupOpenApiDoc` as a separate post-process, and drops the 20-odd `@ts-ignore`s that the dual-version approach required. The result is a smaller surface, fully type-safe end to end, with extension points where you actually need them — exception factories, response status resolution, custom emission overrides.
|
|
17
17
|
|
|
18
18
|
For the long-form motivation, see [`docs/why-this-exists.md`](docs/why-this-exists.md).
|
|
19
19
|
|
|
@@ -42,7 +42,7 @@ A short list of behavioural differences you'll hit on day one. Full migration ta
|
|
|
42
42
|
- **Multi-status `@ZodResponse`** — stack the decorator per status code. In `nestjs-zod`, multi-status required mixing `@ZodSerializerDto` with hand-rolled `@ApiResponse({ status: ... })` calls.
|
|
43
43
|
- **No internal `@HttpCode`** — `@ZodResponse` does **not** call `@HttpCode` under the hood. Status resolution precedence: `@ZodResponse({ status })` → `@HttpCode(...)` on the handler → method default (`POST → 201`, others → `200`). The caller controls `201` vs `200` vs `204` via standard NestJS decorators. `status` accepts numeric codes plus the OpenAPI 3.1 range keys (`'1XX'`…`'5XX'`) and `'default'` (sugar for the resolved method default).
|
|
44
44
|
- **I/O suffix only when needed** — `<Id>Output` is only emitted when the input and output JSON Schemas actually differ. `nestjs-zod` always emitted `_Output`.
|
|
45
|
-
- **OpenAPI 3.1
|
|
45
|
+
- **OpenAPI 3.1 and 3.2** — no `3.0` fallback. Pick with `DocumentBuilder.setOpenAPIVersion('3.2.0')`; 3.2 is what makes `QUERY` routes conformant. `$ref`s emit to the final location; `cleanupOpenApiDoc` is unnecessary.
|
|
46
46
|
- **Validation-failure logging out of the box** — `nestjs-zod` has none.
|
|
47
47
|
- **Customizable serialization exception** — both `ZodValidationPipe` and `ZodSerializerInterceptor` accept a factory. `nestjs-zod` only customized the input side.
|
|
48
48
|
- **DTO discriminator** — `Symbol.for('zod-nest.dto')` (cross-realm safe), not `MyDto.isZodDto`.
|
package/dist/index.d.mts
CHANGED
|
@@ -807,9 +807,9 @@ interface ApplyZodNestOptions {
|
|
|
807
807
|
* as a `{ $ref, title }` sibling (`applyRefTitles`, unless `refTitles: false`)
|
|
808
808
|
* so Swagger UI's 3.1 renderer surfaces the component name. Inert annotation.
|
|
809
809
|
* - Every `$ref` whose target is missing throws `ZodNestDocumentError(DANGLING_REF)`.
|
|
810
|
-
* - `doc.openapi` is
|
|
811
|
-
*
|
|
812
|
-
*
|
|
810
|
+
* - `doc.openapi` is normalised to a version zod-nest emits — the one set via
|
|
811
|
+
* `DocumentBuilder.setOpenAPIVersion()` when supported, else `'3.1.0'` with a
|
|
812
|
+
* warning, so the version string always matches the emitted body.
|
|
813
813
|
*
|
|
814
814
|
* Composable with other doc-transform passes — apply other mutations before
|
|
815
815
|
* or after this function.
|
package/dist/index.d.ts
CHANGED
|
@@ -807,9 +807,9 @@ interface ApplyZodNestOptions {
|
|
|
807
807
|
* as a `{ $ref, title }` sibling (`applyRefTitles`, unless `refTitles: false`)
|
|
808
808
|
* so Swagger UI's 3.1 renderer surfaces the component name. Inert annotation.
|
|
809
809
|
* - Every `$ref` whose target is missing throws `ZodNestDocumentError(DANGLING_REF)`.
|
|
810
|
-
* - `doc.openapi` is
|
|
811
|
-
*
|
|
812
|
-
*
|
|
810
|
+
* - `doc.openapi` is normalised to a version zod-nest emits — the one set via
|
|
811
|
+
* `DocumentBuilder.setOpenAPIVersion()` when supported, else `'3.1.0'` with a
|
|
812
|
+
* warning, so the version string always matches the emitted body.
|
|
813
813
|
*
|
|
814
814
|
* Composable with other doc-transform passes — apply other mutations before
|
|
815
815
|
* or after this function.
|
package/dist/index.js
CHANGED
|
@@ -1089,7 +1089,16 @@ var HTTP_METHODS = [
|
|
|
1089
1089
|
"options",
|
|
1090
1090
|
"head",
|
|
1091
1091
|
"patch",
|
|
1092
|
-
"trace"
|
|
1092
|
+
"trace",
|
|
1093
|
+
"query",
|
|
1094
|
+
"search",
|
|
1095
|
+
"propfind",
|
|
1096
|
+
"proppatch",
|
|
1097
|
+
"mkcol",
|
|
1098
|
+
"copy",
|
|
1099
|
+
"move",
|
|
1100
|
+
"lock",
|
|
1101
|
+
"unlock"
|
|
1093
1102
|
];
|
|
1094
1103
|
var forEachOperation = /* @__PURE__ */ chunkEV5I5HGT_js.__name((doc, fn) => {
|
|
1095
1104
|
const paths = doc.paths;
|
|
@@ -1719,6 +1728,25 @@ var decorateIfPresent = /* @__PURE__ */ chunkEV5I5HGT_js.__name((schemas, key) =
|
|
|
1719
1728
|
};
|
|
1720
1729
|
}, "decorateIfPresent");
|
|
1721
1730
|
|
|
1731
|
+
// src/document/openapi-version.ts
|
|
1732
|
+
var SUPPORTED_OPENAPI_SERIES = [
|
|
1733
|
+
"3.1",
|
|
1734
|
+
"3.2"
|
|
1735
|
+
];
|
|
1736
|
+
var DEFAULT_OPENAPI_VERSION = "3.1.0";
|
|
1737
|
+
var SUPPORTED_VERSION_PATTERN = /^3\.[12]\.\d+(?:-.+)?$/;
|
|
1738
|
+
var resolveOpenApiVersion = /* @__PURE__ */ chunkEV5I5HGT_js.__name((doc) => {
|
|
1739
|
+
const declared = doc.openapi;
|
|
1740
|
+
if (typeof declared !== "string" || declared === "") {
|
|
1741
|
+
return DEFAULT_OPENAPI_VERSION;
|
|
1742
|
+
}
|
|
1743
|
+
if (SUPPORTED_VERSION_PATTERN.test(declared)) {
|
|
1744
|
+
return declared;
|
|
1745
|
+
}
|
|
1746
|
+
console.warn(`[zod-nest] Document declares OpenAPI \`${declared}\`, which zod-nest does not emit; emitting \`${DEFAULT_OPENAPI_VERSION}\` instead. Supported: ${SUPPORTED_OPENAPI_SERIES.map((series) => `${series}.x`).join(", ")}. Set one via \`DocumentBuilder.setOpenAPIVersion()\` to silence this.`);
|
|
1747
|
+
return DEFAULT_OPENAPI_VERSION;
|
|
1748
|
+
}, "resolveOpenApiVersion");
|
|
1749
|
+
|
|
1722
1750
|
// src/document/ref-titles.ts
|
|
1723
1751
|
var applyRefTitles = /* @__PURE__ */ chunkEV5I5HGT_js.__name((doc) => {
|
|
1724
1752
|
const schemas = doc.components?.schemas;
|
|
@@ -1871,7 +1899,6 @@ var withForcedExposure = /* @__PURE__ */ chunkEV5I5HGT_js.__name((collected, reg
|
|
|
1871
1899
|
classToDtoId: collected.classToDtoId
|
|
1872
1900
|
};
|
|
1873
1901
|
}, "withForcedExposure");
|
|
1874
|
-
var OPENAPI_VERSION = "3.1.0";
|
|
1875
1902
|
var applyZodNest = /* @__PURE__ */ chunkEV5I5HGT_js.__name((doc, opts = {}) => {
|
|
1876
1903
|
const registry = opts.registry ?? chunkQ3SWJZBB_js.defaultRegistry;
|
|
1877
1904
|
const collected = collectUsage(doc, registry);
|
|
@@ -1912,7 +1939,7 @@ var applyZodNest = /* @__PURE__ */ chunkEV5I5HGT_js.__name((doc, opts = {}) => {
|
|
|
1912
1939
|
doc,
|
|
1913
1940
|
collected: extended
|
|
1914
1941
|
});
|
|
1915
|
-
doc.openapi =
|
|
1942
|
+
doc.openapi = resolveOpenApiVersion(doc);
|
|
1916
1943
|
return doc;
|
|
1917
1944
|
}, "applyZodNest");
|
|
1918
1945
|
|