1
1
import type { ZodType , ZodTypeDef } from 'zod' ;
2
2
3
- import type { oas31 } from '../../openapi3-ts/dist' ;
3
+ import type { oas30 , oas31 } from '../../openapi3-ts/dist' ;
4
4
import {
5
5
type ComponentsObject ,
6
6
type CreationType ,
@@ -24,17 +24,19 @@ export interface SchemaState {
24
24
documentOptions ?: CreateSchemaOptions ;
25
25
}
26
26
27
- const isDescriptionEqual = ( schema : Schema , zodSchema : ZodType ) : boolean =>
28
- schema . type === 'ref' && zodSchema . description === schema . zodType . description ;
29
-
30
27
export const createNewSchema = <
31
28
Output = unknown ,
32
29
Def extends ZodTypeDef = ZodTypeDef ,
33
30
Input = Output ,
34
- > (
35
- zodSchema : ZodType < Output , Def , Input > ,
36
- state : SchemaState ,
37
- ) : Schema => {
31
+ > ( {
32
+ zodSchema,
33
+ previous,
34
+ state,
35
+ } : {
36
+ zodSchema : ZodType < Output , Def , Input > ;
37
+ previous : RefObject | undefined ;
38
+ state : SchemaState ;
39
+ } ) : Schema => {
38
40
if ( state . visited . has ( zodSchema ) ) {
39
41
throw new Error (
40
42
`The schema at ${ state . path . join (
@@ -51,18 +53,16 @@ export const createNewSchema = <
51
53
refType,
52
54
unionOneOf,
53
55
...additionalMetadata
54
- } = zodSchema . _def . openapi ?? { } ;
56
+ } = zodSchema . _def . zodOpenApi ?. openapi ?? { } ;
55
57
56
- const schema = createSchemaSwitch ( zodSchema , state ) ;
57
- const description =
58
- zodSchema . description && ! isDescriptionEqual ( schema , zodSchema )
59
- ? zodSchema . description
60
- : undefined ;
58
+ const schema = createSchemaSwitch ( zodSchema , previous , state ) ;
61
59
62
- const schemaWithMetadata = enhanceWithMetadata ( schema , {
63
- ...( description && { description } ) ,
64
- ...additionalMetadata ,
65
- } ) ;
60
+ const schemaWithMetadata = enhanceWithMetadata (
61
+ schema ,
62
+ additionalMetadata ,
63
+ state ,
64
+ previous ,
65
+ ) ;
66
66
state . visited . delete ( zodSchema ) ;
67
67
return schemaWithMetadata ;
68
68
} ;
@@ -71,19 +71,29 @@ export const createNewRef = <
71
71
Output = unknown ,
72
72
Def extends ZodTypeDef = ZodTypeDef ,
73
73
Input = Output ,
74
- > (
75
- ref : string ,
76
- zodSchema : ZodType < Output , Def , Input > ,
77
- state : SchemaState ,
78
- ) : Schema => {
74
+ > ( {
75
+ previous,
76
+ ref,
77
+ zodSchema,
78
+ state,
79
+ } : {
80
+ ref : string ;
81
+ zodSchema : ZodType < Output , Def , Input > ;
82
+ previous : RefObject | undefined ;
83
+ state : SchemaState ;
84
+ } ) : Schema => {
79
85
state . components . schemas . set ( zodSchema , {
80
86
type : 'in-progress' ,
81
87
ref,
82
88
} ) ;
83
89
84
- const newSchema = createNewSchema ( zodSchema , {
85
- ...state ,
86
- visited : new Set ( ) ,
90
+ const newSchema = createNewSchema ( {
91
+ zodSchema,
92
+ previous,
93
+ state : {
94
+ ...state ,
95
+ visited : new Set ( ) ,
96
+ } ,
87
97
} ) ;
88
98
89
99
state . components . schemas . set ( zodSchema , {
@@ -101,6 +111,7 @@ export const createNewRef = <
101
111
state . documentOptions ?. componentRefPath ,
102
112
) ,
103
113
} ,
114
+ schemaObject : newSchema . schema ,
104
115
effects : newSchema . effects
105
116
? [
106
117
{
@@ -122,7 +133,7 @@ export const createExistingRef = <
122
133
zodSchema : ZodType < Output , Def , Input > ,
123
134
component : SchemaComponent | undefined ,
124
135
state : SchemaState ,
125
- ) : Schema | undefined => {
136
+ ) : RefObject | undefined => {
126
137
if ( component && component . type === 'complete' ) {
127
138
return {
128
139
type : 'ref' ,
@@ -132,6 +143,7 @@ export const createExistingRef = <
132
143
state . documentOptions ?. componentRefPath ,
133
144
) ,
134
145
} ,
146
+ schemaObject : component . schemaObject ,
135
147
effects : component . effects
136
148
? [
137
149
{
@@ -154,6 +166,7 @@ export const createExistingRef = <
154
166
state . documentOptions ?. componentRefPath ,
155
167
) ,
156
168
} ,
169
+ schemaObject : undefined ,
157
170
effects : [
158
171
{
159
172
type : 'component' ,
@@ -175,6 +188,12 @@ export type BaseObject = {
175
188
export type RefObject = BaseObject & {
176
189
type : 'ref' ;
177
190
schema : oas31 . ReferenceObject ;
191
+ schemaObject :
192
+ | oas31 . SchemaObject
193
+ | oas31 . ReferenceObject
194
+ | oas30 . ReferenceObject
195
+ | oas30 . SchemaObject
196
+ | undefined ;
178
197
zodType : ZodType ;
179
198
} ;
180
199
@@ -192,20 +211,41 @@ export const createSchemaOrRef = <
192
211
> (
193
212
zodSchema : ZodType < Output , Def , Input > ,
194
213
state : SchemaState ,
195
- ) : Schema => {
214
+ onlyRef ?: boolean ,
215
+ ) : Schema | undefined => {
196
216
const component = state . components . schemas . get ( zodSchema ) ;
197
217
const existingRef = createExistingRef ( zodSchema , component , state ) ;
198
218
199
219
if ( existingRef ) {
200
220
return existingRef ;
201
221
}
202
222
203
- const ref = zodSchema . _def . openapi ?. ref ?? component ?. ref ;
223
+ const previous = zodSchema . _def . zodOpenApi ?. previous
224
+ ? ( createSchemaOrRef ( zodSchema . _def . zodOpenApi . previous , state , true ) as
225
+ | RefObject
226
+ | undefined )
227
+ : undefined ;
228
+
229
+ const current =
230
+ zodSchema . _def . zodOpenApi ?. current &&
231
+ zodSchema . _def . zodOpenApi . current !== zodSchema
232
+ ? ( createSchemaOrRef ( zodSchema . _def . zodOpenApi . current , state , true ) as
233
+ | RefObject
234
+ | undefined )
235
+ : undefined ;
236
+
237
+ const ref = zodSchema . _def . zodOpenApi ?. openapi ?. ref ?? component ?. ref ;
204
238
if ( ref ) {
205
- return createNewRef ( ref , zodSchema , state ) ;
239
+ return current
240
+ ? createNewSchema ( { zodSchema, previous : current , state } )
241
+ : createNewRef ( { ref, zodSchema, previous, state } ) ;
242
+ }
243
+
244
+ if ( onlyRef ) {
245
+ return previous ?? current ;
206
246
}
207
247
208
- return createNewSchema ( zodSchema , state ) ;
248
+ return createNewSchema ( { zodSchema, previous : previous ?? current , state } ) ;
209
249
} ;
210
250
211
251
export const createSchemaObject = <
@@ -219,6 +259,10 @@ export const createSchemaObject = <
219
259
) : Schema => {
220
260
state . path . push ( ...subpath ) ;
221
261
const schema = createSchemaOrRef ( zodSchema , state ) ;
262
+
263
+ if ( ! schema ) {
264
+ throw new Error ( 'Schema does not exist' ) ;
265
+ }
222
266
state . path . pop ( ) ;
223
267
return schema ;
224
268
} ;
0 commit comments