zod-nest 1.10.0 → 1.11.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 CHANGED
@@ -23,7 +23,7 @@ For the long-form motivation, see [`docs/why-this-exists.md`](docs/why-this-exis
23
23
  - **OpenAPI 3.1 emission** — no post-processing, no spec downgrade, no leftover internal extension keys.
24
24
  - **`createZodDto`** — class wrapper around a Zod schema with introspectable `schema`, `id`, `io`, and a sibling `Output` class when input/output diverge.
25
25
  - **`ZodValidationPipe`** — auto-detects DTO from handler-arg metatype, accepts an explicit DTO or raw Zod schema, customizable exception factory.
26
- - **`@ZodResponse`** — stackable per status code, accepts a single DTO, an array (`[Dto]`), or a tuple (`[A, B, …]`). No internal `@HttpCode` — caller controls status.
26
+ - **`@ZodResponse`** — stackable per status code; each entry is a DTO **or a raw Zod schema** (single, array `[Entry]`, or tuple `[A, B, …]`, mixable). A raw schema is normalised to an output DTO internally, so a `z.discriminatedUnion` / `z.union` / `z.intersection` that can't be wrapped in `createZodDto` (TS2509) drops straight into a response. No internal `@HttpCode` — caller controls status.
27
27
  - **`@ZodBody` / `@ZodQuery` / `@ZodHeaders` / `@ZodCookies`** — method-level decorators that wire OpenAPI docs for schemas whose `z.infer<>` is a union (intersection-of-union, discriminated unions, etc.) — the ones that can't be wrapped in `createZodDto` because TS refuses unions as class bases (TS2509). Schema validation stays via `@Body(new ZodValidationPipe(schema))`; the type at the handler arg stays `z.infer<>`.
28
28
  - **`ZodSerializerInterceptor`** — response validation with a `passthroughOnError` escape hatch for untrusted upstream shapes.
29
29
  - **`applyZodNest`** — one call after `SwaggerModule.createDocument(...)` replaces the entire `cleanupOpenApiDoc` ritual.
@@ -471,7 +471,7 @@ A compact, link-out index. Type signatures and detailed semantics live in the co
471
471
 
472
472
  **DTO** — [`docs/dto.md`](docs/dto.md)
473
473
 
474
- - `createZodDto(schema, options?)`, `isZodDto(value)`, `ZodDto<TSchema>`, `Io`
474
+ - `createZodDto(schema, options?)`, `isZodDto(value)`, `isZodSchema(value)`, `ZodDto<TSchema>`, `Io`
475
475
 
476
476
  **Validation** — [`docs/validation-pipe.md`](docs/validation-pipe.md)
477
477
 
@@ -479,7 +479,7 @@ A compact, link-out index. Type signatures and detailed semantics live in the co
479
479
 
480
480
  **Response** — [`docs/responses.md`](docs/responses.md)
481
481
 
482
- - `@ZodResponse({ status?, type, description?, passthroughOnError? })`, `ZodSerializerInterceptor`, `ZodSerializationException`, `defaultStatusFor`, `resolveEffectiveStatus`, `ResponseStatusInput`, `ResponseStatusWildcard`, `ResponseVariant`, `ZOD_RESPONSES_METADATA_KEY`
482
+ - `@ZodResponse({ status?, type, description?, passthroughOnError?, contentType?, stream? })` (`type` is a DTO or raw schema, or an array/tuple of either), `ZodSerializerInterceptor`, `ZodSerializationException`, `defaultStatusFor`, `resolveEffectiveStatus`, `ResponseStatusInput`, `ResponseStatusWildcard`, `ResponseVariant`, `ZodResponseEntry`, `ZodResponseType`, `ZOD_RESPONSES_METADATA_KEY`
483
483
 
484
484
  **Parameter decorators for raw schemas** — [`docs/recipes/intersection-with-union.md`](docs/recipes/intersection-with-union.md)
485
485
 
package/dist/index.d.mts CHANGED
@@ -225,6 +225,16 @@ declare const isZodDtoMarker: (value: unknown) => value is ZodDtoMarker;
225
225
  * NestJS exposes via `ArgumentMetadata`.
226
226
  */
227
227
  declare const isZodDto: (value: unknown) => value is ZodDto;
228
+ /**
229
+ * Runtime guard: is `value` a Zod schema (any `z.*` type)?
230
+ *
231
+ * Used by `@ZodResponse` to accept a raw schema in place of a DTO — including
232
+ * `z.discriminatedUnion` / `z.union` / `z.intersection`, which can't be wrapped
233
+ * with `createZodDto` (their `z.infer` is a union, so `class … extends
234
+ * createZodDto(schema)` fails to typecheck with TS2509). `instanceof z.ZodType`
235
+ * holds for every schema built through the same `zod` module instance.
236
+ */
237
+ declare const isZodSchema: (value: unknown) => value is z.ZodType;
228
238
 
229
239
  /**
230
240
  * Default exception thrown by `ZodSerializerInterceptor` in strict mode
@@ -477,18 +487,28 @@ declare class ZodValidationPipe implements PipeTransform {
477
487
  }
478
488
 
479
489
  /**
480
- * Accepted shapes for `@ZodResponse({ type })`:
481
- * - `Dto` validates as `Dto.schema` (single-DTO response).
482
- * - `[Dto]` (length 1) validates as `z.array(Dto.schema)`; matches Nest's
490
+ * One entry in `@ZodResponse({ type })` — either a zod-nest DTO or a raw Zod
491
+ * schema. A raw schema is normalised internally to `createZodDto(schema).Output`
492
+ * (output IO, since a response body is output-only), so schemas that can't be
493
+ * wrapped with `createZodDto` — `z.discriminatedUnion` / `z.union` /
494
+ * `z.intersection`, whose `z.infer` is a union and so trip TS2509 in an
495
+ * `extends` clause — can be passed straight to a response. See `toResponseDto`.
496
+ */
497
+ type ZodResponseEntry = ZodDto | z.ZodType;
498
+ /**
499
+ * Accepted shapes for `@ZodResponse({ type })`. Each slot is a `ZodResponseEntry`
500
+ * (DTO or raw schema), and the two may be mixed within an array:
501
+ * - `Dto` / `Schema` → validates as the entry's schema (single response).
502
+ * - `[Entry]` (length 1) → validates as `z.array(entry.schema)`; matches Nest's
483
503
  * `@ApiResponse({ isArray: true })` convention without minting a separate
484
504
  * `*sDto` id.
485
505
  * - `[A, B, ...]` (length ≥ 2) → validates as `z.tuple([A.schema, B.schema, ...])`;
486
506
  * surfaces as an OpenAPI 3.1 `prefixItems` tuple via `applyZodNest`.
487
507
  *
488
- * Empty arrays and non-DTO elements throw `TypeError` at decoration time
489
- * so typos surface at module load, not the first request.
508
+ * Empty arrays and entries that are neither a DTO nor a schema throw `TypeError`
509
+ * at decoration time so typos surface at module load, not the first request.
490
510
  */
491
- type ZodResponseType = ZodDto | readonly [ZodDto, ...ZodDto[]];
511
+ type ZodResponseType = ZodResponseEntry | readonly [ZodResponseEntry, ...ZodResponseEntry[]];
492
512
  /**
493
513
  * Accepted shapes for `@ZodResponse({ status })`:
494
514
  * - `number` — exact match against `response.statusCode` (most common case).
@@ -775,4 +795,4 @@ declare class ZodNestDocumentError extends ZodNestError {
775
795
  constructor(code: ZodNestDocumentErrorCode, message: string, details?: Record<string, unknown>);
776
796
  }
777
797
 
778
- export { type ApplyZodNestOptions, COMPONENTS_SCHEMAS_PREFIX, type CreateSerializationException, type CreateValidationException, type CreateZodDtoOptions, DEFAULT_MAX_LOGGED_VALUE_BYTES, DEFAULT_REDACT_KEYS, DEFAULT_STREAM_CONTENT_TYPES, type Io, type LineageEntry, type NormalizedZodNestOptions, type Override, type OverrideContext, type OverrideJSONSchemaArg, type RegisterSchemaOptions, type ResponseStatusInput, type ResponseStatusWildcard, type ResponseVariant, type ResponseVariantKind, SchemaObject, type ToOpenApiOptions, type ToOpenApiResult, ZOD_DTO_SYMBOL, ZOD_NEST_DTO_EXTENSION, ZOD_NEST_ERROR_DUPLICATE_ID, ZOD_NEST_ERROR_EXTENSION, ZOD_NEST_OPTIONS, ZOD_RESPONSES_METADATA_KEY, ZodBody, type ZodBodyOptions, ZodCookies, type ZodCookiesOptions, type ZodDto, type ZodDtoMarker, ZodHeaders, type ZodHeadersOptions, ZodNestDocumentError, type ZodNestDocumentErrorCode, ZodNestError, ZodNestModule, type ZodNestModuleOptions, type ZodNestRegistry, ZodNestUnrepresentableError, ZodQuery, type ZodQueryOptions, ZodResponse, type ZodResponseDescription, type ZodResponseOptions, type ZodResponseType, ZodSerializationException, ZodSerializerInterceptor, ZodValidationException, ZodValidationPipe, type ZodValidationPipeArg, type ZodValidationPipeOptions, applyZodNest, createRegistry, createZodDto, defaultRegistry, defaultStatusFor, extend, getLineage, isZodDto, isZodDtoMarker, makeZodDtoMarker, overrideJSONSchema, registerSchema, resolveEffectiveStatus, toOpenApi };
798
+ export { type ApplyZodNestOptions, COMPONENTS_SCHEMAS_PREFIX, type CreateSerializationException, type CreateValidationException, type CreateZodDtoOptions, DEFAULT_MAX_LOGGED_VALUE_BYTES, DEFAULT_REDACT_KEYS, DEFAULT_STREAM_CONTENT_TYPES, type Io, type LineageEntry, type NormalizedZodNestOptions, type Override, type OverrideContext, type OverrideJSONSchemaArg, type RegisterSchemaOptions, type ResponseStatusInput, type ResponseStatusWildcard, type ResponseVariant, type ResponseVariantKind, SchemaObject, type ToOpenApiOptions, type ToOpenApiResult, ZOD_DTO_SYMBOL, ZOD_NEST_DTO_EXTENSION, ZOD_NEST_ERROR_DUPLICATE_ID, ZOD_NEST_ERROR_EXTENSION, ZOD_NEST_OPTIONS, ZOD_RESPONSES_METADATA_KEY, ZodBody, type ZodBodyOptions, ZodCookies, type ZodCookiesOptions, type ZodDto, type ZodDtoMarker, ZodHeaders, type ZodHeadersOptions, ZodNestDocumentError, type ZodNestDocumentErrorCode, ZodNestError, ZodNestModule, type ZodNestModuleOptions, type ZodNestRegistry, ZodNestUnrepresentableError, ZodQuery, type ZodQueryOptions, ZodResponse, type ZodResponseDescription, type ZodResponseEntry, type ZodResponseOptions, type ZodResponseType, ZodSerializationException, ZodSerializerInterceptor, ZodValidationException, ZodValidationPipe, type ZodValidationPipeArg, type ZodValidationPipeOptions, applyZodNest, createRegistry, createZodDto, defaultRegistry, defaultStatusFor, extend, getLineage, isZodDto, isZodDtoMarker, isZodSchema, makeZodDtoMarker, overrideJSONSchema, registerSchema, resolveEffectiveStatus, toOpenApi };
package/dist/index.d.ts CHANGED
@@ -225,6 +225,16 @@ declare const isZodDtoMarker: (value: unknown) => value is ZodDtoMarker;
225
225
  * NestJS exposes via `ArgumentMetadata`.
226
226
  */
227
227
  declare const isZodDto: (value: unknown) => value is ZodDto;
228
+ /**
229
+ * Runtime guard: is `value` a Zod schema (any `z.*` type)?
230
+ *
231
+ * Used by `@ZodResponse` to accept a raw schema in place of a DTO — including
232
+ * `z.discriminatedUnion` / `z.union` / `z.intersection`, which can't be wrapped
233
+ * with `createZodDto` (their `z.infer` is a union, so `class … extends
234
+ * createZodDto(schema)` fails to typecheck with TS2509). `instanceof z.ZodType`
235
+ * holds for every schema built through the same `zod` module instance.
236
+ */
237
+ declare const isZodSchema: (value: unknown) => value is z.ZodType;
228
238
 
229
239
  /**
230
240
  * Default exception thrown by `ZodSerializerInterceptor` in strict mode
@@ -477,18 +487,28 @@ declare class ZodValidationPipe implements PipeTransform {
477
487
  }
478
488
 
479
489
  /**
480
- * Accepted shapes for `@ZodResponse({ type })`:
481
- * - `Dto` validates as `Dto.schema` (single-DTO response).
482
- * - `[Dto]` (length 1) validates as `z.array(Dto.schema)`; matches Nest's
490
+ * One entry in `@ZodResponse({ type })` — either a zod-nest DTO or a raw Zod
491
+ * schema. A raw schema is normalised internally to `createZodDto(schema).Output`
492
+ * (output IO, since a response body is output-only), so schemas that can't be
493
+ * wrapped with `createZodDto` — `z.discriminatedUnion` / `z.union` /
494
+ * `z.intersection`, whose `z.infer` is a union and so trip TS2509 in an
495
+ * `extends` clause — can be passed straight to a response. See `toResponseDto`.
496
+ */
497
+ type ZodResponseEntry = ZodDto | z.ZodType;
498
+ /**
499
+ * Accepted shapes for `@ZodResponse({ type })`. Each slot is a `ZodResponseEntry`
500
+ * (DTO or raw schema), and the two may be mixed within an array:
501
+ * - `Dto` / `Schema` → validates as the entry's schema (single response).
502
+ * - `[Entry]` (length 1) → validates as `z.array(entry.schema)`; matches Nest's
483
503
  * `@ApiResponse({ isArray: true })` convention without minting a separate
484
504
  * `*sDto` id.
485
505
  * - `[A, B, ...]` (length ≥ 2) → validates as `z.tuple([A.schema, B.schema, ...])`;
486
506
  * surfaces as an OpenAPI 3.1 `prefixItems` tuple via `applyZodNest`.
487
507
  *
488
- * Empty arrays and non-DTO elements throw `TypeError` at decoration time
489
- * so typos surface at module load, not the first request.
508
+ * Empty arrays and entries that are neither a DTO nor a schema throw `TypeError`
509
+ * at decoration time so typos surface at module load, not the first request.
490
510
  */
491
- type ZodResponseType = ZodDto | readonly [ZodDto, ...ZodDto[]];
511
+ type ZodResponseType = ZodResponseEntry | readonly [ZodResponseEntry, ...ZodResponseEntry[]];
492
512
  /**
493
513
  * Accepted shapes for `@ZodResponse({ status })`:
494
514
  * - `number` — exact match against `response.statusCode` (most common case).
@@ -775,4 +795,4 @@ declare class ZodNestDocumentError extends ZodNestError {
775
795
  constructor(code: ZodNestDocumentErrorCode, message: string, details?: Record<string, unknown>);
776
796
  }
777
797
 
778
- export { type ApplyZodNestOptions, COMPONENTS_SCHEMAS_PREFIX, type CreateSerializationException, type CreateValidationException, type CreateZodDtoOptions, DEFAULT_MAX_LOGGED_VALUE_BYTES, DEFAULT_REDACT_KEYS, DEFAULT_STREAM_CONTENT_TYPES, type Io, type LineageEntry, type NormalizedZodNestOptions, type Override, type OverrideContext, type OverrideJSONSchemaArg, type RegisterSchemaOptions, type ResponseStatusInput, type ResponseStatusWildcard, type ResponseVariant, type ResponseVariantKind, SchemaObject, type ToOpenApiOptions, type ToOpenApiResult, ZOD_DTO_SYMBOL, ZOD_NEST_DTO_EXTENSION, ZOD_NEST_ERROR_DUPLICATE_ID, ZOD_NEST_ERROR_EXTENSION, ZOD_NEST_OPTIONS, ZOD_RESPONSES_METADATA_KEY, ZodBody, type ZodBodyOptions, ZodCookies, type ZodCookiesOptions, type ZodDto, type ZodDtoMarker, ZodHeaders, type ZodHeadersOptions, ZodNestDocumentError, type ZodNestDocumentErrorCode, ZodNestError, ZodNestModule, type ZodNestModuleOptions, type ZodNestRegistry, ZodNestUnrepresentableError, ZodQuery, type ZodQueryOptions, ZodResponse, type ZodResponseDescription, type ZodResponseOptions, type ZodResponseType, ZodSerializationException, ZodSerializerInterceptor, ZodValidationException, ZodValidationPipe, type ZodValidationPipeArg, type ZodValidationPipeOptions, applyZodNest, createRegistry, createZodDto, defaultRegistry, defaultStatusFor, extend, getLineage, isZodDto, isZodDtoMarker, makeZodDtoMarker, overrideJSONSchema, registerSchema, resolveEffectiveStatus, toOpenApi };
798
+ export { type ApplyZodNestOptions, COMPONENTS_SCHEMAS_PREFIX, type CreateSerializationException, type CreateValidationException, type CreateZodDtoOptions, DEFAULT_MAX_LOGGED_VALUE_BYTES, DEFAULT_REDACT_KEYS, DEFAULT_STREAM_CONTENT_TYPES, type Io, type LineageEntry, type NormalizedZodNestOptions, type Override, type OverrideContext, type OverrideJSONSchemaArg, type RegisterSchemaOptions, type ResponseStatusInput, type ResponseStatusWildcard, type ResponseVariant, type ResponseVariantKind, SchemaObject, type ToOpenApiOptions, type ToOpenApiResult, ZOD_DTO_SYMBOL, ZOD_NEST_DTO_EXTENSION, ZOD_NEST_ERROR_DUPLICATE_ID, ZOD_NEST_ERROR_EXTENSION, ZOD_NEST_OPTIONS, ZOD_RESPONSES_METADATA_KEY, ZodBody, type ZodBodyOptions, ZodCookies, type ZodCookiesOptions, type ZodDto, type ZodDtoMarker, ZodHeaders, type ZodHeadersOptions, ZodNestDocumentError, type ZodNestDocumentErrorCode, ZodNestError, ZodNestModule, type ZodNestModuleOptions, type ZodNestRegistry, ZodNestUnrepresentableError, ZodQuery, type ZodQueryOptions, ZodResponse, type ZodResponseDescription, type ZodResponseEntry, type ZodResponseOptions, type ZodResponseType, ZodSerializationException, ZodSerializerInterceptor, ZodValidationException, ZodValidationPipe, type ZodValidationPipeArg, type ZodValidationPipeOptions, applyZodNest, createRegistry, createZodDto, defaultRegistry, defaultStatusFor, extend, getLineage, isZodDto, isZodDtoMarker, isZodSchema, makeZodDtoMarker, overrideJSONSchema, registerSchema, resolveEffectiveStatus, toOpenApi };
package/dist/index.js CHANGED
@@ -585,6 +585,10 @@ var buildSiblingClass = /* @__PURE__ */ __name((parent, schema) => {
585
585
  };
586
586
  }
587
587
  };
588
+ Object.defineProperty(SiblingClass, "name", {
589
+ get: /* @__PURE__ */ __name(() => parent.id, "get"),
590
+ configurable: true
591
+ });
588
592
  return SiblingClass;
589
593
  }, "buildSiblingClass");
590
594
  var resolveOutput = /* @__PURE__ */ __name((parent, schema) => {
@@ -658,9 +662,8 @@ var createZodDto = /* @__PURE__ */ __name((schema, options) => {
658
662
  };
659
663
  return ZodDtoBase;
660
664
  }, "createZodDto");
661
-
662
- // src/dto/predicates.ts
663
665
  var isZodDto = /* @__PURE__ */ __name((value) => typeof value === "function" && value[ZOD_DTO_SYMBOL] === true, "isZodDto");
666
+ var isZodSchema = /* @__PURE__ */ __name((value) => value instanceof zod.z.ZodType, "isZodSchema");
664
667
  var ZodSerializationException = class extends common.InternalServerErrorException {
665
668
  static {
666
669
  __name(this, "ZodSerializationException");
@@ -948,8 +951,8 @@ function _ts_param(paramIndex, decorator) {
948
951
  };
949
952
  }
950
953
  __name(_ts_param, "_ts_param");
951
- var isZodSchema = /* @__PURE__ */ __name((value) => value !== null && typeof value === "object" && "_zod" in value, "isZodSchema");
952
- var isOptionsObject = /* @__PURE__ */ __name((value) => value !== null && typeof value === "object" && !isZodSchema(value), "isOptionsObject");
954
+ var isZodSchema2 = /* @__PURE__ */ __name((value) => value !== null && typeof value === "object" && "_zod" in value, "isZodSchema");
955
+ var isOptionsObject = /* @__PURE__ */ __name((value) => value !== null && typeof value === "object" && !isZodSchema2(value), "isOptionsObject");
953
956
  var defaultExceptionFactory = /* @__PURE__ */ __name((zodError, argMetadata) => new ZodValidationException(zodError, argMetadata), "defaultExceptionFactory");
954
957
  exports.ZodValidationPipe = class _ZodValidationPipe {
955
958
  static {
@@ -1018,7 +1021,7 @@ exports.ZodValidationPipe = class _ZodValidationPipe {
1018
1021
  dtoName: arg.name
1019
1022
  };
1020
1023
  }
1021
- if (isZodSchema(arg)) {
1024
+ if (isZodSchema2(arg)) {
1022
1025
  return {
1023
1026
  schema: arg,
1024
1027
  factory: void 0,
@@ -1086,6 +1089,48 @@ var appendResponseVariant = /* @__PURE__ */ __name((handler, variant) => {
1086
1089
  ...existing
1087
1090
  ], handler);
1088
1091
  }, "appendResponseVariant");
1092
+
1093
+ // src/response/normalize-type.ts
1094
+ var responseDtoCache = /* @__PURE__ */ new WeakMap();
1095
+ var anonResponseSchemaCounter = 0;
1096
+ var warnedOnAnonymousResponseSchema = false;
1097
+ var warnAnonymousOnce = /* @__PURE__ */ __name((fallbackId) => {
1098
+ if (warnedOnAnonymousResponseSchema) {
1099
+ return;
1100
+ }
1101
+ warnedOnAnonymousResponseSchema = true;
1102
+ console.warn(`[zod-nest] @ZodResponse received a raw Zod schema with no \`.meta({ id })\`. It will appear in components.schemas as "${fallbackId}". Add \`schema.meta({ id: 'Foo' })\` to control the OpenAPI component name.`);
1103
+ }, "warnAnonymousOnce");
1104
+ var schemaToOutputDto = /* @__PURE__ */ __name((schema) => {
1105
+ const cached = responseDtoCache.get(schema);
1106
+ if (cached !== void 0) {
1107
+ return cached;
1108
+ }
1109
+ const namedId = registerSchema(schema);
1110
+ if (namedId !== void 0) {
1111
+ const dto2 = createZodDto(schema).Output;
1112
+ responseDtoCache.set(schema, dto2);
1113
+ return dto2;
1114
+ }
1115
+ anonResponseSchemaCounter += 1;
1116
+ const fallbackId = `_AnonZodResponseSchema_${anonResponseSchemaCounter}`;
1117
+ warnAnonymousOnce(fallbackId);
1118
+ const dto = createZodDto(schema, {
1119
+ id: fallbackId
1120
+ }).Output;
1121
+ responseDtoCache.set(schema, dto);
1122
+ return dto;
1123
+ }, "schemaToOutputDto");
1124
+ var toResponseDto = /* @__PURE__ */ __name((entry, index) => {
1125
+ if (isZodDto(entry)) {
1126
+ return entry;
1127
+ }
1128
+ if (isZodSchema(entry)) {
1129
+ return schemaToOutputDto(entry);
1130
+ }
1131
+ const where = index === void 0 ? "@ZodResponse({ type })" : `@ZodResponse({ type }) element [${index}]`;
1132
+ throw new TypeError(`[zod-nest] ${where} must be a zod-nest DTO class (from createZodDto), a Zod schema, or a non-empty array of those.`);
1133
+ }, "toResponseDto");
1089
1134
  var extractDescriptionFields = /* @__PURE__ */ __name((desc) => {
1090
1135
  if (desc === void 0) {
1091
1136
  return {};
@@ -1188,13 +1233,10 @@ var applySwaggerResponseDecorator = /* @__PURE__ */ __name((variant, effectiveSt
1188
1233
  }, "applySwaggerResponseDecorator");
1189
1234
 
1190
1235
  // src/decorators/zod-response.decorator.ts
1191
- var buildArrayKind = /* @__PURE__ */ __name((dtos) => {
1192
- for (const [index, element] of dtos.entries()) {
1193
- if (!isZodDto(element)) {
1194
- throw new TypeError(`[zod-nest] @ZodResponse({ type }) element [${index}] is not a zod-nest DTO (class returned by createZodDto). Wrap raw schemas with createZodDto first.`);
1195
- }
1196
- }
1197
- const [head, ...rest] = dtos;
1236
+ var buildArrayKind = /* @__PURE__ */ __name((entries) => {
1237
+ const [headEntry, ...restEntries] = entries;
1238
+ const head = toResponseDto(headEntry, 0);
1239
+ const rest = restEntries.map((entry, index) => toResponseDto(entry, index + 1));
1198
1240
  if (rest.length === 0) {
1199
1241
  return {
1200
1242
  kind: "array",
@@ -1210,24 +1252,25 @@ var buildArrayKind = /* @__PURE__ */ __name((dtos) => {
1210
1252
  ];
1211
1253
  return {
1212
1254
  kind: "tuple",
1213
- dto: dtos,
1255
+ dto: [
1256
+ head,
1257
+ ...rest
1258
+ ],
1214
1259
  validationSchema: zod.z.tuple(tupleSchemas)
1215
1260
  };
1216
1261
  }, "buildArrayKind");
1217
1262
  var buildKind = /* @__PURE__ */ __name((type) => {
1218
1263
  if (Array.isArray(type)) {
1219
1264
  if (type.length === 0) {
1220
- throw new TypeError("[zod-nest] @ZodResponse({ type: [] }) is invalid \u2014 provide at least one DTO.");
1265
+ throw new TypeError("[zod-nest] @ZodResponse({ type: [] }) is invalid \u2014 provide at least one DTO or schema.");
1221
1266
  }
1222
1267
  return buildArrayKind(type);
1223
1268
  }
1224
- if (!isZodDto(type)) {
1225
- throw new TypeError("[zod-nest] @ZodResponse({ type }) must be a zod-nest DTO class (from createZodDto) or an array of such classes.");
1226
- }
1269
+ const dto = toResponseDto(type);
1227
1270
  return {
1228
1271
  kind: "single",
1229
- dto: type,
1230
- validationSchema: type.schema
1272
+ dto,
1273
+ validationSchema: dto.schema
1231
1274
  };
1232
1275
  }, "buildKind");
1233
1276
  var normaliseStatus = /* @__PURE__ */ __name((status) => {
@@ -1516,10 +1559,10 @@ __name(_ts_param2, "_ts_param");
1516
1559
  var defaultSerializationFactory = /* @__PURE__ */ __name((err, ctx) => new ZodSerializationException(err, ctx), "defaultSerializationFactory");
1517
1560
  var formatDtoLabel = /* @__PURE__ */ __name((variant) => {
1518
1561
  if (variant.kind === "single") {
1519
- return variant.dto.name;
1562
+ return variant.dto.id;
1520
1563
  }
1521
1564
  const dtos = variant.dto;
1522
- return `[${dtos.map((d) => d.name).join(", ")}]`;
1565
+ return `[${dtos.map((d) => d.id).join(", ")}]`;
1523
1566
  }, "formatDtoLabel");
1524
1567
  var formatHandlerLabel = /* @__PURE__ */ __name((context) => `${context.getClass().name}.${context.getHandler().name}`, "formatHandlerLabel");
1525
1568
  var matchesWildcard = /* @__PURE__ */ __name((wildcard, status) => wildcard.charCodeAt(0) - 48 === Math.floor(status / 100), "matchesWildcard");
@@ -2372,6 +2415,7 @@ exports.extend = extend;
2372
2415
  exports.getLineage = getLineage;
2373
2416
  exports.isZodDto = isZodDto;
2374
2417
  exports.isZodDtoMarker = isZodDtoMarker;
2418
+ exports.isZodSchema = isZodSchema;
2375
2419
  exports.makeZodDtoMarker = makeZodDtoMarker;
2376
2420
  exports.overrideJSONSchema = overrideJSONSchema;
2377
2421
  exports.registerSchema = registerSchema;