Skip to content

Commit 4884081

Browse files
authored
.openapi() Breaking Change (#356)
1 parent ad24cf7 commit 4884081

24 files changed

+1247
-149
lines changed

src/create/components.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ const getSchemas = (
254254
`Schema ${JSON.stringify(schema._def)} is already registered`,
255255
);
256256
}
257-
const ref = schema._def.openapi?.ref ?? key;
257+
const ref = schema._def.zodOpenApi?.openapi?.ref ?? key;
258258
components.schemas.set(schema, {
259259
type: 'manual',
260260
ref,
@@ -278,9 +278,9 @@ const getParameters = (
278278
`Parameter ${JSON.stringify(schema._def)} is already registered`,
279279
);
280280
}
281-
const ref = schema._def.openapi?.param?.ref ?? key;
282-
const name = schema._def.openapi?.param?.name;
283-
const location = schema._def.openapi?.param?.in;
281+
const ref = schema._def.zodOpenApi?.openapi?.param?.ref ?? key;
282+
const name = schema._def.zodOpenApi?.openapi?.param?.name;
283+
const location = schema._def.zodOpenApi?.openapi?.param?.in;
284284

285285
if (!name || !location) {
286286
throw new Error('`name` or `in` missing in .openapi()');
@@ -310,7 +310,7 @@ const getHeaders = (
310310
`Header ${JSON.stringify(schema._def)} is already registered`,
311311
);
312312
}
313-
const ref = schema._def.openapi?.param?.ref ?? key;
313+
const ref = schema._def.zodOpenApi?.openapi?.param?.ref ?? key;
314314
components.headers.set(schema, {
315315
type: 'manual',
316316
ref,
@@ -456,7 +456,7 @@ export const createSchemaComponents = (
456456
if (type === 'manual') {
457457
const state: SchemaState = {
458458
components,
459-
type: schema._def.openapi?.refType ?? 'output',
459+
type: schema._def.zodOpenApi?.openapi?.refType ?? 'output',
460460
path: [],
461461
visited: new Set(),
462462
documentOptions,

src/create/document.test.ts

-2
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,6 @@ describe('createDocument', () => {
518518
"required": [
519519
"d",
520520
],
521-
"type": "object",
522521
},
523522
"lazy": {
524523
"items": {
@@ -852,7 +851,6 @@ describe('createDocument', () => {
852851
"required": [
853852
"d",
854853
],
855-
"type": "object",
856854
},
857855
"lazy": {
858856
"items": {

src/create/parameters.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export const createBaseParameter = (
2020
subpath: string[],
2121
documentOptions?: CreateDocumentOptions,
2222
): oas31.BaseParameterObject => {
23-
const { ref, ...rest } = schema._def.openapi?.param ?? {};
23+
const { ref, ...rest } = schema._def.zodOpenApi?.openapi?.param ?? {};
2424
const state: SchemaState = {
2525
components,
2626
type: 'input',
@@ -32,7 +32,7 @@ export const createBaseParameter = (
3232
const required = !schema.isOptional();
3333

3434
const description =
35-
schema._def.openapi?.description ?? schema._def.description;
35+
schema._def.zodOpenApi?.openapi?.description ?? schema._def.description;
3636

3737
return {
3838
...(description && { description }),
@@ -51,9 +51,10 @@ export const createParamOrRef = (
5151
documentOptions?: CreateDocumentOptions,
5252
): oas31.ParameterObject | oas31.ReferenceObject => {
5353
const component = components.parameters.get(zodSchema);
54-
const paramType = zodSchema._def?.openapi?.param?.in ?? component?.in ?? type;
54+
const paramType =
55+
zodSchema._def.zodOpenApi?.openapi?.param?.in ?? component?.in ?? type;
5556
const paramName =
56-
zodSchema._def?.openapi?.param?.name ?? component?.name ?? name;
57+
zodSchema._def.zodOpenApi?.openapi?.param?.name ?? component?.name ?? name;
5758

5859
if (!paramType) {
5960
throw new Error('Parameter type missing');
@@ -86,7 +87,7 @@ export const createParamOrRef = (
8687
throw new Error('Unexpected Error: received a reference object');
8788
}
8889

89-
const ref = zodSchema?._def?.openapi?.param?.ref ?? component?.ref;
90+
const ref = zodSchema?._def.zodOpenApi?.openapi?.param?.ref ?? component?.ref;
9091

9192
const paramObject: oas31.ParameterObject = {
9293
in: paramType,

src/create/responses.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export const createHeaderOrRef = (
5959
throw new Error('Unexpected Error: received a reference object');
6060
}
6161

62-
const ref = schema._def?.openapi?.header?.ref ?? component?.ref;
62+
const ref = schema._def.zodOpenApi?.openapi?.header?.ref ?? component?.ref;
6363

6464
if (ref) {
6565
components.headers.set(schema, {
@@ -80,7 +80,7 @@ export const createBaseHeader = (
8080
components: ComponentsObject,
8181
documentOptions?: CreateDocumentOptions,
8282
): oas31.BaseParameterObject => {
83-
const { ref, ...rest } = schema._def.openapi?.header ?? {};
83+
const { ref, ...rest } = schema._def.zodOpenApi?.openapi?.header ?? {};
8484
const state: SchemaState = {
8585
components,
8686
type: 'output',

src/create/schema/index.ts

+75-31
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { ZodType, ZodTypeDef } from 'zod';
22

3-
import type { oas31 } from '../../openapi3-ts/dist';
3+
import type { oas30, oas31 } from '../../openapi3-ts/dist';
44
import {
55
type ComponentsObject,
66
type CreationType,
@@ -24,17 +24,19 @@ export interface SchemaState {
2424
documentOptions?: CreateSchemaOptions;
2525
}
2626

27-
const isDescriptionEqual = (schema: Schema, zodSchema: ZodType): boolean =>
28-
schema.type === 'ref' && zodSchema.description === schema.zodType.description;
29-
3027
export const createNewSchema = <
3128
Output = unknown,
3229
Def extends ZodTypeDef = ZodTypeDef,
3330
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 => {
3840
if (state.visited.has(zodSchema)) {
3941
throw new Error(
4042
`The schema at ${state.path.join(
@@ -51,18 +53,16 @@ export const createNewSchema = <
5153
refType,
5254
unionOneOf,
5355
...additionalMetadata
54-
} = zodSchema._def.openapi ?? {};
56+
} = zodSchema._def.zodOpenApi?.openapi ?? {};
5557

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);
6159

62-
const schemaWithMetadata = enhanceWithMetadata(schema, {
63-
...(description && { description }),
64-
...additionalMetadata,
65-
});
60+
const schemaWithMetadata = enhanceWithMetadata(
61+
schema,
62+
additionalMetadata,
63+
state,
64+
previous,
65+
);
6666
state.visited.delete(zodSchema);
6767
return schemaWithMetadata;
6868
};
@@ -71,19 +71,29 @@ export const createNewRef = <
7171
Output = unknown,
7272
Def extends ZodTypeDef = ZodTypeDef,
7373
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 => {
7985
state.components.schemas.set(zodSchema, {
8086
type: 'in-progress',
8187
ref,
8288
});
8389

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+
},
8797
});
8898

8999
state.components.schemas.set(zodSchema, {
@@ -101,6 +111,7 @@ export const createNewRef = <
101111
state.documentOptions?.componentRefPath,
102112
),
103113
},
114+
schemaObject: newSchema.schema,
104115
effects: newSchema.effects
105116
? [
106117
{
@@ -122,7 +133,7 @@ export const createExistingRef = <
122133
zodSchema: ZodType<Output, Def, Input>,
123134
component: SchemaComponent | undefined,
124135
state: SchemaState,
125-
): Schema | undefined => {
136+
): RefObject | undefined => {
126137
if (component && component.type === 'complete') {
127138
return {
128139
type: 'ref',
@@ -132,6 +143,7 @@ export const createExistingRef = <
132143
state.documentOptions?.componentRefPath,
133144
),
134145
},
146+
schemaObject: component.schemaObject,
135147
effects: component.effects
136148
? [
137149
{
@@ -154,6 +166,7 @@ export const createExistingRef = <
154166
state.documentOptions?.componentRefPath,
155167
),
156168
},
169+
schemaObject: undefined,
157170
effects: [
158171
{
159172
type: 'component',
@@ -175,6 +188,12 @@ export type BaseObject = {
175188
export type RefObject = BaseObject & {
176189
type: 'ref';
177190
schema: oas31.ReferenceObject;
191+
schemaObject:
192+
| oas31.SchemaObject
193+
| oas31.ReferenceObject
194+
| oas30.ReferenceObject
195+
| oas30.SchemaObject
196+
| undefined;
178197
zodType: ZodType;
179198
};
180199

@@ -192,20 +211,41 @@ export const createSchemaOrRef = <
192211
>(
193212
zodSchema: ZodType<Output, Def, Input>,
194213
state: SchemaState,
195-
): Schema => {
214+
onlyRef?: boolean,
215+
): Schema | undefined => {
196216
const component = state.components.schemas.get(zodSchema);
197217
const existingRef = createExistingRef(zodSchema, component, state);
198218

199219
if (existingRef) {
200220
return existingRef;
201221
}
202222

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;
204238
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;
206246
}
207247

208-
return createNewSchema(zodSchema, state);
248+
return createNewSchema({ zodSchema, previous: previous ?? current, state });
209249
};
210250

211251
export const createSchemaObject = <
@@ -219,6 +259,10 @@ export const createSchemaObject = <
219259
): Schema => {
220260
state.path.push(...subpath);
221261
const schema = createSchemaOrRef(zodSchema, state);
262+
263+
if (!schema) {
264+
throw new Error('Schema does not exist');
265+
}
222266
state.path.pop();
223267
return schema;
224268
};

0 commit comments

Comments
 (0)