@kubb/ast 5.8.0 → 5.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/constants.ts","../src/guards.ts","../src/defineNode.ts","../src/nodes/code.ts","../src/nodes/content.ts","../src/utils/extractStringsFromNodes.ts","../src/utils/combineFileMembers.ts","../src/nodes/file.ts","../src/nodes/input.ts","../src/nodes/requestBody.ts","../src/nodes/operation.ts","../src/nodes/output.ts","../src/optionality.ts","../src/nodes/parameter.ts","../src/nodes/property.ts","../src/nodes/response.ts","../src/nodes/schema.ts","../src/registry.ts","../src/visitor.ts","../src/defineMacro.ts","../src/createPrinter.ts","../src/utils/refs.ts","../../../internals/utils/src/promise.ts","../src/utils/schemaGraph.ts","../src/utils/schemaProperties.ts","../src/factory.ts","../src/exports.ts"],"sourcesContent":["import type { SchemaType } from './nodes/schema.ts'\n\n/**\n * Traversal depth for AST visitor utilities.\n *\n * - `'shallow'` recurses through every node except nested `Schema` subtrees, which it treats as\n * leaves: a schema node itself is visited, but its children are not.\n * - `'deep'` recursively visits all descendant nodes, including schema subtrees.\n */\nexport type VisitorDepth = 'shallow' | 'deep'\n\nexport const visitorDepths = {\n shallow: 'shallow',\n deep: 'deep',\n} as const satisfies Record<VisitorDepth, VisitorDepth>\n\n/**\n * Schema type discriminators used by all AST schema nodes.\n *\n * Each value is a stable discriminator across the AST (for example `schema.type === schemaTypes.object`).\n */\nexport const schemaTypes = {\n /**\n * Text value.\n */\n string: 'string',\n /**\n * Floating-point number (`float`, `double`).\n */\n number: 'number',\n /**\n * Whole number (`int32`). Use `bigint` for `int64`.\n */\n integer: 'integer',\n /**\n * 64-bit integer (`int64`). Only used when `integerType` is set to `'bigint'`.\n */\n bigint: 'bigint',\n /**\n * Boolean value.\n */\n boolean: 'boolean',\n /**\n * Explicit null value.\n */\n null: 'null',\n /**\n * Any value (no type restriction).\n */\n any: 'any',\n /**\n * Unknown value (must be narrowed before usage).\n */\n unknown: 'unknown',\n /**\n * No return value (`void`).\n */\n void: 'void',\n /**\n * Object with named properties.\n */\n object: 'object',\n /**\n * Sequential list of items.\n */\n array: 'array',\n /**\n * Fixed-length list with position-specific items.\n */\n tuple: 'tuple',\n /**\n * \"One of\" multiple schema members.\n */\n union: 'union',\n /**\n * \"All of\" multiple schema members.\n */\n intersection: 'intersection',\n /**\n * Enum schema.\n */\n enum: 'enum',\n /**\n * Reference to another schema.\n */\n ref: 'ref',\n /**\n * Calendar date (for example `2026-03-24`).\n */\n date: 'date',\n /**\n * Date-time value (for example `2026-03-24T09:00:00Z`).\n */\n datetime: 'datetime',\n /**\n * Time-only value (for example `09:00:00`).\n */\n time: 'time',\n /**\n * UUID value.\n */\n uuid: 'uuid',\n /**\n * Email address value.\n */\n email: 'email',\n /**\n * URL value.\n */\n url: 'url',\n /**\n * IPv4 address value.\n */\n ipv4: 'ipv4',\n /**\n * IPv6 address value.\n */\n ipv6: 'ipv6',\n /**\n * Binary/blob value.\n */\n blob: 'blob',\n /**\n * Impossible value (`never`).\n */\n never: 'never',\n} as const satisfies Record<SchemaType, SchemaType>\n","import type { HttpOperationNode, OperationNode } from './nodes/operation.ts'\nimport type { SchemaNode, SchemaNodeByType } from './nodes/schema.ts'\n\n/**\n * Narrows a `SchemaNode` to the variant that matches `type`.\n *\n * @example\n * ```ts\n * const schema = createSchema({ type: 'string' })\n * const stringNode = narrowSchema(schema, 'string') // StringSchemaNode | null\n * ```\n */\nexport function narrowSchema<T extends SchemaNode['type']>(node: SchemaNode | undefined, type: T): SchemaNodeByType[T] | null {\n return node?.type === type ? (node as SchemaNodeByType[T]) : null\n}\n\n/**\n * Narrows an `OperationNode` to an `HttpOperationNode` so `method` and `path` are present.\n *\n * @example\n * ```ts\n * if (isHttpOperationNode(node)) {\n * console.log(node.method, node.path)\n * }\n * ```\n */\nexport function isHttpOperationNode(node: OperationNode): node is HttpOperationNode {\n return node.protocol === 'http' || (node.method !== undefined && node.path !== undefined)\n}\n","import type { BaseNode, NodeKind } from './nodes/base.ts'\n\n/**\n * Visitor callback names, one per traversable node kind, in traversal order.\n * Kept in sync with the keys of `Visitor` in `visitor.ts`.\n */\nexport const visitorKeys = ['input', 'output', 'operation', 'schema', 'property', 'parameter', 'response'] as const\n\n/**\n * One of the {@link visitorKeys} callback names.\n */\nexport type VisitorKey = (typeof visitorKeys)[number]\n\n/**\n * Distributive `Omit` that preserves each member of a union.\n *\n * @example\n * ```ts\n * type A = { kind: 'a'; keep: string; drop: number }\n * type B = { kind: 'b'; keep: boolean; drop: number }\n * type Result = DistributiveOmit<A | B, 'drop'>\n * // -> { kind: 'a'; keep: string } | { kind: 'b'; keep: boolean }\n * ```\n */\nexport type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never\n\n/**\n * Builds a type guard that matches nodes of the given `kind`.\n */\nfunction isKind<T extends BaseNode>(kind: NodeKind) {\n return (node: unknown): node is T => (node as BaseNode | undefined)?.kind === kind\n}\n\n/**\n * The single definition derived from one {@link defineNode} call: the node's\n * `create` builder, its `is` guard, and the traversal metadata the registry\n * collects into the visitor tables.\n */\nexport type NodeDef<TNode extends BaseNode = BaseNode, TInput = never> = {\n /**\n * Node discriminator this definition owns.\n */\n kind: NodeKind\n /**\n * Builds a node from its input, applying `defaults` and the optional `build` hook.\n */\n create: (input: TInput) => TNode\n /**\n * Type guard matching this node kind.\n */\n is: (node: unknown) => node is TNode\n /**\n * Child node fields in traversal order. Feeds `VISITOR_KEYS`.\n */\n children?: ReadonlyArray<string>\n /**\n * Visitor callback name. Feeds `VISITOR_KEY_BY_KIND`.\n */\n visitorKey?: VisitorKey\n}\n\ntype DefineNodeConfig<TNode extends BaseNode, TInput, TBuilt extends object> = {\n kind: TNode['kind']\n defaults?: Partial<TNode>\n build?: (input: TInput) => TBuilt\n children?: ReadonlyArray<string>\n visitorKey?: VisitorKey\n}\n\n/**\n * Defines a node once and derives its `create` builder, `is` guard, and traversal\n * metadata. `create` merges `defaults`, the `build` hook (or the raw input), and the\n * `kind`, so node construction lives in one place without scattered `as` casts.\n *\n * @example Simple node\n * ```ts\n * const importDef = defineNode<ImportNode>({ kind: 'Import' })\n * const createImport = importDef.create\n * ```\n *\n * @example Node with a build hook\n * ```ts\n * const propertyDef = defineNode<PropertyNode, UserPropertyNode>({\n * kind: 'Property',\n * build: (props) => ({ ...props, required: props.required ?? false }),\n * children: ['schema'],\n * visitorKey: 'property',\n * })\n * ```\n */\nexport function defineNode<TNode extends BaseNode, TInput = Omit<TNode, 'kind'>, TBuilt extends object = Omit<TNode, 'kind'>>(\n config: DefineNodeConfig<TNode, TInput, TBuilt>,\n): NodeDef<TNode, TInput> {\n const { kind, defaults, build, children, visitorKey } = config\n\n function create(input: TInput): TNode {\n const base = build ? build(input) : input\n // `kind` is written first so the discriminant lands at a fixed in-object offset for every node\n // of this kind. Hot dispatch paths (`transform`, `walk`, the parser printers) read `node.kind`\n // constantly; a trailing-only `kind` floats its offset with each node's field count and turns\n // those reads megamorphic. The post-spread reassignment keeps `kind` authoritative when an input\n // carries a (wrong) `kind`: it overwrites the offset-0 slot in place without reshaping the node.\n const built = { kind, ...defaults, ...(base as object) }\n const node = built as TNode\n node.kind = kind\n return node\n }\n\n return { kind, create, is: isKind<TNode>(kind), children, visitorKey }\n}\n","import { defineNode } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\n\n/**\n * JSDoc documentation metadata attached to code declarations.\n */\nexport type JSDocNode = {\n /**\n * JSDoc comment lines. `undefined` entries are filtered out during rendering.\n *\n * @example\n * ```ts\n * ['@description A pet resource', '@deprecated']\n * ```\n */\n comments?: Array<string | undefined>\n}\n\n/**\n * AST node representing a TypeScript `const` declaration.\n *\n * Mirrors the props of the `Const` component from `@kubb/renderer-jsx`.\n * The `children` prop of the component is represented as `nodes`.\n *\n * @example\n * ```ts\n * createConst({ name: 'pet', export: true, asConst: true })\n * // export const pet = ... as const\n * ```\n */\nexport type ConstNode = BaseNode & {\n kind: 'Const'\n /**\n * Name of the constant declaration.\n */\n name: string\n /**\n * Whether the declaration should be exported.\n */\n export?: boolean | null\n /**\n * Explicit type annotation.\n *\n * @example Type reference\n * `'Pet'`\n */\n type?: string | null\n /**\n * JSDoc documentation metadata.\n */\n JSDoc?: JSDocNode | null\n /**\n * Whether to append `as const` to the declaration.\n */\n asConst?: boolean | null\n /**\n * Child nodes representing the value of the constant (children of the `Const` component).\n * Each entry is a {@link CodeNode}. Use {@link TextNode} for raw string content.\n */\n nodes?: Array<CodeNode>\n}\n\n/**\n * AST node representing a TypeScript `type` alias declaration.\n *\n * Mirrors the props of the `Type` component from `@kubb/renderer-jsx`.\n * The `children` prop of the component is represented as `nodes`.\n *\n * @example\n * ```ts\n * createType({ name: 'Pet', export: true })\n * // export type Pet = ...\n * ```\n */\nexport type TypeNode = BaseNode & {\n kind: 'Type'\n /**\n * Name of the type alias.\n */\n name: string\n /**\n * Whether the declaration should be exported.\n */\n export?: boolean | null\n /**\n * JSDoc documentation metadata.\n */\n JSDoc?: JSDocNode | null\n /**\n * Child nodes representing the type body (children of the `Type` component).\n * Each entry is a {@link CodeNode}. Use {@link TextNode} for raw string content.\n */\n nodes?: Array<CodeNode>\n}\n\n/**\n * AST node representing a TypeScript `function` declaration.\n *\n * Mirrors the props of the `Function` component from `@kubb/renderer-jsx`.\n * The `children` prop of the component is represented as `nodes`.\n *\n * @example\n * ```ts\n * createFunction({ name: 'getPet', export: true, async: true, returnType: 'Pet' })\n * // export async function getPet(): Promise<Pet> { ... }\n * ```\n */\nexport type FunctionNode = BaseNode & {\n kind: 'Function'\n /**\n * Name of the function.\n */\n name: string\n /**\n * Whether the function is a default export.\n */\n default?: boolean | null\n /**\n * Function parameter list as a pre-rendered string, written verbatim between the parentheses.\n *\n * @example\n * `'id: string, config: Config = {}'`\n */\n params?: string | null\n /**\n * Whether the function should be exported.\n */\n export?: boolean | null\n /**\n * Whether the function is async. When `true`, the return type is wrapped in `Promise<>`.\n */\n async?: boolean | null\n /**\n * TypeScript generic type parameters.\n *\n * @example Constrained generics\n * `['T', 'U extends string']`\n */\n generics?: string | Array<string> | null\n /**\n * Return type annotation.\n *\n * @example Type reference\n * `'Pet'`\n */\n returnType?: string | null\n /**\n * JSDoc documentation metadata.\n */\n JSDoc?: JSDocNode | null\n /**\n * Child nodes representing the function body (children of the `Function` component).\n * Each entry is a {@link CodeNode}. Use {@link TextNode} for raw string content.\n */\n nodes?: Array<CodeNode>\n}\n\n/**\n * AST node representing a TypeScript arrow function (`const name = () => { ... }`).\n *\n * Mirrors the props of the `Function.Arrow` component from `@kubb/renderer-jsx`.\n * The `children` prop of the component is represented as `nodes`.\n *\n * @example\n * ```ts\n * createArrowFunction({ name: 'getPet', export: true, singleLine: true })\n * // export const getPet = () => ...\n * ```\n */\nexport type ArrowFunctionNode = Omit<FunctionNode, 'kind'> & {\n kind: 'ArrowFunction'\n /**\n * Render the arrow function body as a single-line expression.\n */\n singleLine?: boolean | null\n}\n\n/**\n * AST node representing a raw text/string fragment in the source output.\n *\n * Used instead of bare `string` values so that all entries in `nodes` arrays\n * are typed `CodeNode` objects rather than a mixed `CodeNode | string` union.\n *\n * @example\n * ```ts\n * createText('return fetch(id)')\n * // { kind: 'Text', value: 'return fetch(id)' }\n * ```\n */\nexport type TextNode = BaseNode & {\n kind: 'Text'\n /**\n * The raw string content.\n */\n value: string\n}\n\n/**\n * AST node representing a blank line in the source output.\n *\n * Corresponds to `<br/>` in JSX components. `printNodes` turns a `Break` between two\n * statements into one blank line. Consecutive breaks, and breaks at the start or end of\n * the list, are folded away, so a `Break` never produces more than one blank line.\n *\n * @example\n * ```ts\n * createBreak()\n * // { kind: 'Break' }\n * ```\n */\nexport type BreakNode = BaseNode & {\n kind: 'Break'\n}\n\n/**\n * AST node representing a raw JSX fragment in the source output.\n *\n * Mirrors the `Jsx` component from `@kubb/renderer-jsx`. Embeds raw JSX/TSX markup\n * (including fragments `<>…</>`) directly in generated code.\n *\n * @example\n * ```ts\n * createJsx('<>\\n <a href={href}>Open</a>\\n</>')\n * // { kind: 'Jsx', value: '<>\\n <a href={href}>Open</a>\\n</>' }\n * ```\n */\nexport type JsxNode = BaseNode & {\n kind: 'Jsx'\n /**\n * The raw JSX string content.\n */\n value: string\n}\n\n/**\n * Union of all code-generation AST nodes.\n *\n * These nodes mirror the JSX components from `@kubb/renderer-jsx` and are used as\n * structured children in {@link SourceNode.nodes}.\n */\nexport type CodeNode = ConstNode | TypeNode | FunctionNode | ArrowFunctionNode | TextNode | BreakNode | JsxNode\n\n/**\n * Definition for the {@link ConstNode}.\n */\nexport const constDef = defineNode<ConstNode>({ kind: 'Const' })\n\n/**\n * Definition for the {@link TypeNode}.\n */\nexport const typeDef = defineNode<TypeNode>({ kind: 'Type' })\n\n/**\n * Definition for the {@link FunctionNode}.\n */\nexport const functionDef = defineNode<FunctionNode>({ kind: 'Function' })\n\n/**\n * Definition for the {@link ArrowFunctionNode}.\n */\nexport const arrowFunctionDef = defineNode<ArrowFunctionNode>({ kind: 'ArrowFunction' })\n\n/**\n * Definition for the {@link TextNode}.\n */\nexport const textDef = defineNode<TextNode, string>({ kind: 'Text', build: (value) => ({ value }) })\n\n/**\n * Definition for the {@link BreakNode}.\n */\nexport const breakDef = defineNode<BreakNode, void>({ kind: 'Break', build: () => ({}) })\n\n/**\n * Definition for the {@link JsxNode}.\n */\nexport const jsxDef = defineNode<JsxNode, string>({ kind: 'Jsx', build: (value) => ({ value }) })\n\n/**\n * Creates a `ConstNode` representing a TypeScript `const` declaration.\n *\n * @example Exported constant with type and `as const`\n * ```ts\n * createConst({ name: 'pets', export: true, type: 'Pet[]', asConst: true })\n * // export const pets: Pet[] = ... as const\n * ```\n */\nexport const createConst = constDef.create\n\n/**\n * Creates a `TypeNode` representing a TypeScript `type` alias declaration.\n *\n * @example\n * ```ts\n * createType({ name: 'Pet', export: true })\n * // export type Pet = ...\n * ```\n */\nexport const createType = typeDef.create\n\n/**\n * Creates a `FunctionNode` representing a TypeScript `function` declaration.\n *\n * @example\n * ```ts\n * createFunction({ name: 'fetchPet', export: true, async: true, returnType: 'Pet' })\n * // export async function fetchPet(): Promise<Pet> { ... }\n * ```\n */\nexport const createFunction = functionDef.create\n\n/**\n * Creates an `ArrowFunctionNode` representing a TypeScript arrow function.\n *\n * @example\n * ```ts\n * createArrowFunction({ name: 'double', export: true, params: 'n: number', singleLine: true })\n * // export const double = (n: number) => ...\n * ```\n */\nexport const createArrowFunction = arrowFunctionDef.create\n\n/**\n * Creates a {@link TextNode} representing a raw string fragment in the source output.\n *\n * @example\n * ```ts\n * createText('return fetch(id)')\n * // { kind: 'Text', value: 'return fetch(id)' }\n * ```\n */\nexport const createText = textDef.create\n\n/**\n * Creates a {@link BreakNode} representing a line break in the source output.\n *\n * @example\n * ```ts\n * createBreak()\n * // { kind: 'Break' }\n * ```\n */\nexport function createBreak(): BreakNode {\n return breakDef.create()\n}\n\n/**\n * Creates a {@link JsxNode} representing a raw JSX fragment in the source output.\n *\n * @example\n * ```ts\n * createJsx('<>\\n <a href={href}>Open</a>\\n</>')\n * // { kind: 'Jsx', value: '<>\\n <a href={href}>Open</a>\\n</>' }\n * ```\n */\nexport const createJsx = jsxDef.create\n","import { defineNode } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\nimport type { SchemaNode } from './schema.ts'\n\n/**\n * AST node representing one content-type entry of a request body or response.\n *\n * There is one entry per content type declared in the spec (e.g. `application/json`,\n * `multipart/form-data`), and each entry holds its own body schema.\n *\n * @example\n * ```ts\n * const content: ContentNode = {\n * kind: 'Content',\n * contentType: 'application/json',\n * schema: createSchema({ type: 'string' }),\n * }\n * ```\n */\nexport type ContentNode = BaseNode & {\n /**\n * Node kind.\n */\n kind: 'Content'\n /**\n * The content type for this entry (e.g. `'application/json'`).\n */\n contentType: string\n /**\n * Body schema for this content type.\n */\n schema?: SchemaNode\n /**\n * Property keys to exclude from the generated type via `Omit<Type, Keys>`.\n * Set when a referenced schema has `readOnly`/`writeOnly` fields that should be omitted.\n */\n keysToOmit?: Array<string> | null\n}\n\n/**\n * Definition for the {@link ContentNode}.\n */\nexport const contentDef = defineNode<ContentNode>({\n kind: 'Content',\n children: ['schema'],\n})\n\n/**\n * Creates a `ContentNode` for a single request-body or response content type.\n */\nexport const createContent = contentDef.create\n","import type { CodeNode } from '../nodes/code.ts'\n\n/**\n * Extracts all string content from a `CodeNode` tree recursively.\n *\n * Collects text node values, identifier references in string fields (`params`, `generics`, `returnType`, `type`),\n * and nested node content. Used to build the full source string for import filtering.\n */\nexport function extractStringsFromNodes(nodes: Array<CodeNode> | undefined): string {\n if (!nodes?.length) return ''\n\n // Imperative single pass. The earlier `map().filter().join()` allocated a closure plus two\n // intermediate arrays per call, and this runs recursively over every code node during file\n // assembly, so the churn showed up in deopt traces. Appending directly keeps it flat.\n const collected: Array<string> = []\n\n for (const node of nodes) {\n // Backward-compat: compiled plugins may still pass bare strings at runtime\n if (typeof node === 'string') {\n if (node) collected.push(node as string)\n continue\n }\n if (node.kind === 'Text' || node.kind === 'Jsx') {\n if (node.value) collected.push(node.value)\n continue\n }\n if (node.kind === 'Break') continue\n\n const parts: Array<string> = []\n if ('params' in node && node.params) parts.push(node.params)\n if ('generics' in node && node.generics) parts.push(Array.isArray(node.generics) ? node.generics.join(', ') : node.generics)\n if ('returnType' in node && node.returnType) parts.push(node.returnType)\n if ('type' in node && typeof node.type === 'string') parts.push(node.type)\n\n const nested = extractStringsFromNodes(node.nodes)\n if (nested) parts.push(nested)\n\n if (parts.length) collected.push(parts.join('\\n'))\n }\n\n return collected.join('\\n')\n}\n","/**\n * File-member merging. `combineImports` and `combineExports` deduplicate and sort the import and\n * export entries of one file, while `combineSources` deduplicates source entries in original order.\n * `combineImports` also drops imports nothing references. This works on a file's members, not on\n * schema content.\n */\nimport type { ExportNode, ImportNode, SourceNode } from '../nodes/file.ts'\nimport { extractStringsFromNodes } from './extractStringsFromNodes.ts'\n\nconst IDENTIFIER_RUN = /[\\w$]+/g\n\n/**\n * How many imports a file needs before indexing the source beats scanning it once per name.\n */\nconst INDEX_ABOVE_IMPORTS = 128\n\ntype ImportNameItem = string | { propertyName: string; name?: string }\n\ntype FileMember = { name?: string | Array<unknown> | null; isTypeOnly?: boolean | null; path: string }\n\n/**\n * Returns the local binding an import name item introduces: the alias when there is one, else the\n * imported name.\n */\nexport function importLocalName(item: ImportNameItem): string {\n return typeof item === 'string' ? item : (item.name ?? item.propertyName)\n}\n\n/**\n * Computes a multi-level sort key for exports and imports:\n * non-array names first (wildcards/namespace aliases). Type-only before value. Alphabetical path. Unnamed before named.\n */\nfunction sortKey(node: FileMember): string {\n const isArray = Array.isArray(node.name) ? '1' : '0'\n const typeOnly = node.isTypeOnly ? '0' : '1'\n const hasName = node.name != null ? '1' : '0'\n const name = Array.isArray(node.name) ? node.name.toSorted().join('\\0') : (node.name ?? '')\n return `${isArray}:${typeOnly}:${node.path}:${hasName}:${name}`\n}\n\n/**\n * Sorts members by {@link sortKey}. Keys are computed once per node, not per comparison.\n */\nfunction sortMembers<TNode extends FileMember>(nodes: Array<TNode>): Array<TNode> {\n return nodes\n .map((node) => ({ node, key: sortKey(node) }))\n .sort((a, b) => (a.key < b.key ? -1 : a.key > b.key ? 1 : 0))\n .map(({ node }) => node)\n}\n\n/**\n * Returns a collector for array-named members. A member whose path and `isTypeOnly` were already\n * seen folds its names into that entry, otherwise it joins `result` as a new entry.\n */\nfunction mergeByPath<TNode extends FileMember>(result: Array<TNode>): (member: { node: TNode; names: Array<unknown> }) => void {\n const byPath = new Map<string, TNode>()\n\n return ({ node, names }) => {\n const key = `${node.path}:${node.isTypeOnly ?? false}`\n const existing = byPath.get(key)\n\n if (existing && Array.isArray(existing.name)) {\n existing.name = [...new Set([...existing.name, ...names])]\n return\n }\n\n const item = { ...node, name: names }\n result.push(item)\n byPath.set(key, item)\n }\n}\n\n/**\n * Deduplicates `SourceNode` objects by `name + isExportable + isTypeOnly`, keeping the first of each\n * key. Unnamed sources fall back to their extracted node strings as the name part of the key. Returns\n * the deduplicated array in original order.\n */\nexport function combineSources(sources: Array<SourceNode>): Array<SourceNode> {\n const seen = new Map<string, SourceNode>()\n for (const source of sources) {\n const nameKey = source.name ?? extractStringsFromNodes(source.nodes)\n const key = `${nameKey}:${source.isExportable ?? false}:${source.isTypeOnly ?? false}`\n if (!seen.has(key)) seen.set(key, source)\n }\n return [...seen.values()]\n}\n\n/**\n * Deduplicates and merges `ExportNode` objects by path and type.\n *\n * Named exports with the same path and `isTypeOnly` flag have their names merged into a single export.\n * Non-array exports are deduplicated by exact identity. Returns a sorted, deduplicated array.\n */\nexport function combineExports(exports: Array<ExportNode>): Array<ExportNode> {\n const result: Array<ExportNode> = []\n const merge = mergeByPath(result)\n // Deduplicates non-array exports by their exact identity\n const seen = new Set<string>()\n\n for (const curr of sortMembers(exports)) {\n const { name, path, isTypeOnly, asAlias } = curr\n\n if (Array.isArray(name)) {\n if (name.length) merge({ node: curr, names: [...new Set(name)] })\n continue\n }\n\n const key = `${path}:${name ?? ''}:${isTypeOnly ?? false}:${asAlias ?? ''}`\n if (!seen.has(key)) {\n result.push(curr)\n seen.add(key)\n }\n }\n\n return result\n}\n\n/**\n * Deduplicates and merges `ImportNode` objects, filtering out unused imports.\n *\n * Retains imports that are referenced in `source` or re-exported. Imports with the same path and\n * `isTypeOnly` flag have their names merged. Returns a sorted, deduplicated, filtered array.\n */\nexport function combineImports(imports: Array<ImportNode>, exports: Array<ExportNode>, source?: string): Array<ImportNode> {\n // Build a lookup of all exported names to retain imports that are re-exported\n const exportedNames = new Set(exports.flatMap((e) => (Array.isArray(e.name) ? e.name : e.name ? [e.name] : [])))\n // `createFile` re-runs on every merge into a file, so scanning the source once per import name\n // costs a heavily merged file that scan again for every fragment it already holds. Indexing pays\n // for itself there, and costs more than it saves on the small files the default output produces.\n const identifiers = source && imports.length > INDEX_ABOVE_IMPORTS ? new Set(source.match(IDENTIFIER_RUN)) : null\n\n // A name in the index is used. One that is not still might be, inside a longer identifier, so the\n // substring test stays behind it.\n const isUsed = (importName: string): boolean => !source || identifiers?.has(importName) || source.includes(importName) || exportedNames.has(importName)\n\n // Memoize object import names so the same logical (propertyName, name) pair always\n // reuses the same object reference. Set-based deduplication then works correctly.\n const importNameMemo = new Map<string, ImportNameItem>()\n const canonicalizeName = (n: ImportNameItem): ImportNameItem => {\n if (typeof n === 'string') return n\n const key = `${n.propertyName}:${n.name ?? ''}`\n if (!importNameMemo.has(key)) importNameMemo.set(key, n)\n return importNameMemo.get(key)!\n }\n\n // Paths that keep at least one used named import. A default import from such a path is retained\n // even when its binding can't be found in `source` e.g. a generated `client` default import\n // alongside `import type { Client } from <same path>`, where merged grouped output omits the body.\n const pathsWithUsedNamedImport = new Set<string>()\n for (const node of imports) {\n if (Array.isArray(node.name) && node.name.some((item) => isUsed(importLocalName(item)))) {\n pathsWithUsedNamedImport.add(node.path)\n }\n }\n\n const result: Array<ImportNode> = []\n const merge = mergeByPath(result)\n // Deduplicates non-array imports by their exact identity\n const seen = new Set<string>()\n\n for (const curr of sortMembers(imports)) {\n if (curr.path === curr.root) continue\n\n const { name, path, isTypeOnly } = curr\n\n if (Array.isArray(name)) {\n const names = [...new Set(name.map(canonicalizeName))].filter((item) => isUsed(importLocalName(item)))\n if (names.length) merge({ node: curr, names })\n continue\n }\n\n if (!isUsed(name) && !pathsWithUsedNamedImport.has(path)) continue\n\n const key = `${path}:${name}:${isTypeOnly ?? false}`\n if (!seen.has(key)) {\n result.push(curr)\n seen.add(key)\n }\n }\n\n return result\n}\n","import { hash } from 'node:crypto'\nimport path from 'node:path'\nimport { defineNode } from '../defineNode.ts'\nimport { combineExports, combineImports, combineSources, importLocalName } from '../utils/combineFileMembers.ts'\nimport { extractStringsFromNodes } from '../utils/extractStringsFromNodes.ts'\nimport type { BaseNode } from './base.ts'\nimport type { CodeNode } from './code.ts'\n\n/**\n * Supported file extensions.\n */\ntype Extname = '.ts' | '.js' | '.tsx' | '.json' | `.${string}`\n\ntype ImportName = string | Array<string | { propertyName: string; name?: string }>\n\n/**\n * Represents a language-agnostic import/dependency declaration.\n *\n * @example Named import (TypeScript: `import { useState } from 'react'`)\n * ```ts\n * createImport({ name: ['useState'], path: 'react' })\n * ```\n *\n * @example Default import (TypeScript: `import React from 'react'`)\n * ```ts\n * createImport({ name: 'React', path: 'react' })\n * ```\n *\n * @example Type-only import (TypeScript: `import type { FC } from 'react'`)\n * ```ts\n * createImport({ name: ['FC'], path: 'react', isTypeOnly: true })\n * ```\n *\n * @example Namespace import (TypeScript: `import * as React from 'react'`)\n * ```ts\n * createImport({ name: 'React', path: 'react', isNameSpace: true })\n * ```\n */\nexport type ImportNode = BaseNode & {\n kind: 'Import'\n /**\n * Import name(s) to be used.\n *\n * @example Named imports\n * `['useState']`\n *\n * @example Default import\n * `'React'`\n */\n name: ImportName\n /**\n * Path for the import.\n *\n * @example\n * `'@kubb/core'`\n */\n path: string\n /**\n * Add a type-only import prefix.\n * - `true` generates `import type { Type } from './path'`\n * - `false` generates `import { Type } from './path'`\n */\n isTypeOnly?: boolean | null\n /**\n * Import the entire module as a namespace.\n * - `true` generates `import * as Name from './path'`\n * - `false` generates a standard import\n */\n isNameSpace?: boolean | null\n /**\n * When set, the import path is resolved relative to this root.\n */\n root?: string | null\n}\n\n/**\n * Represents a language-agnostic export/public API declaration.\n *\n * @example Named export (TypeScript: `export { Pets } from './Pets'`)\n * ```ts\n * createExport({ name: ['Pets'], path: './Pets' })\n * ```\n *\n * @example Type-only export (TypeScript: `export type { Pet } from './Pet'`)\n * ```ts\n * createExport({ name: ['Pet'], path: './Pet', isTypeOnly: true })\n * ```\n *\n * @example Wildcard export (TypeScript: `export * from './utils'`)\n * ```ts\n * createExport({ path: './utils' })\n * ```\n *\n * @example Namespace alias (TypeScript: `export * as utils from './utils'`)\n * ```ts\n * createExport({ name: 'utils', path: './utils', asAlias: true })\n * ```\n */\nexport type ExportNode = BaseNode & {\n kind: 'Export'\n /**\n * Export name(s) to be used. When omitted, generates a wildcard export.\n *\n * @example Named exports\n * `['useState']`\n *\n * @example Single export\n * `'React'`\n */\n name?: string | Array<string> | null\n /**\n * Path for the export.\n *\n * @example\n * `'@kubb/core'`\n */\n path: string\n /**\n * Add a type-only export prefix.\n * - `true` generates `export type { Type } from './path'`\n * - `false` generates `export { Type } from './path'`\n */\n isTypeOnly?: boolean | null\n /**\n * Export as an aliased namespace.\n * - `true` generates `export * as aliasName from './path'`\n * - `false` generates a standard export\n */\n asAlias?: boolean | null\n}\n\n/**\n * Represents a fragment of source code within a file.\n *\n * @example Named exportable source\n * ```ts\n * createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')], isExportable: true, isIndexable: true })\n * ```\n *\n * @example Inline unnamed code block\n * ```ts\n * createSource({ nodes: [createText('const x = 1')] })\n * ```\n */\nexport type SourceNode = BaseNode & {\n kind: 'Source'\n /**\n * Optional name identifying this source (used for deduplication and barrel generation).\n */\n name?: string | null\n /**\n * Mark this source as a type-only export.\n */\n isTypeOnly?: boolean | null\n /**\n * Include the `export` keyword in the generated source.\n */\n isExportable?: boolean | null\n /**\n * Include this source in barrel/index file generation.\n */\n isIndexable?: boolean | null\n /**\n * Child nodes that make up this source fragment, in DOM order.\n * Use a {@link TextNode} for raw string content.\n */\n nodes?: Array<CodeNode>\n}\n\n/**\n * Represents a fully resolved file in the AST.\n *\n * Created via `createFile()`, which computes the `id`, `name`, and `extname` from the input\n * and deduplicates `imports`, `exports`, and `sources`.\n *\n * @example\n * ```ts\n * const file = createFile({\n * baseName: 'petStore.ts',\n * path: 'src/models/petStore.ts',\n * sources: [createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')], isExportable: true })],\n * imports: [createImport({ name: ['z'], path: 'zod' })],\n * exports: [createExport({ name: ['Pet'], path: './petStore' })],\n * })\n * // file.id = SHA256 hash of the path\n * // file.name = 'petStore'\n * // file.extname = '.ts'\n * ```\n */\nexport type FileNode<TMeta extends object = object> = BaseNode & {\n kind: 'File'\n /**\n * Unique identifier derived from a SHA256 hash of the file path. `createFile`\n * computes it, so callers do not need to provide it.\n */\n id: string\n /**\n * File name without extension, derived from `baseName`.\n *\n * @see https://nodejs.org/api/path.html#pathformatpathobject\n */\n name: string\n /**\n * File base name, including extension, shaped like `${name}${extname}`.\n *\n * @see https://nodejs.org/api/path.html#pathbasenamepath-suffix\n */\n baseName: `${string}.${string}`\n /**\n * Full qualified path to the file.\n */\n path: string\n /**\n * File extension extracted from `baseName`.\n */\n extname: Extname\n /**\n * Deduplicated list of source code fragments.\n */\n sources: Array<SourceNode>\n /**\n * Deduplicated list of import declarations.\n */\n imports: Array<ImportNode>\n /**\n * Deduplicated list of export declarations.\n */\n exports: Array<ExportNode>\n /**\n * Optional metadata attached to this file, read by plugins during barrel generation.\n */\n meta?: TMeta\n /**\n * Optional banner prepended to the generated file content.\n * Accepts `null` so `resolver.default.banner()` results can be passed directly.\n */\n banner?: string | null\n /**\n * Optional footer appended to the generated file content.\n * Accepts `null` so `resolver.default.footer()` results can be passed directly.\n */\n footer?: string | null\n /**\n * Absolute on-disk path to copy into the output, through the parser's `copy` hook when it has one.\n *\n * Use to emit a real source file shipped inside a package (a template) into the generated\n * folder. When set, `copy` provides the file content and any `sources` nodes are ignored for\n * output; `sources` may still carry `name`/`isExportable`/`isIndexable` so barrel generation\n * treats the file the same as a rendered one.\n */\n copy?: string | null\n}\n\n/**\n * Definition for the {@link ImportNode}.\n */\nexport const importDef = defineNode<ImportNode>({ kind: 'Import' })\n\n/**\n * Definition for the {@link ExportNode}.\n */\nexport const exportDef = defineNode<ExportNode>({ kind: 'Export' })\n\n/**\n * Definition for the {@link SourceNode}.\n */\nexport const sourceDef = defineNode<SourceNode>({ kind: 'Source' })\n\n/**\n * Definition for the {@link FileNode}. The fully resolved builder lives in\n * `createFile`, so this definition only supplies the guard.\n */\nexport const fileDef = defineNode<FileNode>({ kind: 'File' })\n\n/**\n * Creates an `ImportNode` representing a language-agnostic import/dependency declaration.\n *\n * @example Named import\n * ```ts\n * createImport({ name: ['useState'], path: 'react' })\n * // import { useState } from 'react'\n * ```\n */\nexport const createImport = importDef.create\n\n/**\n * Creates an `ExportNode` representing a language-agnostic export/public API declaration.\n *\n * @example Named export\n * ```ts\n * createExport({ name: ['Pet'], path: './Pet' })\n * // export { Pet } from './Pet'\n * ```\n */\nexport const createExport = exportDef.create\n\n/**\n * Creates a `SourceNode` representing a fragment of source code within a file.\n *\n * @example\n * ```ts\n * createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')], isExportable: true })\n * ```\n */\nexport const createSource = sourceDef.create\n\n/**\n * Input descriptor for {@link createFile}, before `id`, `name`, and `extname` are computed\n * and `imports`/`exports`/`sources` are deduplicated.\n */\nexport type UserFileNode<TMeta extends object = object> = Omit<FileNode<TMeta>, 'kind' | 'id' | 'name' | 'extname' | 'imports' | 'exports' | 'sources'> &\n Pick<Partial<FileNode<TMeta>>, 'imports' | 'exports' | 'sources'>\n\n/**\n * Creates a fully resolved `FileNode` from a file input descriptor.\n *\n * Computes:\n * - `id` SHA256 hash of the file path\n * - `name` `baseName` without extension\n * - `extname` extension extracted from `baseName`\n *\n * Deduplicates:\n * - `sources` via `combineSources`\n * - `exports` via `combineExports`\n * - `imports` via `combineImports` (also filters unused imports)\n *\n * @throws {Error} when `baseName` has no extension.\n *\n * @example\n * ```ts\n * const file = createFile({\n * baseName: 'petStore.ts',\n * path: 'src/models/petStore.ts',\n * sources: [createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')] })],\n * imports: [createImport({ name: ['z'], path: 'zod' })],\n * exports: [createExport({ name: ['Pet'], path: './petStore' })],\n * })\n * // file.id = SHA256 hash of 'src/models/petStore.ts'\n * // file.name = 'petStore'\n * // file.extname = '.ts'\n * ```\n *\n * @example Copy a real file into the output\n * ```ts\n * const file = createFile({\n * baseName: 'client.ts',\n * path: 'src/gen/client.ts',\n * copy: '/abs/path/to/templates/client.ts',\n * })\n * ```\n */\nexport function createFile<TMeta extends object = object>(input: UserFileNode<TMeta>): FileNode<TMeta> {\n const extname = path.extname(input.baseName) as `.${string}`\n if (!extname) {\n throw new Error(`No extname found for ${input.baseName}`)\n }\n\n const resolvedExports = input.exports?.length ? combineExports(input.exports) : []\n\n // Skip building the source text and local-name set when there are no imports to resolve against them.\n const resolvedImports: Array<ImportNode> = (() => {\n if (!input.imports?.length) return []\n\n const sourceParts: Array<string> = []\n const localNames = new Set<string>()\n for (const item of input.sources ?? []) {\n const extracted = item.nodes && extractStringsFromNodes(item.nodes)\n if (extracted) sourceParts.push(extracted)\n if (item.name) localNames.add(item.name)\n }\n const source = sourceParts.join('\\n') || undefined\n const combinedImports = combineImports(input.imports, resolvedExports, source)\n // Consolidating output (`mode: 'file'`) can put a symbol's definition and an import of it in the\n // same file: by path when the import still targets this file, by name when consolidation moved it.\n return combinedImports.flatMap((imp) => {\n if (imp.path === input.path) return []\n if (!Array.isArray(imp.name)) {\n return typeof imp.name === 'string' && localNames.has(imp.name) ? [] : [imp]\n }\n const kept = imp.name.filter((item) => !localNames.has(importLocalName(item)))\n\n if (!kept.length) return []\n return [kept.length === imp.name.length ? imp : { ...imp, name: kept }]\n })\n })()\n const resolvedSources = input.sources?.length ? combineSources(input.sources) : []\n\n return {\n kind: 'File',\n ...input,\n id: hash('sha256', input.path, 'hex'),\n name: path.basename(input.baseName, extname),\n extname,\n imports: resolvedImports,\n exports: resolvedExports,\n sources: resolvedSources,\n meta: (input.meta ?? {}) as TMeta,\n }\n}\n","import { defineNode } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\nimport type { OperationNode } from './operation.ts'\nimport type { SchemaNode } from './schema.ts'\n\n/**\n * Metadata for an API document, populated by the adapter and available to every generator.\n *\n * All fields are plain JSON-serializable values, no `Set`, no `Map`, no class instances.\n * Computed fields (`circularNames`, `enumNames`) are pre-calculated once during the adapter\n * pre-scan so generators never need to iterate the full schema list themselves.\n *\n * @example\n * ```ts\n * const meta: InputMeta = { title: 'Pet Store', version: '1.0.0', baseURL: 'https://api.example.com/v2', circularNames: [], enumNames: [] }\n * ```\n */\nexport type InputMeta = {\n /**\n * API title from `info.title` in the source document.\n */\n title?: string\n /**\n * API description from `info.description` in the source document.\n */\n description?: string\n /**\n * API version string from `info.version` in the source document.\n */\n version?: string\n /**\n * Resolved base URL from the first matching server entry in the source document.\n */\n baseURL?: string | null\n /**\n * Names of schemas that participate in a circular reference chain.\n * Computed once during the adapter pre-scan, so a generator never has to\n * call `findCircularSchemas` itself.\n *\n * Convert to a `Set` once at the start of a generator, not per-schema,\n * so lookups stay O(1) without repeated allocations.\n *\n * @example Wrap a circular schema in z.lazy()\n * ```ts\n * const circular = new Set(meta.circularNames)\n * if (circular.has(schema.name)) { ... }\n * ```\n */\n circularNames: ReadonlyArray<string>\n /**\n * Names of schemas whose type is `enum`.\n * Computed once during the adapter pre-scan, so a generator never has to\n * filter the schema list itself.\n *\n * Convert to a `Set` once at the start of a generator when you need repeated\n * membership checks, so each check stays O(1) instead of an array scan.\n *\n * @example Check if a referenced schema is an enum\n * `const enums = new Set(meta.enumNames)`\n * `const isEnum = enums.has(schemaName)`\n */\n enumNames: ReadonlyArray<string>\n}\n\n/**\n * Input AST node that contains all schemas and operations for one API document.\n * Produced by the adapter and consumed by all Kubb plugins.\n *\n * @example\n * ```ts\n * const input: InputNode = {\n * kind: 'Input',\n * schemas: [],\n * operations: [],\n * meta: { circularNames: [], enumNames: [] },\n * }\n * ```\n */\nexport type InputNode = BaseNode & {\n /**\n * Node kind.\n */\n kind: 'Input'\n /**\n * All schema nodes in the document.\n */\n schemas: Array<SchemaNode>\n /**\n * All operation nodes in the document.\n */\n operations: Array<OperationNode>\n /**\n * Document metadata populated by the adapter.\n */\n meta: InputMeta\n}\n\n/**\n * Definition for the {@link InputNode}.\n */\nexport const inputDef = defineNode<InputNode, Partial<Omit<InputNode, 'kind'>>>({\n kind: 'Input',\n // A build hook, not `defaults`: a shared default object would let every InputNode mutate the same\n // `schemas`, `operations` and `meta` instances.\n build: (props) => ({ schemas: [], operations: [], meta: { circularNames: [], enumNames: [] }, ...props }),\n children: ['schemas', 'operations'],\n visitorKey: 'input',\n})\n\n/**\n * Creates an `InputNode`, defaulting `schemas`/`operations` to empty arrays and `meta` per\n * {@link inputDef}.\n *\n * @example\n * ```ts\n * const input = createInput()\n * // { kind: 'Input', schemas: [], operations: [] }\n * ```\n */\nexport function createInput(overrides: Partial<Omit<InputNode, 'kind'>> = {}): InputNode {\n return inputDef.create(overrides)\n}\n","import { defineNode } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\nimport type { ContentNode } from './content.ts'\n\n/**\n * AST node representing an operation request body.\n *\n * Body schemas live exclusively inside the `content` array (one entry per content type),\n * mirroring {@link ResponseNode}.\n *\n * @example\n * ```ts\n * const requestBody: RequestBodyNode = {\n * kind: 'RequestBody',\n * required: true,\n * content: [{ kind: 'Content', contentType: 'application/json', schema: createSchema({ type: 'string' }) }],\n * }\n * ```\n */\nexport type RequestBodyNode = BaseNode & {\n kind: 'RequestBody'\n /**\n * Request body description carried over from the spec.\n */\n description?: string\n /**\n * Whether the request body is required (`requestBody.required: true` in the spec).\n * When `false` or absent, the generated `data` parameter should be optional.\n */\n required?: boolean\n /**\n * Content type entries for this request body.\n *\n * When the adapter `contentType` option is set, this array contains exactly one entry for\n * that content type. Otherwise it contains one entry per content type declared in the spec,\n * so plugins can generate code for every variant (for example, separate hooks for\n * `application/json` and `multipart/form-data`).\n */\n content?: Array<ContentNode>\n}\n\n/**\n * Definition for the {@link RequestBodyNode}. Content entries are built upfront with\n * {@link createContent}, mirroring how `parameters` and `responses` take prebuilt nodes.\n */\nexport const requestBodyDef = defineNode<RequestBodyNode>({\n kind: 'RequestBody',\n children: ['content'],\n})\n\n/**\n * Creates a `RequestBodyNode`.\n */\nexport const createRequestBody = requestBodyDef.create\n","import { defineNode } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\nimport type { ParameterNode } from './parameter.ts'\nimport { createRequestBody, type RequestBodyNode } from './requestBody.ts'\nimport type { ResponseNode } from './response.ts'\n\n/**\n * HTTP method an operation responds to.\n */\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'TRACE'\n\n/**\n * Transport an operation belongs to.\n */\ntype OperationProtocol = 'http'\n\n/**\n * Fields shared by every operation, regardless of transport.\n */\ntype OperationNodeBase = BaseNode & {\n /**\n * Node kind.\n */\n kind: 'Operation'\n /**\n * Stable identifier for the operation.\n */\n operationId: string\n /**\n * Group labels for the operation.\n */\n tags: Array<string>\n /**\n * Short one-line operation summary.\n */\n summary?: string\n /**\n * Full operation description.\n */\n description?: string\n /**\n * Marks the operation as deprecated.\n */\n deprecated?: boolean\n /**\n * Query, path, header, and cookie parameters for the operation.\n */\n parameters: Array<ParameterNode>\n /**\n * Request body for the operation.\n */\n requestBody?: RequestBodyNode\n /**\n * Operation responses.\n */\n responses: Array<ResponseNode>\n}\n\n/**\n * Operation served over HTTP. `method` and `path` are guaranteed.\n *\n * @example\n * ```ts\n * const operation: HttpOperationNode = {\n * kind: 'Operation',\n * operationId: 'listPets',\n * protocol: 'http',\n * method: 'GET',\n * path: '/pets',\n * tags: [],\n * parameters: [],\n * responses: [],\n * }\n * ```\n */\nexport type HttpOperationNode = OperationNodeBase & {\n /**\n * Transport the operation belongs to.\n */\n protocol?: 'http'\n /**\n * HTTP method like `'GET'`.\n */\n method: HttpMethod\n /**\n * Path string, for example `/pets/{petId}`, with `{param}` notation preserved.\n */\n path: string\n}\n\n/**\n * Operation for a non-HTTP transport. HTTP-only fields are forbidden.\n */\nexport type GenericOperationNode = OperationNodeBase & {\n /**\n * Transport the operation belongs to.\n */\n protocol?: Exclude<OperationProtocol, 'http'>\n method?: never\n path?: never\n}\n\n/**\n * AST node representing one API operation.\n *\n * Discriminated on `protocol`: an {@link HttpOperationNode} (`protocol: 'http'`) guarantees\n * `method` and `path`, while a {@link GenericOperationNode} omits them. Narrow with\n * `isHttpOperationNode(node)` or `node.protocol === 'http'` before reading `method`/`path`.\n */\nexport type OperationNode = HttpOperationNode | GenericOperationNode\n\ntype OperationInput = {\n operationId: string\n method?: HttpOperationNode['method']\n path?: HttpOperationNode['path']\n requestBody?: Omit<RequestBodyNode, 'kind'>\n [key: string]: unknown\n}\n\n/**\n * Definition for the {@link OperationNode}. HTTP operations (those carrying both\n * `method` and `path`) are tagged with `protocol: 'http'`, and the request body is\n * normalized into a `RequestBodyNode`.\n */\nexport const operationDef = defineNode<OperationNode, OperationInput>({\n kind: 'Operation',\n build: (props) => {\n const { requestBody, ...rest } = props\n const isHttp = rest.method !== undefined && rest.path !== undefined\n\n return {\n tags: [],\n parameters: [],\n responses: [],\n ...rest,\n ...(isHttp ? { protocol: 'http' as const } : {}),\n requestBody: requestBody ? createRequestBody(requestBody) : undefined,\n }\n },\n children: ['parameters', 'requestBody', 'responses'],\n visitorKey: 'operation',\n})\n\n/**\n * Creates an `OperationNode` with default empty arrays for `tags`, `parameters`, and `responses`.\n *\n * @example\n * ```ts\n * const operation = createOperation({ operationId: 'getPetById', method: 'GET', path: '/pet/{petId}' })\n * // tags, parameters, and responses are []\n * ```\n */\nexport function createOperation(\n props: Pick<HttpOperationNode, 'operationId' | 'method' | 'path'> &\n Partial<Omit<HttpOperationNode, 'kind' | 'operationId' | 'method' | 'path' | 'requestBody'>> & {\n requestBody?: Omit<RequestBodyNode, 'kind'>\n },\n): HttpOperationNode\nexport function createOperation(\n props: Pick<GenericOperationNode, 'operationId'> &\n Partial<Omit<GenericOperationNode, 'kind' | 'operationId' | 'requestBody'>> & {\n requestBody?: Omit<RequestBodyNode, 'kind'>\n },\n): GenericOperationNode\nexport function createOperation(props: OperationInput): OperationNode {\n return operationDef.create(props)\n}\n","import { defineNode } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\nimport type { FileNode } from './file.ts'\n\n/**\n * Output AST node that groups all generated file output for one API document.\n *\n * Produced by generators and consumed by the build pipeline to write files.\n *\n * @example\n * ```ts\n * const output: OutputNode = {\n * kind: 'Output',\n * files: [],\n * }\n * ```\n */\nexport type OutputNode = BaseNode & {\n /**\n * Node kind.\n */\n kind: 'Output'\n /**\n * Generated file nodes.\n */\n files: Array<FileNode>\n}\n\n/**\n * Definition for the {@link OutputNode}.\n */\nexport const outputDef = defineNode<OutputNode, Partial<Omit<OutputNode, 'kind'>>>({\n kind: 'Output',\n defaults: { files: [] },\n visitorKey: 'output',\n})\n\n/**\n * Creates an `OutputNode` with a stable default for `files`.\n *\n * @example\n * ```ts\n * const output = createOutput()\n * // { kind: 'Output', files: [] }\n * ```\n */\nexport function createOutput(overrides: Partial<Omit<OutputNode, 'kind'>> = {}): OutputNode {\n return outputDef.create(overrides)\n}\n","import type { SchemaNode } from './nodes/schema.ts'\n\n/**\n * Generic JSON Schema optionality: a non-required field is optional, and a\n * non-required nullable field is nullish.\n */\nexport function optionality(schema: SchemaNode, required: boolean): SchemaNode {\n const nullable = schema.nullable ?? false\n\n return {\n ...schema,\n optional: !required && !nullable ? true : undefined,\n nullish: !required && nullable ? true : undefined,\n }\n}\n\n/**\n * Defaults `required` to `false` and derives the schema's `optional`/`nullish` flags from it.\n * Shared build step of `createProperty` and `createParameter`.\n */\nexport function withRequired<T extends { required?: boolean; schema: SchemaNode }>(props: T): T & { required: boolean } {\n const required = props.required ?? false\n\n return { ...props, required, schema: optionality(props.schema, required) }\n}\n","import { defineNode } from '../defineNode.ts'\nimport { withRequired } from '../optionality.ts'\nimport type { BaseNode } from './base.ts'\nimport type { SchemaNode } from './schema.ts'\n\nexport type ParameterLocation = 'path' | 'query' | 'header' | 'cookie'\n\n/**\n * Parameter serialization style, controlling how a parameter value is rendered into the request.\n */\nexport type ParameterStyle = 'matrix' | 'label' | 'form' | 'simple' | 'spaceDelimited' | 'pipeDelimited' | 'deepObject'\n\n/**\n * AST node representing one operation parameter.\n *\n * @example\n * ```ts\n * const param: ParameterNode = {\n * kind: 'Parameter',\n * name: 'petId',\n * in: 'path',\n * schema: createSchema({ type: 'string' }),\n * required: true,\n * }\n * ```\n */\nexport type ParameterNode = BaseNode & {\n kind: 'Parameter'\n /**\n * Parameter name.\n */\n name: string\n /**\n * Parameter location (`path`, `query`, `header`, or `cookie`).\n */\n in: ParameterLocation\n /**\n * Parameter schema.\n */\n schema: SchemaNode\n /**\n * Whether the parameter is required.\n */\n required: boolean\n /**\n * Serialization style. Absent when the source omits it, leaving consumers to apply the\n * per-location default.\n */\n style?: ParameterStyle\n /**\n * Whether array and object values expand into separate values. Absent when the source omits it,\n * leaving consumers to apply the default for the style.\n */\n explode?: boolean\n}\n\ntype UserParameterNode = Pick<ParameterNode, 'name' | 'in' | 'schema'> & Partial<Omit<ParameterNode, 'kind' | 'name' | 'in' | 'schema'>>\n\n/**\n * Definition for the {@link ParameterNode}. `required` defaults to `false`, and the schema's\n * `optional`/`nullish` flags are derived from it through {@link withRequired}.\n */\nexport const parameterDef = defineNode<ParameterNode, UserParameterNode>({\n kind: 'Parameter',\n build: withRequired,\n children: ['schema'],\n visitorKey: 'parameter',\n})\n\n/**\n * Creates a `ParameterNode`.\n *\n * @example\n * ```ts\n * const param = createParameter({\n * name: 'petId',\n * in: 'path',\n * required: true,\n * schema: createSchema({ type: 'string' }),\n * })\n * ```\n */\nexport const createParameter = parameterDef.create\n","import { defineNode } from '../defineNode.ts'\nimport { withRequired } from '../optionality.ts'\nimport type { BaseNode } from './base.ts'\nimport type { SchemaNode } from './schema.ts'\n\n/**\n * AST node representing one named object property.\n *\n * @example\n * ```ts\n * const property: PropertyNode = {\n * kind: 'Property',\n * name: 'id',\n * schema: createSchema({ type: 'integer' }),\n * required: true,\n * }\n * ```\n */\nexport type PropertyNode = BaseNode & {\n kind: 'Property'\n /**\n * Property key.\n */\n name: string\n /**\n * Property schema.\n */\n schema: SchemaNode\n /**\n * Whether the property is required.\n */\n required: boolean\n}\n\n/**\n * Loosely-typed property accepted by `createProperty`, with `required` optional.\n */\ntype UserPropertyNode = Pick<PropertyNode, 'name' | 'schema'> & Partial<Omit<PropertyNode, 'kind' | 'name' | 'schema'>>\n\n/**\n * Definition for the {@link PropertyNode}. `required` defaults to `false`, and the schema's\n * `optional`/`nullish` flags are derived from it through {@link withRequired}.\n */\nexport const propertyDef = defineNode<PropertyNode, UserPropertyNode>({\n kind: 'Property',\n build: withRequired,\n children: ['schema'],\n visitorKey: 'property',\n})\n\n/**\n * Creates a `PropertyNode`.\n *\n * @example\n * ```ts\n * const property = createProperty({\n * name: 'status',\n * required: true,\n * schema: createSchema({ type: 'string', nullable: true }),\n * })\n * // required=true, no optional/nullish\n * ```\n */\nexport const createProperty = propertyDef.create\n","import { defineNode } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\nimport { type ContentNode, createContent } from './content.ts'\nimport type { SchemaNode } from './schema.ts'\n\n/**\n * All supported HTTP status code literals as strings, as used in API specs\n * (for example, `\"200\"` and `\"404\"`).\n */\ntype HttpStatusCode =\n // 1xx Informational\n | '100'\n | '101'\n | '102'\n | '103'\n // 2xx Success\n | '200'\n | '201'\n | '202'\n | '203'\n | '204'\n | '205'\n | '206'\n | '207'\n | '208'\n | '226'\n // 3xx Redirection\n | '300'\n | '301'\n | '302'\n | '303'\n | '304'\n | '305'\n | '307'\n | '308'\n // 4xx Client Error\n | '400'\n | '401'\n | '402'\n | '403'\n | '404'\n | '405'\n | '406'\n | '407'\n | '408'\n | '409'\n | '410'\n | '411'\n | '412'\n | '413'\n | '414'\n | '415'\n | '416'\n | '417'\n | '418'\n | '421'\n | '422'\n | '423'\n | '424'\n | '425'\n | '426'\n | '428'\n | '429'\n | '431'\n | '451'\n // 5xx Server Error\n | '500'\n | '501'\n | '502'\n | '503'\n | '504'\n | '505'\n | '506'\n | '507'\n | '508'\n | '510'\n | '511'\n\n/**\n * Response status code literal used by operations.\n *\n * Includes specific HTTP status code strings and `\"default\"` for catch-all responses.\n *\n * @example\n * ```ts\n * const status: StatusCode = '200'\n * const fallback: StatusCode = 'default'\n * ```\n */\nexport type StatusCode = HttpStatusCode | 'default'\n\n/**\n * AST node representing one operation response variant.\n *\n * Mirrors {@link OperationNode.requestBody}: the response body schemas live exclusively inside\n * the `content` array (one entry per content type), so the same schema is never duplicated at the\n * node root and inside `content`.\n *\n * @example\n * ```ts\n * const response: ResponseNode = {\n * kind: 'Response',\n * statusCode: '200',\n * content: [{ kind: 'Content', contentType: 'application/json', schema: createSchema({ type: 'string' }) }],\n * }\n * ```\n */\nexport type ResponseNode = BaseNode & {\n /**\n * Node kind.\n */\n kind: 'Response'\n /**\n * HTTP status code or `'default'` for a fallback response.\n */\n statusCode: StatusCode\n /**\n * Optional response description.\n */\n description?: string\n /**\n * All available content type entries for this response.\n *\n * When the adapter `contentType` option is set, this array contains exactly one entry for that\n * content type. Otherwise it contains one entry per content type declared in the spec, so that\n * plugins can generate a union of response types (e.g. `application/json` and `application/xml`).\n * Body-less responses keep a single entry whose `schema` is the empty/`void` placeholder.\n *\n * @example\n * ```ts\n * // spec response declares both application/json and application/xml\n * response.content[0].contentType // 'application/json'\n * response.content[1].contentType // 'application/xml'\n * ```\n */\n content?: Array<ContentNode>\n}\n\ntype ResponseInput = Pick<ResponseNode, 'statusCode'> &\n Partial<Omit<ResponseNode, 'kind' | 'statusCode' | 'content'>> & {\n content?: Array<ContentNode>\n schema?: SchemaNode\n mediaType?: string | null\n keysToOmit?: Array<string> | null\n }\n\n/**\n * Definition for the {@link ResponseNode}. A single legacy `schema` (with optional\n * `mediaType`/`keysToOmit`) is normalized into one `content` entry.\n */\nexport const responseDef = defineNode<ResponseNode, ResponseInput>({\n kind: 'Response',\n build: (props) => {\n const { schema, mediaType, keysToOmit, content, ...rest } = props\n const entries = content ?? (schema ? [createContent({ contentType: mediaType ?? 'application/json', schema, keysToOmit: keysToOmit ?? null })] : undefined)\n return { ...rest, content: entries }\n },\n children: ['content'],\n visitorKey: 'response',\n})\n\n/**\n * Creates a `ResponseNode`.\n *\n * @example\n * ```ts\n * const response = createResponse({\n * statusCode: '200',\n * content: [createContent({ contentType: 'application/json', schema: createSchema({ type: 'object', properties: [] }) })],\n * })\n * ```\n */\nexport const createResponse = responseDef.create\n","import type { InferSchemaNode } from '../infer.ts'\nimport { defineNode, type DistributiveOmit } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\nimport type { PropertyNode } from './property.ts'\n\nexport type PrimitiveSchemaType =\n /**\n * Text value.\n */\n | 'string'\n /**\n * Floating-point number.\n */\n | 'number'\n /**\n * Integer number.\n */\n | 'integer'\n /**\n * Big integer number.\n */\n | 'bigint'\n /**\n * Boolean value.\n */\n | 'boolean'\n /**\n * Null value.\n */\n | 'null'\n /**\n * Any value.\n */\n | 'any'\n /**\n * Unknown value.\n */\n | 'unknown'\n /**\n * No value (`void`).\n */\n | 'void'\n /**\n * Never value.\n */\n | 'never'\n /**\n * Object value.\n */\n | 'object'\n /**\n * Array value.\n */\n | 'array'\n /**\n * Date value.\n */\n | 'date'\n\n/**\n * All schema type strings, one per key of {@link SchemaNodeByType}.\n */\nexport type SchemaType = keyof SchemaNodeByType\n\n/**\n * Scalar schema types without extra object/array/ref structure or constraints.\n */\nexport type ScalarSchemaType = 'boolean' | 'null' | 'any' | 'unknown' | 'void' | 'never' | 'blob'\n\n/**\n * Fields shared by all schema nodes.\n */\ntype SchemaNodeBase = BaseNode & {\n /**\n * Node kind.\n */\n kind: 'Schema'\n /**\n * Schema name for named definitions (for example, `\"Pet\"`).\n * Inline schemas omit this field.\n * `null` means Kubb has processed this and determined there is no applicable name.\n * `undefined` means the name has not been set yet.\n */\n name?: string | null\n /**\n * Short schema title.\n */\n title?: string\n /**\n * Schema description text.\n */\n description?: string\n /**\n * Whether `null` is allowed.\n */\n nullable?: boolean\n /**\n * Whether the field is optional.\n */\n optional?: boolean\n /**\n * Both optional and nullable (`optional` + `nullable`).\n */\n nullish?: boolean\n /**\n * Whether the schema is deprecated.\n */\n deprecated?: boolean\n /**\n * Whether the schema is read-only.\n */\n readOnly?: boolean\n /**\n * Whether the schema is write-only.\n */\n writeOnly?: boolean\n /**\n * Default value.\n */\n default?: unknown\n /**\n * Example values from an `examples` array.\n */\n examples?: Array<unknown>\n /**\n * Base primitive type.\n * For example, this is `'string'` for a `uuid` schema.\n */\n primitive?: PrimitiveSchemaType\n /**\n * Schema `format` value.\n */\n format?: string\n}\n\n/**\n * Object schema with ordered properties.\n *\n * @example\n * ```ts\n * const objectSchema: ObjectSchemaNode = {\n * kind: 'Schema',\n * type: 'object',\n * properties: [],\n * }\n * ```\n */\nexport type ObjectSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'object'\n /**\n * Primitive type, always `'object'` for object schemas.\n */\n primitive: 'object'\n /**\n * Ordered object properties.\n */\n properties: Array<PropertyNode>\n /**\n * Additional object properties behavior:\n * - `true`: allow any value\n * - `false`: reject unknown properties\n * - `SchemaNode`: allow values that match that schema\n * - `undefined`: no additional properties constraint (open object)\n */\n additionalProperties?: SchemaNode | boolean\n /**\n * Pattern-based property schemas.\n */\n patternProperties?: Record<string, SchemaNode>\n /**\n * Minimum number of properties allowed.\n */\n minProperties?: number\n /**\n * Maximum number of properties allowed.\n */\n maxProperties?: number\n}\n\n/**\n * Array-like schema (`array` or `tuple`).\n *\n * @example\n * ```ts\n * const arraySchema: ArraySchemaNode = {\n * kind: 'Schema',\n * type: 'array',\n * items: [],\n * }\n * ```\n */\nexport type ArraySchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator (`array` or `tuple`).\n */\n type: 'array' | 'tuple'\n /**\n * Item schemas.\n */\n items?: Array<SchemaNode>\n /**\n * Tuple rest-item schema for elements beyond positional `items`.\n */\n rest?: SchemaNode\n /**\n * Minimum item count (or tuple length).\n */\n min?: number\n /**\n * Maximum item count (or tuple length).\n */\n max?: number\n /**\n * Whether all items must be unique.\n */\n unique?: boolean\n}\n\n/**\n * Shared shape for union and intersection schemas.\n */\ntype CompositeSchemaNodeBase = SchemaNodeBase & {\n /**\n * Member schemas.\n */\n members?: Array<SchemaNode>\n}\n\n/**\n * Union schema, often from `oneOf` or `anyOf`.\n *\n * @example\n * ```ts\n * const unionSchema: UnionSchemaNode = {\n * kind: 'Schema',\n * type: 'union',\n * members: [],\n * }\n * ```\n */\nexport type UnionSchemaNode = CompositeSchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'union'\n /**\n * Discriminator property name for a polymorphic union.\n */\n discriminatorPropertyName?: string\n /**\n * How many union members must be valid.\n * - `'one'`: exactly one member, from `oneOf`\n * - `'any'`: any number of members, from `anyOf`\n */\n strategy?: 'one' | 'any'\n}\n\n/**\n * Intersection schema, often from `allOf`.\n *\n * @example\n * ```ts\n * const intersectionSchema: IntersectionSchemaNode = {\n * kind: 'Schema',\n * type: 'intersection',\n * members: [],\n * }\n * ```\n */\nexport type IntersectionSchemaNode = CompositeSchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'intersection'\n}\n\n/**\n * One named enum item.\n */\ntype EnumValueNode = {\n /**\n * Enum item name.\n */\n name: string\n /**\n * Enum item value.\n */\n value: string | number | boolean\n /**\n * Primitive type of the enum value.\n */\n primitive: Extract<PrimitiveSchemaType, 'string' | 'number' | 'boolean'>\n /**\n * Label for the enum item, taken from the `x-enumDescriptions` or\n * `x-enum-descriptions` vendor extension. `@kubb/plugin-ts` renders it as\n * JSDoc on the matching enum member.\n */\n description?: string\n}\n\n/**\n * Enum schema node.\n *\n * @example\n * ```ts\n * const enumSchema: EnumSchemaNode = {\n * kind: 'Schema',\n * type: 'enum',\n * enumValues: ['a', 'b'],\n * }\n * ```\n */\nexport type EnumSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'enum'\n /**\n * Enum values in simple form.\n */\n enumValues?: Array<string | number | boolean | null>\n /**\n * Enum values in named form.\n * If present, this is used instead of `enumValues`.\n */\n namedEnumValues?: Array<EnumValueNode>\n}\n\n/**\n * Reference schema that points to another schema definition.\n *\n * @example\n * ```ts\n * const refSchema: RefSchemaNode = {\n * kind: 'Schema',\n * type: 'ref',\n * ref: '#/components/schemas/Pet',\n * }\n * ```\n */\nexport type RefSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'ref'\n /**\n * Referenced schema name.\n * `null` means Kubb has processed this and determined there is no applicable name.\n */\n name?: string | null\n /**\n * Original `$ref` path, for example, `#/components/schemas/Order`.\n * Used to resolve names later.\n */\n ref?: string\n /**\n * Emitted name of the referenced schema when it differs from the pointer's last segment,\n * for example after a collision rename (`Order` becomes `OrderSchema`) or a macro rename.\n * Resolve display and import names through `resolveRefName`, which prefers this field and\n * falls back to the pointer segment, then `name`.\n */\n targetName?: string\n /**\n * Pattern copied from a sibling `pattern` field.\n */\n pattern?: string\n /**\n * The fully-parsed schema this ref resolves to, so its structure (`primitive`, `properties`)\n * can be read without following the reference. Populated during parsing when the\n * definition resolves, `null` when it can't or the ref is circular, and `undefined` when\n * resolution has not been attempted.\n */\n schema?: SchemaNode | null\n}\n\n/**\n * Datetime schema.\n *\n * @example\n * ```ts\n * const datetimeSchema: DatetimeSchemaNode = { kind: 'Schema', type: 'datetime' }\n * ```\n */\nexport type DatetimeSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'datetime'\n /**\n * Whether the datetime includes a timezone offset (`dateType: 'stringOffset'`).\n */\n offset?: boolean\n /**\n * Whether the datetime is local (no timezone, `dateType: 'stringLocal'`).\n */\n local?: boolean\n}\n\n/**\n * Shared base for `date` and `time` schemas.\n */\ntype TemporalSchemaNodeBase<T extends 'date' | 'time'> = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: T\n /**\n * Output representation in generated code.\n */\n representation: 'date' | 'string'\n}\n\n/**\n * Date schema node.\n *\n * @example\n * ```ts\n * const dateSchema: DateSchemaNode = { kind: 'Schema', type: 'date', representation: 'string' }\n * ```\n */\nexport type DateSchemaNode = TemporalSchemaNodeBase<'date'>\n\n/**\n * Time schema node.\n *\n * @example\n * ```ts\n * const timeSchema: TimeSchemaNode = { kind: 'Schema', type: 'time', representation: 'string' }\n * ```\n */\nexport type TimeSchemaNode = TemporalSchemaNodeBase<'time'>\n\n/**\n * String schema node.\n *\n * @example\n * ```ts\n * const stringSchema: StringSchemaNode = { kind: 'Schema', type: 'string' }\n * ```\n */\nexport type StringSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'string'\n /**\n * Minimum string length.\n */\n min?: number\n /**\n * Maximum string length.\n */\n max?: number\n /**\n * Regex pattern.\n */\n pattern?: string\n}\n\n/**\n * Numeric schema (`number`, `integer`, or `bigint`).\n *\n * @example\n * ```ts\n * const numberSchema: NumberSchemaNode = { kind: 'Schema', type: 'number' }\n * ```\n */\nexport type NumberSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'number' | 'integer' | 'bigint'\n /**\n * Minimum value.\n */\n min?: number\n /**\n * Maximum value.\n */\n max?: number\n /**\n * Exclusive minimum value.\n */\n exclusiveMinimum?: number\n /**\n * Exclusive maximum value.\n */\n exclusiveMaximum?: number\n /**\n * The value must be a multiple of this number.\n */\n multipleOf?: number\n}\n\n/**\n * Scalar schema with no extra constraints.\n *\n * @example\n * ```ts\n * const anySchema: ScalarSchemaNode = { kind: 'Schema', type: 'any' }\n * ```\n */\nexport type ScalarSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: ScalarSchemaType\n}\n\n/**\n * URL schema node.\n * Can include a path template for template literal types.\n *\n * @example\n * ```ts\n * const urlSchema: UrlSchemaNode = { kind: 'Schema', type: 'url', path: '/pets/{petId}' }\n * ```\n */\nexport type UrlSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'url'\n /**\n * Path template, for example, `'/pets/{petId}'`.\n */\n path?: string\n /**\n * Minimum string length.\n */\n min?: number\n /**\n * Maximum string length.\n */\n max?: number\n}\n\n/**\n * Format-string schema for string-based formats that support length constraints.\n *\n * @example\n * ```ts\n * const uuidSchema: FormatStringSchemaNode = { kind: 'Schema', type: 'uuid', min: 36, max: 36 }\n * ```\n */\ntype FormatStringSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'uuid' | 'email'\n /**\n * Minimum string length.\n */\n min?: number\n /**\n * Maximum string length.\n */\n max?: number\n}\n\n/**\n * IPv4 address schema node.\n *\n * @example\n * ```ts\n * const ipv4Schema: Ipv4SchemaNode = { kind: 'Schema', type: 'ipv4' }\n * ```\n */\ntype Ipv4SchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'ipv4'\n}\n\n/**\n * IPv6 address schema node.\n *\n * @example\n * ```ts\n * const ipv6Schema: Ipv6SchemaNode = { kind: 'Schema', type: 'ipv6' }\n * ```\n */\ntype Ipv6SchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'ipv6'\n}\n\n/**\n * Mapping from schema type literals to concrete schema node types.\n * Used by `narrowSchema`.\n */\nexport type SchemaNodeByType = {\n object: ObjectSchemaNode\n array: ArraySchemaNode\n tuple: ArraySchemaNode\n union: UnionSchemaNode\n intersection: IntersectionSchemaNode\n enum: EnumSchemaNode\n ref: RefSchemaNode\n datetime: DatetimeSchemaNode\n date: DateSchemaNode\n time: TimeSchemaNode\n string: StringSchemaNode\n number: NumberSchemaNode\n integer: NumberSchemaNode\n bigint: NumberSchemaNode\n boolean: ScalarSchemaNode\n null: ScalarSchemaNode\n any: ScalarSchemaNode\n unknown: ScalarSchemaNode\n void: ScalarSchemaNode\n never: ScalarSchemaNode\n uuid: FormatStringSchemaNode\n email: FormatStringSchemaNode\n url: UrlSchemaNode\n ipv4: Ipv4SchemaNode\n ipv6: Ipv6SchemaNode\n blob: ScalarSchemaNode\n}\n\n/**\n * Union of all schema node types.\n */\nexport type SchemaNode =\n | ObjectSchemaNode\n | ArraySchemaNode\n | UnionSchemaNode\n | IntersectionSchemaNode\n | EnumSchemaNode\n | RefSchemaNode\n | DatetimeSchemaNode\n | DateSchemaNode\n | TimeSchemaNode\n | StringSchemaNode\n | NumberSchemaNode\n | UrlSchemaNode\n | FormatStringSchemaNode\n | Ipv4SchemaNode\n | Ipv6SchemaNode\n | ScalarSchemaNode\n\ntype CreateSchemaObjectInput = Omit<ObjectSchemaNode, 'kind' | 'properties' | 'primitive'> & { properties?: Array<PropertyNode>; primitive?: 'object' }\ntype CreateSchemaInput = CreateSchemaObjectInput | DistributiveOmit<Exclude<SchemaNode, ObjectSchemaNode>, 'kind'>\ntype CreateSchemaOutput<T extends CreateSchemaInput> = InferSchemaNode<T> & {\n kind: 'Schema'\n}\n\n/**\n * Maps schema `type` to its underlying `primitive`.\n * Primitive types map to themselves and special string formats map to `'string'`.\n * Any type not listed here (such as `ref`, `enum`, `union`, `intersection`, `tuple`, `ipv4`, `ipv6`, `blob`) has no `primitive`.\n */\nconst TYPE_TO_PRIMITIVE: Partial<Record<SchemaNode['type'], PrimitiveSchemaType>> = {\n string: 'string',\n number: 'number',\n integer: 'integer',\n bigint: 'bigint',\n boolean: 'boolean',\n null: 'null',\n any: 'any',\n unknown: 'unknown',\n void: 'void',\n never: 'never',\n object: 'object',\n array: 'array',\n date: 'date',\n uuid: 'string',\n email: 'string',\n url: 'string',\n datetime: 'string',\n time: 'string',\n}\n\n/**\n * Definition for the {@link SchemaNode}. Object schemas default `properties` to an\n * empty array, and `primitive` is inferred from `type` when not explicitly provided.\n */\nexport const schemaDef = defineNode<SchemaNode, CreateSchemaInput>({\n kind: 'Schema',\n build: (props) => {\n if (props.type === 'object') {\n return { properties: [], primitive: 'object' as const, ...props }\n }\n\n return { primitive: TYPE_TO_PRIMITIVE[props.type as keyof typeof TYPE_TO_PRIMITIVE], ...props }\n },\n children: ['properties', 'items', 'members', 'additionalProperties', 'patternProperties', 'rest'],\n visitorKey: 'schema',\n})\n\n/**\n * Creates a `SchemaNode`, narrowed to the variant of `props.type`.\n *\n * @example\n * ```ts\n * const scalar = createSchema({ type: 'string' })\n * // { kind: 'Schema', type: 'string', primitive: 'string' }\n * ```\n *\n * @example\n * ```ts\n * const object = createSchema({ type: 'object' })\n * // { kind: 'Schema', type: 'object', primitive: 'object', properties: [] }\n * ```\n */\nexport function createSchema<T extends CreateSchemaInput>(props: T): CreateSchemaOutput<T>\nexport function createSchema(props: CreateSchemaInput): SchemaNode\nexport function createSchema(props: CreateSchemaInput): SchemaNode {\n return schemaDef.create(props)\n}\n","import type { NodeDef } from './defineNode.ts'\nimport { arrowFunctionDef, breakDef, constDef, functionDef, jsxDef, textDef, typeDef } from './nodes/code.ts'\nimport { contentDef } from './nodes/content.ts'\nimport { exportDef, fileDef, importDef, sourceDef } from './nodes/file.ts'\nimport { inputDef } from './nodes/input.ts'\nimport { operationDef } from './nodes/operation.ts'\nimport { outputDef } from './nodes/output.ts'\nimport { parameterDef } from './nodes/parameter.ts'\nimport { propertyDef } from './nodes/property.ts'\nimport { requestBodyDef } from './nodes/requestBody.ts'\nimport { responseDef } from './nodes/response.ts'\nimport { schemaDef } from './nodes/schema.ts'\n\n// Surface every def from one place so the package barrel re-exports them with `export * from './registry.ts'`.\n// Adding a node means adding its `defineNode` to a `nodes/*.ts` file and listing it in `nodeDefs` below, nothing else.\nexport {\n arrowFunctionDef,\n breakDef,\n constDef,\n contentDef,\n exportDef,\n fileDef,\n functionDef,\n importDef,\n inputDef,\n jsxDef,\n operationDef,\n outputDef,\n parameterDef,\n propertyDef,\n requestBodyDef,\n responseDef,\n schemaDef,\n sourceDef,\n textDef,\n typeDef,\n}\n\n/**\n * Every node definition. Adding a node means adding its `defineNode` to one\n * `nodes/*.ts` file and listing it here. The visitor tables in `visitor.ts` derive from it.\n */\nexport const nodeDefs = [\n inputDef,\n outputDef,\n operationDef,\n requestBodyDef,\n contentDef,\n responseDef,\n schemaDef,\n propertyDef,\n parameterDef,\n constDef,\n typeDef,\n functionDef,\n arrowFunctionDef,\n textDef,\n breakDef,\n jsxDef,\n importDef,\n exportDef,\n sourceDef,\n fileDef,\n] satisfies ReadonlyArray<NodeDef>\n","import type { VisitorDepth } from './constants.ts'\nimport { visitorDepths } from './constants.ts'\nimport type { NodeDef } from './defineNode.ts'\nimport type { Node } from './nodes/index.ts'\nimport type { ContentNode } from './nodes/content.ts'\nimport type { InputNode } from './nodes/input.ts'\nimport type { NodeKind } from './nodes/base.ts'\nimport type { OperationNode } from './nodes/operation.ts'\nimport type { OutputNode } from './nodes/output.ts'\nimport type { ParameterNode } from './nodes/parameter.ts'\nimport type { PropertyNode } from './nodes/property.ts'\nimport type { RequestBodyNode } from './nodes/requestBody.ts'\nimport type { ResponseNode } from './nodes/response.ts'\nimport type { SchemaNode } from './nodes/schema.ts'\nimport { nodeDefs } from './registry.ts'\n\n/**\n * Child node fields per node kind, in traversal order (Babel's `VISITOR_KEYS`).\n * Derived from each definition's `children`.\n */\nconst VISITOR_KEYS = Object.fromEntries(nodeDefs.flatMap((def) => (def.children ? [[def.kind, def.children] as const] : []))) as Partial<\n Record<NodeKind, ReadonlyArray<string>>\n>\n\n/**\n * Maps a node kind to the matching visitor callback name. Derived from each\n * definition's `visitorKey`.\n */\nconst VISITOR_KEY_BY_KIND = Object.fromEntries(nodeDefs.flatMap((def) => (def.visitorKey ? [[def.kind, def.visitorKey] as const] : []))) as Partial<\n Record<NodeKind, NonNullable<NodeDef['visitorKey']>>\n>\n\n/**\n * Ordered mapping of `[NodeType, ParentType]` pairs.\n *\n * `ParentOf` uses this map to find parent types.\n */\ntype ParentNodeMap = [\n [InputNode, undefined],\n [OutputNode, undefined],\n [OperationNode, InputNode],\n [RequestBodyNode, OperationNode],\n [ContentNode, RequestBodyNode | ResponseNode],\n [SchemaNode, InputNode | ContentNode | SchemaNode | PropertyNode | ParameterNode],\n [PropertyNode, SchemaNode],\n [ParameterNode, OperationNode],\n [ResponseNode, OperationNode],\n]\n\n/**\n * Resolves the parent node type for a given AST node type.\n *\n * Visitor context relies on this so `ctx.parent` is typed for each callback.\n *\n * @example\n * ```ts\n * type InputParent = ParentOf<InputNode>\n * // undefined\n * ```\n *\n * @example\n * ```ts\n * type PropertyParent = ParentOf<PropertyNode>\n * // SchemaNode\n * ```\n *\n * @example\n * ```ts\n * type SchemaParent = ParentOf<SchemaNode>\n * // InputNode | ContentNode | SchemaNode | PropertyNode | ParameterNode\n * ```\n */\nexport type ParentOf<T extends Node, TEntries extends ReadonlyArray<[Node, unknown]> = ParentNodeMap> = TEntries extends [\n infer TEntry extends [Node, unknown],\n ...infer TRest extends ReadonlyArray<[Node, unknown]>,\n]\n ? T extends TEntry[0]\n ? TEntry[1]\n : ParentOf<T, TRest>\n : Node\n\n/**\n * Traversal context passed as the second argument to every visitor callback.\n * `parent` is typed from the current node type.\n *\n * @example\n * ```ts\n * const visitor: Visitor = {\n * schema(node, { parent }) {\n * // parent type is narrowed by node kind\n * },\n * }\n * ```\n */\nexport type VisitorContext<T extends Node = Node> = {\n /**\n * Parent node of the currently visited node.\n * For `InputNode`, this is `undefined`.\n */\n parent?: ParentOf<T>\n}\n\n/**\n * Synchronous visitor consumed by `transform`. Each optional callback runs\n * for the matching node type. Return a new node to replace it, or `undefined`\n * to leave it untouched.\n *\n * Plugins typically expose `transformer` so users can supply a `Visitor` that\n * rewrites the AST before printing.\n *\n * @example Prefix every operationId\n * ```ts\n * const visitor: Visitor = {\n * operation(node) {\n * return { ...node, operationId: `api_${node.operationId}` }\n * },\n * }\n * ```\n *\n * @example Strip schema descriptions\n * ```ts\n * const visitor: Visitor = {\n * schema(node) {\n * return { ...node, description: undefined }\n * },\n * }\n * ```\n */\nexport type Visitor = {\n input?(node: InputNode, context: VisitorContext<InputNode>): undefined | null | InputNode\n output?(node: OutputNode, context: VisitorContext<OutputNode>): undefined | null | OutputNode\n operation?(node: OperationNode, context: VisitorContext<OperationNode>): undefined | null | OperationNode\n schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): undefined | null | SchemaNode\n property?(node: PropertyNode, context: VisitorContext<PropertyNode>): undefined | null | PropertyNode\n parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): undefined | null | ParameterNode\n response?(node: ResponseNode, context: VisitorContext<ResponseNode>): undefined | null | ResponseNode\n}\n\n/**\n * The callbacks of {@link Visitor} with every return type replaced by `TResult`. `collect` uses it\n * so a visitor can yield values instead of replacement nodes.\n *\n * @example\n * ```ts\n * const visitor: VisitorOf<string> = {\n * operation(node) {\n * return node.operationId\n * },\n * }\n * ```\n */\ntype VisitorOf<TResult> = {\n [K in keyof Visitor]?: (node: Parameters<NonNullable<Visitor[K]>>[0], context: Parameters<NonNullable<Visitor[K]>>[1]) => TResult | null | undefined\n}\n\ntype TraversalOptions = {\n /**\n * Traversal depth.\n * @default 'deep'\n */\n depth?: VisitorDepth\n /**\n * Internal parent override used during recursion.\n */\n parent?: Node\n}\n\n/**\n * Options for `transform`.\n *\n * @example\n * ```ts\n * const options: TransformOptions = { depth: 'deep', schema: (node) => node }\n * ```\n *\n * @example\n * ```ts\n * // Only transform the current node, not nested children\n * const options: TransformOptions = { depth: 'shallow', schema: (node) => node }\n * ```\n */\ntype TransformOptions = Visitor & TraversalOptions\n\n/**\n * Options for `collect`.\n *\n * @example\n * ```ts\n * const options: CollectOptions<string> = { depth: 'shallow', schema: () => undefined }\n * ```\n */\ntype CollectOptions<T> = VisitorOf<T> & TraversalOptions\n\nconst visitorKeysByKind = VISITOR_KEYS as Record<string, ReadonlyArray<string> | undefined>\n\n/**\n * Returns `true` when `value` is an AST node (an object carrying a `kind`).\n */\nfunction isNode(value: unknown): value is Node {\n return typeof value === 'object' && value !== null && typeof (value as { kind?: unknown }).kind === 'string'\n}\n\n/**\n * Returns `true` for a plain object that maps names to nodes, such as `patternProperties`.\n */\nfunction isNodeRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Returns the child fields of `node` to walk, from {@link VISITOR_KEYS}, or `undefined` when there\n * is nothing to walk. `Schema` children are only walked when `recurse` is `true`.\n */\nfunction childKeys(node: Node, recurse: boolean): ReadonlyArray<string> | undefined {\n if (node.kind === 'Schema' && !recurse) return undefined\n\n return visitorKeysByKind[node.kind]\n}\n\n/**\n * Returns the immediate traversable children of `node`.\n *\n * @example\n * ```ts\n * const children = getChildren(operationNode, true)\n * // returns parameters, the request body, and responses\n * ```\n */\nfunction* getChildren(node: Node, recurse: boolean): Generator<Node, void, undefined> {\n const keys = childKeys(node, recurse)\n if (!keys) return\n\n const record = node as unknown as Record<string, unknown>\n for (const key of keys) {\n const value = record[key]\n if (Array.isArray(value)) {\n for (const item of value) if (isNode(item)) yield item\n continue\n }\n if (isNode(value)) {\n yield value\n continue\n }\n if (isNodeRecord(value)) {\n for (const item of Object.values(value)) if (isNode(item)) yield item\n }\n }\n}\n\n/**\n * Runs the visitor callback that matches `node.kind` with the traversal\n * context. The result is a replacement node, a collected value, or `undefined`\n * when no callback is registered for the kind.\n *\n * Shared by `transform` and `collect` so node-kind dispatch lives in one place.\n * `TResult` is the caller's expected return: the same node type for `transform`,\n * the collected value type for `collect`.\n */\nfunction applyVisitor<TResult>(node: Node, visitor: Visitor | VisitorOf<unknown>, parent: Node | undefined): TResult | null | undefined {\n const key = VISITOR_KEY_BY_KIND[node.kind]\n if (!key) return undefined\n\n const fn = visitor[key] as ((node: Node, context: VisitorContext) => TResult | null | undefined) | undefined\n\n return fn?.(node, { parent })\n}\n\n/**\n * Synchronous depth-first transform. Each visitor callback can return a\n * replacement node. Returning `undefined` keeps the original.\n *\n * The original tree is never mutated, a new tree is returned. Pass\n * `depth: 'shallow'` to skip recursion into children.\n *\n * @example Prefix every operationId\n * ```ts\n * const next = transform(root, {\n * operation(node) {\n * return { ...node, operationId: `prefixed_${node.operationId}` }\n * },\n * })\n * ```\n *\n * @example Replace only the root node\n * ```ts\n * const next = transform(root, {\n * depth: 'shallow',\n * input: (node) => ({ ...node, meta: { ...node.meta, title: 'Rewritten' } }),\n * })\n * ```\n */\nexport function transform<T extends Node>(node: T, options: TransformOptions): T {\n const { depth, parent, ...visitor } = options\n const recurse = (depth ?? visitorDepths.deep) === visitorDepths.deep\n\n // Split the visitor object out once here, then thread it plus `recurse`/`parent` as plain\n // arguments through the recursion. The previous code re-ran the `...visitor` rest-destructure on\n // every recursive `transform` call and rebuilt a `{ ...options, parent }` object per node, so the\n // options shape (which callbacks are present) varied call to call and the hot recursion churned.\n return transformNode(node, visitor, recurse, parent) as T\n}\n\n/**\n * Visits a single node, then immutably rebuilds its children. Returns the original\n * reference when neither the visitor nor the child rebuild changed anything, so callers\n * can detect \"nothing changed\" by identity and ancestors avoid reallocating.\n */\nfunction transformNode(node: Node, visitor: Visitor, recurse: boolean, parent: Node | undefined): Node {\n const visited = applyVisitor<Node>(node, visitor, parent) ?? node\n return transformChildren(visited, visitor, recurse)\n}\n\n/**\n * Immutably rebuilds a node's children, transforming each child node and leaving non-node values\n * (e.g. `additionalProperties: true`) intact.\n */\nfunction transformChildren(node: Node, visitor: Visitor, recurse: boolean): Node {\n const keys = childKeys(node, recurse)\n if (!keys) return node\n\n const record = node as unknown as Record<string, unknown>\n let updates: Record<string, unknown> | undefined\n\n for (const key of keys) {\n if (!(key in record)) continue\n const value = record[key]\n if (Array.isArray(value)) {\n // Rebuild the array lazily: allocate a new array only once a child actually changes, copying\n // the unchanged prefix at that point. An unchanged array keeps its original reference and\n // allocates nothing. This also drops the per-array `.map` closure that ran on every node.\n let mapped: Array<unknown> | undefined\n for (const [i, item] of value.entries()) {\n const next = isNode(item) ? transformNode(item, visitor, recurse, node) : item\n if (mapped) {\n mapped.push(next)\n continue\n }\n if (next !== item) mapped = [...value.slice(0, i), next]\n }\n if (mapped) (updates ??= {})[key] = mapped\n continue\n }\n if (isNode(value)) {\n const next = transformNode(value, visitor, recurse, node)\n if (next !== value) (updates ??= {})[key] = next\n continue\n }\n if (isNodeRecord(value)) {\n let mapped: Record<string, unknown> | undefined\n for (const [name, item] of Object.entries(value)) {\n const next = isNode(item) ? transformNode(item, visitor, recurse, node) : item\n if (next !== item) (mapped ??= { ...value })[name] = next\n }\n if (mapped) (updates ??= {})[key] = mapped\n }\n }\n\n if (!updates) return node\n const merged = { ...node, ...updates }\n return merged as Node\n}\n\n/**\n * Lazy depth-first collection pass. Yields every non-null value returned by\n * the visitor callbacks. Use `collectSync` for the eager array form.\n *\n * @example Collect every operationId\n * ```ts\n * const ids: string[] = []\n * for (const id of collect<string>(root, {\n * operation(node) {\n * return node.operationId\n * },\n * })) {\n * ids.push(id)\n * }\n * ```\n */\nexport function* collect<T>(node: Node, options: CollectOptions<T>): Generator<T, void, undefined> {\n const { depth, parent, ...visitor } = options\n const recurse = (depth ?? visitorDepths.deep) === visitorDepths.deep\n\n // Thread the split-out visitor through the recursion instead of rebuilding `{ ...options, parent }`\n // for every child, mirroring `transform`. Keeps the recursive object shape stable.\n yield* collectNode<T>(node, visitor, recurse, parent)\n}\n\nfunction* collectNode<T>(node: Node, visitor: VisitorOf<T>, recurse: boolean, parent: Node | undefined): Generator<T, void, undefined> {\n const v = applyVisitor<T>(node, visitor, parent)\n if (v != null) yield v\n\n for (const child of getChildren(node, recurse)) {\n yield* collectNode<T>(child, visitor, recurse, node)\n }\n}\n\n/**\n * Eager depth-first collection pass. Gathers every non-null value the visitor\n * callbacks return into an array.\n *\n * @example Collect every operationId\n * ```ts\n * const ids = collectSync<string>(root, {\n * operation(node) {\n * return node.operationId\n * },\n * })\n * ```\n */\nexport function collectSync<T>(node: Node, options: CollectOptions<T>): Array<T> {\n return Array.from(collect(node, options))\n}\n","import type { VisitorDepth } from './constants.ts'\nimport type { VisitorKey } from './defineNode.ts'\nimport { visitorKeys } from './defineNode.ts'\nimport type { Node } from './nodes/index.ts'\nimport type { Visitor, VisitorContext } from './visitor.ts'\nimport { transform } from './visitor.ts'\n\n/**\n * Ordering hint shared by macros and plugins. `pre` runs before unmarked items, `post` after,\n * and `undefined` keeps declaration order.\n */\nexport type Enforce = 'pre' | 'post'\n\n/**\n * Sort weight for an `enforce` hint. `pre` sorts before unmarked items and `post` after, so a plain\n * list keeps its authored order.\n */\nfunction enforceWeight(enforce?: Enforce): number {\n if (enforce === 'pre') return 0\n if (enforce === 'post') return 2\n return 1\n}\n\n/**\n * A named, composable transform over the Kubb AST. It carries the same per-kind callbacks as a\n * {@link Visitor} (`schema`, `operation`, …), plus a `name`, an optional `enforce` order, and an\n * optional `match` predicate. Macros run on the shared AST, so the same macro works across every\n * adapter and output target. Exports follow the `macro<Name>` convention, mirroring plugins (`pluginTs`).\n */\nexport type Macro = Visitor & {\n /**\n * Macro identifier used to tell macros apart, for example `'simplify-union'`.\n */\n name: string\n /**\n * Ordering hint. `pre` macros run before unmarked macros, `post` macros run after.\n * Ordering within a bucket follows list order.\n */\n enforce?: Enforce\n /**\n * Predicate checked against the current node before any callback runs. Returning `false`\n * skips the macro for that node.\n */\n match?: (node: Node) => boolean\n}\n\n/**\n * Types a macro for inference and a single construction site, mirroring `definePlugin`.\n * Adds no runtime behavior.\n *\n * @example\n * ```ts\n * const macroUntagged = defineMacro({\n * name: 'untagged',\n * operation(node) {\n * return node.tags?.length ? undefined : { ...node, tags: ['untagged'] }\n * },\n * })\n * ```\n */\nexport function defineMacro(macro: Macro): Macro {\n return macro\n}\n\ntype MacroCallback = (node: Node, context: VisitorContext) => Node | null | undefined\n\ntype ChainProps = {\n macros: ReadonlyArray<Macro>\n key: VisitorKey\n node: Node\n context: VisitorContext\n}\n\n/**\n * Runs every macro's callback for one node kind in order, chaining the result so each macro sees\n * the previous macro's output. Returns `undefined` when nothing changed, so `transform` keeps the\n * original reference (structural sharing).\n */\nfunction chain({ macros, key, node, context }: ChainProps): Node | undefined {\n let current = node\n\n for (const macro of macros) {\n const callback = macro[key] as MacroCallback | undefined\n if (!callback) continue\n if (macro.match && !macro.match(current)) continue\n\n const next = callback(current, context)\n if (next != null) current = next\n }\n\n return current === node ? undefined : current\n}\n\n/**\n * Folds an ordered list of macros into a single {@link Visitor} that `transform` (and the per-plugin\n * transform layer in `@kubb/core`) can run. Macros are stable-sorted by `enforce`, then applied\n * sequentially per node so later macros see earlier output. This differs from a plain visitor, which\n * has no names, ordering, or composition.\n *\n * @example\n * ```ts\n * const visitor = composeMacros([macroSimplifyUnion, macroDiscriminatorEnum])\n * const next = transform(root, visitor)\n * ```\n */\nexport function composeMacros(macros: ReadonlyArray<Macro>): Visitor {\n const ordered = [...macros].sort((a, b) => enforceWeight(a.enforce) - enforceWeight(b.enforce))\n\n const visitor: Visitor = {}\n for (const key of visitorKeys) {\n if (!ordered.some((macro) => typeof macro[key] === 'function')) continue\n\n const callback = (node: Node, context: VisitorContext) => chain({ macros: ordered, key, node, context })\n ;(visitor as Record<VisitorKey, MacroCallback>)[key] = callback\n }\n\n return visitor\n}\n\n/**\n * Runs a list of macros over a node tree and returns the rewritten tree. Keeps `transform`'s\n * structural sharing, so an empty or no-op macro list returns the same reference. Pass\n * `depth: 'shallow'` to rewrite the root node only.\n *\n * @example\n * ```ts\n * const next = applyMacros(root, [macroIntegerToString])\n * ```\n *\n * @example Apply to the root node only\n * ```ts\n * const named = applyMacros(node, [macroEnumName({ parentName, propName, enumSuffix })], { depth: 'shallow' })\n * ```\n */\nexport function applyMacros<TNode extends Node>(root: TNode, macros: ReadonlyArray<Macro>, options?: { depth?: VisitorDepth }): TNode {\n if (macros.length === 0) return root\n\n return transform(root, { ...composeMacros(macros), ...options }) as TNode\n}\n","import type { ImportNode } from './nodes/file.ts'\nimport type { SchemaNode, SchemaNodeByType, SchemaType } from './nodes/schema.ts'\n\n/**\n * Runtime context passed as `this` to printer handlers.\n *\n * `this.transform` dispatches to node-level handlers from `nodes`.\n *\n * @example\n * ```ts\n * const context: PrinterHandlerContext<string, {}> = {\n * options: {},\n * transform: () => 'value',\n * base: () => 'value',\n * }\n * ```\n */\ntype PrinterHandlerContext<TOutput, TOptions extends object> = {\n /**\n * Recursively transform a nested `SchemaNode` to `TOutput` using the node-level handlers.\n * Use `this.transform` inside `nodes` handlers and inside the `print` override.\n */\n transform: (node: SchemaNode) => TOutput | null\n /**\n * Run the printer's built-in handler for the node, ignoring any override for its type.\n * Inside an override, `this.base(node)` returns what the printer would have emitted,\n * so the override can wrap it instead of re-implementing the handler. Nested nodes\n * still dispatch through the overrides.\n */\n base: (node: SchemaNode) => TOutput | null\n /** Declares an import the printed code needs. The generator reads it back with `printer.drainImports()`. */\n import: (node: ImportNode) => void\n /**\n * Options for this printer instance.\n */\n options: TOptions\n}\n\n/**\n * Handler for one schema node type.\n *\n * Use a regular function (not an arrow function) if you need `this`.\n *\n * @example\n * ```ts\n * const handler: PrinterHandler<string, {}, 'string'> = function () {\n * return 'string'\n * }\n * ```\n */\ntype PrinterHandler<TOutput, TOptions extends object, T extends SchemaType = SchemaType> = (\n this: PrinterHandlerContext<TOutput, TOptions>,\n node: SchemaNodeByType[T],\n) => TOutput | null\n\n/**\n * Partial map of per-node-type handler overrides for a printer.\n *\n * Each key is a `SchemaType` string (e.g. `'date'`, `'string'`).\n * Supply only the handlers you want to replace. The printer's built-in\n * defaults fill in the rest.\n *\n * @example\n * ```ts\n * pluginZod({\n * printer: {\n * nodes: {\n * date(): string {\n * return 'z.string().date()'\n * },\n * } satisfies PrinterPartial<string, PrinterZodOptions>,\n * },\n * })\n * ```\n */\nexport type PrinterPartial<TOutput, TOptions extends object> = Partial<{\n [K in SchemaType]: PrinterHandler<TOutput, TOptions, K>\n}>\n\n/**\n * Generic shape used by `definePrinter`.\n *\n * - `TName` unique string identifier (e.g. `'zod'`, `'ts'`)\n * - `TOptions` options passed to and stored on the printer instance\n * - `TOutput` the type emitted by node handlers\n * - `TPrintOutput` type returned by public `print` (defaults to `TOutput`)\n *\n * @example\n * ```ts\n * type MyPrinter = PrinterFactoryOptions<'my', { strict: boolean }, string>\n * ```\n */\nexport type PrinterFactoryOptions<TName extends string = string, TOptions extends object = object, TOutput = unknown, TPrintOutput = TOutput> = {\n name: TName\n options: TOptions\n output: TOutput\n printOutput: TPrintOutput\n}\n\n/**\n * Printer instance returned by a printer factory.\n *\n * @example\n * ```ts\n * const printer = definePrinter((options: {}) => ({ name: 'x', options, nodes: {} }))({})\n * ```\n */\nexport type Printer<T extends PrinterFactoryOptions = PrinterFactoryOptions> = {\n /**\n * Unique identifier supplied at creation time.\n */\n name: T['name']\n /**\n * Options for this printer instance.\n */\n options: T['options']\n /**\n * Node-level dispatcher, converts a `SchemaNode` directly to `TOutput` using the `nodes` handlers.\n * Always dispatches through the `nodes` map. Never calls the `print` override.\n * Reach for it when you need the raw output (e.g. `ts.TypeNode`) without declaration wrapping.\n */\n transform: (node: SchemaNode) => T['output'] | null\n /**\n * Public printer. If the builder provides a root-level `print`, this calls that\n * higher-level function (which may produce full declarations).\n * Otherwise, falls back to the node-level dispatcher.\n */\n print: (node: SchemaNode) => T['printOutput'] | null\n /** Returns the imports declared with `this.import(...)` since the last call, then clears them. */\n drainImports: () => Array<ImportNode>\n}\n\n/**\n * Builder function passed to `definePrinter`.\n *\n * It receives resolved options and returns:\n * - `name`\n * - `options`\n * - `nodes` handlers\n * - optional top-level `print` override\n *\n * @example\n * ```ts\n * const build = (options: {}) => ({ name: 'x' as const, options, nodes: {} })\n * ```\n */\ntype PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) => {\n name: T['name']\n /**\n * Options to store on the printer.\n */\n options: T['options']\n nodes: PrinterPartial<T['output'], T['options']>\n /**\n * User-supplied handler overrides. An override wins over the matching `nodes` handler,\n * and can call `this.base(node)` to reuse the handler it replaced. Pass overrides here\n * instead of spreading them into `nodes`, otherwise `this.base` cannot find the original.\n */\n overrides?: PrinterPartial<T['output'], T['options']>\n /**\n * Optional root-level print override. When provided, becomes the public `printer.print`.\n * Use `this.transform(node)` inside this function to dispatch to the node-level handlers (`nodes`),\n * not the override itself, so recursion is safe.\n */\n print?: (this: PrinterHandlerContext<T['output'], T['options']>, node: SchemaNode) => T['printOutput'] | null\n}\n/**\n * Creates a schema printer: a function that takes a `SchemaNode` and emits\n * code in your target language. Each plugin that produces code from schemas\n * (TypeScript types, Zod schemas, Faker factories) ships a printer built\n * with this helper.\n *\n * The builder receives resolved options and returns:\n *\n * - `name` unique identifier for the printer.\n * - `options` stored on the returned printer instance.\n * - `nodes` map of `SchemaType` → handler. Handlers return the rendered\n * output (a string, a TypeScript AST node, ...) for that schema type.\n * - `overrides` (optional), user-supplied handlers that win over `nodes`.\n * An override can call `this.base(node)` to reuse the handler it replaced.\n * - `print` (optional), top-level override exposed as `printer.print`.\n * Use `this.transform(node)` inside it to dispatch to `nodes` recursively.\n *\n * Without a `print` override, `printer.print` falls back to `printer.transform`\n * (the node-level dispatcher).\n *\n * @example Tiny Zod printer\n * ```ts\n * import { createPrinter, type PrinterFactoryOptions } from '@kubb/ast'\n *\n * type PrinterZod = PrinterFactoryOptions<'zod', { strict?: boolean }, string>\n *\n * export const zodPrinter = createPrinter<PrinterZod>((options) => ({\n * name: 'zod',\n * options: { strict: options.strict ?? true },\n * nodes: {\n * string: () => 'z.string()',\n * object(node) {\n * const props = node.properties\n * .map((p) => `${p.name}: ${this.transform(p.schema)}`)\n * .join(', ')\n * return `z.object({ ${props} })`\n * },\n * },\n * }))\n * ```\n */\nexport function createPrinter<T extends PrinterFactoryOptions = PrinterFactoryOptions>(build: PrinterBuilder<T>): (options?: T['options']) => Printer<T> {\n return (options) => {\n const { name, options: resolvedOptions, nodes, overrides, print: printOverride } = build((options ?? {}) as T['options'])\n const merged = overrides ? { ...nodes, ...overrides } : nodes\n\n const collectedImports: Array<ImportNode> = []\n\n const dispatch =\n (table: PrinterPartial<T['output'], T['options']>) =>\n (node: SchemaNode): T['output'] | null => {\n const handler = table[node.type]\n if (!handler) return null\n\n return (handler as (this: PrinterHandlerContext<T['output'], T['options']>, node: SchemaNode) => T['output'] | null).call(context, node)\n }\n\n const context: PrinterHandlerContext<T['output'], T['options']> = {\n options: resolvedOptions,\n import: (node: ImportNode): void => {\n collectedImports.push(node)\n },\n transform: dispatch(merged),\n base: dispatch(nodes),\n }\n\n return {\n name,\n options: resolvedOptions,\n transform: context.transform,\n print: (printOverride ? printOverride.bind(context) : context.transform) as (node: SchemaNode) => T['printOutput'] | null,\n drainImports: () => collectedImports.splice(0),\n }\n }\n}\n","import type { RefSchemaNode, SchemaNode } from '../nodes/schema.ts'\n\n/**\n * Resolves the emitted name of the schema a ref node points at. Prefers `targetName` (set when\n * the referenced schema was renamed, e.g. to break a collision), then the last segment of `ref`,\n * then `name`, then the nested `schema.name`.\n *\n * Returns `null` for non-ref nodes or when no name resolves.\n *\n * @example\n * `resolveRefName({ kind: 'Schema', type: 'ref', ref: '#/components/schemas/Pet' }) // 'Pet'`\n *\n * @example Collision-renamed target\n * `resolveRefName({ kind: 'Schema', type: 'ref', ref: '#/components/schemas/Order', targetName: 'OrderSchema' }) // 'OrderSchema'`\n */\nexport function resolveRefName(node: SchemaNode | null | undefined): string | null {\n if (!node || node.type !== 'ref') return null\n if (node.targetName) return node.targetName\n if (node.ref) return node.ref.split('/').at(-1) ?? node.ref\n\n return node.name ?? node.schema?.name ?? null\n}\n\n/**\n * Merges a ref node with its resolved schema, giving the fields set at the usage site precedence.\n *\n * Every field on the ref except `kind`, `type`, `name`, `ref`, and `schema` overrides the same field\n * of the resolved `schema` (for example `description`, `nullable`, `readOnly`, `deprecated`). Fields\n * left `undefined` on the ref do not shadow the resolved schema. A ref without a resolved `schema`\n * is returned as is.\n *\n * @example\n * ```ts\n * const ref = createSchema({ type: 'ref', ref: '#/components/schemas/Pet', description: 'A pet', schema: petSchema })\n * mergeRefWithSchema(ref) // petSchema's fields with description 'A pet'\n * ```\n */\nexport function mergeRefWithSchema(node: RefSchemaNode): SchemaNode {\n if (!node.schema) return node\n\n const { kind: _kind, type: _type, name: _name, ref: _ref, schema: _schema, ...overrides } = node\n const definedOverrides = Object.fromEntries(Object.entries(overrides).filter(([, value]) => value !== undefined))\n\n return { ...node.schema, ...definedOverrides }\n}\n\n/**\n * Returns `true` when a schema is a bare ref without modifiers, metadata, or omit keys.\n *\n * Modifiers inherited from the resolved schema are included in the check because a ref emits the\n * referenced schema variable with those modifiers already applied.\n */\nexport function isBareRef(node: SchemaNode | null | undefined, keysToOmit?: Array<string> | null): boolean {\n if (!node || node.type !== 'ref') return false\n\n const meta = mergeRefWithSchema(node)\n\n return !meta.nullable && !meta.optional && !meta.nullish && meta.default === undefined && !meta.description && !meta.examples?.length && !keysToOmit?.length\n}\n","/** A value that may already be resolved or still pending.\n *\n * @example\n * ```ts\n * function load(id: string): PossiblePromise<string> {\n * return cache.get(id) ?? fetchRemote(id)\n * }\n * ```\n */\nexport type PossiblePromise<T> = Promise<T> | T\n\n/** Returns `true` when `result` is a thenable `Promise`.\n *\n * @example\n * ```ts\n * isPromise(Promise.resolve(1)) // true\n * isPromise(42) // false\n * ```\n */\nexport function isPromise<T>(result: PossiblePromise<T>): result is Promise<T> {\n return result !== null && result !== undefined && typeof (result as Record<string, unknown>)['then'] === 'function'\n}\n\ntype Store<TKey, TValue> = {\n has(key: TKey): boolean\n get(key: TKey): TValue | undefined\n set(key: TKey, value: TValue): unknown\n}\n\n/**\n * Wraps `factory` with a keyed cache backed by the provided store.\n *\n * Pass a `WeakMap` for object keys (results are GC-eligible when the key is\n * collected) or a `Map` for primitive keys. For multi-argument functions,\n * nest two `memoize` calls — the outer keyed by the first argument, the\n * inner (created once per outer miss) keyed by the second.\n *\n * Because the cache is owned by the caller, it can be shared, inspected, or\n * cleared independently of the memoized function.\n *\n * @example Single WeakMap key\n * ```ts\n * const cache = new WeakMap<SchemaNode, Set<string>>()\n * const getRefs = memoize(cache, (node) => collectRefs(node))\n * ```\n *\n * @example Single Map key (primitive)\n * ```ts\n * const cache = new Map<string, Resolver>()\n * const getResolver = memoize(cache, (name) => buildResolver(name))\n * ```\n *\n * @example Two-level (object + primitive)\n * ```ts\n * const outer = new WeakMap<Params[], Map<string, Params[]>>()\n * const fn = memoize(outer, (params) => memoize(new Map(), (key) => transform(params, key)))\n * fn(params)('camelcase')\n * ```\n */\nexport function memoize<TKey, TValue>(store: Store<TKey, TValue>, factory: (key: TKey) => TValue): (key: TKey) => TValue {\n return (key: TKey): TValue => {\n if (store.has(key)) return store.get(key)!\n const value = factory(key)\n store.set(key, value)\n return value\n }\n}\n\ntype ParallelOptions<TItem> = {\n /**\n * Items to work through, handed out in order.\n */\n items: ReadonlyArray<TItem>\n /**\n * How many items may be in flight at once.\n */\n limit: number\n /**\n * Runs once per item, with the item's position so a caller can report progress.\n */\n run(item: TItem, index: number): Promise<void>\n}\n\n/**\n * Runs `run` over every item with at most `limit` in flight. Workers share one iterator, so each\n * takes the next item the moment it frees up instead of waiting for a batch to drain.\n *\n * @example\n * ```ts\n * await inParallel({ items: files, limit: 50, run: (file) => storage.writeItem(file.path, file.source) })\n * ```\n */\nexport async function inParallel<TItem>({ items, limit, run }: ParallelOptions<TItem>): Promise<void> {\n const queue = items.entries()\n\n const worker = async (): Promise<void> => {\n for (const [index, item] of queue) await run(item, index)\n }\n\n await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => worker()))\n}\n","import { memoize } from '@internals/utils'\nimport type { OperationNode } from '../nodes/operation.ts'\nimport type { SchemaNode } from '../nodes/schema.ts'\nimport { collect, collectSync } from '../visitor.ts'\nimport { resolveRefName } from './refs.ts'\n\n/**\n * Collects the names of every schema a node's subtree references, resolved with `resolveRefName`.\n * Each ref contributes its name only, so the schema it points to is never traversed. The walk is\n * memoized by node identity, which lets `findCircularSchemas` and `containsCircularRef` share one\n * scan per schema.\n *\n * @example\n * ```ts\n * collectSchemaRefs(petSchema)\n * // Set { 'Category', 'Tag' }\n * ```\n */\nexport const collectSchemaRefs = memoize(new WeakMap<SchemaNode, ReadonlySet<string>>(), (node: SchemaNode): ReadonlySet<string> => {\n const refs = new Set<string>()\n collectSync<void>(node, {\n schema(child) {\n if (child.type === 'ref') {\n const name = resolveRefName(child)\n if (name) refs.add(name)\n }\n },\n })\n return refs\n})\n\n/**\n * Collects the de-duplicated target names of every pointer-carrying ref in a node's subtree, in\n * first-occurrence order. The walk is memoized by node identity, so the subtree is scanned once and\n * `resolver.imports` reads the same result across the ts, zod, and faker plugins instead of\n * re-scanning the same schema per plugin.\n *\n * Only refs that carry a `$ref` pointer count, so a synthesized ref pointing at a sibling in the\n * same file (a union member created by name) is left out. That leaves exactly the set\n * `resolver.imports` emits.\n *\n * @example\n * ```ts\n * collectImportedRefNames(petSchema)\n * // ['Category', 'Tag']\n * ```\n */\nexport const collectImportedRefNames = memoize(new WeakMap<SchemaNode, ReadonlyArray<string>>(), (node: SchemaNode): ReadonlyArray<string> => {\n const seen = new Set<string>()\n const names: Array<string> = []\n collectSync<void>(node, {\n schema(child) {\n if (child.type !== 'ref' || !child.ref) return\n const name = resolveRefName(child)\n if (name && !seen.has(name)) {\n seen.add(name)\n names.push(name)\n }\n },\n })\n return names\n})\n\n/**\n * Collects the names of all top-level schemas transitively used by a set of operations.\n *\n * An operation uses a schema when its parameters, request body, or responses reference it, directly\n * or through other named schemas. Once a name is added to the result it is not revisited, so\n * reference cycles terminate.\n *\n * Pair it with `include` filters so schemas reachable only from excluded operations stay ungenerated.\n *\n * @example Only generate schemas referenced by included operations\n * ```ts\n * const includedOps = operations.filter((op) => resolver.default.options(op, { options, include }) !== null)\n * const allowed = collectUsedSchemaNames(includedOps, schemas)\n *\n * for (const schema of schemas) {\n * if (schema.name && !allowed.has(schema.name)) continue\n * // generate schema\n * }\n * ```\n */\nexport function collectUsedSchemaNames(operations: ReadonlyArray<OperationNode>, schemas: ReadonlyArray<SchemaNode>): Set<string> {\n const schemaMap = new Map<string, SchemaNode>()\n for (const schema of schemas) {\n if (schema.name) schemaMap.set(schema.name, schema)\n }\n\n const result = new Set<string>()\n\n function visitSchema(schema: SchemaNode): void {\n for (const name of collectSchemaRefs(schema)) {\n if (!result.has(name)) {\n result.add(name)\n const namedSchema = schemaMap.get(name)\n if (namedSchema) visitSchema(namedSchema)\n }\n }\n }\n\n for (const op of operations) {\n for (const schema of collect<SchemaNode>(op, { depth: 'shallow', schema: (node) => node })) {\n visitSchema(schema)\n }\n }\n\n return result\n}\n\n/**\n * Finds every schema that takes part in a circular dependency chain in a schema dependency graph\n * that maps each schema name to the names it references directly.\n *\n * Use this when the graph was already collected during another pass (e.g. the adapter's convert\n * walk), so the schema nodes are not swept a second time. `findCircularSchemas` builds the graph\n * from schema nodes and delegates here.\n *\n * @example\n * ```ts\n * const graph = new Map([\n * ['Pet', new Set(['Category'])],\n * ['Category', new Set(['Pet'])],\n * ])\n * findCircularSchemasFromGraph(graph) // Set { 'Pet', 'Category' }\n * ```\n */\nexport function findCircularSchemasFromGraph(graph: ReadonlyMap<string, ReadonlySet<string>>): Set<string> {\n const circular = new Set<string>()\n for (const start of graph.keys()) {\n const visited = new Set<string>()\n const stack: Array<string> = [...(graph.get(start) ?? [])]\n while (stack.length > 0) {\n const node = stack.pop()!\n if (node === start) {\n circular.add(start)\n break\n }\n if (visited.has(node)) continue\n visited.add(node)\n\n const next = graph.get(node)\n if (next) for (const r of next) stack.push(r)\n }\n }\n\n return circular\n}\n\n/**\n * Finds every schema that takes part in a circular dependency chain, including direct self-loops.\n *\n * Wrap the returned schema positions in a deferred construct (a lazy getter or `z.lazy(() => …)`) so\n * the generated code does not recurse forever. Refs are followed by name only, so the walk stays\n * linear in the size of the schema graph.\n *\n * @note Call this once on the full graph, then check individual schemas with `containsCircularRef()`.\n */\nexport function findCircularSchemas(schemas: ReadonlyArray<SchemaNode>): Set<string> {\n const graph = new Map<string, ReadonlySet<string>>()\n for (const schema of schemas) {\n if (schema.name) graph.set(schema.name, collectSchemaRefs(schema))\n }\n\n return findCircularSchemasFromGraph(graph)\n}\n","import type { PropertyNode } from '../nodes/property.ts'\nimport type { SchemaNode } from '../nodes/schema.ts'\n\n/**\n * Finds every matching property exposed by an object, resolved reference, or intersection.\n *\n * References are followed through their parsed `schema`. Circular references terminate without\n * revisiting a node. Unions are not traversed because a property on one branch does not describe\n * every branch.\n *\n * @example Faker discriminator narrowing\n * ```ts\n * const values = resolveSchemaProperties({ node: member, propertyName: union.discriminatorPropertyName }).flatMap(({ schema }) =>\n * getSchemaLiteralValues(schema),\n * )\n * const typeName = `Extract<Pet, { type: ${values.map(JSON.stringify).join(' | ')} }>`\n * ```\n *\n * @example Zod discriminated unions\n * ```ts\n * const canDiscriminate = union.members?.every(\n * (member) => resolveSchemaProperties({ node: member, propertyName: 'type' }).length > 0,\n * )\n * const expression = canDiscriminate ? `z.discriminatedUnion('type', members)` : `z.union(members)`\n * ```\n *\n * @example TypeScript property lookup\n * ```ts\n * const properties = resolveSchemaProperties({ node: schema, propertyName: 'status' })\n * const statusSchemas = properties.map((property) => print(property.schema))\n * ```\n */\nexport function resolveSchemaProperties({ node, propertyName }: { node: SchemaNode; propertyName: string }): ReadonlyArray<PropertyNode> {\n const properties: Array<PropertyNode> = []\n const visited = new WeakSet<SchemaNode>()\n\n function visit(current: SchemaNode | null | undefined): void {\n if (!current || visited.has(current)) return\n visited.add(current)\n\n if (current.type === 'object') {\n const property = current.properties.find((candidate) => candidate.name === propertyName)\n if (property) properties.push(property)\n return\n }\n\n if (current.type === 'ref') {\n visit(current.schema)\n return\n }\n\n if (current.type === 'intersection') {\n for (const member of current.members ?? []) visit(member)\n }\n }\n\n visit(node)\n return properties\n}\n\n/**\n * Reads the unique literal values represented by an enum, resolved reference, or union.\n *\n * Named enum values take precedence over simple enum values, matching how renderers consume\n * `EnumSchemaNode`.\n *\n * @example\n * ```ts\n * const values = getSchemaLiteralValues(enumNode)\n * // ['cat', 'dog']\n * ```\n */\nexport function getSchemaLiteralValues(node: SchemaNode): ReadonlyArray<string | number | boolean | null> {\n const values = new Set<string | number | boolean | null>()\n const visited = new WeakSet<SchemaNode>()\n\n function visit(current: SchemaNode | null | undefined): void {\n if (!current || visited.has(current)) return\n visited.add(current)\n\n if (current.type === 'enum') {\n const enumValues = current.namedEnumValues?.map(({ value }) => value) ?? current.enumValues ?? []\n for (const value of enumValues) values.add(value)\n return\n }\n\n if (current.type === 'ref') {\n visit(current.schema)\n return\n }\n\n if (current.type === 'union') {\n for (const member of current.members ?? []) visit(member)\n }\n }\n\n visit(node)\n return [...values]\n}\n\n// Names of every property an object, resolved reference, or intersection exposes.\nfunction collectPropertyNames(node: SchemaNode, visited: WeakSet<SchemaNode> = new WeakSet()): Set<string> {\n if (visited.has(node)) return new Set()\n visited.add(node)\n\n if (node.type === 'object') return new Set(node.properties.map((property) => property.name))\n if (node.type === 'ref') return node.schema ? collectPropertyNames(node.schema, visited) : new Set()\n\n if (node.type === 'intersection') {\n const names = new Set<string>()\n for (const member of node.members ?? []) {\n for (const name of collectPropertyNames(member, visited)) names.add(name)\n }\n return names\n }\n\n return new Set()\n}\n\n/**\n * Infers an implicit discriminator: a property every member exposes with a distinct single\n * literal value, the same shape a declared OpenAPI `discriminator` already narrows on.\n */\nexport function inferDiscriminatorPropertyName(members: ReadonlyArray<SchemaNode>): string | undefined {\n if (members.length < 2) return undefined\n\n let candidates: Set<string> | undefined\n for (const member of members) {\n const names = collectPropertyNames(member)\n candidates = candidates ? new Set([...candidates].filter((name) => names.has(name))) : names\n }\n\n for (const name of candidates ?? []) {\n const values = members.map((member) => {\n const literals = new Set(resolveSchemaProperties({ node: member, propertyName: name }).flatMap((property) => getSchemaLiteralValues(property.schema)))\n return literals.size === 1 ? [...literals][0] : undefined\n })\n\n if (values.every((value) => value !== undefined) && new Set(values).size === members.length) {\n return name\n }\n }\n\n return undefined\n}\n","import type { Node } from './nodes/index.ts'\n\nexport { createArrowFunction, createBreak, createConst, createFunction, createJsx, createText, createType } from './nodes/code.ts'\nexport { createContent } from './nodes/content.ts'\nexport { createExport, createFile, createImport, createSource } from './nodes/file.ts'\nexport type { UserFileNode } from './nodes/file.ts'\nexport { createInput } from './nodes/input.ts'\nexport { createOperation } from './nodes/operation.ts'\nexport { createOutput } from './nodes/output.ts'\nexport { createParameter } from './nodes/parameter.ts'\nexport { createProperty } from './nodes/property.ts'\nexport { createRequestBody } from './nodes/requestBody.ts'\nexport { createResponse } from './nodes/response.ts'\nexport { createSchema } from './nodes/schema.ts'\n\n/**\n * Identity-preserving node update: returns `node` unchanged when every field in\n * `changes` already equals (by reference) the current value, otherwise a new node\n * with the changes applied.\n *\n * Mirrors the TypeScript compiler's `factory.updateX` contract. Pair it with the\n * structural sharing in {@link transform} so a no-op rewrite does not allocate and\n * downstream passes can detect \"nothing changed\" by identity. Comparison is shallow,\n * so a structurally equal but newly allocated array or object counts as a change.\n *\n * @example\n * ```ts\n * update(node, { name: node.name }) // -> same `node` reference\n * update(node, { name: 'renamed' }) // -> new node, `name` replaced\n * ```\n */\nexport function update<T extends Node>(node: T, changes: Partial<T>): T {\n for (const key in changes) {\n if (changes[key] !== node[key as keyof T]) {\n return { ...node, ...changes }\n }\n }\n\n return node\n}\n","export { schemaTypes } from './constants.ts'\nexport { isHttpOperationNode, narrowSchema } from './guards.ts'\nexport { applyMacros, composeMacros, defineMacro } from './defineMacro.ts'\nexport { defineNode } from './defineNode.ts'\nexport { optionality } from './optionality.ts'\nexport { createPrinter } from './createPrinter.ts'\nexport { collect, collectSync, transform } from './visitor.ts'\nexport { extractStringsFromNodes } from './utils/extractStringsFromNodes.ts'\nexport { isBareRef, mergeRefWithSchema, resolveRefName } from './utils/refs.ts'\nexport { collectImportedRefNames, collectSchemaRefs, collectUsedSchemaNames, findCircularSchemas, findCircularSchemasFromGraph } from './utils/schemaGraph.ts'\nexport { getSchemaLiteralValues, inferDiscriminatorPropertyName, resolveSchemaProperties } from './utils/schemaProperties.ts'\n\nexport * as factory from './factory.ts'\nexport * from './registry.ts'\nexport type * from './types.ts'\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/constants.ts","../src/guards.ts","../src/defineNode.ts","../src/nodes/code.ts","../src/nodes/content.ts","../src/utils/extractStringsFromNodes.ts","../src/utils/combineFileMembers.ts","../src/nodes/file.ts","../src/nodes/input.ts","../src/nodes/requestBody.ts","../src/nodes/operation.ts","../src/nodes/output.ts","../src/optionality.ts","../src/nodes/parameter.ts","../src/nodes/property.ts","../src/nodes/response.ts","../src/nodes/schema.ts","../src/registry.ts","../src/visitor.ts","../src/defineMacro.ts","../src/createPrinter.ts","../src/utils/refs.ts","../../../internals/utils/src/promise.ts","../src/utils/schemaGraph.ts","../src/utils/schemaProperties.ts","../src/factory.ts","../src/exports.ts"],"sourcesContent":["import type { SchemaType } from './nodes/schema.ts'\n\n/**\n * Traversal depth for AST visitor utilities.\n *\n * - `'shallow'` recurses through every node except nested `Schema` subtrees, which it treats as\n * leaves: a schema node itself is visited, but its children are not.\n * - `'deep'` recursively visits all descendant nodes, including schema subtrees.\n */\nexport type VisitorDepth = 'shallow' | 'deep'\n\nexport const visitorDepths = {\n shallow: 'shallow',\n deep: 'deep',\n} as const satisfies Record<VisitorDepth, VisitorDepth>\n\n/**\n * Schema type discriminators used by all AST schema nodes.\n *\n * Each value is a stable discriminator across the AST (for example `schema.type === schemaTypes.object`).\n */\nexport const schemaTypes = {\n /**\n * Text value.\n */\n string: 'string',\n /**\n * Floating-point number (`float`, `double`).\n */\n number: 'number',\n /**\n * Whole number (`int32`). Use `bigint` for `int64`.\n */\n integer: 'integer',\n /**\n * 64-bit integer (`int64`). Only used when `integerType` is set to `'bigint'`.\n */\n bigint: 'bigint',\n /**\n * Boolean value.\n */\n boolean: 'boolean',\n /**\n * Explicit null value.\n */\n null: 'null',\n /**\n * Any value (no type restriction).\n */\n any: 'any',\n /**\n * Unknown value (must be narrowed before usage).\n */\n unknown: 'unknown',\n /**\n * No return value (`void`).\n */\n void: 'void',\n /**\n * Object with named properties.\n */\n object: 'object',\n /**\n * Sequential list of items.\n */\n array: 'array',\n /**\n * Fixed-length list with position-specific items.\n */\n tuple: 'tuple',\n /**\n * \"One of\" multiple schema members.\n */\n union: 'union',\n /**\n * \"All of\" multiple schema members.\n */\n intersection: 'intersection',\n /**\n * Enum schema.\n */\n enum: 'enum',\n /**\n * Reference to another schema.\n */\n ref: 'ref',\n /**\n * Calendar date (for example `2026-03-24`).\n */\n date: 'date',\n /**\n * Date-time value (for example `2026-03-24T09:00:00Z`).\n */\n datetime: 'datetime',\n /**\n * Time-only value (for example `09:00:00`).\n */\n time: 'time',\n /**\n * UUID value.\n */\n uuid: 'uuid',\n /**\n * Email address value.\n */\n email: 'email',\n /**\n * URL value.\n */\n url: 'url',\n /**\n * IPv4 address value.\n */\n ipv4: 'ipv4',\n /**\n * IPv6 address value.\n */\n ipv6: 'ipv6',\n /**\n * Binary/blob value.\n */\n blob: 'blob',\n /**\n * Impossible value (`never`).\n */\n never: 'never',\n} as const satisfies Record<SchemaType, SchemaType>\n","import type { HttpOperationNode, OperationNode } from './nodes/operation.ts'\nimport type { SchemaNode, SchemaNodeByType } from './nodes/schema.ts'\n\n/**\n * Narrows a `SchemaNode` to the variant that matches `type`.\n *\n * @example\n * ```ts\n * const schema = createSchema({ type: 'string' })\n * const stringNode = narrowSchema(schema, 'string') // StringSchemaNode | null\n * ```\n */\nexport function narrowSchema<T extends SchemaNode['type']>(node: SchemaNode | undefined, type: T): SchemaNodeByType[T] | null {\n return node?.type === type ? (node as SchemaNodeByType[T]) : null\n}\n\n/**\n * Narrows an `OperationNode` to an `HttpOperationNode` so `method` and `path` are present.\n *\n * @example\n * ```ts\n * if (isHttpOperationNode(node)) {\n * console.log(node.method, node.path)\n * }\n * ```\n */\nexport function isHttpOperationNode(node: OperationNode): node is HttpOperationNode {\n return node.protocol === 'http' || (node.method !== undefined && node.path !== undefined)\n}\n","import type { BaseNode, NodeKind } from './nodes/base.ts'\n\n/**\n * Visitor callback names, one per traversable node kind, in traversal order.\n * Kept in sync with the keys of `Visitor` in `visitor.ts`.\n */\nexport const visitorKeys = ['input', 'output', 'operation', 'schema', 'property', 'parameter', 'response'] as const\n\n/**\n * One of the {@link visitorKeys} callback names.\n */\nexport type VisitorKey = (typeof visitorKeys)[number]\n\n/**\n * Distributive `Omit` that preserves each member of a union.\n *\n * @example\n * ```ts\n * type A = { kind: 'a'; keep: string; drop: number }\n * type B = { kind: 'b'; keep: boolean; drop: number }\n * type Result = DistributiveOmit<A | B, 'drop'>\n * // -> { kind: 'a'; keep: string } | { kind: 'b'; keep: boolean }\n * ```\n */\nexport type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never\n\n/**\n * Builds a type guard that matches nodes of the given `kind`.\n */\nfunction isKind<T extends BaseNode>(kind: NodeKind) {\n return (node: unknown): node is T => (node as BaseNode | undefined)?.kind === kind\n}\n\n/**\n * The single definition derived from one {@link defineNode} call: the node's\n * `create` builder, its `is` guard, and the traversal metadata the registry\n * collects into the visitor tables.\n */\nexport type NodeDef<TNode extends BaseNode = BaseNode, TInput = never> = {\n /**\n * Node discriminator this definition owns.\n */\n kind: NodeKind\n /**\n * Builds a node from its input, applying `defaults` and the optional `build` hook.\n */\n create: (input: TInput) => TNode\n /**\n * Type guard matching this node kind.\n */\n is: (node: unknown) => node is TNode\n /**\n * Child node fields in traversal order. Feeds `VISITOR_KEYS`.\n */\n children?: ReadonlyArray<string>\n /**\n * Visitor callback name. Feeds `VISITOR_KEY_BY_KIND`.\n */\n visitorKey?: VisitorKey\n}\n\ntype DefineNodeConfig<TNode extends BaseNode, TInput, TBuilt extends object> = {\n kind: TNode['kind']\n defaults?: Partial<TNode>\n build?: (input: TInput) => TBuilt\n children?: ReadonlyArray<string>\n visitorKey?: VisitorKey\n}\n\n/**\n * Defines a node once and derives its `create` builder, `is` guard, and traversal\n * metadata. `create` merges `defaults`, the `build` hook (or the raw input), and the\n * `kind`, so node construction lives in one place without scattered `as` casts.\n *\n * @example Simple node\n * ```ts\n * const importDef = defineNode<ImportNode>({ kind: 'Import' })\n * const createImport = importDef.create\n * ```\n *\n * @example Node with a build hook\n * ```ts\n * const propertyDef = defineNode<PropertyNode, UserPropertyNode>({\n * kind: 'Property',\n * build: (props) => ({ ...props, required: props.required ?? false }),\n * children: ['schema'],\n * visitorKey: 'property',\n * })\n * ```\n */\nexport function defineNode<TNode extends BaseNode, TInput = Omit<TNode, 'kind'>, TBuilt extends object = Omit<TNode, 'kind'>>(\n config: DefineNodeConfig<TNode, TInput, TBuilt>,\n): NodeDef<TNode, TInput> {\n const { kind, defaults, build, children, visitorKey } = config\n\n function create(input: TInput): TNode {\n const base = build ? build(input) : input\n // `kind` is written first so the discriminant lands at a fixed in-object offset for every node\n // of this kind. Hot dispatch paths (`transform`, `walk`, the parser printers) read `node.kind`\n // constantly; a trailing-only `kind` floats its offset with each node's field count and turns\n // those reads megamorphic. The post-spread reassignment keeps `kind` authoritative when an input\n // carries a (wrong) `kind`: it overwrites the offset-0 slot in place without reshaping the node.\n const built = { kind, ...defaults, ...(base as object) }\n const node = built as TNode\n node.kind = kind\n return node\n }\n\n return { kind, create, is: isKind<TNode>(kind), children, visitorKey }\n}\n","import { defineNode } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\n\n/**\n * JSDoc documentation metadata attached to code declarations.\n */\nexport type JSDocNode = {\n /**\n * JSDoc comment lines. `undefined` entries are filtered out during rendering.\n *\n * @example\n * ```ts\n * ['@description A pet resource', '@deprecated']\n * ```\n */\n comments?: Array<string | undefined>\n}\n\n/**\n * AST node representing a TypeScript `const` declaration.\n *\n * Mirrors the props of the `Const` component from `@kubb/renderer-jsx`.\n * The `children` prop of the component is represented as `nodes`.\n *\n * @example\n * ```ts\n * createConst({ name: 'pet', export: true, asConst: true })\n * // export const pet = ... as const\n * ```\n */\nexport type ConstNode = BaseNode & {\n kind: 'Const'\n /**\n * Name of the constant declaration.\n */\n name: string\n /**\n * Whether the declaration should be exported.\n */\n export?: boolean | null\n /**\n * Explicit type annotation.\n *\n * @example Type reference\n * `'Pet'`\n */\n type?: string | null\n /**\n * JSDoc documentation metadata.\n */\n JSDoc?: JSDocNode | null\n /**\n * Whether to append `as const` to the declaration.\n */\n asConst?: boolean | null\n /**\n * Child nodes representing the value of the constant (children of the `Const` component).\n * Each entry is a {@link CodeNode}. Use {@link TextNode} for raw string content.\n */\n nodes?: Array<CodeNode>\n}\n\n/**\n * AST node representing a TypeScript `type` alias declaration.\n *\n * Mirrors the props of the `Type` component from `@kubb/renderer-jsx`.\n * The `children` prop of the component is represented as `nodes`.\n *\n * @example\n * ```ts\n * createType({ name: 'Pet', export: true })\n * // export type Pet = ...\n * ```\n */\nexport type TypeNode = BaseNode & {\n kind: 'Type'\n /**\n * Name of the type alias.\n */\n name: string\n /**\n * Whether the declaration should be exported.\n */\n export?: boolean | null\n /**\n * JSDoc documentation metadata.\n */\n JSDoc?: JSDocNode | null\n /**\n * Child nodes representing the type body (children of the `Type` component).\n * Each entry is a {@link CodeNode}. Use {@link TextNode} for raw string content.\n */\n nodes?: Array<CodeNode>\n}\n\n/**\n * AST node representing a TypeScript `function` declaration.\n *\n * Mirrors the props of the `Function` component from `@kubb/renderer-jsx`.\n * The `children` prop of the component is represented as `nodes`.\n *\n * @example\n * ```ts\n * createFunction({ name: 'getPet', export: true, async: true, returnType: 'Pet' })\n * // export async function getPet(): Promise<Pet> { ... }\n * ```\n */\nexport type FunctionNode = BaseNode & {\n kind: 'Function'\n /**\n * Name of the function.\n */\n name: string\n /**\n * Whether the function is a default export.\n */\n default?: boolean | null\n /**\n * Function parameter list as a pre-rendered string, written verbatim between the parentheses.\n *\n * @example\n * `'id: string, config: Config = {}'`\n */\n params?: string | null\n /**\n * Whether the function should be exported.\n */\n export?: boolean | null\n /**\n * Whether the function is async. When `true`, the return type is wrapped in `Promise<>`.\n */\n async?: boolean | null\n /**\n * TypeScript generic type parameters.\n *\n * @example Constrained generics\n * `['T', 'U extends string']`\n */\n generics?: string | Array<string> | null\n /**\n * Return type annotation.\n *\n * @example Type reference\n * `'Pet'`\n */\n returnType?: string | null\n /**\n * JSDoc documentation metadata.\n */\n JSDoc?: JSDocNode | null\n /**\n * Child nodes representing the function body (children of the `Function` component).\n * Each entry is a {@link CodeNode}. Use {@link TextNode} for raw string content.\n */\n nodes?: Array<CodeNode>\n}\n\n/**\n * AST node representing a TypeScript arrow function (`const name = () => { ... }`).\n *\n * Mirrors the props of the `Function.Arrow` component from `@kubb/renderer-jsx`.\n * The `children` prop of the component is represented as `nodes`.\n *\n * @example\n * ```ts\n * createArrowFunction({ name: 'getPet', export: true, singleLine: true })\n * // export const getPet = () => ...\n * ```\n */\nexport type ArrowFunctionNode = Omit<FunctionNode, 'kind'> & {\n kind: 'ArrowFunction'\n /**\n * Render the arrow function body as a single-line expression.\n */\n singleLine?: boolean | null\n}\n\n/**\n * AST node representing a raw text/string fragment in the source output.\n *\n * Used instead of bare `string` values so that all entries in `nodes` arrays\n * are typed `CodeNode` objects rather than a mixed `CodeNode | string` union.\n *\n * @example\n * ```ts\n * createText('return fetch(id)')\n * // { kind: 'Text', value: 'return fetch(id)' }\n * ```\n */\nexport type TextNode = BaseNode & {\n kind: 'Text'\n /**\n * The raw string content.\n */\n value: string\n}\n\n/**\n * AST node representing a blank line in the source output.\n *\n * Corresponds to `<br/>` in JSX components. `printNodes` turns a `Break` between two\n * statements into one blank line. Consecutive breaks, and breaks at the start or end of\n * the list, are folded away, so a `Break` never produces more than one blank line.\n *\n * @example\n * ```ts\n * createBreak()\n * // { kind: 'Break' }\n * ```\n */\nexport type BreakNode = BaseNode & {\n kind: 'Break'\n}\n\n/**\n * AST node representing a raw JSX fragment in the source output.\n *\n * Mirrors the `Jsx` component from `@kubb/renderer-jsx`. Embeds raw JSX/TSX markup\n * (including fragments `<>…</>`) directly in generated code.\n *\n * @example\n * ```ts\n * createJsx('<>\\n <a href={href}>Open</a>\\n</>')\n * // { kind: 'Jsx', value: '<>\\n <a href={href}>Open</a>\\n</>' }\n * ```\n */\nexport type JsxNode = BaseNode & {\n kind: 'Jsx'\n /**\n * The raw JSX string content.\n */\n value: string\n}\n\n/**\n * Union of all code-generation AST nodes.\n *\n * These nodes mirror the JSX components from `@kubb/renderer-jsx` and are used as\n * structured children in {@link SourceNode.nodes}.\n */\nexport type CodeNode = ConstNode | TypeNode | FunctionNode | ArrowFunctionNode | TextNode | BreakNode | JsxNode\n\n/**\n * Definition for the {@link ConstNode}.\n */\nexport const constDef = defineNode<ConstNode>({ kind: 'Const' })\n\n/**\n * Definition for the {@link TypeNode}.\n */\nexport const typeDef = defineNode<TypeNode>({ kind: 'Type' })\n\n/**\n * Definition for the {@link FunctionNode}.\n */\nexport const functionDef = defineNode<FunctionNode>({ kind: 'Function' })\n\n/**\n * Definition for the {@link ArrowFunctionNode}.\n */\nexport const arrowFunctionDef = defineNode<ArrowFunctionNode>({ kind: 'ArrowFunction' })\n\n/**\n * Definition for the {@link TextNode}.\n */\nexport const textDef = defineNode<TextNode, string>({ kind: 'Text', build: (value) => ({ value }) })\n\n/**\n * Definition for the {@link BreakNode}.\n */\nexport const breakDef = defineNode<BreakNode, void>({ kind: 'Break', build: () => ({}) })\n\n/**\n * Definition for the {@link JsxNode}.\n */\nexport const jsxDef = defineNode<JsxNode, string>({ kind: 'Jsx', build: (value) => ({ value }) })\n\n/**\n * Creates a `ConstNode` representing a TypeScript `const` declaration.\n *\n * @example Exported constant with type and `as const`\n * ```ts\n * createConst({ name: 'pets', export: true, type: 'Pet[]', asConst: true })\n * // export const pets: Pet[] = ... as const\n * ```\n */\nexport const createConst = constDef.create\n\n/**\n * Creates a `TypeNode` representing a TypeScript `type` alias declaration.\n *\n * @example\n * ```ts\n * createType({ name: 'Pet', export: true })\n * // export type Pet = ...\n * ```\n */\nexport const createType = typeDef.create\n\n/**\n * Creates a `FunctionNode` representing a TypeScript `function` declaration.\n *\n * @example\n * ```ts\n * createFunction({ name: 'fetchPet', export: true, async: true, returnType: 'Pet' })\n * // export async function fetchPet(): Promise<Pet> { ... }\n * ```\n */\nexport const createFunction = functionDef.create\n\n/**\n * Creates an `ArrowFunctionNode` representing a TypeScript arrow function.\n *\n * @example\n * ```ts\n * createArrowFunction({ name: 'double', export: true, params: 'n: number', singleLine: true })\n * // export const double = (n: number) => ...\n * ```\n */\nexport const createArrowFunction = arrowFunctionDef.create\n\n/**\n * Creates a {@link TextNode} representing a raw string fragment in the source output.\n *\n * @example\n * ```ts\n * createText('return fetch(id)')\n * // { kind: 'Text', value: 'return fetch(id)' }\n * ```\n */\nexport const createText = textDef.create\n\n/**\n * Creates a {@link BreakNode} representing a line break in the source output.\n *\n * @example\n * ```ts\n * createBreak()\n * // { kind: 'Break' }\n * ```\n */\nexport function createBreak(): BreakNode {\n return breakDef.create()\n}\n\n/**\n * Creates a {@link JsxNode} representing a raw JSX fragment in the source output.\n *\n * @example\n * ```ts\n * createJsx('<>\\n <a href={href}>Open</a>\\n</>')\n * // { kind: 'Jsx', value: '<>\\n <a href={href}>Open</a>\\n</>' }\n * ```\n */\nexport const createJsx = jsxDef.create\n","import { defineNode } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\nimport type { SchemaNode } from './schema.ts'\n\n/**\n * AST node representing one content-type entry of a request body or response.\n *\n * There is one entry per content type declared in the spec (e.g. `application/json`,\n * `multipart/form-data`), and each entry holds its own body schema.\n *\n * @example\n * ```ts\n * const content: ContentNode = {\n * kind: 'Content',\n * contentType: 'application/json',\n * schema: createSchema({ type: 'string' }),\n * }\n * ```\n */\nexport type ContentNode = BaseNode & {\n /**\n * Node kind.\n */\n kind: 'Content'\n /**\n * The content type for this entry (e.g. `'application/json'`).\n */\n contentType: string\n /**\n * Body schema for this content type.\n */\n schema?: SchemaNode\n /**\n * Property keys to exclude from the generated type via `Omit<Type, Keys>`.\n * Set when a referenced schema has `readOnly`/`writeOnly` fields that should be omitted.\n */\n keysToOmit?: Array<string> | null\n}\n\n/**\n * Definition for the {@link ContentNode}.\n */\nexport const contentDef = defineNode<ContentNode>({\n kind: 'Content',\n children: ['schema'],\n})\n\n/**\n * Creates a `ContentNode` for a single request-body or response content type.\n */\nexport const createContent = contentDef.create\n","import type { CodeNode } from '../nodes/code.ts'\n\n/**\n * Extracts all string content from a `CodeNode` tree recursively.\n *\n * Collects text node values, identifier references in string fields (`params`, `generics`, `returnType`, `type`),\n * and nested node content. Used to build the full source string for import filtering.\n */\nexport function extractStringsFromNodes(nodes: Array<CodeNode> | undefined): string {\n if (!nodes?.length) return ''\n\n // Imperative single pass. The earlier `map().filter().join()` allocated a closure plus two\n // intermediate arrays per call, and this runs recursively over every code node during file\n // assembly, so the churn showed up in deopt traces. Appending directly keeps it flat.\n const collected: Array<string> = []\n\n for (const node of nodes) {\n // Backward-compat: compiled plugins may still pass bare strings at runtime\n if (typeof node === 'string') {\n if (node) collected.push(node as string)\n continue\n }\n if (node.kind === 'Text' || node.kind === 'Jsx') {\n if (node.value) collected.push(node.value)\n continue\n }\n if (node.kind === 'Break') continue\n\n const parts: Array<string> = []\n if ('params' in node && node.params) parts.push(node.params)\n if ('generics' in node && node.generics) parts.push(Array.isArray(node.generics) ? node.generics.join(', ') : node.generics)\n if ('returnType' in node && node.returnType) parts.push(node.returnType)\n if ('type' in node && typeof node.type === 'string') parts.push(node.type)\n\n const nested = extractStringsFromNodes(node.nodes)\n if (nested) parts.push(nested)\n\n if (parts.length) collected.push(parts.join('\\n'))\n }\n\n return collected.join('\\n')\n}\n","/**\n * File-member merging. `combineImports` and `combineExports` deduplicate and sort the import and\n * export entries of one file, while `combineSources` deduplicates source entries in original order.\n * `combineImports` also drops imports nothing references. This works on a file's members, not on\n * schema content.\n */\nimport type { ExportNode, ImportNode, SourceNode } from '../nodes/file.ts'\nimport { extractStringsFromNodes } from './extractStringsFromNodes.ts'\n\nconst IDENTIFIER_RUN = /[\\w$]+/g\n\n/**\n * How many imports a file needs before indexing the source beats scanning it once per name.\n */\nconst INDEX_ABOVE_IMPORTS = 128\n\ntype ImportNameItem = string | { propertyName: string; name?: string }\n\ntype FileMember = { name?: string | Array<unknown> | null; isTypeOnly?: boolean | null; path: string }\n\n/**\n * Returns the local binding an import name item introduces: the alias when there is one, else the\n * imported name.\n */\nexport function importLocalName(item: ImportNameItem): string {\n return typeof item === 'string' ? item : (item.name ?? item.propertyName)\n}\n\n/**\n * Computes a multi-level sort key for exports and imports:\n * non-array names first (wildcards/namespace aliases). Type-only before value. Alphabetical path. Unnamed before named.\n */\nfunction sortKey(node: FileMember): string {\n const isArray = Array.isArray(node.name) ? '1' : '0'\n const typeOnly = node.isTypeOnly ? '0' : '1'\n const hasName = node.name != null ? '1' : '0'\n const name = Array.isArray(node.name) ? node.name.toSorted().join('\\0') : (node.name ?? '')\n return `${isArray}:${typeOnly}:${node.path}:${hasName}:${name}`\n}\n\n/**\n * Sorts members by {@link sortKey}. Keys are computed once per node, not per comparison.\n */\nfunction sortMembers<TNode extends FileMember>(nodes: Array<TNode>): Array<TNode> {\n return nodes\n .map((node) => ({ node, key: sortKey(node) }))\n .sort((a, b) => (a.key < b.key ? -1 : a.key > b.key ? 1 : 0))\n .map(({ node }) => node)\n}\n\n/**\n * Returns a collector for array-named members. A member whose path and `isTypeOnly` were already\n * seen folds its names into that entry, otherwise it joins `result` as a new entry.\n */\nfunction mergeByPath<TNode extends FileMember>(result: Array<TNode>): (member: { node: TNode; names: Array<unknown> }) => void {\n const byPath = new Map<string, TNode>()\n\n return ({ node, names }) => {\n const key = `${node.path}:${node.isTypeOnly ?? false}`\n const existing = byPath.get(key)\n\n if (existing && Array.isArray(existing.name)) {\n existing.name = [...new Set([...existing.name, ...names])]\n return\n }\n\n const item = { ...node, name: names }\n result.push(item)\n byPath.set(key, item)\n }\n}\n\n/**\n * Deduplicates `SourceNode` objects by `name + isExportable + isTypeOnly`, keeping the first of each\n * key. Unnamed sources fall back to their extracted node strings as the name part of the key. Returns\n * the deduplicated array in original order.\n */\nexport function combineSources(sources: Array<SourceNode>): Array<SourceNode> {\n const seen = new Map<string, SourceNode>()\n for (const source of sources) {\n const nameKey = source.name ?? extractStringsFromNodes(source.nodes)\n const key = `${nameKey}:${source.isExportable ?? false}:${source.isTypeOnly ?? false}`\n if (!seen.has(key)) seen.set(key, source)\n }\n return [...seen.values()]\n}\n\n/**\n * Deduplicates and merges `ExportNode` objects by path and type.\n *\n * Named exports with the same path and `isTypeOnly` flag have their names merged into a single export.\n * Non-array exports are deduplicated by exact identity. Returns a sorted, deduplicated array.\n */\nexport function combineExports(exports: Array<ExportNode>): Array<ExportNode> {\n const result: Array<ExportNode> = []\n const merge = mergeByPath(result)\n // Deduplicates non-array exports by their exact identity\n const seen = new Set<string>()\n\n for (const curr of sortMembers(exports)) {\n const { name, path, isTypeOnly, asAlias } = curr\n\n if (Array.isArray(name)) {\n if (name.length) merge({ node: curr, names: [...new Set(name)] })\n continue\n }\n\n const key = `${path}:${name ?? ''}:${isTypeOnly ?? false}:${asAlias ?? ''}`\n if (!seen.has(key)) {\n result.push(curr)\n seen.add(key)\n }\n }\n\n return result\n}\n\n/**\n * Deduplicates and merges `ImportNode` objects, filtering out unused imports.\n *\n * Retains imports that are referenced in `source` or re-exported. Imports with the same path and\n * `isTypeOnly` flag have their names merged. Returns a sorted, deduplicated, filtered array.\n */\nexport function combineImports(imports: Array<ImportNode>, exports: Array<ExportNode>, source?: string): Array<ImportNode> {\n // Build a lookup of all exported names to retain imports that are re-exported\n const exportedNames = new Set(exports.flatMap((e) => (Array.isArray(e.name) ? e.name : e.name ? [e.name] : [])))\n // `createFile` re-runs on every merge into a file, so scanning the source once per import name\n // costs a heavily merged file that scan again for every fragment it already holds. Indexing pays\n // for itself there, and costs more than it saves on the small files the default output produces.\n const identifiers = source && imports.length > INDEX_ABOVE_IMPORTS ? new Set(source.match(IDENTIFIER_RUN)) : null\n\n // A name in the index is used. One that is not still might be, inside a longer identifier, so the\n // substring test stays behind it.\n const isUsed = (importName: string): boolean => !source || identifiers?.has(importName) || source.includes(importName) || exportedNames.has(importName)\n\n // Memoize object import names so the same logical (propertyName, name) pair always\n // reuses the same object reference. Set-based deduplication then works correctly.\n const importNameMemo = new Map<string, ImportNameItem>()\n const canonicalizeName = (n: ImportNameItem): ImportNameItem => {\n if (typeof n === 'string') return n\n const key = `${n.propertyName}:${n.name ?? ''}`\n if (!importNameMemo.has(key)) importNameMemo.set(key, n)\n return importNameMemo.get(key)!\n }\n\n // Paths that keep at least one used named import. A default import from such a path is retained\n // even when its binding can't be found in `source` e.g. a generated `client` default import\n // alongside `import type { Client } from <same path>`, where merged grouped output omits the body.\n const pathsWithUsedNamedImport = new Set<string>()\n for (const node of imports) {\n if (Array.isArray(node.name) && node.name.some((item) => isUsed(importLocalName(item)))) {\n pathsWithUsedNamedImport.add(node.path)\n }\n }\n\n const result: Array<ImportNode> = []\n const merge = mergeByPath(result)\n // Deduplicates non-array imports by their exact identity\n const seen = new Set<string>()\n\n for (const curr of sortMembers(imports)) {\n if (curr.path === curr.root) continue\n\n const { name, path, isTypeOnly } = curr\n\n if (Array.isArray(name)) {\n const names = [...new Set(name.map(canonicalizeName))].filter((item) => isUsed(importLocalName(item)))\n if (names.length) merge({ node: curr, names })\n continue\n }\n\n if (!isUsed(name) && !pathsWithUsedNamedImport.has(path)) continue\n\n const key = `${path}:${name}:${isTypeOnly ?? false}`\n if (!seen.has(key)) {\n result.push(curr)\n seen.add(key)\n }\n }\n\n return result\n}\n","import { hash } from 'node:crypto'\nimport path from 'node:path'\nimport { defineNode } from '../defineNode.ts'\nimport { combineExports, combineImports, combineSources, importLocalName } from '../utils/combineFileMembers.ts'\nimport { extractStringsFromNodes } from '../utils/extractStringsFromNodes.ts'\nimport type { BaseNode } from './base.ts'\nimport type { CodeNode } from './code.ts'\n\n/**\n * Supported file extensions.\n */\ntype Extname = '.ts' | '.js' | '.tsx' | '.json' | `.${string}`\n\ntype ImportName = string | Array<string | { propertyName: string; name?: string }>\n\n/**\n * Represents a language-agnostic import/dependency declaration.\n *\n * @example Named import (TypeScript: `import { useState } from 'react'`)\n * ```ts\n * createImport({ name: ['useState'], path: 'react' })\n * ```\n *\n * @example Default import (TypeScript: `import React from 'react'`)\n * ```ts\n * createImport({ name: 'React', path: 'react' })\n * ```\n *\n * @example Type-only import (TypeScript: `import type { FC } from 'react'`)\n * ```ts\n * createImport({ name: ['FC'], path: 'react', isTypeOnly: true })\n * ```\n *\n * @example Namespace import (TypeScript: `import * as React from 'react'`)\n * ```ts\n * createImport({ name: 'React', path: 'react', isNameSpace: true })\n * ```\n */\nexport type ImportNode = BaseNode & {\n kind: 'Import'\n /**\n * Import name(s) to be used.\n *\n * @example Named imports\n * `['useState']`\n *\n * @example Default import\n * `'React'`\n */\n name: ImportName\n /**\n * Path for the import.\n *\n * @example\n * `'@kubb/core'`\n */\n path: string\n /**\n * Add a type-only import prefix.\n * - `true` generates `import type { Type } from './path'`\n * - `false` generates `import { Type } from './path'`\n */\n isTypeOnly?: boolean | null\n /**\n * Import the entire module as a namespace.\n * - `true` generates `import * as Name from './path'`\n * - `false` generates a standard import\n */\n isNameSpace?: boolean | null\n /**\n * When set, the import path is resolved relative to this root.\n */\n root?: string | null\n}\n\n/**\n * Represents a language-agnostic export/public API declaration.\n *\n * @example Named export (TypeScript: `export { Pets } from './Pets'`)\n * ```ts\n * createExport({ name: ['Pets'], path: './Pets' })\n * ```\n *\n * @example Type-only export (TypeScript: `export type { Pet } from './Pet'`)\n * ```ts\n * createExport({ name: ['Pet'], path: './Pet', isTypeOnly: true })\n * ```\n *\n * @example Wildcard export (TypeScript: `export * from './utils'`)\n * ```ts\n * createExport({ path: './utils' })\n * ```\n *\n * @example Namespace alias (TypeScript: `export * as utils from './utils'`)\n * ```ts\n * createExport({ name: 'utils', path: './utils', asAlias: true })\n * ```\n */\nexport type ExportNode = BaseNode & {\n kind: 'Export'\n /**\n * Export name(s) to be used. When omitted, generates a wildcard export.\n *\n * @example Named exports\n * `['useState']`\n *\n * @example Single export\n * `'React'`\n */\n name?: string | Array<string> | null\n /**\n * Path for the export.\n *\n * @example\n * `'@kubb/core'`\n */\n path: string\n /**\n * Add a type-only export prefix.\n * - `true` generates `export type { Type } from './path'`\n * - `false` generates `export { Type } from './path'`\n */\n isTypeOnly?: boolean | null\n /**\n * Export as an aliased namespace.\n * - `true` generates `export * as aliasName from './path'`\n * - `false` generates a standard export\n */\n asAlias?: boolean | null\n}\n\n/**\n * Represents a fragment of source code within a file.\n *\n * @example Named exportable source\n * ```ts\n * createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')], isExportable: true, isIndexable: true })\n * ```\n *\n * @example Inline unnamed code block\n * ```ts\n * createSource({ nodes: [createText('const x = 1')] })\n * ```\n */\nexport type SourceNode = BaseNode & {\n kind: 'Source'\n /**\n * Optional name identifying this source (used for deduplication and barrel generation).\n */\n name?: string | null\n /**\n * Mark this source as a type-only export.\n */\n isTypeOnly?: boolean | null\n /**\n * Include the `export` keyword in the generated source.\n */\n isExportable?: boolean | null\n /**\n * Include this source in barrel/index file generation.\n */\n isIndexable?: boolean | null\n /**\n * Child nodes that make up this source fragment, in DOM order.\n * Use a {@link TextNode} for raw string content.\n */\n nodes?: Array<CodeNode>\n}\n\n/**\n * Represents a fully resolved file in the AST.\n *\n * Created via `createFile()`, which computes the `id`, `name`, and `extname` from the input\n * and deduplicates `imports`, `exports`, and `sources`.\n *\n * @example\n * ```ts\n * const file = createFile({\n * baseName: 'petStore.ts',\n * path: 'src/models/petStore.ts',\n * sources: [createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')], isExportable: true })],\n * imports: [createImport({ name: ['z'], path: 'zod' })],\n * exports: [createExport({ name: ['Pet'], path: './petStore' })],\n * })\n * // file.id = SHA256 hash of the path\n * // file.name = 'petStore'\n * // file.extname = '.ts'\n * ```\n */\nexport type FileNode<TMeta extends object = object> = BaseNode & {\n kind: 'File'\n /**\n * Unique identifier derived from a SHA256 hash of the file path. `createFile`\n * computes it, so callers do not need to provide it.\n */\n id: string\n /**\n * File name without extension, derived from `baseName`.\n *\n * @see https://nodejs.org/api/path.html#pathformatpathobject\n */\n name: string\n /**\n * File base name, including extension, shaped like `${name}${extname}`.\n *\n * @see https://nodejs.org/api/path.html#pathbasenamepath-suffix\n */\n baseName: `${string}.${string}`\n /**\n * Full qualified path to the file.\n */\n path: string\n /**\n * File extension extracted from `baseName`.\n */\n extname: Extname\n /**\n * Deduplicated list of source code fragments.\n */\n sources: Array<SourceNode>\n /**\n * Deduplicated list of import declarations.\n */\n imports: Array<ImportNode>\n /**\n * Deduplicated list of export declarations.\n */\n exports: Array<ExportNode>\n /**\n * Optional metadata attached to this file, read by plugins during barrel generation.\n */\n meta?: TMeta\n /**\n * Optional banner prepended to the generated file content.\n * Accepts `null` so `resolver.default.banner()` results can be passed directly.\n */\n banner?: string | null\n /**\n * Optional footer appended to the generated file content.\n * Accepts `null` so `resolver.default.footer()` results can be passed directly.\n */\n footer?: string | null\n /**\n * Absolute on-disk path to copy into the output, through the parser's `copy` hook when it has one.\n *\n * Use to emit a real source file shipped inside a package (a template) into the generated\n * folder. When set, `copy` provides the file content and any `sources` nodes are ignored for\n * output; `sources` may still carry `name`/`isExportable`/`isIndexable` so barrel generation\n * treats the file the same as a rendered one.\n */\n copy?: string | null\n}\n\n/**\n * Definition for the {@link ImportNode}.\n */\nexport const importDef = defineNode<ImportNode>({ kind: 'Import' })\n\n/**\n * Definition for the {@link ExportNode}.\n */\nexport const exportDef = defineNode<ExportNode>({ kind: 'Export' })\n\n/**\n * Definition for the {@link SourceNode}.\n */\nexport const sourceDef = defineNode<SourceNode>({ kind: 'Source' })\n\n/**\n * Definition for the {@link FileNode}. The fully resolved builder lives in\n * `createFile`, so this definition only supplies the guard.\n */\nexport const fileDef = defineNode<FileNode>({ kind: 'File' })\n\n/**\n * Creates an `ImportNode` representing a language-agnostic import/dependency declaration.\n *\n * @example Named import\n * ```ts\n * createImport({ name: ['useState'], path: 'react' })\n * // import { useState } from 'react'\n * ```\n */\nexport const createImport = importDef.create\n\n/**\n * Creates an `ExportNode` representing a language-agnostic export/public API declaration.\n *\n * @example Named export\n * ```ts\n * createExport({ name: ['Pet'], path: './Pet' })\n * // export { Pet } from './Pet'\n * ```\n */\nexport const createExport = exportDef.create\n\n/**\n * Creates a `SourceNode` representing a fragment of source code within a file.\n *\n * @example\n * ```ts\n * createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')], isExportable: true })\n * ```\n */\nexport const createSource = sourceDef.create\n\n/**\n * Input descriptor for {@link createFile}, before `id`, `name`, and `extname` are computed\n * and `imports`/`exports`/`sources` are deduplicated.\n */\nexport type UserFileNode<TMeta extends object = object> = Omit<FileNode<TMeta>, 'kind' | 'id' | 'name' | 'extname' | 'imports' | 'exports' | 'sources'> &\n Pick<Partial<FileNode<TMeta>>, 'imports' | 'exports' | 'sources'>\n\n/**\n * Creates a fully resolved `FileNode` from a file input descriptor.\n *\n * Computes:\n * - `id` SHA256 hash of the file path\n * - `name` `baseName` without extension\n * - `extname` extension extracted from `baseName`\n *\n * Deduplicates:\n * - `sources` via `combineSources`\n * - `exports` via `combineExports`\n * - `imports` via `combineImports` (also filters unused imports)\n *\n * @throws {Error} when `baseName` has no extension.\n *\n * @example\n * ```ts\n * const file = createFile({\n * baseName: 'petStore.ts',\n * path: 'src/models/petStore.ts',\n * sources: [createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')] })],\n * imports: [createImport({ name: ['z'], path: 'zod' })],\n * exports: [createExport({ name: ['Pet'], path: './petStore' })],\n * })\n * // file.id = SHA256 hash of 'src/models/petStore.ts'\n * // file.name = 'petStore'\n * // file.extname = '.ts'\n * ```\n *\n * @example Copy a real file into the output\n * ```ts\n * const file = createFile({\n * baseName: 'client.ts',\n * path: 'src/gen/client.ts',\n * copy: '/abs/path/to/templates/client.ts',\n * })\n * ```\n */\nexport function createFile<TMeta extends object = object>(input: UserFileNode<TMeta>): FileNode<TMeta> {\n const extname = path.extname(input.baseName) as `.${string}`\n if (!extname) {\n throw new Error(`No extname found for ${input.baseName}`)\n }\n\n const resolvedExports = input.exports?.length ? combineExports(input.exports) : []\n\n // Skip building the source text and local-name set when there are no imports to resolve against them.\n const resolvedImports: Array<ImportNode> = (() => {\n if (!input.imports?.length) return []\n\n const sourceParts: Array<string> = []\n const localNames = new Set<string>()\n for (const item of input.sources ?? []) {\n const extracted = item.nodes && extractStringsFromNodes(item.nodes)\n if (extracted) sourceParts.push(extracted)\n if (item.name) localNames.add(item.name)\n }\n const source = sourceParts.join('\\n') || undefined\n const combinedImports = combineImports(input.imports, resolvedExports, source)\n // Consolidating output (`mode: 'file'`) can put a symbol's definition and an import of it in the\n // same file: by path when the import still targets this file, by name when consolidation moved it.\n return combinedImports.flatMap((imp) => {\n if (imp.path === input.path) return []\n if (!Array.isArray(imp.name)) {\n return typeof imp.name === 'string' && localNames.has(imp.name) ? [] : [imp]\n }\n const kept = imp.name.filter((item) => !localNames.has(importLocalName(item)))\n\n if (!kept.length) return []\n return [kept.length === imp.name.length ? imp : { ...imp, name: kept }]\n })\n })()\n const resolvedSources = input.sources?.length ? combineSources(input.sources) : []\n\n return {\n kind: 'File',\n ...input,\n id: hash('sha256', input.path, 'hex'),\n name: path.basename(input.baseName, extname),\n extname,\n imports: resolvedImports,\n exports: resolvedExports,\n sources: resolvedSources,\n meta: (input.meta ?? {}) as TMeta,\n }\n}\n","import { defineNode } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\nimport type { OperationNode } from './operation.ts'\nimport type { SchemaNode } from './schema.ts'\n\n/**\n * Metadata for an API document, populated by the adapter and available to every generator.\n *\n * All fields are plain JSON-serializable values, no `Set`, no `Map`, no class instances.\n * Computed fields (`circularNames`, `enumNames`) are pre-calculated once during the adapter\n * pre-scan so generators never need to iterate the full schema list themselves.\n *\n * @example\n * ```ts\n * const meta: InputMeta = { title: 'Pet Store', version: '1.0.0', baseURL: 'https://api.example.com/v2', circularNames: [], enumNames: [] }\n * ```\n */\nexport type InputMeta = {\n /**\n * API title from `info.title` in the source document.\n */\n title?: string\n /**\n * API description from `info.description` in the source document.\n */\n description?: string\n /**\n * API version string from `info.version` in the source document.\n */\n version?: string\n /**\n * Resolved base URL from the first matching server entry in the source document.\n */\n baseURL?: string | null\n /**\n * Names of schemas that participate in a circular reference chain.\n * Computed once during the adapter pre-scan, so a generator never has to\n * call `findCircularSchemas` itself.\n *\n * Convert to a `Set` once at the start of a generator, not per-schema,\n * so lookups stay O(1) without repeated allocations.\n *\n * @example Wrap a circular schema in z.lazy()\n * ```ts\n * const circular = new Set(meta.circularNames)\n * if (circular.has(schema.name)) { ... }\n * ```\n */\n circularNames: ReadonlyArray<string>\n /**\n * Names of schemas whose type is `enum`.\n * Computed once during the adapter pre-scan, so a generator never has to\n * filter the schema list itself.\n *\n * Convert to a `Set` once at the start of a generator when you need repeated\n * membership checks, so each check stays O(1) instead of an array scan.\n *\n * @example Check if a referenced schema is an enum\n * `const enums = new Set(meta.enumNames)`\n * `const isEnum = enums.has(schemaName)`\n */\n enumNames: ReadonlyArray<string>\n}\n\n/**\n * Input AST node that contains all schemas and operations for one API document.\n * Produced by the adapter and consumed by all Kubb plugins.\n *\n * @example\n * ```ts\n * const input: InputNode = {\n * kind: 'Input',\n * schemas: [],\n * operations: [],\n * meta: { circularNames: [], enumNames: [] },\n * }\n * ```\n */\nexport type InputNode = BaseNode & {\n /**\n * Node kind.\n */\n kind: 'Input'\n /**\n * All schema nodes in the document.\n */\n schemas: Array<SchemaNode>\n /**\n * All operation nodes in the document.\n */\n operations: Array<OperationNode>\n /**\n * Document metadata populated by the adapter.\n */\n meta: InputMeta\n}\n\n/**\n * Definition for the {@link InputNode}.\n */\nexport const inputDef = defineNode<InputNode, Partial<Omit<InputNode, 'kind'>>>({\n kind: 'Input',\n // A build hook, not `defaults`: a shared default object would let every InputNode mutate the same\n // `schemas`, `operations` and `meta` instances.\n build: (props) => ({ schemas: [], operations: [], meta: { circularNames: [], enumNames: [] }, ...props }),\n children: ['schemas', 'operations'],\n visitorKey: 'input',\n})\n\n/**\n * Creates an `InputNode`, defaulting `schemas`/`operations` to empty arrays and `meta` per\n * {@link inputDef}.\n *\n * @example\n * ```ts\n * const input = createInput()\n * // { kind: 'Input', schemas: [], operations: [] }\n * ```\n */\nexport function createInput(overrides: Partial<Omit<InputNode, 'kind'>> = {}): InputNode {\n return inputDef.create(overrides)\n}\n","import { defineNode } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\nimport type { ContentNode } from './content.ts'\n\n/**\n * AST node representing an operation request body.\n *\n * Body schemas live exclusively inside the `content` array (one entry per content type),\n * mirroring {@link ResponseNode}.\n *\n * @example\n * ```ts\n * const requestBody: RequestBodyNode = {\n * kind: 'RequestBody',\n * required: true,\n * content: [{ kind: 'Content', contentType: 'application/json', schema: createSchema({ type: 'string' }) }],\n * }\n * ```\n */\nexport type RequestBodyNode = BaseNode & {\n kind: 'RequestBody'\n /**\n * Request body description carried over from the spec.\n */\n description?: string\n /**\n * Whether the request body is required (`requestBody.required: true` in the spec).\n * When `false` or absent, the generated `data` parameter should be optional.\n */\n required?: boolean\n /**\n * Content type entries for this request body.\n *\n * When the adapter `contentType` option is set, this array contains exactly one entry for\n * that content type. Otherwise it contains one entry per content type declared in the spec,\n * so plugins can generate code for every variant (for example, separate hooks for\n * `application/json` and `multipart/form-data`).\n */\n content?: Array<ContentNode>\n}\n\n/**\n * Definition for the {@link RequestBodyNode}. Content entries are built upfront with\n * {@link createContent}, mirroring how `parameters` and `responses` take prebuilt nodes.\n */\nexport const requestBodyDef = defineNode<RequestBodyNode>({\n kind: 'RequestBody',\n children: ['content'],\n})\n\n/**\n * Creates a `RequestBodyNode`.\n */\nexport const createRequestBody = requestBodyDef.create\n","import { defineNode } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\nimport type { ParameterNode } from './parameter.ts'\nimport { createRequestBody, type RequestBodyNode } from './requestBody.ts'\nimport type { ResponseNode } from './response.ts'\n\n/**\n * HTTP method an operation responds to.\n */\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'TRACE'\n\n/**\n * Transport an operation belongs to.\n */\ntype OperationProtocol = 'http'\n\n/**\n * Fields shared by every operation, regardless of transport.\n */\ntype OperationNodeBase = BaseNode & {\n /**\n * Node kind.\n */\n kind: 'Operation'\n /**\n * Stable identifier for the operation.\n */\n operationId: string\n /**\n * Group labels for the operation.\n */\n tags: Array<string>\n /**\n * Short one-line operation summary.\n */\n summary?: string\n /**\n * Full operation description.\n */\n description?: string\n /**\n * Marks the operation as deprecated.\n */\n deprecated?: boolean\n /**\n * Query, path, header, and cookie parameters for the operation.\n */\n parameters: Array<ParameterNode>\n /**\n * Request body for the operation.\n */\n requestBody?: RequestBodyNode\n /**\n * Operation responses.\n */\n responses: Array<ResponseNode>\n}\n\n/**\n * Operation served over HTTP. `method` and `path` are guaranteed.\n *\n * @example\n * ```ts\n * const operation: HttpOperationNode = {\n * kind: 'Operation',\n * operationId: 'listPets',\n * protocol: 'http',\n * method: 'GET',\n * path: '/pets',\n * tags: [],\n * parameters: [],\n * responses: [],\n * }\n * ```\n */\nexport type HttpOperationNode = OperationNodeBase & {\n /**\n * Transport the operation belongs to.\n */\n protocol?: 'http'\n /**\n * HTTP method like `'GET'`.\n */\n method: HttpMethod\n /**\n * Path string, for example `/pets/{petId}`, with `{param}` notation preserved.\n */\n path: string\n}\n\n/**\n * Operation for a non-HTTP transport. HTTP-only fields are forbidden.\n */\nexport type GenericOperationNode = OperationNodeBase & {\n /**\n * Transport the operation belongs to.\n */\n protocol?: Exclude<OperationProtocol, 'http'>\n method?: never\n path?: never\n}\n\n/**\n * AST node representing one API operation.\n *\n * Discriminated on `protocol`: an {@link HttpOperationNode} (`protocol: 'http'`) guarantees\n * `method` and `path`, while a {@link GenericOperationNode} omits them. Narrow with\n * `isHttpOperationNode(node)` or `node.protocol === 'http'` before reading `method`/`path`.\n */\nexport type OperationNode = HttpOperationNode | GenericOperationNode\n\ntype OperationInput = {\n operationId: string\n method?: HttpOperationNode['method']\n path?: HttpOperationNode['path']\n requestBody?: Omit<RequestBodyNode, 'kind'>\n [key: string]: unknown\n}\n\n/**\n * Definition for the {@link OperationNode}. HTTP operations (those carrying both\n * `method` and `path`) are tagged with `protocol: 'http'`, and the request body is\n * normalized into a `RequestBodyNode`.\n */\nexport const operationDef = defineNode<OperationNode, OperationInput>({\n kind: 'Operation',\n build: (props) => {\n const { requestBody, ...rest } = props\n const isHttp = rest.method !== undefined && rest.path !== undefined\n\n return {\n tags: [],\n parameters: [],\n responses: [],\n ...rest,\n ...(isHttp ? { protocol: 'http' as const } : {}),\n requestBody: requestBody ? createRequestBody(requestBody) : undefined,\n }\n },\n children: ['parameters', 'requestBody', 'responses'],\n visitorKey: 'operation',\n})\n\n/**\n * Creates an `OperationNode` with default empty arrays for `tags`, `parameters`, and `responses`.\n *\n * @example\n * ```ts\n * const operation = createOperation({ operationId: 'getPetById', method: 'GET', path: '/pet/{petId}' })\n * // tags, parameters, and responses are []\n * ```\n */\nexport function createOperation(\n props: Pick<HttpOperationNode, 'operationId' | 'method' | 'path'> &\n Partial<Omit<HttpOperationNode, 'kind' | 'operationId' | 'method' | 'path' | 'requestBody'>> & {\n requestBody?: Omit<RequestBodyNode, 'kind'>\n },\n): HttpOperationNode\nexport function createOperation(\n props: Pick<GenericOperationNode, 'operationId'> &\n Partial<Omit<GenericOperationNode, 'kind' | 'operationId' | 'requestBody'>> & {\n requestBody?: Omit<RequestBodyNode, 'kind'>\n },\n): GenericOperationNode\nexport function createOperation(props: OperationInput): OperationNode {\n return operationDef.create(props)\n}\n","import { defineNode } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\nimport type { FileNode } from './file.ts'\n\n/**\n * Output AST node that groups all generated file output for one API document.\n *\n * Produced by generators and consumed by the build pipeline to write files.\n *\n * @example\n * ```ts\n * const output: OutputNode = {\n * kind: 'Output',\n * files: [],\n * }\n * ```\n */\nexport type OutputNode = BaseNode & {\n /**\n * Node kind.\n */\n kind: 'Output'\n /**\n * Generated file nodes.\n */\n files: Array<FileNode>\n}\n\n/**\n * Definition for the {@link OutputNode}.\n */\nexport const outputDef = defineNode<OutputNode, Partial<Omit<OutputNode, 'kind'>>>({\n kind: 'Output',\n defaults: { files: [] },\n visitorKey: 'output',\n})\n\n/**\n * Creates an `OutputNode` with a stable default for `files`.\n *\n * @example\n * ```ts\n * const output = createOutput()\n * // { kind: 'Output', files: [] }\n * ```\n */\nexport function createOutput(overrides: Partial<Omit<OutputNode, 'kind'>> = {}): OutputNode {\n return outputDef.create(overrides)\n}\n","import type { SchemaNode } from './nodes/schema.ts'\n\n/**\n * Generic JSON Schema optionality: a non-required field is optional, and a\n * non-required nullable field is nullish.\n */\nexport function optionality(schema: SchemaNode, required: boolean): SchemaNode {\n const nullable = schema.nullable ?? false\n\n return {\n ...schema,\n optional: !required && !nullable ? true : undefined,\n nullish: !required && nullable ? true : undefined,\n }\n}\n\n/**\n * Defaults `required` to `false` and derives the schema's `optional`/`nullish` flags from it.\n * Shared build step of `createProperty` and `createParameter`.\n */\nexport function withRequired<T extends { required?: boolean; schema: SchemaNode }>(props: T): T & { required: boolean } {\n const required = props.required ?? false\n\n return { ...props, required, schema: optionality(props.schema, required) }\n}\n","import { defineNode } from '../defineNode.ts'\nimport { withRequired } from '../optionality.ts'\nimport type { BaseNode } from './base.ts'\nimport type { SchemaNode } from './schema.ts'\n\nexport type ParameterLocation = 'path' | 'query' | 'header' | 'cookie'\n\n/**\n * Parameter serialization style, controlling how a parameter value is rendered into the request.\n */\nexport type ParameterStyle = 'matrix' | 'label' | 'form' | 'simple' | 'spaceDelimited' | 'pipeDelimited' | 'deepObject'\n\n/**\n * AST node representing one operation parameter.\n *\n * @example\n * ```ts\n * const param: ParameterNode = {\n * kind: 'Parameter',\n * name: 'petId',\n * in: 'path',\n * schema: createSchema({ type: 'string' }),\n * required: true,\n * }\n * ```\n */\nexport type ParameterNode = BaseNode & {\n kind: 'Parameter'\n /**\n * Parameter name.\n */\n name: string\n /**\n * Parameter location (`path`, `query`, `header`, or `cookie`).\n */\n in: ParameterLocation\n /**\n * Parameter schema.\n */\n schema: SchemaNode\n /**\n * Whether the parameter is required.\n */\n required: boolean\n /**\n * Serialization style. Absent when the source omits it, leaving consumers to apply the\n * per-location default.\n */\n style?: ParameterStyle\n /**\n * Whether array and object values expand into separate values. Absent when the source omits it,\n * leaving consumers to apply the default for the style.\n */\n explode?: boolean\n}\n\ntype UserParameterNode = Pick<ParameterNode, 'name' | 'in' | 'schema'> & Partial<Omit<ParameterNode, 'kind' | 'name' | 'in' | 'schema'>>\n\n/**\n * Definition for the {@link ParameterNode}. `required` defaults to `false`, and the schema's\n * `optional`/`nullish` flags are derived from it through {@link withRequired}.\n */\nexport const parameterDef = defineNode<ParameterNode, UserParameterNode>({\n kind: 'Parameter',\n build: withRequired,\n children: ['schema'],\n visitorKey: 'parameter',\n})\n\n/**\n * Creates a `ParameterNode`.\n *\n * @example\n * ```ts\n * const param = createParameter({\n * name: 'petId',\n * in: 'path',\n * required: true,\n * schema: createSchema({ type: 'string' }),\n * })\n * ```\n */\nexport const createParameter = parameterDef.create\n","import { defineNode } from '../defineNode.ts'\nimport { withRequired } from '../optionality.ts'\nimport type { BaseNode } from './base.ts'\nimport type { SchemaNode } from './schema.ts'\n\n/**\n * AST node representing one named object property.\n *\n * @example\n * ```ts\n * const property: PropertyNode = {\n * kind: 'Property',\n * name: 'id',\n * schema: createSchema({ type: 'integer' }),\n * required: true,\n * }\n * ```\n */\nexport type PropertyNode = BaseNode & {\n kind: 'Property'\n /**\n * Property key.\n */\n name: string\n /**\n * Property schema.\n */\n schema: SchemaNode\n /**\n * Whether the property is required.\n */\n required: boolean\n}\n\n/**\n * Loosely-typed property accepted by `createProperty`, with `required` optional.\n */\ntype UserPropertyNode = Pick<PropertyNode, 'name' | 'schema'> & Partial<Omit<PropertyNode, 'kind' | 'name' | 'schema'>>\n\n/**\n * Definition for the {@link PropertyNode}. `required` defaults to `false`, and the schema's\n * `optional`/`nullish` flags are derived from it through {@link withRequired}.\n */\nexport const propertyDef = defineNode<PropertyNode, UserPropertyNode>({\n kind: 'Property',\n build: withRequired,\n children: ['schema'],\n visitorKey: 'property',\n})\n\n/**\n * Creates a `PropertyNode`.\n *\n * @example\n * ```ts\n * const property = createProperty({\n * name: 'status',\n * required: true,\n * schema: createSchema({ type: 'string', nullable: true }),\n * })\n * // required=true, no optional/nullish\n * ```\n */\nexport const createProperty = propertyDef.create\n","import { defineNode } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\nimport { type ContentNode, createContent } from './content.ts'\nimport type { SchemaNode } from './schema.ts'\n\n/**\n * All supported HTTP status code literals as strings, as used in API specs\n * (for example, `\"200\"` and `\"404\"`).\n */\ntype HttpStatusCode =\n // 1xx Informational\n | '100'\n | '101'\n | '102'\n | '103'\n // 2xx Success\n | '200'\n | '201'\n | '202'\n | '203'\n | '204'\n | '205'\n | '206'\n | '207'\n | '208'\n | '226'\n // 3xx Redirection\n | '300'\n | '301'\n | '302'\n | '303'\n | '304'\n | '305'\n | '307'\n | '308'\n // 4xx Client Error\n | '400'\n | '401'\n | '402'\n | '403'\n | '404'\n | '405'\n | '406'\n | '407'\n | '408'\n | '409'\n | '410'\n | '411'\n | '412'\n | '413'\n | '414'\n | '415'\n | '416'\n | '417'\n | '418'\n | '421'\n | '422'\n | '423'\n | '424'\n | '425'\n | '426'\n | '428'\n | '429'\n | '431'\n | '451'\n // 5xx Server Error\n | '500'\n | '501'\n | '502'\n | '503'\n | '504'\n | '505'\n | '506'\n | '507'\n | '508'\n | '510'\n | '511'\n\n/**\n * Response status code literal used by operations.\n *\n * Includes specific HTTP status code strings and `\"default\"` for catch-all responses.\n *\n * @example\n * ```ts\n * const status: StatusCode = '200'\n * const fallback: StatusCode = 'default'\n * ```\n */\nexport type StatusCode = HttpStatusCode | 'default'\n\n/**\n * AST node representing one operation response variant.\n *\n * Mirrors {@link OperationNode.requestBody}: the response body schemas live exclusively inside\n * the `content` array (one entry per content type), so the same schema is never duplicated at the\n * node root and inside `content`.\n *\n * @example\n * ```ts\n * const response: ResponseNode = {\n * kind: 'Response',\n * statusCode: '200',\n * content: [{ kind: 'Content', contentType: 'application/json', schema: createSchema({ type: 'string' }) }],\n * }\n * ```\n */\nexport type ResponseNode = BaseNode & {\n /**\n * Node kind.\n */\n kind: 'Response'\n /**\n * HTTP status code or `'default'` for a fallback response.\n */\n statusCode: StatusCode\n /**\n * Optional response description.\n */\n description?: string\n /**\n * All available content type entries for this response.\n *\n * When the adapter `contentType` option is set, this array contains exactly one entry for that\n * content type. Otherwise it contains one entry per content type declared in the spec, so that\n * plugins can generate a union of response types (e.g. `application/json` and `application/xml`).\n * Body-less responses keep a single entry whose `schema` is the empty/`void` placeholder.\n *\n * @example\n * ```ts\n * // spec response declares both application/json and application/xml\n * response.content[0].contentType // 'application/json'\n * response.content[1].contentType // 'application/xml'\n * ```\n */\n content?: Array<ContentNode>\n}\n\ntype ResponseInput = Pick<ResponseNode, 'statusCode'> &\n Partial<Omit<ResponseNode, 'kind' | 'statusCode' | 'content'>> & {\n content?: Array<ContentNode>\n schema?: SchemaNode\n mediaType?: string | null\n keysToOmit?: Array<string> | null\n }\n\n/**\n * Definition for the {@link ResponseNode}. A single legacy `schema` (with optional\n * `mediaType`/`keysToOmit`) is normalized into one `content` entry.\n */\nexport const responseDef = defineNode<ResponseNode, ResponseInput>({\n kind: 'Response',\n build: (props) => {\n const { schema, mediaType, keysToOmit, content, ...rest } = props\n const entries = content ?? (schema ? [createContent({ contentType: mediaType ?? 'application/json', schema, keysToOmit: keysToOmit ?? null })] : undefined)\n return { ...rest, content: entries }\n },\n children: ['content'],\n visitorKey: 'response',\n})\n\n/**\n * Creates a `ResponseNode`.\n *\n * @example\n * ```ts\n * const response = createResponse({\n * statusCode: '200',\n * content: [createContent({ contentType: 'application/json', schema: createSchema({ type: 'object', properties: [] }) })],\n * })\n * ```\n */\nexport const createResponse = responseDef.create\n","import type { InferSchemaNode } from '../infer.ts'\nimport { defineNode, type DistributiveOmit } from '../defineNode.ts'\nimport type { BaseNode } from './base.ts'\nimport type { PropertyNode } from './property.ts'\n\nexport type PrimitiveSchemaType =\n /**\n * Text value.\n */\n | 'string'\n /**\n * Floating-point number.\n */\n | 'number'\n /**\n * Integer number.\n */\n | 'integer'\n /**\n * Big integer number.\n */\n | 'bigint'\n /**\n * Boolean value.\n */\n | 'boolean'\n /**\n * Null value.\n */\n | 'null'\n /**\n * Any value.\n */\n | 'any'\n /**\n * Unknown value.\n */\n | 'unknown'\n /**\n * No value (`void`).\n */\n | 'void'\n /**\n * Never value.\n */\n | 'never'\n /**\n * Object value.\n */\n | 'object'\n /**\n * Array value.\n */\n | 'array'\n /**\n * Date value.\n */\n | 'date'\n\n/**\n * All schema type strings, one per key of {@link SchemaNodeByType}.\n */\nexport type SchemaType = keyof SchemaNodeByType\n\n/**\n * Scalar schema types without extra object/array/ref structure or constraints.\n */\nexport type ScalarSchemaType = 'boolean' | 'null' | 'any' | 'unknown' | 'void' | 'never' | 'blob'\n\n/**\n * Fields shared by all schema nodes.\n */\ntype SchemaNodeBase = BaseNode & {\n /**\n * Node kind.\n */\n kind: 'Schema'\n /**\n * Schema name for named definitions (for example, `\"Pet\"`).\n * Inline schemas omit this field.\n * `null` means Kubb has processed this and determined there is no applicable name.\n * `undefined` means the name has not been set yet.\n */\n name?: string | null\n /**\n * Short schema title.\n */\n title?: string\n /**\n * Schema description text.\n */\n description?: string\n /**\n * Whether `null` is allowed.\n */\n nullable?: boolean\n /**\n * Whether the field is optional.\n */\n optional?: boolean\n /**\n * Both optional and nullable (`optional` + `nullable`).\n */\n nullish?: boolean\n /**\n * Whether the schema is deprecated.\n */\n deprecated?: boolean\n /**\n * Whether the schema is read-only.\n */\n readOnly?: boolean\n /**\n * Whether the schema is write-only.\n */\n writeOnly?: boolean\n /**\n * Default value.\n */\n default?: unknown\n /**\n * Example values from an `examples` array.\n */\n examples?: Array<unknown>\n /**\n * Base primitive type.\n * For example, this is `'string'` for a `uuid` schema.\n */\n primitive?: PrimitiveSchemaType\n /**\n * Schema `format` value.\n */\n format?: string\n}\n\n/**\n * Object schema with ordered properties.\n *\n * @example\n * ```ts\n * const objectSchema: ObjectSchemaNode = {\n * kind: 'Schema',\n * type: 'object',\n * properties: [],\n * }\n * ```\n */\nexport type ObjectSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'object'\n /**\n * Primitive type, always `'object'` for object schemas.\n */\n primitive: 'object'\n /**\n * Ordered object properties.\n */\n properties: Array<PropertyNode>\n /**\n * Additional object properties behavior:\n * - `true`: allow any value\n * - `false`: reject unknown properties\n * - `SchemaNode`: allow values that match that schema\n * - `undefined`: no additional properties constraint (open object)\n */\n additionalProperties?: SchemaNode | boolean\n /**\n * Pattern-based property schemas.\n */\n patternProperties?: Record<string, SchemaNode>\n /**\n * Minimum number of properties allowed.\n */\n minProperties?: number\n /**\n * Maximum number of properties allowed.\n */\n maxProperties?: number\n}\n\n/**\n * Array-like schema (`array` or `tuple`).\n *\n * @example\n * ```ts\n * const arraySchema: ArraySchemaNode = {\n * kind: 'Schema',\n * type: 'array',\n * items: [],\n * }\n * ```\n */\nexport type ArraySchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator (`array` or `tuple`).\n */\n type: 'array' | 'tuple'\n /**\n * Item schemas.\n */\n items?: Array<SchemaNode>\n /**\n * Tuple rest-item schema for elements beyond positional `items`.\n */\n rest?: SchemaNode\n /**\n * Minimum item count (or tuple length).\n */\n min?: number\n /**\n * Maximum item count (or tuple length).\n */\n max?: number\n /**\n * Whether all items must be unique.\n */\n unique?: boolean\n}\n\n/**\n * Shared shape for union and intersection schemas.\n */\ntype CompositeSchemaNodeBase = SchemaNodeBase & {\n /**\n * Member schemas.\n */\n members?: Array<SchemaNode>\n}\n\n/**\n * Union schema, often from `oneOf` or `anyOf`.\n *\n * @example\n * ```ts\n * const unionSchema: UnionSchemaNode = {\n * kind: 'Schema',\n * type: 'union',\n * members: [],\n * }\n * ```\n */\nexport type UnionSchemaNode = CompositeSchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'union'\n /**\n * Discriminator property name for a polymorphic union.\n */\n discriminatorPropertyName?: string\n /**\n * How many union members must be valid.\n * - `'one'`: exactly one member, from `oneOf`\n * - `'any'`: any number of members, from `anyOf`\n */\n strategy?: 'one' | 'any'\n}\n\n/**\n * Intersection schema, often from `allOf`.\n *\n * @example\n * ```ts\n * const intersectionSchema: IntersectionSchemaNode = {\n * kind: 'Schema',\n * type: 'intersection',\n * members: [],\n * }\n * ```\n */\nexport type IntersectionSchemaNode = CompositeSchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'intersection'\n}\n\n/**\n * One named enum item.\n */\ntype EnumValueNode = {\n /**\n * Enum item name.\n */\n name: string\n /**\n * Enum item value.\n */\n value: string | number | boolean\n /**\n * Primitive type of the enum value.\n */\n primitive: Extract<PrimitiveSchemaType, 'string' | 'number' | 'boolean'>\n /**\n * Label for the enum item, taken from the `x-enumDescriptions` or\n * `x-enum-descriptions` vendor extension. `@kubb/plugin-ts` renders it as\n * JSDoc on the matching enum member.\n */\n description?: string\n}\n\n/**\n * Enum schema node.\n *\n * @example\n * ```ts\n * const enumSchema: EnumSchemaNode = {\n * kind: 'Schema',\n * type: 'enum',\n * enumValues: ['a', 'b'],\n * }\n * ```\n */\nexport type EnumSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'enum'\n /**\n * Enum values in simple form.\n */\n enumValues?: Array<string | number | boolean | null>\n /**\n * Enum values in named form.\n * If present, this is used instead of `enumValues`.\n */\n namedEnumValues?: Array<EnumValueNode>\n}\n\n/**\n * Reference schema that points to another schema definition.\n *\n * @example\n * ```ts\n * const refSchema: RefSchemaNode = {\n * kind: 'Schema',\n * type: 'ref',\n * ref: '#/components/schemas/Pet',\n * }\n * ```\n */\nexport type RefSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'ref'\n /**\n * Referenced schema name.\n * `null` means Kubb has processed this and determined there is no applicable name.\n */\n name?: string | null\n /**\n * Original `$ref` path, for example, `#/components/schemas/Order`.\n * Used to resolve names later.\n */\n ref?: string\n /**\n * Emitted name of the referenced schema when it differs from the pointer's last segment,\n * for example after a collision rename (`Order` becomes `OrderSchema`) or a macro rename.\n * Resolve display and import names through `resolveRefName`, which prefers this field and\n * falls back to the pointer segment, then `name`.\n */\n targetName?: string\n /**\n * Pattern copied from a sibling `pattern` field.\n */\n pattern?: string\n /**\n * The fully-parsed schema this ref resolves to, so its structure (`primitive`, `properties`)\n * can be read without following the reference. Populated during parsing when the\n * definition resolves, `null` when it can't or the ref is circular, and `undefined` when\n * resolution has not been attempted.\n */\n schema?: SchemaNode | null\n}\n\n/**\n * Datetime schema.\n *\n * @example\n * ```ts\n * const datetimeSchema: DatetimeSchemaNode = { kind: 'Schema', type: 'datetime' }\n * ```\n */\nexport type DatetimeSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'datetime'\n /**\n * Whether the datetime includes a timezone offset (`dateType: 'stringOffset'`).\n */\n offset?: boolean\n /**\n * Whether the datetime is local (no timezone, `dateType: 'stringLocal'`).\n */\n local?: boolean\n}\n\n/**\n * Shared base for `date` and `time` schemas.\n */\ntype TemporalSchemaNodeBase<T extends 'date' | 'time'> = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: T\n /**\n * Output representation in generated code.\n */\n representation: 'date' | 'string'\n}\n\n/**\n * Date schema node.\n *\n * @example\n * ```ts\n * const dateSchema: DateSchemaNode = { kind: 'Schema', type: 'date', representation: 'string' }\n * ```\n */\nexport type DateSchemaNode = TemporalSchemaNodeBase<'date'>\n\n/**\n * Time schema node.\n *\n * @example\n * ```ts\n * const timeSchema: TimeSchemaNode = { kind: 'Schema', type: 'time', representation: 'string' }\n * ```\n */\nexport type TimeSchemaNode = TemporalSchemaNodeBase<'time'>\n\n/**\n * String schema node.\n *\n * @example\n * ```ts\n * const stringSchema: StringSchemaNode = { kind: 'Schema', type: 'string' }\n * ```\n */\nexport type StringSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'string'\n /**\n * Minimum string length.\n */\n min?: number\n /**\n * Maximum string length.\n */\n max?: number\n /**\n * Regex pattern.\n */\n pattern?: string\n}\n\n/**\n * Numeric schema (`number`, `integer`, or `bigint`).\n *\n * @example\n * ```ts\n * const numberSchema: NumberSchemaNode = { kind: 'Schema', type: 'number' }\n * ```\n */\nexport type NumberSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'number' | 'integer' | 'bigint'\n /**\n * Minimum value.\n */\n min?: number\n /**\n * Maximum value.\n */\n max?: number\n /**\n * Exclusive minimum value.\n */\n exclusiveMinimum?: number\n /**\n * Exclusive maximum value.\n */\n exclusiveMaximum?: number\n /**\n * The value must be a multiple of this number.\n */\n multipleOf?: number\n}\n\n/**\n * Scalar schema with no extra constraints.\n *\n * @example\n * ```ts\n * const anySchema: ScalarSchemaNode = { kind: 'Schema', type: 'any' }\n * ```\n */\nexport type ScalarSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: ScalarSchemaType\n}\n\n/**\n * URL schema node.\n * Can include a path template for template literal types.\n *\n * @example\n * ```ts\n * const urlSchema: UrlSchemaNode = { kind: 'Schema', type: 'url', path: '/pets/{petId}' }\n * ```\n */\nexport type UrlSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'url'\n /**\n * Path template, for example, `'/pets/{petId}'`.\n */\n path?: string\n /**\n * Minimum string length.\n */\n min?: number\n /**\n * Maximum string length.\n */\n max?: number\n}\n\n/**\n * Format-string schema for string-based formats that support length constraints.\n *\n * @example\n * ```ts\n * const uuidSchema: FormatStringSchemaNode = { kind: 'Schema', type: 'uuid', min: 36, max: 36 }\n * ```\n */\ntype FormatStringSchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'uuid' | 'email'\n /**\n * Minimum string length.\n */\n min?: number\n /**\n * Maximum string length.\n */\n max?: number\n}\n\n/**\n * IPv4 address schema node.\n *\n * @example\n * ```ts\n * const ipv4Schema: Ipv4SchemaNode = { kind: 'Schema', type: 'ipv4' }\n * ```\n */\ntype Ipv4SchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'ipv4'\n}\n\n/**\n * IPv6 address schema node.\n *\n * @example\n * ```ts\n * const ipv6Schema: Ipv6SchemaNode = { kind: 'Schema', type: 'ipv6' }\n * ```\n */\ntype Ipv6SchemaNode = SchemaNodeBase & {\n /**\n * Schema type discriminator.\n */\n type: 'ipv6'\n}\n\n/**\n * Mapping from schema type literals to concrete schema node types.\n * Used by `narrowSchema`.\n */\nexport type SchemaNodeByType = {\n object: ObjectSchemaNode\n array: ArraySchemaNode\n tuple: ArraySchemaNode\n union: UnionSchemaNode\n intersection: IntersectionSchemaNode\n enum: EnumSchemaNode\n ref: RefSchemaNode\n datetime: DatetimeSchemaNode\n date: DateSchemaNode\n time: TimeSchemaNode\n string: StringSchemaNode\n number: NumberSchemaNode\n integer: NumberSchemaNode\n bigint: NumberSchemaNode\n boolean: ScalarSchemaNode\n null: ScalarSchemaNode\n any: ScalarSchemaNode\n unknown: ScalarSchemaNode\n void: ScalarSchemaNode\n never: ScalarSchemaNode\n uuid: FormatStringSchemaNode\n email: FormatStringSchemaNode\n url: UrlSchemaNode\n ipv4: Ipv4SchemaNode\n ipv6: Ipv6SchemaNode\n blob: ScalarSchemaNode\n}\n\n/**\n * Union of all schema node types.\n */\nexport type SchemaNode =\n | ObjectSchemaNode\n | ArraySchemaNode\n | UnionSchemaNode\n | IntersectionSchemaNode\n | EnumSchemaNode\n | RefSchemaNode\n | DatetimeSchemaNode\n | DateSchemaNode\n | TimeSchemaNode\n | StringSchemaNode\n | NumberSchemaNode\n | UrlSchemaNode\n | FormatStringSchemaNode\n | Ipv4SchemaNode\n | Ipv6SchemaNode\n | ScalarSchemaNode\n\ntype CreateSchemaObjectInput = Omit<ObjectSchemaNode, 'kind' | 'properties' | 'primitive'> & { properties?: Array<PropertyNode>; primitive?: 'object' }\ntype CreateSchemaInput = CreateSchemaObjectInput | DistributiveOmit<Exclude<SchemaNode, ObjectSchemaNode>, 'kind'>\ntype CreateSchemaOutput<T extends CreateSchemaInput> = InferSchemaNode<T> & {\n kind: 'Schema'\n}\n\n/**\n * Maps schema `type` to its underlying `primitive`.\n * Primitive types map to themselves and special string formats map to `'string'`.\n * Any type not listed here (such as `ref`, `enum`, `union`, `intersection`, `tuple`, `ipv4`, `ipv6`, `blob`) has no `primitive`.\n */\nconst TYPE_TO_PRIMITIVE: Partial<Record<SchemaNode['type'], PrimitiveSchemaType>> = {\n string: 'string',\n number: 'number',\n integer: 'integer',\n bigint: 'bigint',\n boolean: 'boolean',\n null: 'null',\n any: 'any',\n unknown: 'unknown',\n void: 'void',\n never: 'never',\n object: 'object',\n array: 'array',\n date: 'date',\n uuid: 'string',\n email: 'string',\n url: 'string',\n datetime: 'string',\n time: 'string',\n}\n\n/**\n * Definition for the {@link SchemaNode}. Object schemas default `properties` to an\n * empty array, and `primitive` is inferred from `type` when not explicitly provided.\n */\nexport const schemaDef = defineNode<SchemaNode, CreateSchemaInput>({\n kind: 'Schema',\n build: (props) => {\n if (props.type === 'object') {\n return { properties: [], primitive: 'object' as const, ...props }\n }\n\n return { primitive: TYPE_TO_PRIMITIVE[props.type as keyof typeof TYPE_TO_PRIMITIVE], ...props }\n },\n children: ['properties', 'items', 'members', 'additionalProperties', 'patternProperties', 'rest'],\n visitorKey: 'schema',\n})\n\n/**\n * Creates a `SchemaNode`, narrowed to the variant of `props.type`.\n *\n * @example\n * ```ts\n * const scalar = createSchema({ type: 'string' })\n * // { kind: 'Schema', type: 'string', primitive: 'string' }\n * ```\n *\n * @example\n * ```ts\n * const object = createSchema({ type: 'object' })\n * // { kind: 'Schema', type: 'object', primitive: 'object', properties: [] }\n * ```\n */\nexport function createSchema<T extends CreateSchemaInput>(props: T): CreateSchemaOutput<T>\nexport function createSchema(props: CreateSchemaInput): SchemaNode\nexport function createSchema(props: CreateSchemaInput): SchemaNode {\n return schemaDef.create(props)\n}\n","import type { NodeDef } from './defineNode.ts'\nimport { arrowFunctionDef, breakDef, constDef, functionDef, jsxDef, textDef, typeDef } from './nodes/code.ts'\nimport { contentDef } from './nodes/content.ts'\nimport { exportDef, fileDef, importDef, sourceDef } from './nodes/file.ts'\nimport { inputDef } from './nodes/input.ts'\nimport { operationDef } from './nodes/operation.ts'\nimport { outputDef } from './nodes/output.ts'\nimport { parameterDef } from './nodes/parameter.ts'\nimport { propertyDef } from './nodes/property.ts'\nimport { requestBodyDef } from './nodes/requestBody.ts'\nimport { responseDef } from './nodes/response.ts'\nimport { schemaDef } from './nodes/schema.ts'\n\n// Surface every def from one place so the package barrel re-exports them with `export * from './registry.ts'`.\n// Adding a node means adding its `defineNode` to a `nodes/*.ts` file and listing it in `nodeDefs` below, nothing else.\nexport {\n arrowFunctionDef,\n breakDef,\n constDef,\n contentDef,\n exportDef,\n fileDef,\n functionDef,\n importDef,\n inputDef,\n jsxDef,\n operationDef,\n outputDef,\n parameterDef,\n propertyDef,\n requestBodyDef,\n responseDef,\n schemaDef,\n sourceDef,\n textDef,\n typeDef,\n}\n\n/**\n * Every node definition. Adding a node means adding its `defineNode` to one\n * `nodes/*.ts` file and listing it here. The visitor tables in `visitor.ts` derive from it.\n */\nexport const nodeDefs = [\n inputDef,\n outputDef,\n operationDef,\n requestBodyDef,\n contentDef,\n responseDef,\n schemaDef,\n propertyDef,\n parameterDef,\n constDef,\n typeDef,\n functionDef,\n arrowFunctionDef,\n textDef,\n breakDef,\n jsxDef,\n importDef,\n exportDef,\n sourceDef,\n fileDef,\n] satisfies ReadonlyArray<NodeDef>\n","import type { VisitorDepth } from './constants.ts'\nimport { visitorDepths } from './constants.ts'\nimport type { NodeDef } from './defineNode.ts'\nimport type { Node } from './nodes/index.ts'\nimport type { ContentNode } from './nodes/content.ts'\nimport type { InputNode } from './nodes/input.ts'\nimport type { NodeKind } from './nodes/base.ts'\nimport type { OperationNode } from './nodes/operation.ts'\nimport type { OutputNode } from './nodes/output.ts'\nimport type { ParameterNode } from './nodes/parameter.ts'\nimport type { PropertyNode } from './nodes/property.ts'\nimport type { RequestBodyNode } from './nodes/requestBody.ts'\nimport type { ResponseNode } from './nodes/response.ts'\nimport type { SchemaNode } from './nodes/schema.ts'\nimport { nodeDefs } from './registry.ts'\n\n/**\n * Child node fields per node kind, in traversal order (Babel's `VISITOR_KEYS`).\n * Derived from each definition's `children`.\n */\nconst VISITOR_KEYS = Object.fromEntries(nodeDefs.flatMap((def) => (def.children ? [[def.kind, def.children] as const] : []))) as Partial<\n Record<NodeKind, ReadonlyArray<string>>\n>\n\n/**\n * Maps a node kind to the matching visitor callback name. Derived from each\n * definition's `visitorKey`.\n */\nconst VISITOR_KEY_BY_KIND = Object.fromEntries(nodeDefs.flatMap((def) => (def.visitorKey ? [[def.kind, def.visitorKey] as const] : []))) as Partial<\n Record<NodeKind, NonNullable<NodeDef['visitorKey']>>\n>\n\n/**\n * Ordered mapping of `[NodeType, ParentType]` pairs.\n *\n * `ParentOf` uses this map to find parent types.\n */\ntype ParentNodeMap = [\n [InputNode, undefined],\n [OutputNode, undefined],\n [OperationNode, InputNode],\n [RequestBodyNode, OperationNode],\n [ContentNode, RequestBodyNode | ResponseNode],\n [SchemaNode, InputNode | ContentNode | SchemaNode | PropertyNode | ParameterNode],\n [PropertyNode, SchemaNode],\n [ParameterNode, OperationNode],\n [ResponseNode, OperationNode],\n]\n\n/**\n * Resolves the parent node type for a given AST node type.\n *\n * Visitor context relies on this so `ctx.parent` is typed for each callback.\n *\n * @example\n * ```ts\n * type InputParent = ParentOf<InputNode>\n * // undefined\n * ```\n *\n * @example\n * ```ts\n * type PropertyParent = ParentOf<PropertyNode>\n * // SchemaNode\n * ```\n *\n * @example\n * ```ts\n * type SchemaParent = ParentOf<SchemaNode>\n * // InputNode | ContentNode | SchemaNode | PropertyNode | ParameterNode\n * ```\n */\nexport type ParentOf<T extends Node, TEntries extends ReadonlyArray<[Node, unknown]> = ParentNodeMap> = TEntries extends [\n infer TEntry extends [Node, unknown],\n ...infer TRest extends ReadonlyArray<[Node, unknown]>,\n]\n ? T extends TEntry[0]\n ? TEntry[1]\n : ParentOf<T, TRest>\n : Node\n\n/**\n * Traversal context passed as the second argument to every visitor callback.\n * `parent` is typed from the current node type.\n *\n * @example\n * ```ts\n * const visitor: Visitor = {\n * schema(node, { parent }) {\n * // parent type is narrowed by node kind\n * },\n * }\n * ```\n */\nexport type VisitorContext<T extends Node = Node> = {\n /**\n * Parent node of the currently visited node.\n * For `InputNode`, this is `undefined`.\n */\n parent?: ParentOf<T>\n}\n\n/**\n * Synchronous visitor consumed by `transform`. Each optional callback runs\n * for the matching node type. Return a new node to replace it, or `undefined`\n * to leave it untouched.\n *\n * Plugins typically expose `transformer` so users can supply a `Visitor` that\n * rewrites the AST before printing.\n *\n * @example Prefix every operationId\n * ```ts\n * const visitor: Visitor = {\n * operation(node) {\n * return { ...node, operationId: `api_${node.operationId}` }\n * },\n * }\n * ```\n *\n * @example Strip schema descriptions\n * ```ts\n * const visitor: Visitor = {\n * schema(node) {\n * return { ...node, description: undefined }\n * },\n * }\n * ```\n */\nexport type Visitor = {\n input?(node: InputNode, context: VisitorContext<InputNode>): undefined | null | InputNode\n output?(node: OutputNode, context: VisitorContext<OutputNode>): undefined | null | OutputNode\n operation?(node: OperationNode, context: VisitorContext<OperationNode>): undefined | null | OperationNode\n schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): undefined | null | SchemaNode\n property?(node: PropertyNode, context: VisitorContext<PropertyNode>): undefined | null | PropertyNode\n parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): undefined | null | ParameterNode\n response?(node: ResponseNode, context: VisitorContext<ResponseNode>): undefined | null | ResponseNode\n}\n\n/**\n * The callbacks of {@link Visitor} with every return type replaced by `TResult`. `collect` uses it\n * so a visitor can yield values instead of replacement nodes.\n *\n * @example\n * ```ts\n * const visitor: VisitorOf<string> = {\n * operation(node) {\n * return node.operationId\n * },\n * }\n * ```\n */\ntype VisitorOf<TResult> = {\n [K in keyof Visitor]?: (node: Parameters<NonNullable<Visitor[K]>>[0], context: Parameters<NonNullable<Visitor[K]>>[1]) => TResult | null | undefined\n}\n\ntype TraversalOptions = {\n /**\n * Traversal depth.\n * @default 'deep'\n */\n depth?: VisitorDepth\n /**\n * Internal parent override used during recursion.\n */\n parent?: Node\n}\n\n/**\n * Options for `transform`.\n *\n * @example\n * ```ts\n * const options: TransformOptions = { depth: 'deep', schema: (node) => node }\n * ```\n *\n * @example\n * ```ts\n * // Only transform the current node, not nested children\n * const options: TransformOptions = { depth: 'shallow', schema: (node) => node }\n * ```\n */\ntype TransformOptions = Visitor & TraversalOptions\n\n/**\n * Options for `collect`.\n *\n * @example\n * ```ts\n * const options: CollectOptions<string> = { depth: 'shallow', schema: () => undefined }\n * ```\n */\ntype CollectOptions<T> = VisitorOf<T> & TraversalOptions\n\nconst visitorKeysByKind = VISITOR_KEYS as Record<string, ReadonlyArray<string> | undefined>\n\n/**\n * Returns `true` when `value` is an AST node (an object carrying a `kind`).\n */\nfunction isNode(value: unknown): value is Node {\n return typeof value === 'object' && value !== null && typeof (value as { kind?: unknown }).kind === 'string'\n}\n\n/**\n * Returns `true` for a plain object that maps names to nodes, such as `patternProperties`.\n */\nfunction isNodeRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Returns the child fields of `node` to walk, from {@link VISITOR_KEYS}, or `undefined` when there\n * is nothing to walk. `Schema` children are only walked when `recurse` is `true`.\n */\nfunction childKeys(node: Node, recurse: boolean): ReadonlyArray<string> | undefined {\n if (node.kind === 'Schema' && !recurse) return undefined\n\n return visitorKeysByKind[node.kind]\n}\n\n/**\n * Returns the immediate traversable children of `node`.\n *\n * @example\n * ```ts\n * const children = getChildren(operationNode, true)\n * // returns parameters, the request body, and responses\n * ```\n */\nfunction* getChildren(node: Node, recurse: boolean): Generator<Node, void, undefined> {\n const keys = childKeys(node, recurse)\n if (!keys) return\n\n const record = node as unknown as Record<string, unknown>\n for (const key of keys) {\n const value = record[key]\n if (Array.isArray(value)) {\n for (const item of value) if (isNode(item)) yield item\n continue\n }\n if (isNode(value)) {\n yield value\n continue\n }\n if (isNodeRecord(value)) {\n for (const item of Object.values(value)) if (isNode(item)) yield item\n }\n }\n}\n\n/**\n * Runs the visitor callback that matches `node.kind` with the traversal\n * context. The result is a replacement node, a collected value, or `undefined`\n * when no callback is registered for the kind.\n *\n * Shared by `transform` and `collect` so node-kind dispatch lives in one place.\n * `TResult` is the caller's expected return: the same node type for `transform`,\n * the collected value type for `collect`.\n */\nfunction applyVisitor<TResult>(node: Node, visitor: Visitor | VisitorOf<unknown>, parent: Node | undefined): TResult | null | undefined {\n const key = VISITOR_KEY_BY_KIND[node.kind]\n if (!key) return undefined\n\n const fn = visitor[key] as ((node: Node, context: VisitorContext) => TResult | null | undefined) | undefined\n\n return fn?.(node, { parent })\n}\n\n/**\n * Synchronous depth-first transform. Each visitor callback can return a\n * replacement node. Returning `undefined` keeps the original.\n *\n * The original tree is never mutated, a new tree is returned. Pass\n * `depth: 'shallow'` to skip recursion into children.\n *\n * @example Prefix every operationId\n * ```ts\n * const next = transform(root, {\n * operation(node) {\n * return { ...node, operationId: `prefixed_${node.operationId}` }\n * },\n * })\n * ```\n *\n * @example Replace only the root node\n * ```ts\n * const next = transform(root, {\n * depth: 'shallow',\n * input: (node) => ({ ...node, meta: { ...node.meta, title: 'Rewritten' } }),\n * })\n * ```\n */\nexport function transform<T extends Node>(node: T, options: TransformOptions): T {\n const { depth, parent, ...visitor } = options\n const recurse = (depth ?? visitorDepths.deep) === visitorDepths.deep\n\n // Split the visitor object out once here, then thread it plus `recurse`/`parent` as plain\n // arguments through the recursion. The previous code re-ran the `...visitor` rest-destructure on\n // every recursive `transform` call and rebuilt a `{ ...options, parent }` object per node, so the\n // options shape (which callbacks are present) varied call to call and the hot recursion churned.\n return transformNode(node, visitor, recurse, parent) as T\n}\n\n/**\n * Visits a single node, then immutably rebuilds its children. Returns the original\n * reference when neither the visitor nor the child rebuild changed anything, so callers\n * can detect \"nothing changed\" by identity and ancestors avoid reallocating.\n */\nfunction transformNode(node: Node, visitor: Visitor, recurse: boolean, parent: Node | undefined): Node {\n const visited = applyVisitor<Node>(node, visitor, parent) ?? node\n return transformChildren(visited, visitor, recurse)\n}\n\n/**\n * Immutably rebuilds a node's children, transforming each child node and leaving non-node values\n * (e.g. `additionalProperties: true`) intact.\n */\nfunction transformChildren(node: Node, visitor: Visitor, recurse: boolean): Node {\n const keys = childKeys(node, recurse)\n if (!keys) return node\n\n const record = node as unknown as Record<string, unknown>\n let updates: Record<string, unknown> | undefined\n\n for (const key of keys) {\n if (!(key in record)) continue\n const value = record[key]\n if (Array.isArray(value)) {\n // Rebuild the array lazily: allocate a new array only once a child actually changes, copying\n // the unchanged prefix at that point. An unchanged array keeps its original reference and\n // allocates nothing. This also drops the per-array `.map` closure that ran on every node.\n let mapped: Array<unknown> | undefined\n for (const [i, item] of value.entries()) {\n const next = isNode(item) ? transformNode(item, visitor, recurse, node) : item\n if (mapped) {\n mapped.push(next)\n continue\n }\n if (next !== item) mapped = [...value.slice(0, i), next]\n }\n if (mapped) (updates ??= {})[key] = mapped\n continue\n }\n if (isNode(value)) {\n const next = transformNode(value, visitor, recurse, node)\n if (next !== value) (updates ??= {})[key] = next\n continue\n }\n if (isNodeRecord(value)) {\n let mapped: Record<string, unknown> | undefined\n for (const [name, item] of Object.entries(value)) {\n const next = isNode(item) ? transformNode(item, visitor, recurse, node) : item\n if (next !== item) (mapped ??= { ...value })[name] = next\n }\n if (mapped) (updates ??= {})[key] = mapped\n }\n }\n\n if (!updates) return node\n const merged = { ...node, ...updates }\n return merged as Node\n}\n\n/**\n * Lazy depth-first collection pass. Yields every non-null value returned by\n * the visitor callbacks. Use `collectSync` for the eager array form.\n *\n * @example Collect every operationId\n * ```ts\n * const ids: string[] = []\n * for (const id of collect<string>(root, {\n * operation(node) {\n * return node.operationId\n * },\n * })) {\n * ids.push(id)\n * }\n * ```\n */\nexport function* collect<T>(node: Node, options: CollectOptions<T>): Generator<T, void, undefined> {\n const { depth, parent, ...visitor } = options\n const recurse = (depth ?? visitorDepths.deep) === visitorDepths.deep\n\n // Thread the split-out visitor through the recursion instead of rebuilding `{ ...options, parent }`\n // for every child, mirroring `transform`. Keeps the recursive object shape stable.\n yield* collectNode<T>(node, visitor, recurse, parent)\n}\n\nfunction* collectNode<T>(node: Node, visitor: VisitorOf<T>, recurse: boolean, parent: Node | undefined): Generator<T, void, undefined> {\n const v = applyVisitor<T>(node, visitor, parent)\n if (v != null) yield v\n\n for (const child of getChildren(node, recurse)) {\n yield* collectNode<T>(child, visitor, recurse, node)\n }\n}\n\n/**\n * Eager depth-first collection pass. Gathers every non-null value the visitor\n * callbacks return into an array.\n *\n * @example Collect every operationId\n * ```ts\n * const ids = collectSync<string>(root, {\n * operation(node) {\n * return node.operationId\n * },\n * })\n * ```\n */\nexport function collectSync<T>(node: Node, options: CollectOptions<T>): Array<T> {\n return Array.from(collect(node, options))\n}\n","import type { VisitorDepth } from './constants.ts'\nimport type { VisitorKey } from './defineNode.ts'\nimport { visitorKeys } from './defineNode.ts'\nimport type { Node } from './nodes/index.ts'\nimport type { Visitor, VisitorContext } from './visitor.ts'\nimport { transform } from './visitor.ts'\n\n/**\n * Ordering hint shared by macros and plugins. `pre` runs before unmarked items, `post` after,\n * and `undefined` keeps declaration order.\n */\nexport type Enforce = 'pre' | 'post'\n\n/**\n * Sort weight for an `enforce` hint. `pre` sorts before unmarked items and `post` after, so a plain\n * list keeps its authored order.\n */\nfunction enforceWeight(enforce?: Enforce): number {\n if (enforce === 'pre') return 0\n if (enforce === 'post') return 2\n return 1\n}\n\n/**\n * A named, composable transform over the Kubb AST. It carries the same per-kind callbacks as a\n * {@link Visitor} (`schema`, `operation`, …), plus a `name`, an optional `enforce` order, and an\n * optional `match` predicate. Macros run on the shared AST, so the same macro works across every\n * adapter and output target. Exports follow the `macro<Name>` convention, mirroring plugins (`pluginTs`).\n */\nexport type Macro = Visitor & {\n /**\n * Macro identifier used to tell macros apart, for example `'simplify-union'`.\n */\n name: string\n /**\n * Ordering hint. `pre` macros run before unmarked macros, `post` macros run after.\n * Ordering within a bucket follows list order.\n */\n enforce?: Enforce\n /**\n * Predicate checked against the current node before any callback runs. Returning `false`\n * skips the macro for that node.\n */\n match?: (node: Node) => boolean\n}\n\n/**\n * Types a macro for inference and a single construction site, mirroring `defineExtension`.\n * Adds no runtime behavior.\n *\n * @example\n * ```ts\n * const macroUntagged = defineMacro({\n * name: 'untagged',\n * operation(node) {\n * return node.tags?.length ? undefined : { ...node, tags: ['untagged'] }\n * },\n * })\n * ```\n */\nexport function defineMacro(macro: Macro): Macro {\n return macro\n}\n\ntype MacroCallback = (node: Node, context: VisitorContext) => Node | null | undefined\n\ntype ChainProps = {\n macros: ReadonlyArray<Macro>\n key: VisitorKey\n node: Node\n context: VisitorContext\n}\n\n/**\n * Runs every macro's callback for one node kind in order, chaining the result so each macro sees\n * the previous macro's output. Returns `undefined` when nothing changed, so `transform` keeps the\n * original reference (structural sharing).\n */\nfunction chain({ macros, key, node, context }: ChainProps): Node | undefined {\n let current = node\n\n for (const macro of macros) {\n const callback = macro[key] as MacroCallback | undefined\n if (!callback) continue\n if (macro.match && !macro.match(current)) continue\n\n const next = callback(current, context)\n if (next != null) current = next\n }\n\n return current === node ? undefined : current\n}\n\n/**\n * Folds an ordered list of macros into a single {@link Visitor} that `transform` (and the per-plugin\n * transform layer in `@kubb/core`) can run. Macros are stable-sorted by `enforce`, then applied\n * sequentially per node so later macros see earlier output. This differs from a plain visitor, which\n * has no names, ordering, or composition.\n *\n * @example\n * ```ts\n * const visitor = composeMacros([macroSimplifyUnion, macroDiscriminatorEnum])\n * const next = transform(root, visitor)\n * ```\n */\nexport function composeMacros(macros: ReadonlyArray<Macro>): Visitor {\n const ordered = [...macros].sort((a, b) => enforceWeight(a.enforce) - enforceWeight(b.enforce))\n\n const visitor: Visitor = {}\n for (const key of visitorKeys) {\n if (!ordered.some((macro) => typeof macro[key] === 'function')) continue\n\n const callback = (node: Node, context: VisitorContext) => chain({ macros: ordered, key, node, context })\n ;(visitor as Record<VisitorKey, MacroCallback>)[key] = callback\n }\n\n return visitor\n}\n\n/**\n * Runs a list of macros over a node tree and returns the rewritten tree. Keeps `transform`'s\n * structural sharing, so an empty or no-op macro list returns the same reference. Pass\n * `depth: 'shallow'` to rewrite the root node only.\n *\n * @example\n * ```ts\n * const next = applyMacros(root, [macroIntegerToString])\n * ```\n *\n * @example Apply to the root node only\n * ```ts\n * const named = applyMacros(node, [macroEnumName({ parentName, propName, enumSuffix })], { depth: 'shallow' })\n * ```\n */\nexport function applyMacros<TNode extends Node>(root: TNode, macros: ReadonlyArray<Macro>, options?: { depth?: VisitorDepth }): TNode {\n if (macros.length === 0) return root\n\n return transform(root, { ...composeMacros(macros), ...options }) as TNode\n}\n","import type { ImportNode } from './nodes/file.ts'\nimport type { SchemaNode, SchemaNodeByType, SchemaType } from './nodes/schema.ts'\n\n/**\n * Runtime context passed as `this` to printer handlers.\n *\n * `this.transform` dispatches to node-level handlers from `nodes`.\n *\n * @example\n * ```ts\n * const context: PrinterHandlerContext<string, {}> = {\n * options: {},\n * transform: () => 'value',\n * base: () => 'value',\n * }\n * ```\n */\ntype PrinterHandlerContext<TOutput, TOptions extends object> = {\n /**\n * Recursively transform a nested `SchemaNode` to `TOutput` using the node-level handlers.\n * Use `this.transform` inside `nodes` handlers and inside the `print` override.\n */\n transform: (node: SchemaNode) => TOutput | null\n /**\n * Run the printer's built-in handler for the node, ignoring any override for its type.\n * Inside an override, `this.base(node)` returns what the printer would have emitted,\n * so the override can wrap it instead of re-implementing the handler. Nested nodes\n * still dispatch through the overrides.\n */\n base: (node: SchemaNode) => TOutput | null\n /** Declares an import the printed code needs. The generator reads it back with `printer.drainImports()`. */\n import: (node: ImportNode) => void\n /**\n * Options for this printer instance.\n */\n options: TOptions\n}\n\n/**\n * Handler for one schema node type.\n *\n * Use a regular function (not an arrow function) if you need `this`.\n *\n * @example\n * ```ts\n * const handler: PrinterHandler<string, {}, 'string'> = function () {\n * return 'string'\n * }\n * ```\n */\ntype PrinterHandler<TOutput, TOptions extends object, T extends SchemaType = SchemaType> = (\n this: PrinterHandlerContext<TOutput, TOptions>,\n node: SchemaNodeByType[T],\n) => TOutput | null\n\n/**\n * Partial map of per-node-type handler overrides for a printer.\n *\n * Each key is a `SchemaType` string (e.g. `'date'`, `'string'`).\n * Supply only the handlers you want to replace. The printer's built-in\n * defaults fill in the rest.\n *\n * @example\n * ```ts\n * pluginZod({\n * printer: {\n * nodes: {\n * date(): string {\n * return 'z.string().date()'\n * },\n * } satisfies PrinterPartial<string, PrinterZodOptions>,\n * },\n * })\n * ```\n */\nexport type PrinterPartial<TOutput, TOptions extends object> = Partial<{\n [K in SchemaType]: PrinterHandler<TOutput, TOptions, K>\n}>\n\n/**\n * Generic shape used by `definePrinter`.\n *\n * - `TName` unique string identifier (e.g. `'zod'`, `'ts'`)\n * - `TOptions` options passed to and stored on the printer instance\n * - `TOutput` the type emitted by node handlers\n * - `TPrintOutput` type returned by public `print` (defaults to `TOutput`)\n *\n * @example\n * ```ts\n * type MyPrinter = PrinterFactoryOptions<'my', { strict: boolean }, string>\n * ```\n */\nexport type PrinterFactoryOptions<TName extends string = string, TOptions extends object = object, TOutput = unknown, TPrintOutput = TOutput> = {\n name: TName\n options: TOptions\n output: TOutput\n printOutput: TPrintOutput\n}\n\n/**\n * Printer instance returned by a printer factory.\n *\n * @example\n * ```ts\n * const printer = definePrinter((options: {}) => ({ name: 'x', options, nodes: {} }))({})\n * ```\n */\nexport type Printer<T extends PrinterFactoryOptions = PrinterFactoryOptions> = {\n /**\n * Unique identifier supplied at creation time.\n */\n name: T['name']\n /**\n * Options for this printer instance.\n */\n options: T['options']\n /**\n * Node-level dispatcher, converts a `SchemaNode` directly to `TOutput` using the `nodes` handlers.\n * Always dispatches through the `nodes` map. Never calls the `print` override.\n * Reach for it when you need the raw output (e.g. `ts.TypeNode`) without declaration wrapping.\n */\n transform: (node: SchemaNode) => T['output'] | null\n /**\n * Public printer. If the builder provides a root-level `print`, this calls that\n * higher-level function (which may produce full declarations).\n * Otherwise, falls back to the node-level dispatcher.\n */\n print: (node: SchemaNode) => T['printOutput'] | null\n /** Returns the imports declared with `this.import(...)` since the last call, then clears them. */\n drainImports: () => Array<ImportNode>\n}\n\n/**\n * Builder function passed to `definePrinter`.\n *\n * It receives resolved options and returns:\n * - `name`\n * - `options`\n * - `nodes` handlers\n * - optional top-level `print` override\n *\n * @example\n * ```ts\n * const build = (options: {}) => ({ name: 'x' as const, options, nodes: {} })\n * ```\n */\ntype PrinterBuilder<T extends PrinterFactoryOptions> = (options: T['options']) => {\n name: T['name']\n /**\n * Options to store on the printer.\n */\n options: T['options']\n nodes: PrinterPartial<T['output'], T['options']>\n /**\n * User-supplied handler overrides. An override wins over the matching `nodes` handler,\n * and can call `this.base(node)` to reuse the handler it replaced. Pass overrides here\n * instead of spreading them into `nodes`, otherwise `this.base` cannot find the original.\n */\n overrides?: PrinterPartial<T['output'], T['options']>\n /**\n * Optional root-level print override. When provided, becomes the public `printer.print`.\n * Use `this.transform(node)` inside this function to dispatch to the node-level handlers (`nodes`),\n * not the override itself, so recursion is safe.\n */\n print?: (this: PrinterHandlerContext<T['output'], T['options']>, node: SchemaNode) => T['printOutput'] | null\n}\n/**\n * Creates a schema printer: a function that takes a `SchemaNode` and emits\n * code in your target language. Each plugin that produces code from schemas\n * (TypeScript types, Zod schemas, Faker factories) ships a printer built\n * with this helper.\n *\n * The builder receives resolved options and returns:\n *\n * - `name` unique identifier for the printer.\n * - `options` stored on the returned printer instance.\n * - `nodes` map of `SchemaType` → handler. Handlers return the rendered\n * output (a string, a TypeScript AST node, ...) for that schema type.\n * - `overrides` (optional), user-supplied handlers that win over `nodes`.\n * An override can call `this.base(node)` to reuse the handler it replaced.\n * - `print` (optional), top-level override exposed as `printer.print`.\n * Use `this.transform(node)` inside it to dispatch to `nodes` recursively.\n *\n * Without a `print` override, `printer.print` falls back to `printer.transform`\n * (the node-level dispatcher).\n *\n * @example Tiny Zod printer\n * ```ts\n * import { createPrinter, type PrinterFactoryOptions } from '@kubb/ast'\n *\n * type PrinterZod = PrinterFactoryOptions<'zod', { strict?: boolean }, string>\n *\n * export const zodPrinter = createPrinter<PrinterZod>((options) => ({\n * name: 'zod',\n * options: { strict: options.strict ?? true },\n * nodes: {\n * string: () => 'z.string()',\n * object(node) {\n * const props = node.properties\n * .map((p) => `${p.name}: ${this.transform(p.schema)}`)\n * .join(', ')\n * return `z.object({ ${props} })`\n * },\n * },\n * }))\n * ```\n */\nexport function createPrinter<T extends PrinterFactoryOptions = PrinterFactoryOptions>(build: PrinterBuilder<T>): (options?: T['options']) => Printer<T> {\n return (options) => {\n const { name, options: resolvedOptions, nodes, overrides, print: printOverride } = build((options ?? {}) as T['options'])\n const merged = overrides ? { ...nodes, ...overrides } : nodes\n\n const collectedImports: Array<ImportNode> = []\n\n const dispatch =\n (table: PrinterPartial<T['output'], T['options']>) =>\n (node: SchemaNode): T['output'] | null => {\n const handler = table[node.type]\n if (!handler) return null\n\n return (handler as (this: PrinterHandlerContext<T['output'], T['options']>, node: SchemaNode) => T['output'] | null).call(context, node)\n }\n\n const context: PrinterHandlerContext<T['output'], T['options']> = {\n options: resolvedOptions,\n import: (node: ImportNode): void => {\n collectedImports.push(node)\n },\n transform: dispatch(merged),\n base: dispatch(nodes),\n }\n\n return {\n name,\n options: resolvedOptions,\n transform: context.transform,\n print: (printOverride ? printOverride.bind(context) : context.transform) as (node: SchemaNode) => T['printOutput'] | null,\n drainImports: () => collectedImports.splice(0),\n }\n }\n}\n","import type { RefSchemaNode, SchemaNode } from '../nodes/schema.ts'\n\n/**\n * Resolves the emitted name of the schema a ref node points at. Prefers `targetName` (set when\n * the referenced schema was renamed, e.g. to break a collision), then the last segment of `ref`,\n * then `name`, then the nested `schema.name`.\n *\n * Returns `null` for non-ref nodes or when no name resolves.\n *\n * @example\n * `resolveRefName({ kind: 'Schema', type: 'ref', ref: '#/components/schemas/Pet' }) // 'Pet'`\n *\n * @example Collision-renamed target\n * `resolveRefName({ kind: 'Schema', type: 'ref', ref: '#/components/schemas/Order', targetName: 'OrderSchema' }) // 'OrderSchema'`\n */\nexport function resolveRefName(node: SchemaNode | null | undefined): string | null {\n if (!node || node.type !== 'ref') return null\n if (node.targetName) return node.targetName\n if (node.ref) return node.ref.split('/').at(-1) ?? node.ref\n\n return node.name ?? node.schema?.name ?? null\n}\n\n/**\n * Merges a ref node with its resolved schema, giving the fields set at the usage site precedence.\n *\n * Every field on the ref except `kind`, `type`, `name`, `ref`, and `schema` overrides the same field\n * of the resolved `schema` (for example `description`, `nullable`, `readOnly`, `deprecated`). Fields\n * left `undefined` on the ref do not shadow the resolved schema. A ref without a resolved `schema`\n * is returned as is.\n *\n * @example\n * ```ts\n * const ref = createSchema({ type: 'ref', ref: '#/components/schemas/Pet', description: 'A pet', schema: petSchema })\n * mergeRefWithSchema(ref) // petSchema's fields with description 'A pet'\n * ```\n */\nexport function mergeRefWithSchema(node: RefSchemaNode): SchemaNode {\n if (!node.schema) return node\n\n const { kind: _kind, type: _type, name: _name, ref: _ref, schema: _schema, ...overrides } = node\n const definedOverrides = Object.fromEntries(Object.entries(overrides).filter(([, value]) => value !== undefined))\n\n return { ...node.schema, ...definedOverrides }\n}\n\n/**\n * Returns `true` when a schema is a bare ref without modifiers, metadata, or omit keys.\n *\n * Modifiers inherited from the resolved schema are included in the check because a ref emits the\n * referenced schema variable with those modifiers already applied.\n */\nexport function isBareRef(node: SchemaNode | null | undefined, keysToOmit?: Array<string> | null): boolean {\n if (!node || node.type !== 'ref') return false\n\n const meta = mergeRefWithSchema(node)\n\n return !meta.nullable && !meta.optional && !meta.nullish && meta.default === undefined && !meta.description && !meta.examples?.length && !keysToOmit?.length\n}\n","/** A value that may already be resolved or still pending.\n *\n * @example\n * ```ts\n * function load(id: string): PossiblePromise<string> {\n * return cache.get(id) ?? fetchRemote(id)\n * }\n * ```\n */\nexport type PossiblePromise<T> = Promise<T> | T\n\n/** Returns `true` when `result` is a thenable `Promise`.\n *\n * @example\n * ```ts\n * isPromise(Promise.resolve(1)) // true\n * isPromise(42) // false\n * ```\n */\nexport function isPromise<T>(result: PossiblePromise<T>): result is Promise<T> {\n return result !== null && result !== undefined && typeof (result as Record<string, unknown>)['then'] === 'function'\n}\n\ntype Store<TKey, TValue> = {\n has(key: TKey): boolean\n get(key: TKey): TValue | undefined\n set(key: TKey, value: TValue): unknown\n}\n\n/**\n * Wraps `factory` with a keyed cache backed by the provided store.\n *\n * Pass a `WeakMap` for object keys (results are GC-eligible when the key is\n * collected) or a `Map` for primitive keys. For multi-argument functions,\n * nest two `memoize` calls — the outer keyed by the first argument, the\n * inner (created once per outer miss) keyed by the second.\n *\n * Because the cache is owned by the caller, it can be shared, inspected, or\n * cleared independently of the memoized function.\n *\n * @example Single WeakMap key\n * ```ts\n * const cache = new WeakMap<SchemaNode, Set<string>>()\n * const getRefs = memoize(cache, (node) => collectRefs(node))\n * ```\n *\n * @example Single Map key (primitive)\n * ```ts\n * const cache = new Map<string, Resolver>()\n * const getResolver = memoize(cache, (name) => buildResolver(name))\n * ```\n *\n * @example Two-level (object + primitive)\n * ```ts\n * const outer = new WeakMap<Params[], Map<string, Params[]>>()\n * const fn = memoize(outer, (params) => memoize(new Map(), (key) => transform(params, key)))\n * fn(params)('camelcase')\n * ```\n */\nexport function memoize<TKey, TValue>(store: Store<TKey, TValue>, factory: (key: TKey) => TValue): (key: TKey) => TValue {\n return (key: TKey): TValue => {\n if (store.has(key)) return store.get(key)!\n const value = factory(key)\n store.set(key, value)\n return value\n }\n}\n\ntype ParallelOptions<TItem> = {\n /**\n * Items to work through, handed out in order.\n */\n items: ReadonlyArray<TItem>\n /**\n * How many items may be in flight at once.\n */\n limit: number\n /**\n * Runs once per item, with the item's position so a caller can report progress.\n */\n run(item: TItem, index: number): Promise<void>\n}\n\n/**\n * Runs `run` over every item with at most `limit` in flight. Workers share one iterator, so each\n * takes the next item the moment it frees up instead of waiting for a batch to drain.\n *\n * @example\n * ```ts\n * await inParallel({ items: files, limit: 50, run: (file) => storage.writeItem(file.path, file.source) })\n * ```\n */\nexport async function inParallel<TItem>({ items, limit, run }: ParallelOptions<TItem>): Promise<void> {\n const queue = items.entries()\n\n const worker = async (): Promise<void> => {\n for (const [index, item] of queue) await run(item, index)\n }\n\n await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => worker()))\n}\n","import { memoize } from '@internals/utils'\nimport type { OperationNode } from '../nodes/operation.ts'\nimport type { SchemaNode } from '../nodes/schema.ts'\nimport { collect, collectSync } from '../visitor.ts'\nimport { resolveRefName } from './refs.ts'\n\n/**\n * Collects the names of every schema a node's subtree references, resolved with `resolveRefName`.\n * Each ref contributes its name only, so the schema it points to is never traversed. The walk is\n * memoized by node identity, which lets `findCircularSchemas` and `containsCircularRef` share one\n * scan per schema.\n *\n * @example\n * ```ts\n * collectSchemaRefs(petSchema)\n * // Set { 'Category', 'Tag' }\n * ```\n */\nexport const collectSchemaRefs = memoize(new WeakMap<SchemaNode, ReadonlySet<string>>(), (node: SchemaNode): ReadonlySet<string> => {\n const refs = new Set<string>()\n collectSync<void>(node, {\n schema(child) {\n if (child.type === 'ref') {\n const name = resolveRefName(child)\n if (name) refs.add(name)\n }\n },\n })\n return refs\n})\n\n/**\n * Collects the de-duplicated target names of every pointer-carrying ref in a node's subtree, in\n * first-occurrence order. The walk is memoized by node identity, so the subtree is scanned once and\n * `resolver.imports` reads the same result across the ts, zod, and faker plugins instead of\n * re-scanning the same schema per plugin.\n *\n * Only refs that carry a `$ref` pointer count, so a synthesized ref pointing at a sibling in the\n * same file (a union member created by name) is left out. That leaves exactly the set\n * `resolver.imports` emits.\n *\n * @example\n * ```ts\n * collectImportedRefNames(petSchema)\n * // ['Category', 'Tag']\n * ```\n */\nexport const collectImportedRefNames = memoize(new WeakMap<SchemaNode, ReadonlyArray<string>>(), (node: SchemaNode): ReadonlyArray<string> => {\n const seen = new Set<string>()\n const names: Array<string> = []\n collectSync<void>(node, {\n schema(child) {\n if (child.type !== 'ref' || !child.ref) return\n const name = resolveRefName(child)\n if (name && !seen.has(name)) {\n seen.add(name)\n names.push(name)\n }\n },\n })\n return names\n})\n\n/**\n * Collects the names of all top-level schemas transitively used by a set of operations.\n *\n * An operation uses a schema when its parameters, request body, or responses reference it, directly\n * or through other named schemas. Once a name is added to the result it is not revisited, so\n * reference cycles terminate.\n *\n * Pair it with `include` filters so schemas reachable only from excluded operations stay ungenerated.\n *\n * @example Only generate schemas referenced by included operations\n * ```ts\n * const includedOps = operations.filter((op) => resolver.default.options(op, { options, include }) !== null)\n * const allowed = collectUsedSchemaNames(includedOps, schemas)\n *\n * for (const schema of schemas) {\n * if (schema.name && !allowed.has(schema.name)) continue\n * // generate schema\n * }\n * ```\n */\nexport function collectUsedSchemaNames(operations: ReadonlyArray<OperationNode>, schemas: ReadonlyArray<SchemaNode>): Set<string> {\n const schemaMap = new Map<string, SchemaNode>()\n for (const schema of schemas) {\n if (schema.name) schemaMap.set(schema.name, schema)\n }\n\n const result = new Set<string>()\n\n function visitSchema(schema: SchemaNode): void {\n for (const name of collectSchemaRefs(schema)) {\n if (!result.has(name)) {\n result.add(name)\n const namedSchema = schemaMap.get(name)\n if (namedSchema) visitSchema(namedSchema)\n }\n }\n }\n\n for (const op of operations) {\n for (const schema of collect<SchemaNode>(op, { depth: 'shallow', schema: (node) => node })) {\n visitSchema(schema)\n }\n }\n\n return result\n}\n\n/**\n * Finds every schema that takes part in a circular dependency chain in a schema dependency graph\n * that maps each schema name to the names it references directly.\n *\n * Use this when the graph was already collected during another pass (e.g. the adapter's convert\n * walk), so the schema nodes are not swept a second time. `findCircularSchemas` builds the graph\n * from schema nodes and delegates here.\n *\n * @example\n * ```ts\n * const graph = new Map([\n * ['Pet', new Set(['Category'])],\n * ['Category', new Set(['Pet'])],\n * ])\n * findCircularSchemasFromGraph(graph) // Set { 'Pet', 'Category' }\n * ```\n */\nexport function findCircularSchemasFromGraph(graph: ReadonlyMap<string, ReadonlySet<string>>): Set<string> {\n const circular = new Set<string>()\n for (const start of graph.keys()) {\n const visited = new Set<string>()\n const stack: Array<string> = [...(graph.get(start) ?? [])]\n while (stack.length > 0) {\n const node = stack.pop()!\n if (node === start) {\n circular.add(start)\n break\n }\n if (visited.has(node)) continue\n visited.add(node)\n\n const next = graph.get(node)\n if (next) for (const r of next) stack.push(r)\n }\n }\n\n return circular\n}\n\n/**\n * Finds every schema that takes part in a circular dependency chain, including direct self-loops.\n *\n * Wrap the returned schema positions in a deferred construct (a lazy getter or `z.lazy(() => …)`) so\n * the generated code does not recurse forever. Refs are followed by name only, so the walk stays\n * linear in the size of the schema graph.\n *\n * @note Call this once on the full graph, then check individual schemas with `containsCircularRef()`.\n */\nexport function findCircularSchemas(schemas: ReadonlyArray<SchemaNode>): Set<string> {\n const graph = new Map<string, ReadonlySet<string>>()\n for (const schema of schemas) {\n if (schema.name) graph.set(schema.name, collectSchemaRefs(schema))\n }\n\n return findCircularSchemasFromGraph(graph)\n}\n","import type { PropertyNode } from '../nodes/property.ts'\nimport type { SchemaNode } from '../nodes/schema.ts'\n\n/**\n * Finds every matching property exposed by an object, resolved reference, or intersection.\n *\n * References are followed through their parsed `schema`. Circular references terminate without\n * revisiting a node. Unions are not traversed because a property on one branch does not describe\n * every branch.\n *\n * @example Faker discriminator narrowing\n * ```ts\n * const values = resolveSchemaProperties({ node: member, propertyName: union.discriminatorPropertyName }).flatMap(({ schema }) =>\n * getSchemaLiteralValues(schema),\n * )\n * const typeName = `Extract<Pet, { type: ${values.map(JSON.stringify).join(' | ')} }>`\n * ```\n *\n * @example Zod discriminated unions\n * ```ts\n * const canDiscriminate = union.members?.every(\n * (member) => resolveSchemaProperties({ node: member, propertyName: 'type' }).length > 0,\n * )\n * const expression = canDiscriminate ? `z.discriminatedUnion('type', members)` : `z.union(members)`\n * ```\n *\n * @example TypeScript property lookup\n * ```ts\n * const properties = resolveSchemaProperties({ node: schema, propertyName: 'status' })\n * const statusSchemas = properties.map((property) => print(property.schema))\n * ```\n */\nexport function resolveSchemaProperties({ node, propertyName }: { node: SchemaNode; propertyName: string }): ReadonlyArray<PropertyNode> {\n const properties: Array<PropertyNode> = []\n const visited = new WeakSet<SchemaNode>()\n\n function visit(current: SchemaNode | null | undefined): void {\n if (!current || visited.has(current)) return\n visited.add(current)\n\n if (current.type === 'object') {\n const property = current.properties.find((candidate) => candidate.name === propertyName)\n if (property) properties.push(property)\n return\n }\n\n if (current.type === 'ref') {\n visit(current.schema)\n return\n }\n\n if (current.type === 'intersection') {\n for (const member of current.members ?? []) visit(member)\n }\n }\n\n visit(node)\n return properties\n}\n\n/**\n * Reads the unique literal values represented by an enum, resolved reference, or union.\n *\n * Named enum values take precedence over simple enum values, matching how renderers consume\n * `EnumSchemaNode`.\n *\n * @example\n * ```ts\n * const values = getSchemaLiteralValues(enumNode)\n * // ['cat', 'dog']\n * ```\n */\nexport function getSchemaLiteralValues(node: SchemaNode): ReadonlyArray<string | number | boolean | null> {\n const values = new Set<string | number | boolean | null>()\n const visited = new WeakSet<SchemaNode>()\n\n function visit(current: SchemaNode | null | undefined): void {\n if (!current || visited.has(current)) return\n visited.add(current)\n\n if (current.type === 'enum') {\n const enumValues = current.namedEnumValues?.map(({ value }) => value) ?? current.enumValues ?? []\n for (const value of enumValues) values.add(value)\n return\n }\n\n if (current.type === 'ref') {\n visit(current.schema)\n return\n }\n\n if (current.type === 'union') {\n for (const member of current.members ?? []) visit(member)\n }\n }\n\n visit(node)\n return [...values]\n}\n\n// Names of every property an object, resolved reference, or intersection exposes.\nfunction collectPropertyNames(node: SchemaNode, visited: WeakSet<SchemaNode> = new WeakSet()): Set<string> {\n if (visited.has(node)) return new Set()\n visited.add(node)\n\n if (node.type === 'object') return new Set(node.properties.map((property) => property.name))\n if (node.type === 'ref') return node.schema ? collectPropertyNames(node.schema, visited) : new Set()\n\n if (node.type === 'intersection') {\n const names = new Set<string>()\n for (const member of node.members ?? []) {\n for (const name of collectPropertyNames(member, visited)) names.add(name)\n }\n return names\n }\n\n return new Set()\n}\n\n/**\n * Infers an implicit discriminator: a property every member exposes with a distinct single\n * literal value, the same shape a declared OpenAPI `discriminator` already narrows on.\n */\nexport function inferDiscriminatorPropertyName(members: ReadonlyArray<SchemaNode>): string | undefined {\n if (members.length < 2) return undefined\n\n let candidates: Set<string> | undefined\n for (const member of members) {\n const names = collectPropertyNames(member)\n candidates = candidates ? new Set([...candidates].filter((name) => names.has(name))) : names\n }\n\n for (const name of candidates ?? []) {\n const values = members.map((member) => {\n const literals = new Set(resolveSchemaProperties({ node: member, propertyName: name }).flatMap((property) => getSchemaLiteralValues(property.schema)))\n return literals.size === 1 ? [...literals][0] : undefined\n })\n\n if (values.every((value) => value !== undefined) && new Set(values).size === members.length) {\n return name\n }\n }\n\n return undefined\n}\n","import type { Node } from './nodes/index.ts'\n\nexport { createArrowFunction, createBreak, createConst, createFunction, createJsx, createText, createType } from './nodes/code.ts'\nexport { createContent } from './nodes/content.ts'\nexport { createExport, createFile, createImport, createSource } from './nodes/file.ts'\nexport type { UserFileNode } from './nodes/file.ts'\nexport { createInput } from './nodes/input.ts'\nexport { createOperation } from './nodes/operation.ts'\nexport { createOutput } from './nodes/output.ts'\nexport { createParameter } from './nodes/parameter.ts'\nexport { createProperty } from './nodes/property.ts'\nexport { createRequestBody } from './nodes/requestBody.ts'\nexport { createResponse } from './nodes/response.ts'\nexport { createSchema } from './nodes/schema.ts'\n\n/**\n * Identity-preserving node update: returns `node` unchanged when every field in\n * `changes` already equals (by reference) the current value, otherwise a new node\n * with the changes applied.\n *\n * Mirrors the TypeScript compiler's `factory.updateX` contract. Pair it with the\n * structural sharing in {@link transform} so a no-op rewrite does not allocate and\n * downstream passes can detect \"nothing changed\" by identity. Comparison is shallow,\n * so a structurally equal but newly allocated array or object counts as a change.\n *\n * @example\n * ```ts\n * update(node, { name: node.name }) // -> same `node` reference\n * update(node, { name: 'renamed' }) // -> new node, `name` replaced\n * ```\n */\nexport function update<T extends Node>(node: T, changes: Partial<T>): T {\n for (const key in changes) {\n if (changes[key] !== node[key as keyof T]) {\n return { ...node, ...changes }\n }\n }\n\n return node\n}\n","export { schemaTypes } from './constants.ts'\nexport { isHttpOperationNode, narrowSchema } from './guards.ts'\nexport { applyMacros, composeMacros, defineMacro } from './defineMacro.ts'\nexport { defineNode } from './defineNode.ts'\nexport { optionality } from './optionality.ts'\nexport { createPrinter } from './createPrinter.ts'\nexport { collect, collectSync, transform } from './visitor.ts'\nexport { extractStringsFromNodes } from './utils/extractStringsFromNodes.ts'\nexport { isBareRef, mergeRefWithSchema, resolveRefName } from './utils/refs.ts'\nexport { collectImportedRefNames, collectSchemaRefs, collectUsedSchemaNames, findCircularSchemas, findCircularSchemasFromGraph } from './utils/schemaGraph.ts'\nexport { getSchemaLiteralValues, inferDiscriminatorPropertyName, resolveSchemaProperties } from './utils/schemaProperties.ts'\n\nexport * as factory from './factory.ts'\nexport * from './registry.ts'\nexport type * from './types.ts'\n"],"mappings":";;;;AAWA,MAAa,gBAAgB;CAC3B,SAAS;CACT,MAAM;AACR;;;;;;AAOA,MAAa,cAAc;;;;CAIzB,QAAQ;;;;CAIR,QAAQ;;;;CAIR,SAAS;;;;CAIT,QAAQ;;;;CAIR,SAAS;;;;CAIT,MAAM;;;;CAIN,KAAK;;;;CAIL,SAAS;;;;CAIT,MAAM;;;;CAIN,QAAQ;;;;CAIR,OAAO;;;;CAIP,OAAO;;;;CAIP,OAAO;;;;CAIP,cAAc;;;;CAId,MAAM;;;;CAIN,KAAK;;;;CAIL,MAAM;;;;CAIN,UAAU;;;;CAIV,MAAM;;;;CAIN,MAAM;;;;CAIN,OAAO;;;;CAIP,KAAK;;;;CAIL,MAAM;;;;CAIN,MAAM;;;;CAIN,MAAM;;;;CAIN,OAAO;AACT;;;;;;;;;;;;AClHA,SAAgB,aAA2C,MAA8B,MAAqC;CAC5H,OAAO,MAAM,SAAS,OAAQ,OAA+B;AAC/D;;;;;;;;;;;AAYA,SAAgB,oBAAoB,MAAgD;CAClF,OAAO,KAAK,aAAa,UAAW,KAAK,WAAW,KAAA,KAAa,KAAK,SAAS,KAAA;AACjF;;;;;;;ACtBA,MAAa,cAAc;CAAC;CAAS;CAAU;CAAa;CAAU;CAAY;CAAa;AAAU;;;;AAuBzG,SAAS,OAA2B,MAAgB;CAClD,QAAQ,SAA8B,MAA+B,SAAS;AAChF;;;;;;;;;;;;;;;;;;;;;;AA2DA,SAAgB,WACd,QACwB;CACxB,MAAM,EAAE,MAAM,UAAU,OAAO,UAAU,eAAe;CAExD,SAAS,OAAO,OAAsB;EACpC,MAAM,OAAO,QAAQ,MAAM,KAAK,IAAI;EAOpC,MAAM,OAAO;GADG;GAAM,GAAG;GAAU,GAAI;EACtB;EACjB,KAAK,OAAO;EACZ,OAAO;CACT;CAEA,OAAO;EAAE;EAAM;EAAQ,IAAI,OAAc,IAAI;EAAG;EAAU;CAAW;AACvE;;;;;;ACwIA,MAAa,WAAW,WAAsB,EAAE,MAAM,QAAQ,CAAC;;;;AAK/D,MAAa,UAAU,WAAqB,EAAE,MAAM,OAAO,CAAC;;;;AAK5D,MAAa,cAAc,WAAyB,EAAE,MAAM,WAAW,CAAC;;;;AAKxE,MAAa,mBAAmB,WAA8B,EAAE,MAAM,gBAAgB,CAAC;;;;AAKvF,MAAa,UAAU,WAA6B;CAAE,MAAM;CAAQ,QAAQ,WAAW,EAAE,MAAM;AAAG,CAAC;;;;AAKnG,MAAa,WAAW,WAA4B;CAAE,MAAM;CAAS,cAAc,CAAC;AAAG,CAAC;;;;AAKxF,MAAa,SAAS,WAA4B;CAAE,MAAM;CAAO,QAAQ,WAAW,EAAE,MAAM;AAAG,CAAC;;;;;;;;;;AAWhG,MAAa,cAAc,SAAS;;;;;;;;;;AAWpC,MAAa,aAAa,QAAQ;;;;;;;;;;AAWlC,MAAa,iBAAiB,YAAY;;;;;;;;;;AAW1C,MAAa,sBAAsB,iBAAiB;;;;;;;;;;AAWpD,MAAa,aAAa,QAAQ;;;;;;;;;;AAWlC,SAAgB,cAAyB;CACvC,OAAO,SAAS,OAAO;AACzB;;;;;;;;;;AAWA,MAAa,YAAY,OAAO;;;;;;ACxThC,MAAa,aAAa,WAAwB;CAChD,MAAM;CACN,UAAU,CAAC,QAAQ;AACrB,CAAC;;;;AAKD,MAAa,gBAAgB,WAAW;;;;;;;;;AC1CxC,SAAgB,wBAAwB,OAA4C;CAClF,IAAI,CAAC,OAAO,QAAQ,OAAO;CAK3B,MAAM,YAA2B,CAAC;CAElC,KAAK,MAAM,QAAQ,OAAO;EAExB,IAAI,OAAO,SAAS,UAAU;GAC5B,IAAI,MAAM,UAAU,KAAK,IAAc;GACvC;EACF;EACA,IAAI,KAAK,SAAS,UAAU,KAAK,SAAS,OAAO;GAC/C,IAAI,KAAK,OAAO,UAAU,KAAK,KAAK,KAAK;GACzC;EACF;EACA,IAAI,KAAK,SAAS,SAAS;EAE3B,MAAM,QAAuB,CAAC;EAC9B,IAAI,YAAY,QAAQ,KAAK,QAAQ,MAAM,KAAK,KAAK,MAAM;EAC3D,IAAI,cAAc,QAAQ,KAAK,UAAU,MAAM,KAAK,MAAM,QAAQ,KAAK,QAAQ,IAAI,KAAK,SAAS,KAAK,IAAI,IAAI,KAAK,QAAQ;EAC3H,IAAI,gBAAgB,QAAQ,KAAK,YAAY,MAAM,KAAK,KAAK,UAAU;EACvE,IAAI,UAAU,QAAQ,OAAO,KAAK,SAAS,UAAU,MAAM,KAAK,KAAK,IAAI;EAEzE,MAAM,SAAS,wBAAwB,KAAK,KAAK;EACjD,IAAI,QAAQ,MAAM,KAAK,MAAM;EAE7B,IAAI,MAAM,QAAQ,UAAU,KAAK,MAAM,KAAK,IAAI,CAAC;CACnD;CAEA,OAAO,UAAU,KAAK,IAAI;AAC5B;;;AChCA,MAAM,iBAAiB;;;;AAKvB,MAAM,sBAAsB;;;;;AAU5B,SAAgB,gBAAgB,MAA8B;CAC5D,OAAO,OAAO,SAAS,WAAW,OAAQ,KAAK,QAAQ,KAAK;AAC9D;;;;;AAMA,SAAS,QAAQ,MAA0B;CACzC,MAAM,UAAU,MAAM,QAAQ,KAAK,IAAI,IAAI,MAAM;CACjD,MAAM,WAAW,KAAK,aAAa,MAAM;CACzC,MAAM,UAAU,KAAK,QAAQ,OAAO,MAAM;CAC1C,MAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,KAAK,IAAI,IAAK,KAAK,QAAQ;CACxF,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,KAAK,GAAG,QAAQ,GAAG;AAC3D;;;;AAKA,SAAS,YAAsC,OAAmC;CAChF,OAAO,MACJ,KAAK,UAAU;EAAE;EAAM,KAAK,QAAQ,IAAI;CAAE,EAAE,CAAC,CAC7C,MAAM,GAAG,MAAO,EAAE,MAAM,EAAE,MAAM,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI,CAAE,CAAC,CAC5D,KAAK,EAAE,WAAW,IAAI;AAC3B;;;;;AAMA,SAAS,YAAsC,QAAgF;CAC7H,MAAM,yBAAS,IAAI,IAAmB;CAEtC,QAAQ,EAAE,MAAM,YAAY;EAC1B,MAAM,MAAM,GAAG,KAAK,KAAK,GAAG,KAAK,cAAc;EAC/C,MAAM,WAAW,OAAO,IAAI,GAAG;EAE/B,IAAI,YAAY,MAAM,QAAQ,SAAS,IAAI,GAAG;GAC5C,SAAS,OAAO,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAG,SAAS,MAAM,GAAG,KAAK,CAAC,CAAC;GACzD;EACF;EAEA,MAAM,OAAO;GAAE,GAAG;GAAM,MAAM;EAAM;EACpC,OAAO,KAAK,IAAI;EAChB,OAAO,IAAI,KAAK,IAAI;CACtB;AACF;;;;;;AAOA,SAAgB,eAAe,SAA+C;CAC5E,MAAM,uBAAO,IAAI,IAAwB;CACzC,KAAK,MAAM,UAAU,SAAS;EAE5B,MAAM,MAAM,GADI,OAAO,QAAQ,wBAAwB,OAAO,KAAK,EAC5C,GAAG,OAAO,gBAAgB,MAAM,GAAG,OAAO,cAAc;EAC/E,IAAI,CAAC,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,KAAK,MAAM;CAC1C;CACA,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC;AAC1B;;;;;;;AAQA,SAAgB,eAAe,SAA+C;CAC5E,MAAM,SAA4B,CAAC;CACnC,MAAM,QAAQ,YAAY,MAAM;CAEhC,MAAM,uBAAO,IAAI,IAAY;CAE7B,KAAK,MAAM,QAAQ,YAAY,OAAO,GAAG;EACvC,MAAM,EAAE,MAAM,MAAM,YAAY,YAAY;EAE5C,IAAI,MAAM,QAAQ,IAAI,GAAG;GACvB,IAAI,KAAK,QAAQ,MAAM;IAAE,MAAM;IAAM,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC;GAAE,CAAC;GAChE;EACF;EAEA,MAAM,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,GAAG,cAAc,MAAM,GAAG,WAAW;EACvE,IAAI,CAAC,KAAK,IAAI,GAAG,GAAG;GAClB,OAAO,KAAK,IAAI;GAChB,KAAK,IAAI,GAAG;EACd;CACF;CAEA,OAAO;AACT;;;;;;;AAQA,SAAgB,eAAe,SAA4B,SAA4B,QAAoC;CAEzH,MAAM,gBAAgB,IAAI,IAAI,QAAQ,SAAS,MAAO,MAAM,QAAQ,EAAE,IAAI,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,IAAI,IAAI,CAAC,CAAE,CAAC;CAI/G,MAAM,cAAc,UAAU,QAAQ,SAAS,sBAAsB,IAAI,IAAI,OAAO,MAAM,cAAc,CAAC,IAAI;CAI7G,MAAM,UAAU,eAAgC,CAAC,UAAU,aAAa,IAAI,UAAU,KAAK,OAAO,SAAS,UAAU,KAAK,cAAc,IAAI,UAAU;CAItJ,MAAM,iCAAiB,IAAI,IAA4B;CACvD,MAAM,oBAAoB,MAAsC;EAC9D,IAAI,OAAO,MAAM,UAAU,OAAO;EAClC,MAAM,MAAM,GAAG,EAAE,aAAa,GAAG,EAAE,QAAQ;EAC3C,IAAI,CAAC,eAAe,IAAI,GAAG,GAAG,eAAe,IAAI,KAAK,CAAC;EACvD,OAAO,eAAe,IAAI,GAAG;CAC/B;CAKA,MAAM,2CAA2B,IAAI,IAAY;CACjD,KAAK,MAAM,QAAQ,SACjB,IAAI,MAAM,QAAQ,KAAK,IAAI,KAAK,KAAK,KAAK,MAAM,SAAS,OAAO,gBAAgB,IAAI,CAAC,CAAC,GACpF,yBAAyB,IAAI,KAAK,IAAI;CAI1C,MAAM,SAA4B,CAAC;CACnC,MAAM,QAAQ,YAAY,MAAM;CAEhC,MAAM,uBAAO,IAAI,IAAY;CAE7B,KAAK,MAAM,QAAQ,YAAY,OAAO,GAAG;EACvC,IAAI,KAAK,SAAS,KAAK,MAAM;EAE7B,MAAM,EAAE,MAAM,MAAM,eAAe;EAEnC,IAAI,MAAM,QAAQ,IAAI,GAAG;GACvB,MAAM,QAAQ,CAAC,GAAG,IAAI,IAAI,KAAK,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC,QAAQ,SAAS,OAAO,gBAAgB,IAAI,CAAC,CAAC;GACrG,IAAI,MAAM,QAAQ,MAAM;IAAE,MAAM;IAAM;GAAM,CAAC;GAC7C;EACF;EAEA,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,yBAAyB,IAAI,IAAI,GAAG;EAE1D,MAAM,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,cAAc;EAC7C,IAAI,CAAC,KAAK,IAAI,GAAG,GAAG;GAClB,OAAO,KAAK,IAAI;GAChB,KAAK,IAAI,GAAG;EACd;CACF;CAEA,OAAO;AACT;;;;;;AC2EA,MAAa,YAAY,WAAuB,EAAE,MAAM,SAAS,CAAC;;;;AAKlE,MAAa,YAAY,WAAuB,EAAE,MAAM,SAAS,CAAC;;;;AAKlE,MAAa,YAAY,WAAuB,EAAE,MAAM,SAAS,CAAC;;;;;AAMlE,MAAa,UAAU,WAAqB,EAAE,MAAM,OAAO,CAAC;;;;;;;;;;AAW5D,MAAa,eAAe,UAAU;;;;;;;;;;AAWtC,MAAa,eAAe,UAAU;;;;;;;;;AAUtC,MAAa,eAAe,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CtC,SAAgB,WAA0C,OAA6C;CACrG,MAAM,UAAU,KAAK,QAAQ,MAAM,QAAQ;CAC3C,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,wBAAwB,MAAM,UAAU;CAG1D,MAAM,kBAAkB,MAAM,SAAS,SAAS,eAAe,MAAM,OAAO,IAAI,CAAC;CAGjF,MAAM,yBAA4C;EAChD,IAAI,CAAC,MAAM,SAAS,QAAQ,OAAO,CAAC;EAEpC,MAAM,cAA6B,CAAC;EACpC,MAAM,6BAAa,IAAI,IAAY;EACnC,KAAK,MAAM,QAAQ,MAAM,WAAW,CAAC,GAAG;GACtC,MAAM,YAAY,KAAK,SAAS,wBAAwB,KAAK,KAAK;GAClE,IAAI,WAAW,YAAY,KAAK,SAAS;GACzC,IAAI,KAAK,MAAM,WAAW,IAAI,KAAK,IAAI;EACzC;EACA,MAAM,SAAS,YAAY,KAAK,IAAI,KAAK,KAAA;EAIzC,OAHwB,eAAe,MAAM,SAAS,iBAAiB,MAGlD,CAAC,CAAC,SAAS,QAAQ;GACtC,IAAI,IAAI,SAAS,MAAM,MAAM,OAAO,CAAC;GACrC,IAAI,CAAC,MAAM,QAAQ,IAAI,IAAI,GACzB,OAAO,OAAO,IAAI,SAAS,YAAY,WAAW,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG;GAE7E,MAAM,OAAO,IAAI,KAAK,QAAQ,SAAS,CAAC,WAAW,IAAI,gBAAgB,IAAI,CAAC,CAAC;GAE7E,IAAI,CAAC,KAAK,QAAQ,OAAO,CAAC;GAC1B,OAAO,CAAC,KAAK,WAAW,IAAI,KAAK,SAAS,MAAM;IAAE,GAAG;IAAK,MAAM;GAAK,CAAC;EACxE,CAAC;CACH,EAAA,CAAG;CACH,MAAM,kBAAkB,MAAM,SAAS,SAAS,eAAe,MAAM,OAAO,IAAI,CAAC;CAEjF,OAAO;EACL,MAAM;EACN,GAAG;EACH,IAAI,KAAK,UAAU,MAAM,MAAM,KAAK;EACpC,MAAM,KAAK,SAAS,MAAM,UAAU,OAAO;EAC3C;EACA,SAAS;EACT,SAAS;EACT,SAAS;EACT,MAAO,MAAM,QAAQ,CAAC;CACxB;AACF;;;;;;AC1SA,MAAa,WAAW,WAAwD;CAC9E,MAAM;CAGN,QAAQ,WAAW;EAAE,SAAS,CAAC;EAAG,YAAY,CAAC;EAAG,MAAM;GAAE,eAAe,CAAC;GAAG,WAAW,CAAC;EAAE;EAAG,GAAG;CAAM;CACvG,UAAU,CAAC,WAAW,YAAY;CAClC,YAAY;AACd,CAAC;;;;;;;;;;;AAYD,SAAgB,YAAY,YAA8C,CAAC,GAAc;CACvF,OAAO,SAAS,OAAO,SAAS;AAClC;;;;;;;AC5EA,MAAa,iBAAiB,WAA4B;CACxD,MAAM;CACN,UAAU,CAAC,SAAS;AACtB,CAAC;;;;AAKD,MAAa,oBAAoB,eAAe;;;;;;;;ACuEhD,MAAa,eAAe,WAA0C;CACpE,MAAM;CACN,QAAQ,UAAU;EAChB,MAAM,EAAE,aAAa,GAAG,SAAS;EACjC,MAAM,SAAS,KAAK,WAAW,KAAA,KAAa,KAAK,SAAS,KAAA;EAE1D,OAAO;GACL,MAAM,CAAC;GACP,YAAY,CAAC;GACb,WAAW,CAAC;GACZ,GAAG;GACH,GAAI,SAAS,EAAE,UAAU,OAAgB,IAAI,CAAC;GAC9C,aAAa,cAAc,kBAAkB,WAAW,IAAI,KAAA;EAC9D;CACF;CACA,UAAU;EAAC;EAAc;EAAe;CAAW;CACnD,YAAY;AACd,CAAC;AAuBD,SAAgB,gBAAgB,OAAsC;CACpE,OAAO,aAAa,OAAO,KAAK;AAClC;;;;;;ACvIA,MAAa,YAAY,WAA0D;CACjF,MAAM;CACN,UAAU,EAAE,OAAO,CAAC,EAAE;CACtB,YAAY;AACd,CAAC;;;;;;;;;;AAWD,SAAgB,aAAa,YAA+C,CAAC,GAAe;CAC1F,OAAO,UAAU,OAAO,SAAS;AACnC;;;;;;;AC1CA,SAAgB,YAAY,QAAoB,UAA+B;CAC7E,MAAM,WAAW,OAAO,YAAY;CAEpC,OAAO;EACL,GAAG;EACH,UAAU,CAAC,YAAY,CAAC,WAAW,OAAO,KAAA;EAC1C,SAAS,CAAC,YAAY,WAAW,OAAO,KAAA;CAC1C;AACF;;;;;AAMA,SAAgB,aAAmE,OAAqC;CACtH,MAAM,WAAW,MAAM,YAAY;CAEnC,OAAO;EAAE,GAAG;EAAO;EAAU,QAAQ,YAAY,MAAM,QAAQ,QAAQ;CAAE;AAC3E;;;;;;;ACsCA,MAAa,eAAe,WAA6C;CACvE,MAAM;CACN,OAAO;CACP,UAAU,CAAC,QAAQ;CACnB,YAAY;AACd,CAAC;;;;;;;;;;;;;;AAeD,MAAa,kBAAkB,aAAa;;;;;;;ACvC5C,MAAa,cAAc,WAA2C;CACpE,MAAM;CACN,OAAO;CACP,UAAU,CAAC,QAAQ;CACnB,YAAY;AACd,CAAC;;;;;;;;;;;;;;AAeD,MAAa,iBAAiB,YAAY;;;;;;;ACuF1C,MAAa,cAAc,WAAwC;CACjE,MAAM;CACN,QAAQ,UAAU;EAChB,MAAM,EAAE,QAAQ,WAAW,YAAY,SAAS,GAAG,SAAS;EAC5D,MAAM,UAAU,YAAY,SAAS,CAAC,cAAc;GAAE,aAAa,aAAa;GAAoB;GAAQ,YAAY,cAAc;EAAK,CAAC,CAAC,IAAI,KAAA;EACjJ,OAAO;GAAE,GAAG;GAAM,SAAS;EAAQ;CACrC;CACA,UAAU,CAAC,SAAS;CACpB,YAAY;AACd,CAAC;;;;;;;;;;;;AAaD,MAAa,iBAAiB,YAAY;;;;;;;;ACse1C,MAAM,oBAA8E;CAClF,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,SAAS;CACT,MAAM;CACN,KAAK;CACL,SAAS;CACT,MAAM;CACN,OAAO;CACP,QAAQ;CACR,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACP,KAAK;CACL,UAAU;CACV,MAAM;AACR;;;;;AAMA,MAAa,YAAY,WAA0C;CACjE,MAAM;CACN,QAAQ,UAAU;EAChB,IAAI,MAAM,SAAS,UACjB,OAAO;GAAE,YAAY,CAAC;GAAG,WAAW;GAAmB,GAAG;EAAM;EAGlE,OAAO;GAAE,WAAW,kBAAkB,MAAM;GAAyC,GAAG;EAAM;CAChG;CACA,UAAU;EAAC;EAAc;EAAS;EAAW;EAAwB;EAAqB;CAAM;CAChG,YAAY;AACd,CAAC;AAmBD,SAAgB,aAAa,OAAsC;CACjE,OAAO,UAAU,OAAO,KAAK;AAC/B;;;;;;;ACjqBA,MAAa,WAAW;CACtB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;;;;;;AC3CA,MAAM,eAAe,OAAO,YAAY,SAAS,SAAS,QAAS,IAAI,WAAW,CAAC,CAAC,IAAI,MAAM,IAAI,QAAQ,CAAU,IAAI,CAAC,CAAE,CAAC;;;;;AAQ5H,MAAM,sBAAsB,OAAO,YAAY,SAAS,SAAS,QAAS,IAAI,aAAa,CAAC,CAAC,IAAI,MAAM,IAAI,UAAU,CAAU,IAAI,CAAC,CAAE,CAAC;AAqKvI,MAAM,oBAAoB;;;;AAK1B,SAAS,OAAO,OAA+B;CAC7C,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,OAAQ,MAA6B,SAAS;AACtG;;;;AAKA,SAAS,aAAa,OAAkD;CACtE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;;;;;AAMA,SAAS,UAAU,MAAY,SAAqD;CAClF,IAAI,KAAK,SAAS,YAAY,CAAC,SAAS,OAAO,KAAA;CAE/C,OAAO,kBAAkB,KAAK;AAChC;;;;;;;;;;AAWA,UAAU,YAAY,MAAY,SAAoD;CACpF,MAAM,OAAO,UAAU,MAAM,OAAO;CACpC,IAAI,CAAC,MAAM;CAEX,MAAM,SAAS;CACf,KAAK,MAAM,OAAO,MAAM;EACtB,MAAM,QAAQ,OAAO;EACrB,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,KAAK,MAAM,QAAQ,OAAO,IAAI,OAAO,IAAI,GAAG,MAAM;GAClD;EACF;EACA,IAAI,OAAO,KAAK,GAAG;GACjB,MAAM;GACN;EACF;EACA,IAAI,aAAa,KAAK,GACf;QAAA,MAAM,QAAQ,OAAO,OAAO,KAAK,GAAG,IAAI,OAAO,IAAI,GAAG,MAAM;EAAA;CAErE;AACF;;;;;;;;;;AAWA,SAAS,aAAsB,MAAY,SAAuC,QAAsD;CACtI,MAAM,MAAM,oBAAoB,KAAK;CACrC,IAAI,CAAC,KAAK,OAAO,KAAA;CAEjB,MAAM,KAAK,QAAQ;CAEnB,OAAO,KAAK,MAAM,EAAE,OAAO,CAAC;AAC9B;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,UAA0B,MAAS,SAA8B;CAC/E,MAAM,EAAE,OAAO,QAAQ,GAAG,YAAY;CAOtC,OAAO,cAAc,MAAM,UANV,SAAS,cAAc,UAAU,cAAc,MAMnB,MAAM;AACrD;;;;;;AAOA,SAAS,cAAc,MAAY,SAAkB,SAAkB,QAAgC;CAErG,OAAO,kBADS,aAAmB,MAAM,SAAS,MAAM,KAAK,MAC3B,SAAS,OAAO;AACpD;;;;;AAMA,SAAS,kBAAkB,MAAY,SAAkB,SAAwB;CAC/E,MAAM,OAAO,UAAU,MAAM,OAAO;CACpC,IAAI,CAAC,MAAM,OAAO;CAElB,MAAM,SAAS;CACf,IAAI;CAEJ,KAAK,MAAM,OAAO,MAAM;EACtB,IAAI,EAAE,OAAO,SAAS;EACtB,MAAM,QAAQ,OAAO;EACrB,IAAI,MAAM,QAAQ,KAAK,GAAG;GAIxB,IAAI;GACJ,KAAK,MAAM,CAAC,GAAG,SAAS,MAAM,QAAQ,GAAG;IACvC,MAAM,OAAO,OAAO,IAAI,IAAI,cAAc,MAAM,SAAS,SAAS,IAAI,IAAI;IAC1E,IAAI,QAAQ;KACV,OAAO,KAAK,IAAI;KAChB;IACF;IACA,IAAI,SAAS,MAAM,SAAS,CAAC,GAAG,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI;GACzD;GACA,IAAI,QAAQ,CAAC,YAAY,CAAC,EAAA,CAAG,OAAO;GACpC;EACF;EACA,IAAI,OAAO,KAAK,GAAG;GACjB,MAAM,OAAO,cAAc,OAAO,SAAS,SAAS,IAAI;GACxD,IAAI,SAAS,OAAO,CAAC,YAAY,CAAC,EAAA,CAAG,OAAO;GAC5C;EACF;EACA,IAAI,aAAa,KAAK,GAAG;GACvB,IAAI;GACJ,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,KAAK,GAAG;IAChD,MAAM,OAAO,OAAO,IAAI,IAAI,cAAc,MAAM,SAAS,SAAS,IAAI,IAAI;IAC1E,IAAI,SAAS,MAAM,CAAC,WAAW,EAAE,GAAG,MAAM,EAAA,CAAG,QAAQ;GACvD;GACA,IAAI,QAAQ,CAAC,YAAY,CAAC,EAAA,CAAG,OAAO;EACtC;CACF;CAEA,IAAI,CAAC,SAAS,OAAO;CAErB,OAAO;EADU,GAAG;EAAM,GAAG;CACjB;AACd;;;;;;;;;;;;;;;;;AAkBA,UAAiB,QAAW,MAAY,SAA2D;CACjG,MAAM,EAAE,OAAO,QAAQ,GAAG,YAAY;CAKtC,OAAO,YAAe,MAAM,UAJX,SAAS,cAAc,UAAU,cAAc,MAIlB,MAAM;AACtD;AAEA,UAAU,YAAe,MAAY,SAAuB,SAAkB,QAAyD;CACrI,MAAM,IAAI,aAAgB,MAAM,SAAS,MAAM;CAC/C,IAAI,KAAK,MAAM,MAAM;CAErB,KAAK,MAAM,SAAS,YAAY,MAAM,OAAO,GAC3C,OAAO,YAAe,OAAO,SAAS,SAAS,IAAI;AAEvD;;;;;;;;;;;;;;AAeA,SAAgB,YAAe,MAAY,SAAsC;CAC/E,OAAO,MAAM,KAAK,QAAQ,MAAM,OAAO,CAAC;AAC1C;;;;;;;AC1YA,SAAS,cAAc,SAA2B;CAChD,IAAI,YAAY,OAAO,OAAO;CAC9B,IAAI,YAAY,QAAQ,OAAO;CAC/B,OAAO;AACT;;;;;;;;;;;;;;;AAuCA,SAAgB,YAAY,OAAqB;CAC/C,OAAO;AACT;;;;;;AAgBA,SAAS,MAAM,EAAE,QAAQ,KAAK,MAAM,WAAyC;CAC3E,IAAI,UAAU;CAEd,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,WAAW,MAAM;EACvB,IAAI,CAAC,UAAU;EACf,IAAI,MAAM,SAAS,CAAC,MAAM,MAAM,OAAO,GAAG;EAE1C,MAAM,OAAO,SAAS,SAAS,OAAO;EACtC,IAAI,QAAQ,MAAM,UAAU;CAC9B;CAEA,OAAO,YAAY,OAAO,KAAA,IAAY;AACxC;;;;;;;;;;;;;AAcA,SAAgB,cAAc,QAAuC;CACnE,MAAM,UAAU,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM,cAAc,EAAE,OAAO,IAAI,cAAc,EAAE,OAAO,CAAC;CAE9F,MAAM,UAAmB,CAAC;CAC1B,KAAK,MAAM,OAAO,aAAa;EAC7B,IAAI,CAAC,QAAQ,MAAM,UAAU,OAAO,MAAM,SAAS,UAAU,GAAG;EAEhE,MAAM,YAAY,MAAY,YAA4B,MAAM;GAAE,QAAQ;GAAS;GAAK;GAAM;EAAQ,CAAC;EACtG,QAA+C,OAAO;CACzD;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;AAiBA,SAAgB,YAAgC,MAAa,QAA8B,SAA2C;CACpI,IAAI,OAAO,WAAW,GAAG,OAAO;CAEhC,OAAO,UAAU,MAAM;EAAE,GAAG,cAAc,MAAM;EAAG,GAAG;CAAQ,CAAC;AACjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACqEA,SAAgB,cAAuE,OAAkE;CACvJ,QAAQ,YAAY;EAClB,MAAM,EAAE,MAAM,SAAS,iBAAiB,OAAO,WAAW,OAAO,kBAAkB,MAAO,WAAW,CAAC,CAAkB;EACxH,MAAM,SAAS,YAAY;GAAE,GAAG;GAAO,GAAG;EAAU,IAAI;EAExD,MAAM,mBAAsC,CAAC;EAE7C,MAAM,YACH,WACA,SAAyC;GACxC,MAAM,UAAU,MAAM,KAAK;GAC3B,IAAI,CAAC,SAAS,OAAO;GAErB,OAAQ,QAA6G,KAAK,SAAS,IAAI;EACzI;EAEF,MAAM,UAA4D;GAChE,SAAS;GACT,SAAS,SAA2B;IAClC,iBAAiB,KAAK,IAAI;GAC5B;GACA,WAAW,SAAS,MAAM;GAC1B,MAAM,SAAS,KAAK;EACtB;EAEA,OAAO;GACL;GACA,SAAS;GACT,WAAW,QAAQ;GACnB,OAAQ,gBAAgB,cAAc,KAAK,OAAO,IAAI,QAAQ;GAC9D,oBAAoB,iBAAiB,OAAO,CAAC;EAC/C;CACF;AACF;;;;;;;;;;;;;;;;ACjOA,SAAgB,eAAe,MAAoD;CACjF,IAAI,CAAC,QAAQ,KAAK,SAAS,OAAO,OAAO;CACzC,IAAI,KAAK,YAAY,OAAO,KAAK;CACjC,IAAI,KAAK,KAAK,OAAO,KAAK,IAAI,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,KAAK;CAExD,OAAO,KAAK,QAAQ,KAAK,QAAQ,QAAQ;AAC3C;;;;;;;;;;;;;;;AAgBA,SAAgB,mBAAmB,MAAiC;CAClE,IAAI,CAAC,KAAK,QAAQ,OAAO;CAEzB,MAAM,EAAE,MAAM,OAAO,MAAM,OAAO,MAAM,OAAO,KAAK,MAAM,QAAQ,SAAS,GAAG,cAAc;CAC5F,MAAM,mBAAmB,OAAO,YAAY,OAAO,QAAQ,SAAS,CAAC,CAAC,QAAQ,GAAG,WAAW,UAAU,KAAA,CAAS,CAAC;CAEhH,OAAO;EAAE,GAAG,KAAK;EAAQ,GAAG;CAAiB;AAC/C;;;;;;;AAQA,SAAgB,UAAU,MAAqC,YAA4C;CACzG,IAAI,CAAC,QAAQ,KAAK,SAAS,OAAO,OAAO;CAEzC,MAAM,OAAO,mBAAmB,IAAI;CAEpC,OAAO,CAAC,KAAK,YAAY,CAAC,KAAK,YAAY,CAAC,KAAK,WAAW,KAAK,YAAY,KAAA,KAAa,CAAC,KAAK,eAAe,CAAC,KAAK,UAAU,UAAU,CAAC,YAAY;AACxJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACCA,SAAgB,QAAsB,OAA4B,SAAuD;CACvH,QAAQ,QAAsB;EAC5B,IAAI,MAAM,IAAI,GAAG,GAAG,OAAO,MAAM,IAAI,GAAG;EACxC,MAAM,QAAQ,QAAQ,GAAG;EACzB,MAAM,IAAI,KAAK,KAAK;EACpB,OAAO;CACT;AACF;;;;;;;;;;;;;;;AChDA,MAAa,oBAAoB,wBAAQ,IAAI,QAAyC,IAAI,SAA0C;CAClI,MAAM,uBAAO,IAAI,IAAY;CAC7B,YAAkB,MAAM,EACtB,OAAO,OAAO;EACZ,IAAI,MAAM,SAAS,OAAO;GACxB,MAAM,OAAO,eAAe,KAAK;GACjC,IAAI,MAAM,KAAK,IAAI,IAAI;EACzB;CACF,EACF,CAAC;CACD,OAAO;AACT,CAAC;;;;;;;;;;;;;;;;;AAkBD,MAAa,0BAA0B,wBAAQ,IAAI,QAA2C,IAAI,SAA4C;CAC5I,MAAM,uBAAO,IAAI,IAAY;CAC7B,MAAM,QAAuB,CAAC;CAC9B,YAAkB,MAAM,EACtB,OAAO,OAAO;EACZ,IAAI,MAAM,SAAS,SAAS,CAAC,MAAM,KAAK;EACxC,MAAM,OAAO,eAAe,KAAK;EACjC,IAAI,QAAQ,CAAC,KAAK,IAAI,IAAI,GAAG;GAC3B,KAAK,IAAI,IAAI;GACb,MAAM,KAAK,IAAI;EACjB;CACF,EACF,CAAC;CACD,OAAO;AACT,CAAC;;;;;;;;;;;;;;;;;;;;;AAsBD,SAAgB,uBAAuB,YAA0C,SAAiD;CAChI,MAAM,4BAAY,IAAI,IAAwB;CAC9C,KAAK,MAAM,UAAU,SACnB,IAAI,OAAO,MAAM,UAAU,IAAI,OAAO,MAAM,MAAM;CAGpD,MAAM,yBAAS,IAAI,IAAY;CAE/B,SAAS,YAAY,QAA0B;EAC7C,KAAK,MAAM,QAAQ,kBAAkB,MAAM,GACzC,IAAI,CAAC,OAAO,IAAI,IAAI,GAAG;GACrB,OAAO,IAAI,IAAI;GACf,MAAM,cAAc,UAAU,IAAI,IAAI;GACtC,IAAI,aAAa,YAAY,WAAW;EAC1C;CAEJ;CAEA,KAAK,MAAM,MAAM,YACf,KAAK,MAAM,UAAU,QAAoB,IAAI;EAAE,OAAO;EAAW,SAAS,SAAS;CAAK,CAAC,GACvF,YAAY,MAAM;CAItB,OAAO;AACT;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,6BAA6B,OAA8D;CACzG,MAAM,2BAAW,IAAI,IAAY;CACjC,KAAK,MAAM,SAAS,MAAM,KAAK,GAAG;EAChC,MAAM,0BAAU,IAAI,IAAY;EAChC,MAAM,QAAuB,CAAC,GAAI,MAAM,IAAI,KAAK,KAAK,CAAC,CAAE;EACzD,OAAO,MAAM,SAAS,GAAG;GACvB,MAAM,OAAO,MAAM,IAAI;GACvB,IAAI,SAAS,OAAO;IAClB,SAAS,IAAI,KAAK;IAClB;GACF;GACA,IAAI,QAAQ,IAAI,IAAI,GAAG;GACvB,QAAQ,IAAI,IAAI;GAEhB,MAAM,OAAO,MAAM,IAAI,IAAI;GAC3B,IAAI,MAAM,KAAK,MAAM,KAAK,MAAM,MAAM,KAAK,CAAC;EAC9C;CACF;CAEA,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,oBAAoB,SAAiD;CACnF,MAAM,wBAAQ,IAAI,IAAiC;CACnD,KAAK,MAAM,UAAU,SACnB,IAAI,OAAO,MAAM,MAAM,IAAI,OAAO,MAAM,kBAAkB,MAAM,CAAC;CAGnE,OAAO,6BAA6B,KAAK;AAC3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACrIA,SAAgB,wBAAwB,EAAE,MAAM,gBAAyF;CACvI,MAAM,aAAkC,CAAC;CACzC,MAAM,0BAAU,IAAI,QAAoB;CAExC,SAAS,MAAM,SAA8C;EAC3D,IAAI,CAAC,WAAW,QAAQ,IAAI,OAAO,GAAG;EACtC,QAAQ,IAAI,OAAO;EAEnB,IAAI,QAAQ,SAAS,UAAU;GAC7B,MAAM,WAAW,QAAQ,WAAW,MAAM,cAAc,UAAU,SAAS,YAAY;GACvF,IAAI,UAAU,WAAW,KAAK,QAAQ;GACtC;EACF;EAEA,IAAI,QAAQ,SAAS,OAAO;GAC1B,MAAM,QAAQ,MAAM;GACpB;EACF;EAEA,IAAI,QAAQ,SAAS,gBACnB,KAAK,MAAM,UAAU,QAAQ,WAAW,CAAC,GAAG,MAAM,MAAM;CAE5D;CAEA,MAAM,IAAI;CACV,OAAO;AACT;;;;;;;;;;;;;AAcA,SAAgB,uBAAuB,MAAmE;CACxG,MAAM,yBAAS,IAAI,IAAsC;CACzD,MAAM,0BAAU,IAAI,QAAoB;CAExC,SAAS,MAAM,SAA8C;EAC3D,IAAI,CAAC,WAAW,QAAQ,IAAI,OAAO,GAAG;EACtC,QAAQ,IAAI,OAAO;EAEnB,IAAI,QAAQ,SAAS,QAAQ;GAC3B,MAAM,aAAa,QAAQ,iBAAiB,KAAK,EAAE,YAAY,KAAK,KAAK,QAAQ,cAAc,CAAC;GAChG,KAAK,MAAM,SAAS,YAAY,OAAO,IAAI,KAAK;GAChD;EACF;EAEA,IAAI,QAAQ,SAAS,OAAO;GAC1B,MAAM,QAAQ,MAAM;GACpB;EACF;EAEA,IAAI,QAAQ,SAAS,SACnB,KAAK,MAAM,UAAU,QAAQ,WAAW,CAAC,GAAG,MAAM,MAAM;CAE5D;CAEA,MAAM,IAAI;CACV,OAAO,CAAC,GAAG,MAAM;AACnB;AAGA,SAAS,qBAAqB,MAAkB,0BAA+B,IAAI,QAAQ,GAAgB;CACzG,IAAI,QAAQ,IAAI,IAAI,GAAG,uBAAO,IAAI,IAAI;CACtC,QAAQ,IAAI,IAAI;CAEhB,IAAI,KAAK,SAAS,UAAU,OAAO,IAAI,IAAI,KAAK,WAAW,KAAK,aAAa,SAAS,IAAI,CAAC;CAC3F,IAAI,KAAK,SAAS,OAAO,OAAO,KAAK,SAAS,qBAAqB,KAAK,QAAQ,OAAO,oBAAI,IAAI,IAAI;CAEnG,IAAI,KAAK,SAAS,gBAAgB;EAChC,MAAM,wBAAQ,IAAI,IAAY;EAC9B,KAAK,MAAM,UAAU,KAAK,WAAW,CAAC,GACpC,KAAK,MAAM,QAAQ,qBAAqB,QAAQ,OAAO,GAAG,MAAM,IAAI,IAAI;EAE1E,OAAO;CACT;CAEA,uBAAO,IAAI,IAAI;AACjB;;;;;AAMA,SAAgB,+BAA+B,SAAwD;CACrG,IAAI,QAAQ,SAAS,GAAG,OAAO,KAAA;CAE/B,IAAI;CACJ,KAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,QAAQ,qBAAqB,MAAM;EACzC,aAAa,aAAa,IAAI,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC,QAAQ,SAAS,MAAM,IAAI,IAAI,CAAC,CAAC,IAAI;CACzF;CAEA,KAAK,MAAM,QAAQ,cAAc,CAAC,GAAG;EACnC,MAAM,SAAS,QAAQ,KAAK,WAAW;GACrC,MAAM,WAAW,IAAI,IAAI,wBAAwB;IAAE,MAAM;IAAQ,cAAc;GAAK,CAAC,CAAC,CAAC,SAAS,aAAa,uBAAuB,SAAS,MAAM,CAAC,CAAC;GACrJ,OAAO,SAAS,SAAS,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,KAAK,KAAA;EAClD,CAAC;EAED,IAAI,OAAO,OAAO,UAAU,UAAU,KAAA,CAAS,KAAK,IAAI,IAAI,MAAM,CAAC,CAAC,SAAS,QAAQ,QACnF,OAAO;CAEX;AAGF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACjHA,SAAgB,OAAuB,MAAS,SAAwB;CACtE,KAAK,MAAM,OAAO,SAChB,IAAI,QAAQ,SAAS,KAAK,MACxB,OAAO;EAAE,GAAG;EAAM,GAAG;CAAQ;CAIjC,OAAO;AACT"}