zod-openapi 2.11.0 → 2.13.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.
Files changed (39) hide show
  1. package/README.md +6 -4
  2. package/lib-commonjs/index.js +691 -285
  3. package/lib-esm/{index.js → index.mjs} +691 -285
  4. package/lib-types/create/components.d.ts +25 -2
  5. package/lib-types/create/schema/index.d.ts +19 -12
  6. package/lib-types/create/schema/metadata.d.ts +2 -1
  7. package/lib-types/create/schema/parsers/array.d.ts +2 -3
  8. package/lib-types/create/schema/parsers/boolean.d.ts +2 -2
  9. package/lib-types/create/schema/parsers/brand.d.ts +2 -3
  10. package/lib-types/create/schema/parsers/catch.d.ts +2 -3
  11. package/lib-types/create/schema/parsers/date.d.ts +2 -2
  12. package/lib-types/create/schema/parsers/default.d.ts +2 -3
  13. package/lib-types/create/schema/parsers/discriminatedUnion.d.ts +2 -2
  14. package/lib-types/create/schema/parsers/enum.d.ts +2 -2
  15. package/lib-types/create/schema/parsers/index.d.ts +2 -3
  16. package/lib-types/create/schema/parsers/intersection.d.ts +2 -3
  17. package/lib-types/create/schema/parsers/lazy.d.ts +2 -3
  18. package/lib-types/create/schema/parsers/literal.d.ts +2 -2
  19. package/lib-types/create/schema/parsers/manual.d.ts +2 -3
  20. package/lib-types/create/schema/parsers/nativeEnum.d.ts +2 -3
  21. package/lib-types/create/schema/parsers/null.d.ts +2 -2
  22. package/lib-types/create/schema/parsers/nullable.d.ts +2 -3
  23. package/lib-types/create/schema/parsers/number.d.ts +2 -2
  24. package/lib-types/create/schema/parsers/object.d.ts +14 -6
  25. package/lib-types/create/schema/parsers/optional.d.ts +9 -4
  26. package/lib-types/create/schema/parsers/pipeline.d.ts +2 -3
  27. package/lib-types/create/schema/parsers/preprocess.d.ts +2 -3
  28. package/lib-types/create/schema/parsers/readonly.d.ts +2 -3
  29. package/lib-types/create/schema/parsers/record.d.ts +2 -3
  30. package/lib-types/create/schema/parsers/refine.d.ts +2 -3
  31. package/lib-types/create/schema/parsers/set.d.ts +2 -3
  32. package/lib-types/create/schema/parsers/string.d.ts +2 -2
  33. package/lib-types/create/schema/parsers/transform.d.ts +9 -4
  34. package/lib-types/create/schema/parsers/tuple.d.ts +2 -3
  35. package/lib-types/create/schema/parsers/union.d.ts +2 -3
  36. package/lib-types/create/schema/parsers/unknown.d.ts +2 -2
  37. package/lib-types/extendZod.d.ts +1 -1
  38. package/lib-types/openapi3-ts/dist/model/openapi31.d.ts +4 -0
  39. package/package.json +14 -8
@@ -34,30 +34,27 @@ var isAnyZodType = (zodType) => Boolean(
34
34
  zodType?._def?.typeName
35
35
  );
36
36
 
37
- // src/openapi.ts
38
- var openApiVersions = [
39
- "3.0.0",
40
- "3.0.1",
41
- "3.0.2",
42
- "3.0.3",
43
- "3.1.0"
44
- ];
45
- var satisfiesVersion = (test, against) => openApiVersions.indexOf(test) >= openApiVersions.indexOf(against);
46
- var isReferenceObject = (schemaOrRef) => Boolean("$ref" in schemaOrRef && schemaOrRef.$ref);
47
-
48
37
  // src/create/schema/metadata.ts
49
- var enhanceWithMetadata = (schemaObject, metadata) => {
50
- if (isReferenceObject(schemaObject)) {
38
+ var enhanceWithMetadata = (schema, metadata) => {
39
+ if (schema.type === "ref") {
51
40
  if (Object.values(metadata).every((val) => val === void 0)) {
52
- return schemaObject;
41
+ return schema;
53
42
  }
54
43
  return {
55
- allOf: [schemaObject, metadata]
44
+ type: "schema",
45
+ schema: {
46
+ allOf: [schema.schema, metadata]
47
+ },
48
+ effects: schema.effects
56
49
  };
57
50
  }
58
51
  return {
59
- ...schemaObject,
60
- ...metadata
52
+ type: "schema",
53
+ schema: {
54
+ ...schema.schema,
55
+ ...metadata
56
+ },
57
+ effects: schema.effects
61
58
  };
62
59
  };
63
60
 
@@ -66,17 +63,25 @@ var createArraySchema = (zodArray, state) => {
66
63
  const zodType = zodArray._def.type;
67
64
  const minItems = zodArray._def.exactLength?.value ?? zodArray._def.minLength?.value;
68
65
  const maxItems = zodArray._def.exactLength?.value ?? zodArray._def.maxLength?.value;
66
+ const items = createSchemaObject(zodType, state, ["array items"]);
69
67
  return {
70
- type: "array",
71
- items: createSchemaObject(zodType, state, ["array items"]),
72
- ...minItems !== void 0 && { minItems },
73
- ...maxItems !== void 0 && { maxItems }
68
+ type: "schema",
69
+ schema: {
70
+ type: "array",
71
+ items: items.schema,
72
+ ...minItems !== void 0 && { minItems },
73
+ ...maxItems !== void 0 && { maxItems }
74
+ },
75
+ effects: items.effects
74
76
  };
75
77
  };
76
78
 
77
79
  // src/create/schema/parsers/boolean.ts
78
80
  var createBooleanSchema = (_zodBoolean) => ({
79
- type: "boolean"
81
+ type: "schema",
82
+ schema: {
83
+ type: "boolean"
84
+ }
80
85
  });
81
86
 
82
87
  // src/create/schema/parsers/brand.ts
@@ -87,7 +92,10 @@ var createCatchSchema = (zodCatch, state) => createSchemaObject(zodCatch._def.in
87
92
 
88
93
  // src/create/schema/parsers/date.ts
89
94
  var createDateSchema = (_zodDate) => ({
90
- type: "string"
95
+ type: "schema",
96
+ schema: {
97
+ type: "string"
98
+ }
91
99
  });
92
100
 
93
101
  // src/create/schema/parsers/default.ts
@@ -100,21 +108,186 @@ var createDefaultSchema = (zodDefault, state) => {
100
108
  });
101
109
  };
102
110
 
111
+ // src/create/schema/parsers/transform.ts
112
+ var createTransformSchema = (zodTransform, state) => {
113
+ if (zodTransform._def.openapi?.effectType === "output") {
114
+ return {
115
+ type: "schema",
116
+ schema: createManualOutputTransformSchema(zodTransform, state)
117
+ };
118
+ }
119
+ if (zodTransform._def.openapi?.effectType === "input" || zodTransform._def.openapi?.effectType === "same") {
120
+ return createSchemaObject(zodTransform._def.schema, state, [
121
+ "transform input"
122
+ ]);
123
+ }
124
+ if (state.type === "output") {
125
+ return {
126
+ type: "schema",
127
+ schema: createManualOutputTransformSchema(zodTransform, state)
128
+ };
129
+ }
130
+ const schema = createSchemaObject(zodTransform._def.schema, state, [
131
+ "transform input"
132
+ ]);
133
+ return {
134
+ ...schema,
135
+ effects: flattenEffects([
136
+ [
137
+ {
138
+ type: "schema",
139
+ creationType: "input",
140
+ zodType: zodTransform,
141
+ path: [...state.path]
142
+ }
143
+ ],
144
+ schema.effects
145
+ ])
146
+ };
147
+ };
148
+ var createManualOutputTransformSchema = (zodTransform, state) => {
149
+ if (!zodTransform._def.openapi?.type) {
150
+ const zodType = zodTransform.constructor.name;
151
+ const schemaName = `${zodType} - ${zodTransform._def.effect.type}`;
152
+ throw new Error(
153
+ `Failed to determine a type for ${schemaName} at ${state.path.join(
154
+ " > "
155
+ )}. Please change the 'effectType' to 'input', wrap it in a ZodPipeline or assign it a manual 'type'.`
156
+ );
157
+ }
158
+ return {
159
+ type: zodTransform._def.openapi.type
160
+ };
161
+ };
162
+ var getZodTypeName = (zodType) => {
163
+ if (isZodType(zodType, "ZodEffects")) {
164
+ return `${zodType._def.typeName} - ${zodType._def.effect.type}`;
165
+ }
166
+ return zodType._def.typeName;
167
+ };
168
+ var throwTransformError = (effect) => {
169
+ const typeName = getZodTypeName(effect.zodType);
170
+ const input = effect.creationType;
171
+ const opposite = input === "input" ? "output" : "input";
172
+ throw new Error(
173
+ `The ${typeName} at ${effect.path.join(
174
+ " > "
175
+ )} is used within a registered compoment schema${effect.component ? ` (${effect.component.ref})` : ""} and contains an ${input} transformation${effect.component ? ` (${getZodTypeName(
176
+ effect.component.zodType
177
+ )}) defined at ${effect.component.path.join(" > ")}` : ""} which is also used in an ${opposite} schema.
178
+
179
+ This may cause the schema to render incorrectly and is most likely a mistake. You can resolve this by:
180
+
181
+ 1. Setting an \`effectType\` on the transformation to \`same\` or \`${opposite}\` eg. \`.openapi({type: 'same'})\`
182
+ 2. Wrapping the transformation in a ZodPipeline
183
+ 3. Assigning a manual type to the transformation eg. \`.openapi({type: 'string'})\`
184
+ 4. Removing the transformation
185
+ 5. Deregistering the component containing the transformation`
186
+ );
187
+ };
188
+ var resolveSingleEffect = (effect, state) => {
189
+ if (effect.type === "schema") {
190
+ return {
191
+ creationType: effect.creationType,
192
+ path: effect.path,
193
+ zodType: effect.zodType
194
+ };
195
+ }
196
+ if (effect.type === "component") {
197
+ if (state.visited.has(effect.zodType)) {
198
+ return;
199
+ }
200
+ const component = state.components.schemas.get(effect.zodType);
201
+ if (component?.type !== "complete") {
202
+ throw new Error("Something went wrong, component schema is not complete");
203
+ }
204
+ if (component.resolvedEffect) {
205
+ return {
206
+ creationType: component.resolvedEffect.creationType,
207
+ path: effect.path,
208
+ zodType: effect.zodType,
209
+ component: {
210
+ ref: component.ref,
211
+ zodType: component.resolvedEffect.zodType,
212
+ path: component.resolvedEffect.path
213
+ }
214
+ };
215
+ }
216
+ if (!component.effects) {
217
+ return void 0;
218
+ }
219
+ state.visited.add(effect.zodType);
220
+ const resolved = resolveEffect(component.effects, state);
221
+ state.visited.delete(effect.zodType);
222
+ if (!resolved) {
223
+ return void 0;
224
+ }
225
+ component.resolvedEffect = resolved;
226
+ return resolved;
227
+ }
228
+ return void 0;
229
+ };
230
+ var resolveEffect = (effects, state) => {
231
+ const { input, output } = effects.reduce(
232
+ (acc, effect) => {
233
+ const resolvedSchemaEffect = resolveSingleEffect(effect, state);
234
+ if (resolvedSchemaEffect?.creationType === "input") {
235
+ acc.input.push(resolvedSchemaEffect);
236
+ }
237
+ if (resolvedSchemaEffect?.creationType === "output") {
238
+ acc.output.push(resolvedSchemaEffect);
239
+ }
240
+ if (resolvedSchemaEffect && acc.input.length > 1 && acc.output.length > 1) {
241
+ throwTransformError(resolvedSchemaEffect);
242
+ }
243
+ return acc;
244
+ },
245
+ { input: [], output: [] }
246
+ );
247
+ if (input.length > 0) {
248
+ return input[0];
249
+ }
250
+ if (output.length > 0) {
251
+ return output[0];
252
+ }
253
+ return void 0;
254
+ };
255
+ var verifyEffects = (effects, state) => {
256
+ const resolved = resolveEffect(effects, state);
257
+ if (resolved?.creationType && resolved.creationType !== state.type) {
258
+ throwTransformError(resolved);
259
+ }
260
+ };
261
+ var flattenEffects = (effects) => {
262
+ const allEffects = effects.reduce((acc, effect) => {
263
+ if (effect) {
264
+ return acc.concat(effect);
265
+ }
266
+ return acc;
267
+ }, []);
268
+ return allEffects.length ? allEffects : void 0;
269
+ };
270
+
103
271
  // src/create/schema/parsers/discriminatedUnion.ts
104
272
  var createDiscriminatedUnionSchema = (zodDiscriminatedUnion, state) => {
105
273
  const options = zodDiscriminatedUnion.options;
106
274
  const schemas = options.map(
107
275
  (option, index) => createSchemaObject(option, state, [`discriminated union option ${index}`])
108
276
  );
277
+ const schemaObjects = schemas.map((schema) => schema.schema);
109
278
  const discriminator = mapDiscriminator(
110
- schemas,
279
+ schemaObjects,
111
280
  options,
112
281
  zodDiscriminatedUnion.discriminator,
113
282
  state
114
283
  );
115
284
  return {
116
- oneOf: schemas,
117
- ...discriminator && { discriminator }
285
+ type: "schema",
286
+ schema: {
287
+ oneOf: schemaObjects,
288
+ ...discriminator && { discriminator }
289
+ },
290
+ effects: flattenEffects(schemas.map((schema) => schema.effects))
118
291
  };
119
292
  };
120
293
  var mapDiscriminator = (schemas, zodObjects, discriminator, state) => {
@@ -153,19 +326,29 @@ var mapDiscriminator = (schemas, zodObjects, discriminator, state) => {
153
326
 
154
327
  // src/create/schema/parsers/enum.ts
155
328
  var createEnumSchema = (zodEnum) => ({
156
- type: "string",
157
- enum: zodEnum._def.values
329
+ type: "schema",
330
+ schema: {
331
+ type: "string",
332
+ enum: zodEnum._def.values
333
+ }
158
334
  });
159
335
 
160
336
  // src/create/schema/parsers/intersection.ts
161
- var createIntersectionSchema = (zodIntersection, state) => ({
162
- allOf: [
163
- createSchemaObject(zodIntersection._def.left, state, ["intersection left"]),
164
- createSchemaObject(zodIntersection._def.right, state, [
165
- "intersection right"
166
- ])
167
- ]
168
- });
337
+ var createIntersectionSchema = (zodIntersection, state) => {
338
+ const left = createSchemaObject(zodIntersection._def.left, state, [
339
+ "intersection left"
340
+ ]);
341
+ const right = createSchemaObject(zodIntersection._def.right, state, [
342
+ "intersection right"
343
+ ]);
344
+ return {
345
+ type: "schema",
346
+ schema: {
347
+ allOf: [left.schema, right.schema]
348
+ },
349
+ effects: flattenEffects([left.effects, right.effects])
350
+ };
351
+ };
169
352
 
170
353
  // src/create/schema/parsers/lazy.ts
171
354
  var createLazySchema = (zodLazy, state) => {
@@ -175,31 +358,41 @@ var createLazySchema = (zodLazy, state) => {
175
358
 
176
359
  // src/create/schema/parsers/literal.ts
177
360
  var createLiteralSchema = (zodLiteral) => ({
178
- type: typeof zodLiteral.value,
179
- enum: [zodLiteral._def.value]
361
+ type: "schema",
362
+ schema: {
363
+ type: typeof zodLiteral.value,
364
+ enum: [zodLiteral._def.value]
365
+ }
180
366
  });
181
367
 
182
368
  // src/create/schema/parsers/manual.ts
183
369
  var createManualTypeSchema = (zodSchema, state) => {
184
370
  if (!zodSchema._def.openapi?.type) {
185
- const zodType = zodSchema.constructor.name;
186
- if (isZodType(zodSchema, "ZodEffects")) {
187
- const schemaName = `${zodType} - ${zodSchema._def.effect.type}`;
188
- throw new Error(
189
- `Unknown schema ${schemaName} at ${state.path.join(
190
- " > "
191
- )}. Please assign it a manual 'type', wrap it in a ZodPipeline or change the 'effectType'.`
192
- );
193
- }
371
+ const schemaName = zodSchema.constructor.name;
194
372
  throw new Error(
195
- `Unknown schema ${zodType}. Please assign it a manual 'type'.`
373
+ `Unknown schema ${schemaName} at ${state.path.join(
374
+ " > "
375
+ )}. Please assign it a manual 'type'.`
196
376
  );
197
377
  }
198
378
  return {
199
- type: zodSchema._def.openapi.type
379
+ type: "schema",
380
+ schema: {
381
+ type: zodSchema._def.openapi.type
382
+ }
200
383
  };
201
384
  };
202
385
 
386
+ // src/openapi.ts
387
+ var openApiVersions = [
388
+ "3.0.0",
389
+ "3.0.1",
390
+ "3.0.2",
391
+ "3.0.3",
392
+ "3.1.0"
393
+ ];
394
+ var satisfiesVersion = (test, against) => openApiVersions.indexOf(test) >= openApiVersions.indexOf(against);
395
+
203
396
  // src/create/schema/parsers/nativeEnum.ts
204
397
  var createNativeEnumSchema = (zodEnum, state) => {
205
398
  const enumValues = getValidEnumValues(zodEnum._def.values);
@@ -207,25 +400,37 @@ var createNativeEnumSchema = (zodEnum, state) => {
207
400
  if (strings.length && numbers.length) {
208
401
  if (satisfiesVersion(state.components.openapi, "3.1.0"))
209
402
  return {
210
- type: ["string", "number"],
211
- enum: [...strings, ...numbers]
403
+ type: "schema",
404
+ schema: {
405
+ type: ["string", "number"],
406
+ enum: [...strings, ...numbers]
407
+ }
212
408
  };
213
409
  return {
214
- oneOf: [
215
- { type: "string", enum: strings },
216
- { type: "number", enum: numbers }
217
- ]
410
+ type: "schema",
411
+ schema: {
412
+ oneOf: [
413
+ { type: "string", enum: strings },
414
+ { type: "number", enum: numbers }
415
+ ]
416
+ }
218
417
  };
219
418
  }
220
419
  if (strings.length) {
221
420
  return {
222
- type: "string",
223
- enum: strings
421
+ type: "schema",
422
+ schema: {
423
+ type: "string",
424
+ enum: strings
425
+ }
224
426
  };
225
427
  }
226
428
  return {
227
- type: "number",
228
- enum: numbers
429
+ type: "schema",
430
+ schema: {
431
+ type: "number",
432
+ enum: numbers
433
+ }
229
434
  };
230
435
  };
231
436
  var getValidEnumValues = (enumValues) => {
@@ -241,7 +446,10 @@ var sortStringsAndNumbers = (values) => ({
241
446
 
242
447
  // src/create/schema/parsers/null.ts
243
448
  var createNullSchema = (_zodNull) => ({
244
- type: "null"
449
+ type: "schema",
450
+ schema: {
451
+ type: "null"
452
+ }
245
453
  });
246
454
 
247
455
  // src/create/schema/parsers/nullable.ts
@@ -250,45 +458,69 @@ var createNullableSchema = (zodNullable, state) => {
250
458
  "nullable"
251
459
  ]);
252
460
  if (satisfiesVersion(state.components.openapi, "3.1.0")) {
253
- if (isReferenceObject(schemaObject) || schemaObject.allOf) {
461
+ if (schemaObject.type === "ref" || schemaObject.schema.allOf) {
254
462
  return {
255
- oneOf: mapNullOf([schemaObject], state.components.openapi)
463
+ type: "schema",
464
+ schema: {
465
+ oneOf: mapNullOf([schemaObject.schema], state.components.openapi)
466
+ },
467
+ effects: schemaObject.effects
256
468
  };
257
469
  }
258
- if (schemaObject.oneOf) {
259
- const { oneOf, ...schema3 } = schemaObject;
470
+ if (schemaObject.schema.oneOf) {
471
+ const { oneOf, ...schema3 } = schemaObject.schema;
260
472
  return {
261
- oneOf: mapNullOf(oneOf, state.components.openapi),
262
- ...schema3
473
+ type: "schema",
474
+ schema: {
475
+ oneOf: mapNullOf(oneOf, state.components.openapi),
476
+ ...schema3
477
+ },
478
+ effects: schemaObject.effects
263
479
  };
264
480
  }
265
- if (schemaObject.anyOf) {
266
- const { anyOf, ...schema3 } = schemaObject;
481
+ if (schemaObject.schema.anyOf) {
482
+ const { anyOf, ...schema3 } = schemaObject.schema;
267
483
  return {
268
- anyOf: mapNullOf(anyOf, state.components.openapi),
269
- ...schema3
484
+ type: "schema",
485
+ schema: {
486
+ anyOf: mapNullOf(anyOf, state.components.openapi),
487
+ ...schema3
488
+ },
489
+ effects: schemaObject.effects
270
490
  };
271
491
  }
272
- const { type: type2, ...schema2 } = schemaObject;
492
+ const { type: type2, ...schema2 } = schemaObject.schema;
273
493
  return {
274
- type: mapNullType(type2),
275
- ...schema2
494
+ type: "schema",
495
+ schema: {
496
+ type: mapNullType(type2),
497
+ ...schema2
498
+ },
499
+ effects: schemaObject.effects
276
500
  };
277
501
  }
278
- if (isReferenceObject(schemaObject)) {
502
+ if (schemaObject.type === "ref") {
279
503
  return {
280
- allOf: [schemaObject],
281
- nullable: true
504
+ type: "schema",
505
+ schema: {
506
+ allOf: [schemaObject.schema],
507
+ nullable: true
508
+ },
509
+ effects: schemaObject.effects
282
510
  };
283
511
  }
284
- const { type, ...schema } = schemaObject;
512
+ const { type, ...schema } = schemaObject.schema;
285
513
  return {
286
- ...type && { type },
287
- nullable: true,
288
- ...schema,
289
- // https://github.com/OAI/OpenAPI-Specification/blob/main/proposals/2019-10-31-Clarify-Nullable.md#if-a-schema-specifies-nullable-true-and-enum-1-2-3-does-that-schema-allow-null-values-see-1900
290
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
291
- ...schema.enum && { enum: [...schema.enum, null] }
514
+ type: "schema",
515
+ schema: {
516
+ ...type && { type },
517
+ nullable: true,
518
+ ...schema,
519
+ // https://github.com/OAI/OpenAPI-Specification/blob/main/proposals/2019-10-31-Clarify-Nullable.md#if-a-schema-specifies-nullable-true-and-enum-1-2-3-does-that-schema-allow-null-values-see-1900
520
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
521
+ ...schema.enum && { enum: [...schema.enum, null] }
522
+ },
523
+ effects: schemaObject.effects
292
524
  };
293
525
  };
294
526
  var mapNullType = (type) => {
@@ -313,10 +545,13 @@ var createNumberSchema = (zodNumber, state) => {
313
545
  const minimum = mapMinimum(zodNumberChecks, state.components.openapi);
314
546
  const maximum = mapMaximum(zodNumberChecks, state.components.openapi);
315
547
  return {
316
- type: mapNumberType(zodNumberChecks),
317
- ...minimum && minimum,
318
- // Union types are not easy to tame
319
- ...maximum && maximum
548
+ type: "schema",
549
+ schema: {
550
+ type: mapNumberType(zodNumberChecks),
551
+ ...minimum && minimum,
552
+ // Union types are not easy to tame
553
+ ...maximum && maximum
554
+ }
320
555
  };
321
556
  };
322
557
  var mapMaximum = (zodNumberCheck, openapi) => {
@@ -352,16 +587,29 @@ var getZodNumberChecks = (zodNumber) => zodNumber._def.checks.reduce((acc, check
352
587
  var mapNumberType = (zodNumberChecks) => zodNumberChecks.int ? "integer" : "number";
353
588
 
354
589
  // src/create/schema/parsers/optional.ts
355
- var createOptionalSchema = (zodOptional, state) => (
356
- // Optional doesn't change OpenAPI schema
357
- createSchemaObject(zodOptional.unwrap(), state, ["optional"])
358
- );
590
+ var createOptionalSchema = (zodOptional, state) => createSchemaObject(zodOptional.unwrap(), state, ["optional"]);
359
591
  var isOptionalSchema = (zodSchema, state) => {
360
- if (isZodType(zodSchema, "ZodOptional")) {
361
- return true;
592
+ if (isZodType(zodSchema, "ZodOptional") || isZodType(zodSchema, "ZodNever") || isZodType(zodSchema, "ZodUndefined")) {
593
+ return { optional: true };
362
594
  }
363
595
  if (isZodType(zodSchema, "ZodDefault")) {
364
- return state.type === "input";
596
+ if (zodSchema._def.openapi?.effectType === "input") {
597
+ return { optional: true };
598
+ }
599
+ if (zodSchema._def.openapi?.effectType === "output") {
600
+ return { optional: false };
601
+ }
602
+ return {
603
+ optional: state.type === "input",
604
+ effects: [
605
+ {
606
+ type: "schema",
607
+ creationType: state.type,
608
+ zodType: zodSchema,
609
+ path: [...state.path]
610
+ }
611
+ ]
612
+ };
365
613
  }
366
614
  if (isZodType(zodSchema, "ZodNullable") || isZodType(zodSchema, "ZodCatch")) {
367
615
  return isOptionalSchema(zodSchema._def.innerType, state);
@@ -370,27 +618,42 @@ var isOptionalSchema = (zodSchema, state) => {
370
618
  return isOptionalSchema(zodSchema._def.schema, state);
371
619
  }
372
620
  if (isZodType(zodSchema, "ZodUnion") || isZodType(zodSchema, "ZodDiscriminatedUnion")) {
373
- return zodSchema._def.options.some(
621
+ const results = zodSchema._def.options.map(
374
622
  (schema) => isOptionalSchema(schema, state)
375
623
  );
624
+ return results.reduce(
625
+ (acc, result) => ({
626
+ optional: acc.optional || result.optional,
627
+ effects: flattenEffects([acc.effects, result.effects])
628
+ }),
629
+ { optional: false }
630
+ );
376
631
  }
377
632
  if (isZodType(zodSchema, "ZodIntersection")) {
378
- return [zodSchema._def.left, zodSchema._def.right].some(
633
+ const results = [zodSchema._def.left, zodSchema._def.right].map(
379
634
  (schema) => isOptionalSchema(schema, state)
380
635
  );
636
+ return results.reduce(
637
+ (acc, result) => ({
638
+ optional: acc.optional || result.optional,
639
+ effects: flattenEffects([acc.effects, result.effects])
640
+ }),
641
+ { optional: false }
642
+ );
381
643
  }
382
644
  if (isZodType(zodSchema, "ZodPipeline")) {
383
- if (state.effectType === "input" || state.type === "input" && state.effectType !== "output") {
645
+ const type = zodSchema._def.openapi?.effectType ?? state.type;
646
+ if (type === "input") {
384
647
  return isOptionalSchema(zodSchema._def.in, state);
385
648
  }
386
- if (state.effectType === "output" || state.type === "output" && state.effectType !== "input") {
649
+ if (type === "output") {
387
650
  return isOptionalSchema(zodSchema._def.out, state);
388
651
  }
389
652
  }
390
653
  if (isZodType(zodSchema, "ZodLazy")) {
391
654
  return isOptionalSchema(zodSchema._def.getter(), state);
392
655
  }
393
- return zodSchema.isOptional();
656
+ return { optional: zodSchema.isOptional() };
394
657
  };
395
658
 
396
659
  // src/create/schema/parsers/object.ts
@@ -444,9 +707,28 @@ var createExtendedSchema = (zodObject, baseZodObject, state) => {
444
707
  if (!diffShape) {
445
708
  return void 0;
446
709
  }
710
+ const extendedSchema = createObjectSchemaFromShape(
711
+ diffShape,
712
+ diffOpts,
713
+ state
714
+ );
447
715
  return {
448
- allOf: [{ $ref: createComponentSchemaRef(completeComponent.ref) }],
449
- ...createObjectSchemaFromShape(diffShape, diffOpts, state)
716
+ type: "schema",
717
+ schema: {
718
+ allOf: [{ $ref: createComponentSchemaRef(completeComponent.ref) }],
719
+ ...extendedSchema.schema
720
+ },
721
+ effects: flattenEffects([
722
+ completeComponent.type === "complete" ? completeComponent.effects : [],
723
+ completeComponent.type === "in-progress" ? [
724
+ {
725
+ type: "component",
726
+ zodType: zodObject,
727
+ path: [...state.path]
728
+ }
729
+ ] : [],
730
+ extendedSchema.effects
731
+ ])
450
732
  };
451
733
  };
452
734
  var createDiffOpts = (baseOpts, extendedOpts) => {
@@ -476,47 +758,114 @@ var createShapeDiff = (baseObj, extendedObj) => {
476
758
  var createObjectSchemaFromShape = (shape, { unknownKeys, catchAll }, state) => {
477
759
  const properties = mapProperties(shape, state);
478
760
  const required = mapRequired(shape, state);
761
+ const additionalProperties = !isZodType(catchAll, "ZodNever") ? createSchemaObject(catchAll, state, ["additional properties"]) : void 0;
479
762
  return {
480
- type: "object",
481
- ...properties && { properties },
482
- ...required && { required },
483
- ...unknownKeys === "strict" && { additionalProperties: false },
484
- ...!isZodType(catchAll, "ZodNever") && {
485
- additionalProperties: createSchemaObject(catchAll, state, [
486
- "additional properties"
487
- ])
488
- }
763
+ type: "schema",
764
+ schema: {
765
+ type: "object",
766
+ ...properties && { properties: properties.properties },
767
+ ...required?.required.length && { required: required.required },
768
+ ...unknownKeys === "strict" && { additionalProperties: false },
769
+ ...additionalProperties && {
770
+ additionalProperties: additionalProperties.schema
771
+ }
772
+ },
773
+ effects: flattenEffects([
774
+ ...properties?.effects ?? [],
775
+ additionalProperties?.effects,
776
+ required?.effects
777
+ ])
489
778
  };
490
779
  };
491
780
  var mapRequired = (shape, state) => {
492
- const required = Object.entries(shape).filter(([_key, zodSchema]) => !isOptionalSchema(zodSchema, state)).map(([key]) => key);
493
- if (!required.length) {
781
+ const { required, effects: allEffects } = Object.entries(shape).reduce(
782
+ (acc, [key, zodSchema]) => {
783
+ state.path.push(`property: ${key}`);
784
+ const { optional, effects } = isOptionalSchema(zodSchema, state);
785
+ state.path.pop();
786
+ if (!optional) {
787
+ acc.required.push(key);
788
+ }
789
+ if (effects) {
790
+ acc.effects.push(effects);
791
+ }
792
+ return acc;
793
+ },
794
+ {
795
+ required: [],
796
+ effects: []
797
+ }
798
+ );
799
+ return { required, effects: flattenEffects(allEffects) };
800
+ };
801
+ var mapProperties = (shape, state) => {
802
+ const shapeEntries = Object.entries(shape);
803
+ if (!shapeEntries.length) {
494
804
  return void 0;
495
805
  }
496
- return required;
806
+ return shapeEntries.reduce(
807
+ (acc, [key, zodSchema]) => {
808
+ if (isZodType(zodSchema, "ZodNever") || isZodType(zodSchema, "ZodUndefined")) {
809
+ return acc;
810
+ }
811
+ const property = createSchemaObject(zodSchema, state, [
812
+ `property: ${key}`
813
+ ]);
814
+ acc.properties[key] = property.schema;
815
+ acc.effects.push(property.effects);
816
+ return acc;
817
+ },
818
+ {
819
+ properties: {},
820
+ effects: []
821
+ }
822
+ );
497
823
  };
498
- var mapProperties = (shape, state) => Object.entries(shape).reduce(
499
- (acc, [key, zodSchema]) => {
500
- acc[key] = createSchemaObject(zodSchema, state, [`property: ${key}`]);
501
- return acc;
502
- },
503
- {}
504
- );
505
824
 
506
825
  // src/create/schema/parsers/pipeline.ts
507
826
  var createPipelineSchema = (zodPipeline, state) => {
508
- if (zodPipeline._def.openapi?.effectType === "input") {
827
+ if (zodPipeline._def.openapi?.effectType === "input" || zodPipeline._def.openapi?.effectType === "same") {
509
828
  return createSchemaObject(zodPipeline._def.in, state, ["pipeline input"]);
510
829
  }
511
830
  if (zodPipeline._def.openapi?.effectType === "output") {
512
831
  return createSchemaObject(zodPipeline._def.out, state, ["pipeline output"]);
513
832
  }
514
833
  if (state.type === "input") {
515
- state.effectType = "input";
516
- return createSchemaObject(zodPipeline._def.in, state, ["pipeline input"]);
834
+ const schema2 = createSchemaObject(zodPipeline._def.in, state, [
835
+ "pipeline input"
836
+ ]);
837
+ return {
838
+ ...schema2,
839
+ effects: flattenEffects([
840
+ [
841
+ {
842
+ type: "schema",
843
+ creationType: "input",
844
+ path: [...state.path],
845
+ zodType: zodPipeline
846
+ }
847
+ ],
848
+ schema2.effects
849
+ ])
850
+ };
517
851
  }
518
- state.effectType = "output";
519
- return createSchemaObject(zodPipeline._def.out, state, ["pipeline output"]);
852
+ const schema = createSchemaObject(zodPipeline._def.out, state, [
853
+ "pipeline output"
854
+ ]);
855
+ return {
856
+ ...schema,
857
+ effects: flattenEffects([
858
+ [
859
+ {
860
+ type: "schema",
861
+ creationType: "output",
862
+ path: [...state.path],
863
+ zodType: zodPipeline
864
+ }
865
+ ],
866
+ schema.effects
867
+ ])
868
+ };
520
869
  };
521
870
 
522
871
  // src/create/schema/parsers/preprocess.ts
@@ -538,30 +887,50 @@ var createRecordSchema = (zodRecord, state) => {
538
887
  const keySchema = createSchemaObject(zodRecord.keySchema, state, [
539
888
  "record key"
540
889
  ]);
541
- const maybeComponent = "$ref" in keySchema && state.components.schemas.get(zodRecord.keySchema);
542
- const maybeSchema = maybeComponent && maybeComponent.type === "complete" && maybeComponent.schemaObject;
543
- const renderedKeySchema = maybeSchema || keySchema;
890
+ const maybeComponent = state.components.schemas.get(zodRecord.keySchema);
891
+ const isComplete = maybeComponent && maybeComponent.type === "complete";
892
+ const maybeSchema = isComplete && maybeComponent.schemaObject;
893
+ const maybeEffects = isComplete && maybeComponent.effects || void 0;
894
+ const renderedKeySchema = maybeSchema || keySchema.schema;
544
895
  if ("enum" in renderedKeySchema && renderedKeySchema.enum) {
545
896
  return {
546
- type: "object",
547
- properties: renderedKeySchema.enum.reduce((acc, key) => {
548
- acc[key] = additionalProperties;
549
- return acc;
550
- }, {}),
551
- additionalProperties: false
897
+ type: "schema",
898
+ schema: {
899
+ type: "object",
900
+ properties: renderedKeySchema.enum.reduce((acc, key) => {
901
+ acc[key] = additionalProperties.schema;
902
+ return acc;
903
+ }, {}),
904
+ additionalProperties: false
905
+ },
906
+ effects: flattenEffects([
907
+ keySchema.effects,
908
+ additionalProperties.effects,
909
+ maybeEffects
910
+ ])
552
911
  };
553
912
  }
554
913
  if (satisfiesVersion(state.components.openapi, "3.1.0") && "type" in renderedKeySchema && renderedKeySchema.type === "string" && Object.keys(renderedKeySchema).length > 1) {
555
914
  return {
556
- type: "object",
557
- // @ts-expect-error FIXME: https://github.com/metadevpro/openapi3-ts/pull/120
558
- propertyNames: keySchema,
559
- additionalProperties
915
+ type: "schema",
916
+ schema: {
917
+ type: "object",
918
+ propertyNames: keySchema.schema,
919
+ additionalProperties: additionalProperties.schema
920
+ },
921
+ effects: flattenEffects([
922
+ keySchema.effects,
923
+ additionalProperties.effects
924
+ ])
560
925
  };
561
926
  }
562
927
  return {
563
- type: "object",
564
- additionalProperties
928
+ type: "schema",
929
+ schema: {
930
+ type: "object",
931
+ additionalProperties: additionalProperties.schema
932
+ },
933
+ effects: additionalProperties.effects
565
934
  };
566
935
  };
567
936
 
@@ -573,12 +942,17 @@ var createSetSchema = (zodSet, state) => {
573
942
  const schema = zodSet._def.valueType;
574
943
  const minItems = zodSet._def.minSize?.value;
575
944
  const maxItems = zodSet._def.maxSize?.value;
945
+ const itemSchema = createSchemaObject(schema, state, ["set items"]);
576
946
  return {
577
- type: "array",
578
- items: createSchemaObject(schema, state, ["set items"]),
579
- uniqueItems: true,
580
- ...minItems !== void 0 && { minItems },
581
- ...maxItems !== void 0 && { maxItems }
947
+ type: "schema",
948
+ schema: {
949
+ type: "array",
950
+ items: itemSchema.schema,
951
+ uniqueItems: true,
952
+ ...minItems !== void 0 && { minItems },
953
+ ...maxItems !== void 0 && { maxItems }
954
+ },
955
+ effects: itemSchema.effects
582
956
  };
583
957
  };
584
958
 
@@ -591,29 +965,35 @@ var createStringSchema = (zodString) => {
591
965
  const maxLength = zodStringChecks.length?.[0]?.value ?? zodStringChecks.max?.[0]?.value;
592
966
  if (patterns.length <= 1) {
593
967
  return {
594
- type: "string",
595
- ...format && { format },
596
- ...patterns[0] && { pattern: patterns[0] },
597
- ...minLength !== void 0 && { minLength },
598
- ...maxLength !== void 0 && { maxLength }
599
- };
600
- }
601
- return {
602
- allOf: [
603
- {
968
+ type: "schema",
969
+ schema: {
604
970
  type: "string",
605
971
  ...format && { format },
606
972
  ...patterns[0] && { pattern: patterns[0] },
607
973
  ...minLength !== void 0 && { minLength },
608
974
  ...maxLength !== void 0 && { maxLength }
609
- },
610
- ...patterns.slice(1).map(
611
- (pattern) => ({
975
+ }
976
+ };
977
+ }
978
+ return {
979
+ type: "schema",
980
+ schema: {
981
+ allOf: [
982
+ {
612
983
  type: "string",
613
- pattern
614
- })
615
- )
616
- ]
984
+ ...format && { format },
985
+ ...patterns[0] && { pattern: patterns[0] },
986
+ ...minLength !== void 0 && { minLength },
987
+ ...maxLength !== void 0 && { maxLength }
988
+ },
989
+ ...patterns.slice(1).map(
990
+ (pattern) => ({
991
+ type: "string",
992
+ pattern
993
+ })
994
+ )
995
+ ]
996
+ }
617
997
  };
618
998
  };
619
999
  var getZodStringChecks = (zodString) => zodString._def.checks.reduce(
@@ -679,82 +1059,88 @@ var mapStringFormat = (zodStringChecks) => {
679
1059
  return void 0;
680
1060
  };
681
1061
 
682
- // src/create/schema/parsers/transform.ts
683
- var createTransformSchema = (zodTransform, state) => {
684
- if (zodTransform._def.openapi?.effectType === "output") {
685
- return createManualTypeSchema(zodTransform, state);
686
- }
687
- if (zodTransform._def.openapi?.effectType === "input") {
688
- return createSchemaObject(zodTransform._def.schema, state, [
689
- "transform input"
690
- ]);
691
- }
692
- if (state.type === "output") {
693
- return createManualTypeSchema(zodTransform, state);
694
- }
695
- state.effectType = "input";
696
- return createSchemaObject(zodTransform._def.schema, state, [
697
- "transform input"
698
- ]);
699
- };
700
- var throwTransformError = (zodType, state) => {
701
- throw new Error(
702
- `${JSON.stringify(zodType)} at ${state.path.join(
703
- " > "
704
- )} contains a transformation but is used in both an input and an output. This is likely a mistake. Set an \`effectType\`, wrap it in a ZodPipeline or assign it a manual type to resolve`
705
- );
706
- };
707
-
708
1062
  // src/create/schema/parsers/tuple.ts
709
1063
  var createTupleSchema = (zodTuple, state) => {
710
1064
  const items = zodTuple.items;
711
1065
  const rest = zodTuple._def.rest;
712
- return {
713
- type: "array",
714
- ...mapItemProperties(items, rest, state)
715
- };
716
- };
717
- var mapPrefixItems = (items, state) => {
718
- if (items.length) {
719
- return items.map(
720
- (item, index) => createSchemaObject(item, state, [`tuple item ${index}`])
721
- );
722
- }
723
- return void 0;
724
- };
725
- var mapItemProperties = (items, rest, state) => {
726
1066
  const prefixItems = mapPrefixItems(items, state);
727
1067
  if (satisfiesVersion(state.components.openapi, "3.1.0")) {
728
1068
  if (!rest) {
729
1069
  return {
730
- maxItems: items.length,
731
- minItems: items.length,
732
- ...prefixItems && { prefixItems }
1070
+ type: "schema",
1071
+ schema: {
1072
+ type: "array",
1073
+ maxItems: items.length,
1074
+ minItems: items.length,
1075
+ ...prefixItems && {
1076
+ prefixItems: prefixItems.schemas.map((item) => item.schema)
1077
+ }
1078
+ },
1079
+ effects: prefixItems?.effects
733
1080
  };
734
1081
  }
1082
+ const itemSchema = createSchemaObject(rest, state, ["tuple items"]);
735
1083
  return {
736
- items: createSchemaObject(rest, state, ["tuple items"]),
737
- ...prefixItems && { prefixItems }
1084
+ type: "schema",
1085
+ schema: {
1086
+ type: "array",
1087
+ items: itemSchema.schema,
1088
+ ...prefixItems && {
1089
+ prefixItems: prefixItems.schemas.map((item) => item.schema)
1090
+ }
1091
+ },
1092
+ effects: flattenEffects([prefixItems?.effects, itemSchema.effects])
738
1093
  };
739
1094
  }
740
1095
  if (!rest) {
741
1096
  return {
742
- maxItems: items.length,
743
- minItems: items.length,
744
- ...prefixItems && { items: { oneOf: prefixItems } }
1097
+ type: "schema",
1098
+ schema: {
1099
+ type: "array",
1100
+ maxItems: items.length,
1101
+ minItems: items.length,
1102
+ ...prefixItems && {
1103
+ items: { oneOf: prefixItems.schemas.map((item) => item.schema) }
1104
+ }
1105
+ },
1106
+ effects: prefixItems?.effects
1107
+ };
1108
+ }
1109
+ if (prefixItems) {
1110
+ const restSchema = createSchemaObject(rest, state, ["tuple items"]);
1111
+ return {
1112
+ type: "schema",
1113
+ schema: {
1114
+ type: "array",
1115
+ items: {
1116
+ oneOf: [
1117
+ ...prefixItems.schemas.map((item) => item.schema),
1118
+ restSchema.schema
1119
+ ]
1120
+ }
1121
+ },
1122
+ effects: flattenEffects([restSchema.effects, prefixItems.effects])
745
1123
  };
746
1124
  }
747
1125
  return {
748
- ...prefixItems && {
749
- items: {
750
- oneOf: [
751
- ...prefixItems,
752
- createSchemaObject(rest, state, ["tuple items"])
753
- ]
754
- }
1126
+ type: "schema",
1127
+ schema: {
1128
+ type: "array"
755
1129
  }
756
1130
  };
757
1131
  };
1132
+ var mapPrefixItems = (items, state) => {
1133
+ if (items.length) {
1134
+ const schemas = items.map(
1135
+ (item, index) => createSchemaObject(item, state, [`tuple item ${index}`])
1136
+ );
1137
+ return {
1138
+ effects: flattenEffects(schemas.map((s) => s.effects)),
1139
+ schemas
1140
+ };
1141
+ }
1142
+ return void 0;
1143
+ };
758
1144
 
759
1145
  // src/create/schema/parsers/union.ts
760
1146
  var createUnionSchema = (zodUnion, state) => {
@@ -763,16 +1149,27 @@ var createUnionSchema = (zodUnion, state) => {
763
1149
  );
764
1150
  if (zodUnion._def.openapi?.unionOneOf) {
765
1151
  return {
766
- oneOf: schemas
1152
+ type: "schema",
1153
+ schema: {
1154
+ oneOf: schemas.map((s) => s.schema)
1155
+ },
1156
+ effects: flattenEffects(schemas.map((s) => s.effects))
767
1157
  };
768
1158
  }
769
1159
  return {
770
- anyOf: schemas
1160
+ type: "schema",
1161
+ schema: {
1162
+ anyOf: schemas.map((s) => s.schema)
1163
+ },
1164
+ effects: flattenEffects(schemas.map((s) => s.effects))
771
1165
  };
772
1166
  };
773
1167
 
774
1168
  // src/create/schema/parsers/unknown.ts
775
- var createUnknownSchema = (_zodUnknown) => ({});
1169
+ var createUnknownSchema = (_zodUnknown) => ({
1170
+ type: "schema",
1171
+ schema: {}
1172
+ });
776
1173
 
777
1174
  // src/create/schema/parsers/index.ts
778
1175
  var createSchemaSwitch = (zodSchema, state) => {
@@ -870,22 +1267,16 @@ var createSchemaSwitch = (zodSchema, state) => {
870
1267
  };
871
1268
 
872
1269
  // src/create/schema/index.ts
873
- var newSchemaState = (state) => ({
874
- type: state.type,
875
- components: state.components,
876
- path: [...state.path],
877
- visited: new Set(state.visited)
878
- });
879
- var createNewSchema = (zodSchema, newState, subpath) => {
880
- newState.path.push(...subpath);
881
- if (newState.visited.has(zodSchema)) {
1270
+ var isDescriptionEqual = (schema, zodSchema) => schema.type === "ref" && zodSchema.description === schema.zodType.description;
1271
+ var createNewSchema = (zodSchema, state) => {
1272
+ if (state.visited.has(zodSchema)) {
882
1273
  throw new Error(
883
- `The schema at ${newState.path.join(
1274
+ `The schema at ${state.path.join(
884
1275
  " > "
885
1276
  )} needs to be registered because it's circularly referenced`
886
1277
  );
887
1278
  }
888
- newState.visited.add(zodSchema);
1279
+ state.visited.add(zodSchema);
889
1280
  const {
890
1281
  effectType,
891
1282
  param,
@@ -895,100 +1286,115 @@ var createNewSchema = (zodSchema, newState, subpath) => {
895
1286
  unionOneOf,
896
1287
  ...additionalMetadata
897
1288
  } = zodSchema._def.openapi ?? {};
898
- const schema = createSchemaSwitch(zodSchema, newState);
899
- const description = zodSchema.description;
1289
+ const schema = createSchemaSwitch(zodSchema, state);
1290
+ const description = zodSchema.description && !isDescriptionEqual(schema, zodSchema) ? zodSchema.description : void 0;
900
1291
  const schemaWithMetadata = enhanceWithMetadata(schema, {
901
1292
  ...description && { description },
902
1293
  ...additionalMetadata
903
1294
  });
904
- return {
905
- schema: schemaWithMetadata,
906
- newState
907
- };
1295
+ state.visited.delete(zodSchema);
1296
+ return schemaWithMetadata;
908
1297
  };
909
- var createNewRef = (ref, zodSchema, state, subpath) => {
1298
+ var createNewRef = (ref, zodSchema, state) => {
910
1299
  state.components.schemas.set(zodSchema, {
911
1300
  type: "in-progress",
912
1301
  ref
913
1302
  });
914
- const newSchema = createNewSchema(
915
- zodSchema,
916
- newSchemaState({ ...state, visited: /* @__PURE__ */ new Set() }),
917
- subpath
918
- );
1303
+ const newSchema = createNewSchema(zodSchema, {
1304
+ ...state,
1305
+ visited: /* @__PURE__ */ new Set()
1306
+ });
919
1307
  state.components.schemas.set(zodSchema, {
920
1308
  type: "complete",
921
1309
  ref,
922
1310
  schemaObject: newSchema.schema,
923
- creationType: newSchema.newState?.effectType
1311
+ effects: newSchema.effects
924
1312
  });
925
1313
  return {
1314
+ type: "ref",
926
1315
  schema: { $ref: createComponentSchemaRef(ref) },
927
- newState: newSchema.newState
1316
+ effects: newSchema.effects ? [
1317
+ {
1318
+ type: "component",
1319
+ zodType: zodSchema,
1320
+ path: [...state.path]
1321
+ }
1322
+ ] : void 0,
1323
+ zodType: zodSchema
928
1324
  };
929
1325
  };
930
- var createExistingRef = (zodSchema, component, state, subpath) => {
931
- const newState = newSchemaState(state);
932
- newState.path.push(...subpath);
1326
+ var createExistingRef = (zodSchema, component, state) => {
933
1327
  if (component && component.type === "complete") {
934
- if (component.creationType && component.creationType !== state.type) {
935
- throwTransformError(zodSchema, newState);
936
- }
937
1328
  return {
1329
+ type: "ref",
938
1330
  schema: { $ref: createComponentSchemaRef(component.ref) },
939
- newState: {
940
- ...newState,
941
- effectType: component.creationType
942
- }
1331
+ effects: component.effects ? [
1332
+ {
1333
+ type: "component",
1334
+ zodType: zodSchema,
1335
+ path: [...state.path]
1336
+ }
1337
+ ] : void 0,
1338
+ zodType: zodSchema
943
1339
  };
944
1340
  }
945
1341
  if (component && component.type === "in-progress") {
946
1342
  return {
1343
+ type: "ref",
947
1344
  schema: { $ref: createComponentSchemaRef(component.ref) },
948
- newState
1345
+ effects: [
1346
+ {
1347
+ type: "component",
1348
+ zodType: zodSchema,
1349
+ path: [...state.path]
1350
+ }
1351
+ ],
1352
+ zodType: zodSchema
949
1353
  };
950
1354
  }
951
1355
  return;
952
1356
  };
953
- var createSchemaOrRef = (zodSchema, state, subpath) => {
1357
+ var createSchemaOrRef = (zodSchema, state) => {
954
1358
  const component = state.components.schemas.get(zodSchema);
955
- const existingRef = createExistingRef(zodSchema, component, state, subpath);
1359
+ const existingRef = createExistingRef(zodSchema, component, state);
956
1360
  if (existingRef) {
957
1361
  return existingRef;
958
1362
  }
959
1363
  const ref = zodSchema._def.openapi?.ref ?? component?.ref;
960
1364
  if (ref) {
961
- return createNewRef(ref, zodSchema, state, subpath);
1365
+ return createNewRef(ref, zodSchema, state);
962
1366
  }
963
- return createNewSchema(zodSchema, newSchemaState(state), subpath);
1367
+ return createNewSchema(zodSchema, state);
964
1368
  };
965
1369
  var createSchemaObject = (zodSchema, state, subpath) => {
966
- const { schema, newState } = createSchemaOrRef(zodSchema, state, subpath);
967
- if (newState?.effectType) {
968
- if (state.type !== newState?.effectType || state.effectType && newState.effectType !== state.effectType) {
969
- throwTransformError(zodSchema, newState);
970
- }
971
- state.effectType = newState.effectType;
972
- }
1370
+ state.path.push(...subpath);
1371
+ const schema = createSchemaOrRef(zodSchema, state);
1372
+ state.path.pop();
973
1373
  return schema;
974
1374
  };
1375
+ var createSchema = (zodSchema, state, subpath) => {
1376
+ const schema = createSchemaObject(zodSchema, state, subpath);
1377
+ if (schema.effects) {
1378
+ verifyEffects(schema.effects, state);
1379
+ }
1380
+ return schema.schema;
1381
+ };
975
1382
 
976
1383
  // src/create/parameters.ts
977
1384
  var createComponentParamRef = (ref) => `#/components/parameters/${ref}`;
978
1385
  var createBaseParameter = (schema, components, subpath) => {
979
1386
  const { ref, ...rest } = schema._def.openapi?.param ?? {};
980
- const state = newSchemaState({
1387
+ const state = {
981
1388
  components,
982
1389
  type: "input",
983
1390
  path: [],
984
1391
  visited: /* @__PURE__ */ new Set()
985
- });
986
- const schemaObject = createSchemaObject(schema, state, [
987
- ...subpath,
988
- "schema"
989
- ]);
990
- const required = !isOptionalSchema(schema, state);
1392
+ };
1393
+ const schemaObject = createSchema(schema, state, [...subpath, "schema"]);
1394
+ const required = !isOptionalSchema(schema, state)?.optional;
1395
+ const description = schema._def.openapi?.description ?? schema._def.description;
991
1396
  return {
1397
+ ...description && { description },
992
1398
  ...rest,
993
1399
  ...schema && { schema: schemaObject },
994
1400
  ...required && { required }
@@ -1005,7 +1411,7 @@ var createParamOrRef = (zodSchema, components, subpath, type, name) => {
1005
1411
  throw new Error("Parameter name missing");
1006
1412
  }
1007
1413
  if (component && component.type === "complete") {
1008
- if (!("$ref" in component.paramObject) && (component.in !== type || component.name !== name)) {
1414
+ if (!("$ref" in component.paramObject) && (component.in !== paramType || component.name !== paramName)) {
1009
1415
  throw new Error(`parameterRef "${component.ref}" is already registered`);
1010
1416
  }
1011
1417
  return {
@@ -1103,14 +1509,14 @@ var createMediaTypeSchema = (schemaObject, components, type, subpath) => {
1103
1509
  if (!isAnyZodType(schemaObject)) {
1104
1510
  return schemaObject;
1105
1511
  }
1106
- return createSchemaObject(
1512
+ return createSchema(
1107
1513
  schemaObject,
1108
- newSchemaState({
1514
+ {
1109
1515
  components,
1110
1516
  type,
1111
1517
  path: [],
1112
1518
  visited: /* @__PURE__ */ new Set()
1113
- }),
1519
+ },
1114
1520
  subpath
1115
1521
  );
1116
1522
  };
@@ -1184,14 +1590,14 @@ var createHeaderOrRef = (schema, components) => {
1184
1590
  };
1185
1591
  var createBaseHeader = (schema, components) => {
1186
1592
  const { ref, ...rest } = schema._def.openapi?.header ?? {};
1187
- const state = newSchemaState({
1593
+ const state = {
1188
1594
  components,
1189
1595
  type: "output",
1190
1596
  path: [],
1191
1597
  visited: /* @__PURE__ */ new Set()
1192
- });
1193
- const schemaObject = createSchemaObject(schema, state, ["header"]);
1194
- const required = !isOptionalSchema(schema, state);
1598
+ };
1599
+ const schemaObject = createSchema(schema, state, ["header"]);
1600
+ const required = !isOptionalSchema(schema, state)?.optional;
1195
1601
  return {
1196
1602
  ...rest,
1197
1603
  ...schema && { schema: schemaObject },
@@ -1482,13 +1888,13 @@ var createComponents = (componentsObject, components) => {
1482
1888
  var createSchemaComponents = (componentsObject, components) => {
1483
1889
  Array.from(components.schemas).forEach(([schema, { type }], index) => {
1484
1890
  if (type === "manual") {
1485
- const state = newSchemaState({
1891
+ const state = {
1486
1892
  components,
1487
1893
  type: schema._def.openapi?.refType ?? "output",
1488
1894
  path: [],
1489
1895
  visited: /* @__PURE__ */ new Set()
1490
- });
1491
- createSchemaObject(schema, state, [`component schema index ${index}`]);
1896
+ };
1897
+ createSchema(schema, state, [`component schema index ${index}`]);
1492
1898
  }
1493
1899
  });
1494
1900
  const customComponents = Object.entries(