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.
- package/README.md +22 -0
- package/dist/express/index.d.mts +62 -0
- package/dist/express/index.d.ts +62 -0
- package/dist/express/index.js +1149 -0
- package/dist/express/index.js.map +1 -0
- package/dist/express/index.mjs +1139 -0
- package/dist/express/index.mjs.map +1 -0
- package/dist/fastify/index.d.mts +46 -0
- package/dist/fastify/index.d.ts +46 -0
- package/dist/fastify/index.js +1125 -0
- package/dist/fastify/index.js.map +1 -0
- package/dist/fastify/index.mjs +1119 -0
- package/dist/fastify/index.mjs.map +1 -0
- package/dist/index.d.mts +3 -77
- package/dist/index.d.ts +3 -77
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14 -1
- package/dist/index.mjs.map +1 -1
- package/dist/param-decorators-CX1cUqfY.d.ts +92 -0
- package/dist/param-decorators-DbgygRVn.d.mts +92 -0
- package/dist/registry-C9xStKa6.d.mts +79 -0
- package/dist/registry-C9xStKa6.d.ts +79 -0
- package/package.json +22 -1
|
@@ -0,0 +1,1139 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ApiConsumes, ApiBody } from '@nestjs/swagger';
|
|
3
|
+
import { BadRequestException, HttpStatus, createParamDecorator } from '@nestjs/common';
|
|
4
|
+
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
|
+
|
|
8
|
+
// src/helpers/fragments.ts
|
|
9
|
+
var binaryFragment = {
|
|
10
|
+
type: "string",
|
|
11
|
+
format: "binary"
|
|
12
|
+
};
|
|
13
|
+
var binary = /* @__PURE__ */ __name((opts) => ({
|
|
14
|
+
...binaryFragment,
|
|
15
|
+
...opts
|
|
16
|
+
}), "binary");
|
|
17
|
+
|
|
18
|
+
// src/schema/custom-override.ts
|
|
19
|
+
var customOverrideMap = /* @__PURE__ */ new WeakMap();
|
|
20
|
+
var isWrapper = /* @__PURE__ */ __name((arg) => "input" in arg || "output" in arg, "isWrapper");
|
|
21
|
+
var overrideJSONSchema = /* @__PURE__ */ __name((schema, arg) => {
|
|
22
|
+
const overrideSchema = isWrapper(arg) ? {
|
|
23
|
+
...arg
|
|
24
|
+
} : {
|
|
25
|
+
input: arg,
|
|
26
|
+
output: arg
|
|
27
|
+
};
|
|
28
|
+
const schemaDescription = schema.description;
|
|
29
|
+
if (typeof schemaDescription === "string") {
|
|
30
|
+
overrideSchema.description = schemaDescription;
|
|
31
|
+
}
|
|
32
|
+
customOverrideMap.set(schema, overrideSchema);
|
|
33
|
+
return schema;
|
|
34
|
+
}, "overrideJSONSchema");
|
|
35
|
+
var peekRegistration = /* @__PURE__ */ __name((schema) => customOverrideMap.get(schema), "peekRegistration");
|
|
36
|
+
var createCustomOverride = /* @__PURE__ */ __name((io) => {
|
|
37
|
+
return ({ zodSchema, jsonSchema }) => {
|
|
38
|
+
const record = customOverrideMap.get(zodSchema);
|
|
39
|
+
if (record === void 0) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const fragment = record[io];
|
|
43
|
+
if (fragment === void 0) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
for (const key of Object.keys(jsonSchema)) {
|
|
47
|
+
Reflect.deleteProperty(jsonSchema, key);
|
|
48
|
+
}
|
|
49
|
+
Object.assign(jsonSchema, fragment);
|
|
50
|
+
if (fragment.description === void 0 && record.description !== void 0) {
|
|
51
|
+
jsonSchema.description = record.description;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}, "createCustomOverride");
|
|
55
|
+
|
|
56
|
+
// src/multipart/file-checks.ts
|
|
57
|
+
var normalizeExtension = /* @__PURE__ */ __name((extension) => extension.startsWith(".") ? extension.toLowerCase() : `.${extension.toLowerCase()}`, "normalizeExtension");
|
|
58
|
+
var mimeTypeCheck = /* @__PURE__ */ __name((accessors, options) => {
|
|
59
|
+
const allowed = new Set(options.mimeTypes.map((mimeType) => mimeType.toLowerCase()));
|
|
60
|
+
return (payload) => {
|
|
61
|
+
const mimeType = accessors.mimeType(payload.value).toLowerCase();
|
|
62
|
+
if (allowed.has(mimeType)) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
payload.issues.push({
|
|
66
|
+
code: "custom",
|
|
67
|
+
input: payload.value,
|
|
68
|
+
message: `Expected one of ${options.mimeTypes.join(", ")}, received ${mimeType}`
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
}, "mimeTypeCheck");
|
|
72
|
+
var extensionCheck = /* @__PURE__ */ __name((accessors, options) => {
|
|
73
|
+
const allowed = new Set(options.extensions.map(normalizeExtension));
|
|
74
|
+
return (payload) => {
|
|
75
|
+
const fileName = accessors.fileName(payload.value).toLowerCase();
|
|
76
|
+
const matched = [
|
|
77
|
+
...allowed
|
|
78
|
+
].some((extension) => fileName.endsWith(extension));
|
|
79
|
+
if (matched) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
payload.issues.push({
|
|
83
|
+
code: "custom",
|
|
84
|
+
input: payload.value,
|
|
85
|
+
message: `Expected a file ending in ${options.extensions.map(normalizeExtension).join(", ")}, received ${fileName}`
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
}, "extensionCheck");
|
|
89
|
+
var sizeCheck = /* @__PURE__ */ __name((readSize, options) => {
|
|
90
|
+
return (payload) => {
|
|
91
|
+
const size = readSize(payload.value);
|
|
92
|
+
if (size <= options.maxSize) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
payload.issues.push({
|
|
96
|
+
code: "custom",
|
|
97
|
+
input: payload.value,
|
|
98
|
+
message: `Expected at most ${options.maxSize} bytes, received ${size}`
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
}, "sizeCheck");
|
|
102
|
+
|
|
103
|
+
// src/multipart/file-marker.ts
|
|
104
|
+
var fileSchemas = /* @__PURE__ */ new WeakSet();
|
|
105
|
+
var isZodType = /* @__PURE__ */ __name((value) => value !== null && typeof value === "object" && "_zod" in value, "isZodType");
|
|
106
|
+
var innerOf = /* @__PURE__ */ __name((def) => {
|
|
107
|
+
if ("innerType" in def) {
|
|
108
|
+
return def.innerType;
|
|
109
|
+
}
|
|
110
|
+
if ("element" in def) {
|
|
111
|
+
return def.element;
|
|
112
|
+
}
|
|
113
|
+
return void 0;
|
|
114
|
+
}, "innerOf");
|
|
115
|
+
var unwrapOnce = /* @__PURE__ */ __name((schema) => {
|
|
116
|
+
const inner = innerOf(schema._zod.def);
|
|
117
|
+
return isZodType(inner) ? inner : void 0;
|
|
118
|
+
}, "unwrapOnce");
|
|
119
|
+
var markFileSchema = /* @__PURE__ */ __name((schema) => {
|
|
120
|
+
fileSchemas.add(schema);
|
|
121
|
+
return schema;
|
|
122
|
+
}, "markFileSchema");
|
|
123
|
+
var isFileSchema = /* @__PURE__ */ __name((schema) => {
|
|
124
|
+
if (fileSchemas.has(schema)) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
const inner = unwrapOnce(schema);
|
|
128
|
+
if (inner === void 0) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
return isFileSchema(inner);
|
|
132
|
+
}, "isFileSchema");
|
|
133
|
+
|
|
134
|
+
// src/multipart/build-file-schema.ts
|
|
135
|
+
var resolveFragment = /* @__PURE__ */ __name((options) => {
|
|
136
|
+
const contentMediaType = options?.contentMediaType ?? singleMimeType(options?.mimeTypes);
|
|
137
|
+
return binary({
|
|
138
|
+
...options?.description !== void 0 ? {
|
|
139
|
+
description: options.description
|
|
140
|
+
} : {},
|
|
141
|
+
...contentMediaType !== void 0 ? {
|
|
142
|
+
contentMediaType
|
|
143
|
+
} : {}
|
|
144
|
+
});
|
|
145
|
+
}, "resolveFragment");
|
|
146
|
+
var singleMimeType = /* @__PURE__ */ __name((mimeTypes) => {
|
|
147
|
+
if (mimeTypes === void 0 || mimeTypes.length !== 1) {
|
|
148
|
+
return void 0;
|
|
149
|
+
}
|
|
150
|
+
return mimeTypes[0];
|
|
151
|
+
}, "singleMimeType");
|
|
152
|
+
var collectChecks = /* @__PURE__ */ __name((params) => {
|
|
153
|
+
const { accessors, options, maxSize } = params;
|
|
154
|
+
const checks = [];
|
|
155
|
+
if (options?.mimeTypes !== void 0) {
|
|
156
|
+
checks.push(mimeTypeCheck(accessors, {
|
|
157
|
+
mimeTypes: options.mimeTypes
|
|
158
|
+
}));
|
|
159
|
+
}
|
|
160
|
+
if (options?.extensions !== void 0) {
|
|
161
|
+
checks.push(extensionCheck(accessors, {
|
|
162
|
+
extensions: options.extensions
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
if (maxSize !== void 0 && accessors.size !== void 0) {
|
|
166
|
+
checks.push(sizeCheck(accessors.size, {
|
|
167
|
+
maxSize
|
|
168
|
+
}));
|
|
169
|
+
}
|
|
170
|
+
return checks;
|
|
171
|
+
}, "collectChecks");
|
|
172
|
+
var withId = /* @__PURE__ */ __name((schema, options, fragment) => {
|
|
173
|
+
if (options?.id === void 0) {
|
|
174
|
+
return schema;
|
|
175
|
+
}
|
|
176
|
+
return overrideJSONSchema(schema.meta({
|
|
177
|
+
id: options.id
|
|
178
|
+
}), fragment);
|
|
179
|
+
}, "withId");
|
|
180
|
+
var buildFileSchema = /* @__PURE__ */ __name((params) => {
|
|
181
|
+
const fragment = resolveFragment(params.options);
|
|
182
|
+
const base = overrideJSONSchema(z.custom(params.predicate), fragment);
|
|
183
|
+
const checks = collectChecks(params);
|
|
184
|
+
const checked = checks.length === 0 ? base : overrideJSONSchema(base.check(...checks), fragment);
|
|
185
|
+
return markFileSchema(withId(checked, params.options, fragment));
|
|
186
|
+
}, "buildFileSchema");
|
|
187
|
+
|
|
188
|
+
// src/multipart/metadata.ts
|
|
189
|
+
var MultipartFilesIn = {
|
|
190
|
+
Request: "request",
|
|
191
|
+
Body: "body"
|
|
192
|
+
};
|
|
193
|
+
var ZOD_MULTIPART_METADATA_KEY = /* @__PURE__ */ Symbol.for("zod-nest.multipart");
|
|
194
|
+
var INNER_TYPE_WRAPPERS = /* @__PURE__ */ new Set([
|
|
195
|
+
"optional",
|
|
196
|
+
"nullable",
|
|
197
|
+
"default",
|
|
198
|
+
"prefault",
|
|
199
|
+
"catch",
|
|
200
|
+
"nonoptional",
|
|
201
|
+
"success",
|
|
202
|
+
"readonly",
|
|
203
|
+
"promise"
|
|
204
|
+
]);
|
|
205
|
+
var readId = /* @__PURE__ */ __name((schema) => {
|
|
206
|
+
const meta = z.globalRegistry.get(schema);
|
|
207
|
+
if (meta === void 0) {
|
|
208
|
+
return void 0;
|
|
209
|
+
}
|
|
210
|
+
const id = meta.id;
|
|
211
|
+
return typeof id === "string" ? id : void 0;
|
|
212
|
+
}, "readId");
|
|
213
|
+
var resolveLazyTarget = /* @__PURE__ */ __name((getter) => {
|
|
214
|
+
try {
|
|
215
|
+
return [
|
|
216
|
+
getter()
|
|
217
|
+
];
|
|
218
|
+
} catch (error) {
|
|
219
|
+
if (error instanceof ReferenceError) {
|
|
220
|
+
return [];
|
|
221
|
+
}
|
|
222
|
+
throw error;
|
|
223
|
+
}
|
|
224
|
+
}, "resolveLazyTarget");
|
|
225
|
+
var collectChildren = /* @__PURE__ */ __name((schema) => {
|
|
226
|
+
const def = schema._zod.def;
|
|
227
|
+
if (def.type === "object") {
|
|
228
|
+
const out = [];
|
|
229
|
+
const shape = def.shape;
|
|
230
|
+
if (shape !== void 0) {
|
|
231
|
+
for (const value of Object.values(shape)) {
|
|
232
|
+
out.push(value);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (def.catchall !== void 0) {
|
|
236
|
+
out.push(def.catchall);
|
|
237
|
+
}
|
|
238
|
+
return out;
|
|
239
|
+
}
|
|
240
|
+
if (def.type === "array") {
|
|
241
|
+
return [
|
|
242
|
+
def.element
|
|
243
|
+
];
|
|
244
|
+
}
|
|
245
|
+
if (def.type === "union") {
|
|
246
|
+
return def.options.map((opt) => opt);
|
|
247
|
+
}
|
|
248
|
+
if (def.type === "intersection") {
|
|
249
|
+
return [
|
|
250
|
+
def.left,
|
|
251
|
+
def.right
|
|
252
|
+
];
|
|
253
|
+
}
|
|
254
|
+
if (def.type === "tuple") {
|
|
255
|
+
const out = def.items.map((it) => it);
|
|
256
|
+
if (def.rest !== null) {
|
|
257
|
+
out.push(def.rest);
|
|
258
|
+
}
|
|
259
|
+
return out;
|
|
260
|
+
}
|
|
261
|
+
if (def.type === "record" || def.type === "map") {
|
|
262
|
+
return [
|
|
263
|
+
def.keyType,
|
|
264
|
+
def.valueType
|
|
265
|
+
];
|
|
266
|
+
}
|
|
267
|
+
if (def.type === "set") {
|
|
268
|
+
return [
|
|
269
|
+
def.valueType
|
|
270
|
+
];
|
|
271
|
+
}
|
|
272
|
+
if (def.type === "pipe") {
|
|
273
|
+
return [
|
|
274
|
+
def.in,
|
|
275
|
+
def.out
|
|
276
|
+
];
|
|
277
|
+
}
|
|
278
|
+
if (def.type === "lazy") {
|
|
279
|
+
return resolveLazyTarget(() => def.getter());
|
|
280
|
+
}
|
|
281
|
+
if (INNER_TYPE_WRAPPERS.has(def.type)) {
|
|
282
|
+
return [
|
|
283
|
+
def.innerType
|
|
284
|
+
];
|
|
285
|
+
}
|
|
286
|
+
return [];
|
|
287
|
+
}, "collectChildren");
|
|
288
|
+
var discoverDependents = /* @__PURE__ */ __name((schema) => {
|
|
289
|
+
const visited = /* @__PURE__ */ new WeakSet();
|
|
290
|
+
const out = [];
|
|
291
|
+
const stack = [
|
|
292
|
+
schema
|
|
293
|
+
];
|
|
294
|
+
while (stack.length > 0) {
|
|
295
|
+
const current = stack.pop();
|
|
296
|
+
if (visited.has(current)) {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
visited.add(current);
|
|
300
|
+
for (const child of collectChildren(current)) {
|
|
301
|
+
if (child === void 0 || visited.has(child)) {
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
const id = readId(child);
|
|
305
|
+
if (id !== void 0) {
|
|
306
|
+
out.push([
|
|
307
|
+
child,
|
|
308
|
+
id
|
|
309
|
+
]);
|
|
310
|
+
}
|
|
311
|
+
stack.push(child);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return out;
|
|
315
|
+
}, "discoverDependents");
|
|
316
|
+
|
|
317
|
+
// src/schema/constants.ts
|
|
318
|
+
var COMPONENTS_SCHEMAS_PREFIX = "#/components/schemas/";
|
|
319
|
+
var DEFS_PREFIX = "#/$defs/";
|
|
320
|
+
var ZOD_NEST_ERROR_EXTENSION = "x-zod-nest-error";
|
|
321
|
+
var ZOD_NEST_ERROR_DUPLICATE_ID = "duplicate-id";
|
|
322
|
+
var createRegistry = /* @__PURE__ */ __name(() => {
|
|
323
|
+
const seen = /* @__PURE__ */ new Map();
|
|
324
|
+
const forceExposed = /* @__PURE__ */ new Set();
|
|
325
|
+
const anonymous = /* @__PURE__ */ new Set();
|
|
326
|
+
const pendingRoots = [];
|
|
327
|
+
const recordOnce = /* @__PURE__ */ __name((schema, id) => {
|
|
328
|
+
let set = seen.get(id);
|
|
329
|
+
if (set === void 0) {
|
|
330
|
+
set = /* @__PURE__ */ new Set();
|
|
331
|
+
seen.set(id, set);
|
|
332
|
+
}
|
|
333
|
+
if (set.has(schema)) {
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
set.add(schema);
|
|
337
|
+
return true;
|
|
338
|
+
}, "recordOnce");
|
|
339
|
+
const flushPendingDiscovery = /* @__PURE__ */ __name(() => {
|
|
340
|
+
for (const root of pendingRoots.splice(0)) {
|
|
341
|
+
for (const [child, childId] of discoverDependents(root)) {
|
|
342
|
+
recordOnce(child, childId);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}, "flushPendingDiscovery");
|
|
346
|
+
return {
|
|
347
|
+
zodRegistry: z.globalRegistry,
|
|
348
|
+
register: /* @__PURE__ */ __name((schema, id, flags) => {
|
|
349
|
+
if (flags?.expose === true) {
|
|
350
|
+
forceExposed.add(id);
|
|
351
|
+
}
|
|
352
|
+
if (flags?.anonymous === true) {
|
|
353
|
+
anonymous.add(id);
|
|
354
|
+
}
|
|
355
|
+
if (z.globalRegistry.has(schema)) {
|
|
356
|
+
const existing = z.globalRegistry.get(schema);
|
|
357
|
+
if (existing?.id !== id) {
|
|
358
|
+
z.globalRegistry.add(schema, {
|
|
359
|
+
...existing ?? {},
|
|
360
|
+
id
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
} else {
|
|
364
|
+
z.globalRegistry.add(schema, {
|
|
365
|
+
id
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
if (!recordOnce(schema, id)) {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
pendingRoots.push(schema);
|
|
372
|
+
}, "register"),
|
|
373
|
+
hasCollision: /* @__PURE__ */ __name((id) => {
|
|
374
|
+
flushPendingDiscovery();
|
|
375
|
+
const set = seen.get(id);
|
|
376
|
+
return set !== void 0 && set.size > 1;
|
|
377
|
+
}, "hasCollision"),
|
|
378
|
+
getCollisions: /* @__PURE__ */ __name(() => {
|
|
379
|
+
flushPendingDiscovery();
|
|
380
|
+
const out = /* @__PURE__ */ new Map();
|
|
381
|
+
for (const [id, set] of seen) {
|
|
382
|
+
if (set.size <= 1) {
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
out.set(id, set);
|
|
386
|
+
}
|
|
387
|
+
return out;
|
|
388
|
+
}, "getCollisions"),
|
|
389
|
+
ids: /* @__PURE__ */ __name(() => {
|
|
390
|
+
flushPendingDiscovery();
|
|
391
|
+
return [
|
|
392
|
+
...seen.keys()
|
|
393
|
+
];
|
|
394
|
+
}, "ids"),
|
|
395
|
+
forceExposedIds: /* @__PURE__ */ __name(() => [
|
|
396
|
+
...forceExposed
|
|
397
|
+
], "forceExposedIds"),
|
|
398
|
+
anonymousIds: /* @__PURE__ */ __name(() => [
|
|
399
|
+
...anonymous
|
|
400
|
+
], "anonymousIds")
|
|
401
|
+
};
|
|
402
|
+
}, "createRegistry");
|
|
403
|
+
var defaultRegistry = createRegistry();
|
|
404
|
+
var registerSchema = /* @__PURE__ */ __name((schema, registry = defaultRegistry, options) => {
|
|
405
|
+
const flags = {
|
|
406
|
+
expose: options?.expose,
|
|
407
|
+
anonymous: options?.anonymous
|
|
408
|
+
};
|
|
409
|
+
const explicit = options?.id;
|
|
410
|
+
if (typeof explicit === "string" && explicit !== "") {
|
|
411
|
+
registry.register(schema, explicit, flags);
|
|
412
|
+
return explicit;
|
|
413
|
+
}
|
|
414
|
+
const meta = registry.zodRegistry.get(schema);
|
|
415
|
+
const metaId = meta === void 0 ? void 0 : meta.id;
|
|
416
|
+
if (typeof metaId !== "string" || metaId === "") {
|
|
417
|
+
return void 0;
|
|
418
|
+
}
|
|
419
|
+
registry.register(schema, metaId, flags);
|
|
420
|
+
return metaId;
|
|
421
|
+
}, "registerSchema");
|
|
422
|
+
|
|
423
|
+
// src/schema/composition.ts
|
|
424
|
+
var lineageMap = /* @__PURE__ */ new WeakMap();
|
|
425
|
+
var propsMap = /* @__PURE__ */ new WeakMap();
|
|
426
|
+
var DEFAULT_BUILD_REF = /* @__PURE__ */ __name((id) => `${DEFS_PREFIX}${id}`, "DEFAULT_BUILD_REF");
|
|
427
|
+
var createCompositionOverride = /* @__PURE__ */ __name((opts) => {
|
|
428
|
+
const { buildRef, registry } = opts;
|
|
429
|
+
return (ctx) => {
|
|
430
|
+
const { jsonSchema, zodSchema } = ctx;
|
|
431
|
+
const entry = lineageMap.get(zodSchema);
|
|
432
|
+
if (entry === void 0) {
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
const parentCache = propsMap.get(entry.parent);
|
|
436
|
+
if (parentCache === void 0) {
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
const parentId = registry.zodRegistry.get(entry.parent)?.id;
|
|
440
|
+
if (parentId === void 0) {
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
registerSchema(entry.parent, registry);
|
|
444
|
+
const childProps = jsonSchema.properties ?? {};
|
|
445
|
+
const childRequired = jsonSchema.required ?? [];
|
|
446
|
+
const parentPropSet = new Set(parentCache.properties);
|
|
447
|
+
const parentReqSet = new Set(parentCache.required);
|
|
448
|
+
const deltaProps = {};
|
|
449
|
+
for (const [key, value] of Object.entries(childProps)) {
|
|
450
|
+
if (parentPropSet.has(key) && !entry.overriddenKeys.has(key)) {
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
deltaProps[key] = value;
|
|
454
|
+
}
|
|
455
|
+
const deltaRequired = childRequired.filter((key) => !parentReqSet.has(key) || entry.overriddenKeys.has(key));
|
|
456
|
+
const delta = {
|
|
457
|
+
type: "object",
|
|
458
|
+
properties: deltaProps
|
|
459
|
+
};
|
|
460
|
+
if (deltaRequired.length > 0) {
|
|
461
|
+
delta.required = deltaRequired;
|
|
462
|
+
}
|
|
463
|
+
delete jsonSchema.properties;
|
|
464
|
+
delete jsonSchema.required;
|
|
465
|
+
delete jsonSchema.additionalProperties;
|
|
466
|
+
jsonSchema.type = "object";
|
|
467
|
+
jsonSchema.allOf = [
|
|
468
|
+
{
|
|
469
|
+
$ref: buildRef(parentId)
|
|
470
|
+
},
|
|
471
|
+
delta
|
|
472
|
+
];
|
|
473
|
+
jsonSchema.unevaluatedProperties = false;
|
|
474
|
+
};
|
|
475
|
+
}, "createCompositionOverride");
|
|
476
|
+
|
|
477
|
+
// src/schema/errors.ts
|
|
478
|
+
var ZodNestError = class extends Error {
|
|
479
|
+
static {
|
|
480
|
+
__name(this, "ZodNestError");
|
|
481
|
+
}
|
|
482
|
+
constructor(message) {
|
|
483
|
+
super(message);
|
|
484
|
+
this.name = "ZodNestError";
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
var ZodNestUnrepresentableError = class extends ZodNestError {
|
|
488
|
+
static {
|
|
489
|
+
__name(this, "ZodNestUnrepresentableError");
|
|
490
|
+
}
|
|
491
|
+
path;
|
|
492
|
+
zodType;
|
|
493
|
+
constructor(path, zodType) {
|
|
494
|
+
super(`Unrepresentable Zod schema \`${zodType}\` at ${formatPath(path)}: no override produced a JSON Schema body. Set strict: false to emit \`{}\` instead, or supply an \`override\` that handles this Zod type.`);
|
|
495
|
+
this.name = "ZodNestUnrepresentableError";
|
|
496
|
+
this.path = path;
|
|
497
|
+
this.zodType = zodType;
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
var formatPath = /* @__PURE__ */ __name((path) => {
|
|
501
|
+
if (path.length === 0) {
|
|
502
|
+
return "<root>";
|
|
503
|
+
}
|
|
504
|
+
return "/" + path.map(String).join("/");
|
|
505
|
+
}, "formatPath");
|
|
506
|
+
|
|
507
|
+
// src/schema/override.ts
|
|
508
|
+
var primitiveOverride = /* @__PURE__ */ __name(({ zodSchema, jsonSchema }) => {
|
|
509
|
+
const type = zodSchema._zod.def.type;
|
|
510
|
+
if (type === "bigint") {
|
|
511
|
+
jsonSchema.type = "integer";
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
if (type === "date") {
|
|
515
|
+
jsonSchema.type = "string";
|
|
516
|
+
jsonSchema.format = "date-time";
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
}, "primitiveOverride");
|
|
520
|
+
var combine = /* @__PURE__ */ __name((...overrides) => {
|
|
521
|
+
const list = [];
|
|
522
|
+
for (const candidate of overrides) {
|
|
523
|
+
if (typeof candidate !== "function") {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
list.push(candidate);
|
|
527
|
+
}
|
|
528
|
+
return (ctx) => {
|
|
529
|
+
for (const o of list) {
|
|
530
|
+
o(ctx);
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
}, "combine");
|
|
534
|
+
|
|
535
|
+
// src/schema/post-process.ts
|
|
536
|
+
var rewriteRefs = /* @__PURE__ */ __name((node, rootRef) => {
|
|
537
|
+
if (Array.isArray(node)) {
|
|
538
|
+
for (const item of node) {
|
|
539
|
+
rewriteRefs(item, rootRef);
|
|
540
|
+
}
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
if (node === null || typeof node !== "object") {
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
const obj = node;
|
|
547
|
+
const ref = obj.$ref;
|
|
548
|
+
if (typeof ref === "string" && ref.startsWith(DEFS_PREFIX)) {
|
|
549
|
+
obj.$ref = COMPONENTS_SCHEMAS_PREFIX + ref.slice(DEFS_PREFIX.length);
|
|
550
|
+
} else if (ref === "#" && rootRef !== void 0) {
|
|
551
|
+
obj.$ref = rootRef;
|
|
552
|
+
}
|
|
553
|
+
for (const value of Object.values(obj)) {
|
|
554
|
+
rewriteRefs(value, rootRef);
|
|
555
|
+
}
|
|
556
|
+
}, "rewriteRefs");
|
|
557
|
+
var refsIn = /* @__PURE__ */ __name(function* (node) {
|
|
558
|
+
if (Array.isArray(node)) {
|
|
559
|
+
for (const item of node) {
|
|
560
|
+
yield* refsIn(item);
|
|
561
|
+
}
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
if (node === null || typeof node !== "object") {
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
const obj = node;
|
|
568
|
+
if (typeof obj.$ref === "string") {
|
|
569
|
+
yield obj.$ref;
|
|
570
|
+
}
|
|
571
|
+
for (const value of Object.values(obj)) {
|
|
572
|
+
yield* refsIn(value);
|
|
573
|
+
}
|
|
574
|
+
}, "refsIn");
|
|
575
|
+
var rootDefId = /* @__PURE__ */ __name((raw) => {
|
|
576
|
+
const ref = raw.$ref;
|
|
577
|
+
if (typeof ref !== "string" || !ref.startsWith(DEFS_PREFIX)) {
|
|
578
|
+
return void 0;
|
|
579
|
+
}
|
|
580
|
+
return ref.slice(DEFS_PREFIX.length);
|
|
581
|
+
}, "rootDefId");
|
|
582
|
+
var isReferenced = /* @__PURE__ */ __name((defs, id) => {
|
|
583
|
+
const ownRef = `${DEFS_PREFIX}${id}`;
|
|
584
|
+
for (const ref of refsIn(defs)) {
|
|
585
|
+
if (ref === "#" || ref === ownRef) {
|
|
586
|
+
return true;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
return false;
|
|
590
|
+
}, "isReferenced");
|
|
591
|
+
var referencesRoot = /* @__PURE__ */ __name((raw) => {
|
|
592
|
+
for (const ref of refsIn(raw)) {
|
|
593
|
+
if (ref === "#") {
|
|
594
|
+
return true;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
return false;
|
|
598
|
+
}, "referencesRoot");
|
|
599
|
+
var stripEnvelope = /* @__PURE__ */ __name((raw) => {
|
|
600
|
+
const root = {
|
|
601
|
+
...raw
|
|
602
|
+
};
|
|
603
|
+
delete root.$schema;
|
|
604
|
+
delete root.$defs;
|
|
605
|
+
return root;
|
|
606
|
+
}, "stripEnvelope");
|
|
607
|
+
var resolveRoot = /* @__PURE__ */ __name((raw, refs, options) => {
|
|
608
|
+
const liftedId = rootDefId(raw);
|
|
609
|
+
if (liftedId !== void 0) {
|
|
610
|
+
const body = refs.get(liftedId);
|
|
611
|
+
if (body !== void 0 && !isReferenced(raw.$defs, liftedId)) {
|
|
612
|
+
refs.delete(liftedId);
|
|
613
|
+
return {
|
|
614
|
+
schema: body,
|
|
615
|
+
rootRef: void 0
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
return {
|
|
619
|
+
schema: stripEnvelope(raw),
|
|
620
|
+
rootRef: `${COMPONENTS_SCHEMAS_PREFIX}${liftedId}`
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
const root = stripEnvelope(raw);
|
|
624
|
+
if (!referencesRoot(raw)) {
|
|
625
|
+
return {
|
|
626
|
+
schema: root,
|
|
627
|
+
rootRef: void 0
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
const rootId = options?.rootId;
|
|
631
|
+
if (rootId === void 0) {
|
|
632
|
+
if (options?.strict ?? true) {
|
|
633
|
+
throw new ZodNestError('A schema referenced from inside its own emission has no id, so the reference cannot be resolved. Add `.meta({ id: "\u2026" })` to the root schema, or set strict: false to leave the reference unresolved.');
|
|
634
|
+
}
|
|
635
|
+
return {
|
|
636
|
+
schema: root,
|
|
637
|
+
rootRef: void 0
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
refs.set(rootId, root);
|
|
641
|
+
const rootRef = `${COMPONENTS_SCHEMAS_PREFIX}${rootId}`;
|
|
642
|
+
return {
|
|
643
|
+
schema: {
|
|
644
|
+
$ref: rootRef
|
|
645
|
+
},
|
|
646
|
+
rootRef
|
|
647
|
+
};
|
|
648
|
+
}, "resolveRoot");
|
|
649
|
+
var postProcess = /* @__PURE__ */ __name((raw, options) => {
|
|
650
|
+
const refs = /* @__PURE__ */ new Map();
|
|
651
|
+
const rawDefs = raw.$defs;
|
|
652
|
+
if (rawDefs !== void 0) {
|
|
653
|
+
for (const [id, body] of Object.entries(rawDefs)) {
|
|
654
|
+
refs.set(id, body);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
const { schema, rootRef } = resolveRoot(raw, refs, options);
|
|
658
|
+
rewriteRefs(schema, rootRef);
|
|
659
|
+
for (const body of refs.values()) {
|
|
660
|
+
rewriteRefs(body, rootRef);
|
|
661
|
+
}
|
|
662
|
+
return {
|
|
663
|
+
schema,
|
|
664
|
+
refs
|
|
665
|
+
};
|
|
666
|
+
}, "postProcess");
|
|
667
|
+
|
|
668
|
+
// src/schema/engine.ts
|
|
669
|
+
var STRICT_REQUIRES_OVERRIDE = /* @__PURE__ */ new Set([
|
|
670
|
+
"bigint",
|
|
671
|
+
"date",
|
|
672
|
+
"symbol",
|
|
673
|
+
"undefined",
|
|
674
|
+
"void",
|
|
675
|
+
"map",
|
|
676
|
+
"set",
|
|
677
|
+
"transform",
|
|
678
|
+
"nan",
|
|
679
|
+
"custom"
|
|
680
|
+
]);
|
|
681
|
+
var ANNOTATION_ONLY_KEYS = /* @__PURE__ */ new Set([
|
|
682
|
+
"title",
|
|
683
|
+
"description",
|
|
684
|
+
"deprecated",
|
|
685
|
+
"examples",
|
|
686
|
+
"default",
|
|
687
|
+
"readOnly",
|
|
688
|
+
"writeOnly",
|
|
689
|
+
"$id",
|
|
690
|
+
"$schema",
|
|
691
|
+
"$comment",
|
|
692
|
+
"id"
|
|
693
|
+
]);
|
|
694
|
+
var isStrictlyUnrepresentable = /* @__PURE__ */ __name((jsonSchema, zodSchema) => {
|
|
695
|
+
if (!STRICT_REQUIRES_OVERRIDE.has(zodSchema._zod.def.type)) {
|
|
696
|
+
return false;
|
|
697
|
+
}
|
|
698
|
+
return Object.keys(jsonSchema).every((key) => ANNOTATION_ONLY_KEYS.has(key));
|
|
699
|
+
}, "isStrictlyUnrepresentable");
|
|
700
|
+
var markPipeCoverage = /* @__PURE__ */ __name((schema, io, covered) => {
|
|
701
|
+
const def = schema._zod.def;
|
|
702
|
+
if (def.type !== "pipe" || def.in === void 0 || def.out === void 0) {
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
const target = io === "output" ? def.out : def.in._zod.traits.has("$ZodTransform") ? def.out : def.in;
|
|
706
|
+
if (covered.has(target)) {
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
covered.add(target);
|
|
710
|
+
markPipeCoverage(target, io, covered);
|
|
711
|
+
}, "markPipeCoverage");
|
|
712
|
+
var buildToJsonSchemaOptions = /* @__PURE__ */ __name((params) => {
|
|
713
|
+
const strict = params.strict ?? true;
|
|
714
|
+
const compositionOverride = createCompositionOverride({
|
|
715
|
+
buildRef: params.uri ?? DEFAULT_BUILD_REF,
|
|
716
|
+
registry: params.registry
|
|
717
|
+
});
|
|
718
|
+
const customOverride = createCustomOverride(params.io);
|
|
719
|
+
const merged = combine(primitiveOverride, compositionOverride, customOverride, params.override);
|
|
720
|
+
const unrepresentableHits = [];
|
|
721
|
+
const coveredByPipe = /* @__PURE__ */ new WeakSet();
|
|
722
|
+
const wrapped = /* @__PURE__ */ __name((ctx) => {
|
|
723
|
+
merged(ctx);
|
|
724
|
+
if (ctx.zodSchema._zod.def.type === "pipe") {
|
|
725
|
+
const record = peekRegistration(ctx.zodSchema);
|
|
726
|
+
if (record !== void 0 && record[params.io] !== void 0) {
|
|
727
|
+
markPipeCoverage(ctx.zodSchema, params.io, coveredByPipe);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
if (!strict || !isStrictlyUnrepresentable(ctx.jsonSchema, ctx.zodSchema)) {
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
unrepresentableHits.push({
|
|
734
|
+
path: [
|
|
735
|
+
...ctx.path
|
|
736
|
+
],
|
|
737
|
+
zodType: ctx.zodSchema._zod.def.type,
|
|
738
|
+
zodSchema: ctx.zodSchema
|
|
739
|
+
});
|
|
740
|
+
}, "wrapped");
|
|
741
|
+
const options = {
|
|
742
|
+
target: "draft-2020-12",
|
|
743
|
+
io: params.io,
|
|
744
|
+
unrepresentable: "any",
|
|
745
|
+
metadata: params.registry.zodRegistry,
|
|
746
|
+
override: wrapped,
|
|
747
|
+
cycles: "ref",
|
|
748
|
+
reused: params.reused
|
|
749
|
+
};
|
|
750
|
+
if (params.uri !== void 0) {
|
|
751
|
+
options.uri = params.uri;
|
|
752
|
+
}
|
|
753
|
+
return {
|
|
754
|
+
options,
|
|
755
|
+
consumeUnrepresentable: /* @__PURE__ */ __name(() => {
|
|
756
|
+
const firstHit = unrepresentableHits.find((hit) => !coveredByPipe.has(hit.zodSchema));
|
|
757
|
+
if (firstHit !== void 0) {
|
|
758
|
+
throw new ZodNestUnrepresentableError(firstHit.path, firstHit.zodType);
|
|
759
|
+
}
|
|
760
|
+
}, "consumeUnrepresentable")
|
|
761
|
+
};
|
|
762
|
+
}, "buildToJsonSchemaOptions");
|
|
763
|
+
var resolveRootId = /* @__PURE__ */ __name((schema, registry) => {
|
|
764
|
+
const id = registry.zodRegistry.get(schema)?.id;
|
|
765
|
+
return typeof id === "string" && id !== "" ? id : void 0;
|
|
766
|
+
}, "resolveRootId");
|
|
767
|
+
var toOpenApi = /* @__PURE__ */ __name((schema, opts) => {
|
|
768
|
+
const built = buildToJsonSchemaOptions({
|
|
769
|
+
registry: opts.registry,
|
|
770
|
+
io: opts.io,
|
|
771
|
+
override: opts.override,
|
|
772
|
+
strict: opts.strict,
|
|
773
|
+
reused: "inline"
|
|
774
|
+
});
|
|
775
|
+
const raw = z.toJSONSchema(schema, built.options);
|
|
776
|
+
built.consumeUnrepresentable();
|
|
777
|
+
const result = postProcess(raw, {
|
|
778
|
+
rootId: resolveRootId(schema, opts.registry),
|
|
779
|
+
strict: opts.strict
|
|
780
|
+
});
|
|
781
|
+
for (const [id] of opts.registry.getCollisions()) {
|
|
782
|
+
if (!result.refs.has(id)) {
|
|
783
|
+
continue;
|
|
784
|
+
}
|
|
785
|
+
result.refs.set(id, {
|
|
786
|
+
description: `ERROR: duplicate zod-nest id <${id}>`,
|
|
787
|
+
[ZOD_NEST_ERROR_EXTENSION]: ZOD_NEST_ERROR_DUPLICATE_ID
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
return result;
|
|
791
|
+
}, "toOpenApi");
|
|
792
|
+
|
|
793
|
+
// src/schema/anon-id.ts
|
|
794
|
+
var ANON_BODY_PREFIX = "_AnonBodySchema_";
|
|
795
|
+
var anonIdCache = /* @__PURE__ */ new WeakMap();
|
|
796
|
+
var counter = 0;
|
|
797
|
+
var resolveAnonId = /* @__PURE__ */ __name((schema, prefix) => {
|
|
798
|
+
const cached = anonIdCache.get(schema);
|
|
799
|
+
if (cached !== void 0) {
|
|
800
|
+
return cached;
|
|
801
|
+
}
|
|
802
|
+
counter += 1;
|
|
803
|
+
const id = `${prefix}${counter}`;
|
|
804
|
+
anonIdCache.set(schema, id);
|
|
805
|
+
return id;
|
|
806
|
+
}, "resolveAnonId");
|
|
807
|
+
|
|
808
|
+
// src/decorators/internal/zod-schema-ref.ts
|
|
809
|
+
function resolveSchemaRef(schema, options) {
|
|
810
|
+
const registry = options?.registry ?? defaultRegistry;
|
|
811
|
+
const id = registerSchema(schema, registry, {
|
|
812
|
+
id: options?.id
|
|
813
|
+
});
|
|
814
|
+
if (id !== void 0) {
|
|
815
|
+
return {
|
|
816
|
+
kind: "ref",
|
|
817
|
+
ref: {
|
|
818
|
+
$ref: `${COMPONENTS_SCHEMAS_PREFIX}${id}`
|
|
819
|
+
}
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
if (options?.deferAnonInline === true) {
|
|
823
|
+
const anonId = resolveAnonId(schema, ANON_BODY_PREFIX);
|
|
824
|
+
registerSchema(schema, registry, {
|
|
825
|
+
id: anonId,
|
|
826
|
+
anonymous: true
|
|
827
|
+
});
|
|
828
|
+
return {
|
|
829
|
+
kind: "ref",
|
|
830
|
+
ref: {
|
|
831
|
+
$ref: `${COMPONENTS_SCHEMAS_PREFIX}${anonId}`
|
|
832
|
+
}
|
|
833
|
+
};
|
|
834
|
+
}
|
|
835
|
+
for (const [child, childId] of discoverDependents(schema)) {
|
|
836
|
+
registry.register(child, childId);
|
|
837
|
+
}
|
|
838
|
+
const { schema: body } = toOpenApi(schema, {
|
|
839
|
+
io: "input",
|
|
840
|
+
registry
|
|
841
|
+
});
|
|
842
|
+
return {
|
|
843
|
+
kind: "inline",
|
|
844
|
+
schema: body
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
__name(resolveSchemaRef, "resolveSchemaRef");
|
|
848
|
+
|
|
849
|
+
// src/decorators/internal/zod-param-expand.ts
|
|
850
|
+
var isZodObject = /* @__PURE__ */ __name((schema) => schema._zod.def.type === "object", "isZodObject");
|
|
851
|
+
|
|
852
|
+
// src/decorators/internal/flatten-intersection.ts
|
|
853
|
+
var intersectionArms = /* @__PURE__ */ __name((schema) => {
|
|
854
|
+
if (schema._zod.def.type !== "intersection") {
|
|
855
|
+
return null;
|
|
856
|
+
}
|
|
857
|
+
const def = schema._zod.def;
|
|
858
|
+
return {
|
|
859
|
+
left: def.left,
|
|
860
|
+
right: def.right
|
|
861
|
+
};
|
|
862
|
+
}, "intersectionArms");
|
|
863
|
+
var unionOptions = /* @__PURE__ */ __name((schema) => {
|
|
864
|
+
if (schema._zod.def.type !== "union") {
|
|
865
|
+
return null;
|
|
866
|
+
}
|
|
867
|
+
const def = schema._zod.def;
|
|
868
|
+
return def.options;
|
|
869
|
+
}, "unionOptions");
|
|
870
|
+
var collectObjectShapes = /* @__PURE__ */ __name((schema) => {
|
|
871
|
+
if (isZodObject(schema)) {
|
|
872
|
+
return {
|
|
873
|
+
shapes: [
|
|
874
|
+
schema.shape
|
|
875
|
+
],
|
|
876
|
+
unionCrossed: false
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
const options = unionOptions(schema);
|
|
880
|
+
if (options !== null) {
|
|
881
|
+
const allShapes = [];
|
|
882
|
+
for (const variant of options) {
|
|
883
|
+
const variantResult = collectObjectShapes(variant);
|
|
884
|
+
if (variantResult === null) {
|
|
885
|
+
return null;
|
|
886
|
+
}
|
|
887
|
+
allShapes.push(...variantResult.shapes);
|
|
888
|
+
}
|
|
889
|
+
return {
|
|
890
|
+
shapes: allShapes,
|
|
891
|
+
unionCrossed: true
|
|
892
|
+
};
|
|
893
|
+
}
|
|
894
|
+
const arms = intersectionArms(schema);
|
|
895
|
+
if (arms === null) {
|
|
896
|
+
return null;
|
|
897
|
+
}
|
|
898
|
+
const left = collectObjectShapes(arms.left);
|
|
899
|
+
if (left === null) {
|
|
900
|
+
return null;
|
|
901
|
+
}
|
|
902
|
+
const right = collectObjectShapes(arms.right);
|
|
903
|
+
if (right === null) {
|
|
904
|
+
return null;
|
|
905
|
+
}
|
|
906
|
+
return {
|
|
907
|
+
shapes: [
|
|
908
|
+
...left.shapes,
|
|
909
|
+
...right.shapes
|
|
910
|
+
],
|
|
911
|
+
unionCrossed: left.unionCrossed || right.unionCrossed
|
|
912
|
+
};
|
|
913
|
+
}, "collectObjectShapes");
|
|
914
|
+
var flattenObjectIntersection = /* @__PURE__ */ __name((schema, registry, decoratorName) => {
|
|
915
|
+
const collected = collectObjectShapes(schema);
|
|
916
|
+
if (collected === null) {
|
|
917
|
+
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.`);
|
|
918
|
+
}
|
|
919
|
+
const mergedShape = {};
|
|
920
|
+
for (const shape of collected.shapes) {
|
|
921
|
+
Object.assign(mergedShape, shape);
|
|
922
|
+
}
|
|
923
|
+
if (collected.unionCrossed) {
|
|
924
|
+
for (const key of Object.keys(mergedShape)) {
|
|
925
|
+
const value = mergedShape[key];
|
|
926
|
+
if (value !== void 0) {
|
|
927
|
+
mergedShape[key] = value.optional();
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
const merged = z.object(mergedShape);
|
|
932
|
+
registerSchema(schema, registry);
|
|
933
|
+
for (const [child, childId] of discoverDependents(schema)) {
|
|
934
|
+
registry.register(child, childId);
|
|
935
|
+
}
|
|
936
|
+
const { schema: body } = toOpenApi(merged, {
|
|
937
|
+
io: "input",
|
|
938
|
+
registry
|
|
939
|
+
});
|
|
940
|
+
return body;
|
|
941
|
+
}, "flattenObjectIntersection");
|
|
942
|
+
var isZodSchema = /* @__PURE__ */ __name((value) => value instanceof z.ZodType, "isZodSchema");
|
|
943
|
+
|
|
944
|
+
// src/multipart/zod-multipart.decorator.ts
|
|
945
|
+
var MULTIPART_CONTENT_TYPE = "multipart/form-data";
|
|
946
|
+
var toSchema = /* @__PURE__ */ __name((body) => isZodSchema(body) ? body : z.object({
|
|
947
|
+
...body
|
|
948
|
+
}), "toSchema");
|
|
949
|
+
var toShape = /* @__PURE__ */ __name((body) => {
|
|
950
|
+
if (!isZodSchema(body)) {
|
|
951
|
+
return body;
|
|
952
|
+
}
|
|
953
|
+
return isZodObject(body) ? body.shape : void 0;
|
|
954
|
+
}, "toShape");
|
|
955
|
+
var partitionKeys = /* @__PURE__ */ __name((shape) => {
|
|
956
|
+
const fileKeys = [];
|
|
957
|
+
const textKeys = [];
|
|
958
|
+
for (const [key, schema] of Object.entries(shape ?? {})) {
|
|
959
|
+
if (isFileSchema(schema)) {
|
|
960
|
+
fileKeys.push(key);
|
|
961
|
+
continue;
|
|
962
|
+
}
|
|
963
|
+
textKeys.push(key);
|
|
964
|
+
}
|
|
965
|
+
return {
|
|
966
|
+
fileKeys,
|
|
967
|
+
textKeys
|
|
968
|
+
};
|
|
969
|
+
}, "partitionKeys");
|
|
970
|
+
var resolveBody = /* @__PURE__ */ __name((schema, options, registry) => {
|
|
971
|
+
if (options?.flatten === true) {
|
|
972
|
+
return flattenObjectIntersection(schema, registry, "@ZodMultipart");
|
|
973
|
+
}
|
|
974
|
+
const resolved = resolveSchemaRef(schema, {
|
|
975
|
+
...options?.id !== void 0 ? {
|
|
976
|
+
id: options.id
|
|
977
|
+
} : {},
|
|
978
|
+
registry
|
|
979
|
+
});
|
|
980
|
+
return resolved.kind === "ref" ? resolved.ref : resolved.schema;
|
|
981
|
+
}, "resolveBody");
|
|
982
|
+
var createZodMultipart = /* @__PURE__ */ __name((defaultFilesIn) => {
|
|
983
|
+
return (body, options) => {
|
|
984
|
+
const registry = options?.registry ?? defaultRegistry;
|
|
985
|
+
const shape = toShape(body);
|
|
986
|
+
const metadata = {
|
|
987
|
+
shape,
|
|
988
|
+
...partitionKeys(shape),
|
|
989
|
+
filesIn: options?.filesIn ?? defaultFilesIn
|
|
990
|
+
};
|
|
991
|
+
const schema = resolveBody(toSchema(body), options, registry);
|
|
992
|
+
return (target, propertyKey, descriptor) => {
|
|
993
|
+
const handler = descriptor.value;
|
|
994
|
+
if (typeof handler !== "function") {
|
|
995
|
+
throw new TypeError("[zod-nest] @ZodMultipart can only be applied to methods.");
|
|
996
|
+
}
|
|
997
|
+
Reflect.defineMetadata(ZOD_MULTIPART_METADATA_KEY, metadata, handler);
|
|
998
|
+
const swaggerDescriptor = descriptor;
|
|
999
|
+
ApiConsumes(MULTIPART_CONTENT_TYPE)(target, propertyKey, swaggerDescriptor);
|
|
1000
|
+
ApiBody({
|
|
1001
|
+
schema,
|
|
1002
|
+
...options?.description !== void 0 ? {
|
|
1003
|
+
description: options.description
|
|
1004
|
+
} : {},
|
|
1005
|
+
required: options?.required ?? true
|
|
1006
|
+
})(target, propertyKey, swaggerDescriptor);
|
|
1007
|
+
};
|
|
1008
|
+
};
|
|
1009
|
+
}, "createZodMultipart");
|
|
1010
|
+
var ZodValidationException = class extends BadRequestException {
|
|
1011
|
+
static {
|
|
1012
|
+
__name(this, "ZodValidationException");
|
|
1013
|
+
}
|
|
1014
|
+
zodError;
|
|
1015
|
+
argMetadata;
|
|
1016
|
+
constructor(zodError, argMetadata) {
|
|
1017
|
+
super({
|
|
1018
|
+
statusCode: HttpStatus.BAD_REQUEST,
|
|
1019
|
+
message: "Validation failed",
|
|
1020
|
+
errors: z.treeifyError(zodError)
|
|
1021
|
+
}, {
|
|
1022
|
+
cause: zodError
|
|
1023
|
+
});
|
|
1024
|
+
this.zodError = zodError;
|
|
1025
|
+
this.argMetadata = argMetadata;
|
|
1026
|
+
}
|
|
1027
|
+
};
|
|
1028
|
+
|
|
1029
|
+
// src/multipart/param-decorators.ts
|
|
1030
|
+
var readMetadata = /* @__PURE__ */ __name((ctx, decorator) => {
|
|
1031
|
+
const metadata = Reflect.getMetadata(ZOD_MULTIPART_METADATA_KEY, ctx.getHandler());
|
|
1032
|
+
if (!isMultipartMetadata(metadata)) {
|
|
1033
|
+
throw new Error(`[zod-nest] ${decorator} requires @ZodMultipart on the same handler \u2014 it reads the declared shape from there.`);
|
|
1034
|
+
}
|
|
1035
|
+
return metadata;
|
|
1036
|
+
}, "readMetadata");
|
|
1037
|
+
var isMultipartMetadata = /* @__PURE__ */ __name((value) => value !== null && typeof value === "object" && "shape" in value && "filesIn" in value, "isMultipartMetadata");
|
|
1038
|
+
var requireShape = /* @__PURE__ */ __name((metadata, decorator) => {
|
|
1039
|
+
if (metadata.shape !== void 0) {
|
|
1040
|
+
return metadata.shape;
|
|
1041
|
+
}
|
|
1042
|
+
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.`);
|
|
1043
|
+
}, "requireShape");
|
|
1044
|
+
var schemaFor = /* @__PURE__ */ __name((metadata, name, decorator) => {
|
|
1045
|
+
const shape = requireShape(metadata, decorator);
|
|
1046
|
+
const schema = shape[name];
|
|
1047
|
+
if (schema === void 0) {
|
|
1048
|
+
throw new Error(`[zod-nest] ${decorator}('${name}') has no matching property in the @ZodMultipart shape. Declared: ${Object.keys(shape).join(", ")}.`);
|
|
1049
|
+
}
|
|
1050
|
+
return schema;
|
|
1051
|
+
}, "schemaFor");
|
|
1052
|
+
var pick = /* @__PURE__ */ __name((shape, keys) => {
|
|
1053
|
+
const wanted = new Set(keys);
|
|
1054
|
+
const picked = {};
|
|
1055
|
+
for (const [key, schema] of Object.entries(shape)) {
|
|
1056
|
+
if (wanted.has(key)) {
|
|
1057
|
+
picked[key] = schema;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
return z.object(picked);
|
|
1061
|
+
}, "pick");
|
|
1062
|
+
var validate = /* @__PURE__ */ __name(async (schema, value, argType) => {
|
|
1063
|
+
const result = await schema.safeParseAsync(value);
|
|
1064
|
+
if (result.success) {
|
|
1065
|
+
return result.data;
|
|
1066
|
+
}
|
|
1067
|
+
throw new ZodValidationException(result.error, {
|
|
1068
|
+
type: argType,
|
|
1069
|
+
metatype: void 0,
|
|
1070
|
+
data: void 0
|
|
1071
|
+
});
|
|
1072
|
+
}, "validate");
|
|
1073
|
+
var assertFilesOnRequest = /* @__PURE__ */ __name((metadata, decorator) => {
|
|
1074
|
+
if (metadata.filesIn === MultipartFilesIn.Request) {
|
|
1075
|
+
return;
|
|
1076
|
+
}
|
|
1077
|
+
throw new Error(`[zod-nest] ${decorator} is unavailable under filesIn: 'body' \u2014 the parser puts files in the request body, so read them with @ZodMultipartBody().`);
|
|
1078
|
+
}, "assertFilesOnRequest");
|
|
1079
|
+
var resolveUploadedFile = /* @__PURE__ */ __name(async (name, ctx) => {
|
|
1080
|
+
const metadata = readMetadata(ctx, "@ZodUploadedFile");
|
|
1081
|
+
assertFilesOnRequest(metadata, "@ZodUploadedFile");
|
|
1082
|
+
const request = ctx.switchToHttp().getRequest();
|
|
1083
|
+
return validate(schemaFor(metadata, name, "@ZodUploadedFile"), request.file, "custom");
|
|
1084
|
+
}, "resolveUploadedFile");
|
|
1085
|
+
var resolveUploadedFiles = /* @__PURE__ */ __name(async (name, ctx) => {
|
|
1086
|
+
const metadata = readMetadata(ctx, "@ZodUploadedFiles");
|
|
1087
|
+
assertFilesOnRequest(metadata, "@ZodUploadedFiles");
|
|
1088
|
+
const request = ctx.switchToHttp().getRequest();
|
|
1089
|
+
const schema = name === void 0 ? pick(requireShape(metadata, "@ZodUploadedFiles"), metadata.fileKeys) : schemaFor(metadata, name, "@ZodUploadedFiles");
|
|
1090
|
+
return validate(schema, request.files, "custom");
|
|
1091
|
+
}, "resolveUploadedFiles");
|
|
1092
|
+
var resolveMultipartBody = /* @__PURE__ */ __name(async (_data, ctx) => {
|
|
1093
|
+
const metadata = readMetadata(ctx, "@ZodMultipartBody");
|
|
1094
|
+
const shape = requireShape(metadata, "@ZodMultipartBody");
|
|
1095
|
+
const request = ctx.switchToHttp().getRequest();
|
|
1096
|
+
const keys = metadata.filesIn === MultipartFilesIn.Body ? Object.keys(shape) : metadata.textKeys;
|
|
1097
|
+
return validate(pick(shape, keys), request.body, "body");
|
|
1098
|
+
}, "resolveMultipartBody");
|
|
1099
|
+
var ZodUploadedFile = createParamDecorator(resolveUploadedFile);
|
|
1100
|
+
var ZodUploadedFiles = createParamDecorator(resolveUploadedFiles);
|
|
1101
|
+
var ZodMultipartBody = createParamDecorator(resolveMultipartBody);
|
|
1102
|
+
|
|
1103
|
+
// src/express/index.ts
|
|
1104
|
+
var hasCommonFields = /* @__PURE__ */ __name((value) => value !== null && typeof value === "object" && "mimetype" in value && "originalname" in value && "size" in value, "hasCommonFields");
|
|
1105
|
+
var isMulterMemoryFile = /* @__PURE__ */ __name((value) => hasCommonFields(value) && Buffer.isBuffer(value.buffer), "isMulterMemoryFile");
|
|
1106
|
+
var isMulterDiskFile = /* @__PURE__ */ __name((value) => hasCommonFields(value) && typeof value.path === "string", "isMulterDiskFile");
|
|
1107
|
+
var memoryAccessors = {
|
|
1108
|
+
mimeType: /* @__PURE__ */ __name((file) => file.mimetype, "mimeType"),
|
|
1109
|
+
fileName: /* @__PURE__ */ __name((file) => file.originalname, "fileName"),
|
|
1110
|
+
size: /* @__PURE__ */ __name((file) => file.size, "size")
|
|
1111
|
+
};
|
|
1112
|
+
var diskAccessors = {
|
|
1113
|
+
mimeType: /* @__PURE__ */ __name((file) => file.mimetype, "mimeType"),
|
|
1114
|
+
fileName: /* @__PURE__ */ __name((file) => file.originalname, "fileName"),
|
|
1115
|
+
size: /* @__PURE__ */ __name((file) => file.size, "size")
|
|
1116
|
+
};
|
|
1117
|
+
var multerMemoryFile = /* @__PURE__ */ __name((options) => buildFileSchema({
|
|
1118
|
+
predicate: isMulterMemoryFile,
|
|
1119
|
+
accessors: memoryAccessors,
|
|
1120
|
+
options,
|
|
1121
|
+
...options?.maxSize !== void 0 ? {
|
|
1122
|
+
maxSize: options.maxSize
|
|
1123
|
+
} : {}
|
|
1124
|
+
}), "multerMemoryFile");
|
|
1125
|
+
var multerDiskFile = /* @__PURE__ */ __name((options) => buildFileSchema({
|
|
1126
|
+
predicate: isMulterDiskFile,
|
|
1127
|
+
accessors: diskAccessors,
|
|
1128
|
+
options,
|
|
1129
|
+
...options?.maxSize !== void 0 ? {
|
|
1130
|
+
maxSize: options.maxSize
|
|
1131
|
+
} : {}
|
|
1132
|
+
}), "multerDiskFile");
|
|
1133
|
+
var MulterMemoryFileSchema = multerMemoryFile();
|
|
1134
|
+
var MulterDiskFileSchema = multerDiskFile();
|
|
1135
|
+
var ZodMultipart = createZodMultipart(MultipartFilesIn.Request);
|
|
1136
|
+
|
|
1137
|
+
export { MULTIPART_CONTENT_TYPE, MulterDiskFileSchema, MulterMemoryFileSchema, ZodMultipart, ZodMultipartBody, ZodUploadedFile, ZodUploadedFiles, multerDiskFile, multerMemoryFile };
|
|
1138
|
+
//# sourceMappingURL=index.mjs.map
|
|
1139
|
+
//# sourceMappingURL=index.mjs.map
|