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
@@ -10,30 +10,27 @@ var isAnyZodType = (zodType) => Boolean(
10
10
  zodType?._def?.typeName
11
11
  );
12
12
 
13
- // src/openapi.ts
14
- var openApiVersions = [
15
- "3.0.0",
16
- "3.0.1",
17
- "3.0.2",
18
- "3.0.3",
19
- "3.1.0"
20
- ];
21
- var satisfiesVersion = (test, against) => openApiVersions.indexOf(test) >= openApiVersions.indexOf(against);
22
- var isReferenceObject = (schemaOrRef) => Boolean("$ref" in schemaOrRef && schemaOrRef.$ref);
23
-
24
13
  // src/create/schema/metadata.ts
25
- var enhanceWithMetadata = (schemaObject, metadata) => {
26
- if (isReferenceObject(schemaObject)) {
14
+ var enhanceWithMetadata = (schema, metadata) => {
15
+ if (schema.type === "ref") {
27
16
  if (Object.values(metadata).every((val) => val === void 0)) {
28
- return schemaObject;
17
+ return schema;
29
18
  }
30
19
  return {
31
- allOf: [schemaObject, metadata]
20
+ type: "schema",
21
+ schema: {
22
+ allOf: [schema.schema, metadata]
23
+ },
24
+ effects: schema.effects
32
25
  };
33
26
  }
34
27
  return {
35
- ...schemaObject,
36
- ...metadata
28
+ type: "schema",
29
+ schema: {
30
+ ...schema.schema,
31
+ ...metadata
32
+ },
33
+ effects: schema.effects
37
34
  };
38
35
  };
39
36
 
@@ -42,17 +39,25 @@ var createArraySchema = (zodArray, state) => {
42
39
  const zodType = zodArray._def.type;
43
40
  const minItems = zodArray._def.exactLength?.value ?? zodArray._def.minLength?.value;
44
41
  const maxItems = zodArray._def.exactLength?.value ?? zodArray._def.maxLength?.value;
42
+ const items = createSchemaObject(zodType, state, ["array items"]);
45
43
  return {
46
- type: "array",
47
- items: createSchemaObject(zodType, state, ["array items"]),
48
- ...minItems !== void 0 && { minItems },
49
- ...maxItems !== void 0 && { maxItems }
44
+ type: "schema",
45
+ schema: {
46
+ type: "array",
47
+ items: items.schema,
48
+ ...minItems !== void 0 && { minItems },
49
+ ...maxItems !== void 0 && { maxItems }
50
+ },
51
+ effects: items.effects
50
52
  };
51
53
  };
52
54
 
53
55
  // src/create/schema/parsers/boolean.ts
54
56
  var createBooleanSchema = (_zodBoolean) => ({
55
- type: "boolean"
57
+ type: "schema",
58
+ schema: {
59
+ type: "boolean"
60
+ }
56
61
  });
57
62
 
58
63
  // src/create/schema/parsers/brand.ts
@@ -63,7 +68,10 @@ var createCatchSchema = (zodCatch, state) => createSchemaObject(zodCatch._def.in
63
68
 
64
69
  // src/create/schema/parsers/date.ts
65
70
  var createDateSchema = (_zodDate) => ({
66
- type: "string"
71
+ type: "schema",
72
+ schema: {
73
+ type: "string"
74
+ }
67
75
  });
68
76
 
69
77
  // src/create/schema/parsers/default.ts
@@ -76,21 +84,186 @@ var createDefaultSchema = (zodDefault, state) => {
76
84
  });
77
85
  };
78
86
 
87
+ // src/create/schema/parsers/transform.ts
88
+ var createTransformSchema = (zodTransform, state) => {
89
+ if (zodTransform._def.openapi?.effectType === "output") {
90
+ return {
91
+ type: "schema",
92
+ schema: createManualOutputTransformSchema(zodTransform, state)
93
+ };
94
+ }
95
+ if (zodTransform._def.openapi?.effectType === "input" || zodTransform._def.openapi?.effectType === "same") {
96
+ return createSchemaObject(zodTransform._def.schema, state, [
97
+ "transform input"
98
+ ]);
99
+ }
100
+ if (state.type === "output") {
101
+ return {
102
+ type: "schema",
103
+ schema: createManualOutputTransformSchema(zodTransform, state)
104
+ };
105
+ }
106
+ const schema = createSchemaObject(zodTransform._def.schema, state, [
107
+ "transform input"
108
+ ]);
109
+ return {
110
+ ...schema,
111
+ effects: flattenEffects([
112
+ [
113
+ {
114
+ type: "schema",
115
+ creationType: "input",
116
+ zodType: zodTransform,
117
+ path: [...state.path]
118
+ }
119
+ ],
120
+ schema.effects
121
+ ])
122
+ };
123
+ };
124
+ var createManualOutputTransformSchema = (zodTransform, state) => {
125
+ if (!zodTransform._def.openapi?.type) {
126
+ const zodType = zodTransform.constructor.name;
127
+ const schemaName = `${zodType} - ${zodTransform._def.effect.type}`;
128
+ throw new Error(
129
+ `Failed to determine a type for ${schemaName} at ${state.path.join(
130
+ " > "
131
+ )}. Please change the 'effectType' to 'input', wrap it in a ZodPipeline or assign it a manual 'type'.`
132
+ );
133
+ }
134
+ return {
135
+ type: zodTransform._def.openapi.type
136
+ };
137
+ };
138
+ var getZodTypeName = (zodType) => {
139
+ if (isZodType(zodType, "ZodEffects")) {
140
+ return `${zodType._def.typeName} - ${zodType._def.effect.type}`;
141
+ }
142
+ return zodType._def.typeName;
143
+ };
144
+ var throwTransformError = (effect) => {
145
+ const typeName = getZodTypeName(effect.zodType);
146
+ const input = effect.creationType;
147
+ const opposite = input === "input" ? "output" : "input";
148
+ throw new Error(
149
+ `The ${typeName} at ${effect.path.join(
150
+ " > "
151
+ )} is used within a registered compoment schema${effect.component ? ` (${effect.component.ref})` : ""} and contains an ${input} transformation${effect.component ? ` (${getZodTypeName(
152
+ effect.component.zodType
153
+ )}) defined at ${effect.component.path.join(" > ")}` : ""} which is also used in an ${opposite} schema.
154
+
155
+ This may cause the schema to render incorrectly and is most likely a mistake. You can resolve this by:
156
+
157
+ 1. Setting an \`effectType\` on the transformation to \`same\` or \`${opposite}\` eg. \`.openapi({type: 'same'})\`
158
+ 2. Wrapping the transformation in a ZodPipeline
159
+ 3. Assigning a manual type to the transformation eg. \`.openapi({type: 'string'})\`
160
+ 4. Removing the transformation
161
+ 5. Deregistering the component containing the transformation`
162
+ );
163
+ };
164
+ var resolveSingleEffect = (effect, state) => {
165
+ if (effect.type === "schema") {
166
+ return {
167
+ creationType: effect.creationType,
168
+ path: effect.path,
169
+ zodType: effect.zodType
170
+ };
171
+ }
172
+ if (effect.type === "component") {
173
+ if (state.visited.has(effect.zodType)) {
174
+ return;
175
+ }
176
+ const component = state.components.schemas.get(effect.zodType);
177
+ if (component?.type !== "complete") {
178
+ throw new Error("Something went wrong, component schema is not complete");
179
+ }
180
+ if (component.resolvedEffect) {
181
+ return {
182
+ creationType: component.resolvedEffect.creationType,
183
+ path: effect.path,
184
+ zodType: effect.zodType,
185
+ component: {
186
+ ref: component.ref,
187
+ zodType: component.resolvedEffect.zodType,
188
+ path: component.resolvedEffect.path
189
+ }
190
+ };
191
+ }
192
+ if (!component.effects) {
193
+ return void 0;
194
+ }
195
+ state.visited.add(effect.zodType);
196
+ const resolved = resolveEffect(component.effects, state);
197
+ state.visited.delete(effect.zodType);
198
+ if (!resolved) {
199
+ return void 0;
200
+ }
201
+ component.resolvedEffect = resolved;
202
+ return resolved;
203
+ }
204
+ return void 0;
205
+ };
206
+ var resolveEffect = (effects, state) => {
207
+ const { input, output } = effects.reduce(
208
+ (acc, effect) => {
209
+ const resolvedSchemaEffect = resolveSingleEffect(effect, state);
210
+ if (resolvedSchemaEffect?.creationType === "input") {
211
+ acc.input.push(resolvedSchemaEffect);
212
+ }
213
+ if (resolvedSchemaEffect?.creationType === "output") {
214
+ acc.output.push(resolvedSchemaEffect);
215
+ }
216
+ if (resolvedSchemaEffect && acc.input.length > 1 && acc.output.length > 1) {
217
+ throwTransformError(resolvedSchemaEffect);
218
+ }
219
+ return acc;
220
+ },
221
+ { input: [], output: [] }
222
+ );
223
+ if (input.length > 0) {
224
+ return input[0];
225
+ }
226
+ if (output.length > 0) {
227
+ return output[0];
228
+ }
229
+ return void 0;
230
+ };
231
+ var verifyEffects = (effects, state) => {
232
+ const resolved = resolveEffect(effects, state);
233
+ if (resolved?.creationType && resolved.creationType !== state.type) {
234
+ throwTransformError(resolved);
235
+ }
236
+ };
237
+ var flattenEffects = (effects) => {
238
+ const allEffects = effects.reduce((acc, effect) => {
239
+ if (effect) {
240
+ return acc.concat(effect);
241
+ }
242
+ return acc;
243
+ }, []);
244
+ return allEffects.length ? allEffects : void 0;
245
+ };
246
+
79
247
  // src/create/schema/parsers/discriminatedUnion.ts
80
248
  var createDiscriminatedUnionSchema = (zodDiscriminatedUnion, state) => {
81
249
  const options = zodDiscriminatedUnion.options;
82
250
  const schemas = options.map(
83
251
  (option, index) => createSchemaObject(option, state, [`discriminated union option ${index}`])
84
252
  );
253
+ const schemaObjects = schemas.map((schema) => schema.schema);
85
254
  const discriminator = mapDiscriminator(
86
- schemas,
255
+ schemaObjects,
87
256
  options,
88
257
  zodDiscriminatedUnion.discriminator,
89
258
  state
90
259
  );
91
260
  return {
92
- oneOf: schemas,
93
- ...discriminator && { discriminator }
261
+ type: "schema",
262
+ schema: {
263
+ oneOf: schemaObjects,
264
+ ...discriminator && { discriminator }
265
+ },
266
+ effects: flattenEffects(schemas.map((schema) => schema.effects))
94
267
  };
95
268
  };
96
269
  var mapDiscriminator = (schemas, zodObjects, discriminator, state) => {
@@ -129,19 +302,29 @@ var mapDiscriminator = (schemas, zodObjects, discriminator, state) => {
129
302
 
130
303
  // src/create/schema/parsers/enum.ts
131
304
  var createEnumSchema = (zodEnum) => ({
132
- type: "string",
133
- enum: zodEnum._def.values
305
+ type: "schema",
306
+ schema: {
307
+ type: "string",
308
+ enum: zodEnum._def.values
309
+ }
134
310
  });
135
311
 
136
312
  // src/create/schema/parsers/intersection.ts
137
- var createIntersectionSchema = (zodIntersection, state) => ({
138
- allOf: [
139
- createSchemaObject(zodIntersection._def.left, state, ["intersection left"]),
140
- createSchemaObject(zodIntersection._def.right, state, [
141
- "intersection right"
142
- ])
143
- ]
144
- });
313
+ var createIntersectionSchema = (zodIntersection, state) => {
314
+ const left = createSchemaObject(zodIntersection._def.left, state, [
315
+ "intersection left"
316
+ ]);
317
+ const right = createSchemaObject(zodIntersection._def.right, state, [
318
+ "intersection right"
319
+ ]);
320
+ return {
321
+ type: "schema",
322
+ schema: {
323
+ allOf: [left.schema, right.schema]
324
+ },
325
+ effects: flattenEffects([left.effects, right.effects])
326
+ };
327
+ };
145
328
 
146
329
  // src/create/schema/parsers/lazy.ts
147
330
  var createLazySchema = (zodLazy, state) => {
@@ -151,31 +334,41 @@ var createLazySchema = (zodLazy, state) => {
151
334
 
152
335
  // src/create/schema/parsers/literal.ts
153
336
  var createLiteralSchema = (zodLiteral) => ({
154
- type: typeof zodLiteral.value,
155
- enum: [zodLiteral._def.value]
337
+ type: "schema",
338
+ schema: {
339
+ type: typeof zodLiteral.value,
340
+ enum: [zodLiteral._def.value]
341
+ }
156
342
  });
157
343
 
158
344
  // src/create/schema/parsers/manual.ts
159
345
  var createManualTypeSchema = (zodSchema, state) => {
160
346
  if (!zodSchema._def.openapi?.type) {
161
- const zodType = zodSchema.constructor.name;
162
- if (isZodType(zodSchema, "ZodEffects")) {
163
- const schemaName = `${zodType} - ${zodSchema._def.effect.type}`;
164
- throw new Error(
165
- `Unknown schema ${schemaName} at ${state.path.join(
166
- " > "
167
- )}. Please assign it a manual 'type', wrap it in a ZodPipeline or change the 'effectType'.`
168
- );
169
- }
347
+ const schemaName = zodSchema.constructor.name;
170
348
  throw new Error(
171
- `Unknown schema ${zodType}. Please assign it a manual 'type'.`
349
+ `Unknown schema ${schemaName} at ${state.path.join(
350
+ " > "
351
+ )}. Please assign it a manual 'type'.`
172
352
  );
173
353
  }
174
354
  return {
175
- type: zodSchema._def.openapi.type
355
+ type: "schema",
356
+ schema: {
357
+ type: zodSchema._def.openapi.type
358
+ }
176
359
  };
177
360
  };
178
361
 
362
+ // src/openapi.ts
363
+ var openApiVersions = [
364
+ "3.0.0",
365
+ "3.0.1",
366
+ "3.0.2",
367
+ "3.0.3",
368
+ "3.1.0"
369
+ ];
370
+ var satisfiesVersion = (test, against) => openApiVersions.indexOf(test) >= openApiVersions.indexOf(against);
371
+
179
372
  // src/create/schema/parsers/nativeEnum.ts
180
373
  var createNativeEnumSchema = (zodEnum, state) => {
181
374
  const enumValues = getValidEnumValues(zodEnum._def.values);
@@ -183,25 +376,37 @@ var createNativeEnumSchema = (zodEnum, state) => {
183
376
  if (strings.length && numbers.length) {
184
377
  if (satisfiesVersion(state.components.openapi, "3.1.0"))
185
378
  return {
186
- type: ["string", "number"],
187
- enum: [...strings, ...numbers]
379
+ type: "schema",
380
+ schema: {
381
+ type: ["string", "number"],
382
+ enum: [...strings, ...numbers]
383
+ }
188
384
  };
189
385
  return {
190
- oneOf: [
191
- { type: "string", enum: strings },
192
- { type: "number", enum: numbers }
193
- ]
386
+ type: "schema",
387
+ schema: {
388
+ oneOf: [
389
+ { type: "string", enum: strings },
390
+ { type: "number", enum: numbers }
391
+ ]
392
+ }
194
393
  };
195
394
  }
196
395
  if (strings.length) {
197
396
  return {
198
- type: "string",
199
- enum: strings
397
+ type: "schema",
398
+ schema: {
399
+ type: "string",
400
+ enum: strings
401
+ }
200
402
  };
201
403
  }
202
404
  return {
203
- type: "number",
204
- enum: numbers
405
+ type: "schema",
406
+ schema: {
407
+ type: "number",
408
+ enum: numbers
409
+ }
205
410
  };
206
411
  };
207
412
  var getValidEnumValues = (enumValues) => {
@@ -217,7 +422,10 @@ var sortStringsAndNumbers = (values) => ({
217
422
 
218
423
  // src/create/schema/parsers/null.ts
219
424
  var createNullSchema = (_zodNull) => ({
220
- type: "null"
425
+ type: "schema",
426
+ schema: {
427
+ type: "null"
428
+ }
221
429
  });
222
430
 
223
431
  // src/create/schema/parsers/nullable.ts
@@ -226,45 +434,69 @@ var createNullableSchema = (zodNullable, state) => {
226
434
  "nullable"
227
435
  ]);
228
436
  if (satisfiesVersion(state.components.openapi, "3.1.0")) {
229
- if (isReferenceObject(schemaObject) || schemaObject.allOf) {
437
+ if (schemaObject.type === "ref" || schemaObject.schema.allOf) {
230
438
  return {
231
- oneOf: mapNullOf([schemaObject], state.components.openapi)
439
+ type: "schema",
440
+ schema: {
441
+ oneOf: mapNullOf([schemaObject.schema], state.components.openapi)
442
+ },
443
+ effects: schemaObject.effects
232
444
  };
233
445
  }
234
- if (schemaObject.oneOf) {
235
- const { oneOf, ...schema3 } = schemaObject;
446
+ if (schemaObject.schema.oneOf) {
447
+ const { oneOf, ...schema3 } = schemaObject.schema;
236
448
  return {
237
- oneOf: mapNullOf(oneOf, state.components.openapi),
238
- ...schema3
449
+ type: "schema",
450
+ schema: {
451
+ oneOf: mapNullOf(oneOf, state.components.openapi),
452
+ ...schema3
453
+ },
454
+ effects: schemaObject.effects
239
455
  };
240
456
  }
241
- if (schemaObject.anyOf) {
242
- const { anyOf, ...schema3 } = schemaObject;
457
+ if (schemaObject.schema.anyOf) {
458
+ const { anyOf, ...schema3 } = schemaObject.schema;
243
459
  return {
244
- anyOf: mapNullOf(anyOf, state.components.openapi),
245
- ...schema3
460
+ type: "schema",
461
+ schema: {
462
+ anyOf: mapNullOf(anyOf, state.components.openapi),
463
+ ...schema3
464
+ },
465
+ effects: schemaObject.effects
246
466
  };
247
467
  }
248
- const { type: type2, ...schema2 } = schemaObject;
468
+ const { type: type2, ...schema2 } = schemaObject.schema;
249
469
  return {
250
- type: mapNullType(type2),
251
- ...schema2
470
+ type: "schema",
471
+ schema: {
472
+ type: mapNullType(type2),
473
+ ...schema2
474
+ },
475
+ effects: schemaObject.effects
252
476
  };
253
477
  }
254
- if (isReferenceObject(schemaObject)) {
478
+ if (schemaObject.type === "ref") {
255
479
  return {
256
- allOf: [schemaObject],
257
- nullable: true
480
+ type: "schema",
481
+ schema: {
482
+ allOf: [schemaObject.schema],
483
+ nullable: true
484
+ },
485
+ effects: schemaObject.effects
258
486
  };
259
487
  }
260
- const { type, ...schema } = schemaObject;
488
+ const { type, ...schema } = schemaObject.schema;
261
489
  return {
262
- ...type && { type },
263
- nullable: true,
264
- ...schema,
265
- // 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
266
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
267
- ...schema.enum && { enum: [...schema.enum, null] }
490
+ type: "schema",
491
+ schema: {
492
+ ...type && { type },
493
+ nullable: true,
494
+ ...schema,
495
+ // 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
496
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
497
+ ...schema.enum && { enum: [...schema.enum, null] }
498
+ },
499
+ effects: schemaObject.effects
268
500
  };
269
501
  };
270
502
  var mapNullType = (type) => {
@@ -289,10 +521,13 @@ var createNumberSchema = (zodNumber, state) => {
289
521
  const minimum = mapMinimum(zodNumberChecks, state.components.openapi);
290
522
  const maximum = mapMaximum(zodNumberChecks, state.components.openapi);
291
523
  return {
292
- type: mapNumberType(zodNumberChecks),
293
- ...minimum && minimum,
294
- // Union types are not easy to tame
295
- ...maximum && maximum
524
+ type: "schema",
525
+ schema: {
526
+ type: mapNumberType(zodNumberChecks),
527
+ ...minimum && minimum,
528
+ // Union types are not easy to tame
529
+ ...maximum && maximum
530
+ }
296
531
  };
297
532
  };
298
533
  var mapMaximum = (zodNumberCheck, openapi) => {
@@ -328,16 +563,29 @@ var getZodNumberChecks = (zodNumber) => zodNumber._def.checks.reduce((acc, check
328
563
  var mapNumberType = (zodNumberChecks) => zodNumberChecks.int ? "integer" : "number";
329
564
 
330
565
  // src/create/schema/parsers/optional.ts
331
- var createOptionalSchema = (zodOptional, state) => (
332
- // Optional doesn't change OpenAPI schema
333
- createSchemaObject(zodOptional.unwrap(), state, ["optional"])
334
- );
566
+ var createOptionalSchema = (zodOptional, state) => createSchemaObject(zodOptional.unwrap(), state, ["optional"]);
335
567
  var isOptionalSchema = (zodSchema, state) => {
336
- if (isZodType(zodSchema, "ZodOptional")) {
337
- return true;
568
+ if (isZodType(zodSchema, "ZodOptional") || isZodType(zodSchema, "ZodNever") || isZodType(zodSchema, "ZodUndefined")) {
569
+ return { optional: true };
338
570
  }
339
571
  if (isZodType(zodSchema, "ZodDefault")) {
340
- return state.type === "input";
572
+ if (zodSchema._def.openapi?.effectType === "input") {
573
+ return { optional: true };
574
+ }
575
+ if (zodSchema._def.openapi?.effectType === "output") {
576
+ return { optional: false };
577
+ }
578
+ return {
579
+ optional: state.type === "input",
580
+ effects: [
581
+ {
582
+ type: "schema",
583
+ creationType: state.type,
584
+ zodType: zodSchema,
585
+ path: [...state.path]
586
+ }
587
+ ]
588
+ };
341
589
  }
342
590
  if (isZodType(zodSchema, "ZodNullable") || isZodType(zodSchema, "ZodCatch")) {
343
591
  return isOptionalSchema(zodSchema._def.innerType, state);
@@ -346,27 +594,42 @@ var isOptionalSchema = (zodSchema, state) => {
346
594
  return isOptionalSchema(zodSchema._def.schema, state);
347
595
  }
348
596
  if (isZodType(zodSchema, "ZodUnion") || isZodType(zodSchema, "ZodDiscriminatedUnion")) {
349
- return zodSchema._def.options.some(
597
+ const results = zodSchema._def.options.map(
350
598
  (schema) => isOptionalSchema(schema, state)
351
599
  );
600
+ return results.reduce(
601
+ (acc, result) => ({
602
+ optional: acc.optional || result.optional,
603
+ effects: flattenEffects([acc.effects, result.effects])
604
+ }),
605
+ { optional: false }
606
+ );
352
607
  }
353
608
  if (isZodType(zodSchema, "ZodIntersection")) {
354
- return [zodSchema._def.left, zodSchema._def.right].some(
609
+ const results = [zodSchema._def.left, zodSchema._def.right].map(
355
610
  (schema) => isOptionalSchema(schema, state)
356
611
  );
612
+ return results.reduce(
613
+ (acc, result) => ({
614
+ optional: acc.optional || result.optional,
615
+ effects: flattenEffects([acc.effects, result.effects])
616
+ }),
617
+ { optional: false }
618
+ );
357
619
  }
358
620
  if (isZodType(zodSchema, "ZodPipeline")) {
359
- if (state.effectType === "input" || state.type === "input" && state.effectType !== "output") {
621
+ const type = zodSchema._def.openapi?.effectType ?? state.type;
622
+ if (type === "input") {
360
623
  return isOptionalSchema(zodSchema._def.in, state);
361
624
  }
362
- if (state.effectType === "output" || state.type === "output" && state.effectType !== "input") {
625
+ if (type === "output") {
363
626
  return isOptionalSchema(zodSchema._def.out, state);
364
627
  }
365
628
  }
366
629
  if (isZodType(zodSchema, "ZodLazy")) {
367
630
  return isOptionalSchema(zodSchema._def.getter(), state);
368
631
  }
369
- return zodSchema.isOptional();
632
+ return { optional: zodSchema.isOptional() };
370
633
  };
371
634
 
372
635
  // src/create/schema/parsers/object.ts
@@ -420,9 +683,28 @@ var createExtendedSchema = (zodObject, baseZodObject, state) => {
420
683
  if (!diffShape) {
421
684
  return void 0;
422
685
  }
686
+ const extendedSchema = createObjectSchemaFromShape(
687
+ diffShape,
688
+ diffOpts,
689
+ state
690
+ );
423
691
  return {
424
- allOf: [{ $ref: createComponentSchemaRef(completeComponent.ref) }],
425
- ...createObjectSchemaFromShape(diffShape, diffOpts, state)
692
+ type: "schema",
693
+ schema: {
694
+ allOf: [{ $ref: createComponentSchemaRef(completeComponent.ref) }],
695
+ ...extendedSchema.schema
696
+ },
697
+ effects: flattenEffects([
698
+ completeComponent.type === "complete" ? completeComponent.effects : [],
699
+ completeComponent.type === "in-progress" ? [
700
+ {
701
+ type: "component",
702
+ zodType: zodObject,
703
+ path: [...state.path]
704
+ }
705
+ ] : [],
706
+ extendedSchema.effects
707
+ ])
426
708
  };
427
709
  };
428
710
  var createDiffOpts = (baseOpts, extendedOpts) => {
@@ -452,47 +734,114 @@ var createShapeDiff = (baseObj, extendedObj) => {
452
734
  var createObjectSchemaFromShape = (shape, { unknownKeys, catchAll }, state) => {
453
735
  const properties = mapProperties(shape, state);
454
736
  const required = mapRequired(shape, state);
737
+ const additionalProperties = !isZodType(catchAll, "ZodNever") ? createSchemaObject(catchAll, state, ["additional properties"]) : void 0;
455
738
  return {
456
- type: "object",
457
- ...properties && { properties },
458
- ...required && { required },
459
- ...unknownKeys === "strict" && { additionalProperties: false },
460
- ...!isZodType(catchAll, "ZodNever") && {
461
- additionalProperties: createSchemaObject(catchAll, state, [
462
- "additional properties"
463
- ])
464
- }
739
+ type: "schema",
740
+ schema: {
741
+ type: "object",
742
+ ...properties && { properties: properties.properties },
743
+ ...required?.required.length && { required: required.required },
744
+ ...unknownKeys === "strict" && { additionalProperties: false },
745
+ ...additionalProperties && {
746
+ additionalProperties: additionalProperties.schema
747
+ }
748
+ },
749
+ effects: flattenEffects([
750
+ ...properties?.effects ?? [],
751
+ additionalProperties?.effects,
752
+ required?.effects
753
+ ])
465
754
  };
466
755
  };
467
756
  var mapRequired = (shape, state) => {
468
- const required = Object.entries(shape).filter(([_key, zodSchema]) => !isOptionalSchema(zodSchema, state)).map(([key]) => key);
469
- if (!required.length) {
757
+ const { required, effects: allEffects } = Object.entries(shape).reduce(
758
+ (acc, [key, zodSchema]) => {
759
+ state.path.push(`property: ${key}`);
760
+ const { optional, effects } = isOptionalSchema(zodSchema, state);
761
+ state.path.pop();
762
+ if (!optional) {
763
+ acc.required.push(key);
764
+ }
765
+ if (effects) {
766
+ acc.effects.push(effects);
767
+ }
768
+ return acc;
769
+ },
770
+ {
771
+ required: [],
772
+ effects: []
773
+ }
774
+ );
775
+ return { required, effects: flattenEffects(allEffects) };
776
+ };
777
+ var mapProperties = (shape, state) => {
778
+ const shapeEntries = Object.entries(shape);
779
+ if (!shapeEntries.length) {
470
780
  return void 0;
471
781
  }
472
- return required;
782
+ return shapeEntries.reduce(
783
+ (acc, [key, zodSchema]) => {
784
+ if (isZodType(zodSchema, "ZodNever") || isZodType(zodSchema, "ZodUndefined")) {
785
+ return acc;
786
+ }
787
+ const property = createSchemaObject(zodSchema, state, [
788
+ `property: ${key}`
789
+ ]);
790
+ acc.properties[key] = property.schema;
791
+ acc.effects.push(property.effects);
792
+ return acc;
793
+ },
794
+ {
795
+ properties: {},
796
+ effects: []
797
+ }
798
+ );
473
799
  };
474
- var mapProperties = (shape, state) => Object.entries(shape).reduce(
475
- (acc, [key, zodSchema]) => {
476
- acc[key] = createSchemaObject(zodSchema, state, [`property: ${key}`]);
477
- return acc;
478
- },
479
- {}
480
- );
481
800
 
482
801
  // src/create/schema/parsers/pipeline.ts
483
802
  var createPipelineSchema = (zodPipeline, state) => {
484
- if (zodPipeline._def.openapi?.effectType === "input") {
803
+ if (zodPipeline._def.openapi?.effectType === "input" || zodPipeline._def.openapi?.effectType === "same") {
485
804
  return createSchemaObject(zodPipeline._def.in, state, ["pipeline input"]);
486
805
  }
487
806
  if (zodPipeline._def.openapi?.effectType === "output") {
488
807
  return createSchemaObject(zodPipeline._def.out, state, ["pipeline output"]);
489
808
  }
490
809
  if (state.type === "input") {
491
- state.effectType = "input";
492
- return createSchemaObject(zodPipeline._def.in, state, ["pipeline input"]);
810
+ const schema2 = createSchemaObject(zodPipeline._def.in, state, [
811
+ "pipeline input"
812
+ ]);
813
+ return {
814
+ ...schema2,
815
+ effects: flattenEffects([
816
+ [
817
+ {
818
+ type: "schema",
819
+ creationType: "input",
820
+ path: [...state.path],
821
+ zodType: zodPipeline
822
+ }
823
+ ],
824
+ schema2.effects
825
+ ])
826
+ };
493
827
  }
494
- state.effectType = "output";
495
- return createSchemaObject(zodPipeline._def.out, state, ["pipeline output"]);
828
+ const schema = createSchemaObject(zodPipeline._def.out, state, [
829
+ "pipeline output"
830
+ ]);
831
+ return {
832
+ ...schema,
833
+ effects: flattenEffects([
834
+ [
835
+ {
836
+ type: "schema",
837
+ creationType: "output",
838
+ path: [...state.path],
839
+ zodType: zodPipeline
840
+ }
841
+ ],
842
+ schema.effects
843
+ ])
844
+ };
496
845
  };
497
846
 
498
847
  // src/create/schema/parsers/preprocess.ts
@@ -514,30 +863,50 @@ var createRecordSchema = (zodRecord, state) => {
514
863
  const keySchema = createSchemaObject(zodRecord.keySchema, state, [
515
864
  "record key"
516
865
  ]);
517
- const maybeComponent = "$ref" in keySchema && state.components.schemas.get(zodRecord.keySchema);
518
- const maybeSchema = maybeComponent && maybeComponent.type === "complete" && maybeComponent.schemaObject;
519
- const renderedKeySchema = maybeSchema || keySchema;
866
+ const maybeComponent = state.components.schemas.get(zodRecord.keySchema);
867
+ const isComplete = maybeComponent && maybeComponent.type === "complete";
868
+ const maybeSchema = isComplete && maybeComponent.schemaObject;
869
+ const maybeEffects = isComplete && maybeComponent.effects || void 0;
870
+ const renderedKeySchema = maybeSchema || keySchema.schema;
520
871
  if ("enum" in renderedKeySchema && renderedKeySchema.enum) {
521
872
  return {
522
- type: "object",
523
- properties: renderedKeySchema.enum.reduce((acc, key) => {
524
- acc[key] = additionalProperties;
525
- return acc;
526
- }, {}),
527
- additionalProperties: false
873
+ type: "schema",
874
+ schema: {
875
+ type: "object",
876
+ properties: renderedKeySchema.enum.reduce((acc, key) => {
877
+ acc[key] = additionalProperties.schema;
878
+ return acc;
879
+ }, {}),
880
+ additionalProperties: false
881
+ },
882
+ effects: flattenEffects([
883
+ keySchema.effects,
884
+ additionalProperties.effects,
885
+ maybeEffects
886
+ ])
528
887
  };
529
888
  }
530
889
  if (satisfiesVersion(state.components.openapi, "3.1.0") && "type" in renderedKeySchema && renderedKeySchema.type === "string" && Object.keys(renderedKeySchema).length > 1) {
531
890
  return {
532
- type: "object",
533
- // @ts-expect-error FIXME: https://github.com/metadevpro/openapi3-ts/pull/120
534
- propertyNames: keySchema,
535
- additionalProperties
891
+ type: "schema",
892
+ schema: {
893
+ type: "object",
894
+ propertyNames: keySchema.schema,
895
+ additionalProperties: additionalProperties.schema
896
+ },
897
+ effects: flattenEffects([
898
+ keySchema.effects,
899
+ additionalProperties.effects
900
+ ])
536
901
  };
537
902
  }
538
903
  return {
539
- type: "object",
540
- additionalProperties
904
+ type: "schema",
905
+ schema: {
906
+ type: "object",
907
+ additionalProperties: additionalProperties.schema
908
+ },
909
+ effects: additionalProperties.effects
541
910
  };
542
911
  };
543
912
 
@@ -549,12 +918,17 @@ var createSetSchema = (zodSet, state) => {
549
918
  const schema = zodSet._def.valueType;
550
919
  const minItems = zodSet._def.minSize?.value;
551
920
  const maxItems = zodSet._def.maxSize?.value;
921
+ const itemSchema = createSchemaObject(schema, state, ["set items"]);
552
922
  return {
553
- type: "array",
554
- items: createSchemaObject(schema, state, ["set items"]),
555
- uniqueItems: true,
556
- ...minItems !== void 0 && { minItems },
557
- ...maxItems !== void 0 && { maxItems }
923
+ type: "schema",
924
+ schema: {
925
+ type: "array",
926
+ items: itemSchema.schema,
927
+ uniqueItems: true,
928
+ ...minItems !== void 0 && { minItems },
929
+ ...maxItems !== void 0 && { maxItems }
930
+ },
931
+ effects: itemSchema.effects
558
932
  };
559
933
  };
560
934
 
@@ -567,29 +941,35 @@ var createStringSchema = (zodString) => {
567
941
  const maxLength = zodStringChecks.length?.[0]?.value ?? zodStringChecks.max?.[0]?.value;
568
942
  if (patterns.length <= 1) {
569
943
  return {
570
- type: "string",
571
- ...format && { format },
572
- ...patterns[0] && { pattern: patterns[0] },
573
- ...minLength !== void 0 && { minLength },
574
- ...maxLength !== void 0 && { maxLength }
575
- };
576
- }
577
- return {
578
- allOf: [
579
- {
944
+ type: "schema",
945
+ schema: {
580
946
  type: "string",
581
947
  ...format && { format },
582
948
  ...patterns[0] && { pattern: patterns[0] },
583
949
  ...minLength !== void 0 && { minLength },
584
950
  ...maxLength !== void 0 && { maxLength }
585
- },
586
- ...patterns.slice(1).map(
587
- (pattern) => ({
951
+ }
952
+ };
953
+ }
954
+ return {
955
+ type: "schema",
956
+ schema: {
957
+ allOf: [
958
+ {
588
959
  type: "string",
589
- pattern
590
- })
591
- )
592
- ]
960
+ ...format && { format },
961
+ ...patterns[0] && { pattern: patterns[0] },
962
+ ...minLength !== void 0 && { minLength },
963
+ ...maxLength !== void 0 && { maxLength }
964
+ },
965
+ ...patterns.slice(1).map(
966
+ (pattern) => ({
967
+ type: "string",
968
+ pattern
969
+ })
970
+ )
971
+ ]
972
+ }
593
973
  };
594
974
  };
595
975
  var getZodStringChecks = (zodString) => zodString._def.checks.reduce(
@@ -655,82 +1035,88 @@ var mapStringFormat = (zodStringChecks) => {
655
1035
  return void 0;
656
1036
  };
657
1037
 
658
- // src/create/schema/parsers/transform.ts
659
- var createTransformSchema = (zodTransform, state) => {
660
- if (zodTransform._def.openapi?.effectType === "output") {
661
- return createManualTypeSchema(zodTransform, state);
662
- }
663
- if (zodTransform._def.openapi?.effectType === "input") {
664
- return createSchemaObject(zodTransform._def.schema, state, [
665
- "transform input"
666
- ]);
667
- }
668
- if (state.type === "output") {
669
- return createManualTypeSchema(zodTransform, state);
670
- }
671
- state.effectType = "input";
672
- return createSchemaObject(zodTransform._def.schema, state, [
673
- "transform input"
674
- ]);
675
- };
676
- var throwTransformError = (zodType, state) => {
677
- throw new Error(
678
- `${JSON.stringify(zodType)} at ${state.path.join(
679
- " > "
680
- )} 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`
681
- );
682
- };
683
-
684
1038
  // src/create/schema/parsers/tuple.ts
685
1039
  var createTupleSchema = (zodTuple, state) => {
686
1040
  const items = zodTuple.items;
687
1041
  const rest = zodTuple._def.rest;
688
- return {
689
- type: "array",
690
- ...mapItemProperties(items, rest, state)
691
- };
692
- };
693
- var mapPrefixItems = (items, state) => {
694
- if (items.length) {
695
- return items.map(
696
- (item, index) => createSchemaObject(item, state, [`tuple item ${index}`])
697
- );
698
- }
699
- return void 0;
700
- };
701
- var mapItemProperties = (items, rest, state) => {
702
1042
  const prefixItems = mapPrefixItems(items, state);
703
1043
  if (satisfiesVersion(state.components.openapi, "3.1.0")) {
704
1044
  if (!rest) {
705
1045
  return {
706
- maxItems: items.length,
707
- minItems: items.length,
708
- ...prefixItems && { prefixItems }
1046
+ type: "schema",
1047
+ schema: {
1048
+ type: "array",
1049
+ maxItems: items.length,
1050
+ minItems: items.length,
1051
+ ...prefixItems && {
1052
+ prefixItems: prefixItems.schemas.map((item) => item.schema)
1053
+ }
1054
+ },
1055
+ effects: prefixItems?.effects
709
1056
  };
710
1057
  }
1058
+ const itemSchema = createSchemaObject(rest, state, ["tuple items"]);
711
1059
  return {
712
- items: createSchemaObject(rest, state, ["tuple items"]),
713
- ...prefixItems && { prefixItems }
1060
+ type: "schema",
1061
+ schema: {
1062
+ type: "array",
1063
+ items: itemSchema.schema,
1064
+ ...prefixItems && {
1065
+ prefixItems: prefixItems.schemas.map((item) => item.schema)
1066
+ }
1067
+ },
1068
+ effects: flattenEffects([prefixItems?.effects, itemSchema.effects])
714
1069
  };
715
1070
  }
716
1071
  if (!rest) {
717
1072
  return {
718
- maxItems: items.length,
719
- minItems: items.length,
720
- ...prefixItems && { items: { oneOf: prefixItems } }
1073
+ type: "schema",
1074
+ schema: {
1075
+ type: "array",
1076
+ maxItems: items.length,
1077
+ minItems: items.length,
1078
+ ...prefixItems && {
1079
+ items: { oneOf: prefixItems.schemas.map((item) => item.schema) }
1080
+ }
1081
+ },
1082
+ effects: prefixItems?.effects
1083
+ };
1084
+ }
1085
+ if (prefixItems) {
1086
+ const restSchema = createSchemaObject(rest, state, ["tuple items"]);
1087
+ return {
1088
+ type: "schema",
1089
+ schema: {
1090
+ type: "array",
1091
+ items: {
1092
+ oneOf: [
1093
+ ...prefixItems.schemas.map((item) => item.schema),
1094
+ restSchema.schema
1095
+ ]
1096
+ }
1097
+ },
1098
+ effects: flattenEffects([restSchema.effects, prefixItems.effects])
721
1099
  };
722
1100
  }
723
1101
  return {
724
- ...prefixItems && {
725
- items: {
726
- oneOf: [
727
- ...prefixItems,
728
- createSchemaObject(rest, state, ["tuple items"])
729
- ]
730
- }
1102
+ type: "schema",
1103
+ schema: {
1104
+ type: "array"
731
1105
  }
732
1106
  };
733
1107
  };
1108
+ var mapPrefixItems = (items, state) => {
1109
+ if (items.length) {
1110
+ const schemas = items.map(
1111
+ (item, index) => createSchemaObject(item, state, [`tuple item ${index}`])
1112
+ );
1113
+ return {
1114
+ effects: flattenEffects(schemas.map((s) => s.effects)),
1115
+ schemas
1116
+ };
1117
+ }
1118
+ return void 0;
1119
+ };
734
1120
 
735
1121
  // src/create/schema/parsers/union.ts
736
1122
  var createUnionSchema = (zodUnion, state) => {
@@ -739,16 +1125,27 @@ var createUnionSchema = (zodUnion, state) => {
739
1125
  );
740
1126
  if (zodUnion._def.openapi?.unionOneOf) {
741
1127
  return {
742
- oneOf: schemas
1128
+ type: "schema",
1129
+ schema: {
1130
+ oneOf: schemas.map((s) => s.schema)
1131
+ },
1132
+ effects: flattenEffects(schemas.map((s) => s.effects))
743
1133
  };
744
1134
  }
745
1135
  return {
746
- anyOf: schemas
1136
+ type: "schema",
1137
+ schema: {
1138
+ anyOf: schemas.map((s) => s.schema)
1139
+ },
1140
+ effects: flattenEffects(schemas.map((s) => s.effects))
747
1141
  };
748
1142
  };
749
1143
 
750
1144
  // src/create/schema/parsers/unknown.ts
751
- var createUnknownSchema = (_zodUnknown) => ({});
1145
+ var createUnknownSchema = (_zodUnknown) => ({
1146
+ type: "schema",
1147
+ schema: {}
1148
+ });
752
1149
 
753
1150
  // src/create/schema/parsers/index.ts
754
1151
  var createSchemaSwitch = (zodSchema, state) => {
@@ -846,22 +1243,16 @@ var createSchemaSwitch = (zodSchema, state) => {
846
1243
  };
847
1244
 
848
1245
  // src/create/schema/index.ts
849
- var newSchemaState = (state) => ({
850
- type: state.type,
851
- components: state.components,
852
- path: [...state.path],
853
- visited: new Set(state.visited)
854
- });
855
- var createNewSchema = (zodSchema, newState, subpath) => {
856
- newState.path.push(...subpath);
857
- if (newState.visited.has(zodSchema)) {
1246
+ var isDescriptionEqual = (schema, zodSchema) => schema.type === "ref" && zodSchema.description === schema.zodType.description;
1247
+ var createNewSchema = (zodSchema, state) => {
1248
+ if (state.visited.has(zodSchema)) {
858
1249
  throw new Error(
859
- `The schema at ${newState.path.join(
1250
+ `The schema at ${state.path.join(
860
1251
  " > "
861
1252
  )} needs to be registered because it's circularly referenced`
862
1253
  );
863
1254
  }
864
- newState.visited.add(zodSchema);
1255
+ state.visited.add(zodSchema);
865
1256
  const {
866
1257
  effectType,
867
1258
  param,
@@ -871,100 +1262,115 @@ var createNewSchema = (zodSchema, newState, subpath) => {
871
1262
  unionOneOf,
872
1263
  ...additionalMetadata
873
1264
  } = zodSchema._def.openapi ?? {};
874
- const schema = createSchemaSwitch(zodSchema, newState);
875
- const description = zodSchema.description;
1265
+ const schema = createSchemaSwitch(zodSchema, state);
1266
+ const description = zodSchema.description && !isDescriptionEqual(schema, zodSchema) ? zodSchema.description : void 0;
876
1267
  const schemaWithMetadata = enhanceWithMetadata(schema, {
877
1268
  ...description && { description },
878
1269
  ...additionalMetadata
879
1270
  });
880
- return {
881
- schema: schemaWithMetadata,
882
- newState
883
- };
1271
+ state.visited.delete(zodSchema);
1272
+ return schemaWithMetadata;
884
1273
  };
885
- var createNewRef = (ref, zodSchema, state, subpath) => {
1274
+ var createNewRef = (ref, zodSchema, state) => {
886
1275
  state.components.schemas.set(zodSchema, {
887
1276
  type: "in-progress",
888
1277
  ref
889
1278
  });
890
- const newSchema = createNewSchema(
891
- zodSchema,
892
- newSchemaState({ ...state, visited: /* @__PURE__ */ new Set() }),
893
- subpath
894
- );
1279
+ const newSchema = createNewSchema(zodSchema, {
1280
+ ...state,
1281
+ visited: /* @__PURE__ */ new Set()
1282
+ });
895
1283
  state.components.schemas.set(zodSchema, {
896
1284
  type: "complete",
897
1285
  ref,
898
1286
  schemaObject: newSchema.schema,
899
- creationType: newSchema.newState?.effectType
1287
+ effects: newSchema.effects
900
1288
  });
901
1289
  return {
1290
+ type: "ref",
902
1291
  schema: { $ref: createComponentSchemaRef(ref) },
903
- newState: newSchema.newState
1292
+ effects: newSchema.effects ? [
1293
+ {
1294
+ type: "component",
1295
+ zodType: zodSchema,
1296
+ path: [...state.path]
1297
+ }
1298
+ ] : void 0,
1299
+ zodType: zodSchema
904
1300
  };
905
1301
  };
906
- var createExistingRef = (zodSchema, component, state, subpath) => {
907
- const newState = newSchemaState(state);
908
- newState.path.push(...subpath);
1302
+ var createExistingRef = (zodSchema, component, state) => {
909
1303
  if (component && component.type === "complete") {
910
- if (component.creationType && component.creationType !== state.type) {
911
- throwTransformError(zodSchema, newState);
912
- }
913
1304
  return {
1305
+ type: "ref",
914
1306
  schema: { $ref: createComponentSchemaRef(component.ref) },
915
- newState: {
916
- ...newState,
917
- effectType: component.creationType
918
- }
1307
+ effects: component.effects ? [
1308
+ {
1309
+ type: "component",
1310
+ zodType: zodSchema,
1311
+ path: [...state.path]
1312
+ }
1313
+ ] : void 0,
1314
+ zodType: zodSchema
919
1315
  };
920
1316
  }
921
1317
  if (component && component.type === "in-progress") {
922
1318
  return {
1319
+ type: "ref",
923
1320
  schema: { $ref: createComponentSchemaRef(component.ref) },
924
- newState
1321
+ effects: [
1322
+ {
1323
+ type: "component",
1324
+ zodType: zodSchema,
1325
+ path: [...state.path]
1326
+ }
1327
+ ],
1328
+ zodType: zodSchema
925
1329
  };
926
1330
  }
927
1331
  return;
928
1332
  };
929
- var createSchemaOrRef = (zodSchema, state, subpath) => {
1333
+ var createSchemaOrRef = (zodSchema, state) => {
930
1334
  const component = state.components.schemas.get(zodSchema);
931
- const existingRef = createExistingRef(zodSchema, component, state, subpath);
1335
+ const existingRef = createExistingRef(zodSchema, component, state);
932
1336
  if (existingRef) {
933
1337
  return existingRef;
934
1338
  }
935
1339
  const ref = zodSchema._def.openapi?.ref ?? component?.ref;
936
1340
  if (ref) {
937
- return createNewRef(ref, zodSchema, state, subpath);
1341
+ return createNewRef(ref, zodSchema, state);
938
1342
  }
939
- return createNewSchema(zodSchema, newSchemaState(state), subpath);
1343
+ return createNewSchema(zodSchema, state);
940
1344
  };
941
1345
  var createSchemaObject = (zodSchema, state, subpath) => {
942
- const { schema, newState } = createSchemaOrRef(zodSchema, state, subpath);
943
- if (newState?.effectType) {
944
- if (state.type !== newState?.effectType || state.effectType && newState.effectType !== state.effectType) {
945
- throwTransformError(zodSchema, newState);
946
- }
947
- state.effectType = newState.effectType;
948
- }
1346
+ state.path.push(...subpath);
1347
+ const schema = createSchemaOrRef(zodSchema, state);
1348
+ state.path.pop();
949
1349
  return schema;
950
1350
  };
1351
+ var createSchema = (zodSchema, state, subpath) => {
1352
+ const schema = createSchemaObject(zodSchema, state, subpath);
1353
+ if (schema.effects) {
1354
+ verifyEffects(schema.effects, state);
1355
+ }
1356
+ return schema.schema;
1357
+ };
951
1358
 
952
1359
  // src/create/parameters.ts
953
1360
  var createComponentParamRef = (ref) => `#/components/parameters/${ref}`;
954
1361
  var createBaseParameter = (schema, components, subpath) => {
955
1362
  const { ref, ...rest } = schema._def.openapi?.param ?? {};
956
- const state = newSchemaState({
1363
+ const state = {
957
1364
  components,
958
1365
  type: "input",
959
1366
  path: [],
960
1367
  visited: /* @__PURE__ */ new Set()
961
- });
962
- const schemaObject = createSchemaObject(schema, state, [
963
- ...subpath,
964
- "schema"
965
- ]);
966
- const required = !isOptionalSchema(schema, state);
1368
+ };
1369
+ const schemaObject = createSchema(schema, state, [...subpath, "schema"]);
1370
+ const required = !isOptionalSchema(schema, state)?.optional;
1371
+ const description = schema._def.openapi?.description ?? schema._def.description;
967
1372
  return {
1373
+ ...description && { description },
968
1374
  ...rest,
969
1375
  ...schema && { schema: schemaObject },
970
1376
  ...required && { required }
@@ -981,7 +1387,7 @@ var createParamOrRef = (zodSchema, components, subpath, type, name) => {
981
1387
  throw new Error("Parameter name missing");
982
1388
  }
983
1389
  if (component && component.type === "complete") {
984
- if (!("$ref" in component.paramObject) && (component.in !== type || component.name !== name)) {
1390
+ if (!("$ref" in component.paramObject) && (component.in !== paramType || component.name !== paramName)) {
985
1391
  throw new Error(`parameterRef "${component.ref}" is already registered`);
986
1392
  }
987
1393
  return {
@@ -1079,14 +1485,14 @@ var createMediaTypeSchema = (schemaObject, components, type, subpath) => {
1079
1485
  if (!isAnyZodType(schemaObject)) {
1080
1486
  return schemaObject;
1081
1487
  }
1082
- return createSchemaObject(
1488
+ return createSchema(
1083
1489
  schemaObject,
1084
- newSchemaState({
1490
+ {
1085
1491
  components,
1086
1492
  type,
1087
1493
  path: [],
1088
1494
  visited: /* @__PURE__ */ new Set()
1089
- }),
1495
+ },
1090
1496
  subpath
1091
1497
  );
1092
1498
  };
@@ -1160,14 +1566,14 @@ var createHeaderOrRef = (schema, components) => {
1160
1566
  };
1161
1567
  var createBaseHeader = (schema, components) => {
1162
1568
  const { ref, ...rest } = schema._def.openapi?.header ?? {};
1163
- const state = newSchemaState({
1569
+ const state = {
1164
1570
  components,
1165
1571
  type: "output",
1166
1572
  path: [],
1167
1573
  visited: /* @__PURE__ */ new Set()
1168
- });
1169
- const schemaObject = createSchemaObject(schema, state, ["header"]);
1170
- const required = !isOptionalSchema(schema, state);
1574
+ };
1575
+ const schemaObject = createSchema(schema, state, ["header"]);
1576
+ const required = !isOptionalSchema(schema, state)?.optional;
1171
1577
  return {
1172
1578
  ...rest,
1173
1579
  ...schema && { schema: schemaObject },
@@ -1458,13 +1864,13 @@ var createComponents = (componentsObject, components) => {
1458
1864
  var createSchemaComponents = (componentsObject, components) => {
1459
1865
  Array.from(components.schemas).forEach(([schema, { type }], index) => {
1460
1866
  if (type === "manual") {
1461
- const state = newSchemaState({
1867
+ const state = {
1462
1868
  components,
1463
1869
  type: schema._def.openapi?.refType ?? "output",
1464
1870
  path: [],
1465
1871
  visited: /* @__PURE__ */ new Set()
1466
- });
1467
- createSchemaObject(schema, state, [`component schema index ${index}`]);
1872
+ };
1873
+ createSchema(schema, state, [`component schema index ${index}`]);
1468
1874
  }
1469
1875
  });
1470
1876
  const customComponents = Object.entries(