fastify-type-provider-zod
Version:
Zod Type Provider for Fastify@5
1 lines • 8.8 kB
Source Map (JSON)
{"version":3,"file":"core.cjs","sources":["../../src/core.ts"],"sourcesContent":["import type { SwaggerTransform, SwaggerTransformObject } from '@fastify/swagger'\nimport type {\n FastifyPluginAsync,\n FastifyPluginCallback,\n FastifyPluginOptions,\n FastifySchema,\n FastifySchemaCompiler,\n FastifyTypeProvider,\n RawServerBase,\n RawServerDefault,\n} from 'fastify'\nimport type { FastifySerializerCompiler } from 'fastify/types/schema'\nimport { z } from 'zod/v4'\n\nimport { InvalidSchemaError, ResponseSerializationError, createValidationError } from './errors'\nimport { zodRegistryToJson, zodSchemaToJson } from './zod-to-json'\n\ntype FreeformRecord = Record<string, any>\n\nconst defaultSkipList = [\n '/documentation/',\n '/documentation/initOAuth',\n '/documentation/json',\n '/documentation/uiConfig',\n '/documentation/yaml',\n '/documentation/*',\n '/documentation/static/*',\n]\n\nexport interface ZodTypeProvider extends FastifyTypeProvider {\n validator: this['schema'] extends z.ZodTypeAny ? z.output<this['schema']> : unknown\n serializer: this['schema'] extends z.ZodTypeAny ? z.input<this['schema']> : unknown\n}\n\ninterface Schema extends FastifySchema {\n hide?: boolean\n}\n\ntype CreateJsonSchemaTransformOptions = {\n skipList?: readonly string[]\n schemaRegistry?: z.core.$ZodRegistry<{ id?: string | undefined }>\n}\n\nexport const createJsonSchemaTransform = ({\n skipList = defaultSkipList,\n schemaRegistry = z.globalRegistry,\n}: CreateJsonSchemaTransformOptions): SwaggerTransform<Schema> => {\n return ({ schema, url }) => {\n if (!schema) {\n return {\n schema,\n url,\n }\n }\n\n const { response, headers, querystring, body, params, hide, ...rest } = schema\n\n const transformed: FreeformRecord = {}\n\n if (skipList.includes(url) || hide) {\n transformed.hide = true\n return { schema: transformed, url }\n }\n\n const zodSchemas: FreeformRecord = { headers, querystring, body, params }\n\n for (const prop in zodSchemas) {\n const zodSchema = zodSchemas[prop]\n if (zodSchema) {\n transformed[prop] = zodSchemaToJson(zodSchema, schemaRegistry, 'input')\n }\n }\n\n if (response) {\n transformed.response = {}\n\n for (const prop in response as any) {\n const zodSchema = resolveSchema((response as any)[prop])\n\n transformed.response[prop] = zodSchemaToJson(zodSchema, schemaRegistry, 'output')\n }\n }\n\n for (const prop in rest) {\n const meta = rest[prop as keyof typeof rest]\n if (meta) {\n transformed[prop] = meta\n }\n }\n\n return { schema: transformed, url }\n }\n}\n\nexport const jsonSchemaTransform: SwaggerTransform<Schema> = createJsonSchemaTransform({})\n\ntype CreateJsonSchemaTransformObjectOptions = {\n schemaRegistry?: z.core.$ZodRegistry<{ id?: string | undefined }>\n}\n\nexport const createJsonSchemaTransformObject =\n ({\n schemaRegistry = z.globalRegistry,\n }: CreateJsonSchemaTransformObjectOptions): SwaggerTransformObject =>\n (input) => {\n if ('swaggerObject' in input) {\n console.warn('This package currently does not support component references for Swagger 2.0')\n return input.swaggerObject\n }\n\n const inputSchemas = zodRegistryToJson(schemaRegistry, 'input')\n const outputSchemas = zodRegistryToJson(schemaRegistry, 'output')\n\n for (const key in outputSchemas) {\n if (inputSchemas[key]) {\n throw new Error(\n `Collision detected for schema \"${key}\". The is already an input schema with the same name.`,\n )\n }\n }\n\n return {\n ...input.openapiObject,\n components: {\n ...input.openapiObject.components,\n schemas: {\n ...input.openapiObject.components?.schemas,\n ...inputSchemas,\n ...outputSchemas,\n },\n },\n } as ReturnType<SwaggerTransformObject>\n }\n\nexport const jsonSchemaTransformObject: SwaggerTransformObject = createJsonSchemaTransformObject({})\n\nexport const validatorCompiler: FastifySchemaCompiler<z.ZodTypeAny> =\n ({ schema }) =>\n (data) => {\n const result = schema.safeParse(data)\n if (result.error) {\n return { error: createValidationError(result.error) as unknown as Error }\n }\n\n return { value: result.data }\n }\n\nfunction resolveSchema(maybeSchema: z.ZodTypeAny | { properties: z.ZodTypeAny }): z.ZodTypeAny {\n if ('safeParse' in maybeSchema) {\n return maybeSchema\n }\n if ('properties' in maybeSchema) {\n return maybeSchema.properties\n }\n throw new InvalidSchemaError(JSON.stringify(maybeSchema))\n}\n\ntype ReplacerFunction = (this: any, key: string, value: any) => any\n\nexport type ZodSerializerCompilerOptions = {\n replacer?: ReplacerFunction\n}\n\nexport const createSerializerCompiler =\n (\n options?: ZodSerializerCompilerOptions,\n ): FastifySerializerCompiler<z.ZodTypeAny | { properties: z.ZodTypeAny }> =>\n ({ schema: maybeSchema, method, url }) =>\n (data) => {\n const schema = resolveSchema(maybeSchema)\n\n const result = schema.safeParse(data)\n if (result.error) {\n throw new ResponseSerializationError(method, url, { cause: result.error })\n }\n\n return JSON.stringify(result.data, options?.replacer)\n }\n\nexport const serializerCompiler: ReturnType<typeof createSerializerCompiler> =\n createSerializerCompiler({})\n\n/**\n * FastifyPluginCallbackZod with Zod automatic type inference\n *\n * @example\n * ```typescript\n * import { FastifyPluginCallbackZod } from \"fastify-type-provider-zod\"\n *\n * const plugin: FastifyPluginCallbackZod = (fastify, options, done) => {\n * done()\n * }\n * ```\n */\nexport type FastifyPluginCallbackZod<\n Options extends FastifyPluginOptions = Record<never, never>,\n Server extends RawServerBase = RawServerDefault,\n> = FastifyPluginCallback<Options, Server, ZodTypeProvider>\n\n/**\n * FastifyPluginAsyncZod with Zod automatic type inference\n *\n * @example\n * ```typescript\n * import { FastifyPluginAsyncZod } from \"fastify-type-provider-zod\"\n *\n * const plugin: FastifyPluginAsyncZod = async (fastify, options) => {\n * }\n * ```\n */\nexport type FastifyPluginAsyncZod<\n Options extends FastifyPluginOptions = Record<never, never>,\n Server extends RawServerBase = RawServerDefault,\n> = FastifyPluginAsync<Options, Server, ZodTypeProvider>\n"],"names":["z","zodSchemaToJson","zodRegistryToJson","createValidationError","InvalidSchemaError","ResponseSerializationError"],"mappings":"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"}