zod-nest 3.1.0 → 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.
@@ -1,8 +1,8 @@
1
+ import { B as BaseFileOptions, a as MultipartBody, c as ZodMultipartOptions } from '../param-decorators-DbgygRVn.mjs';
2
+ export { M as MULTIPART_CONTENT_TYPE, b as MultipartShape, Z as ZodMultipartBody, d as ZodUploadedFile, e as ZodUploadedFiles } from '../param-decorators-DbgygRVn.mjs';
1
3
  import { z } from 'zod';
2
- import { B as BaseFileOptions, a as MultipartShape, b as ZodMultipartOptions } from '../zod-multipart.decorator-CxS2KuSv.mjs';
3
- export { M as MULTIPART_CONTENT_TYPE, Z as ZodMultipartBody, c as ZodUploadedFile, d as ZodUploadedFiles } from '../zod-multipart.decorator-CxS2KuSv.mjs';
4
- import '@nestjs/common';
5
4
  import '../registry-C9xStKa6.mjs';
5
+ import '@nestjs/common';
6
6
 
7
7
  /**
8
8
  * Shape multer hands you under **memory storage** (`FileInterceptor`'s
@@ -57,6 +57,6 @@ declare const MulterDiskFileSchema: z.ZodType<MulterDiskFileLike, MulterDiskFile
57
57
  * `multipart/form-data` as the consumed type, and is the schema source for
58
58
  * `@ZodUploadedFile` / `@ZodUploadedFiles` / `@ZodMultipartBody`.
59
59
  */
60
- declare const ZodMultipart: (shape: MultipartShape, options?: ZodMultipartOptions) => MethodDecorator;
60
+ declare const ZodMultipart: (body: MultipartBody, options?: ZodMultipartOptions) => MethodDecorator;
61
61
 
62
- export { type MulterDiskFileLike, MulterDiskFileSchema, type MulterFileOptions, type MulterMemoryFileLike, MulterMemoryFileSchema, MultipartShape, ZodMultipart, ZodMultipartOptions, multerDiskFile, multerMemoryFile };
62
+ export { type MulterDiskFileLike, MulterDiskFileSchema, type MulterFileOptions, type MulterMemoryFileLike, MulterMemoryFileSchema, ZodMultipart, ZodMultipartOptions, multerDiskFile, multerMemoryFile };
@@ -1,8 +1,8 @@
1
+ import { B as BaseFileOptions, a as MultipartBody, c as ZodMultipartOptions } from '../param-decorators-CX1cUqfY.js';
2
+ export { M as MULTIPART_CONTENT_TYPE, b as MultipartShape, Z as ZodMultipartBody, d as ZodUploadedFile, e as ZodUploadedFiles } from '../param-decorators-CX1cUqfY.js';
1
3
  import { z } from 'zod';
2
- import { B as BaseFileOptions, a as MultipartShape, b as ZodMultipartOptions } from '../zod-multipart.decorator-CjiQkmkR.js';
3
- export { M as MULTIPART_CONTENT_TYPE, Z as ZodMultipartBody, c as ZodUploadedFile, d as ZodUploadedFiles } from '../zod-multipart.decorator-CjiQkmkR.js';
4
- import '@nestjs/common';
5
4
  import '../registry-C9xStKa6.js';
5
+ import '@nestjs/common';
6
6
 
7
7
  /**
8
8
  * Shape multer hands you under **memory storage** (`FileInterceptor`'s
@@ -57,6 +57,6 @@ declare const MulterDiskFileSchema: z.ZodType<MulterDiskFileLike, MulterDiskFile
57
57
  * `multipart/form-data` as the consumed type, and is the schema source for
58
58
  * `@ZodUploadedFile` / `@ZodUploadedFiles` / `@ZodMultipartBody`.
59
59
  */
60
- declare const ZodMultipart: (shape: MultipartShape, options?: ZodMultipartOptions) => MethodDecorator;
60
+ declare const ZodMultipart: (body: MultipartBody, options?: ZodMultipartOptions) => MethodDecorator;
61
61
 
62
- export { type MulterDiskFileLike, MulterDiskFileSchema, type MulterFileOptions, type MulterMemoryFileLike, MulterMemoryFileSchema, MultipartShape, ZodMultipart, ZodMultipartOptions, multerDiskFile, multerMemoryFile };
62
+ export { type MulterDiskFileLike, MulterDiskFileSchema, type MulterFileOptions, type MulterMemoryFileLike, MulterMemoryFileSchema, ZodMultipart, ZodMultipartOptions, multerDiskFile, multerMemoryFile };
@@ -105,15 +105,18 @@ var sizeCheck = /* @__PURE__ */ __name((readSize, options) => {
105
105
  // src/multipart/file-marker.ts
106
106
  var fileSchemas = /* @__PURE__ */ new WeakSet();
107
107
  var isZodType = /* @__PURE__ */ __name((value) => value !== null && typeof value === "object" && "_zod" in value, "isZodType");
108
- var unwrapOnce = /* @__PURE__ */ __name((schema) => {
109
- const def = schema._zod.def;
108
+ var innerOf = /* @__PURE__ */ __name((def) => {
110
109
  if ("innerType" in def) {
111
- return isZodType(def.innerType) ? def.innerType : void 0;
110
+ return def.innerType;
112
111
  }
113
112
  if ("element" in def) {
114
- return isZodType(def.element) ? def.element : void 0;
113
+ return def.element;
115
114
  }
116
115
  return void 0;
116
+ }, "innerOf");
117
+ var unwrapOnce = /* @__PURE__ */ __name((schema) => {
118
+ const inner = innerOf(schema._zod.def);
119
+ return isZodType(inner) ? inner : void 0;
117
120
  }, "unwrapOnce");
118
121
  var markFileSchema = /* @__PURE__ */ __name((schema) => {
119
122
  fileSchemas.add(schema);
@@ -789,12 +792,172 @@ var toOpenApi = /* @__PURE__ */ __name((schema, opts) => {
789
792
  return result;
790
793
  }, "toOpenApi");
791
794
 
795
+ // src/schema/anon-id.ts
796
+ var ANON_BODY_PREFIX = "_AnonBodySchema_";
797
+ var anonIdCache = /* @__PURE__ */ new WeakMap();
798
+ var counter = 0;
799
+ var resolveAnonId = /* @__PURE__ */ __name((schema, prefix) => {
800
+ const cached = anonIdCache.get(schema);
801
+ if (cached !== void 0) {
802
+ return cached;
803
+ }
804
+ counter += 1;
805
+ const id = `${prefix}${counter}`;
806
+ anonIdCache.set(schema, id);
807
+ return id;
808
+ }, "resolveAnonId");
809
+
810
+ // src/decorators/internal/zod-schema-ref.ts
811
+ function resolveSchemaRef(schema, options) {
812
+ const registry = options?.registry ?? defaultRegistry;
813
+ const id = registerSchema(schema, registry, {
814
+ id: options?.id
815
+ });
816
+ if (id !== void 0) {
817
+ return {
818
+ kind: "ref",
819
+ ref: {
820
+ $ref: `${COMPONENTS_SCHEMAS_PREFIX}${id}`
821
+ }
822
+ };
823
+ }
824
+ if (options?.deferAnonInline === true) {
825
+ const anonId = resolveAnonId(schema, ANON_BODY_PREFIX);
826
+ registerSchema(schema, registry, {
827
+ id: anonId,
828
+ anonymous: true
829
+ });
830
+ return {
831
+ kind: "ref",
832
+ ref: {
833
+ $ref: `${COMPONENTS_SCHEMAS_PREFIX}${anonId}`
834
+ }
835
+ };
836
+ }
837
+ for (const [child, childId] of discoverDependents(schema)) {
838
+ registry.register(child, childId);
839
+ }
840
+ const { schema: body } = toOpenApi(schema, {
841
+ io: "input",
842
+ registry
843
+ });
844
+ return {
845
+ kind: "inline",
846
+ schema: body
847
+ };
848
+ }
849
+ __name(resolveSchemaRef, "resolveSchemaRef");
850
+
851
+ // src/decorators/internal/zod-param-expand.ts
852
+ var isZodObject = /* @__PURE__ */ __name((schema) => schema._zod.def.type === "object", "isZodObject");
853
+
854
+ // src/decorators/internal/flatten-intersection.ts
855
+ var intersectionArms = /* @__PURE__ */ __name((schema) => {
856
+ if (schema._zod.def.type !== "intersection") {
857
+ return null;
858
+ }
859
+ const def = schema._zod.def;
860
+ return {
861
+ left: def.left,
862
+ right: def.right
863
+ };
864
+ }, "intersectionArms");
865
+ var unionOptions = /* @__PURE__ */ __name((schema) => {
866
+ if (schema._zod.def.type !== "union") {
867
+ return null;
868
+ }
869
+ const def = schema._zod.def;
870
+ return def.options;
871
+ }, "unionOptions");
872
+ var collectObjectShapes = /* @__PURE__ */ __name((schema) => {
873
+ if (isZodObject(schema)) {
874
+ return {
875
+ shapes: [
876
+ schema.shape
877
+ ],
878
+ unionCrossed: false
879
+ };
880
+ }
881
+ const options = unionOptions(schema);
882
+ if (options !== null) {
883
+ const allShapes = [];
884
+ for (const variant of options) {
885
+ const variantResult = collectObjectShapes(variant);
886
+ if (variantResult === null) {
887
+ return null;
888
+ }
889
+ allShapes.push(...variantResult.shapes);
890
+ }
891
+ return {
892
+ shapes: allShapes,
893
+ unionCrossed: true
894
+ };
895
+ }
896
+ const arms = intersectionArms(schema);
897
+ if (arms === null) {
898
+ return null;
899
+ }
900
+ const left = collectObjectShapes(arms.left);
901
+ if (left === null) {
902
+ return null;
903
+ }
904
+ const right = collectObjectShapes(arms.right);
905
+ if (right === null) {
906
+ return null;
907
+ }
908
+ return {
909
+ shapes: [
910
+ ...left.shapes,
911
+ ...right.shapes
912
+ ],
913
+ unionCrossed: left.unionCrossed || right.unionCrossed
914
+ };
915
+ }, "collectObjectShapes");
916
+ var flattenObjectIntersection = /* @__PURE__ */ __name((schema, registry, decoratorName) => {
917
+ const collected = collectObjectShapes(schema);
918
+ if (collected === null) {
919
+ throw new ZodNestError(`${decoratorName} \`flatten: true\` requires every leaf of the schema to be a \`z.object({...})\` \u2014 intersections and unions of objects are supported, but primitives, tuples, transforms, and other non-object leaves are not. Drop \`flatten: true\` to emit the original schema with its composition intact.`);
920
+ }
921
+ const mergedShape = {};
922
+ for (const shape of collected.shapes) {
923
+ Object.assign(mergedShape, shape);
924
+ }
925
+ if (collected.unionCrossed) {
926
+ for (const key of Object.keys(mergedShape)) {
927
+ const value = mergedShape[key];
928
+ if (value !== void 0) {
929
+ mergedShape[key] = value.optional();
930
+ }
931
+ }
932
+ }
933
+ const merged = zod.z.object(mergedShape);
934
+ registerSchema(schema, registry);
935
+ for (const [child, childId] of discoverDependents(schema)) {
936
+ registry.register(child, childId);
937
+ }
938
+ const { schema: body } = toOpenApi(merged, {
939
+ io: "input",
940
+ registry
941
+ });
942
+ return body;
943
+ }, "flattenObjectIntersection");
944
+ var isZodSchema = /* @__PURE__ */ __name((value) => value instanceof zod.z.ZodType, "isZodSchema");
945
+
792
946
  // src/multipart/zod-multipart.decorator.ts
793
947
  var MULTIPART_CONTENT_TYPE = "multipart/form-data";
948
+ var toSchema = /* @__PURE__ */ __name((body) => isZodSchema(body) ? body : zod.z.object({
949
+ ...body
950
+ }), "toSchema");
951
+ var toShape = /* @__PURE__ */ __name((body) => {
952
+ if (!isZodSchema(body)) {
953
+ return body;
954
+ }
955
+ return isZodObject(body) ? body.shape : void 0;
956
+ }, "toShape");
794
957
  var partitionKeys = /* @__PURE__ */ __name((shape) => {
795
958
  const fileKeys = [];
796
959
  const textKeys = [];
797
- for (const [key, schema] of Object.entries(shape)) {
960
+ for (const [key, schema] of Object.entries(shape ?? {})) {
798
961
  if (isFileSchema(schema)) {
799
962
  fileKeys.push(key);
800
963
  continue;
@@ -806,30 +969,28 @@ var partitionKeys = /* @__PURE__ */ __name((shape) => {
806
969
  textKeys
807
970
  };
808
971
  }, "partitionKeys");
809
- var emitInlineBody = /* @__PURE__ */ __name((shape, registry) => {
810
- const object = zod.z.object({
811
- ...shape
812
- });
813
- for (const [child, childId] of discoverDependents(object)) {
814
- registry.register(child, childId);
972
+ var resolveBody = /* @__PURE__ */ __name((schema, options, registry) => {
973
+ if (options?.flatten === true) {
974
+ return flattenObjectIntersection(schema, registry, "@ZodMultipart");
815
975
  }
816
- const { schema } = toOpenApi(object, {
817
- io: "input",
976
+ const resolved = resolveSchemaRef(schema, {
977
+ ...options?.id !== void 0 ? {
978
+ id: options.id
979
+ } : {},
818
980
  registry
819
981
  });
820
- return schema;
821
- }, "emitInlineBody");
982
+ return resolved.kind === "ref" ? resolved.ref : resolved.schema;
983
+ }, "resolveBody");
822
984
  var createZodMultipart = /* @__PURE__ */ __name((defaultFilesIn) => {
823
- return (shape, options) => {
985
+ return (body, options) => {
824
986
  const registry = options?.registry ?? defaultRegistry;
825
- const { fileKeys, textKeys } = partitionKeys(shape);
987
+ const shape = toShape(body);
826
988
  const metadata = {
827
989
  shape,
828
- fileKeys,
829
- textKeys,
990
+ ...partitionKeys(shape),
830
991
  filesIn: options?.filesIn ?? defaultFilesIn
831
992
  };
832
- const body = emitInlineBody(shape, registry);
993
+ const schema = resolveBody(toSchema(body), options, registry);
833
994
  return (target, propertyKey, descriptor) => {
834
995
  const handler = descriptor.value;
835
996
  if (typeof handler !== "function") {
@@ -839,7 +1000,7 @@ var createZodMultipart = /* @__PURE__ */ __name((defaultFilesIn) => {
839
1000
  const swaggerDescriptor = descriptor;
840
1001
  swagger.ApiConsumes(MULTIPART_CONTENT_TYPE)(target, propertyKey, swaggerDescriptor);
841
1002
  swagger.ApiBody({
842
- schema: body,
1003
+ schema,
843
1004
  ...options?.description !== void 0 ? {
844
1005
  description: options.description
845
1006
  } : {},
@@ -876,10 +1037,17 @@ var readMetadata = /* @__PURE__ */ __name((ctx, decorator) => {
876
1037
  return metadata;
877
1038
  }, "readMetadata");
878
1039
  var isMultipartMetadata = /* @__PURE__ */ __name((value) => value !== null && typeof value === "object" && "shape" in value && "filesIn" in value, "isMultipartMetadata");
1040
+ var requireShape = /* @__PURE__ */ __name((metadata, decorator) => {
1041
+ if (metadata.shape !== void 0) {
1042
+ return metadata.shape;
1043
+ }
1044
+ throw new Error(`[zod-nest] ${decorator} needs a flat body shape, but @ZodMultipart was given a composite schema (an intersection or union). Validate it with @Body(new ZodValidationPipe(schema)) instead.`);
1045
+ }, "requireShape");
879
1046
  var schemaFor = /* @__PURE__ */ __name((metadata, name, decorator) => {
880
- const schema = metadata.shape[name];
1047
+ const shape = requireShape(metadata, decorator);
1048
+ const schema = shape[name];
881
1049
  if (schema === void 0) {
882
- throw new Error(`[zod-nest] ${decorator}('${name}') has no matching property in the @ZodMultipart shape. Declared: ${Object.keys(metadata.shape).join(", ")}.`);
1050
+ throw new Error(`[zod-nest] ${decorator}('${name}') has no matching property in the @ZodMultipart shape. Declared: ${Object.keys(shape).join(", ")}.`);
883
1051
  }
884
1052
  return schema;
885
1053
  }, "schemaFor");
@@ -920,14 +1088,15 @@ var resolveUploadedFiles = /* @__PURE__ */ __name(async (name, ctx) => {
920
1088
  const metadata = readMetadata(ctx, "@ZodUploadedFiles");
921
1089
  assertFilesOnRequest(metadata, "@ZodUploadedFiles");
922
1090
  const request = ctx.switchToHttp().getRequest();
923
- const schema = name === void 0 ? pick(metadata.shape, metadata.fileKeys) : schemaFor(metadata, name, "@ZodUploadedFiles");
1091
+ const schema = name === void 0 ? pick(requireShape(metadata, "@ZodUploadedFiles"), metadata.fileKeys) : schemaFor(metadata, name, "@ZodUploadedFiles");
924
1092
  return validate(schema, request.files, "custom");
925
1093
  }, "resolveUploadedFiles");
926
1094
  var resolveMultipartBody = /* @__PURE__ */ __name(async (_data, ctx) => {
927
1095
  const metadata = readMetadata(ctx, "@ZodMultipartBody");
1096
+ const shape = requireShape(metadata, "@ZodMultipartBody");
928
1097
  const request = ctx.switchToHttp().getRequest();
929
- const keys = metadata.filesIn === MultipartFilesIn.Body ? Object.keys(metadata.shape) : metadata.textKeys;
930
- return validate(pick(metadata.shape, keys), request.body, "body");
1098
+ const keys = metadata.filesIn === MultipartFilesIn.Body ? Object.keys(shape) : metadata.textKeys;
1099
+ return validate(pick(shape, keys), request.body, "body");
931
1100
  }, "resolveMultipartBody");
932
1101
  var ZodUploadedFile = common.createParamDecorator(resolveUploadedFile);
933
1102
  var ZodUploadedFiles = common.createParamDecorator(resolveUploadedFiles);