zod-nest 3.0.2 → 3.2.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.
@@ -0,0 +1,92 @@
1
+ import { z } from 'zod';
2
+ import { Z as ZodNestRegistry } from './registry-C9xStKa6.js';
3
+ import * as _nestjs_common from '@nestjs/common';
4
+
5
+ /**
6
+ * Where the multipart parser puts uploaded files. Multer leaves them on the
7
+ * request (`req.file` / `req.files`) with only text fields in `req.body`;
8
+ * `@fastify/multipart` with `attachFieldsToBody: true` puts everything in
9
+ * `req.body`.
10
+ */
11
+ declare const MultipartFilesIn: {
12
+ readonly Request: "request";
13
+ readonly Body: "body";
14
+ };
15
+ type MultipartFilesIn = (typeof MultipartFilesIn)[keyof typeof MultipartFilesIn];
16
+ /** Shape accepted by `@ZodMultipart` — one Zod schema per form field. */
17
+ type MultipartShape = Readonly<Record<string, z.ZodType>>;
18
+
19
+ declare const MULTIPART_CONTENT_TYPE = "multipart/form-data";
20
+ /**
21
+ * Body declaration accepted by `@ZodMultipart`: a flat shape record, or any
22
+ * Zod schema. A record is the common case; a schema covers named bodies
23
+ * (`.meta({ id })` → `$ref`) and composites an object literal can't express.
24
+ */
25
+ type MultipartBody = MultipartShape | z.ZodType;
26
+ interface ZodMultipartOptions {
27
+ /**
28
+ * Where the parser puts uploaded files. Defaults to the platform entry
29
+ * point's convention — `'request'` from `zod-nest/express`, `'body'` from
30
+ * `zod-nest/fastify`.
31
+ */
32
+ readonly filesIn?: MultipartFilesIn;
33
+ /**
34
+ * Forces this id, overriding any `.meta({ id })` on the schema. A named body
35
+ * is emitted as a `$ref` to `components.schemas`, which keeps a stable name
36
+ * for client generators — at the cost of Swagger UI's `try-it-out` form,
37
+ * which doesn't follow `$ref` for `multipart/form-data`.
38
+ */
39
+ readonly id?: string;
40
+ /**
41
+ * Merge an intersection / union of `z.object` arms into one flat inline
42
+ * object. Needed for composite bodies whose `try-it-out` form must render.
43
+ * All merged properties become optional. See `@ZodBody`'s `flatten`.
44
+ */
45
+ readonly flatten?: boolean;
46
+ /** Registry to register named descendants into. Defaults to `defaultRegistry`. */
47
+ readonly registry?: ZodNestRegistry;
48
+ /** OpenAPI `description` for the request body. */
49
+ readonly description?: string;
50
+ /** Whether the body is required. Defaults to `true`. */
51
+ readonly required?: boolean;
52
+ }
53
+
54
+ interface BaseFileOptions {
55
+ /**
56
+ * Registry id for the schema. Set it to get a reusable
57
+ * `components.schemas` entry that every field `$ref`s, instead of the
58
+ * fragment being inlined at each use site. There is no `title` counterpart
59
+ * — `overrideJSONSchema` replaces the emitted body and does not carry
60
+ * `title` into it, so one would have no effect.
61
+ */
62
+ readonly id?: string;
63
+ /** Allowed MIME types, matched case-insensitively against the client-supplied value. */
64
+ readonly mimeTypes?: readonly string[];
65
+ /** Allowed filename extensions, with or without a leading dot. */
66
+ readonly extensions?: readonly string[];
67
+ /** OpenAPI `description` for the emitted binary property. */
68
+ readonly description?: string;
69
+ /** Overrides the `contentMediaType` derived from a single-entry `mimeTypes`. */
70
+ readonly contentMediaType?: string;
71
+ }
72
+
73
+ /**
74
+ * Validates `req.file` against the named property of the `@ZodMultipart`
75
+ * shape. The name selects a schema; it never searches the request. Match it
76
+ * to your `FileInterceptor('<name>')` field name, as with plain Nest.
77
+ */
78
+ declare const ZodUploadedFile: (...dataOrPipes: (string | _nestjs_common.PipeTransform<any, any> | _nestjs_common.Type<_nestjs_common.PipeTransform<any, any>>)[]) => ParameterDecorator;
79
+ /**
80
+ * Validates `req.files` against the named property of the `@ZodMultipart`
81
+ * shape, or against an object of every declared file property when called
82
+ * with no name — the record shape `FileFieldsInterceptor` produces.
83
+ */
84
+ declare const ZodUploadedFiles: (...dataOrPipes: (string | _nestjs_common.PipeTransform<any, any> | _nestjs_common.Type<_nestjs_common.PipeTransform<any, any>> | undefined)[]) => ParameterDecorator;
85
+ /**
86
+ * Validates `req.body` against the `@ZodMultipart` shape — the text fields
87
+ * only under `filesIn: 'request'` (multer keeps files off the body), the
88
+ * whole shape under `filesIn: 'body'`.
89
+ */
90
+ declare const ZodMultipartBody: (...dataOrPipes: unknown[]) => ParameterDecorator;
91
+
92
+ export { type BaseFileOptions as B, MULTIPART_CONTENT_TYPE as M, ZodMultipartBody as Z, type MultipartBody as a, type MultipartShape as b, type ZodMultipartOptions as c, ZodUploadedFile as d, ZodUploadedFiles as e };
@@ -0,0 +1,92 @@
1
+ import { z } from 'zod';
2
+ import { Z as ZodNestRegistry } from './registry-C9xStKa6.mjs';
3
+ import * as _nestjs_common from '@nestjs/common';
4
+
5
+ /**
6
+ * Where the multipart parser puts uploaded files. Multer leaves them on the
7
+ * request (`req.file` / `req.files`) with only text fields in `req.body`;
8
+ * `@fastify/multipart` with `attachFieldsToBody: true` puts everything in
9
+ * `req.body`.
10
+ */
11
+ declare const MultipartFilesIn: {
12
+ readonly Request: "request";
13
+ readonly Body: "body";
14
+ };
15
+ type MultipartFilesIn = (typeof MultipartFilesIn)[keyof typeof MultipartFilesIn];
16
+ /** Shape accepted by `@ZodMultipart` — one Zod schema per form field. */
17
+ type MultipartShape = Readonly<Record<string, z.ZodType>>;
18
+
19
+ declare const MULTIPART_CONTENT_TYPE = "multipart/form-data";
20
+ /**
21
+ * Body declaration accepted by `@ZodMultipart`: a flat shape record, or any
22
+ * Zod schema. A record is the common case; a schema covers named bodies
23
+ * (`.meta({ id })` → `$ref`) and composites an object literal can't express.
24
+ */
25
+ type MultipartBody = MultipartShape | z.ZodType;
26
+ interface ZodMultipartOptions {
27
+ /**
28
+ * Where the parser puts uploaded files. Defaults to the platform entry
29
+ * point's convention — `'request'` from `zod-nest/express`, `'body'` from
30
+ * `zod-nest/fastify`.
31
+ */
32
+ readonly filesIn?: MultipartFilesIn;
33
+ /**
34
+ * Forces this id, overriding any `.meta({ id })` on the schema. A named body
35
+ * is emitted as a `$ref` to `components.schemas`, which keeps a stable name
36
+ * for client generators — at the cost of Swagger UI's `try-it-out` form,
37
+ * which doesn't follow `$ref` for `multipart/form-data`.
38
+ */
39
+ readonly id?: string;
40
+ /**
41
+ * Merge an intersection / union of `z.object` arms into one flat inline
42
+ * object. Needed for composite bodies whose `try-it-out` form must render.
43
+ * All merged properties become optional. See `@ZodBody`'s `flatten`.
44
+ */
45
+ readonly flatten?: boolean;
46
+ /** Registry to register named descendants into. Defaults to `defaultRegistry`. */
47
+ readonly registry?: ZodNestRegistry;
48
+ /** OpenAPI `description` for the request body. */
49
+ readonly description?: string;
50
+ /** Whether the body is required. Defaults to `true`. */
51
+ readonly required?: boolean;
52
+ }
53
+
54
+ interface BaseFileOptions {
55
+ /**
56
+ * Registry id for the schema. Set it to get a reusable
57
+ * `components.schemas` entry that every field `$ref`s, instead of the
58
+ * fragment being inlined at each use site. There is no `title` counterpart
59
+ * — `overrideJSONSchema` replaces the emitted body and does not carry
60
+ * `title` into it, so one would have no effect.
61
+ */
62
+ readonly id?: string;
63
+ /** Allowed MIME types, matched case-insensitively against the client-supplied value. */
64
+ readonly mimeTypes?: readonly string[];
65
+ /** Allowed filename extensions, with or without a leading dot. */
66
+ readonly extensions?: readonly string[];
67
+ /** OpenAPI `description` for the emitted binary property. */
68
+ readonly description?: string;
69
+ /** Overrides the `contentMediaType` derived from a single-entry `mimeTypes`. */
70
+ readonly contentMediaType?: string;
71
+ }
72
+
73
+ /**
74
+ * Validates `req.file` against the named property of the `@ZodMultipart`
75
+ * shape. The name selects a schema; it never searches the request. Match it
76
+ * to your `FileInterceptor('<name>')` field name, as with plain Nest.
77
+ */
78
+ declare const ZodUploadedFile: (...dataOrPipes: (string | _nestjs_common.PipeTransform<any, any> | _nestjs_common.Type<_nestjs_common.PipeTransform<any, any>>)[]) => ParameterDecorator;
79
+ /**
80
+ * Validates `req.files` against the named property of the `@ZodMultipart`
81
+ * shape, or against an object of every declared file property when called
82
+ * with no name — the record shape `FileFieldsInterceptor` produces.
83
+ */
84
+ declare const ZodUploadedFiles: (...dataOrPipes: (string | _nestjs_common.PipeTransform<any, any> | _nestjs_common.Type<_nestjs_common.PipeTransform<any, any>> | undefined)[]) => ParameterDecorator;
85
+ /**
86
+ * Validates `req.body` against the `@ZodMultipart` shape — the text fields
87
+ * only under `filesIn: 'request'` (multer keeps files off the body), the
88
+ * whole shape under `filesIn: 'body'`.
89
+ */
90
+ declare const ZodMultipartBody: (...dataOrPipes: unknown[]) => ParameterDecorator;
91
+
92
+ export { type BaseFileOptions as B, MULTIPART_CONTENT_TYPE as M, ZodMultipartBody as Z, type MultipartBody as a, type MultipartShape as b, type ZodMultipartOptions as c, ZodUploadedFile as d, ZodUploadedFiles as e };
@@ -0,0 +1,79 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * Per-registration flags carried alongside the id.
5
+ *
6
+ * - `expose` — force the id into the emitted document even when no endpoint
7
+ * references it. The author deliberately wants it in `components.schemas`
8
+ * (e.g. for out-of-band client codegen). Default exposure is otherwise
9
+ * reachability-scoped, so an unreferenced schema is pruned unless flagged.
10
+ * - `anonymous` — the id is a synthetic placeholder for a schema with no
11
+ * resolvable id (passed inline to `@ZodResponse` / `@ZodBody`). It exists
12
+ * only to carry the body through bulk emission under the document's
13
+ * `strict` / `override` options; `inlineAnonymousBodies` later inlines the
14
+ * body at each `$ref` site and prunes the component, so the synthetic id
15
+ * never reaches the final document.
16
+ *
17
+ * Both flags are sticky — once set for an id they stay set, so a later plain
18
+ * `register` of the same id (e.g. the idempotent re-register inside
19
+ * `createZodDto`) doesn't clear them.
20
+ */
21
+ interface RegisterFlags {
22
+ readonly expose?: boolean;
23
+ readonly anonymous?: boolean;
24
+ }
25
+ interface ZodNestRegistry {
26
+ readonly zodRegistry: typeof z.globalRegistry;
27
+ register(schema: z.ZodType, id: string, flags?: RegisterFlags): void;
28
+ hasCollision(id: string): boolean;
29
+ getCollisions(): ReadonlyMap<string, ReadonlySet<z.ZodType>>;
30
+ /**
31
+ * Snapshot of every id registered through this `ZodNestRegistry`. The
32
+ * underlying Zod registry is `z.globalRegistry`, which may hold third-party
33
+ * entries — bulk emission filters its output against this snapshot to keep
34
+ * only zod-nest-known ids.
35
+ *
36
+ * Includes ids discovered transitively via `.meta({ id })` on descendants
37
+ * of explicitly-registered schemas.
38
+ */
39
+ ids(): readonly string[];
40
+ /** Ids registered with `{ expose: true }` — exposed regardless of usage. */
41
+ forceExposedIds(): readonly string[];
42
+ /** Ids registered with `{ anonymous: true }` — inlined + pruned by `applyZodNest`. */
43
+ anonymousIds(): readonly string[];
44
+ }
45
+ declare const createRegistry: () => ZodNestRegistry;
46
+ /** Process-wide default registry, used when no explicit `options.registry` is passed. */
47
+ declare const defaultRegistry: ZodNestRegistry;
48
+ interface RegisterSchemaOptions {
49
+ /** Forces this id, overriding any `.meta({ id })` already on the schema. */
50
+ readonly id?: string;
51
+ /**
52
+ * Force the schema into the emitted document even when no endpoint
53
+ * references it. Default exposure is reachability-scoped — see
54
+ * {@link RegisterFlags.expose}.
55
+ */
56
+ readonly expose?: boolean;
57
+ /**
58
+ * Mark the resolved id as a synthetic anonymous placeholder — inlined and
59
+ * pruned by `applyZodNest`. See {@link RegisterFlags.anonymous}.
60
+ */
61
+ readonly anonymous?: boolean;
62
+ }
63
+ /**
64
+ * Register a schema with the given registry, resolving its id from (in order):
65
+ * an explicit `options.id`, then `.meta({ id })` on the schema. Returns the
66
+ * resolved id, or `undefined` when neither source yields one (the call is then
67
+ * a no-op — callers with their own fallback path handle that case).
68
+ *
69
+ * Shared by `createZodDto` and `extend` so a schema named via `.meta({ id })`
70
+ * gets its body emitted into `components.schemas` even when it never flows
71
+ * through `createZodDto` (e.g. used only as an `extend()` parent — Zod's
72
+ * `.extend()` produces a flat object, so the parent isn't a transitive
73
+ * descendant of the child and would otherwise be missed by `discoverDependents`).
74
+ *
75
+ * Idempotent — `registry.register` already deduplicates repeat calls.
76
+ */
77
+ declare const registerSchema: (schema: z.ZodType, registry?: ZodNestRegistry, options?: RegisterSchemaOptions) => string | undefined;
78
+
79
+ export { type RegisterFlags as R, type ZodNestRegistry as Z, type RegisterSchemaOptions as a, createRegistry as c, defaultRegistry as d, registerSchema as r };
@@ -0,0 +1,79 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * Per-registration flags carried alongside the id.
5
+ *
6
+ * - `expose` — force the id into the emitted document even when no endpoint
7
+ * references it. The author deliberately wants it in `components.schemas`
8
+ * (e.g. for out-of-band client codegen). Default exposure is otherwise
9
+ * reachability-scoped, so an unreferenced schema is pruned unless flagged.
10
+ * - `anonymous` — the id is a synthetic placeholder for a schema with no
11
+ * resolvable id (passed inline to `@ZodResponse` / `@ZodBody`). It exists
12
+ * only to carry the body through bulk emission under the document's
13
+ * `strict` / `override` options; `inlineAnonymousBodies` later inlines the
14
+ * body at each `$ref` site and prunes the component, so the synthetic id
15
+ * never reaches the final document.
16
+ *
17
+ * Both flags are sticky — once set for an id they stay set, so a later plain
18
+ * `register` of the same id (e.g. the idempotent re-register inside
19
+ * `createZodDto`) doesn't clear them.
20
+ */
21
+ interface RegisterFlags {
22
+ readonly expose?: boolean;
23
+ readonly anonymous?: boolean;
24
+ }
25
+ interface ZodNestRegistry {
26
+ readonly zodRegistry: typeof z.globalRegistry;
27
+ register(schema: z.ZodType, id: string, flags?: RegisterFlags): void;
28
+ hasCollision(id: string): boolean;
29
+ getCollisions(): ReadonlyMap<string, ReadonlySet<z.ZodType>>;
30
+ /**
31
+ * Snapshot of every id registered through this `ZodNestRegistry`. The
32
+ * underlying Zod registry is `z.globalRegistry`, which may hold third-party
33
+ * entries — bulk emission filters its output against this snapshot to keep
34
+ * only zod-nest-known ids.
35
+ *
36
+ * Includes ids discovered transitively via `.meta({ id })` on descendants
37
+ * of explicitly-registered schemas.
38
+ */
39
+ ids(): readonly string[];
40
+ /** Ids registered with `{ expose: true }` — exposed regardless of usage. */
41
+ forceExposedIds(): readonly string[];
42
+ /** Ids registered with `{ anonymous: true }` — inlined + pruned by `applyZodNest`. */
43
+ anonymousIds(): readonly string[];
44
+ }
45
+ declare const createRegistry: () => ZodNestRegistry;
46
+ /** Process-wide default registry, used when no explicit `options.registry` is passed. */
47
+ declare const defaultRegistry: ZodNestRegistry;
48
+ interface RegisterSchemaOptions {
49
+ /** Forces this id, overriding any `.meta({ id })` already on the schema. */
50
+ readonly id?: string;
51
+ /**
52
+ * Force the schema into the emitted document even when no endpoint
53
+ * references it. Default exposure is reachability-scoped — see
54
+ * {@link RegisterFlags.expose}.
55
+ */
56
+ readonly expose?: boolean;
57
+ /**
58
+ * Mark the resolved id as a synthetic anonymous placeholder — inlined and
59
+ * pruned by `applyZodNest`. See {@link RegisterFlags.anonymous}.
60
+ */
61
+ readonly anonymous?: boolean;
62
+ }
63
+ /**
64
+ * Register a schema with the given registry, resolving its id from (in order):
65
+ * an explicit `options.id`, then `.meta({ id })` on the schema. Returns the
66
+ * resolved id, or `undefined` when neither source yields one (the call is then
67
+ * a no-op — callers with their own fallback path handle that case).
68
+ *
69
+ * Shared by `createZodDto` and `extend` so a schema named via `.meta({ id })`
70
+ * gets its body emitted into `components.schemas` even when it never flows
71
+ * through `createZodDto` (e.g. used only as an `extend()` parent — Zod's
72
+ * `.extend()` produces a flat object, so the parent isn't a transitive
73
+ * descendant of the child and would otherwise be missed by `discoverDependents`).
74
+ *
75
+ * Idempotent — `registry.register` already deduplicates repeat calls.
76
+ */
77
+ declare const registerSchema: (schema: z.ZodType, registry?: ZodNestRegistry, options?: RegisterSchemaOptions) => string | undefined;
78
+
79
+ export { type RegisterFlags as R, type ZodNestRegistry as Z, type RegisterSchemaOptions as a, createRegistry as c, defaultRegistry as d, registerSchema as r };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zod-nest",
3
- "version": "3.0.2",
3
+ "version": "3.2.0",
4
4
  "description": "Modern Zod v4-only NestJS + OpenAPI 3.1 integration. Successor to nestjs-zod.",
5
5
  "license": "MIT",
6
6
  "author": "Rodrigo Azevedo",
@@ -49,6 +49,26 @@
49
49
  "default": "./dist/helpers/index.js"
50
50
  }
51
51
  },
52
+ "./express": {
53
+ "import": {
54
+ "types": "./dist/express/index.d.mts",
55
+ "default": "./dist/express/index.mjs"
56
+ },
57
+ "require": {
58
+ "types": "./dist/express/index.d.ts",
59
+ "default": "./dist/express/index.js"
60
+ }
61
+ },
62
+ "./fastify": {
63
+ "import": {
64
+ "types": "./dist/fastify/index.d.mts",
65
+ "default": "./dist/fastify/index.mjs"
66
+ },
67
+ "require": {
68
+ "types": "./dist/fastify/index.d.ts",
69
+ "default": "./dist/fastify/index.js"
70
+ }
71
+ },
52
72
  "./package.json": "./package.json"
53
73
  },
54
74
  "files": [
@@ -95,6 +115,7 @@
95
115
  "@semantic-release/github": "^12.0.9",
96
116
  "@semantic-release/npm": "^13.1.5",
97
117
  "@swc/core": "^1.16.1",
118
+ "@types/multer": "2.2.0",
98
119
  "@types/node": "^24.13.3",
99
120
  "@types/supertest": "^7.2.1",
100
121
  "@types/swagger2openapi": "^7.0.4",