Open djbb7 opened 1 year ago
Want to create a PR for this? And how would typing work? It would be extending the Zod object.
Try this:
import { extendApi as extendOpenApi } from '@anatine/zod-openapi'
import type { SchemaObject } from 'openapi3-ts'
import type { default as z, ZodTypeDef, ZodType } from 'zod'
export interface ApiOptions<T extends ZodType<any>> extends SchemaObject {
example?: z.input<T>
examples?: z.input<T>[]
}
declare module 'zod' {
interface ZodType<
Output = any,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Def extends ZodTypeDef = ZodTypeDef,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Input = Output
> {
extendApi<T extends ZodType<any>>(this: T, metadata: ApiOptions<T>): T
}
}
export function extendZodWithExtendApi(zod: typeof z) {
if (typeof zod.ZodType.prototype.extendApi !== 'undefined') {
return
}
zod.ZodType.prototype.extendApi = function extendApi(
this: any,
args: SchemaObject
) {
return extendOpenApi((this as ZodType<any>).transform(s => s) as any, args)
}
}
Can confirm the solution provided by @tangye1234 works, check out a broader example here: https://github.com/Aetherspace/green-stack-starter-demo/blob/main/packages/%40aetherspace/schemas/aetherSchemas.ts
There is 1 caveat to this approach though, since if any other package exports zod, bundlers like webpack will not apply your prototype extensions to both versions.
You can fix this by either:
export { z } from 'zod'
in your zod.extension.ts
file and importing z
from there wherever you want to use the new chained methodsZod
to an addChainedMethod(zod: Zod)
so you can attach your prototype methods on a zod instance of your choosingThis is already possible with extendZodWithOpenApi(z)
extendZodWithOpenApi(z)
export const GetCatsZ =
z.object({
cats: z.string().array().extendApi({ description: 'List of cats' }),
}).openapi(
{ title: 'Get Cat Response' }
);
Currently the
extendApi
syntax wraps around zod objects, which is hard to read. It would be much more readable to use a chained syntax to avoid all the nested parentheses.Current syntax:
Suggested syntax:
I think this could be achieved by patching the
z
prototype schema, there is an example of a project that does that here: https://github.com/asteasolutions/zod-to-openapi/blob/master/src/zod-extensions.ts#L50