Skip to content

Commit

Permalink
Add enforceDiscriminatedUnionComponents (#369)
Browse files Browse the repository at this point in the history
  • Loading branch information
samchungy authored Nov 25, 2024
1 parent eee8671 commit 0b3ffaa
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ const document = createDocument({
const document = createDocument(details, {
defaultDateSchema: { type: 'string', format: 'date-time' }, // defaults to { type: 'string' }
unionOneOf: true, // defaults to false. Forces all ZodUnions to output oneOf instead of anyOf. An `.openapi()` `unionOneOf` value takes precedence over this one.
enforceDiscriminatedUnionComponents: true, // defaults to false. Throws an error if a Discriminated Union member is not registered as a component.
});
```

Expand Down
4 changes: 4 additions & 0 deletions src/create/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ export type ZodObjectInputType<
> = ZodType<Output, Def, Input>;

export interface CreateDocumentOptions {
/**
* Used to throw an error if a Discriminated Union member is not registered as a component
*/
enforceDiscriminatedUnionComponents?: boolean;
/**
* Used to change the default Zod Date schema
*/
Expand Down
22 changes: 22 additions & 0 deletions src/create/schema/parsers/discriminatedUnion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -486,4 +486,26 @@ describe('createDiscriminatedUnionSchema', () => {
],
});
});

it('throws an error if enforceDiscriminatedUnionComponents is specified and a schema is not registered', () => {
const schema = z.discriminatedUnion('type', [
z.object({
type: z.literal('a'),
}),
z
.object({
type: z.literal('b'),
})
.openapi({ ref: 'b' }),
]);

expect(() =>
createDiscriminatedUnionSchema(schema, {
...createOutputState({}, { enforceDiscriminatedUnionComponents: true }),
path: ['some', 'path'],
}),
).toThrowErrorMatchingInlineSnapshot(
`"Discriminated Union member 0 at some > path is not registered as a component"`,
);
});
});
6 changes: 6 additions & 0 deletions src/create/schema/parsers/discriminatedUnion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const createDiscriminatedUnionSchema = <
zodDiscriminatedUnion.discriminator,
state,
);

return {
type: 'schema',
schema: {
Expand Down Expand Up @@ -98,6 +99,11 @@ export const mapDiscriminator = (
const schema = schemas[index] as oas31.SchemaObject | oas31.ReferenceObject;
const componentSchemaRef = '$ref' in schema ? schema?.$ref : undefined;
if (!componentSchemaRef) {
if (state.documentOptions?.enforceDiscriminatedUnionComponents) {
throw new Error(
`Discriminated Union member ${index} at ${state.path.join(' > ')} is not registered as a component`,
);
}
return undefined;
}

Expand Down

0 comments on commit 0b3ffaa

Please sign in to comment.