{"version":3,"file":"zod-to-json.cjs","sources":["../../src/zod-to-json.ts"],"sourcesContent":["import type {\n  $ZodDate,\n  $ZodUndefined,\n  $ZodUnion,\n  JSONSchema,\n  JSONSchemaGenerator,\n} from 'zod/v4/core'\nimport { $ZodRegistry, $ZodType, toJSONSchema } from 'zod/v4/core'\nimport type { OASVersion } from './json-to-oas'\n\nconst getSchemaId = (id: string, io: 'input' | 'output') => {\n  return io === 'input' ? `${id}Input` : id\n}\n\nconst getReferenceUri = (id: string, io: 'input' | 'output') => {\n  return `#/components/schemas/${getSchemaId(id, io)}`\n}\n\nfunction isZodDate(entity: unknown): entity is $ZodDate {\n  return entity instanceof $ZodType && entity._zod.def.type === 'date'\n}\n\nfunction isZodUnion(entity: unknown): entity is $ZodUnion {\n  return entity instanceof $ZodType && entity._zod.def.type === 'union'\n}\n\nfunction isZodUndefined(entity: unknown): entity is $ZodUndefined {\n  return entity instanceof $ZodType && entity._zod.def.type === 'undefined'\n}\n\nconst getOverride = (\n  ctx: {\n    zodSchema: $ZodType\n    jsonSchema: JSONSchema.BaseSchema\n  },\n  io: 'input' | 'output',\n) => {\n  if (isZodUnion(ctx.zodSchema)) {\n    // Filter unrepresentable types in unions\n    // TODO: Should be fixed upstream and not merged in this plugin.\n    // Remove when passed: https://github.com/colinhacks/zod/pull/5013\n    ctx.jsonSchema.anyOf = ctx.jsonSchema.anyOf?.filter((schema) => Object.keys(schema).length > 0)\n  }\n\n  if (isZodDate(ctx.zodSchema)) {\n    // Allow dates to be represented as strings in output schemas\n    if (io === 'output') {\n      ctx.jsonSchema.type = 'string'\n      ctx.jsonSchema.format = 'date-time'\n    }\n  }\n\n  if (isZodUndefined(ctx.zodSchema)) {\n    // Allow undefined to be represented as null in output schemas\n    if (io === 'output') {\n      ctx.jsonSchema.type = 'null'\n    }\n  }\n}\n\nexport interface ZodToJsonConfig {\n  target?: JSONSchemaGenerator['target']\n}\n\nexport const zodSchemaToJson: (\n  zodSchema: $ZodType,\n  registry: $ZodRegistry<{ id?: string }>,\n  io: 'input' | 'output',\n  oasVersion: OASVersion,\n  config?: ZodToJsonConfig,\n) => JSONSchema.BaseSchema = (zodSchema, registry, io, oasVersion, config = {}) => {\n  const defaultTarget =\n    oasVersion === '3.0' ? 'openapi-3.0' : ('draft-2020-12' satisfies JSONSchemaGenerator['target'])\n  const target = config?.target ?? defaultTarget\n  const schemaRegistryEntry = registry.get(zodSchema)\n\n  /**\n   * Checks whether the provided schema is registered in the given registry.\n   * If it is present and has an `id`, it can be referenced as component.\n   *\n   * @see https://github.com/turkerdev/fastify-type-provider-zod/issues/173\n   */\n  if (schemaRegistryEntry?.id) {\n    return {\n      $ref: getReferenceUri(schemaRegistryEntry.id, io),\n    }\n  }\n\n  /**\n   * Unfortunately, at the time of writing, there is no way to generate a schema with `$ref`\n   * using `toJSONSchema` and a zod schema.\n   *\n   * As a workaround, we create a zod registry containing only the specific schema we want to convert.\n   *\n   * @see https://github.com/colinhacks/zod/issues/4281\n   */\n  const tempID = 'GEN'\n  const tempRegistry = new $ZodRegistry<{ id?: string }>()\n  tempRegistry.add(zodSchema, { id: tempID })\n\n  const {\n    schemas: { [tempID]: result },\n  } = toJSONSchema(tempRegistry, {\n    target,\n    metadata: registry,\n    io,\n    unrepresentable: 'any',\n    cycles: 'ref',\n    reused: 'inline',\n\n    /**\n     * The uri option only allows customizing the base path of the `$ref`, and it automatically appends a path to it.\n     * As a workaround, we set a placeholder that looks something like this:\n     *\n     * |       marker          | always added by zod | meta.id |\n     * |__SCHEMA__PLACEHOLDER__|      #/$defs/       | User    |\n     *\n     * @example `__SCHEMA__PLACEHOLDER__#/$defs/User\"`\n     * @example `__SCHEMA__PLACEHOLDER__#/$defs/Group\"`\n     *\n     * @see jsonSchemaReplaceRef\n     * @see https://github.com/colinhacks/zod/issues/4750\n     */\n    uri: () => `__SCHEMA__PLACEHOLDER__`,\n    override: (ctx) => getOverride(ctx, io),\n  })\n\n  const jsonSchema = { ...result }\n  delete jsonSchema.id\n\n  // Helper to normalize whatever Zod put after the placeholder into just the ID\n  const normalizeId = (raw: string) =>\n    raw.replace(/^#\\/(?:\\$defs|definitions|components\\/schemas)\\//, '')\n\n  /**\n   * Replace the previous generated placeholders with the final `$ref` value\n   */\n  const jsonSchemaReplaceRef = JSON.stringify(jsonSchema).replaceAll(\n    /\"__SCHEMA__PLACEHOLDER__(?:(?:#\\/(?:\\$defs|definitions|components\\/schemas)\\/))?([^\"]+)\"/g,\n    (_, raw) => {\n      const id = normalizeId(raw)\n      return `\"${getReferenceUri(id, io)}\"`\n    },\n  )\n\n  return JSON.parse(jsonSchemaReplaceRef) as typeof result\n}\n\nexport const zodRegistryToJson: (\n  registry: $ZodRegistry<{ id?: string }>,\n  io: 'input' | 'output',\n  config?: ZodToJsonConfig,\n) => Record<string, JSONSchema.BaseSchema> = (registry, io, config = {}) => {\n  const { target = 'draft-2020-12' } = config\n  const result = toJSONSchema(registry, {\n    target,\n    io,\n    unrepresentable: 'any',\n    cycles: 'ref',\n    reused: 'inline',\n    uri: (id) => getReferenceUri(id, io),\n    override: (ctx) => getOverride(ctx, io),\n  }).schemas\n\n  const jsonSchemas: Record<string, JSONSchema.BaseSchema> = {}\n  for (const id in result) {\n    const jsonSchema = { ...result[id] }\n\n    delete jsonSchema.id\n\n    jsonSchemas[getSchemaId(id, io)] = jsonSchema\n  }\n\n  return jsonSchemas\n}\n"],"names":["$ZodType","$ZodRegistry","toJSONSchema"],"mappings":"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"}