"use strict"; var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const fp = require("fastify-plugin"); const api = require("zod-openapi/api"); const fastJsonStringify = require("fast-json-stringify"); const zodOpenapi = require("zod-openapi"); const error = require("@fastify/error"); const _interopDefaultCompat = (e) => e && typeof e === "object" && "default" in e ? e : { default: e }; const fp__default = /* @__PURE__ */ _interopDefaultCompat(fp); const fastJsonStringify__default = /* @__PURE__ */ _interopDefaultCompat(fastJsonStringify); const FASTIFY_ZOD_OPENAPI_CONFIG = Symbol("fastify-zod-openapi-config"); const FASTIFY_ZOD_OPENAPI_COMPONENTS = Symbol( "fastify-zod-openapi-components" ); const fastifyZodOpenApi = async (fastify, opts) => { const components = api.getDefaultComponents(opts.components); fastify.addHook("onRoute", ({ schema }) => { if (!schema || schema.hide) { return; } schema[FASTIFY_ZOD_OPENAPI_CONFIG] ?? (schema[FASTIFY_ZOD_OPENAPI_CONFIG] = { components, documentOpts: opts.documentOpts }); }); }; const fastifyZodOpenApiPlugin = fp__default.default(fastifyZodOpenApi, { name: "fastify-zod-openapi" }); class RequestValidationError extends Error { constructor(keyword, instancePath, schemaPath, message, params) { super(message, { cause: params.issue }); __publicField(this, "cause"); this.keyword = keyword; this.instancePath = instancePath; this.schemaPath = schemaPath; this.message = message; this.params = params; } } class ResponseSerializationError extends error.createError( "FST_ERR_RESPONSE_SERIALIZATION", "Response does not match the schema", 500 ) { constructor(method, url, options) { super(); __publicField(this, "cause"); this.method = method; this.url = url; this.cause = options.cause; } } const createSerializerCompiler = (opts) => ({ schema, method, url }) => { let stringify = opts == null ? void 0 : opts.stringify; if (!stringify) { const { schema: jsonSchema, components } = zodOpenapi.createSchema(schema, { components: opts == null ? void 0 : opts.components, componentRefPath: "#/definitions/" }); const maybeDefinitions = components ? { definitions: components } : void 0; stringify = fastJsonStringify__default.default({ ...jsonSchema, ...maybeDefinitions }); } return (value) => { const result = schema.safeParse(value); if (!result.success) { throw new ResponseSerializationError(method, url, { cause: result.error }); } return stringify(result.data); }; }; const serializerCompiler = createSerializerCompiler(); const isZodType = (object) => { var _a; return Boolean( object && // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access ((_a = Object.getPrototypeOf(object == null ? void 0 : object.constructor)) == null ? void 0 : _a.name) === "ZodType" ); }; const isZodObject = (object) => { var _a; return Boolean(object && ((_a = object == null ? void 0 : object.constructor) == null ? void 0 : _a.name) === "ZodObject"); }; const createParams = (querystring, type, components, path, doucmentOpts) => Object.entries(querystring.shape).reduce( (acc, [key, value]) => { const parameter = api.createParamOrRef( value, components, [...path, key], type, key, doucmentOpts ); if ("$ref" in parameter || !parameter.schema) { throw new Error("References not supported"); } acc[key] = { ...parameter.schema, ...parameter.required && { required: true } }; return acc; }, {} ); const createResponseSchema = (schema, components, path, documentOpts) => { if (isZodType(schema)) { return api.createMediaTypeSchema( schema, components, "output", [...path, "schema"], documentOpts ); } return schema; }; const createContent = (content, components, path, documentOpts) => { if (typeof content !== "object" || content == null) { return content; } return Object.entries(content).reduce( (acc, [key, value]) => { if (typeof value === "object" && value !== null && "schema" in value) { const schema = createResponseSchema( value.schema, components, [...path, "schema"], documentOpts ); acc[key] = { ...value, schema }; return acc; } acc[key] = value; return acc; }, {} ); }; const createResponse = (response, components, path, documentOpts) => { if (typeof response !== "object" || response == null) { return response; } return Object.entries(response).reduce( (acc, [key, value]) => { if (isZodType(value)) { acc[key] = api.createMediaTypeSchema( value, components, "output", [...path, key], documentOpts ); return acc; } if (typeof value === "object" && value !== null && "content" in value) { const content = createContent( value.content, components, [...path, "content"], documentOpts ); acc[key] = { ...value, content }; return acc; } acc[key] = value; return acc; }, {} ); }; const fastifyZodOpenApiTransform = ({ schema, url, ...opts }) => { var _a, _b; if (!schema || schema.hide) { return { schema, url }; } const { response, headers, querystring, body, params } = schema; if (!("openapiObject" in opts)) { throw new Error("openapiObject was not found in the options"); } const config = schema[FASTIFY_ZOD_OPENAPI_CONFIG]; if (!config) { throw new Error("Please register the fastify-zod-openapi plugin"); } const { components, documentOpts } = config; (_a = opts.openapiObject)[FASTIFY_ZOD_OPENAPI_COMPONENTS] ?? (_a[FASTIFY_ZOD_OPENAPI_COMPONENTS] = config.components); if (opts.openapiObject.openapi) { components.openapi = opts.openapiObject.openapi; } (_b = opts.openapiObject)[FASTIFY_ZOD_OPENAPI_COMPONENTS] ?? (_b[FASTIFY_ZOD_OPENAPI_COMPONENTS] = components); const transformedSchema = { ...schema }; if (isZodType(body)) { transformedSchema.body = api.createMediaTypeSchema( body, components, "input", [url, "body"], documentOpts ); } const maybeResponse = createResponse( response, components, [url, "response"], documentOpts ); if (maybeResponse) { transformedSchema.response = maybeResponse; } if (isZodObject(querystring)) { transformedSchema.querystring = createParams( querystring, "query", components, [url, "querystring"], documentOpts ); } if (isZodObject(params)) { transformedSchema.params = createParams(params, "path", components, [ url, "params" ]); } if (isZodObject(headers)) { transformedSchema.headers = createParams(headers, "header", components, [ url, "headers" ]); } return { schema: transformedSchema, url }; }; const fastifyZodOpenApiTransformObject = (opts) => { if ("swaggerObject" in opts) { return opts.swaggerObject; } const components = opts.openapiObject[FASTIFY_ZOD_OPENAPI_COMPONENTS]; if (!components) { return opts.openapiObject; } return { ...opts.openapiObject, components: api.createComponents( opts.openapiObject.components ?? {}, components ) }; }; const validatorCompiler = ({ schema }) => (value) => { const result = schema.safeParse(value); if (!result.success) { return { error: result.error.errors.map( (issue) => new RequestValidationError( issue.code, `/${issue.path.join("/")}`, `#/${issue.path.join("/")}/${issue.code}`, issue.message, { issue, error: result.error } ) ) // Types are wrong https://github.com/fastify/fastify/pull/5787 }; } return { value: result.data }; }; exports.FASTIFY_ZOD_OPENAPI_COMPONENTS = FASTIFY_ZOD_OPENAPI_COMPONENTS; exports.FASTIFY_ZOD_OPENAPI_CONFIG = FASTIFY_ZOD_OPENAPI_CONFIG; exports.RequestValidationError = RequestValidationError; exports.ResponseSerializationError = ResponseSerializationError; exports.createContent = createContent; exports.createParams = createParams; exports.createResponse = createResponse; exports.createResponseSchema = createResponseSchema; exports.createSerializerCompiler = createSerializerCompiler; exports.fastifyZodOpenApiPlugin = fastifyZodOpenApiPlugin; exports.fastifyZodOpenApiTransform = fastifyZodOpenApiTransform; exports.fastifyZodOpenApiTransformObject = fastifyZodOpenApiTransformObject; exports.isZodObject = isZodObject; exports.isZodType = isZodType; exports.serializerCompiler = serializerCompiler; exports.validatorCompiler = validatorCompiler;