@kubb/core 5.0.0-beta.65 → 5.0.0-beta.67
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.cjs +6 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +7 -8
- package/dist/index.js.map +1 -1
- package/dist/{memoryStorage-mojU6pbA.cjs → memoryStorage-67VG6jZn.cjs} +3 -4
- package/dist/memoryStorage-67VG6jZn.cjs.map +1 -0
- package/dist/{memoryStorage-DWnhqUf2.js → memoryStorage-D0gb5tRV.js} +3 -3
- package/dist/memoryStorage-D0gb5tRV.js.map +1 -0
- package/dist/mocks.cjs +1 -1
- package/dist/mocks.js +1 -1
- package/package.json +4 -4
- package/dist/memoryStorage-DWnhqUf2.js.map +0 -1
- package/dist/memoryStorage-mojU6pbA.cjs.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["#reporterStorage","#macros","#composed","#memo","#invalidate","#visitorFor","#eventGeneratorPlugins","#resolvers","#defaultResolvers","#listeners","#transforms","#normalizePlugin","#registerPlugin","#adapterSource","#parseInput","#trackListener","#filesPayload","#emitPluginEnd","#runGenerators","#getDefaultResolver","#storage","#driver","logLevel","logLevelMap","process"],"sources":["../../../internals/utils/src/time.ts","../../../internals/utils/src/colors.ts","../../../internals/utils/src/runtime.ts","../../../internals/utils/src/fs.ts","../../../internals/utils/src/promise.ts","../../../internals/utils/src/reserved.ts","../../../internals/utils/src/url.ts","../src/createAdapter.ts","../package.json","../src/diagnostics.ts","../src/definePlugin.ts","../src/defineResolver.ts","../src/Transform.ts","../src/KubbDriver.ts","../src/storages/fsStorage.ts","../src/createKubb.ts","../src/createReporter.ts","../src/reporters/report.ts","../src/reporters/cliReporter.ts","../src/reporters/fileReporter.ts","../src/reporters/jsonReporter.ts","../src/createRenderer.ts","../src/defineGenerator.ts","../src/defineParser.ts"],"sourcesContent":["/**\n * Calculates elapsed time in milliseconds from a high-resolution `process.hrtime` start time.\n * Rounds to 2 decimal places for sub-millisecond precision without noise.\n *\n * @example\n * ```ts\n * const start = process.hrtime()\n * doWork()\n * getElapsedMs(start) // 42.35\n * ```\n */\nexport function getElapsedMs(hrStart: [number, number]): number {\n const [seconds, nanoseconds] = process.hrtime(hrStart)\n const ms = seconds * 1000 + nanoseconds / 1e6\n return Math.round(ms * 100) / 100\n}\n\n/**\n * Converts a millisecond duration into a human-readable string (`ms`, `s`, or `m s`).\n *\n * @example\n * ```ts\n * formatMs(250) // '250ms'\n * formatMs(1500) // '1.50s'\n * formatMs(90000) // '1m 30.0s'\n * ```\n */\nexport function formatMs(ms: number): string {\n if (ms >= 60000) {\n const mins = Math.floor(ms / 60000)\n const secs = ((ms % 60000) / 1000).toFixed(1)\n return `${mins}m ${secs}s`\n }\n\n if (ms >= 1000) {\n return `${(ms / 1000).toFixed(2)}s`\n }\n return `${Math.round(ms)}ms`\n}\n\n/**\n * Formats the elapsed time since `hrStart` as a human-readable string.\n *\n * @example\n * ```ts\n * const start = process.hrtime()\n * doWork()\n * formatHrtime(start) // '1.50s'\n * ```\n */\nexport function formatHrtime(hrStart: [number, number]): string {\n return formatMs(getElapsedMs(hrStart))\n}\n","import { hash } from 'node:crypto'\nimport { styleText } from 'node:util'\nimport { formatMs } from './time.ts'\n\n/**\n * Parsed RGB channels from a CSS hex color string.\n */\ntype RGB = { r: number; g: number; b: number }\n\n/**\n * Parses a CSS hex color string (`#RGB`) into its RGB channels.\n * Falls back to `255` for any channel that cannot be parsed.\n */\nfunction parseHex(color: string): RGB {\n const int = Number.parseInt(color.replace('#', ''), 16)\n return Number.isNaN(int) ? { r: 255, g: 255, b: 255 } : { r: (int >> 16) & 0xff, g: (int >> 8) & 0xff, b: int & 0xff }\n}\n\n/**\n * Returns a function that wraps a string in a 24-bit ANSI true-color escape sequence\n * for the given hex color.\n */\nfunction hex(color: string): (text: string) => string {\n const { r, g, b } = parseHex(color)\n return (text: string) => `\\x1b[38;2;${r};${g};${b}m${text}\\x1b[0m`\n}\n\nfunction gradient(colorStops: Array<string>, text: string): string {\n const chars = text.split('')\n return chars\n .map((char, i) => {\n const t = chars.length <= 1 ? 0 : i / (chars.length - 1)\n const seg = Math.min(Math.floor(t * (colorStops.length - 1)), colorStops.length - 2)\n const lt = t * (colorStops.length - 1) - seg\n const from = parseHex(colorStops[seg]!)\n const to = parseHex(colorStops[seg + 1]!)\n const r = Math.round(from.r + (to.r - from.r) * lt)\n const g = Math.round(from.g + (to.g - from.g) * lt)\n const b = Math.round(from.b + (to.b - from.b) * lt)\n return `\\x1b[38;2;${r};${g};${b}m${char}\\x1b[0m`\n })\n .join('')\n}\n\n/**\n * ANSI color functions for each part of the Kubb mascot illustration.\n */\nconst palette = {\n /**\n * Top cap of the skittle.\n */\n lid: hex('#F55A17'),\n /**\n * Upper wood body.\n */\n woodTop: hex('#F5A217'),\n /**\n * Middle wood body.\n */\n woodMid: hex('#F58517'),\n /**\n * Base wood body.\n */\n woodBase: hex('#B45309'),\n /**\n * Eye whites.\n */\n eye: hex('#FFFFFF'),\n /**\n * Highlight accent.\n */\n highlight: hex('#adadc6'),\n /**\n * Cheek blush.\n */\n blush: hex('#FDA4AF'),\n}\n\n/**\n * Generates the Kubb mascot welcome banner as an ANSI-colored string.\n *\n * @example\n * ```ts\n * console.log(getIntro({ title: 'kubb.config.ts', description: 'generating…', version: '5.0.0', areEyesOpen: true }))\n * ```\n */\nexport function getIntro({\n title,\n description,\n version,\n areEyesOpen,\n}: {\n /**\n * Name of the active configuration or tool being started.\n */\n title: string\n /**\n * Short subtitle shown next to the arrow prompt.\n */\n description: string\n /**\n * Kubb version string rendered in the gradient header.\n */\n version: string\n /**\n * When `false` the eyes are shown as closed dashes instead of open blocks.\n */\n areEyesOpen: boolean\n}): string {\n const kubbVersion = gradient(['#F58517', '#F5A217', '#F55A17'], `KUBB v${version}`)\n\n const eyeTop = areEyesOpen ? palette.eye('█▀█') : palette.eye('───')\n const eyeBottom = areEyesOpen ? palette.eye('▀▀▀') : palette.eye('───')\n\n return `\n ${palette.lid('▄▄▄▄▄▄▄▄▄▄▄▄▄')}\n ${palette.woodTop('█ ')}${palette.highlight('▄▄')}${palette.woodTop(' ')}${palette.highlight('▄▄')}${palette.woodTop(' █')} ${kubbVersion}\n ${palette.woodMid('█ ')}${eyeTop}${palette.woodMid(' ')}${eyeTop}${palette.woodMid(' █')} ${styleText('gray', title)}\n ${palette.woodMid('█ ')}${eyeBottom}${palette.woodMid(' ')}${palette.blush('◡')}${palette.woodMid(' ')}${eyeBottom}${palette.woodMid(' █')} ${styleText('yellow', '➜')} ${styleText('white', description)}\n ${palette.woodBase('▀▀▀▀▀▀▀▀▀▀▀▀▀')}\n`\n}\n\n/**\n * ANSI color names used by {@link randomCliColor} for deterministic terminal coloring.\n */\nconst randomColors = ['black', 'red', 'green', 'yellow', 'blue', 'white', 'magenta', 'cyan', 'gray'] as const\n\n/**\n * Wraps `text` in a deterministic ANSI color derived from the text's SHA-256 hash.\n *\n * @example\n * ```ts\n * randomCliColor('petstore') // '\\x1b[33m' + 'petstore' + '\\x1b[39m' (always the same color for 'petstore')\n * ```\n */\nexport function randomCliColor(text?: string): string {\n if (!text) return ''\n const index = hash('sha256', text, 'buffer').readUInt32BE(0) % randomColors.length\n const color = randomColors[index] ?? 'white'\n return styleText(color, text)\n}\n\n/**\n * Formats a millisecond duration with a threshold-based ANSI color.\n * `≤ 500 ms` → green · `≤ 1 000 ms` → yellow · `> 1 000 ms` → red.\n *\n * @example\n * ```ts\n * formatMsWithColor(200) // '\\x1b[32m200ms\\x1b[39m'\n * formatMsWithColor(800) // '\\x1b[33m800ms\\x1b[39m'\n * formatMsWithColor(1500) // '\\x1b[31m1.50s\\x1b[39m'\n * ```\n */\nexport function formatMsWithColor(ms: number): string {\n const formatted = formatMs(ms)\n if (ms <= 500) return styleText('green', formatted)\n if (ms <= 1000) return styleText('yellow', formatted)\n return styleText('red', formatted)\n}\n","/**\n * Name of the JavaScript runtime executing the current process.\n */\ntype RuntimeName = 'bun' | 'deno' | 'node'\n\n/**\n * Detects the JavaScript runtime executing the current process and exposes its name and version.\n *\n * Prefer the shared {@link runtime} instance over constructing your own.\n */\nclass Runtime {\n /**\n * `true` when the current process is running under Bun.\n *\n * Detection keys off the global `Bun` object rather than `process.versions`,\n * because Bun polyfills `process.versions.node` for Node compatibility and would\n * otherwise look like Node.\n *\n * @example\n * ```ts\n * if (runtime.isBun) {\n * await Bun.write(path, data)\n * }\n * ```\n */\n get isBun(): boolean {\n return typeof Bun !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Deno.\n */\n get isDeno(): boolean {\n return typeof (globalThis as { Deno?: unknown }).Deno !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Node.\n *\n * Bun and Deno are excluded first so a polyfilled `process` does not register as Node.\n */\n get isNode(): boolean {\n return !this.isBun && !this.isDeno && typeof process !== 'undefined' && process.versions?.node != null\n }\n\n /**\n * Name of the runtime executing the current process.\n *\n * @example\n * ```ts\n * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise\n * ```\n */\n get name(): RuntimeName {\n if (this.isBun) return 'bun'\n if (this.isDeno) return 'deno'\n\n return 'node'\n }\n\n /**\n * Version of the active runtime, or an empty string when it cannot be read.\n *\n * @example\n * ```ts\n * runtime.version // '1.3.11' under Bun, '22.22.2' under Node\n * ```\n */\n get version(): string {\n if (this.isBun) return process.versions.bun ?? ''\n if (this.isDeno) return (globalThis as { Deno?: { version?: { deno?: string } } }).Deno?.version?.deno ?? ''\n\n return process.versions?.node ?? ''\n }\n}\n\n/**\n * Shared {@link Runtime} instance describing the JavaScript runtime executing the current process.\n */\nexport const runtime = new Runtime()\n","import { existsSync } from 'node:fs'\nimport { access, mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { dirname, join, posix, resolve } from 'node:path'\nimport { camelCase } from './casing.ts'\nimport { runtime } from './runtime.ts'\n\n/**\n * Walks up the directory tree from `cwd` (defaults to `process.cwd()`) and\n * returns the absolute path of the nearest `package.json`, or `null` when none\n * is found before reaching the filesystem root.\n *\n * @example\n * ```ts\n * const pkgPath = findPackageJSON('/home/user/project/src') // '/home/user/project/package.json'\n * ```\n */\nexport function findPackageJSON(cwd?: string): string | null {\n let dir = cwd ? resolve(cwd) : process.cwd()\n while (true) {\n const pkgPath = join(dir, 'package.json')\n if (existsSync(pkgPath)) return pkgPath\n const parent = dirname(dir)\n if (parent === dir) return null\n dir = parent\n }\n}\n\n/**\n * Converts all backslashes to forward slashes.\n * Extended-length Windows paths (`\\\\?\\...`) are left unchanged.\n */\nfunction toSlash(p: string): string {\n if (p.startsWith('\\\\\\\\?\\\\')) return p\n\n return p.replaceAll('\\\\', '/')\n}\n\n/**\n * Returns the relative path from `rootDir` to `filePath`, always using forward slashes\n * and prefixed with `./` when not already traversing upward.\n *\n * @example\n * ```ts\n * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'\n * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'\n * ```\n */\nexport function getRelativePath(rootDir?: string | null, filePath?: string | null): string {\n if (!rootDir || !filePath) {\n throw new Error(`Root and file should be filled in when retrieving the relativePath, ${rootDir || ''} ${filePath || ''}`)\n }\n\n const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath))\n\n return relativePath.startsWith('../') ? relativePath : `./${relativePath}`\n}\n\n/**\n * Resolves to `true` when the file or directory at `path` exists.\n * Uses `Bun.file().exists()` when running under Bun, `fs.access` otherwise.\n *\n * @example\n * ```ts\n * if (await exists('./kubb.config.ts')) {\n * const content = await read('./kubb.config.ts')\n * }\n * ```\n */\nexport async function exists(path: string): Promise<boolean> {\n if (runtime.isBun) {\n return Bun.file(path).exists()\n }\n return access(path).then(\n () => true,\n () => false,\n )\n}\n\n/**\n * Reads the file at `path` as a UTF-8 string.\n * Uses `Bun.file().text()` when running under Bun, `fs.readFile` otherwise.\n *\n * @example\n * ```ts\n * const source = await read('./src/Pet.ts')\n * ```\n */\nexport async function read(path: string): Promise<string> {\n if (runtime.isBun) {\n return Bun.file(path).text()\n }\n return readFile(path, { encoding: 'utf8' })\n}\n\ntype WriteOptions = {\n /**\n * When `true`, re-reads the file immediately after writing and throws if the\n * content does not match — useful for catching write failures on unreliable file systems.\n */\n sanity?: boolean\n}\n\n/**\n * Writes `data` to `path`, trimming leading/trailing whitespace before saving.\n * Skips the write when the trimmed content is empty or identical to what is already on disk.\n * Creates any missing parent directories automatically.\n * When `sanity` is `true`, re-reads the file after writing and throws if the content does not match.\n *\n * @example\n * ```ts\n * await write('./src/Pet.ts', source) // writes and returns trimmed content\n * await write('./src/Pet.ts', source) // null — file unchanged\n * await write('./src/Pet.ts', ' ') // null — empty content skipped\n * ```\n */\nexport async function write(path: string, data: string, options: WriteOptions = {}): Promise<string | null> {\n const trimmed = data.trim()\n if (trimmed === '') return null\n\n const resolved = resolve(path)\n\n if (runtime.isBun) {\n const file = Bun.file(resolved)\n const oldContent = (await file.exists()) ? await file.text() : null\n if (oldContent === trimmed) return null\n await Bun.write(resolved, trimmed)\n return trimmed\n }\n\n try {\n const oldContent = await readFile(resolved, { encoding: 'utf-8' })\n if (oldContent === trimmed) return null\n } catch {\n /* file doesn't exist yet */\n }\n\n await mkdir(dirname(resolved), { recursive: true })\n await writeFile(resolved, trimmed, { encoding: 'utf-8' })\n\n if (options.sanity) {\n const savedData = await readFile(resolved, { encoding: 'utf-8' })\n if (savedData !== trimmed) {\n throw new Error(`Sanity check failed for ${path}\\n\\nData[${data.length}]:\\n${data}\\n\\nSaved[${savedData.length}]:\\n${savedData}\\n`)\n }\n return savedData\n }\n\n return trimmed\n}\n\n/**\n * Recursively removes `path`. Silently succeeds when `path` does not exist.\n *\n * @example\n * ```ts\n * await clean('./dist')\n * ```\n */\nexport async function clean(path: string): Promise<void> {\n return rm(path, { recursive: true, force: true })\n}\n\n/**\n * Converts a filesystem path to use POSIX (`/`) separators.\n *\n * Most of the codebase compares and composes paths as strings (prefix matching, joining for\n * import specifiers, splitting on `/`). On POSIX `path.resolve` already returns `/`-separated\n * paths, but on Windows it returns `\\`-separated paths, which breaks every such comparison.\n *\n * Routing every path that crosses a module boundary through `toPosixPath` keeps the rest of the\n * code platform-agnostic. The conversion runs unconditionally so Windows-specific behavior is\n * exercisable from POSIX CI.\n *\n * @example\n * toPosixPath('C:\\\\repo\\\\src\\\\pet.ts') // 'C:/repo/src/pet.ts'\n */\nexport function toPosixPath(filePath: string): string {\n return filePath.replaceAll('\\\\', '/')\n}\n\n/**\n * Strips the file extension from a path or file name.\n * Only removes the last `.ext` segment when the dot is not part of a directory name.\n *\n * @example\n * trimExtName('petStore.ts') // 'petStore'\n * trimExtName('/src/models/pet.ts') // '/src/models/pet'\n * trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'\n * trimExtName('noExtension') // 'noExtension'\n */\nexport function trimExtName(text: string): string {\n const dotIndex = text.lastIndexOf('.')\n if (dotIndex > 0 && !text.includes('/', dotIndex)) {\n return text.slice(0, dotIndex)\n }\n return text\n}\n\n/**\n * Builds a nested file path from a dotted name. Splits on dots that precede a letter\n * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases\n * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.\n *\n * Empty segments are dropped before joining. They arise when the name starts with a dot\n * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to\n * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an\n * absolute path, letting generated files escape the configured output directory.\n *\n * @example Nested path from a dotted name\n * `toFilePath('pet.petId') // 'pet/petId'`\n *\n * @example PascalCase the final segment\n * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`\n *\n * @example Suffix applied to the final segment only\n * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`\n */\nexport function toFilePath(name: string, caseLast: (part: string) => string = camelCase): string {\n const parts = name.split(/\\.(?=[a-zA-Z])/)\n return parts\n .map((part, i) => (i === parts.length - 1 ? caseLast(part) : camelCase(part)))\n .filter(Boolean)\n .join('/')\n}\n","function* chunks<T>(arr: ReadonlyArray<T>, size: number): Generator<Array<T>> {\n for (let i = 0; i < arr.length; i += size) {\n yield arr.slice(i, i + size)\n }\n}\n\nexport type ForBatchesOptions = {\n /**\n * Maximum batch size handed to `process`.\n * Parallel dispatch within a batch is the caller's responsibility\n * (typically via `Promise.all(batch.map(...))`).\n */\n concurrency: number\n /**\n * Called after every batch.\n *\n * Use a cheap, idempotent callback (e.g. one that short-circuits when there\n * is nothing new to do). The helper does not coalesce calls — if you need\n * throttling, do it inside `flush` itself.\n */\n flush?: () => Promise<void>\n}\n\n/**\n * Slices `source` into batches of `concurrency` items and awaits `process` for each batch.\n * Accepts both plain arrays (sync) and `AsyncIterable` (streaming).\n *\n * `process` controls whether items inside a batch run in parallel; this helper only\n * controls batch size and per-batch flushing.\n *\n * @example\n * ```ts\n * // parallel dispatch inside each batch\n * await forBatches(schemas, (batch) => Promise.all(batch.map(process)), { concurrency: 8 })\n *\n * // async iterable with a flush after every batch\n * await forBatches(stream.schemas, (batch) => dispatch(batch), { concurrency: 8, flush })\n * ```\n */\nexport async function forBatches<T>(\n source: ReadonlyArray<T> | AsyncIterable<T>,\n process: (batch: Array<T>) => Promise<unknown>,\n options: ForBatchesOptions,\n): Promise<void> {\n const { concurrency, flush } = options\n\n if (Array.isArray(source)) {\n for (const batch of chunks(source, concurrency)) {\n await process(batch)\n if (flush) await flush()\n }\n return\n }\n\n const batch: Array<T> = []\n for await (const item of source) {\n batch.push(item)\n if (batch.length >= concurrency) {\n await process(batch.splice(0))\n\n if (flush) await flush()\n }\n }\n if (batch.length > 0) {\n await process(batch.splice(0))\n\n if (flush) await flush()\n }\n}\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\n/**\n * Container that switches between an eager `Array<T>` and a lazy `AsyncIterable<T>`.\n *\n * `Array<T>` by default. With `Stream` set to `true` it becomes `AsyncIterable<T>`, so large\n * collections can be produced lazily without holding every item in memory. Pairs with\n * {@link arrayToAsyncIterable}, which lifts a plain array into the streaming form.\n *\n * @example\n * ```ts\n * type Eager = Streamable<number> // Array<number>\n * type Lazy = Streamable<number, true> // AsyncIterable<number>\n * ```\n */\nexport type Streamable<T, Stream extends boolean = false> = Stream extends true ? AsyncIterable<T> : Array<T>\n\n/**\n * Wraps a plain array in a reusable `AsyncIterable`.\n * Each `[Symbol.asyncIterator]()` call returns a fresh generator so the\n * iterable can be consumed multiple times (e.g. once per plugin pre-scan).\n *\n * @example\n * ```ts\n * const stream = arrayToAsyncIterable([1, 2, 3])\n * for await (const n of stream) console.log(n) // 1, 2, 3\n * ```\n */\nexport function arrayToAsyncIterable<T>(arr: ReadonlyArray<T>): AsyncIterable<T> {\n return {\n [Symbol.asyncIterator]() {\n return (async function* () {\n yield* arr\n })()\n },\n }\n}\n","/**\n * JavaScript and Java reserved words.\n * @link https://github.com/jonschlinkert/reserved/blob/master/index.js\n */\nconst reservedWords = new Set([\n 'abstract',\n 'arguments',\n 'boolean',\n 'break',\n 'byte',\n 'case',\n 'catch',\n 'char',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'double',\n 'else',\n 'enum',\n 'eval',\n 'export',\n 'extends',\n 'false',\n 'final',\n 'finally',\n 'float',\n 'for',\n 'function',\n 'goto',\n 'if',\n 'implements',\n 'import',\n 'in',\n 'instanceof',\n 'int',\n 'interface',\n 'let',\n 'long',\n 'native',\n 'new',\n 'null',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'return',\n 'short',\n 'static',\n 'super',\n 'switch',\n 'synchronized',\n 'this',\n 'throw',\n 'throws',\n 'transient',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'volatile',\n 'while',\n 'with',\n 'yield',\n 'Array',\n 'Date',\n 'hasOwnProperty',\n 'Infinity',\n 'isFinite',\n 'isNaN',\n 'isPrototypeOf',\n 'length',\n 'Math',\n 'name',\n 'NaN',\n 'Number',\n 'Object',\n 'prototype',\n 'String',\n 'toString',\n 'undefined',\n 'valueOf',\n] as const)\n\n/**\n * Prefixes `word` with `_` when it is a reserved JavaScript/Java identifier or starts with a digit.\n *\n * @example\n * ```ts\n * transformReservedWord('class') // '_class'\n * transformReservedWord('42foo') // '_42foo'\n * transformReservedWord('status') // 'status'\n * ```\n */\nexport function transformReservedWord(word: string): string {\n const firstChar = word.charCodeAt(0)\n if (word && (reservedWords.has(word as 'valueOf') || (firstChar >= 48 && firstChar <= 57))) {\n return `_${word}`\n }\n return word\n}\n\n/**\n * Returns `true` when `name` is a syntactically valid JavaScript variable name.\n *\n * @example\n * ```ts\n * isValidVarName('status') // true\n * isValidVarName('class') // false (reserved word)\n * isValidVarName('42foo') // false (starts with digit)\n * ```\n */\nexport function isValidVarName(name: string): boolean {\n if (!name || reservedWords.has(name as 'valueOf')) {\n return false\n }\n return isIdentifier(name)\n}\n\n/**\n * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.\n *\n * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys\n * even though they are not valid variable names, so use this (not {@link isValidVarName}) when\n * deciding whether an object key needs quoting.\n *\n * @example\n * ```ts\n * isIdentifier('name') // true\n * isIdentifier('x-total')// false\n * ```\n */\nexport function isIdentifier(name: string): boolean {\n return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)\n}\n","import { camelCase } from './casing.ts'\nimport { isValidVarName } from './reserved.ts'\n\ntype URLObject = {\n /**\n * The resolved URL string (Express-style or template literal, depending on context).\n */\n url: string\n /**\n * Extracted path parameters as a key-value map, or `null` when the path has none.\n */\n params: Record<string, string> | null\n}\n\n/**\n * Supported identifier casing strategies for path parameters.\n */\ntype PathCasing = 'camelcase'\n\ntype TemplateOptions = {\n /**\n * Literal text prepended inside the template literal, e.g. a base URL.\n */\n prefix?: string | null\n /**\n * Transform applied to each extracted parameter name before interpolation.\n */\n replacer?: (pathParam: string) => string\n /**\n * Casing strategy applied to path parameter names.\n */\n casing?: PathCasing\n}\n\ntype ObjectOptions = {\n /**\n * Controls whether the `url` is rendered as an Express path or a template literal.\n * @default 'path'\n */\n type?: 'path' | 'template'\n /**\n * Transform applied to each extracted parameter name.\n */\n replacer?: (pathParam: string) => string\n /**\n * When `true`, the result is serialized to a string expression instead of a plain object.\n */\n stringify?: boolean\n /**\n * Casing strategy applied to path parameter names.\n */\n casing?: PathCasing\n}\n\nfunction transformParam(raw: string, casing?: PathCasing): string {\n const param = isValidVarName(raw) ? raw : camelCase(raw)\n return casing === 'camelcase' ? camelCase(param) : param\n}\n\nfunction toParamsObject(\n path: string,\n { replacer, casing }: { replacer?: (pathParam: string) => string; casing?: PathCasing } = {},\n): Record<string, string> | null {\n const params: Record<string, string> = {}\n\n for (const match of path.matchAll(/\\{([^}]+)\\}/g)) {\n const param = transformParam(match[1]!, casing)\n const key = replacer ? replacer(param) : param\n params[key] = key\n }\n\n return Object.keys(params).length > 0 ? params : null\n}\n\n/**\n * Helpers for OpenAPI/Swagger paths, plus a thin wrapper over the native `URL`.\n */\nexport class Url {\n /**\n * Reports whether `url` is a parseable absolute URL. Delegates to the native `URL.canParse`.\n *\n * @example\n * Url.canParse('https://petstore.swagger.io/v2') // true\n * Url.canParse('/pet/{petId}') // false\n */\n static canParse(url: string, base?: string | URL): boolean {\n return URL.canParse(url, base)\n }\n\n /**\n * Converts an OpenAPI/Swagger path to Express-style colon syntax.\n *\n * @example\n * Url.toPath('/pet/{petId}') // '/pet/:petId'\n */\n static toPath(path: string): string {\n return path.replace(/\\{([^}]+)\\}/g, ':$1')\n }\n\n /**\n * Converts an OpenAPI/Swagger path to a TypeScript template literal string.\n * `prefix` is prepended inside the literal, `replacer` transforms each parameter name,\n * and `casing` controls parameter identifier casing.\n *\n * @example\n * Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'\n *\n * @example\n * Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'\n */\n static toTemplateString(path: string, { prefix, replacer, casing }: TemplateOptions = {}): string {\n const parts = path.split(/\\{([^}]+)\\}/)\n const result = parts\n .map((part, i) => {\n if (i % 2 === 0) return part\n const param = transformParam(part, casing)\n return `\\${${replacer ? replacer(param) : param}}`\n })\n .join('')\n\n return `\\`${prefix ?? ''}${result}\\``\n }\n\n /**\n * Returns the path and its extracted params as a structured `URLObject`, or as a stringified\n * expression when `stringify` is set.\n *\n * @example\n * Url.toObject('/pet/{petId}')\n * // { url: '/pet/:petId', params: { petId: 'petId' } }\n */\n static toObject(path: string, { type = 'path', replacer, stringify, casing }: ObjectOptions = {}): URLObject | string {\n const object: URLObject = {\n url: type === 'path' ? Url.toPath(path) : Url.toTemplateString(path, { replacer, casing }),\n params: toParamsObject(path, { replacer, casing }),\n }\n\n if (stringify) {\n if (type === 'template') {\n return JSON.stringify(object).replaceAll(\"'\", '').replaceAll(`\"`, '')\n }\n\n if (object.params) {\n return `{ url: '${object.url}', params: ${JSON.stringify(object.params).replaceAll(\"'\", '').replaceAll(`\"`, '')} }`\n }\n\n return `{ url: '${object.url}' }`\n }\n\n return object\n }\n}\n","import type { PossiblePromise } from '@internals/utils'\nimport type { ImportNode, InputNode, SchemaNode } from '@kubb/ast'\n\n/**\n * Source data handed to an adapter's `parse` function. Mirrors the config\n * input shape with paths resolved to absolute.\n *\n * - `{ type: 'path' }`: single file on disk.\n * - `{ type: 'data' }`: raw string or parsed object provided inline.\n */\nexport type AdapterSource = { type: 'path'; path: string } | { type: 'data'; data: string | unknown }\n\n/**\n * Generic parameters used by `createAdapter` and the resulting `Adapter` type.\n *\n * - `TName`: unique adapter identifier (`'oas'`, `'asyncapi'`, ...).\n * - `TOptions`: user-facing options accepted by the adapter factory.\n * - `TResolvedOptions`: options after defaults are applied.\n * - `TDocument`: type of the parsed source document.\n */\nexport type AdapterFactoryOptions<\n TName extends string = string,\n TOptions extends object = object,\n TResolvedOptions extends object = TOptions,\n TDocument = unknown,\n> = {\n name: TName\n options: TOptions\n resolvedOptions: TResolvedOptions\n document: TDocument\n}\n\n/**\n * Converts input files or inline data into Kubb's universal AST `InputNode`.\n *\n * Adapters live between the spec format and the plugins. The built-in\n * `@kubb/adapter-oas` handles OpenAPI 2.0, 3.0, and 3.1. A custom adapter can\n * support GraphQL, gRPC, or another schema language.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { adapterOas } from '@kubb/adapter-oas'\n * import { pluginTs } from '@kubb/plugin-ts'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * adapter: adapterOas(),\n * plugins: [pluginTs()],\n * })\n * ```\n */\nexport type Adapter<TOptions extends AdapterFactoryOptions = AdapterFactoryOptions> = {\n /**\n * Human-readable adapter identifier (e.g. `'oas'`, `'asyncapi'`).\n */\n name: TOptions['name']\n /**\n * Resolved adapter options after defaults have been applied.\n */\n options: TOptions['resolvedOptions']\n /**\n * Parsed source document after the first `parse()` call. `null` before parsing.\n */\n document: TOptions['document'] | null\n /**\n * Parse the source into a universal `InputNode`.\n */\n parse: (source: AdapterSource) => PossiblePromise<InputNode>\n /**\n * Extract `ImportNode` entries for a schema tree.\n * Returns an empty array before the first `parse()` call.\n *\n * The `resolve` callback receives the collision-corrected schema name and must\n * return `{ name, path }` for the import, or `undefined` to skip it.\n */\n getImports: (node: SchemaNode, resolve: (schemaName: string) => { name: string; path: string }) => Array<ImportNode>\n /**\n * Validate the document at the given path or URL.\n */\n validate: (input: string, options?: { throwOnError?: boolean }) => Promise<void>\n /**\n * Memory-efficient streaming variant of `parse()`.\n *\n * Returns an `InputNode<true>` whose `schemas` and `operations` are `AsyncIterable`.\n * Each `for await` loop creates a fresh parse pass over the cached in-memory document.\n * No pre-built arrays are held in memory.\n */\n stream?: (source: AdapterSource) => Promise<InputNode<true>>\n}\n\ntype AdapterBuilder<T extends AdapterFactoryOptions> = (options: T['options']) => Adapter<T>\n\n/**\n * Defines a custom adapter that translates a spec format into Kubb's universal\n * AST, for example GraphQL, gRPC, or AsyncAPI. The built-in `@kubb/adapter-oas`\n * handles OpenAPI/Swagger documents.\n *\n * Adapters must return an `InputNode` from `parse`. That node is what every\n * plugin in the build consumes.\n *\n * @example\n * ```ts\n * import { createAdapter, ast, type AdapterFactoryOptions } from '@kubb/core'\n *\n * type MyAdapter = AdapterFactoryOptions<'my-adapter', { validate?: boolean }>\n *\n * export const myAdapter = createAdapter<MyAdapter>((options) => ({\n * name: 'my-adapter',\n * options,\n * document: null,\n * async parse(_source) {\n * // Convert the source (path or inline data) into an InputNode.\n * return ast.factory.createInput()\n * },\n * getImports: () => [],\n * async validate() {\n * // Throw here when the spec is invalid.\n * },\n * }))\n * ```\n */\nexport function createAdapter<T extends AdapterFactoryOptions = AdapterFactoryOptions>(build: AdapterBuilder<T>): (options?: T['options']) => Adapter<T> {\n return (options) => build(options ?? ({} as T['options']))\n}\n","","import { AsyncLocalStorage } from 'node:async_hooks'\nimport { styleText } from 'node:util'\nimport type { AsyncEventEmitter } from '@internals/utils'\nimport { getErrorMessage } from '@internals/utils'\nimport { version } from '../package.json'\nimport { type DiagnosticCode, diagnosticCode } from './constants.ts'\nimport type { KubbHooks } from './types.ts'\n\n/**\n * Docs major version, derived from the package version so the link tracks the published major.\n */\nconst docsMajor = version.split('.')[0] ?? '5'\n\n/**\n * How serious a diagnostic is. `error` fails the build, `warning` and `info`\n * are reported but do not.\n */\nexport type DiagnosticSeverity = 'error' | 'warning' | 'info'\n\n/**\n * A human-readable explanation of a diagnostic code: a short title, what triggers it, and how\n * to resolve it. This is the source of truth the kubb.dev `/diagnostics/<slug>` pages mirror, so\n * every code stays documented in one place. Adding a code without documenting it fails the build.\n */\nexport type DiagnosticDoc = {\n /**\n * Short title shown as the docs heading.\n */\n title: string\n /**\n * What triggers the diagnostic.\n */\n cause: string\n /**\n * The action that resolves it.\n */\n fix: string\n}\n\n/**\n * Points a diagnostic back into the source document. Inputs are parsed into an\n * object model with no line/column, so locations carry a JSON pointer the adapter\n * builds (the OAS adapter emits `#/components/schemas/Pet`). A `config` diagnostic\n * points at the Kubb config itself and so has no pointer.\n */\nexport type DiagnosticLocation =\n | {\n kind: 'schema'\n /**\n * RFC 6901 JSON pointer into the source document.\n */\n pointer: string\n /**\n * The original reference when the diagnostic stems from an unresolved one.\n */\n ref?: string\n }\n | {\n kind: 'operation' | 'document'\n /**\n * RFC 6901 JSON pointer into the source document.\n */\n pointer: string\n }\n | {\n kind: 'config'\n }\n\n/**\n * What a diagnostic carries.\n * - `problem` is a build issue shown to the user, and the only kind rendered as a problem.\n * - `performance` records a plugin's elapsed time.\n * - `update` is a version notice.\n */\nexport type DiagnosticKind = 'problem' | 'performance' | 'update'\n\n/**\n * Codes that describe a build problem: every {@link DiagnosticCode} except the\n * `performance` and `updateAvailable` codes, which ride on their own variants.\n */\nexport type ProblemCode = Exclude<DiagnosticCode, typeof diagnosticCode.performance | typeof diagnosticCode.updateAvailable>\n\n/**\n * A build problem collected during a run, gathered into the result instead of\n * aborting on the first failure.\n */\nexport type ProblemDiagnostic = {\n /**\n * @default 'problem'\n */\n kind?: 'problem'\n /**\n * Stable identifier for the problem, from the {@link diagnosticCode} catalog.\n */\n code: ProblemCode\n severity: DiagnosticSeverity\n message: string\n location?: DiagnosticLocation\n /**\n * A suggested fix, phrased as an action the user can take.\n */\n help?: string\n /**\n * Name of the plugin or subsystem that produced the diagnostic.\n */\n plugin?: string\n /**\n * The underlying error, when the diagnostic wraps a thrown one.\n */\n cause?: Error\n}\n\n/**\n * A per-plugin performance record, built with {@link Diagnostics.performance}. The `performance`\n * kind keeps it out of the problem list. It feeds the per-plugin timing bars, and reporters sum\n * these into the run total.\n */\nexport type PerformanceDiagnostic = {\n kind: 'performance'\n code: typeof diagnosticCode.performance\n severity: 'info'\n message: string\n /**\n * The plugin this measurement belongs to.\n */\n plugin: string\n /**\n * Elapsed milliseconds.\n */\n duration: number\n}\n\n/**\n * A notice that a newer Kubb version is available on npm, built with {@link Diagnostics.update}.\n * It renders like any info diagnostic.\n */\nexport type UpdateDiagnostic = {\n kind: 'update'\n code: typeof diagnosticCode.updateAvailable\n severity: 'info'\n message: string\n /**\n * The running Kubb version.\n */\n currentVersion: string\n /**\n * The newest version published on npm.\n */\n latestVersion: string\n}\n\n/**\n * A structured record collected during a build, discriminated on `kind`: a\n * {@link ProblemDiagnostic} for an issue, a {@link PerformanceDiagnostic} for a per-plugin\n * timing, or an {@link UpdateDiagnostic} for a version notice.\n */\nexport type Diagnostic = ProblemDiagnostic | PerformanceDiagnostic | UpdateDiagnostic\n\n/**\n * Maps each {@link DiagnosticCode} to the variant it selects, for {@link narrow}.\n * Every {@link ProblemCode} selects a {@link ProblemDiagnostic}, and the two bookkeeping codes\n * select their own variant.\n */\nexport type DiagnosticByCode = Record<ProblemCode, ProblemDiagnostic> &\n Record<typeof diagnosticCode.performance, PerformanceDiagnostic> &\n Record<typeof diagnosticCode.updateAvailable, UpdateDiagnostic>\n\n/**\n * Narrows a {@link Diagnostic} to the variant for `code`, or `null` when it does not match.\n *\n * @example\n * ```ts\n * const update = narrow(diagnostic, diagnosticCode.updateAvailable)\n * if (update) {\n * console.log(update.latestVersion)\n * }\n * ```\n */\nfunction narrow<C extends DiagnosticCode>(diagnostic: Diagnostic, code: C): DiagnosticByCode[C] | null {\n return diagnostic.code === code ? (diagnostic as DiagnosticByCode[C]) : null\n}\n\n/**\n * Builds a type guard that narrows a {@link Diagnostic} to the variant for `kind`. A diagnostic\n * with no `kind` is treated as a `problem`.\n */\nfunction isKind<T extends Diagnostic>(kind: DiagnosticKind) {\n return (diagnostic: Diagnostic): diagnostic is T => (diagnostic.kind ?? 'problem') === kind\n}\n\n/**\n * Returns `true` when the diagnostic is a build {@link ProblemDiagnostic}.\n *\n * @example\n * ```ts\n * if (isProblem(diagnostic)) {\n * console.log(diagnostic.location)\n * }\n * ```\n */\nconst isProblem = isKind<ProblemDiagnostic>('problem')\n\n/**\n * Returns `true` when the diagnostic is a per-plugin {@link PerformanceDiagnostic}.\n *\n * @example\n * ```ts\n * const timings = diagnostics.filter(isPerformance)\n * ```\n */\nconst isPerformance = isKind<PerformanceDiagnostic>('performance')\n\n/**\n * Returns `true` when the diagnostic is a version-update {@link UpdateDiagnostic}.\n *\n * @example\n * ```ts\n * if (isUpdate(diagnostic)) {\n * console.log(diagnostic.latestVersion)\n * }\n * ```\n */\nconst isUpdate = isKind<UpdateDiagnostic>('update')\n\n/**\n * Accent color per severity. The color tints the `[CODE]` tag (red error, yellow warning,\n * blue info).\n */\nconst severityStyle: Record<DiagnosticSeverity, { color: 'red' | 'yellow' | 'blue' }> = {\n error: { color: 'red' },\n warning: { color: 'yellow' },\n info: { color: 'blue' },\n}\n\n/**\n * A {@link Diagnostic} reduced to its JSON-safe fields plus a `docsUrl`, for\n * machine-readable output (the `--reporter json` report, the MCP tools). Drops the\n * non-serializable `cause` and the `kind`/`duration` bookkeeping.\n */\nexport type SerializedDiagnostic = {\n code: DiagnosticCode\n severity: DiagnosticSeverity\n message: string\n location?: DiagnosticLocation\n help?: string\n plugin?: string\n /**\n * The kubb.dev docs link for the code, omitted for the unknown fallback.\n */\n docsUrl?: string\n}\n\n/**\n * Explanation for every {@link diagnosticCode}. Use {@link Diagnostics.explain} to look one up\n * and `Diagnostics.docsUrl` for the matching kubb.dev page.\n */\nconst diagnosticCatalog: Record<DiagnosticCode, DiagnosticDoc> = {\n [diagnosticCode.unknown]: {\n title: 'Unknown error',\n cause: 'An error was thrown without a stable Kubb code, so it is reported as-is.',\n fix: 'Read the underlying message and stack. If it comes from a plugin or adapter, check its configuration; otherwise report it as a possible Kubb bug.',\n },\n [diagnosticCode.inputNotFound]: {\n title: 'Input not found',\n cause: 'The file or URL set in `input.path` (or passed as `kubb generate PATH`) could not be read.',\n fix: 'Check that the path or URL exists and is readable, then set it in `input.path` or pass it on the CLI.',\n },\n [diagnosticCode.inputRequired]: {\n title: 'Input required',\n cause: 'An adapter is configured but no `input` was provided.',\n fix: 'Set `input.path` (a file or URL) or `input.data` (an inline spec) in your Kubb config.',\n },\n [diagnosticCode.refNotFound]: {\n title: 'Reference not found',\n cause: 'A `$ref` could not be resolved in the source document.',\n fix: 'Add the missing definition (for example under `components.schemas`) or fix the `$ref`. Run `kubb validate` to check the spec.',\n },\n [diagnosticCode.invalidServerVariable]: {\n title: 'Invalid server variable',\n cause: 'A server variable value is not allowed by its `enum`.',\n fix: 'Use one of the values listed in the server variable `enum`, or update the spec.',\n },\n [diagnosticCode.pluginNotFound]: {\n title: 'Plugin not found',\n cause: 'A plugin that another plugin depends on is missing from the config.',\n fix: 'Add the required plugin to the `plugins` array in kubb.config.ts, or remove the dependency on it.',\n },\n [diagnosticCode.pluginFailed]: {\n title: 'Plugin failed',\n cause: 'A plugin threw while generating, or reported an error through `ctx.error`.',\n fix: 'Read the underlying error and check the plugin options and the schema or operation it failed on.',\n },\n [diagnosticCode.pluginWarning]: {\n title: 'Plugin warning',\n cause: 'A plugin reported a non-fatal warning through `ctx.warn`.',\n fix: 'Review the message. It does not fail the build; adjust the plugin options or input if the warning is unwanted.',\n },\n [diagnosticCode.pluginInfo]: {\n title: 'Plugin info',\n cause: 'A plugin reported an informational message through `ctx.info`.',\n fix: 'Informational only. No action is required.',\n },\n [diagnosticCode.unsupportedFormat]: {\n title: 'Unsupported format',\n cause: 'A schema uses a `format` Kubb does not map to a specific type, so it falls back to the base type.',\n fix: 'Use a format Kubb supports, or handle the custom format with a parser or plugin.',\n },\n [diagnosticCode.deprecated]: {\n title: 'Deprecated',\n cause: 'A referenced schema or operation is marked `deprecated`.',\n fix: 'Migrate off the deprecated definition if the warning is unwanted.',\n },\n [diagnosticCode.adapterRequired]: {\n title: 'Adapter required',\n cause: 'An action needs an adapter but none is configured.',\n fix: 'Set `adapter` in kubb.config.ts, for example `adapterOas()`.',\n },\n [diagnosticCode.pathTraversal]: {\n title: 'Path traversal',\n cause: 'A resolved output path escaped the output directory, which can stem from a path traversal in the spec or a misconfigured `group.name`.',\n fix: 'Keep generated paths within the output directory. Review the `group.name` function and the names coming from the spec.',\n },\n [diagnosticCode.invalidPluginOptions]: {\n title: 'Invalid plugin options',\n cause: \"A plugin was configured with options that cannot be honored, for example `output.mode: 'file'` paired with a `group` option.\",\n fix: \"Fix the plugin options. A single-file output has nothing to group, so remove the `group` option or use `output.mode: 'directory'`.\",\n },\n [diagnosticCode.hookFailed]: {\n title: 'Hook failed',\n cause: 'A post-generate shell hook (`hooks.done`) exited with a non-zero status.',\n fix: 'Check the command is installed and correct, and run it manually to see the error.',\n },\n [diagnosticCode.formatFailed]: {\n title: 'Format failed',\n cause: 'The formatter pass over the generated files failed.',\n fix: 'Check the formatter (oxfmt, biome, or prettier) is installed and its config is valid, then run it manually on the output.',\n },\n [diagnosticCode.lintFailed]: {\n title: 'Lint failed',\n cause: 'The linter pass over the generated files failed.',\n fix: 'Check the linter (oxlint, biome, or eslint) is installed and its config is valid, then run it manually on the output.',\n },\n [diagnosticCode.performance]: {\n title: 'Performance',\n cause: 'Not a failure. Records a plugin’s elapsed time, summed into the run total.',\n fix: 'No action. This is an informational metric.',\n },\n [diagnosticCode.updateAvailable]: {\n title: 'Update available',\n cause: 'A newer Kubb version is published on npm than the one running.',\n fix: 'Update the `@kubb/*` packages, for example `npm install -g @kubb/cli`, to get the latest fixes.',\n },\n}\n\n/**\n * Static helpers for working with {@link Diagnostic}s, plus the run-scoped sink\n * that lets deep code report a diagnostic without threading a callback.\n *\n * The sink lives in a single `AsyncLocalStorage` in the `@kubb/core` bundle.\n * `Diagnostics.scope` activates it for a run, so anything inside that run (the\n * adapter parse, a lazily consumed stream, a generator) reports through\n * `Diagnostics.report` and lands in the same run.\n */\nexport class Diagnostics {\n static #reporterStorage = new AsyncLocalStorage<(diagnostic: Diagnostic) => void>()\n\n /**\n * The diagnostic code catalog, exposed as `Diagnostics.code` (e.g. `Diagnostics.code.refNotFound`).\n */\n static code = diagnosticCode\n\n /**\n * Type guard for a build {@link ProblemDiagnostic}.\n */\n static isProblem = isProblem\n\n /**\n * Type guard for a version-update {@link UpdateDiagnostic}.\n */\n static isUpdate = isUpdate\n\n /**\n * Type guard for a per-plugin {@link PerformanceDiagnostic}.\n */\n static isPerformance = isPerformance\n\n /**\n * Narrows a {@link Diagnostic} to the variant for `code`, or `null` when it does not match.\n */\n static narrow = narrow\n\n /**\n * An `Error` that carries a {@link Diagnostic}, so structured problems can flow\n * through the existing throw/catch paths while keeping their code and location.\n *\n * @example\n * ```ts\n * throw new Diagnostics.Error({ code: diagnosticCode.refNotFound, severity: 'error', message: `Could not find ${ref}`, location: { kind: 'schema', pointer: ref, ref } })\n * ```\n */\n static Error = class DiagnosticError extends Error {\n diagnostic: ProblemDiagnostic\n\n constructor(diagnostic: ProblemDiagnostic) {\n super(diagnostic.message, { cause: diagnostic.cause })\n this.name = 'DiagnosticError'\n this.diagnostic = diagnostic\n }\n }\n\n /**\n * Structural check for a {@link Diagnostics.Error}, including one thrown from a duplicated\n * `@kubb/core` copy where `instanceof` fails. Matches on the `name` and a `diagnostic`\n * that carries a `code`.\n */\n static isError(error: unknown): error is InstanceType<typeof Diagnostics.Error> {\n if (error instanceof Diagnostics.Error) {\n return true\n }\n return (\n error instanceof Error &&\n error.name === 'DiagnosticError' &&\n 'diagnostic' in error &&\n typeof (error as { diagnostic?: unknown }).diagnostic === 'object' &&\n (error as { diagnostic?: Diagnostic }).diagnostic !== null &&\n typeof (error as { diagnostic?: { code?: unknown } }).diagnostic?.code === 'string'\n )\n }\n\n /**\n * Runs `fn` with `sink` as the active diagnostic sink for the whole async\n * subtree, so {@link Diagnostics.report} reaches it from anywhere inside.\n */\n static scope<T>(sink: (diagnostic: Diagnostic) => void, fn: () => T): T {\n return Diagnostics.#reporterStorage.run(sink, fn)\n }\n\n /**\n * Collects a diagnostic into the active build via the run-scoped sink, without throwing.\n * Returns `true` when a run consumed it, `false` when called outside a {@link Diagnostics.scope}\n * (so callers can fall back to throwing). Use a `warning`/`info` severity for non-fatal issues.\n * For rendering a diagnostic live on the hook bus, use {@link Diagnostics.emit} instead.\n */\n static report(diagnostic: Diagnostic): boolean {\n const sink = Diagnostics.#reporterStorage.getStore()\n if (!sink) {\n return false\n }\n sink(diagnostic)\n return true\n }\n\n /**\n * Emits a diagnostic on the run's `kubb:diagnostic` event so the loggers render it live.\n * Use it instead of calling `hooks.emit('kubb:diagnostic', ...)` directly. To collect a\n * diagnostic into the build result from deep in a run, use {@link Diagnostics.report} instead.\n */\n static async emit(hooks: AsyncEventEmitter<KubbHooks>, diagnostic: ProblemDiagnostic | UpdateDiagnostic): Promise<void> {\n await hooks.emit('kubb:diagnostic', { diagnostic })\n }\n\n /**\n * Coerces any thrown value into a {@link ProblemDiagnostic}. A {@link Diagnostics.Error}\n * keeps its structured data, and anything else becomes a `KUBB_UNKNOWN` error.\n */\n static from(error: unknown): ProblemDiagnostic {\n // The event emitter and BuildError wrap the original, so walk the cause chain to\n // recover a Diagnostics.Error thrown deeper down. `root` tracks the deepest error so\n // the unknown diagnostic reports the original message and stack, not the wrapper's.\n const seen = new Set<unknown>()\n let current: unknown = error\n let root: Error | undefined\n while (current instanceof Error && !seen.has(current)) {\n // Match structurally, not just by `instanceof`: a `Diagnostics.Error` thrown from a\n // duplicated `@kubb/core` copy (bundled into an adapter or plugin) is a different\n // class, but still carries the same `diagnostic`, so its code must survive.\n if (Diagnostics.isError(current)) {\n return current.diagnostic\n }\n seen.add(current)\n root = current\n current = current.cause\n }\n\n return {\n code: diagnosticCode.unknown,\n severity: 'error',\n message: root ? root.message : getErrorMessage(error),\n cause: root,\n }\n }\n\n /**\n * Builds a per-plugin performance record. Reporters sum these into the run total.\n */\n static performance({ plugin, duration }: { plugin: string; duration: number }): PerformanceDiagnostic {\n return {\n kind: 'performance',\n code: diagnosticCode.performance,\n severity: 'info',\n message: `${plugin} generated in ${Math.round(duration)}ms`,\n plugin,\n duration,\n }\n }\n\n /**\n * Builds the version-update notice shown when a newer Kubb is published on npm.\n */\n static update({ currentVersion, latestVersion }: { currentVersion: string; latestVersion: string }): UpdateDiagnostic {\n return {\n kind: 'update',\n code: diagnosticCode.updateAvailable,\n severity: 'info',\n message: `Update available: v${currentVersion} → v${latestVersion}. Run \\`npm install -g @kubb/cli\\` to update.`,\n currentVersion,\n latestVersion,\n }\n }\n\n /**\n * True when any diagnostic is an error, the severity that fails a build. Non-error\n * diagnostics are ignored.\n */\n static hasError(diagnostics: ReadonlyArray<Diagnostic>): boolean {\n return diagnostics.some((diagnostic) => diagnostic.severity === 'error')\n }\n\n /**\n * Names of the plugins that failed, deduped, derived from the error diagnostics\n * that carry a `plugin`.\n */\n static failedPlugins(diagnostics: ReadonlyArray<Diagnostic>): Array<string> {\n const names = new Set<string>()\n for (const diagnostic of diagnostics) {\n if (diagnostic.severity === 'error' && diagnostic.plugin) {\n names.add(diagnostic.plugin)\n }\n }\n return [...names]\n }\n\n /**\n * Counts `problem` diagnostics by severity for the run summary. `performance` and\n * `update` diagnostics are ignored.\n */\n static count(diagnostics: ReadonlyArray<Diagnostic>): { errors: number; warnings: number; infos: number } {\n let errors = 0\n let warnings = 0\n let infos = 0\n for (const diagnostic of diagnostics) {\n if (!isProblem(diagnostic)) {\n continue\n }\n if (diagnostic.severity === 'error') {\n errors += 1\n } else if (diagnostic.severity === 'warning') {\n warnings += 1\n } else {\n infos += 1\n }\n }\n return { errors, warnings, infos }\n }\n\n /**\n * Drops duplicate `problem` diagnostics that share a code, location pointer, and\n * plugin, so the same issue reported across several passes is shown once. Non-problem\n * diagnostics are always kept.\n */\n static dedupe(diagnostics: ReadonlyArray<Diagnostic>): Array<Diagnostic> {\n const seen = new Set<string>()\n const result: Array<Diagnostic> = []\n for (const diagnostic of diagnostics) {\n if (!isProblem(diagnostic)) {\n result.push(diagnostic)\n continue\n }\n const pointer = diagnostic.location && 'pointer' in diagnostic.location ? diagnostic.location.pointer : ''\n const key = `${diagnostic.code} ${pointer} ${diagnostic.plugin ?? ''}`\n if (seen.has(key)) {\n continue\n }\n seen.add(key)\n result.push(diagnostic)\n }\n return result\n }\n\n /**\n * Builds the kubb.dev docs URL for a diagnostic code, e.g.\n * `KUBB_REF_NOT_FOUND` → `https://kubb.dev/docs/5.x/reference/diagnostics/kubb-ref-not-found`.\n */\n static docsUrl(code: string): string {\n const slug = code.toLowerCase().replaceAll('_', '-')\n return `https://kubb.dev/docs/${docsMajor}.x/reference/diagnostics/${slug}`\n }\n\n /**\n * The catalog entry for a code: its title, cause, and fix. Mirrors the kubb.dev\n * `/diagnostics/<slug>` page.\n */\n static explain(code: DiagnosticCode): DiagnosticDoc {\n return diagnosticCatalog[code]\n }\n\n /**\n * Reduces a diagnostic to its JSON-safe fields plus a `docsUrl`, for machine-readable\n * consumers. The `cause`, `kind`, and `duration` are dropped, and absent optional\n * fields are omitted rather than set to `undefined`.\n */\n static serialize(diagnostic: Diagnostic): SerializedDiagnostic {\n const problem = isProblem(diagnostic) ? diagnostic : undefined\n return {\n code: diagnostic.code,\n severity: diagnostic.severity,\n message: diagnostic.message,\n ...(problem?.location ? { location: problem.location } : {}),\n ...(problem?.help ? { help: problem.help } : {}),\n ...(problem?.plugin ? { plugin: problem.plugin } : {}),\n ...(diagnostic.code === diagnosticCode.unknown ? {} : { docsUrl: Diagnostics.docsUrl(diagnostic.code) }),\n }\n }\n\n /**\n * Renders a {@link Diagnostic} for terminal output as its parts: the `headline`\n * (`[CODE] plugin: message`, with the code in the severity color) and the indented `details`\n * rows (`at:` pointer, `fix:` help, `see:` docs link).\n *\n * Hosts compose these to fit their gutter: a clack logger passes `[headline, ...details]` as the\n * message with no gutter symbol, while plain text outputs use {@link Diagnostics.formatLines}.\n */\n static format(diagnostic: Diagnostic): { headline: string; details: Array<string> } {\n const { code, severity, message } = diagnostic\n const { color } = severityStyle[severity]\n const problem = isProblem(diagnostic) ? diagnostic : undefined\n\n const tag = styleText(color, styleText('bold', `[${code}]`))\n const headline = problem?.plugin ? `${tag} ${problem.plugin}: ${message}` : `${tag}: ${message}`\n\n const details: Array<string> = []\n if (problem?.location && 'pointer' in problem.location) {\n details.push(` ${styleText('dim', 'at:')} ${styleText('cyan', problem.location.pointer)}`)\n }\n if (problem?.help) {\n details.push(` ${styleText('cyan', 'fix:')} ${problem.help}`)\n }\n if (code !== diagnosticCode.unknown) {\n details.push(` ${styleText('dim', 'see:')} ${styleText('cyan', Diagnostics.docsUrl(code))}`)\n }\n\n return { headline, details }\n }\n\n /**\n * The self-contained block form of {@link Diagnostics.format}: the `headline` followed by the\n * indented detail rows. Used where there is no gutter (plain and file output).\n */\n static formatLines(diagnostic: Diagnostic): Array<string> {\n const { headline, details } = Diagnostics.format(diagnostic)\n return [headline, ...details]\n }\n}\n","import type { Enforce, FileNode, HttpMethod, Macro, UserFileNode } from '@kubb/ast'\nimport { diagnosticCode } from './constants.ts'\nimport type { Generator } from './defineGenerator.ts'\nimport type { BannerMeta, Resolver } from './defineResolver.ts'\nimport { Diagnostics } from './diagnostics.ts'\nimport type { Config, KubbHooks } from './types.ts'\n\n/**\n * Reads a type from a registry, falling back to `{}` when the key is absent. Lets\n * `Kubb.ConfigOptionsRegistry` and `Kubb.PluginOptionsRegistry` be augmented without\n * touching core.\n *\n * @internal\n */\ntype ExtractRegistryKey<T, K extends PropertyKey> = K extends keyof T ? T[K] : {}\n\n/**\n * How a plugin consolidates its generated code into files.\n * - `'directory'` writes one file per operation or schema under `path`.\n * - `'file'` writes everything into a single file.\n */\nexport type OutputMode = 'directory' | 'file'\n\n/**\n * Output configuration shared by every plugin. Each plugin extends this with\n * its own keys via the `Kubb.PluginOptionsRegistry.output` interface merge.\n */\nexport type Output<_TOptions = unknown> = {\n /**\n * Directory where the plugin writes its generated code, resolved against the global\n * `output.path` set on `defineConfig`. With `mode: 'file'`, this is the full output file\n * path and must include the extension (e.g. `'types.ts'`, `'models.py'`).\n */\n path: string\n /**\n * How generated code is consolidated into files.\n * - `'directory'` writes one file per operation or schema under `path`.\n * - `'file'` writes everything into a single file. The `path` must include the file extension.\n *\n * @default 'directory'\n */\n mode?: OutputMode\n /**\n * Text prepended to every generated file. Useful for license headers,\n * lint disables, or `@ts-nocheck` directives.\n *\n * A string is applied to every file (including barrel and aggregation re-export files).\n * Pass a function to compute the banner from the file's `BannerMeta` document metadata\n * plus per-file context (`isBarrel`, `isAggregation`, `filePath`, `baseName`), so you can\n * skip the banner on specific files.\n *\n * @example Add a directive to source files but not re-export files\n * `banner: (meta) => (meta.isBarrel || meta.isAggregation) ? '' : \"'use server'\"`\n */\n banner?: string | ((meta: BannerMeta) => string)\n /**\n * Text appended at the end of every generated file. Mirror of `banner`.\n * Pass a function to compute the footer from the file's `BannerMeta`.\n */\n footer?: string | ((meta: BannerMeta) => string)\n /**\n * Allows the plugin to overwrite hand-written files at the same path.\n * Defaults to `false` to protect manual edits.\n *\n * @default false\n */\n override?: boolean\n} & ExtractRegistryKey<Kubb.PluginOptionsRegistry, 'output'>\n\n/**\n * Groups generated files into subdirectories based on an OpenAPI tag or path\n * segment.\n */\nexport type Group = {\n /**\n * Property used to assign each operation to a group.\n * - `'tag'` uses the first tag (`operation.getTags().at(0)?.name`).\n * - `'path'` uses the first segment of the operation's URL.\n */\n type: 'tag' | 'path'\n /**\n * Returns the subdirectory name from the group key. Defaults to the camelCased tag for\n * `tag` groups, or the camelCased first path segment for `path` groups.\n */\n name?: (context: { group: string }) => string\n}\n\n/**\n * Couples `output.mode` with the plugin's `group` option at the type level.\n * - `mode: 'file'` forbids `group` (a single file has nothing to group).\n * - `mode: 'directory'` (or no mode) allows an optional `group` to organize\n * files into per-group subdirectories.\n *\n * Intersect into a plugin's `Options` type instead of declaring `output` and\n * `group` directly, since `mode` lives inside `output` while `group` is its sibling.\n * The generic keeps a plugin's extended `Output` shape intact.\n *\n * @example\n * ```ts\n * export type Options = OutputOptions & {\n * exclude?: Array<Exclude>\n * }\n * ```\n */\nexport type OutputOptions<TOutput extends Output = Output> =\n | {\n output?: TOutput & { mode?: 'directory' }\n group?: Group\n }\n | {\n output: TOutput & { mode: 'file' }\n group?: never\n }\n\n/**\n * Merges the `output.mode` default into the output config and validates the combination.\n * Throws `KUBB_INVALID_PLUGIN_OPTIONS` when `mode: 'file'` is paired with a `group` option,\n * since a single-file output has nothing to group.\n */\nexport function normalizeOutput({ output, group, pluginName }: { output: Output; group?: Group | null; pluginName: string }): Output {\n const mode = output.mode ?? 'directory'\n\n if (mode === 'file' && group) {\n throw new Diagnostics.Error({\n code: diagnosticCode.invalidPluginOptions,\n severity: 'error',\n message: `Plugin \"${pluginName}\" sets \\`output.mode: 'file'\\` but also configures a \\`group\\` option.`,\n help: \"A single-file output has nothing to group. Remove the `group` option, or use `output.mode: 'directory'` to organize files into subdirectories.\",\n location: { kind: 'config' },\n plugin: pluginName,\n })\n }\n\n return { ...output, mode }\n}\n\ntype ByTag = {\n /**\n * Filter by OpenAPI `tags` field. Matches one or more tags assigned to operations.\n */\n type: 'tag'\n /**\n * Tag name to match (case-sensitive). Can be a literal string or regex pattern.\n */\n pattern: string | RegExp\n}\n\ntype ByOperationId = {\n /**\n * Filter by OpenAPI `operationId` field. Each operation (GET, POST, etc.) has a unique identifier.\n */\n type: 'operationId'\n /**\n * Operation ID to match (case-sensitive). Can be a literal string or regex pattern.\n */\n pattern: string | RegExp\n}\n\ntype ByPath = {\n /**\n * Filter by OpenAPI `path` (URL endpoint). Useful to group or filter by service segments like `/pets`, `/users`, etc.\n */\n type: 'path'\n /**\n * URL path to match (case-sensitive). Can be a literal string or regex pattern. Matches against the full path.\n */\n pattern: string | RegExp\n}\n\ntype ByMethod = {\n /**\n * Filter by HTTP method: `'GET'`, `'POST'`, `'PUT'`, `'PATCH'`, `'DELETE'`, `'HEAD'`, `'OPTIONS'`, `'TRACE'`.\n */\n type: 'method'\n /**\n * HTTP method to match, as one of the `HttpMethod` values (`'GET'`, `'POST'`, `'PUT'`,\n * `'PATCH'`, `'DELETE'`, `'HEAD'`, `'OPTIONS'`, `'TRACE'`) or a regex.\n */\n pattern: HttpMethod | RegExp\n}\n\ntype BySchemaName = {\n /**\n * Filter by schema component name (TypeScript or JSON schema). Matches schemas in `#/components/schemas`.\n */\n type: 'schemaName'\n /**\n * Schema name to match (case-sensitive). Can be a literal string or regex pattern.\n */\n pattern: string | RegExp\n}\n\ntype ByContentType = {\n /**\n * Filter by response or request content type: `'application/json'`, `'application/xml'`, etc.\n */\n type: 'contentType'\n /**\n * Content type to match (case-sensitive). Can be a literal string or regex pattern.\n */\n pattern: string | RegExp\n}\n\n/**\n * Filter that skips matching operations or schemas during generation, for example\n * deprecated endpoints or internal-only schemas.\n *\n * @example\n * ```ts\n * exclude: [\n * { type: 'tag', pattern: 'internal' },\n * { type: 'path', pattern: /^\\/admin/ },\n * { type: 'operationId', pattern: /^deprecated_/ },\n * ]\n * ```\n */\nexport type Exclude = ByTag | ByOperationId | ByPath | ByMethod | ByContentType | BySchemaName\n\n/**\n * Filter that restricts generation to operations or schemas matching at least\n * one entry. Useful for partial builds (one tag, one API version).\n *\n * @example\n * ```ts\n * include: [\n * { type: 'tag', pattern: 'public' },\n * { type: 'path', pattern: /^\\/api\\/v1/ },\n * ]\n * ```\n */\nexport type Include = ByTag | ByOperationId | ByPath | ByMethod | ByContentType | BySchemaName\n\n/**\n * Filter paired with a partial options object. When the filter matches, the\n * options are merged on top of the plugin defaults for that operation only.\n * Useful for \"this one tag goes to a different folder\" rules.\n *\n * Entries are evaluated top to bottom. The first matching entry wins.\n *\n * @example\n * ```ts\n * override: [\n * {\n * type: 'tag',\n * pattern: 'admin',\n * options: { output: { path: './src/gen/admin' } },\n * },\n * {\n * type: 'operationId',\n * pattern: 'listPets',\n * options: { enumType: 'literal' },\n * },\n * ]\n * ```\n */\nexport type Override<TOptions> = (ByTag | ByOperationId | ByPath | ByMethod | BySchemaName | ByContentType) & {\n options: Omit<Partial<TOptions>, 'override'>\n}\n\nexport type PluginFactoryOptions<\n /**\n * Unique plugin name.\n */\n TName extends string = string,\n /**\n * User-facing plugin options.\n */\n TOptions extends object = object,\n /**\n * Plugin options after defaults are applied.\n */\n TResolvedOptions extends object = TOptions,\n /**\n * Resolver that encapsulates naming and path-resolution helpers.\n * Define with `defineResolver` and export alongside the plugin.\n */\n TResolver extends Resolver = Resolver,\n> = {\n name: TName\n options: TOptions\n resolvedOptions: TResolvedOptions\n resolver: TResolver\n}\n\n/**\n * Context passed to a plugin's `kubb:plugin:setup` handler, where it registers generators and\n * sets its resolver, transformer, and options.\n */\nexport type KubbPluginSetupContext<TFactory extends PluginFactoryOptions = PluginFactoryOptions> = {\n /**\n * Register a generator dynamically. Generators fire during the AST walk (schema/operation/operations)\n * just like generators declared statically on `createPlugin`.\n */\n addGenerator<TElement = unknown>(generator: Generator<TFactory, TElement>): void\n /**\n * Set or override the resolver for this plugin.\n * The resolver controls file naming and path resolution.\n */\n setResolver(resolver: Partial<TFactory['resolver']>): void\n /**\n * Add a macro that rewrites AST nodes before they reach generators. Macros run in the order they\n * are added, after any macros from earlier `addMacro` calls.\n */\n addMacro(macro: Macro): void\n /**\n * Replace this plugin's macros with `macros`.\n */\n setMacros(macros: ReadonlyArray<Macro>): void\n /**\n * Set resolved options merged into the normalized plugin's `options`.\n * Call this in `kubb:plugin:setup` to provide options generators need.\n */\n setOptions(options: TFactory['resolvedOptions']): void\n /**\n * Inject a raw file into the build output, bypassing the generation pipeline.\n */\n injectFile(userFileNode: UserFileNode): void\n /**\n * Merge a partial config update into the current build configuration.\n */\n updateConfig(config: Partial<Config>): void\n /**\n * The resolved build configuration at setup time.\n */\n config: Config\n /**\n * The plugin's user-provided options.\n */\n options: TFactory['options']\n}\n\n/**\n * A plugin object produced by `definePlugin`. Its lifecycle handlers live under a single\n * `hooks` property rather than flat methods.\n */\nexport type Plugin<TFactory extends PluginFactoryOptions = PluginFactoryOptions> = {\n /**\n * Unique name for the plugin, following the same naming convention as `createPlugin`.\n */\n name: string\n /**\n * Plugins that must be registered before this plugin executes.\n * An error is thrown at startup when any listed dependency is missing.\n */\n dependencies?: Array<string>\n /**\n * Controls the execution order of this plugin relative to others.\n *\n * - `'pre'` runs before all normal plugins.\n * - `'post'` runs after all normal plugins.\n * - `undefined` (default) runs in declaration order among normal plugins.\n *\n * Dependency constraints always take precedence over `enforce`.\n */\n enforce?: Enforce\n /**\n * The options passed by the user when calling the plugin factory.\n */\n options?: TFactory['options']\n /**\n * Lifecycle event handlers for this plugin.\n * Any event from the global `KubbHooks` map can be subscribed to here.\n */\n hooks: {\n [K in keyof KubbHooks as K extends 'kubb:plugin:setup' ? never : K]?: (...args: KubbHooks[K]) => void | Promise<void>\n } & {\n 'kubb:plugin:setup'?(ctx: KubbPluginSetupContext<TFactory>): void | Promise<void>\n }\n}\n\n/**\n * Normalized plugin after setup, with runtime fields populated. Internal only. Plugins use the\n * public `Plugin` type.\n *\n * @internal\n */\nexport type NormalizedPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = Plugin<TOptions> & {\n options: TOptions['resolvedOptions'] & {\n output: Output\n include?: Array<Include>\n exclude: Array<Exclude>\n override: Array<Override<TOptions['resolvedOptions']>>\n }\n resolver: TOptions['resolver']\n macros?: Array<Macro>\n generators?: Array<Generator>\n apply?: (config: Config) => boolean\n version?: string\n}\n\nexport type KubbPluginStartContext = {\n plugin: NormalizedPlugin\n}\n\nexport type KubbPluginEndContext = {\n plugin: NormalizedPlugin\n duration: number\n success: boolean\n error?: Error\n config: Config\n /**\n * Returns all files currently in the file manager (lazy snapshot).\n * Includes files added by plugins that have already run.\n */\n readonly files: ReadonlyArray<FileNode>\n /**\n * Upsert one or more files into the file manager.\n */\n upsertFile: (...files: Array<FileNode>) => void\n}\n\n/**\n * Wraps a plugin factory and returns a function that accepts user options and\n * yields a typed `Plugin`. Lifecycle handlers go inside a single `hooks` object.\n *\n * Pass a `PluginFactoryOptions` type parameter to get a typed `ctx` inside\n * `kubb:plugin:setup`. Plugin names should follow the `plugin-<feature>`\n * convention (`plugin-react-query`, `plugin-zod`, ...).\n *\n * @example\n * ```ts\n * import { definePlugin } from '@kubb/core'\n *\n * export const pluginTs = definePlugin((options: { prefix?: string } = {}) => ({\n * name: 'plugin-ts',\n * hooks: {\n * 'kubb:plugin:setup'(ctx) {\n * ctx.setResolver(resolverTs)\n * },\n * },\n * }))\n * ```\n */\nexport function definePlugin<TFactory extends PluginFactoryOptions = PluginFactoryOptions>(\n factory: (options: TFactory['options']) => Plugin<TFactory>,\n): (options?: TFactory['options']) => Plugin<TFactory> {\n return (options) => factory(options ?? ({} as TFactory['options']))\n}\n","import path from 'node:path'\nimport { camelCase, pascalCase, toFilePath } from '@internals/utils'\nimport type { FileNode, InputMeta, Node, OperationNode, SchemaNode } from '@kubb/ast'\nimport { operationDef, schemaDef } from '@kubb/ast'\nimport * as factory from '@kubb/ast/factory'\nimport { Diagnostics } from './diagnostics.ts'\nimport type { PluginFactoryOptions } from './definePlugin.ts'\nimport type { Config, Group, Output } from './types.ts'\n\n/**\n * Type/string pattern filter for include/exclude/override matching.\n */\ntype PatternFilter = {\n type: string\n pattern: string | RegExp\n}\n\n/**\n * Pattern filter with partial option overrides applied when the pattern matches.\n */\ntype PatternOverride<TOptions> = PatternFilter & {\n options: Omit<Partial<TOptions>, 'override'>\n}\n\n/**\n * Context for resolving filtered options for a given operation or schema node.\n *\n * @internal\n */\nexport type ResolveOptionsContext<TOptions> = {\n options: TOptions\n exclude?: Array<PatternFilter>\n include?: Array<PatternFilter>\n override?: Array<PatternOverride<TOptions>>\n}\n\n/**\n * Base constraint for all plugin resolver objects.\n *\n * `default`, `resolveOptions`, `resolvePath`, `resolveFile`, `resolveBanner`, and `resolveFooter`\n * are injected automatically by `defineResolver`. Extend this type to add custom resolution methods.\n *\n * @example\n * ```ts\n * type MyResolver = Resolver & {\n * resolveName(node: SchemaNode): string\n * resolveTypedName(node: SchemaNode): string\n * }\n * ```\n */\nexport type Resolver = {\n name: string\n pluginName: string\n default(name: string, type?: 'file' | 'function' | 'type' | 'const'): string\n resolveOptions<TOptions>(node: Node, context: ResolveOptionsContext<TOptions>): TOptions | null\n resolvePath(params: ResolverPathParams, context: ResolverContext): string\n resolveFile(params: ResolverFileParams, context: ResolverContext): FileNode\n resolveBanner(meta: InputMeta | undefined, context: ResolveBannerContext): string | null\n resolveFooter(meta: InputMeta | undefined, context: ResolveBannerContext): string | null\n}\n\n/**\n * File-specific parameters for `Resolver.resolvePath`.\n *\n * Pass alongside a `ResolverContext` to identify which file to resolve.\n * Provide `tag` for tag-based grouping or `path` for path-based grouping.\n *\n * @example\n * ```ts\n * resolver.resolvePath(\n * { baseName: 'petTypes.ts', tag: 'pets' },\n * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },\n * )\n * // → '/src/types/pets/petTypes.ts'\n * ```\n */\nexport type ResolverPathParams = {\n baseName: FileNode['baseName']\n /**\n * Tag value used when `group.type === 'tag'`.\n */\n tag?: string\n /**\n * Path value used when `group.type === 'path'`.\n */\n path?: string\n}\n\n/**\n * Shared context passed as the second argument to `Resolver.resolvePath` and `Resolver.resolveFile`.\n *\n * Describes where on disk output is rooted, which output config is active, and the optional\n * grouping strategy that controls subdirectory layout.\n *\n * @example\n * ```ts\n * const context: ResolverContext = {\n * root: config.root,\n * output,\n * group,\n * }\n * ```\n */\nexport type ResolverContext = {\n root: string\n output: Output\n group?: Group\n /**\n * Plugin name used to populate `meta.pluginName` on the resolved file.\n */\n pluginName?: string\n}\n\n/**\n * File-specific parameters for `Resolver.resolveFile`.\n *\n * Pass alongside a `ResolverContext` to fully describe the file to resolve.\n * `tag` and `path` are used only when a matching `group` is present in the context.\n *\n * @example\n * ```ts\n * resolver.resolveFile(\n * { name: 'listPets', extname: '.ts', tag: 'pets' },\n * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },\n * )\n * // → { baseName: 'listPets.ts', path: '/src/types/pets/listPets.ts', ... }\n * ```\n */\nexport type ResolverFileParams = {\n name: string\n extname: FileNode['extname']\n /**\n * Tag value used when `group.type === 'tag'`.\n */\n tag?: string\n /**\n * Path value used when `group.type === 'path'`.\n */\n path?: string\n}\n\n/**\n * Per-file context describing the file a banner/footer is being resolved for.\n *\n * Supplied by the generator (or the barrel plugin) at resolve-time and merged\n * into `BannerMeta` so a `banner`/`footer` function can branch on the file kind,\n * e.g. omit a `'use server'` directive on re-export files.\n */\nexport type ResolveBannerFile = {\n /**\n * Full output path of the file being generated.\n */\n path: string\n /**\n * File name only, e.g. `'stocks.ts'`.\n */\n baseName: string\n /**\n * `true` for `index.ts` re-export barrels.\n */\n isBarrel?: boolean\n /**\n * `true` for group `[dir]/[dir].ts` aggregation files.\n */\n isAggregation?: boolean\n}\n\n/**\n * Document metadata extended with per-file context, passed to a `banner`/`footer` function.\n *\n * Carries everything in {@link InputMeta} plus the file the banner is rendered into, so a\n * single function can decide per file (e.g. skip a directive on barrel/aggregation files).\n *\n * @example Skip a directive on re-export files\n * `banner: (meta) => (meta.isBarrel || meta.isAggregation) ? '' : \"'use server'\"`\n */\nexport type BannerMeta = InputMeta & {\n /**\n * Full output path of the file being generated.\n */\n filePath: string\n /**\n * File name only, e.g. `'stocks.ts'`.\n */\n baseName: string\n /**\n * `true` for `index.ts` re-export barrels.\n */\n isBarrel: boolean\n /**\n * `true` for group `[dir]/[dir].ts` aggregation files.\n */\n isAggregation: boolean\n}\n\n/**\n * Context passed to `Resolver.resolveBanner` and `Resolver.resolveFooter`.\n *\n * `output` is optional, since not every plugin configures a banner/footer.\n * `config` carries the global Kubb config, used to derive the default Kubb banner.\n * `file` carries per-file context forwarded to a `banner`/`footer` function.\n *\n * @example\n * ```ts\n * resolver.resolveBanner(meta, { output: { banner: '// generated' }, config })\n * // → '// generated'\n * ```\n */\nexport type ResolveBannerContext = {\n output?: Pick<Output, 'banner' | 'footer'>\n config: Config\n file?: ResolveBannerFile\n}\n\n/**\n * Merges document `meta` with per-file `file` context into the `BannerMeta` passed to a\n * `banner`/`footer` function. Missing fields default to empty/`false` so the object shape\n * is stable even when a caller (e.g. the barrel plugin) has no document metadata.\n */\nfunction buildBannerMeta({ meta, file }: { meta: InputMeta | undefined; file: ResolveBannerFile | undefined }): BannerMeta {\n return {\n title: meta?.title,\n description: meta?.description,\n version: meta?.version,\n baseURL: meta?.baseURL,\n circularNames: meta?.circularNames ?? [],\n enumNames: meta?.enumNames ?? [],\n filePath: file?.path ?? '',\n baseName: file?.baseName ?? '',\n isBarrel: file?.isBarrel ?? false,\n isAggregation: file?.isAggregation ?? false,\n }\n}\n\n/**\n * Builder type for the plugin-specific resolver fields.\n *\n * `default`, `resolveOptions`, `resolvePath`, `resolveFile`, `resolveBanner`, and `resolveFooter`\n * are optional, with built-in fallbacks injected when omitted.\n *\n * Methods in the returned object can call sibling resolver methods via `this`.\n */\ntype ResolverBuilder<T extends PluginFactoryOptions> = () => Omit<\n T['resolver'],\n 'default' | 'resolveOptions' | 'resolvePath' | 'resolveFile' | 'resolveBanner' | 'resolveFooter' | 'name' | 'pluginName'\n> &\n Partial<Pick<T['resolver'], 'default' | 'resolveOptions' | 'resolvePath' | 'resolveFile' | 'resolveBanner' | 'resolveFooter'>> & {\n name: string\n pluginName: T['name']\n } & ThisType<T['resolver']>\n\n// String patterns are compiled lazily and cached, so the same filter is reused for every node.\nconst stringPatternCache = new Map<string, RegExp>()\n\nfunction testPattern(value: string, pattern: string | RegExp): boolean {\n if (typeof pattern === 'string') {\n let regex = stringPatternCache.get(pattern)\n if (!regex) {\n regex = new RegExp(pattern)\n stringPatternCache.set(pattern, regex)\n }\n return regex.test(value)\n }\n // Use .match() for user-supplied RegExp to preserve semantics regardless of `g`/`y` flags.\n return value.match(pattern) !== null\n}\n\n/**\n * Checks if an operation matches a pattern for a given filter type (`tag`, `operationId`, `path`, `method`).\n */\nfunction matchesOperationPattern(node: OperationNode, type: string, pattern: string | RegExp): boolean {\n if (type === 'tag') return node.tags.some((tag) => testPattern(tag, pattern))\n if (type === 'operationId') return testPattern(node.operationId, pattern)\n if (type === 'path') return node.path !== undefined && testPattern(node.path, pattern)\n if (type === 'method') return node.method !== undefined && testPattern(node.method.toLowerCase(), pattern)\n if (type === 'contentType') return node.requestBody?.content?.some((c) => testPattern(c.contentType, pattern)) ?? false\n return false\n}\n\n/**\n * Checks if a schema matches a pattern for a given filter type (`schemaName`).\n *\n * Returns `null` when the filter type doesn't apply to schemas.\n */\nfunction matchesSchemaPattern(node: SchemaNode, type: string, pattern: string | RegExp): boolean | null {\n if (type === 'schemaName') return node.name ? testPattern(node.name, pattern) : false\n return null\n}\n\n/**\n * Default name resolver used by `defineResolver`.\n *\n * - `camelCase` for `file`, with dotted names split into `/`-joined nested paths.\n * - `PascalCase` for `type`.\n * - `camelCase` for `function` and everything else.\n */\nfunction defaultResolver(name: string, type?: 'file' | 'function' | 'type' | 'const'): string {\n if (type === 'file') return toFilePath(name)\n if (type === 'type') return pascalCase(name)\n return camelCase(name)\n}\n\n/**\n * Default option resolver. Applies include/exclude filters and merges matching override options.\n *\n * Returns `null` when the node is filtered out by an `exclude` rule or not matched by any `include` rule.\n *\n * @example Include/exclude filtering\n * ```ts\n * const options = defaultResolveOptions(operationNode, {\n * options: { output: 'types' },\n * exclude: [{ type: 'tag', pattern: 'internal' }],\n * })\n * // → null when node has tag 'internal'\n * ```\n *\n * @example Override merging\n * ```ts\n * const options = defaultResolveOptions(operationNode, {\n * options: { enumType: 'asConst' },\n * override: [{ type: 'operationId', pattern: 'listPets', options: { enumType: 'enum' } }],\n * })\n * // → { enumType: 'enum' } when operationId matches\n * ```\n */\nconst resolveOptionsCache = new WeakMap<object, WeakMap<Node, { value: unknown }>>()\n\nfunction computeOptions<TOptions>(\n node: Node,\n options: TOptions,\n exclude: Array<PatternFilter>,\n include: Array<PatternFilter> | undefined,\n override: Array<PatternOverride<TOptions>>,\n): TOptions | null {\n if (operationDef.is(node)) {\n if (exclude.some(({ type, pattern }) => matchesOperationPattern(node, type, pattern))) return null\n if (include && !include.some(({ type, pattern }) => matchesOperationPattern(node, type, pattern))) return null\n\n const overrideOptions = override.find(({ type, pattern }) => matchesOperationPattern(node, type, pattern))?.options\n\n return { ...options, ...overrideOptions }\n }\n\n if (schemaDef.is(node)) {\n if (exclude.some(({ type, pattern }) => matchesSchemaPattern(node, type, pattern) === true)) return null\n if (include) {\n const results = include.map(({ type, pattern }) => matchesSchemaPattern(node, type, pattern))\n const applicable = results.filter((result) => result !== null)\n\n if (applicable.length > 0 && !applicable.includes(true)) return null\n }\n const overrideOptions = override.find(({ type, pattern }) => matchesSchemaPattern(node, type, pattern) === true)?.options\n\n return { ...options, ...overrideOptions }\n }\n\n return options\n}\n\nfunction defaultResolveOptions<TOptions>(node: Node, { options, exclude = [], include, override = [] }: ResolveOptionsContext<TOptions>): TOptions | null {\n const optionsKey = options as object\n let byOptions = resolveOptionsCache.get(optionsKey)\n if (!byOptions) {\n byOptions = new WeakMap()\n resolveOptionsCache.set(optionsKey, byOptions)\n }\n const cached = byOptions.get(node)\n if (cached !== undefined) return cached.value as TOptions | null\n\n const result = computeOptions(node, options, exclude, include, override)\n\n byOptions.set(node, { value: result })\n\n return result\n}\n\n/**\n * Default path resolver used by `defineResolver`.\n *\n * - `mode: 'file'` resolves directly to `output.path` (the full file path, extension included).\n * - `mode: 'directory'` (default) resolves to `output.path/{baseName}`, or into a\n * subdirectory when `group` and a `tag`/`path` value are provided.\n *\n * A custom `group.name` function overrides the default subdirectory naming.\n * For `tag` groups the default is the camelCased tag.\n * For `path` groups the default is the first path segment after `/`.\n *\n * @example Flat output\n * ```ts\n * defaultResolvePath({ baseName: 'petTypes.ts' }, { root: '/src', output: { path: 'types' } })\n * // → '/src/types/petTypes.ts'\n * ```\n *\n * @example Tag-based grouping\n * ```ts\n * defaultResolvePath(\n * { baseName: 'petTypes.ts', tag: 'pets' },\n * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },\n * )\n * // → '/src/types/pets/petTypes.ts'\n * ```\n *\n * @example Path-based grouping\n * ```ts\n * defaultResolvePath(\n * { baseName: 'petTypes.ts', path: '/pets/list' },\n * { root: '/src', output: { path: 'types' }, group: { type: 'path' } },\n * )\n * // → '/src/types/pets/petTypes.ts'\n * ```\n *\n * @example Single file (`mode: 'file'`)\n * ```ts\n * defaultResolvePath(\n * { baseName: 'petTypes.ts' },\n * { root: '/src', output: { path: 'types.ts', mode: 'file' } },\n * )\n * // → '/src/types.ts'\n * ```\n */\nexport function defaultResolvePath({ baseName, tag, path: groupPath }: ResolverPathParams, { root, output, group }: ResolverContext): string {\n const mode = output.mode ?? 'directory'\n\n if (mode === 'file') {\n return path.resolve(root, output.path)\n }\n\n const result: string = (() => {\n if (group && (groupPath || tag)) {\n const groupValue = group.type === 'path' ? groupPath! : tag!\n const defaultName =\n group.type === 'tag'\n ? ({ group: groupName }: { group: string }) => camelCase(groupName)\n : ({ group: groupName }: { group: string }) => {\n // Strip traversal components (empty, '.', '..') before taking the first meaningful segment.\n // When every segment is a traversal component (e.g. '../../') we fall back to '' so the\n // file is placed directly in the output root, and the boundary check below ensures safety.\n const segment = groupName.split('/').filter((part) => part !== '' && part !== '.' && part !== '..')[0]\n return segment ? camelCase(segment) : ''\n }\n const resolveName = group.name ?? defaultName\n const groupName = resolveName({ group: groupValue })\n\n return path.resolve(root, output.path, groupName, baseName)\n }\n return path.resolve(root, output.path, baseName)\n })()\n\n // Ensure the resolved path stays within the configured output directory.\n // This prevents path traversal from malicious OpenAPI specs or custom group.name functions.\n // `result === outputDir` is intentionally permitted: it matches edge cases where baseName\n // resolves to the output directory itself.\n const outputDir = path.resolve(root, output.path)\n const outputDirWithSep = outputDir.endsWith(path.sep) ? outputDir : `${outputDir}${path.sep}`\n if (result !== outputDir && !result.startsWith(outputDirWithSep)) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.pathTraversal,\n severity: 'error',\n message: `Resolved path \"${result}\" is outside the output directory \"${outputDir}\".`,\n help: 'This can stem from a path traversal in the OpenAPI specification or a misconfigured `group.name` function. Keep generated paths within the output directory.',\n location: { kind: 'config' },\n })\n }\n\n return result\n}\n\n/**\n * Default file resolver used by `defineResolver`.\n *\n * Resolves a `FileNode` by combining name resolution (`resolver.default`) with\n * path resolution (`resolver.resolvePath`). The resolved file always has empty\n * `sources`, `imports`, and `exports` arrays, which consumers populate separately.\n *\n * In `mode: 'file'` the name is omitted and the file sits directly at the output path.\n *\n * @example Resolve a schema file\n * ```ts\n * const file = defaultResolveFile.call(\n * resolver,\n * { name: 'pet', extname: '.ts' },\n * { root: '/src', output: { path: 'types' } },\n * )\n * // → { baseName: 'pet.ts', path: '/src/types/pet.ts', sources: [], ... }\n * ```\n *\n * @example Resolve an operation file with tag grouping\n * ```ts\n * const file = defaultResolveFile.call(\n * resolver,\n * { name: 'listPets', extname: '.ts', tag: 'pets' },\n * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },\n * )\n * // → { baseName: 'listPets.ts', path: '/src/types/pets/listPets.ts', ... }\n * ```\n */\nexport function defaultResolveFile(this: Resolver, { name, extname, tag, path: groupPath }: ResolverFileParams, context: ResolverContext): FileNode {\n const mode = context.output.mode ?? 'directory'\n const resolvedName = mode === 'file' ? '' : this.default(name, 'file')\n const baseName = `${resolvedName}${extname}` as FileNode['baseName']\n const filePath = this.resolvePath({ baseName, tag, path: groupPath }, context)\n\n return factory.createFile({\n path: filePath,\n baseName: path.basename(filePath) as `${string}.${string}`,\n meta: {\n pluginName: this.pluginName,\n },\n sources: [],\n imports: [],\n exports: [],\n })\n}\n\n/**\n * Generates the default \"Generated by Kubb\" banner from config and optional node metadata.\n */\nfunction buildDefaultBanner({ title, description, version, config }: { title?: string; description?: string; version?: string; config: Config }): string {\n try {\n const source = (() => {\n if (Array.isArray(config.input)) {\n const first = config.input[0]\n if (first && 'path' in first) return path.basename(first.path)\n return ''\n }\n if (config.input && 'path' in config.input) return path.basename(config.input.path)\n if (config.input && 'data' in config.input) return 'text content'\n return ''\n })()\n\n let banner = '/**\\n* Generated by Kubb (https://kubb.dev/).\\n* Do not edit manually.\\n'\n\n if (config.output.defaultBanner === 'simple') {\n banner += '*/\\n'\n return banner\n }\n\n if (source) {\n banner += `* Source: ${source}\\n`\n }\n\n if (title) {\n banner += `* Title: ${title}\\n`\n }\n\n if (description) {\n const formattedDescription = description.replace(/\\n/gm, '\\n* ')\n banner += `* Description: ${formattedDescription}\\n`\n }\n\n if (version) {\n banner += `* OpenAPI spec version: ${version}\\n`\n }\n\n banner += '*/\\n'\n return banner\n } catch (_error) {\n return '/**\\n* Generated by Kubb (https://kubb.dev/).\\n* Do not edit manually.\\n*/'\n }\n}\n\n/**\n * Default banner resolver. Returns the banner string for a generated file.\n *\n * A user-supplied `output.banner` overrides the default Kubb \"Generated by Kubb\" notice.\n * When no `output.banner` is set, the Kubb notice is used (including `title` and `version`\n * from the document metadata when `meta` is provided).\n *\n * - When `output.banner` is a function, calls it with the file's `BannerMeta` and returns the result.\n * - When `output.banner` is a string, returns it directly.\n * - When `config.output.defaultBanner` is `false`, returns `undefined`.\n * - Otherwise returns the Kubb \"Generated by Kubb\" notice.\n *\n * @example String banner overrides default\n * ```ts\n * defaultResolveBanner(undefined, { output: { banner: '// my banner' }, config })\n * // → '// my banner'\n * ```\n *\n * @example Function banner with metadata\n * ```ts\n * defaultResolveBanner(meta, { output: { banner: (m) => `// v${m.version}` }, config })\n * // → '// v3.0.0'\n * ```\n *\n * @example Function banner skips re-export files\n * ```ts\n * defaultResolveBanner(meta, { output: { banner: (m) => (m.isBarrel ? '' : \"'use server'\") }, config, file: { path, baseName, isBarrel: true } })\n * // → ''\n * ```\n *\n * @example No user banner, Kubb notice with OAS metadata\n * ```ts\n * defaultResolveBanner(meta, { config })\n * // → '/** Generated by Kubb ... Title: Pet Store ... *\\/'\n * ```\n *\n * @example Disabled default banner\n * ```ts\n * defaultResolveBanner(undefined, { config: { output: { defaultBanner: false }, ...config } })\n * // → null\n * ```\n */\nexport function defaultResolveBanner(meta: InputMeta | undefined, { output, config, file }: ResolveBannerContext): string | null {\n if (typeof output?.banner === 'function') {\n return output.banner(buildBannerMeta({ meta, file }))\n }\n\n if (typeof output?.banner === 'string') {\n return output.banner\n }\n\n if (config.output.defaultBanner === false) {\n return null\n }\n\n return buildDefaultBanner({\n title: meta?.title,\n version: meta?.version,\n config,\n })\n}\n\n/**\n * Default footer resolver. Returns the footer string for a generated file.\n *\n * - When `output.footer` is a function, calls it with the file's `BannerMeta` and returns the result.\n * - When `output.footer` is a string, returns it directly.\n * - Otherwise returns `undefined`.\n *\n * @example String footer\n * ```ts\n * defaultResolveFooter(undefined, { output: { footer: '// end of file' }, config })\n * // → '// end of file'\n * ```\n *\n * @example Function footer with metadata\n * ```ts\n * defaultResolveFooter(meta, { output: { footer: (m) => `// ${m.title}` }, config })\n * // → '// Pet Store'\n * ```\n */\nexport function defaultResolveFooter(meta: InputMeta | undefined, { output, file }: ResolveBannerContext): string | null {\n if (typeof output?.footer === 'function') {\n return output.footer(buildBannerMeta({ meta, file }))\n }\n if (typeof output?.footer === 'string') {\n return output.footer\n }\n return null\n}\n\n/**\n * Defines a plugin resolver. The resolver is the object that decides what\n * every generated symbol and file path is called. Built-in defaults handle\n * name casing, include/exclude/override filtering, output path computation,\n * and file construction. Supply your own to override any of them:\n *\n * - `default` sets the name casing strategy (camelCase or PascalCase).\n * - `resolveOptions` does include/exclude/override filtering.\n * - `resolvePath` computes the output path.\n * - `resolveFile` builds the full `FileNode`.\n * - `resolveBanner` and `resolveFooter` produce the top and bottom of file text.\n *\n * Methods in the returned object can call sibling resolver methods via `this`.\n * A custom rule can delegate to a default, for example `this.default(name, 'type')`.\n *\n * @example Basic resolver with naming helpers\n * ```ts\n * export const resolverTs = defineResolver<PluginTs>(() => ({\n * name: 'default',\n * resolveName(name) {\n * return this.default(name, 'function')\n * },\n * resolveTypeName(name) {\n * return this.default(name, 'type')\n * },\n * }))\n * ```\n *\n * @example Custom output path\n * ```ts\n * import path from 'node:path'\n *\n * export const resolverTs = defineResolver<PluginTs>(() => ({\n * name: 'custom',\n * resolvePath({ baseName }, { root, output }) {\n * return path.resolve(root, output.path, 'generated', baseName)\n * },\n * }))\n * ```\n */\nexport function defineResolver<T extends PluginFactoryOptions>(build: ResolverBuilder<T>): T['resolver'] {\n // `resolver` is kept so the default `resolveFile` wrapper can reference the fully assembled\n // object via `.call(resolver, ...)` at call-time, after the result is assigned below.\n let resolver: T['resolver']\n\n const result = {\n default: defaultResolver,\n resolveOptions: defaultResolveOptions,\n resolvePath: defaultResolvePath,\n resolveFile: (params: ResolverFileParams, context: ResolverContext) => defaultResolveFile.call(resolver as Resolver, params, context),\n resolveBanner: defaultResolveBanner,\n resolveFooter: defaultResolveFooter,\n ...build(),\n } as T['resolver']\n\n resolver = result\n\n return resolver\n}\n","import type { Macro, OperationNode, SchemaNode, Visitor } from '@kubb/ast'\nimport { composeMacros, transform } from '@kubb/ast'\n\n/**\n * Holds an ordered list of macros per plugin, keyed by plugin name. Each plugin's macros run in\n * isolation on the original adapter node and are composed into a single `Visitor` that the\n * `@kubb/ast` `transform` primitive applies. `applyTo` is a per-plugin lookup, not a cross-plugin\n * chain, so plugin A's macros never see plugin B's output. When a plugin has no macros, `applyTo`\n * returns the original node reference, and `transform` does the same when the composed visitor\n * leaves the tree untouched, so callers can detect a no-op by identity.\n *\n * Registration order matches the order setup hooks fire, which the driver has already sorted by\n * `enforce` and dependency edges. The registry preserves that order. Macro `enforce` only reorders\n * within a single plugin's list.\n */\nexport class Transform {\n readonly #macros = new Map<string, Array<Macro>>()\n // Composed visitor per plugin, rebuilt lazily after the macro list changes.\n readonly #composed = new Map<string, Visitor>()\n // Memoized results per plugin. Repeated `applyTo` calls return the same node identity, so\n // downstream WeakMap caches keyed by node (the resolver's resolveOptions memo) hit when the\n // driver resolves a node a second time, and a stateful macro runs once per node.\n readonly #memo = new Map<string, WeakMap<SchemaNode | OperationNode, SchemaNode | OperationNode>>()\n\n /**\n * Number of plugins with at least one registered macro.\n */\n get size(): number {\n return this.#macros.size\n }\n\n /**\n * Appends `macro` to the plugin's list, after any macros already registered.\n */\n add(pluginName: string, macro: Macro): void {\n const list = this.#macros.get(pluginName)\n if (list) list.push(macro)\n else this.#macros.set(pluginName, [macro])\n this.#invalidate(pluginName)\n }\n\n /**\n * Replaces the plugin's macro list with `macros`.\n */\n set(pluginName: string, macros: ReadonlyArray<Macro>): void {\n this.#macros.set(pluginName, [...macros])\n this.#invalidate(pluginName)\n }\n\n /**\n * Looks up the composed visitor for `pluginName`, or `undefined` when the plugin has no macros.\n */\n get(pluginName: string): Visitor | undefined {\n return this.#visitorFor(pluginName)\n }\n\n /**\n * Runs the plugin's macros on `node`. Returns the original node reference when the plugin has no\n * macros, so callers can compare by identity to detect a no-op.\n */\n applyTo<TNode extends SchemaNode | OperationNode>(pluginName: string, node: TNode): TNode {\n const visitor = this.#visitorFor(pluginName)\n if (!visitor) return node\n\n let memo = this.#memo.get(pluginName)\n if (!memo) {\n memo = new WeakMap()\n this.#memo.set(pluginName, memo)\n }\n\n const cached = memo.get(node)\n if (cached) return cached as TNode\n\n const result = transform(node, visitor) as TNode\n memo.set(node, result)\n return result\n }\n\n /**\n * Clears every registration. Called from the driver's `dispose()` so macros do not leak across\n * builds.\n */\n dispose(): void {\n this.#macros.clear()\n this.#composed.clear()\n this.#memo.clear()\n }\n\n #invalidate(pluginName: string): void {\n this.#composed.delete(pluginName)\n this.#memo.delete(pluginName)\n }\n\n #visitorFor(pluginName: string): Visitor | undefined {\n const macros = this.#macros.get(pluginName)\n if (!macros || macros.length === 0) return undefined\n\n let composed = this.#composed.get(pluginName)\n if (!composed) {\n composed = composeMacros(macros)\n this.#composed.set(pluginName, composed)\n }\n return composed\n }\n}\n","import { resolve } from 'node:path'\nimport { arrayToAsyncIterable, type AsyncEventEmitter, forBatches, getElapsedMs, isPromise, memoize, Url } from '@internals/utils'\nimport * as factory from '@kubb/ast/factory'\nimport { collectUsedSchemaNames } from '@kubb/ast/utils'\nimport type { Enforce, FileNode, InputMeta, InputNode, OperationNode, SchemaNode } from '@kubb/ast'\nimport { OPERATION_FILTER_TYPES, SCHEMA_PARALLEL } from './constants.ts'\nimport { type Diagnostic, Diagnostics, type ProblemDiagnostic } from './diagnostics.ts'\nimport type { RendererFactory } from './createRenderer.ts'\nimport type { Storage } from './createStorage.ts'\nimport type { Generator } from './defineGenerator.ts'\nimport type { Parser } from './defineParser.ts'\nimport type { Plugin } from './definePlugin.ts'\nimport { normalizeOutput } from './definePlugin.ts'\nimport { defineResolver } from './defineResolver.ts'\nimport { FileManager } from './FileManager.ts'\nimport { FileProcessor } from './FileProcessor.ts'\nimport { Transform } from './Transform.ts'\n\nimport type {\n Adapter,\n AdapterSource,\n Config,\n GeneratorContext,\n Group,\n KubbHooks,\n KubbPluginSetupContext,\n NormalizedPlugin,\n PluginFactoryOptions,\n Resolver,\n} from './types.ts'\n\ntype Options = {\n hooks: AsyncEventEmitter<KubbHooks>\n}\n\ntype HookListener<TArgs extends Array<unknown>, TResult = void> = (...args: TArgs) => TResult | Promise<TResult>\n\ntype ListenerEntry = [event: keyof KubbHooks & string, handler: HookListener<Array<unknown>, unknown>]\n\ntype RequirePluginContext = {\n /**\n * Name of the plugin that declared the dependency, included in the error so users can\n * trace which plugin needs the missing one.\n */\n requiredBy?: string\n}\n\nfunction enforceOrder(enforce: Enforce | undefined): number {\n return enforce === 'pre' ? -1 : enforce === 'post' ? 1 : 0\n}\n\nexport class KubbDriver {\n readonly config: Config\n readonly options: Options\n\n /**\n * The streaming `InputNode<true>` produced by the adapter. Set after adapter setup.\n * Parse-only adapters are wrapped automatically.\n */\n inputNode: InputNode<true> | null = null\n adapter: Adapter | null = null\n /**\n * Raw adapter source so `adapter.parse()` / `adapter.stream()` can run lazily.\n * Intentionally outlives the build, cleared by `dispose()`.\n */\n #adapterSource: AdapterSource | null = null\n\n /**\n * Central file store for all generated files.\n * Plugins should use `this.addFile()` / `this.upsertFile()` (via their context) to\n * add files. This property gives direct read/write access when needed.\n */\n readonly fileManager = new FileManager()\n readonly plugins = new Map<string, NormalizedPlugin>()\n\n /**\n * Tracks which plugins have generators registered via `addGenerator()` (event-based path).\n * Used by the build loop to decide whether to emit generator events for a given plugin.\n */\n readonly #eventGeneratorPlugins = new Set<string>()\n readonly #resolvers = new Map<string, Resolver>()\n readonly #defaultResolvers = new Map<string, Resolver>()\n\n /**\n * Tracks every listener the driver added (plugin, generator) so `dispose()` can remove them\n * in one pass. External `hooks.on(...)` listeners are not tracked.\n */\n readonly #listeners: Array<ListenerEntry> = []\n\n /**\n * Transform registry. Plugins populate it during `kubb:plugin:setup` via `addMacro`/`setMacros`,\n * and `#runGenerators` reads it once per `(plugin, node)` pair through `applyTo`.\n */\n readonly #transforms = new Transform()\n\n constructor(config: Config, options: Options) {\n this.config = config\n this.options = options\n this.adapter = config.adapter ?? null\n }\n\n /**\n * Attaches a listener to the shared emitter and tracks it so `dispose()` can remove it later.\n * Listeners attached directly via `hooks.on(...)` are not tracked and survive disposal.\n */\n #trackListener<K extends keyof KubbHooks & string>(event: K, handler: HookListener<KubbHooks[K], unknown>): void {\n this.hooks.on(event, handler as HookListener<KubbHooks[K]>)\n this.#listeners.push([event, handler as HookListener<Array<unknown>, unknown>])\n }\n\n /**\n * Normalizes every configured plugin, orders them, and registers their lifecycle handlers.\n * A plugin that another lists as a dependency runs first, then `enforce: 'pre'` before\n * `'post'`. When the config has an adapter, the adapter source is resolved from the input\n * so `run` can parse it later.\n */\n async setup() {\n const normalized: Array<NormalizedPlugin> = this.config.plugins.map((rawPlugin) => this.#normalizePlugin(rawPlugin as Plugin))\n\n const dependenciesByName = new Map(normalized.map((plugin) => [plugin.name, new Set(plugin.dependencies ?? [])]))\n\n normalized.sort((a, b) => {\n if (dependenciesByName.get(b.name)?.has(a.name)) return -1\n if (dependenciesByName.get(a.name)?.has(b.name)) return 1\n\n return enforceOrder(a.enforce) - enforceOrder(b.enforce)\n })\n\n for (const plugin of normalized) {\n if (plugin.apply) {\n plugin.apply(this.config)\n }\n\n this.#registerPlugin(plugin)\n this.plugins.set(plugin.name, plugin)\n }\n\n if (this.config.adapter) {\n this.#adapterSource = inputToAdapterSource(this.config)\n }\n }\n\n get hooks() {\n return this.options.hooks\n }\n\n /**\n * Builds a `NormalizedPlugin` from a hook-style plugin, filling in default\n * options and copying `apply` when present. Registering its lifecycle handlers\n * on the `AsyncEventEmitter` is done separately by `#registerPlugin`.\n */\n #normalizePlugin(plugin: Plugin): NormalizedPlugin {\n const normalized: NormalizedPlugin = {\n name: plugin.name,\n dependencies: plugin.dependencies,\n enforce: plugin.enforce,\n hooks: plugin.hooks,\n options: plugin.options ?? { output: { path: '.', mode: 'directory' }, exclude: [], override: [] },\n } as NormalizedPlugin\n\n if ('apply' in plugin && typeof plugin.apply === 'function') {\n normalized.apply = plugin.apply as (config: Config) => boolean\n }\n\n return normalized\n }\n\n /**\n * Parses the adapter source into `this.inputNode`. Idempotent, so repeated calls from\n * `run` do not re-parse. Adapters with `stream()` are used directly.\n * Adapters with only `parse()` are wrapped via `factory.createInput({ stream: true })` so the dispatch loop\n * stays stream-only.\n */\n async #parseInput(): Promise<void> {\n if (this.inputNode || !this.adapter || !this.#adapterSource) return\n\n const adapter = this.adapter\n const source = this.#adapterSource\n\n if (adapter.stream) {\n this.inputNode = await adapter.stream(source)\n return\n }\n\n const parsed = await adapter.parse(source)\n this.inputNode = factory.createInput({\n stream: true,\n schemas: arrayToAsyncIterable(parsed.schemas),\n operations: arrayToAsyncIterable(parsed.operations),\n meta: parsed.meta,\n })\n }\n\n /**\n * Registers a hook-style plugin's lifecycle handlers on the shared `AsyncEventEmitter`.\n *\n * The `kubb:plugin:setup` listener wraps the global context in a plugin-specific one so\n * `addGenerator`, `setResolver`, and `setMacros` target the right `normalizedPlugin`.\n * Every other `KubbHooks` event registers as a pass-through listener that external tooling\n * can observe via `hooks.on(...)`.\n *\n * @internal\n */\n #registerPlugin(plugin: NormalizedPlugin): void {\n const { hooks } = plugin\n\n if (!hooks) return\n\n // kubb:plugin:setup gets special treatment: the globally emitted context is wrapped with\n // plugin-specific implementations so that addGenerator / setResolver / etc. target\n // this plugin's normalizedPlugin entry rather than being no-ops.\n if (hooks['kubb:plugin:setup']) {\n const setupHandler = (globalCtx: KubbPluginSetupContext) => {\n const pluginCtx: KubbPluginSetupContext = {\n ...globalCtx,\n options: plugin.options ?? {},\n addGenerator: (gen) => {\n this.registerGenerator(plugin.name, gen)\n },\n setResolver: (resolver) => {\n this.setPluginResolver(plugin.name, resolver)\n },\n addMacro: (macro) => {\n this.#transforms.add(plugin.name, macro)\n },\n setMacros: (macros) => {\n this.#transforms.set(plugin.name, macros)\n },\n setOptions: (opts) => {\n plugin.options = { ...plugin.options, ...opts }\n if (plugin.options.output) {\n const group = 'group' in plugin.options ? (plugin.options.group as Group | null | undefined) : undefined\n plugin.options.output = normalizeOutput({ output: plugin.options.output, group, pluginName: plugin.name })\n }\n },\n injectFile: (userFileNode) => {\n this.fileManager.add(factory.createFile(userFileNode))\n },\n }\n return hooks['kubb:plugin:setup']!(pluginCtx)\n }\n\n this.#trackListener('kubb:plugin:setup', setupHandler)\n }\n\n // All other hooks are registered as direct pass-through listeners on the shared emitter.\n for (const event of Object.keys(hooks) as Array<keyof KubbHooks & string>) {\n if (event === 'kubb:plugin:setup') continue\n const handler = hooks[event]\n if (!handler) continue\n\n this.#trackListener(event, handler as HookListener<KubbHooks[typeof event], unknown>)\n }\n }\n\n /**\n * Emits the `kubb:plugin:setup` event so that all registered hook-style plugin listeners\n * can configure generators, resolvers, macros and renderers before `buildStart` runs.\n *\n * Called once from `run` before the plugin execution loop begins.\n */\n async emitSetupHooks(): Promise<void> {\n const noop = () => {}\n\n await this.hooks.emit('kubb:plugin:setup', {\n config: this.config,\n options: {},\n addGenerator: noop,\n setResolver: noop,\n addMacro: noop,\n setMacros: noop,\n setOptions: noop,\n injectFile: noop,\n updateConfig: noop,\n })\n }\n\n /**\n * Registers a generator for the given plugin on the shared event emitter.\n *\n * The generator's `schema`, `operation`, and `operations` methods are registered as\n * listeners on `kubb:generate:schema`, `kubb:generate:operation`, and `kubb:generate:operations`\n * respectively. Each listener is scoped to the owning plugin via a `ctx.plugin.name` check\n * so that generators from different plugins do not cross-fire.\n *\n * The renderer comes from `generator.renderer`. Set `generator.renderer = null` (or leave it\n * unset) to opt out of rendering.\n *\n * Call this method inside `addGenerator()` (in `kubb:plugin:setup`) to wire up a generator.\n */\n registerGenerator(pluginName: string, generator: Generator): void {\n const register = <TNode>(event: keyof KubbHooks & string, method: ((node: TNode, ctx: GeneratorContext) => unknown) | undefined): void => {\n if (!method) return\n\n const handler = async (node: TNode, ctx: GeneratorContext) => {\n if (ctx.plugin.name !== pluginName) return\n const result = await method(node, ctx)\n await this.dispatch({ result, renderer: generator.renderer })\n }\n\n this.#trackListener(event, handler as HookListener<KubbHooks[typeof event], unknown>)\n }\n\n register('kubb:generate:schema', generator.schema)\n register('kubb:generate:operation', generator.operation)\n register('kubb:generate:operations', generator.operations)\n\n this.#eventGeneratorPlugins.add(pluginName)\n }\n\n /**\n * Returns `true` when at least one generator was registered for the given plugin\n * via `addGenerator()` in `kubb:plugin:setup` (event-based path).\n *\n * Used by the build loop to decide whether to walk the AST and emit generator events\n * for a plugin that has no static `plugin.generators`.\n */\n hasEventGenerators(pluginName: string): boolean {\n return this.#eventGeneratorPlugins.has(pluginName)\n }\n\n /**\n * Runs the full plugin pipeline. Returns the diagnostics collected so far even\n * when an outer hook throws, since the orchestrator preserves partial state by capturing\n * the failure as a {@link Diagnostic} instead of propagating. Each plugin also\n * contributes a `timing` diagnostic for the run summary.\n */\n async run({ storage }: { storage: Storage }): Promise<{ diagnostics: Array<Diagnostic> }> {\n const { hooks, config } = this\n const diagnostics: Array<Diagnostic> = []\n const parsersMap = new Map<FileNode['extname'], Parser>()\n\n for (const parser of config.parsers) {\n if (parser.extNames) {\n for (const ext of parser.extNames) parsersMap.set(ext, parser)\n }\n }\n\n const processor = new FileProcessor({ parsers: parsersMap, storage, extension: config.output.extension })\n // Bridge processor lifecycle to the user-facing kubb hooks so existing listeners on\n // kubb:files:processing:* keep firing.\n processor.hooks.on('start', async (files) => {\n await hooks.emit('kubb:files:processing:start', { files })\n })\n const updateBuffer: Array<{ file: FileNode; source?: string; processed: number; total: number; percentage: number }> = []\n processor.hooks.on('update', (item) => {\n updateBuffer.push(item)\n })\n processor.hooks.on('end', async (files) => {\n await hooks.emit('kubb:files:processing:update', {\n files: updateBuffer.map((item) => ({ ...item, config })),\n })\n updateBuffer.length = 0\n await hooks.emit('kubb:files:processing:end', { files })\n })\n const onFileUpsert = (file: FileNode): void => {\n processor.enqueue(file)\n }\n this.fileManager.hooks.on('upsert', onFileUpsert)\n\n // Make `diagnostics` the active sink so deep code (adapter parse, lazily consumed\n // streams, generators) can report into this run via `Diagnostics.report`.\n return Diagnostics.scope(\n (diagnostic) => diagnostics.push(diagnostic),\n async () => {\n try {\n const outputRoot = resolve(config.root, config.output.path)\n\n // Parse the adapter source into the streaming `InputNode`.\n await this.#parseInput()\n // Emit `kubb:plugin:setup` so plugins can register macros via `addMacro`/`setMacros`.\n // Each call writes into `this.#transforms`, which `#runGenerators` later reads through\n // `transforms.applyTo`.\n await this.emitSetupHooks()\n\n if (this.adapter && this.inputNode) {\n await hooks.emit(\n 'kubb:build:start',\n Object.assign({ config, adapter: this.adapter, meta: this.inputNode.meta, getPlugin: this.getPlugin.bind(this) }, this.#filesPayload()),\n )\n }\n\n const generatorPlugins: Array<{ plugin: NormalizedPlugin; context: Omit<GeneratorContext, 'options'>; hrStart: ReturnType<typeof process.hrtime> }> =\n []\n\n for (const plugin of this.plugins.values()) {\n const context = this.getContext(plugin)\n const hrStart = process.hrtime()\n\n try {\n await hooks.emit('kubb:plugin:start', { plugin })\n } catch (caughtError) {\n const error = caughtError as Error\n const duration = getElapsedMs(hrStart)\n\n await this.#emitPluginEnd({ plugin, duration, success: false, error })\n\n diagnostics.push({ ...Diagnostics.from(error), plugin: plugin.name }, Diagnostics.performance({ plugin: plugin.name, duration }))\n\n continue\n }\n\n if (this.hasEventGenerators(plugin.name)) {\n generatorPlugins.push({ plugin, context, hrStart })\n\n continue\n }\n\n const duration = getElapsedMs(hrStart)\n diagnostics.push(Diagnostics.performance({ plugin: plugin.name, duration }))\n\n await this.#emitPluginEnd({ plugin, duration, success: true })\n }\n\n // Stream every node through the transform registry and into each plugin's generators.\n // When there are no entries it returns early. When `inputNode` is missing it still\n // closes out each entry's `kubb:plugin:end` directly.\n diagnostics.push(...(await this.#runGenerators(generatorPlugins, () => processor.flush())))\n // Wait for the last in-flight batch and write anything still pending.\n await processor.drain()\n\n await hooks.emit('kubb:plugins:end', Object.assign({ config }, this.#filesPayload()))\n\n // Plugins-end listeners (barrel plugin etc.) may have queued more files.\n await processor.drain()\n\n await hooks.emit('kubb:build:end', { files: this.fileManager.files, config, outputDir: outputRoot })\n\n return { diagnostics: Diagnostics.dedupe(diagnostics) }\n } catch (caughtError) {\n diagnostics.push(Diagnostics.from(caughtError))\n return { diagnostics: Diagnostics.dedupe(diagnostics) }\n } finally {\n this.fileManager.hooks.off('upsert', onFileUpsert)\n }\n },\n )\n }\n\n // Returns a fresh object with a lazy `files` getter and a bound `upsertFile`.\n // Caller must use `Object.assign(extra, this.#filesPayload())`, not object spread.\n // Spread would eagerly invoke the getter and freeze a stale snapshot into the payload.\n #filesPayload(): { readonly files: Array<FileNode>; upsertFile: (...files: Array<FileNode>) => Array<FileNode> } {\n const driver = this\n\n return {\n get files() {\n return driver.fileManager.files\n },\n upsertFile: (...files: Array<FileNode>) => driver.fileManager.upsert(...files),\n }\n }\n\n #emitPluginEnd({ plugin, duration, success, error }: { plugin: NormalizedPlugin; duration: number; success: boolean; error?: Error }): Promise<void> | void {\n return this.hooks.emit(\n 'kubb:plugin:end',\n Object.assign({ plugin, duration, success, ...(error ? { error } : {}), config: this.config }, this.#filesPayload()),\n )\n }\n\n /**\n * Streams schemas and operations through every plugin's generators. Each node is run\n * through the plugin's macros (from `this.#transforms`) before the generator sees it,\n * so plugins stay isolated and the hot path stays per-node. Schemas run before operations\n * because the two passes share `flushPending` and the FileProcessor's event emitter.\n * A failing plugin contributes an error diagnostic so the rest of the build continues.\n * Every plugin also contributes a `timing` diagnostic.\n *\n * Plugins run sequentially so `kubb:plugin:end` fires as each plugin completes, instead\n * of all at once after every plugin has marched through the parallel batches together.\n * That ordering is what drives the CLI's `Plugins N/M` counter. Without it the bar would\n * sit at the initial value until the very end of the run.\n *\n * When `this.inputNode` is `null`, every entry still gets a `kubb:plugin:end` so\n * post-plugin listeners (the barrel writer and friends) complete.\n */\n async #runGenerators(\n entries: Array<{ plugin: NormalizedPlugin; context: Omit<GeneratorContext, 'options'>; hrStart: ReturnType<typeof process.hrtime> }>,\n flushPending: () => Promise<void>,\n ): Promise<Array<Diagnostic>> {\n const diagnostics: Array<Diagnostic> = []\n\n if (entries.length === 0) return diagnostics\n\n if (!this.inputNode) {\n for (const { plugin, hrStart } of entries) {\n const duration = getElapsedMs(hrStart)\n diagnostics.push(Diagnostics.performance({ plugin: plugin.name, duration }))\n await this.#emitPluginEnd({ plugin, duration, success: true })\n }\n return diagnostics\n }\n\n const transforms = this.#transforms\n const { schemas, operations } = this.inputNode\n\n type PluginState = {\n plugin: NormalizedPlugin\n generatorContext: Omit<GeneratorContext, 'options'>\n generators: Array<Generator>\n hrStart: ReturnType<typeof process.hrtime>\n failed: boolean\n error: Error | null\n optionsAreStatic: boolean\n allowedSchemaNames: Set<string> | null\n }\n\n const states: Array<PluginState> = entries.map(({ plugin, context, hrStart }) => {\n const { exclude, include, override } = plugin.options\n const hasExclude = Array.isArray(exclude) && exclude.length > 0\n const hasInclude = Array.isArray(include) && include.length > 0\n const hasOverride = Array.isArray(override) && override.length > 0\n return {\n plugin,\n generatorContext: { ...context, resolver: this.getResolver(plugin.name) },\n generators: plugin.generators ?? [],\n hrStart,\n failed: false,\n error: null,\n optionsAreStatic: !hasExclude && !hasInclude && !hasOverride,\n allowedSchemaNames: null,\n }\n })\n\n const emitsSchemaHook = this.hooks.listenerCount('kubb:generate:schema') > 0\n const emitsOperationHook = this.hooks.listenerCount('kubb:generate:operation') > 0\n const emitsOperationsHook = this.hooks.listenerCount('kubb:generate:operations') > 0\n\n // Buffer the streaming adapter's nodes once. Each plugin reads the same buffer\n // instead of re-parsing the document per pass, and the pruning pre-scan below\n // shares it too (previously it iterated its own copies).\n const schemasBuffer: Array<SchemaNode> = await Array.fromAsync(schemas)\n const operationsBuffer: Array<OperationNode> = await Array.fromAsync(operations)\n\n // Pre-scan: plugins with operation-based includes (but no schemaName include) need\n // the reachable schema set. This requires the full schema graph in memory at once,\n // since transitive reachability can't be derived from a single node.\n const pruningStates = states.filter(({ plugin }) => {\n const { include } = plugin.options\n return (include?.some(({ type }) => OPERATION_FILTER_TYPES.has(type)) ?? false) && !(include?.some(({ type }) => type === 'schemaName') ?? false)\n })\n\n if (pruningStates.length > 0) {\n const includedOpsByState = new Map<PluginState, Array<OperationNode>>(pruningStates.map((state) => [state, []]))\n for (const operation of operationsBuffer) {\n for (const state of pruningStates) {\n const { exclude, include, override } = state.plugin.options\n const options = state.generatorContext.resolver.resolveOptions(operation, { options: state.plugin.options, exclude, include, override })\n if (options !== null) includedOpsByState.get(state)?.push(operation)\n }\n }\n\n for (const state of pruningStates) {\n state.allowedSchemaNames = collectUsedSchemaNames(includedOpsByState.get(state) ?? [], schemasBuffer)\n includedOpsByState.delete(state)\n }\n }\n\n // Apply the plugin's macros, then resolve options (skipping the resolver when\n // optionsAreStatic). Returns null when include/exclude/override rules out the node.\n // The per-node dispatch and the collected-operations tail both go through this so\n // they agree on what a plugin sees.\n const resolveForPlugin = <TNode extends SchemaNode | OperationNode>(\n state: PluginState,\n node: TNode,\n ): { transformedNode: TNode; options: NormalizedPlugin['options'] } | null => {\n const { plugin, generatorContext } = state\n const transformedNode = transforms.applyTo(plugin.name, node)\n if (state.optionsAreStatic) return { transformedNode, options: plugin.options }\n\n const { exclude, include, override } = plugin.options\n const options = generatorContext.resolver.resolveOptions(transformedNode, { options: plugin.options, exclude, include, override })\n if (options === null) return null\n return { transformedNode, options }\n }\n\n // Schema and operation passes share this body. They differ only in which generator\n // method runs, which hook is emitted, and the schema-only `allowedSchemaNames` prune\n // (operations don't carry that constraint).\n const dispatchNode = async <TNode extends SchemaNode | OperationNode>(\n state: PluginState,\n node: TNode,\n dispatch: {\n method: 'schema' | 'operation'\n checkAllowedNames: boolean\n emit: ((node: TNode, ctx: GeneratorContext) => Promise<void> | void) | null\n },\n ): Promise<void> => {\n if (state.failed) return\n try {\n const resolved = resolveForPlugin(state, node)\n if (!resolved) return\n\n const { transformedNode, options } = resolved\n if (\n dispatch.checkAllowedNames &&\n state.allowedSchemaNames !== null &&\n 'name' in transformedNode &&\n transformedNode.name &&\n !state.allowedSchemaNames.has(transformedNode.name)\n ) {\n return\n }\n\n const ctx = { ...state.generatorContext, options }\n for (const gen of state.generators) {\n const run = gen[dispatch.method] as ((node: TNode, ctx: GeneratorContext) => unknown) | undefined\n if (!run) continue\n const raw = run(transformedNode, ctx)\n const result = isPromise(raw) ? await raw : raw\n const applied = this.dispatch({ result, renderer: gen.renderer })\n if (isPromise(applied)) await applied\n }\n if (dispatch.emit) await dispatch.emit(transformedNode, ctx)\n } catch (caughtError) {\n state.failed = true\n state.error = caughtError as Error\n }\n }\n\n const schemaDispatch = {\n method: 'schema',\n checkAllowedNames: true,\n emit: emitsSchemaHook ? (node: SchemaNode, ctx: GeneratorContext) => this.hooks.emit('kubb:generate:schema', node, ctx) : null,\n } as const\n const operationDispatch = {\n method: 'operation',\n checkAllowedNames: false,\n emit: emitsOperationHook ? (node: OperationNode, ctx: GeneratorContext) => this.hooks.emit('kubb:generate:operation', node, ctx) : null,\n } as const\n\n for (const state of states) {\n // Skip building the aggregated operations array when this plugin doesn't consume it.\n // Saves an N-sized allocation when the plugin only defines per-node `gen.operation`.\n const needsCollectedOperations = emitsOperationsHook || state.generators.some((gen) => !!gen.operations)\n const collectedOperations: Array<OperationNode> | undefined = needsCollectedOperations ? [] : undefined\n\n // Run schemas before operations: the two passes share `flushPending` and the\n // FileProcessor's event emitter, so running them concurrently would interleave\n // `kubb:files:processing:start|end` events and race on the shared dirty list.\n await forBatches(schemasBuffer, (nodes) => Promise.all(nodes.map((node) => dispatchNode(state, node, schemaDispatch))), {\n concurrency: SCHEMA_PARALLEL,\n flush: flushPending,\n })\n\n await forBatches(\n operationsBuffer,\n (nodes) => {\n if (needsCollectedOperations) collectedOperations?.push(...nodes)\n return Promise.all(nodes.map((node) => dispatchNode(state, node, operationDispatch)))\n },\n { concurrency: SCHEMA_PARALLEL, flush: flushPending },\n )\n\n if (!state.failed && needsCollectedOperations) {\n try {\n const { plugin, generatorContext, generators } = state\n const ctx = { ...generatorContext, options: plugin.options }\n // Match what the per-node dispatch passes to gen.operation(): the transformed node,\n // already filtered by excludes/includes/overrides.\n const ops = collectedOperations ?? []\n const pluginOperations = ops.reduce<Array<OperationNode>>((acc, node) => {\n const resolved = resolveForPlugin(state, node)\n if (resolved) acc.push(resolved.transformedNode)\n return acc\n }, [])\n for (const gen of generators) {\n if (!gen.operations) continue\n const result = await gen.operations(pluginOperations, ctx)\n await this.dispatch({ result, renderer: gen.renderer })\n }\n await this.hooks.emit('kubb:generate:operations', pluginOperations, ctx)\n } catch (caughtError) {\n state.failed = true\n state.error = caughtError as Error\n }\n }\n\n const duration = getElapsedMs(state.hrStart)\n await this.#emitPluginEnd({ plugin: state.plugin, duration, success: !state.failed, error: state.failed && state.error ? state.error : undefined })\n\n if (state.failed && state.error) {\n diagnostics.push({ ...Diagnostics.from(state.error), plugin: state.plugin.name })\n }\n diagnostics.push(Diagnostics.performance({ plugin: state.plugin.name, duration }))\n }\n\n return diagnostics\n }\n\n /**\n * Stores whatever a generator method or `kubb:generate:*` hook returned.\n *\n * - An `Array<FileNode>` goes straight into `fileManager` via `upsert`.\n * - A renderer element runs through `renderer` (the renderer factory, e.g. JSX) and the\n * produced files go to `fileManager.upsert`.\n * - A falsy result is treated as a no-op. The generator wrote files itself via\n * `ctx.upsertFile`.\n *\n * Pass `renderer` when the result may be a renderer element. Generators that only return\n * `Array<FileNode>` do not need one.\n */\n async dispatch<TElement = unknown>({\n result,\n renderer,\n }: {\n result: TElement | Array<FileNode> | undefined | null\n renderer?: RendererFactory<TElement> | null\n }): Promise<void> {\n if (!result) return\n\n if (Array.isArray(result)) {\n this.fileManager.upsert(...(result as Array<FileNode>))\n return\n }\n\n if (!renderer) {\n return\n }\n\n using instance = renderer()\n if (instance.stream) {\n for (const file of instance.stream(result)) {\n this.fileManager.upsert(file)\n }\n return\n }\n\n await instance.render(result)\n this.fileManager.upsert(...instance.files)\n }\n\n /**\n * Removes every listener the driver added. Listeners attached directly to `hooks` from outside\n * the driver survive. Called at the end of a build to prevent leaks across repeated builds.\n *\n * @internal\n */\n dispose(): void {\n for (const [event, handler] of this.#listeners) {\n this.hooks.off(event, handler as HookListener<KubbHooks[typeof event]>)\n }\n this.#listeners.length = 0\n this.#eventGeneratorPlugins.clear()\n this.#transforms.dispose()\n // Release resolver closures. The driver is rebuilt for each build() call\n // so there is no value in retaining these maps after disposal.\n this.#resolvers.clear()\n this.#defaultResolvers.clear()\n // Release the FileNode cache and parsed adapter graph so memory is reclaimed\n // between builds. The returned `BuildOutput.files` array still references any\n // FileNodes the caller needs to inspect.\n this.fileManager.dispose()\n this.inputNode = null\n this.#adapterSource = null\n }\n\n [Symbol.dispose](): void {\n this.dispose()\n }\n\n #getDefaultResolver = memoize(\n this.#defaultResolvers,\n (pluginName: string): Resolver => defineResolver<PluginFactoryOptions>(() => ({ name: 'default', pluginName })),\n )\n\n /**\n * Merges `partial` with the plugin's default resolver and stores the result.\n * Also mirrors it onto `plugin.resolver` so callers using `getPlugin(name).resolver`\n * get the up-to-date resolver without going through `getResolver()`.\n */\n setPluginResolver(pluginName: string, partial: Partial<Resolver>): void {\n const defaultResolver = this.#getDefaultResolver(pluginName)\n const merged = { ...defaultResolver, ...partial }\n this.#resolvers.set(pluginName, merged)\n const plugin = this.plugins.get(pluginName)\n if (plugin) {\n plugin.resolver = merged\n }\n }\n\n /**\n * Returns the resolver for the given plugin.\n *\n * Resolution order: dynamic resolver set via `setPluginResolver` → static resolver on the\n * plugin → lazily created default resolver (identity name, no path transforms).\n */\n getResolver<TName extends keyof Kubb.PluginRegistry>(pluginName: TName): Kubb.PluginRegistry[TName]['resolver']\n getResolver<TResolver extends Resolver = Resolver>(pluginName: string): TResolver\n getResolver(pluginName: string): Resolver {\n return this.#resolvers.get(pluginName) ?? this.plugins.get(pluginName)?.resolver ?? this.#getDefaultResolver(pluginName)\n }\n\n getContext<TOptions extends PluginFactoryOptions>(plugin: NormalizedPlugin<TOptions>): Omit<GeneratorContext<TOptions>, 'options'> {\n const driver = this\n\n // Collect into the active build only. The host renders each collected diagnostic once after the\n // build (the CLI via `Diagnostics.emit`, the agent via its post-build loop), so emitting a live\n // `kubb:error`/`kubb:warn`/`kubb:info` here would render it twice.\n const report = (diagnostic: Omit<ProblemDiagnostic, 'plugin'>): void => {\n Diagnostics.report({ ...diagnostic, plugin: plugin.name })\n }\n\n return {\n config: driver.config,\n get root(): string {\n return resolve(driver.config.root, driver.config.output.path)\n },\n hooks: driver.hooks,\n plugin,\n getPlugin: driver.getPlugin.bind(driver),\n // Close over the owning plugin so a missing dependency error names who required it.\n requirePlugin: ((name: string) => driver.requirePlugin(name, { requiredBy: plugin.name })) as GeneratorContext<TOptions>['requirePlugin'],\n getResolver: driver.getResolver.bind(driver),\n driver,\n addFile: async (...files: Array<FileNode>) => {\n driver.fileManager.add(...files)\n },\n upsertFile: async (...files: Array<FileNode>) => {\n driver.fileManager.upsert(...files)\n },\n get meta(): InputMeta {\n return driver.inputNode?.meta ?? { circularNames: [], enumNames: [] }\n },\n get adapter(): Adapter {\n // Generators only read `adapter` during AST hooks, which run after the\n // adapter is set, so it is guaranteed defined at read time.\n return driver.adapter!\n },\n get resolver() {\n return driver.getResolver(plugin.name)\n },\n warn(message: string) {\n report({ code: Diagnostics.code.pluginWarning, severity: 'warning', message })\n },\n error(error: string | Error) {\n const cause = typeof error === 'string' ? undefined : error\n report({ code: Diagnostics.code.pluginFailed, severity: 'error', message: typeof error === 'string' ? error : error.message, cause })\n },\n info(message: string) {\n report({ code: Diagnostics.code.pluginInfo, severity: 'info', message })\n },\n }\n }\n\n getPlugin<TName extends keyof Kubb.PluginRegistry>(pluginName: TName): Plugin<Kubb.PluginRegistry[TName]> | undefined\n getPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>(pluginName: string): Plugin<TOptions> | undefined\n getPlugin(pluginName: string): Plugin | undefined {\n return this.plugins.get(pluginName)\n }\n\n /**\n * Like `getPlugin` but throws a descriptive error when the plugin is not found.\n */\n requirePlugin<TName extends keyof Kubb.PluginRegistry>(pluginName: TName, context?: RequirePluginContext): Plugin<Kubb.PluginRegistry[TName]>\n requirePlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>(pluginName: string, context?: RequirePluginContext): Plugin<TOptions>\n requirePlugin(pluginName: string, context?: RequirePluginContext): Plugin {\n const plugin = this.plugins.get(pluginName)\n if (!plugin) {\n const requiredBy = context?.requiredBy\n throw new Diagnostics.Error({\n code: Diagnostics.code.pluginNotFound,\n severity: 'error',\n message: requiredBy\n ? `Plugin \"${pluginName}\" is required by \"${requiredBy}\" but not found. Make sure it is included in your Kubb config.`\n : `Plugin \"${pluginName}\" is required but not found. Make sure it is included in your Kubb config.`,\n help: requiredBy\n ? `Add \"${pluginName}\" to the \\`plugins\\` array in kubb.config.ts (required by \"${requiredBy}\"), or remove the dependency on it.`\n : `Add \"${pluginName}\" to the \\`plugins\\` array in kubb.config.ts, or remove the dependency on it.`,\n location: { kind: 'config' },\n })\n }\n return plugin\n }\n}\n\nfunction inputToAdapterSource(config: Config): AdapterSource {\n const input = config.input\n if (!input) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.inputRequired,\n severity: 'error',\n message: 'An adapter is configured without an input.',\n help: 'Provide `input.path` (a file or URL) or `input.data` (an inline spec) in your Kubb config.',\n location: { kind: 'config' },\n })\n }\n\n if ('data' in input) {\n return { type: 'data', data: input.data }\n }\n\n if (Url.canParse(input.path)) {\n return { type: 'path', path: input.path }\n }\n\n const resolved = resolve(config.root, input.path)\n\n return { type: 'path', path: resolved }\n}\n","import { access, glob, readFile, rm } from 'node:fs/promises'\nimport { join, relative, resolve } from 'node:path'\nimport { clean, runtime, toPosixPath, write } from '@internals/utils'\nimport { createStorage } from '../createStorage.ts'\n\n/**\n * Built-in filesystem storage driver.\n *\n * This is the default storage when no `storage` option is configured in the root config.\n * Keys are resolved against `process.cwd()`, so root-relative paths such as\n * `src/gen/api/getPets.ts` are written to the correct location without extra configuration.\n *\n * Writes are deduplicated and directory-safe:\n * - leading and trailing whitespace is trimmed before writing\n * - the write is skipped when the file content is already identical\n * - missing parent directories are created automatically\n * - Bun's native file API is used when running under Bun\n *\n * @example\n * ```ts\n * import { fsStorage } from '@kubb/core'\n * import { defineConfig } from 'kubb'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * storage: fsStorage(),\n * })\n * ```\n */\nexport const fsStorage = createStorage(() => ({\n name: 'fs',\n async hasItem(key: string) {\n try {\n await access(resolve(key))\n return true\n } catch (_error) {\n return false\n }\n },\n async getItem(key: string) {\n try {\n return await readFile(resolve(key), 'utf8')\n } catch (_error) {\n return null\n }\n },\n async setItem(key: string, value: string) {\n await write(resolve(key), value, { sanity: false })\n },\n async removeItem(key: string) {\n await rm(resolve(key), { force: true })\n },\n async getKeys(base?: string) {\n const resolvedBase = resolve(base ?? process.cwd())\n\n if (runtime.isBun) {\n const bunGlob = new Bun.Glob('**/*')\n return Array.fromAsync(bunGlob.scan({ cwd: resolvedBase, onlyFiles: true, dot: true }))\n }\n\n const keys: Array<string> = []\n try {\n for await (const entry of glob('**/*', { cwd: resolvedBase, withFileTypes: true })) {\n if (entry.isFile()) {\n keys.push(toPosixPath(relative(resolvedBase, join(entry.parentPath, entry.name))))\n }\n }\n } catch (_error) {\n // base directory does not exist yet\n }\n\n return keys\n },\n async clear(base?: string) {\n if (!base) {\n return\n }\n\n await clean(resolve(base))\n },\n}))\n","import { resolve } from 'node:path'\nimport { AsyncEventEmitter, BuildError } from '@internals/utils'\nimport { HOOK_LISTENERS_PER_PLUGIN } from './constants.ts'\nimport { Diagnostics } from './diagnostics.ts'\nimport { createStorage, type Storage } from './createStorage.ts'\nimport { KubbDriver } from './KubbDriver.ts'\nimport { fsStorage } from './storages/fsStorage.ts'\nimport type { BuildOutput, Config, KubbHooks, UserConfig } from './types.ts'\n\n/**\n * Builds a `Storage` view scoped to the file paths produced by the current build.\n * Reads delegate to the underlying `storage` so source bytes stay where they were\n * written. Writes register the key so subsequent reads and `getKeys` are scoped\n * to this build's output.\n */\nfunction createSourcesView(storage: Storage): Storage {\n const paths = new Set<string>()\n\n return createStorage(() => ({\n name: `${storage.name}:sources`,\n async hasItem(key: string) {\n return paths.has(key) && (await storage.hasItem(key))\n },\n async getItem(key: string) {\n return paths.has(key) ? storage.getItem(key) : null\n },\n async setItem(key: string, value: string) {\n paths.add(key)\n await storage.setItem(key, value)\n },\n async removeItem(key: string) {\n paths.delete(key)\n await storage.removeItem(key)\n },\n async getKeys(base?: string) {\n if (!base) return [...paths]\n const result: Array<string> = []\n for (const key of paths) {\n if (key.startsWith(base)) result.push(key)\n }\n return result\n },\n async clear() {\n paths.clear()\n await storage.clear()\n },\n }))()\n}\n\nfunction resolveConfig(userConfig: UserConfig): Config {\n return {\n ...userConfig,\n root: userConfig.root || process.cwd(),\n parsers: userConfig.parsers ?? [],\n output: {\n format: false,\n lint: false,\n extension: { '.ts': '.ts' },\n defaultBanner: 'simple',\n ...userConfig.output,\n },\n storage: userConfig.storage ?? fsStorage(),\n reporters: userConfig.reporters ?? [],\n plugins: userConfig.plugins ?? [],\n }\n}\n\ntype CreateKubbOptions = {\n hooks?: AsyncEventEmitter<KubbHooks>\n}\n\n/**\n * Kubb code-generation instance bound to a single config entry. Resolves the user\n * config in the constructor, so `config` is available right away, and shares `hooks`,\n * `storage`, and `driver` across the `setup → build` lifecycle.\n *\n * `createKubb` takes a plain config object (the shape `defineConfig` produces),\n * not a fluent builder.\n *\n * Attach event listeners to `.hooks` before calling `setup()` or `build()`.\n *\n * @example\n * ```ts\n * const kubb = createKubb(userConfig)\n * kubb.hooks.on('kubb:plugin:end', ({ plugin, duration }) => console.log(plugin.name, duration))\n * const { files, diagnostics } = await kubb.safeBuild()\n * ```\n */\nexport class Kubb {\n readonly hooks: AsyncEventEmitter<KubbHooks>\n readonly config: Config\n #driver: KubbDriver | null = null\n #storage: Storage | null = null\n\n constructor(userConfig: UserConfig, options: CreateKubbOptions = {}) {\n this.config = resolveConfig(userConfig)\n this.hooks = options.hooks ?? new AsyncEventEmitter<KubbHooks>()\n }\n\n get storage(): Storage {\n if (!this.#storage) throw new Error('[kubb] setup() must be called before accessing storage')\n return this.#storage\n }\n\n get driver(): KubbDriver {\n if (!this.#driver) throw new Error('[kubb] setup() must be called before accessing driver')\n return this.#driver\n }\n\n /**\n * Initializes the driver and storage. `build()` calls this automatically.\n */\n async setup(): Promise<void> {\n const config = this.config\n const driver = new KubbDriver(config, { hooks: this.hooks })\n const storage = createSourcesView(config.storage)\n\n // Each generator a plugin registers adds a listener to the shared hooks emitter, so size the\n // ceiling to the plugin count. Without this, a multi-generator plugin set trips Node's\n // EventEmitter leak warning at the default 10.\n this.hooks.setMaxListeners(Math.max(10, config.plugins.length * HOOK_LISTENERS_PER_PLUGIN))\n\n if (config.output.clean) {\n await config.storage.clear(resolve(config.root, config.output.path))\n }\n\n await driver.setup()\n\n this.#driver = driver\n this.#storage = storage\n }\n\n /**\n * Runs the full pipeline and throws on any plugin error.\n * Automatically calls `setup()` if needed.\n */\n async build(): Promise<BuildOutput> {\n const out = await this.safeBuild()\n if (Diagnostics.hasError(out.diagnostics)) {\n const errors = out.diagnostics\n .filter(Diagnostics.isProblem)\n .filter((diagnostic) => diagnostic.severity === 'error')\n .map((diagnostic) => diagnostic.cause ?? new Diagnostics.Error(diagnostic))\n throw new BuildError(`Build failed with ${errors.length} ${errors.length === 1 ? 'error' : 'errors'}`, { errors })\n }\n return out\n }\n\n /**\n * Runs the full pipeline and captures errors in `BuildOutput` instead of throwing.\n * Automatically calls `setup()` if needed. This is the canonical call: it never throws on\n * plugin errors, so callers stay in control of how failures surface.\n */\n async safeBuild(): Promise<BuildOutput> {\n if (!this.#driver) await this.setup()\n using cleanup = this\n const driver = cleanup.driver\n const storage = cleanup.storage\n const { diagnostics } = await driver.run({ storage })\n\n return { diagnostics, files: driver.fileManager.files, driver, storage }\n }\n\n dispose(): void {\n this.#driver?.dispose()\n }\n\n [Symbol.dispose](): void {\n this.dispose()\n }\n}\n\n/**\n * Constructs a {@link Kubb} build orchestrator from a user config. Equivalent\n * to `new Kubb(userConfig, options)` and the canonical public entry point.\n *\n * @example\n * ```ts\n * import { createKubb } from '@kubb/core'\n * import { adapterOas } from '@kubb/adapter-oas'\n * import { pluginTs } from '@kubb/plugin-ts'\n *\n * const kubb = createKubb({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * adapter: adapterOas(),\n * plugins: [pluginTs()],\n * })\n *\n * await kubb.build()\n * ```\n */\nexport function createKubb(userConfig: UserConfig, options: CreateKubbOptions = {}): Kubb {\n return new Kubb(userConfig, options)\n}\n","import type { Config } from './types.ts'\nimport type { Diagnostic } from './diagnostics.ts'\n\n/**\n * Numeric log-level thresholds used internally to compare verbosity.\n *\n * Higher numbers are more verbose.\n */\nexport const logLevel = {\n silent: Number.NEGATIVE_INFINITY,\n error: 0,\n warn: 1,\n info: 3,\n verbose: 4,\n} as const\n\n/**\n * A built-in reporter that renders a run's output, independent of the live logger view.\n *\n * - `cli` renders the per-config summary to the terminal (the default).\n * - `json` writes a machine-readable report to stdout, for CI.\n * - `file` writes a config's diagnostics to `.kubb/kubb-<name>-<timestamp>.log`.\n */\nexport type ReporterName = 'cli' | 'json' | 'file'\n\n/**\n * One config's outcome within a run, as handed to a {@link Reporter}.\n */\nexport type GenerationResult = {\n config: Config\n /**\n * Diagnostics collected while generating this config.\n */\n diagnostics: Array<Diagnostic>\n /**\n * Number of files written for this config.\n */\n filesCreated: number\n status: 'success' | 'failed'\n /**\n * `process.hrtime()` snapshot taken when this config started generating.\n */\n hrStart: [number, number]\n}\n\n/**\n * Render settings passed alongside the {@link GenerationResult}. These are not part of the run\n * data, such as the output verbosity.\n */\nexport type ReporterContext = {\n /**\n * Output verbosity. Use the `logLevel` constants exported from `@kubb/core`\n * (`silent`, `error`, `warn`, `info`, `verbose`).\n */\n logLevel: (typeof logLevel)[keyof typeof logLevel]\n}\n\n/**\n * Host-facing reporter, as installed onto a run. Unlike a Logger (the live TUI view), a reporter\n * never sees the event emitter. `report` runs once per config. `drain`, when present, runs once\n * after the last config.\n */\nexport type Reporter = {\n /**\n * Display name, matching a {@link ReporterName} for the built-ins.\n */\n name: string\n /**\n * Called once per config with that config's result and the render context.\n */\n report: (result: GenerationResult, context: ReporterContext) => void | Promise<void>\n /**\n * Optional finalizer called once after the run's last config. The host wires it to\n * `kubb:lifecycle:end`. {@link createReporter} closes it over the values that `report` returned.\n */\n drain?: (context: ReporterContext) => void | Promise<void>\n}\n\n/**\n * Reporter definition passed to {@link createReporter}. `report` returns the value to collect for\n * this config (e.g. a built report), and the optional `drain` receives the collected reports to\n * emit as one document. `T` is inferred from `report`'s return type.\n */\nexport type UserReporter<T = void> = {\n name: string\n report: (result: GenerationResult, context: ReporterContext) => T | Promise<T>\n drain?: (context: ReporterContext, reports: Array<T>) => void | Promise<void>\n}\n\n/**\n * Defines a reporter. When the definition has a `drain`, the returned reporter buffers each value\n * `report` returns and hands the array to `drain` once, then clears it. Without a `drain`, nothing\n * is buffered. Wiring the reporter onto the run's events is the host's job, so the reporter only\n * ever deals with a {@link GenerationResult}.\n *\n * @example\n * ```ts\n * import { createReporter, Diagnostics } from '@kubb/core'\n *\n * export const jsonReporter = createReporter({\n * name: 'json',\n * report(result) {\n * return { status: Diagnostics.hasError(result.diagnostics) ? 'failed' : 'success', diagnostics: result.diagnostics }\n * },\n * drain(context, reports) {\n * process.stdout.write(`${JSON.stringify(reports, null, 2)}\\n`)\n * },\n * })\n * ```\n */\nexport function createReporter<T = void>(reporter: UserReporter<T>): Reporter {\n const drain = reporter.drain\n if (!drain) {\n return {\n name: reporter.name,\n async report(result, context) {\n await reporter.report(result, context)\n },\n }\n }\n\n const reports: Array<T> = []\n\n return {\n name: reporter.name,\n async report(result, context) {\n reports.push(await reporter.report(result, context))\n },\n async drain(context) {\n await drain(context, reports)\n reports.length = 0\n },\n }\n}\n","import { resolve } from 'node:path'\nimport { getElapsedMs } from '@internals/utils'\nimport type { GenerationResult } from '../createReporter.ts'\nimport { Diagnostics, type SerializedDiagnostic } from '../diagnostics.ts'\n\n/**\n * One plugin's elapsed time, derived from a `performance` diagnostic.\n */\ntype ReportTiming = {\n plugin: string\n durationMs: number\n}\n\n/**\n * The normalized result of generating one config, shared by every reporter. Each reporter renders\n * the same {@link Report} in its own format (the `cli` summary, the `json` document, the `file`\n * log), so they always agree on the numbers. Build it with {@link buildReport}.\n */\nexport type Report = {\n /**\n * The config name, or an empty string when it is unnamed.\n */\n name: string\n status: 'success' | 'failed'\n plugins: {\n passed: number\n /**\n * Names of the plugins that failed.\n */\n failed: Array<string>\n total: number\n }\n counts: {\n errors: number\n warnings: number\n infos: number\n }\n filesCreated: number\n /**\n * Wall-clock time spent generating this config, in milliseconds.\n */\n durationMs: number\n /**\n * Absolute output directory the files were written to.\n */\n output: string\n /**\n * Per-plugin durations, slowest first.\n */\n timings: Array<ReportTiming>\n /**\n * The build problems, serialized to their JSON-safe fields plus a `docsUrl`.\n */\n diagnostics: Array<SerializedDiagnostic>\n}\n\n/**\n * Builds the normalized {@link Report} for one config from its {@link GenerationResult}. Splits the\n * diagnostics into problems and per-plugin timings (slowest first) and derives the plugin and issue\n * counts, so every reporter renders the same data.\n */\nexport function buildReport(result: GenerationResult): Report {\n const { config, diagnostics, filesCreated, status, hrStart } = result\n\n const failed = Diagnostics.failedPlugins(diagnostics)\n const total = config.plugins?.length ?? 0\n const counts = Diagnostics.count(diagnostics)\n const problems = diagnostics.filter(Diagnostics.isProblem)\n const timings = diagnostics\n .filter(Diagnostics.isPerformance)\n .sort((a, b) => b.duration - a.duration)\n .map((diagnostic) => ({ plugin: diagnostic.plugin, durationMs: diagnostic.duration }))\n\n return {\n name: config.name ?? '',\n status,\n plugins: { passed: total - failed.length, failed, total },\n counts,\n filesCreated,\n durationMs: getElapsedMs(hrStart),\n output: resolve(config.root, config.output.path),\n timings,\n diagnostics: problems.map((diagnostic) => Diagnostics.serialize(diagnostic)),\n }\n}\n","import { styleText } from 'node:util'\nimport { formatMs, randomCliColor } from '@internals/utils'\nimport { SUMMARY_MAX_BAR_LENGTH, SUMMARY_TIME_SCALE_DIVISOR } from '../constants.ts'\nimport { createReporter, logLevel as logLevelMap } from '../createReporter.ts'\nimport { buildReport, type Report } from './report.ts'\n\n/**\n * Builds the vitest/jest-style summary for one {@link Report}: right-aligned dim labels with\n * `N passed (total)` counts, and a per-plugin `Timings` section when `showTimings`.\n */\nfunction buildSummaryLines(report: Report, { showTimings }: { showTimings: boolean }): Array<string> {\n const { status, plugins, counts, filesCreated, durationMs, output, timings } = report\n\n const rows: Array<[label: string, value: string]> = []\n\n rows.push([\n 'Plugins',\n status === 'success'\n ? `${styleText('green', `${plugins.passed} passed`)} (${plugins.total})`\n : `${styleText('green', `${plugins.passed} passed`)} | ${styleText('red', `${plugins.failed.length} failed`)} (${plugins.total})`,\n ])\n\n if (status === 'failed' && plugins.failed.length > 0) {\n rows.push(['Failed', plugins.failed.map((name) => randomCliColor(name)).join(', ')])\n }\n\n if (counts.errors > 0 || counts.warnings > 0) {\n const issues = [\n counts.errors > 0 ? styleText('red', `${counts.errors} ${counts.errors === 1 ? 'error' : 'errors'}`) : undefined,\n counts.warnings > 0 ? styleText('yellow', `${counts.warnings} ${counts.warnings === 1 ? 'warning' : 'warnings'}`) : undefined,\n ]\n .filter(Boolean)\n .join(' | ')\n rows.push(['Issues', issues])\n }\n\n rows.push(['Files', `${styleText('green', String(filesCreated))} generated`])\n rows.push(['Duration', styleText('green', formatMs(durationMs))])\n rows.push(['Output', output])\n\n const labelWidth = Math.max(...rows.map(([label]) => label.length), timings.length > 0 ? 'Timings'.length : 0)\n const lines = rows.map(([label, value]) => `${styleText('dim', label.padStart(labelWidth))} ${value}`)\n\n if (showTimings && timings.length > 0) {\n const nameWidth = Math.max(0, ...timings.map((timing) => timing.plugin.length))\n const indent = ' '.repeat(labelWidth + 2)\n\n lines.push(styleText('dim', 'Timings'.padStart(labelWidth)))\n for (const timing of timings) {\n const timeStr = formatMs(timing.durationMs)\n const barLength = Math.min(Math.ceil(timing.durationMs / SUMMARY_TIME_SCALE_DIVISOR), SUMMARY_MAX_BAR_LENGTH)\n const bar = styleText('dim', '█'.repeat(barLength))\n lines.push(`${indent}${styleText('dim', '•')} ${timing.plugin.padEnd(nameWidth)} ${bar} ${timeStr}`)\n }\n }\n\n return lines\n}\n\n/**\n * Renders the summary as plain `console.log` lines so it works in every CLI (no clack/TTY\n * dependency): a blank line, the config name colored by status, then the summary rows.\n */\nfunction renderSummary(lines: ReadonlyArray<string>, { title, status }: { title: string; status: 'success' | 'failed' }): void {\n console.log('')\n if (title) {\n console.log(styleText(status === 'failed' ? 'red' : 'green', title))\n }\n for (const line of lines) {\n console.log(line)\n }\n}\n\n/**\n * The default `cli` reporter. Renders the {@link Report} for each config as it finishes, independent\n * of the live logger view. Suppressed at `silent`. The `verbose` level adds the per-plugin timings.\n */\nexport const cliReporter = createReporter({\n name: 'cli',\n report(result, { logLevel }) {\n if (logLevel <= logLevelMap.silent) {\n return\n }\n\n const report = buildReport(result)\n const lines = buildSummaryLines(report, { showTimings: logLevel >= logLevelMap.verbose })\n renderSummary(lines, { title: report.name, status: report.status })\n },\n})\n","import { relative, resolve } from 'node:path'\nimport process from 'node:process'\nimport { stripVTControlCharacters } from 'node:util'\nimport { formatMs, write } from '@internals/utils'\nimport { createReporter } from '../createReporter.ts'\nimport { type Diagnostic, Diagnostics } from '../diagnostics.ts'\nimport { buildReport, type Report } from './report.ts'\n\n/**\n * Builds the `## Summary` section: the same counts the cli and json reporters expose, as a list of\n * `label value` rows with the labels padded to a common width.\n */\nfunction buildSummarySection(report: Report): Array<string> {\n const { status, plugins, counts, filesCreated, durationMs, output } = report\n\n const rows: Array<[label: string, value: string]> = [\n ['Status', status],\n [\n 'Plugins',\n status === 'success' ? `${plugins.passed} passed (${plugins.total})` : `${plugins.passed} passed | ${plugins.failed.length} failed (${plugins.total})`,\n ],\n ]\n\n if (plugins.failed.length > 0) {\n rows.push(['Failed', plugins.failed.join(', ')])\n }\n\n rows.push(['Issues', `${counts.errors} errors | ${counts.warnings} warnings | ${counts.infos} infos`])\n rows.push(['Files', `${filesCreated} generated`])\n rows.push(['Duration', formatMs(durationMs)])\n rows.push(['Output', output])\n\n const labelWidth = Math.max(...rows.map(([label]) => label.length))\n const lines = rows.map(([label, value]) => ` ${label.padEnd(labelWidth)} ${value}`)\n\n return ['## Summary', '', ...lines]\n}\n\n/**\n * Builds the `## Problems` section: each problem rendered in the miette block format, blocks\n * separated by a blank line. Returns an empty array when there are no problems, so the caller\n * can drop the heading.\n */\nfunction buildProblemSection(diagnostics: ReadonlyArray<Diagnostic>): Array<string> {\n const problems = diagnostics.filter(Diagnostics.isProblem)\n if (problems.length === 0) {\n return []\n }\n\n const blocks = problems.map((diagnostic) => Diagnostics.formatLines(diagnostic).join('\\n'))\n return ['## Problems', '', blocks.join('\\n\\n')]\n}\n\n/**\n * Builds the `## Timings` section from a {@link Report}: one `plugin duration` row per record,\n * slowest first with the plugin names left-aligned and the durations right-aligned. Returns an\n * empty array when there are no timings.\n */\nfunction buildTimingSection(report: Report): Array<string> {\n const { timings } = report\n if (timings.length === 0) {\n return []\n }\n\n const nameWidth = Math.max(...timings.map((timing) => timing.plugin.length))\n const durations = timings.map((timing) => formatMs(timing.durationMs))\n const durationWidth = Math.max(...durations.map((duration) => duration.length))\n const rows = timings.map((timing, index) => ` ${timing.plugin.padEnd(nameWidth)} ${durations[index]!.padStart(durationWidth)}`)\n\n return ['## Timings', '', ...rows]\n}\n\n/**\n * The `file` reporter. Writes a config's {@link Report} to `.kubb/kubb-<name>-<timestamp>.log` as a\n * plain-text document: a `# <name> — <timestamp>` header, a `## Summary` with the same counts the\n * cli and json reporters expose, a `## Problems` section in the miette block format, and a\n * `## Timings` section. Selected with `--reporter file` (or `reporters: ['file']`).\n *\n * @note It captures the collected diagnostics once a config finishes, not the live\n * `kubb:info`/`kubb:plugin` event stream. Color is stripped so the file stays plain text even when\n * the run is attached to a TTY.\n */\nexport const fileReporter = createReporter({\n name: 'file',\n async report(result) {\n const { diagnostics, config } = result\n if (diagnostics.length === 0) {\n return\n }\n\n const report = buildReport(result)\n const header = config.name ? `# ${config.name} — ${new Date().toISOString()}` : `# ${new Date().toISOString()}`\n const sections = [buildSummarySection(report), buildProblemSection(diagnostics), buildTimingSection(report)].filter((section) => section.length > 0)\n const content = stripVTControlCharacters([header, ...sections.map((section) => section.join('\\n'))].join('\\n\\n'))\n\n const baseName = `${['kubb', config.name, Date.now()].filter(Boolean).join('-')}.log`\n const pathName = resolve(process.cwd(), '.kubb', baseName)\n\n await write(pathName, `${content}\\n`)\n console.error(`Debug log written to ${relative(process.cwd(), pathName)}`)\n },\n})\n","import process from 'node:process'\nimport { createReporter } from '../createReporter.ts'\nimport { buildReport } from './report.ts'\n\n/**\n * The `json` reporter. `report` returns one config's {@link Report}, which {@link createReporter}\n * buffers, and `drain` writes them as a single pretty-printed JSON array on `kubb:lifecycle:end`.\n * Buffering keeps a multi-config run one valid JSON document on stdout instead of concatenated\n * objects that would break `jq .`. The terminal reporter is suppressed while `json` is active so\n * stdout stays valid JSON.\n */\nexport const jsonReporter = createReporter({\n name: 'json',\n report(result) {\n return buildReport(result)\n },\n drain(_context, reports) {\n process.stdout.write(`${JSON.stringify(reports, null, 2)}\\n`)\n },\n})\n","import type { FileNode } from '@kubb/ast'\n\n/**\n * Minimal interface any Kubb renderer must satisfy.\n *\n * `TElement` is the type the renderer accepts, for example `KubbReactElement`\n * for `@kubb/renderer-jsx` or a custom type for your own renderer. Defaults to\n * `unknown` so generators that don't care about the element type work without\n * specifying it.\n */\nexport type Renderer<TElement = unknown> = {\n /**\n * Renders `element` and populates {@link files} with the resulting {@link FileNode} objects.\n * Called once per render cycle. Must resolve before {@link files} is read.\n */\n render(element: TElement): Promise<void>\n /**\n * Accumulated {@link FileNode} results produced by the last {@link render} call.\n * Not populated when {@link stream} is implemented.\n */\n readonly files: Array<FileNode>\n /**\n * When present, core calls this instead of {@link render} and {@link files},\n * forwarding each file to `FileManager` as soon as it is ready.\n */\n stream?(element: TElement): Iterable<FileNode>\n /**\n * Disposer hook so renderers participate in `using` blocks: `using r = rendererFactory()`\n * runs cleanup on every exit path, including thrown errors.\n */\n [Symbol.dispose](): void\n}\n\n/**\n * A factory function that produces a fresh {@link Renderer} per render cycle.\n *\n * Generators use this to declare which renderer handles their output.\n */\nexport type RendererFactory<TElement = unknown> = () => Renderer<TElement>\n\n/**\n * Defines a renderer factory. Renderers turn the generator's return value\n * (JSX, a template string, a tree of any shape) into `FileNode`s that get\n * written to disk.\n *\n * A renderer can target output formats beyond JSX, for instance a Handlebars\n * renderer or one that writes binary files. Plugins and generators pick the\n * renderer to use via the `renderer` field on `defineGenerator`.\n *\n * @example A minimal renderer that wraps a custom runtime\n * ```ts\n * import { createRenderer } from '@kubb/core'\n *\n * export const myRenderer = createRenderer(() => {\n * const runtime = new MyRuntime()\n * return {\n * async render(element) {\n * await runtime.render(element)\n * },\n * get files() {\n * return runtime.files\n * },\n * [Symbol.dispose]() {\n * runtime.dispose()\n * },\n * }\n * })\n * ```\n */\nexport function createRenderer<TElement = unknown>(factory: RendererFactory<TElement>): RendererFactory<TElement> {\n return factory\n}\n","import type { AsyncEventEmitter, PossiblePromise } from '@internals/utils'\nimport type { FileNode, InputMeta, OperationNode, SchemaNode } from '@kubb/ast'\nimport type { Adapter } from './createAdapter.ts'\nimport type { RendererFactory } from './createRenderer.ts'\nimport type { KubbHooks } from './types.ts'\nimport type { KubbDriver } from './KubbDriver.ts'\nimport type { Plugin, PluginFactoryOptions } from './definePlugin.ts'\nimport type { Resolver } from './defineResolver.ts'\nimport type { Config } from './types.ts'\n\n/**\n * Context passed to a generator's `schema`, `operation`, and `operations` methods.\n *\n * The driver sets `adapter` on the context before it runs a generator, so methods can read it\n * without a null check. `ctx.options` carries the per-node options after exclude/include/override\n * filtering for `schema` and `operation`, or the plugin-level options for `operations`.\n */\nexport type GeneratorContext<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {\n /**\n * The resolved Kubb config for this build, including `root`, `input`, `output`, and the\n * full plugin list.\n */\n config: Config\n /**\n * Absolute path to the current plugin's output directory.\n */\n root: string\n /**\n * The driver running this build. Most generators never need it. Prefer the scoped helpers\n * on this context (`getPlugin`, `getResolver`, `upsertFile`) over reaching into the driver.\n */\n driver: KubbDriver\n /**\n * Get a plugin by name, typed via `Kubb.PluginRegistry` when registered.\n */\n getPlugin<TName extends keyof Kubb.PluginRegistry>(name: TName): Plugin<Kubb.PluginRegistry[TName]> | undefined\n getPlugin(name: string): Plugin | undefined\n /**\n * Get a plugin by name, throws an error if not found.\n */\n requirePlugin<TName extends keyof Kubb.PluginRegistry>(name: TName): Plugin<Kubb.PluginRegistry[TName]>\n requirePlugin(name: string): Plugin\n /**\n * Get a resolver by plugin name, typed via `Kubb.PluginRegistry` when registered.\n */\n getResolver<TName extends keyof Kubb.PluginRegistry>(name: TName): Kubb.PluginRegistry[TName]['resolver']\n getResolver(name: string): Resolver\n /**\n * Add files only if they don't exist.\n */\n addFile: (...file: Array<FileNode>) => Promise<void>\n /**\n * Merge sources into the same output file.\n */\n upsertFile: (...file: Array<FileNode>) => Promise<void>\n /**\n * The build's event bus. Emit or listen to any `KubbHooks` event, for example to react to\n * `kubb:build:end` from inside a generator.\n */\n hooks: AsyncEventEmitter<KubbHooks>\n /**\n * The current plugin instance.\n */\n plugin: Plugin<TOptions>\n /**\n * The current plugin's resolver. It decides what every generated symbol and file path is\n * called. Kubb picks a `setResolver` registration first, then the plugin's static\n * `resolver`, then the built-in default.\n *\n * @example Resolve a type name\n * `ctx.resolver.default('pet', 'type') // 'Pet'`\n *\n * @example Resolve an output file\n * `ctx.resolver.resolveFile({ name: 'pet', extname: '.ts' }, { root, output })`\n */\n resolver: TOptions['resolver']\n /**\n * Report a warning. Collected as a `warning` diagnostic attributed to the current\n * plugin. It surfaces in the run summary but does not fail the build. For a structured\n * diagnostic with a code and source location, use `Diagnostics.report` or throw a\n * `Diagnostics.Error` directly.\n */\n warn: (message: string) => void\n /**\n * Report an error. Collected as an `error` diagnostic attributed to the current\n * plugin, which fails the build.\n */\n error: (error: string | Error) => void\n /**\n * Report an informational message. Collected as an `info` diagnostic attributed to\n * the current plugin.\n */\n info: (message: string) => void\n /**\n * The configured adapter instance.\n */\n adapter: Adapter\n /**\n * Document metadata from the adapter: title, version, base URL, and pre-computed\n * schema index fields (`circularNames`, `enumNames`).\n */\n meta: InputMeta\n /**\n * Resolved options after exclude/include/override filtering.\n */\n options: TOptions['resolvedOptions']\n}\n\n/**\n * Declares a named generator unit that walks the AST and emits files.\n *\n * `schema` runs for each schema node and `operation` for each operation node. `operations` runs\n * once after every operation node is walked. JSX-based generators require a `renderer` factory.\n * Return `Array<FileNode>` directly, or call `ctx.upsertFile()` manually and return `null` to\n * bypass rendering.\n *\n * @note Generators are consumed by plugins and registered via `ctx.addGenerator()` in `kubb:plugin:setup`.\n *\n * @example\n * ```ts\n * import { defineGenerator } from '@kubb/core'\n * import { jsxRenderer } from '@kubb/renderer-jsx'\n *\n * export const typeGenerator = defineGenerator({\n * name: 'typescript',\n * renderer: jsxRenderer,\n * schema(node, ctx) {\n * const { adapter, resolver, root, options } = ctx\n * return <File ...><Type node={node} resolver={resolver} /></File>\n * },\n * })\n * ```\n */\nexport type Generator<TOptions extends PluginFactoryOptions = PluginFactoryOptions, TElement = unknown> = {\n /**\n * Used in diagnostic messages and debug output.\n */\n name: string\n /**\n * Optional renderer factory that produces a {@link Renderer} for each render cycle.\n *\n * Generators that return renderer elements (e.g. JSX via `@kubb/renderer-jsx`) must set this\n * to the matching renderer factory (e.g. `jsxRenderer` from `@kubb/renderer-jsx`).\n *\n * Generators that only return `Array<FileNode>` or `void` do not need to set this.\n *\n * Leave it unset or set `renderer: null` to opt out of rendering.\n *\n * @example\n * ```ts\n * import { jsxRenderer } from '@kubb/renderer-jsx'\n * export const myGenerator = defineGenerator<PluginTs>({\n * renderer: jsxRenderer,\n * schema(node, ctx) { return <File ...>...</File> },\n * })\n * ```\n */\n renderer?: RendererFactory<TElement> | null\n /**\n * Called for each schema node in the AST walk.\n * `ctx` carries the plugin context with `adapter` and `meta` (document metadata),\n * plus `ctx.options` with the per-node resolved options (after exclude/include/override).\n */\n schema?: (node: SchemaNode, ctx: GeneratorContext<TOptions>) => PossiblePromise<TElement | Array<FileNode> | undefined | null>\n /**\n * Called for each operation node in the AST walk.\n * `ctx` carries the plugin context with `adapter` and `meta` (document metadata),\n * plus `ctx.options` with the per-node resolved options (after exclude/include/override).\n */\n operation?: (node: OperationNode, ctx: GeneratorContext<TOptions>) => PossiblePromise<TElement | Array<FileNode> | undefined | null>\n /**\n * Called once after all operations have been walked.\n * `ctx` carries the plugin context with `adapter` and `meta` (document metadata),\n * plus `ctx.options` with the plugin-level options for the batch call.\n */\n operations?: (nodes: Array<OperationNode>, ctx: GeneratorContext<TOptions>) => PossiblePromise<TElement | Array<FileNode> | undefined | null>\n}\n\n/**\n * Defines a generator: a unit of work that runs during the plugin's AST walk\n * and produces files. Plugins register generators via `ctx.addGenerator()`\n * inside `kubb:plugin:setup`.\n *\n * The returned object is the input as-is, but with `this` types preserved so\n * `schema`/`operation`/`operations` methods are correctly typed against the\n * plugin's `PluginFactoryOptions`. Renderer elements and `FileNode[]` returns\n * are both handled by the runtime, so pick whichever style fits.\n *\n * @example JSX-based schema generator\n * ```tsx\n * import { defineGenerator } from '@kubb/core'\n * import { jsxRenderer } from '@kubb/renderer-jsx'\n *\n * export const typeGenerator = defineGenerator({\n * name: 'typescript',\n * renderer: jsxRenderer,\n * schema(node, ctx) {\n * return (\n * <File path={`${ctx.root}/${node.name}.ts`}>\n * <Type node={node} resolver={ctx.resolver} />\n * </File>\n * )\n * },\n * })\n * ```\n */\nexport function defineGenerator<TOptions extends PluginFactoryOptions = PluginFactoryOptions, TElement = unknown>(\n generator: Generator<TOptions, TElement>,\n): Generator<TOptions, TElement> {\n return generator\n}\n","import type { FileNode } from '@kubb/ast'\n\ntype PrintOptions = {\n extname?: FileNode['extname']\n}\n\n/**\n * Converts a resolved {@link FileNode} into the final source string that gets\n * written to disk. Kubb ships with TypeScript and TSX parsers. Add your own\n * for new file types (JSON, Markdown, ...).\n */\nexport type Parser<TMeta extends object = object, TNode = unknown> = {\n /**\n * Display name used in diagnostics and the parser registry.\n */\n name: string\n /**\n * File extensions this parser handles. The driver registers the parser for each\n * extension in this list. A parser with `undefined` here is not registered, so\n * files of an unclaimed extension fall back to joining their sources verbatim.\n *\n * @example\n * `['.ts', '.js']`\n */\n extNames: Array<FileNode['extname']> | undefined\n /**\n * Serialize the file's AST into source code.\n */\n parse(file: FileNode<TMeta>, options?: PrintOptions): string\n /**\n * Render compiler AST nodes for this parser's language into source text.\n * Plugins call this to format the nodes they assemble before handing them\n * back to the parser as `FileNode.sources`.\n */\n print(...nodes: Array<TNode>): string\n}\n\n/**\n * Defines a parser with type-safe `this`. Used to register handlers for new\n * file extensions or to plug a non-TypeScript output into the build.\n *\n * @example\n * ```ts\n * import { defineParser } from '@kubb/core'\n * import { extractStringsFromNodes } from '@kubb/ast/utils'\n *\n * export const jsonParser = defineParser({\n * name: 'json',\n * extNames: ['.json'],\n * parse(file) {\n * return file.sources\n * .map((source) => extractStringsFromNodes(source.nodes ?? []))\n * .join('\\n')\n * },\n * print(...nodes) {\n * return nodes.map(String).join('\\n')\n * },\n * })\n * ```\n */\nexport function defineParser<T extends Parser>(parser: T): T {\n return parser\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["#reporterStorage","ast","#macros","#composed","#memo","#invalidate","#visitorFor","#eventGeneratorPlugins","#resolvers","#defaultResolvers","#listeners","#transforms","#normalizePlugin","#registerPlugin","#adapterSource","#parseInput","ast","#trackListener","#filesPayload","#emitPluginEnd","#runGenerators","#getDefaultResolver","#storage","#driver","logLevel","logLevelMap","process"],"sources":["../../../internals/utils/src/time.ts","../../../internals/utils/src/colors.ts","../../../internals/utils/src/runtime.ts","../../../internals/utils/src/fs.ts","../../../internals/utils/src/promise.ts","../../../internals/utils/src/reserved.ts","../../../internals/utils/src/url.ts","../src/createAdapter.ts","../package.json","../src/diagnostics.ts","../src/definePlugin.ts","../src/defineResolver.ts","../src/Transform.ts","../src/KubbDriver.ts","../src/storages/fsStorage.ts","../src/createKubb.ts","../src/createReporter.ts","../src/reporters/report.ts","../src/reporters/cliReporter.ts","../src/reporters/fileReporter.ts","../src/reporters/jsonReporter.ts","../src/createRenderer.ts","../src/defineGenerator.ts","../src/defineParser.ts"],"sourcesContent":["/**\n * Calculates elapsed time in milliseconds from a high-resolution `process.hrtime` start time.\n * Rounds to 2 decimal places for sub-millisecond precision without noise.\n *\n * @example\n * ```ts\n * const start = process.hrtime()\n * doWork()\n * getElapsedMs(start) // 42.35\n * ```\n */\nexport function getElapsedMs(hrStart: [number, number]): number {\n const [seconds, nanoseconds] = process.hrtime(hrStart)\n const ms = seconds * 1000 + nanoseconds / 1e6\n return Math.round(ms * 100) / 100\n}\n\n/**\n * Converts a millisecond duration into a human-readable string (`ms`, `s`, or `m s`).\n *\n * @example\n * ```ts\n * formatMs(250) // '250ms'\n * formatMs(1500) // '1.50s'\n * formatMs(90000) // '1m 30.0s'\n * ```\n */\nexport function formatMs(ms: number): string {\n if (ms >= 60000) {\n const mins = Math.floor(ms / 60000)\n const secs = ((ms % 60000) / 1000).toFixed(1)\n return `${mins}m ${secs}s`\n }\n\n if (ms >= 1000) {\n return `${(ms / 1000).toFixed(2)}s`\n }\n return `${Math.round(ms)}ms`\n}\n\n/**\n * Formats the elapsed time since `hrStart` as a human-readable string.\n *\n * @example\n * ```ts\n * const start = process.hrtime()\n * doWork()\n * formatHrtime(start) // '1.50s'\n * ```\n */\nexport function formatHrtime(hrStart: [number, number]): string {\n return formatMs(getElapsedMs(hrStart))\n}\n","import { hash } from 'node:crypto'\nimport { styleText } from 'node:util'\nimport { formatMs } from './time.ts'\n\n/**\n * Parsed RGB channels from a CSS hex color string.\n */\ntype RGB = { r: number; g: number; b: number }\n\n/**\n * Parses a CSS hex color string (`#RGB`) into its RGB channels.\n * Falls back to `255` for any channel that cannot be parsed.\n */\nfunction parseHex(color: string): RGB {\n const int = Number.parseInt(color.replace('#', ''), 16)\n return Number.isNaN(int) ? { r: 255, g: 255, b: 255 } : { r: (int >> 16) & 0xff, g: (int >> 8) & 0xff, b: int & 0xff }\n}\n\n/**\n * Returns a function that wraps a string in a 24-bit ANSI true-color escape sequence\n * for the given hex color.\n */\nfunction hex(color: string): (text: string) => string {\n const { r, g, b } = parseHex(color)\n return (text: string) => `\\x1b[38;2;${r};${g};${b}m${text}\\x1b[0m`\n}\n\nfunction gradient(colorStops: Array<string>, text: string): string {\n const chars = text.split('')\n return chars\n .map((char, i) => {\n const t = chars.length <= 1 ? 0 : i / (chars.length - 1)\n const seg = Math.min(Math.floor(t * (colorStops.length - 1)), colorStops.length - 2)\n const lt = t * (colorStops.length - 1) - seg\n const from = parseHex(colorStops[seg]!)\n const to = parseHex(colorStops[seg + 1]!)\n const r = Math.round(from.r + (to.r - from.r) * lt)\n const g = Math.round(from.g + (to.g - from.g) * lt)\n const b = Math.round(from.b + (to.b - from.b) * lt)\n return `\\x1b[38;2;${r};${g};${b}m${char}\\x1b[0m`\n })\n .join('')\n}\n\n/**\n * ANSI color functions for each part of the Kubb mascot illustration.\n */\nconst palette = {\n /**\n * Top cap of the skittle.\n */\n lid: hex('#F55A17'),\n /**\n * Upper wood body.\n */\n woodTop: hex('#F5A217'),\n /**\n * Middle wood body.\n */\n woodMid: hex('#F58517'),\n /**\n * Base wood body.\n */\n woodBase: hex('#B45309'),\n /**\n * Eye whites.\n */\n eye: hex('#FFFFFF'),\n /**\n * Highlight accent.\n */\n highlight: hex('#adadc6'),\n /**\n * Cheek blush.\n */\n blush: hex('#FDA4AF'),\n}\n\n/**\n * Generates the Kubb mascot welcome banner as an ANSI-colored string.\n *\n * @example\n * ```ts\n * console.log(getIntro({ title: 'kubb.config.ts', description: 'generating…', version: '5.0.0', areEyesOpen: true }))\n * ```\n */\nexport function getIntro({\n title,\n description,\n version,\n areEyesOpen,\n}: {\n /**\n * Name of the active configuration or tool being started.\n */\n title: string\n /**\n * Short subtitle shown next to the arrow prompt.\n */\n description: string\n /**\n * Kubb version string rendered in the gradient header.\n */\n version: string\n /**\n * When `false` the eyes are shown as closed dashes instead of open blocks.\n */\n areEyesOpen: boolean\n}): string {\n const kubbVersion = gradient(['#F58517', '#F5A217', '#F55A17'], `KUBB v${version}`)\n\n const eyeTop = areEyesOpen ? palette.eye('█▀█') : palette.eye('───')\n const eyeBottom = areEyesOpen ? palette.eye('▀▀▀') : palette.eye('───')\n\n return `\n ${palette.lid('▄▄▄▄▄▄▄▄▄▄▄▄▄')}\n ${palette.woodTop('█ ')}${palette.highlight('▄▄')}${palette.woodTop(' ')}${palette.highlight('▄▄')}${palette.woodTop(' █')} ${kubbVersion}\n ${palette.woodMid('█ ')}${eyeTop}${palette.woodMid(' ')}${eyeTop}${palette.woodMid(' █')} ${styleText('gray', title)}\n ${palette.woodMid('█ ')}${eyeBottom}${palette.woodMid(' ')}${palette.blush('◡')}${palette.woodMid(' ')}${eyeBottom}${palette.woodMid(' █')} ${styleText('yellow', '➜')} ${styleText('white', description)}\n ${palette.woodBase('▀▀▀▀▀▀▀▀▀▀▀▀▀')}\n`\n}\n\n/**\n * ANSI color names used by {@link randomCliColor} for deterministic terminal coloring.\n */\nconst randomColors = ['black', 'red', 'green', 'yellow', 'blue', 'white', 'magenta', 'cyan', 'gray'] as const\n\n/**\n * Wraps `text` in a deterministic ANSI color derived from the text's SHA-256 hash.\n *\n * @example\n * ```ts\n * randomCliColor('petstore') // '\\x1b[33m' + 'petstore' + '\\x1b[39m' (always the same color for 'petstore')\n * ```\n */\nexport function randomCliColor(text?: string): string {\n if (!text) return ''\n const index = hash('sha256', text, 'buffer').readUInt32BE(0) % randomColors.length\n const color = randomColors[index] ?? 'white'\n return styleText(color, text)\n}\n\n/**\n * Formats a millisecond duration with a threshold-based ANSI color.\n * `≤ 500 ms` → green · `≤ 1 000 ms` → yellow · `> 1 000 ms` → red.\n *\n * @example\n * ```ts\n * formatMsWithColor(200) // '\\x1b[32m200ms\\x1b[39m'\n * formatMsWithColor(800) // '\\x1b[33m800ms\\x1b[39m'\n * formatMsWithColor(1500) // '\\x1b[31m1.50s\\x1b[39m'\n * ```\n */\nexport function formatMsWithColor(ms: number): string {\n const formatted = formatMs(ms)\n if (ms <= 500) return styleText('green', formatted)\n if (ms <= 1000) return styleText('yellow', formatted)\n return styleText('red', formatted)\n}\n","/**\n * Name of the JavaScript runtime executing the current process.\n */\ntype RuntimeName = 'bun' | 'deno' | 'node'\n\n/**\n * Detects the JavaScript runtime executing the current process and exposes its name and version.\n *\n * Prefer the shared {@link runtime} instance over constructing your own.\n */\nclass Runtime {\n /**\n * `true` when the current process is running under Bun.\n *\n * Detection keys off the global `Bun` object rather than `process.versions`,\n * because Bun polyfills `process.versions.node` for Node compatibility and would\n * otherwise look like Node.\n *\n * @example\n * ```ts\n * if (runtime.isBun) {\n * await Bun.write(path, data)\n * }\n * ```\n */\n get isBun(): boolean {\n return typeof Bun !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Deno.\n */\n get isDeno(): boolean {\n return typeof (globalThis as { Deno?: unknown }).Deno !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Node.\n *\n * Bun and Deno are excluded first so a polyfilled `process` does not register as Node.\n */\n get isNode(): boolean {\n return !this.isBun && !this.isDeno && typeof process !== 'undefined' && process.versions?.node != null\n }\n\n /**\n * Name of the runtime executing the current process.\n *\n * @example\n * ```ts\n * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise\n * ```\n */\n get name(): RuntimeName {\n if (this.isBun) return 'bun'\n if (this.isDeno) return 'deno'\n\n return 'node'\n }\n\n /**\n * Version of the active runtime, or an empty string when it cannot be read.\n *\n * @example\n * ```ts\n * runtime.version // '1.3.11' under Bun, '22.22.2' under Node\n * ```\n */\n get version(): string {\n if (this.isBun) return process.versions.bun ?? ''\n if (this.isDeno) return (globalThis as { Deno?: { version?: { deno?: string } } }).Deno?.version?.deno ?? ''\n\n return process.versions?.node ?? ''\n }\n}\n\n/**\n * Shared {@link Runtime} instance describing the JavaScript runtime executing the current process.\n */\nexport const runtime = new Runtime()\n","import { existsSync } from 'node:fs'\nimport { access, mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { dirname, join, posix, resolve } from 'node:path'\nimport { camelCase } from './casing.ts'\nimport { runtime } from './runtime.ts'\n\n/**\n * Walks up the directory tree from `cwd` (defaults to `process.cwd()`) and\n * returns the absolute path of the nearest `package.json`, or `null` when none\n * is found before reaching the filesystem root.\n *\n * @example\n * ```ts\n * const pkgPath = findPackageJSON('/home/user/project/src') // '/home/user/project/package.json'\n * ```\n */\nexport function findPackageJSON(cwd?: string): string | null {\n let dir = cwd ? resolve(cwd) : process.cwd()\n while (true) {\n const pkgPath = join(dir, 'package.json')\n if (existsSync(pkgPath)) return pkgPath\n const parent = dirname(dir)\n if (parent === dir) return null\n dir = parent\n }\n}\n\n/**\n * Converts all backslashes to forward slashes.\n * Extended-length Windows paths (`\\\\?\\...`) are left unchanged.\n */\nfunction toSlash(p: string): string {\n if (p.startsWith('\\\\\\\\?\\\\')) return p\n\n return p.replaceAll('\\\\', '/')\n}\n\n/**\n * Returns the relative path from `rootDir` to `filePath`, always using forward slashes\n * and prefixed with `./` when not already traversing upward.\n *\n * @example\n * ```ts\n * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'\n * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'\n * ```\n */\nexport function getRelativePath(rootDir?: string | null, filePath?: string | null): string {\n if (!rootDir || !filePath) {\n throw new Error(`Root and file should be filled in when retrieving the relativePath, ${rootDir || ''} ${filePath || ''}`)\n }\n\n const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath))\n\n return relativePath.startsWith('../') ? relativePath : `./${relativePath}`\n}\n\n/**\n * Resolves to `true` when the file or directory at `path` exists.\n * Uses `Bun.file().exists()` when running under Bun, `fs.access` otherwise.\n *\n * @example\n * ```ts\n * if (await exists('./kubb.config.ts')) {\n * const content = await read('./kubb.config.ts')\n * }\n * ```\n */\nexport async function exists(path: string): Promise<boolean> {\n if (runtime.isBun) {\n return Bun.file(path).exists()\n }\n return access(path).then(\n () => true,\n () => false,\n )\n}\n\n/**\n * Reads the file at `path` as a UTF-8 string.\n * Uses `Bun.file().text()` when running under Bun, `fs.readFile` otherwise.\n *\n * @example\n * ```ts\n * const source = await read('./src/Pet.ts')\n * ```\n */\nexport async function read(path: string): Promise<string> {\n if (runtime.isBun) {\n return Bun.file(path).text()\n }\n return readFile(path, { encoding: 'utf8' })\n}\n\ntype WriteOptions = {\n /**\n * When `true`, re-reads the file immediately after writing and throws if the\n * content does not match — useful for catching write failures on unreliable file systems.\n */\n sanity?: boolean\n}\n\n/**\n * Writes `data` to `path`, trimming leading/trailing whitespace before saving.\n * Skips the write when the trimmed content is empty or identical to what is already on disk.\n * Creates any missing parent directories automatically.\n * When `sanity` is `true`, re-reads the file after writing and throws if the content does not match.\n *\n * @example\n * ```ts\n * await write('./src/Pet.ts', source) // writes and returns trimmed content\n * await write('./src/Pet.ts', source) // null — file unchanged\n * await write('./src/Pet.ts', ' ') // null — empty content skipped\n * ```\n */\nexport async function write(path: string, data: string, options: WriteOptions = {}): Promise<string | null> {\n const trimmed = data.trim()\n if (trimmed === '') return null\n\n const resolved = resolve(path)\n\n if (runtime.isBun) {\n const file = Bun.file(resolved)\n const oldContent = (await file.exists()) ? await file.text() : null\n if (oldContent === trimmed) return null\n await Bun.write(resolved, trimmed)\n return trimmed\n }\n\n try {\n const oldContent = await readFile(resolved, { encoding: 'utf-8' })\n if (oldContent === trimmed) return null\n } catch {\n /* file doesn't exist yet */\n }\n\n await mkdir(dirname(resolved), { recursive: true })\n await writeFile(resolved, trimmed, { encoding: 'utf-8' })\n\n if (options.sanity) {\n const savedData = await readFile(resolved, { encoding: 'utf-8' })\n if (savedData !== trimmed) {\n throw new Error(`Sanity check failed for ${path}\\n\\nData[${data.length}]:\\n${data}\\n\\nSaved[${savedData.length}]:\\n${savedData}\\n`)\n }\n return savedData\n }\n\n return trimmed\n}\n\n/**\n * Recursively removes `path`. Silently succeeds when `path` does not exist.\n *\n * @example\n * ```ts\n * await clean('./dist')\n * ```\n */\nexport async function clean(path: string): Promise<void> {\n return rm(path, { recursive: true, force: true })\n}\n\n/**\n * Converts a filesystem path to use POSIX (`/`) separators.\n *\n * Most of the codebase compares and composes paths as strings (prefix matching, joining for\n * import specifiers, splitting on `/`). On POSIX `path.resolve` already returns `/`-separated\n * paths, but on Windows it returns `\\`-separated paths, which breaks every such comparison.\n *\n * Routing every path that crosses a module boundary through `toPosixPath` keeps the rest of the\n * code platform-agnostic. The conversion runs unconditionally so Windows-specific behavior is\n * exercisable from POSIX CI.\n *\n * @example\n * toPosixPath('C:\\\\repo\\\\src\\\\pet.ts') // 'C:/repo/src/pet.ts'\n */\nexport function toPosixPath(filePath: string): string {\n return filePath.replaceAll('\\\\', '/')\n}\n\n/**\n * Strips the file extension from a path or file name.\n * Only removes the last `.ext` segment when the dot is not part of a directory name.\n *\n * @example\n * trimExtName('petStore.ts') // 'petStore'\n * trimExtName('/src/models/pet.ts') // '/src/models/pet'\n * trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'\n * trimExtName('noExtension') // 'noExtension'\n */\nexport function trimExtName(text: string): string {\n const dotIndex = text.lastIndexOf('.')\n if (dotIndex > 0 && !text.includes('/', dotIndex)) {\n return text.slice(0, dotIndex)\n }\n return text\n}\n\n/**\n * Builds a nested file path from a dotted name. Splits on dots that precede a letter\n * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases\n * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.\n *\n * Empty segments are dropped before joining. They arise when the name starts with a dot\n * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to\n * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an\n * absolute path, letting generated files escape the configured output directory.\n *\n * @example Nested path from a dotted name\n * `toFilePath('pet.petId') // 'pet/petId'`\n *\n * @example PascalCase the final segment\n * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`\n *\n * @example Suffix applied to the final segment only\n * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`\n */\nexport function toFilePath(name: string, caseLast: (part: string) => string = camelCase): string {\n const parts = name.split(/\\.(?=[a-zA-Z])/)\n return parts\n .map((part, i) => (i === parts.length - 1 ? caseLast(part) : camelCase(part)))\n .filter(Boolean)\n .join('/')\n}\n","function* chunks<T>(arr: ReadonlyArray<T>, size: number): Generator<Array<T>> {\n for (let i = 0; i < arr.length; i += size) {\n yield arr.slice(i, i + size)\n }\n}\n\nexport type ForBatchesOptions = {\n /**\n * Maximum batch size handed to `process`.\n * Parallel dispatch within a batch is the caller's responsibility\n * (typically via `Promise.all(batch.map(...))`).\n */\n concurrency: number\n /**\n * Called after every batch.\n *\n * Use a cheap, idempotent callback (e.g. one that short-circuits when there\n * is nothing new to do). The helper does not coalesce calls — if you need\n * throttling, do it inside `flush` itself.\n */\n flush?: () => Promise<void>\n}\n\n/**\n * Slices `source` into batches of `concurrency` items and awaits `process` for each batch.\n * Accepts both plain arrays (sync) and `AsyncIterable` (streaming).\n *\n * `process` controls whether items inside a batch run in parallel; this helper only\n * controls batch size and per-batch flushing.\n *\n * @example\n * ```ts\n * // parallel dispatch inside each batch\n * await forBatches(schemas, (batch) => Promise.all(batch.map(process)), { concurrency: 8 })\n *\n * // async iterable with a flush after every batch\n * await forBatches(stream.schemas, (batch) => dispatch(batch), { concurrency: 8, flush })\n * ```\n */\nexport async function forBatches<T>(\n source: ReadonlyArray<T> | AsyncIterable<T>,\n process: (batch: Array<T>) => Promise<unknown>,\n options: ForBatchesOptions,\n): Promise<void> {\n const { concurrency, flush } = options\n\n if (Array.isArray(source)) {\n for (const batch of chunks(source, concurrency)) {\n await process(batch)\n if (flush) await flush()\n }\n return\n }\n\n const batch: Array<T> = []\n for await (const item of source) {\n batch.push(item)\n if (batch.length >= concurrency) {\n await process(batch.splice(0))\n\n if (flush) await flush()\n }\n }\n if (batch.length > 0) {\n await process(batch.splice(0))\n\n if (flush) await flush()\n }\n}\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\n/**\n * Container that switches between an eager `Array<T>` and a lazy `AsyncIterable<T>`.\n *\n * `Array<T>` by default. With `Stream` set to `true` it becomes `AsyncIterable<T>`, so large\n * collections can be produced lazily without holding every item in memory. Pairs with\n * {@link arrayToAsyncIterable}, which lifts a plain array into the streaming form.\n *\n * @example\n * ```ts\n * type Eager = Streamable<number> // Array<number>\n * type Lazy = Streamable<number, true> // AsyncIterable<number>\n * ```\n */\nexport type Streamable<T, Stream extends boolean = false> = Stream extends true ? AsyncIterable<T> : Array<T>\n\n/**\n * Wraps a plain array in a reusable `AsyncIterable`.\n * Each `[Symbol.asyncIterator]()` call returns a fresh generator so the\n * iterable can be consumed multiple times (e.g. once per plugin pre-scan).\n *\n * @example\n * ```ts\n * const stream = arrayToAsyncIterable([1, 2, 3])\n * for await (const n of stream) console.log(n) // 1, 2, 3\n * ```\n */\nexport function arrayToAsyncIterable<T>(arr: ReadonlyArray<T>): AsyncIterable<T> {\n return {\n [Symbol.asyncIterator]() {\n return (async function* () {\n yield* arr\n })()\n },\n }\n}\n","/**\n * JavaScript and Java reserved words.\n * @link https://github.com/jonschlinkert/reserved/blob/master/index.js\n */\nconst reservedWords = new Set([\n 'abstract',\n 'arguments',\n 'boolean',\n 'break',\n 'byte',\n 'case',\n 'catch',\n 'char',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'double',\n 'else',\n 'enum',\n 'eval',\n 'export',\n 'extends',\n 'false',\n 'final',\n 'finally',\n 'float',\n 'for',\n 'function',\n 'goto',\n 'if',\n 'implements',\n 'import',\n 'in',\n 'instanceof',\n 'int',\n 'interface',\n 'let',\n 'long',\n 'native',\n 'new',\n 'null',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'return',\n 'short',\n 'static',\n 'super',\n 'switch',\n 'synchronized',\n 'this',\n 'throw',\n 'throws',\n 'transient',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'volatile',\n 'while',\n 'with',\n 'yield',\n 'Array',\n 'Date',\n 'hasOwnProperty',\n 'Infinity',\n 'isFinite',\n 'isNaN',\n 'isPrototypeOf',\n 'length',\n 'Math',\n 'name',\n 'NaN',\n 'Number',\n 'Object',\n 'prototype',\n 'String',\n 'toString',\n 'undefined',\n 'valueOf',\n] as const)\n\n/**\n * Prefixes `word` with `_` when it is a reserved JavaScript/Java identifier or starts with a digit.\n *\n * @example\n * ```ts\n * transformReservedWord('class') // '_class'\n * transformReservedWord('42foo') // '_42foo'\n * transformReservedWord('status') // 'status'\n * ```\n */\nexport function transformReservedWord(word: string): string {\n const firstChar = word.charCodeAt(0)\n if (word && (reservedWords.has(word as 'valueOf') || (firstChar >= 48 && firstChar <= 57))) {\n return `_${word}`\n }\n return word\n}\n\n/**\n * Returns `true` when `name` is a syntactically valid JavaScript variable name.\n *\n * @example\n * ```ts\n * isValidVarName('status') // true\n * isValidVarName('class') // false (reserved word)\n * isValidVarName('42foo') // false (starts with digit)\n * ```\n */\nexport function isValidVarName(name: string): boolean {\n if (!name || reservedWords.has(name as 'valueOf')) {\n return false\n }\n return isIdentifier(name)\n}\n\n/**\n * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.\n *\n * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys\n * even though they are not valid variable names, so use this (not {@link isValidVarName}) when\n * deciding whether an object key needs quoting.\n *\n * @example\n * ```ts\n * isIdentifier('name') // true\n * isIdentifier('x-total')// false\n * ```\n */\nexport function isIdentifier(name: string): boolean {\n return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)\n}\n","import { camelCase } from './casing.ts'\nimport { isValidVarName } from './reserved.ts'\n\ntype URLObject = {\n /**\n * The resolved URL string (Express-style or template literal, depending on context).\n */\n url: string\n /**\n * Extracted path parameters as a key-value map, or `null` when the path has none.\n */\n params: Record<string, string> | null\n}\n\n/**\n * Supported identifier casing strategies for path parameters.\n */\ntype PathCasing = 'camelcase'\n\ntype TemplateOptions = {\n /**\n * Literal text prepended inside the template literal, e.g. a base URL.\n */\n prefix?: string | null\n /**\n * Transform applied to each extracted parameter name before interpolation.\n */\n replacer?: (pathParam: string) => string\n /**\n * Casing strategy applied to path parameter names.\n */\n casing?: PathCasing\n}\n\ntype ObjectOptions = {\n /**\n * Controls whether the `url` is rendered as an Express path or a template literal.\n * @default 'path'\n */\n type?: 'path' | 'template'\n /**\n * Transform applied to each extracted parameter name.\n */\n replacer?: (pathParam: string) => string\n /**\n * When `true`, the result is serialized to a string expression instead of a plain object.\n */\n stringify?: boolean\n /**\n * Casing strategy applied to path parameter names.\n */\n casing?: PathCasing\n}\n\nfunction transformParam(raw: string, casing?: PathCasing): string {\n const param = isValidVarName(raw) ? raw : camelCase(raw)\n return casing === 'camelcase' ? camelCase(param) : param\n}\n\nfunction toParamsObject(\n path: string,\n { replacer, casing }: { replacer?: (pathParam: string) => string; casing?: PathCasing } = {},\n): Record<string, string> | null {\n const params: Record<string, string> = {}\n\n for (const match of path.matchAll(/\\{([^}]+)\\}/g)) {\n const param = transformParam(match[1]!, casing)\n const key = replacer ? replacer(param) : param\n params[key] = key\n }\n\n return Object.keys(params).length > 0 ? params : null\n}\n\n/**\n * Helpers for OpenAPI/Swagger paths, plus a thin wrapper over the native `URL`.\n */\nexport class Url {\n /**\n * Reports whether `url` is a parseable absolute URL. Delegates to the native `URL.canParse`.\n *\n * @example\n * Url.canParse('https://petstore.swagger.io/v2') // true\n * Url.canParse('/pet/{petId}') // false\n */\n static canParse(url: string, base?: string | URL): boolean {\n return URL.canParse(url, base)\n }\n\n /**\n * Converts an OpenAPI/Swagger path to Express-style colon syntax.\n *\n * @example\n * Url.toPath('/pet/{petId}') // '/pet/:petId'\n */\n static toPath(path: string): string {\n return path.replace(/\\{([^}]+)\\}/g, ':$1')\n }\n\n /**\n * Converts an OpenAPI/Swagger path to a TypeScript template literal string.\n * `prefix` is prepended inside the literal, `replacer` transforms each parameter name,\n * and `casing` controls parameter identifier casing.\n *\n * @example\n * Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'\n *\n * @example\n * Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'\n */\n static toTemplateString(path: string, { prefix, replacer, casing }: TemplateOptions = {}): string {\n const parts = path.split(/\\{([^}]+)\\}/)\n const result = parts\n .map((part, i) => {\n if (i % 2 === 0) return part\n const param = transformParam(part, casing)\n return `\\${${replacer ? replacer(param) : param}}`\n })\n .join('')\n\n return `\\`${prefix ?? ''}${result}\\``\n }\n\n /**\n * Returns the path and its extracted params as a structured `URLObject`, or as a stringified\n * expression when `stringify` is set.\n *\n * @example\n * Url.toObject('/pet/{petId}')\n * // { url: '/pet/:petId', params: { petId: 'petId' } }\n */\n static toObject(path: string, { type = 'path', replacer, stringify, casing }: ObjectOptions = {}): URLObject | string {\n const object: URLObject = {\n url: type === 'path' ? Url.toPath(path) : Url.toTemplateString(path, { replacer, casing }),\n params: toParamsObject(path, { replacer, casing }),\n }\n\n if (stringify) {\n if (type === 'template') {\n return JSON.stringify(object).replaceAll(\"'\", '').replaceAll(`\"`, '')\n }\n\n if (object.params) {\n return `{ url: '${object.url}', params: ${JSON.stringify(object.params).replaceAll(\"'\", '').replaceAll(`\"`, '')} }`\n }\n\n return `{ url: '${object.url}' }`\n }\n\n return object\n }\n}\n","import type { PossiblePromise } from '@internals/utils'\nimport type { ImportNode, InputNode, SchemaNode } from '@kubb/ast'\n\n/**\n * Source data handed to an adapter's `parse` function. Mirrors the config\n * input shape with paths resolved to absolute.\n *\n * - `{ type: 'path' }`: single file on disk.\n * - `{ type: 'data' }`: raw string or parsed object provided inline.\n */\nexport type AdapterSource = { type: 'path'; path: string } | { type: 'data'; data: string | unknown }\n\n/**\n * Generic parameters used by `createAdapter` and the resulting `Adapter` type.\n *\n * - `TName`: unique adapter identifier (`'oas'`, `'asyncapi'`, ...).\n * - `TOptions`: user-facing options accepted by the adapter factory.\n * - `TResolvedOptions`: options after defaults are applied.\n * - `TDocument`: type of the parsed source document.\n */\nexport type AdapterFactoryOptions<\n TName extends string = string,\n TOptions extends object = object,\n TResolvedOptions extends object = TOptions,\n TDocument = unknown,\n> = {\n name: TName\n options: TOptions\n resolvedOptions: TResolvedOptions\n document: TDocument\n}\n\n/**\n * Converts input files or inline data into Kubb's universal AST `InputNode`.\n *\n * Adapters live between the spec format and the plugins. The built-in\n * `@kubb/adapter-oas` handles OpenAPI 2.0, 3.0, and 3.1. A custom adapter can\n * support GraphQL, gRPC, or another schema language.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { adapterOas } from '@kubb/adapter-oas'\n * import { pluginTs } from '@kubb/plugin-ts'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * adapter: adapterOas(),\n * plugins: [pluginTs()],\n * })\n * ```\n */\nexport type Adapter<TOptions extends AdapterFactoryOptions = AdapterFactoryOptions> = {\n /**\n * Human-readable adapter identifier (e.g. `'oas'`, `'asyncapi'`).\n */\n name: TOptions['name']\n /**\n * Resolved adapter options after defaults have been applied.\n */\n options: TOptions['resolvedOptions']\n /**\n * Parsed source document after the first `parse()` call. `null` before parsing.\n */\n document: TOptions['document'] | null\n /**\n * Parse the source into a universal `InputNode`.\n */\n parse: (source: AdapterSource) => PossiblePromise<InputNode>\n /**\n * Extract `ImportNode` entries for a schema tree.\n * Returns an empty array before the first `parse()` call.\n *\n * The `resolve` callback receives the collision-corrected schema name and must\n * return `{ name, path }` for the import, or `undefined` to skip it.\n */\n getImports: (node: SchemaNode, resolve: (schemaName: string) => { name: string; path: string }) => Array<ImportNode>\n /**\n * Validate the document at the given path or URL.\n */\n validate: (input: string, options?: { throwOnError?: boolean }) => Promise<void>\n /**\n * Memory-efficient streaming variant of `parse()`.\n *\n * Returns an `InputNode<true>` whose `schemas` and `operations` are `AsyncIterable`.\n * Each `for await` loop creates a fresh parse pass over the cached in-memory document.\n * No pre-built arrays are held in memory.\n */\n stream?: (source: AdapterSource) => Promise<InputNode<true>>\n}\n\ntype AdapterBuilder<T extends AdapterFactoryOptions> = (options: T['options']) => Adapter<T>\n\n/**\n * Defines a custom adapter that translates a spec format into Kubb's universal\n * AST, for example GraphQL, gRPC, or AsyncAPI. The built-in `@kubb/adapter-oas`\n * handles OpenAPI/Swagger documents.\n *\n * Adapters must return an `InputNode` from `parse`. That node is what every\n * plugin in the build consumes.\n *\n * @example\n * ```ts\n * import { createAdapter, ast, type AdapterFactoryOptions } from '@kubb/core'\n *\n * type MyAdapter = AdapterFactoryOptions<'my-adapter', { validate?: boolean }>\n *\n * export const myAdapter = createAdapter<MyAdapter>((options) => ({\n * name: 'my-adapter',\n * options,\n * document: null,\n * async parse(_source) {\n * // Convert the source (path or inline data) into an InputNode.\n * return ast.factory.createInput()\n * },\n * getImports: () => [],\n * async validate() {\n * // Throw here when the spec is invalid.\n * },\n * }))\n * ```\n */\nexport function createAdapter<T extends AdapterFactoryOptions = AdapterFactoryOptions>(build: AdapterBuilder<T>): (options?: T['options']) => Adapter<T> {\n return (options) => build(options ?? ({} as T['options']))\n}\n","","import { AsyncLocalStorage } from 'node:async_hooks'\nimport { styleText } from 'node:util'\nimport type { AsyncEventEmitter } from '@internals/utils'\nimport { getErrorMessage } from '@internals/utils'\nimport { version } from '../package.json'\nimport { type DiagnosticCode, diagnosticCode } from './constants.ts'\nimport type { KubbHooks } from './types.ts'\n\n/**\n * Docs major version, derived from the package version so the link tracks the published major.\n */\nconst docsMajor = version.split('.')[0] ?? '5'\n\n/**\n * How serious a diagnostic is. `error` fails the build, `warning` and `info`\n * are reported but do not.\n */\nexport type DiagnosticSeverity = 'error' | 'warning' | 'info'\n\n/**\n * A human-readable explanation of a diagnostic code: a short title, what triggers it, and how\n * to resolve it. This is the source of truth the kubb.dev `/diagnostics/<slug>` pages mirror, so\n * every code stays documented in one place. Adding a code without documenting it fails the build.\n */\nexport type DiagnosticDoc = {\n /**\n * Short title shown as the docs heading.\n */\n title: string\n /**\n * What triggers the diagnostic.\n */\n cause: string\n /**\n * The action that resolves it.\n */\n fix: string\n}\n\n/**\n * Points a diagnostic back into the source document. Inputs are parsed into an\n * object model with no line/column, so locations carry a JSON pointer the adapter\n * builds (the OAS adapter emits `#/components/schemas/Pet`). A `config` diagnostic\n * points at the Kubb config itself and so has no pointer.\n */\nexport type DiagnosticLocation =\n | {\n kind: 'schema'\n /**\n * RFC 6901 JSON pointer into the source document.\n */\n pointer: string\n /**\n * The original reference when the diagnostic stems from an unresolved one.\n */\n ref?: string\n }\n | {\n kind: 'operation' | 'document'\n /**\n * RFC 6901 JSON pointer into the source document.\n */\n pointer: string\n }\n | {\n kind: 'config'\n }\n\n/**\n * What a diagnostic carries.\n * - `problem` is a build issue shown to the user, and the only kind rendered as a problem.\n * - `performance` records a plugin's elapsed time.\n * - `update` is a version notice.\n */\nexport type DiagnosticKind = 'problem' | 'performance' | 'update'\n\n/**\n * Codes that describe a build problem: every {@link DiagnosticCode} except the\n * `performance` and `updateAvailable` codes, which ride on their own variants.\n */\nexport type ProblemCode = Exclude<DiagnosticCode, typeof diagnosticCode.performance | typeof diagnosticCode.updateAvailable>\n\n/**\n * A build problem collected during a run, gathered into the result instead of\n * aborting on the first failure.\n */\nexport type ProblemDiagnostic = {\n /**\n * @default 'problem'\n */\n kind?: 'problem'\n /**\n * Stable identifier for the problem, from the {@link diagnosticCode} catalog.\n */\n code: ProblemCode\n severity: DiagnosticSeverity\n message: string\n location?: DiagnosticLocation\n /**\n * A suggested fix, phrased as an action the user can take.\n */\n help?: string\n /**\n * Name of the plugin or subsystem that produced the diagnostic.\n */\n plugin?: string\n /**\n * The underlying error, when the diagnostic wraps a thrown one.\n */\n cause?: Error\n}\n\n/**\n * A per-plugin performance record, built with {@link Diagnostics.performance}. The `performance`\n * kind keeps it out of the problem list. It feeds the per-plugin timing bars, and reporters sum\n * these into the run total.\n */\nexport type PerformanceDiagnostic = {\n kind: 'performance'\n code: typeof diagnosticCode.performance\n severity: 'info'\n message: string\n /**\n * The plugin this measurement belongs to.\n */\n plugin: string\n /**\n * Elapsed milliseconds.\n */\n duration: number\n}\n\n/**\n * A notice that a newer Kubb version is available on npm, built with {@link Diagnostics.update}.\n * It renders like any info diagnostic.\n */\nexport type UpdateDiagnostic = {\n kind: 'update'\n code: typeof diagnosticCode.updateAvailable\n severity: 'info'\n message: string\n /**\n * The running Kubb version.\n */\n currentVersion: string\n /**\n * The newest version published on npm.\n */\n latestVersion: string\n}\n\n/**\n * A structured record collected during a build, discriminated on `kind`: a\n * {@link ProblemDiagnostic} for an issue, a {@link PerformanceDiagnostic} for a per-plugin\n * timing, or an {@link UpdateDiagnostic} for a version notice.\n */\nexport type Diagnostic = ProblemDiagnostic | PerformanceDiagnostic | UpdateDiagnostic\n\n/**\n * Maps each {@link DiagnosticCode} to the variant it selects, for {@link narrow}.\n * Every {@link ProblemCode} selects a {@link ProblemDiagnostic}, and the two bookkeeping codes\n * select their own variant.\n */\nexport type DiagnosticByCode = Record<ProblemCode, ProblemDiagnostic> &\n Record<typeof diagnosticCode.performance, PerformanceDiagnostic> &\n Record<typeof diagnosticCode.updateAvailable, UpdateDiagnostic>\n\n/**\n * Narrows a {@link Diagnostic} to the variant for `code`, or `null` when it does not match.\n *\n * @example\n * ```ts\n * const update = narrow(diagnostic, diagnosticCode.updateAvailable)\n * if (update) {\n * console.log(update.latestVersion)\n * }\n * ```\n */\nfunction narrow<C extends DiagnosticCode>(diagnostic: Diagnostic, code: C): DiagnosticByCode[C] | null {\n return diagnostic.code === code ? (diagnostic as DiagnosticByCode[C]) : null\n}\n\n/**\n * Builds a type guard that narrows a {@link Diagnostic} to the variant for `kind`. A diagnostic\n * with no `kind` is treated as a `problem`.\n */\nfunction isKind<T extends Diagnostic>(kind: DiagnosticKind) {\n return (diagnostic: Diagnostic): diagnostic is T => (diagnostic.kind ?? 'problem') === kind\n}\n\n/**\n * Returns `true` when the diagnostic is a build {@link ProblemDiagnostic}.\n *\n * @example\n * ```ts\n * if (isProblem(diagnostic)) {\n * console.log(diagnostic.location)\n * }\n * ```\n */\nconst isProblem = isKind<ProblemDiagnostic>('problem')\n\n/**\n * Returns `true` when the diagnostic is a per-plugin {@link PerformanceDiagnostic}.\n *\n * @example\n * ```ts\n * const timings = diagnostics.filter(isPerformance)\n * ```\n */\nconst isPerformance = isKind<PerformanceDiagnostic>('performance')\n\n/**\n * Returns `true` when the diagnostic is a version-update {@link UpdateDiagnostic}.\n *\n * @example\n * ```ts\n * if (isUpdate(diagnostic)) {\n * console.log(diagnostic.latestVersion)\n * }\n * ```\n */\nconst isUpdate = isKind<UpdateDiagnostic>('update')\n\n/**\n * Accent color per severity. The color tints the `[CODE]` tag (red error, yellow warning,\n * blue info).\n */\nconst severityStyle: Record<DiagnosticSeverity, { color: 'red' | 'yellow' | 'blue' }> = {\n error: { color: 'red' },\n warning: { color: 'yellow' },\n info: { color: 'blue' },\n}\n\n/**\n * A {@link Diagnostic} reduced to its JSON-safe fields plus a `docsUrl`, for\n * machine-readable output (the `--reporter json` report, the MCP tools). Drops the\n * non-serializable `cause` and the `kind`/`duration` bookkeeping.\n */\nexport type SerializedDiagnostic = {\n code: DiagnosticCode\n severity: DiagnosticSeverity\n message: string\n location?: DiagnosticLocation\n help?: string\n plugin?: string\n /**\n * The kubb.dev docs link for the code, omitted for the unknown fallback.\n */\n docsUrl?: string\n}\n\n/**\n * Explanation for every {@link diagnosticCode}. Use {@link Diagnostics.explain} to look one up\n * and `Diagnostics.docsUrl` for the matching kubb.dev page.\n */\nconst diagnosticCatalog: Record<DiagnosticCode, DiagnosticDoc> = {\n [diagnosticCode.unknown]: {\n title: 'Unknown error',\n cause: 'An error was thrown without a stable Kubb code, so it is reported as-is.',\n fix: 'Read the underlying message and stack. If it comes from a plugin or adapter, check its configuration; otherwise report it as a possible Kubb bug.',\n },\n [diagnosticCode.inputNotFound]: {\n title: 'Input not found',\n cause: 'The file or URL set in `input.path` (or passed as `kubb generate PATH`) could not be read.',\n fix: 'Check that the path or URL exists and is readable, then set it in `input.path` or pass it on the CLI.',\n },\n [diagnosticCode.inputRequired]: {\n title: 'Input required',\n cause: 'An adapter is configured but no `input` was provided.',\n fix: 'Set `input.path` (a file or URL) or `input.data` (an inline spec) in your Kubb config.',\n },\n [diagnosticCode.refNotFound]: {\n title: 'Reference not found',\n cause: 'A `$ref` could not be resolved in the source document.',\n fix: 'Add the missing definition (for example under `components.schemas`) or fix the `$ref`. Run `kubb validate` to check the spec.',\n },\n [diagnosticCode.invalidServerVariable]: {\n title: 'Invalid server variable',\n cause: 'A server variable value is not allowed by its `enum`.',\n fix: 'Use one of the values listed in the server variable `enum`, or update the spec.',\n },\n [diagnosticCode.pluginNotFound]: {\n title: 'Plugin not found',\n cause: 'A plugin that another plugin depends on is missing from the config.',\n fix: 'Add the required plugin to the `plugins` array in kubb.config.ts, or remove the dependency on it.',\n },\n [diagnosticCode.pluginFailed]: {\n title: 'Plugin failed',\n cause: 'A plugin threw while generating, or reported an error through `ctx.error`.',\n fix: 'Read the underlying error and check the plugin options and the schema or operation it failed on.',\n },\n [diagnosticCode.pluginWarning]: {\n title: 'Plugin warning',\n cause: 'A plugin reported a non-fatal warning through `ctx.warn`.',\n fix: 'Review the message. It does not fail the build; adjust the plugin options or input if the warning is unwanted.',\n },\n [diagnosticCode.pluginInfo]: {\n title: 'Plugin info',\n cause: 'A plugin reported an informational message through `ctx.info`.',\n fix: 'Informational only. No action is required.',\n },\n [diagnosticCode.unsupportedFormat]: {\n title: 'Unsupported format',\n cause: 'A schema uses a `format` Kubb does not map to a specific type, so it falls back to the base type.',\n fix: 'Use a format Kubb supports, or handle the custom format with a parser or plugin.',\n },\n [diagnosticCode.deprecated]: {\n title: 'Deprecated',\n cause: 'A referenced schema or operation is marked `deprecated`.',\n fix: 'Migrate off the deprecated definition if the warning is unwanted.',\n },\n [diagnosticCode.adapterRequired]: {\n title: 'Adapter required',\n cause: 'An action needs an adapter but none is configured.',\n fix: 'Set `adapter` in kubb.config.ts, for example `adapterOas()`.',\n },\n [diagnosticCode.pathTraversal]: {\n title: 'Path traversal',\n cause: 'A resolved output path escaped the output directory, which can stem from a path traversal in the spec or a misconfigured `group.name`.',\n fix: 'Keep generated paths within the output directory. Review the `group.name` function and the names coming from the spec.',\n },\n [diagnosticCode.invalidPluginOptions]: {\n title: 'Invalid plugin options',\n cause: \"A plugin was configured with options that cannot be honored, for example `output.mode: 'file'` paired with a `group` option.\",\n fix: \"Fix the plugin options. A single-file output has nothing to group, so remove the `group` option or use `output.mode: 'directory'`.\",\n },\n [diagnosticCode.hookFailed]: {\n title: 'Hook failed',\n cause: 'A post-generate shell hook (`hooks.done`) exited with a non-zero status.',\n fix: 'Check the command is installed and correct, and run it manually to see the error.',\n },\n [diagnosticCode.formatFailed]: {\n title: 'Format failed',\n cause: 'The formatter pass over the generated files failed.',\n fix: 'Check the formatter (oxfmt, biome, or prettier) is installed and its config is valid, then run it manually on the output.',\n },\n [diagnosticCode.lintFailed]: {\n title: 'Lint failed',\n cause: 'The linter pass over the generated files failed.',\n fix: 'Check the linter (oxlint, biome, or eslint) is installed and its config is valid, then run it manually on the output.',\n },\n [diagnosticCode.performance]: {\n title: 'Performance',\n cause: 'Not a failure. Records a plugin’s elapsed time, summed into the run total.',\n fix: 'No action. This is an informational metric.',\n },\n [diagnosticCode.updateAvailable]: {\n title: 'Update available',\n cause: 'A newer Kubb version is published on npm than the one running.',\n fix: 'Update the `@kubb/*` packages, for example `npm install -g @kubb/cli`, to get the latest fixes.',\n },\n}\n\n/**\n * Static helpers for working with {@link Diagnostic}s, plus the run-scoped sink\n * that lets deep code report a diagnostic without threading a callback.\n *\n * The sink lives in a single `AsyncLocalStorage` in the `@kubb/core` bundle.\n * `Diagnostics.scope` activates it for a run, so anything inside that run (the\n * adapter parse, a lazily consumed stream, a generator) reports through\n * `Diagnostics.report` and lands in the same run.\n */\nexport class Diagnostics {\n static #reporterStorage = new AsyncLocalStorage<(diagnostic: Diagnostic) => void>()\n\n /**\n * The diagnostic code catalog, exposed as `Diagnostics.code` (e.g. `Diagnostics.code.refNotFound`).\n */\n static code = diagnosticCode\n\n /**\n * Type guard for a build {@link ProblemDiagnostic}.\n */\n static isProblem = isProblem\n\n /**\n * Type guard for a version-update {@link UpdateDiagnostic}.\n */\n static isUpdate = isUpdate\n\n /**\n * Type guard for a per-plugin {@link PerformanceDiagnostic}.\n */\n static isPerformance = isPerformance\n\n /**\n * Narrows a {@link Diagnostic} to the variant for `code`, or `null` when it does not match.\n */\n static narrow = narrow\n\n /**\n * An `Error` that carries a {@link Diagnostic}, so structured problems can flow\n * through the existing throw/catch paths while keeping their code and location.\n *\n * @example\n * ```ts\n * throw new Diagnostics.Error({ code: diagnosticCode.refNotFound, severity: 'error', message: `Could not find ${ref}`, location: { kind: 'schema', pointer: ref, ref } })\n * ```\n */\n static Error = class DiagnosticError extends Error {\n diagnostic: ProblemDiagnostic\n\n constructor(diagnostic: ProblemDiagnostic) {\n super(diagnostic.message, { cause: diagnostic.cause })\n this.name = 'DiagnosticError'\n this.diagnostic = diagnostic\n }\n }\n\n /**\n * Structural check for a {@link Diagnostics.Error}, including one thrown from a duplicated\n * `@kubb/core` copy where `instanceof` fails. Matches on the `name` and a `diagnostic`\n * that carries a `code`.\n */\n static isError(error: unknown): error is InstanceType<typeof Diagnostics.Error> {\n if (error instanceof Diagnostics.Error) {\n return true\n }\n return (\n error instanceof Error &&\n error.name === 'DiagnosticError' &&\n 'diagnostic' in error &&\n typeof (error as { diagnostic?: unknown }).diagnostic === 'object' &&\n (error as { diagnostic?: Diagnostic }).diagnostic !== null &&\n typeof (error as { diagnostic?: { code?: unknown } }).diagnostic?.code === 'string'\n )\n }\n\n /**\n * Runs `fn` with `sink` as the active diagnostic sink for the whole async\n * subtree, so {@link Diagnostics.report} reaches it from anywhere inside.\n */\n static scope<T>(sink: (diagnostic: Diagnostic) => void, fn: () => T): T {\n return Diagnostics.#reporterStorage.run(sink, fn)\n }\n\n /**\n * Collects a diagnostic into the active build via the run-scoped sink, without throwing.\n * Returns `true` when a run consumed it, `false` when called outside a {@link Diagnostics.scope}\n * (so callers can fall back to throwing). Use a `warning`/`info` severity for non-fatal issues.\n * For rendering a diagnostic live on the hook bus, use {@link Diagnostics.emit} instead.\n */\n static report(diagnostic: Diagnostic): boolean {\n const sink = Diagnostics.#reporterStorage.getStore()\n if (!sink) {\n return false\n }\n sink(diagnostic)\n return true\n }\n\n /**\n * Emits a diagnostic on the run's `kubb:diagnostic` event so the loggers render it live.\n * Use it instead of calling `hooks.emit('kubb:diagnostic', ...)` directly. To collect a\n * diagnostic into the build result from deep in a run, use {@link Diagnostics.report} instead.\n */\n static async emit(hooks: AsyncEventEmitter<KubbHooks>, diagnostic: ProblemDiagnostic | UpdateDiagnostic): Promise<void> {\n await hooks.emit('kubb:diagnostic', { diagnostic })\n }\n\n /**\n * Coerces any thrown value into a {@link ProblemDiagnostic}. A {@link Diagnostics.Error}\n * keeps its structured data, and anything else becomes a `KUBB_UNKNOWN` error.\n */\n static from(error: unknown): ProblemDiagnostic {\n // The event emitter and BuildError wrap the original, so walk the cause chain to\n // recover a Diagnostics.Error thrown deeper down. `root` tracks the deepest error so\n // the unknown diagnostic reports the original message and stack, not the wrapper's.\n const seen = new Set<unknown>()\n let current: unknown = error\n let root: Error | undefined\n while (current instanceof Error && !seen.has(current)) {\n // Match structurally, not just by `instanceof`: a `Diagnostics.Error` thrown from a\n // duplicated `@kubb/core` copy (bundled into an adapter or plugin) is a different\n // class, but still carries the same `diagnostic`, so its code must survive.\n if (Diagnostics.isError(current)) {\n return current.diagnostic\n }\n seen.add(current)\n root = current\n current = current.cause\n }\n\n return {\n code: diagnosticCode.unknown,\n severity: 'error',\n message: root ? root.message : getErrorMessage(error),\n cause: root,\n }\n }\n\n /**\n * Builds a per-plugin performance record. Reporters sum these into the run total.\n */\n static performance({ plugin, duration }: { plugin: string; duration: number }): PerformanceDiagnostic {\n return {\n kind: 'performance',\n code: diagnosticCode.performance,\n severity: 'info',\n message: `${plugin} generated in ${Math.round(duration)}ms`,\n plugin,\n duration,\n }\n }\n\n /**\n * Builds the version-update notice shown when a newer Kubb is published on npm.\n */\n static update({ currentVersion, latestVersion }: { currentVersion: string; latestVersion: string }): UpdateDiagnostic {\n return {\n kind: 'update',\n code: diagnosticCode.updateAvailable,\n severity: 'info',\n message: `Update available: v${currentVersion} → v${latestVersion}. Run \\`npm install -g @kubb/cli\\` to update.`,\n currentVersion,\n latestVersion,\n }\n }\n\n /**\n * True when any diagnostic is an error, the severity that fails a build. Non-error\n * diagnostics are ignored.\n */\n static hasError(diagnostics: ReadonlyArray<Diagnostic>): boolean {\n return diagnostics.some((diagnostic) => diagnostic.severity === 'error')\n }\n\n /**\n * Names of the plugins that failed, deduped, derived from the error diagnostics\n * that carry a `plugin`.\n */\n static failedPlugins(diagnostics: ReadonlyArray<Diagnostic>): Array<string> {\n const names = new Set<string>()\n for (const diagnostic of diagnostics) {\n if (diagnostic.severity === 'error' && diagnostic.plugin) {\n names.add(diagnostic.plugin)\n }\n }\n return [...names]\n }\n\n /**\n * Counts `problem` diagnostics by severity for the run summary. `performance` and\n * `update` diagnostics are ignored.\n */\n static count(diagnostics: ReadonlyArray<Diagnostic>): { errors: number; warnings: number; infos: number } {\n let errors = 0\n let warnings = 0\n let infos = 0\n for (const diagnostic of diagnostics) {\n if (!isProblem(diagnostic)) {\n continue\n }\n if (diagnostic.severity === 'error') {\n errors += 1\n } else if (diagnostic.severity === 'warning') {\n warnings += 1\n } else {\n infos += 1\n }\n }\n return { errors, warnings, infos }\n }\n\n /**\n * Drops duplicate `problem` diagnostics that share a code, location pointer, and\n * plugin, so the same issue reported across several passes is shown once. Non-problem\n * diagnostics are always kept.\n */\n static dedupe(diagnostics: ReadonlyArray<Diagnostic>): Array<Diagnostic> {\n const seen = new Set<string>()\n const result: Array<Diagnostic> = []\n for (const diagnostic of diagnostics) {\n if (!isProblem(diagnostic)) {\n result.push(diagnostic)\n continue\n }\n const pointer = diagnostic.location && 'pointer' in diagnostic.location ? diagnostic.location.pointer : ''\n const key = `${diagnostic.code} ${pointer} ${diagnostic.plugin ?? ''}`\n if (seen.has(key)) {\n continue\n }\n seen.add(key)\n result.push(diagnostic)\n }\n return result\n }\n\n /**\n * Builds the kubb.dev docs URL for a diagnostic code, e.g.\n * `KUBB_REF_NOT_FOUND` → `https://kubb.dev/docs/5.x/reference/diagnostics/kubb-ref-not-found`.\n */\n static docsUrl(code: string): string {\n const slug = code.toLowerCase().replaceAll('_', '-')\n return `https://kubb.dev/docs/${docsMajor}.x/reference/diagnostics/${slug}`\n }\n\n /**\n * The catalog entry for a code: its title, cause, and fix. Mirrors the kubb.dev\n * `/diagnostics/<slug>` page.\n */\n static explain(code: DiagnosticCode): DiagnosticDoc {\n return diagnosticCatalog[code]\n }\n\n /**\n * Reduces a diagnostic to its JSON-safe fields plus a `docsUrl`, for machine-readable\n * consumers. The `cause`, `kind`, and `duration` are dropped, and absent optional\n * fields are omitted rather than set to `undefined`.\n */\n static serialize(diagnostic: Diagnostic): SerializedDiagnostic {\n const problem = isProblem(diagnostic) ? diagnostic : undefined\n return {\n code: diagnostic.code,\n severity: diagnostic.severity,\n message: diagnostic.message,\n ...(problem?.location ? { location: problem.location } : {}),\n ...(problem?.help ? { help: problem.help } : {}),\n ...(problem?.plugin ? { plugin: problem.plugin } : {}),\n ...(diagnostic.code === diagnosticCode.unknown ? {} : { docsUrl: Diagnostics.docsUrl(diagnostic.code) }),\n }\n }\n\n /**\n * Renders a {@link Diagnostic} for terminal output as its parts: the `headline`\n * (`[CODE] plugin: message`, with the code in the severity color) and the indented `details`\n * rows (`at:` pointer, `fix:` help, `see:` docs link).\n *\n * Hosts compose these to fit their gutter: a clack logger passes `[headline, ...details]` as the\n * message with no gutter symbol, while plain text outputs use {@link Diagnostics.formatLines}.\n */\n static format(diagnostic: Diagnostic): { headline: string; details: Array<string> } {\n const { code, severity, message } = diagnostic\n const { color } = severityStyle[severity]\n const problem = isProblem(diagnostic) ? diagnostic : undefined\n\n const tag = styleText(color, styleText('bold', `[${code}]`))\n const headline = problem?.plugin ? `${tag} ${problem.plugin}: ${message}` : `${tag}: ${message}`\n\n const details: Array<string> = []\n if (problem?.location && 'pointer' in problem.location) {\n details.push(` ${styleText('dim', 'at:')} ${styleText('cyan', problem.location.pointer)}`)\n }\n if (problem?.help) {\n details.push(` ${styleText('cyan', 'fix:')} ${problem.help}`)\n }\n if (code !== diagnosticCode.unknown) {\n details.push(` ${styleText('dim', 'see:')} ${styleText('cyan', Diagnostics.docsUrl(code))}`)\n }\n\n return { headline, details }\n }\n\n /**\n * The self-contained block form of {@link Diagnostics.format}: the `headline` followed by the\n * indented detail rows. Used where there is no gutter (plain and file output).\n */\n static formatLines(diagnostic: Diagnostic): Array<string> {\n const { headline, details } = Diagnostics.format(diagnostic)\n return [headline, ...details]\n }\n}\n","import type { Enforce, FileNode, HttpMethod, Macro, UserFileNode } from '@kubb/ast'\nimport { diagnosticCode } from './constants.ts'\nimport type { Generator } from './defineGenerator.ts'\nimport type { BannerMeta, Resolver } from './defineResolver.ts'\nimport { Diagnostics } from './diagnostics.ts'\nimport type { Config, KubbHooks } from './types.ts'\n\n/**\n * Reads a type from a registry, falling back to `{}` when the key is absent. Lets\n * `Kubb.ConfigOptionsRegistry` and `Kubb.PluginOptionsRegistry` be augmented without\n * touching core.\n *\n * @internal\n */\ntype ExtractRegistryKey<T, K extends PropertyKey> = K extends keyof T ? T[K] : {}\n\n/**\n * How a plugin consolidates its generated code into files.\n * - `'directory'` writes one file per operation or schema under `path`.\n * - `'file'` writes everything into a single file.\n */\nexport type OutputMode = 'directory' | 'file'\n\n/**\n * Output configuration shared by every plugin. Each plugin extends this with\n * its own keys via the `Kubb.PluginOptionsRegistry.output` interface merge.\n */\nexport type Output<_TOptions = unknown> = {\n /**\n * Directory where the plugin writes its generated code, resolved against the global\n * `output.path` set on `defineConfig`. With `mode: 'file'`, this is the full output file\n * path and must include the extension (e.g. `'types.ts'`, `'models.py'`).\n */\n path: string\n /**\n * How generated code is consolidated into files.\n * - `'directory'` writes one file per operation or schema under `path`.\n * - `'file'` writes everything into a single file. The `path` must include the file extension.\n *\n * @default 'directory'\n */\n mode?: OutputMode\n /**\n * Text prepended to every generated file. Useful for license headers,\n * lint disables, or `@ts-nocheck` directives.\n *\n * A string is applied to every file (including barrel and aggregation re-export files).\n * Pass a function to compute the banner from the file's `BannerMeta` document metadata\n * plus per-file context (`isBarrel`, `isAggregation`, `filePath`, `baseName`), so you can\n * skip the banner on specific files.\n *\n * @example Add a directive to source files but not re-export files\n * `banner: (meta) => (meta.isBarrel || meta.isAggregation) ? '' : \"'use server'\"`\n */\n banner?: string | ((meta: BannerMeta) => string)\n /**\n * Text appended at the end of every generated file. Mirror of `banner`.\n * Pass a function to compute the footer from the file's `BannerMeta`.\n */\n footer?: string | ((meta: BannerMeta) => string)\n /**\n * Allows the plugin to overwrite hand-written files at the same path.\n * Defaults to `false` to protect manual edits.\n *\n * @default false\n */\n override?: boolean\n} & ExtractRegistryKey<Kubb.PluginOptionsRegistry, 'output'>\n\n/**\n * Groups generated files into subdirectories based on an OpenAPI tag or path\n * segment.\n */\nexport type Group = {\n /**\n * Property used to assign each operation to a group.\n * - `'tag'` uses the first tag (`operation.getTags().at(0)?.name`).\n * - `'path'` uses the first segment of the operation's URL.\n */\n type: 'tag' | 'path'\n /**\n * Returns the subdirectory name from the group key. Defaults to the camelCased tag for\n * `tag` groups, or the camelCased first path segment for `path` groups.\n */\n name?: (context: { group: string }) => string\n}\n\n/**\n * Couples `output.mode` with the plugin's `group` option at the type level.\n * - `mode: 'file'` forbids `group` (a single file has nothing to group).\n * - `mode: 'directory'` (or no mode) allows an optional `group` to organize\n * files into per-group subdirectories.\n *\n * Intersect into a plugin's `Options` type instead of declaring `output` and\n * `group` directly, since `mode` lives inside `output` while `group` is its sibling.\n * The generic keeps a plugin's extended `Output` shape intact.\n *\n * @example\n * ```ts\n * export type Options = OutputOptions & {\n * exclude?: Array<Exclude>\n * }\n * ```\n */\nexport type OutputOptions<TOutput extends Output = Output> =\n | {\n output?: TOutput & { mode?: 'directory' }\n group?: Group\n }\n | {\n output: TOutput & { mode: 'file' }\n group?: never\n }\n\n/**\n * Merges the `output.mode` default into the output config and validates the combination.\n * Throws `KUBB_INVALID_PLUGIN_OPTIONS` when `mode: 'file'` is paired with a `group` option,\n * since a single-file output has nothing to group.\n */\nexport function normalizeOutput({ output, group, pluginName }: { output: Output; group?: Group | null; pluginName: string }): Output {\n const mode = output.mode ?? 'directory'\n\n if (mode === 'file' && group) {\n throw new Diagnostics.Error({\n code: diagnosticCode.invalidPluginOptions,\n severity: 'error',\n message: `Plugin \"${pluginName}\" sets \\`output.mode: 'file'\\` but also configures a \\`group\\` option.`,\n help: \"A single-file output has nothing to group. Remove the `group` option, or use `output.mode: 'directory'` to organize files into subdirectories.\",\n location: { kind: 'config' },\n plugin: pluginName,\n })\n }\n\n return { ...output, mode }\n}\n\ntype ByTag = {\n /**\n * Filter by OpenAPI `tags` field. Matches one or more tags assigned to operations.\n */\n type: 'tag'\n /**\n * Tag name to match (case-sensitive). Can be a literal string or regex pattern.\n */\n pattern: string | RegExp\n}\n\ntype ByOperationId = {\n /**\n * Filter by OpenAPI `operationId` field. Each operation (GET, POST, etc.) has a unique identifier.\n */\n type: 'operationId'\n /**\n * Operation ID to match (case-sensitive). Can be a literal string or regex pattern.\n */\n pattern: string | RegExp\n}\n\ntype ByPath = {\n /**\n * Filter by OpenAPI `path` (URL endpoint). Useful to group or filter by service segments like `/pets`, `/users`, etc.\n */\n type: 'path'\n /**\n * URL path to match (case-sensitive). Can be a literal string or regex pattern. Matches against the full path.\n */\n pattern: string | RegExp\n}\n\ntype ByMethod = {\n /**\n * Filter by HTTP method: `'GET'`, `'POST'`, `'PUT'`, `'PATCH'`, `'DELETE'`, `'HEAD'`, `'OPTIONS'`, `'TRACE'`.\n */\n type: 'method'\n /**\n * HTTP method to match, as one of the `HttpMethod` values (`'GET'`, `'POST'`, `'PUT'`,\n * `'PATCH'`, `'DELETE'`, `'HEAD'`, `'OPTIONS'`, `'TRACE'`) or a regex.\n */\n pattern: HttpMethod | RegExp\n}\n\ntype BySchemaName = {\n /**\n * Filter by schema component name (TypeScript or JSON schema). Matches schemas in `#/components/schemas`.\n */\n type: 'schemaName'\n /**\n * Schema name to match (case-sensitive). Can be a literal string or regex pattern.\n */\n pattern: string | RegExp\n}\n\ntype ByContentType = {\n /**\n * Filter by response or request content type: `'application/json'`, `'application/xml'`, etc.\n */\n type: 'contentType'\n /**\n * Content type to match (case-sensitive). Can be a literal string or regex pattern.\n */\n pattern: string | RegExp\n}\n\n/**\n * Filter that skips matching operations or schemas during generation, for example\n * deprecated endpoints or internal-only schemas.\n *\n * @example\n * ```ts\n * exclude: [\n * { type: 'tag', pattern: 'internal' },\n * { type: 'path', pattern: /^\\/admin/ },\n * { type: 'operationId', pattern: /^deprecated_/ },\n * ]\n * ```\n */\nexport type Exclude = ByTag | ByOperationId | ByPath | ByMethod | ByContentType | BySchemaName\n\n/**\n * Filter that restricts generation to operations or schemas matching at least\n * one entry. Useful for partial builds (one tag, one API version).\n *\n * @example\n * ```ts\n * include: [\n * { type: 'tag', pattern: 'public' },\n * { type: 'path', pattern: /^\\/api\\/v1/ },\n * ]\n * ```\n */\nexport type Include = ByTag | ByOperationId | ByPath | ByMethod | ByContentType | BySchemaName\n\n/**\n * Filter paired with a partial options object. When the filter matches, the\n * options are merged on top of the plugin defaults for that operation only.\n * Useful for \"this one tag goes to a different folder\" rules.\n *\n * Entries are evaluated top to bottom. The first matching entry wins.\n *\n * @example\n * ```ts\n * override: [\n * {\n * type: 'tag',\n * pattern: 'admin',\n * options: { output: { path: './src/gen/admin' } },\n * },\n * {\n * type: 'operationId',\n * pattern: 'listPets',\n * options: { enumType: 'literal' },\n * },\n * ]\n * ```\n */\nexport type Override<TOptions> = (ByTag | ByOperationId | ByPath | ByMethod | BySchemaName | ByContentType) & {\n options: Omit<Partial<TOptions>, 'override'>\n}\n\nexport type PluginFactoryOptions<\n /**\n * Unique plugin name.\n */\n TName extends string = string,\n /**\n * User-facing plugin options.\n */\n TOptions extends object = object,\n /**\n * Plugin options after defaults are applied.\n */\n TResolvedOptions extends object = TOptions,\n /**\n * Resolver that encapsulates naming and path-resolution helpers.\n * Define with `defineResolver` and export alongside the plugin.\n */\n TResolver extends Resolver = Resolver,\n> = {\n name: TName\n options: TOptions\n resolvedOptions: TResolvedOptions\n resolver: TResolver\n}\n\n/**\n * Context passed to a plugin's `kubb:plugin:setup` handler, where it registers generators and\n * sets its resolver, transformer, and options.\n */\nexport type KubbPluginSetupContext<TFactory extends PluginFactoryOptions = PluginFactoryOptions> = {\n /**\n * Register a generator dynamically. Generators fire during the AST walk (schema/operation/operations)\n * just like generators declared statically on `createPlugin`.\n */\n addGenerator<TElement = unknown>(generator: Generator<TFactory, TElement>): void\n /**\n * Set or override the resolver for this plugin.\n * The resolver controls file naming and path resolution.\n */\n setResolver(resolver: Partial<TFactory['resolver']>): void\n /**\n * Add a macro that rewrites AST nodes before they reach generators. Macros run in the order they\n * are added, after any macros from earlier `addMacro` calls.\n */\n addMacro(macro: Macro): void\n /**\n * Replace this plugin's macros with `macros`.\n */\n setMacros(macros: ReadonlyArray<Macro>): void\n /**\n * Set resolved options merged into the normalized plugin's `options`.\n * Call this in `kubb:plugin:setup` to provide options generators need.\n */\n setOptions(options: TFactory['resolvedOptions']): void\n /**\n * Inject a raw file into the build output, bypassing the generation pipeline.\n */\n injectFile(userFileNode: UserFileNode): void\n /**\n * Merge a partial config update into the current build configuration.\n */\n updateConfig(config: Partial<Config>): void\n /**\n * The resolved build configuration at setup time.\n */\n config: Config\n /**\n * The plugin's user-provided options.\n */\n options: TFactory['options']\n}\n\n/**\n * A plugin object produced by `definePlugin`. Its lifecycle handlers live under a single\n * `hooks` property rather than flat methods.\n */\nexport type Plugin<TFactory extends PluginFactoryOptions = PluginFactoryOptions> = {\n /**\n * Unique name for the plugin, following the same naming convention as `createPlugin`.\n */\n name: string\n /**\n * Plugins that must be registered before this plugin executes.\n * An error is thrown at startup when any listed dependency is missing.\n */\n dependencies?: Array<string>\n /**\n * Controls the execution order of this plugin relative to others.\n *\n * - `'pre'` runs before all normal plugins.\n * - `'post'` runs after all normal plugins.\n * - `undefined` (default) runs in declaration order among normal plugins.\n *\n * Dependency constraints always take precedence over `enforce`.\n */\n enforce?: Enforce\n /**\n * The options passed by the user when calling the plugin factory.\n */\n options?: TFactory['options']\n /**\n * Lifecycle event handlers for this plugin.\n * Any event from the global `KubbHooks` map can be subscribed to here.\n */\n hooks: {\n [K in keyof KubbHooks as K extends 'kubb:plugin:setup' ? never : K]?: (...args: KubbHooks[K]) => void | Promise<void>\n } & {\n 'kubb:plugin:setup'?(ctx: KubbPluginSetupContext<TFactory>): void | Promise<void>\n }\n}\n\n/**\n * Normalized plugin after setup, with runtime fields populated. Internal only. Plugins use the\n * public `Plugin` type.\n *\n * @internal\n */\nexport type NormalizedPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = Plugin<TOptions> & {\n options: TOptions['resolvedOptions'] & {\n output: Output\n include?: Array<Include>\n exclude: Array<Exclude>\n override: Array<Override<TOptions['resolvedOptions']>>\n }\n resolver: TOptions['resolver']\n macros?: Array<Macro>\n generators?: Array<Generator>\n apply?: (config: Config) => boolean\n version?: string\n}\n\nexport type KubbPluginStartContext = {\n plugin: NormalizedPlugin\n}\n\nexport type KubbPluginEndContext = {\n plugin: NormalizedPlugin\n duration: number\n success: boolean\n error?: Error\n config: Config\n /**\n * Returns all files currently in the file manager (lazy snapshot).\n * Includes files added by plugins that have already run.\n */\n readonly files: ReadonlyArray<FileNode>\n /**\n * Upsert one or more files into the file manager.\n */\n upsertFile: (...files: Array<FileNode>) => void\n}\n\n/**\n * Wraps a plugin factory and returns a function that accepts user options and\n * yields a typed `Plugin`. Lifecycle handlers go inside a single `hooks` object.\n *\n * Pass a `PluginFactoryOptions` type parameter to get a typed `ctx` inside\n * `kubb:plugin:setup`. Plugin names should follow the `plugin-<feature>`\n * convention (`plugin-react-query`, `plugin-zod`, ...).\n *\n * @example\n * ```ts\n * import { definePlugin } from '@kubb/core'\n *\n * export const pluginTs = definePlugin((options: { prefix?: string } = {}) => ({\n * name: 'plugin-ts',\n * hooks: {\n * 'kubb:plugin:setup'(ctx) {\n * ctx.setResolver(resolverTs)\n * },\n * },\n * }))\n * ```\n */\nexport function definePlugin<TFactory extends PluginFactoryOptions = PluginFactoryOptions>(\n factory: (options: TFactory['options']) => Plugin<TFactory>,\n): (options?: TFactory['options']) => Plugin<TFactory> {\n return (options) => factory(options ?? ({} as TFactory['options']))\n}\n","import path from 'node:path'\nimport { camelCase, pascalCase, toFilePath } from '@internals/utils'\nimport { ast, operationDef, schemaDef, type FileNode, type InputMeta, type Node, type OperationNode, type SchemaNode } from '@kubb/ast'\nimport { Diagnostics } from './diagnostics.ts'\nimport type { PluginFactoryOptions } from './definePlugin.ts'\nimport type { Config, Group, Output } from './types.ts'\n\n/**\n * Type/string pattern filter for include/exclude/override matching.\n */\ntype PatternFilter = {\n type: string\n pattern: string | RegExp\n}\n\n/**\n * Pattern filter with partial option overrides applied when the pattern matches.\n */\ntype PatternOverride<TOptions> = PatternFilter & {\n options: Omit<Partial<TOptions>, 'override'>\n}\n\n/**\n * Context for resolving filtered options for a given operation or schema node.\n *\n * @internal\n */\nexport type ResolveOptionsContext<TOptions> = {\n options: TOptions\n exclude?: Array<PatternFilter>\n include?: Array<PatternFilter>\n override?: Array<PatternOverride<TOptions>>\n}\n\n/**\n * Base constraint for all plugin resolver objects.\n *\n * `default`, `resolveOptions`, `resolvePath`, `resolveFile`, `resolveBanner`, and `resolveFooter`\n * are injected automatically by `defineResolver`. Extend this type to add custom resolution methods.\n *\n * @example\n * ```ts\n * type MyResolver = Resolver & {\n * resolveName(node: SchemaNode): string\n * resolveTypedName(node: SchemaNode): string\n * }\n * ```\n */\nexport type Resolver = {\n name: string\n pluginName: string\n default(name: string, type?: 'file' | 'function' | 'type' | 'const'): string\n resolveOptions<TOptions>(node: Node, context: ResolveOptionsContext<TOptions>): TOptions | null\n resolvePath(params: ResolverPathParams, context: ResolverContext): string\n resolveFile(params: ResolverFileParams, context: ResolverContext): FileNode\n resolveBanner(meta: InputMeta | undefined, context: ResolveBannerContext): string | null\n resolveFooter(meta: InputMeta | undefined, context: ResolveBannerContext): string | null\n}\n\n/**\n * File-specific parameters for `Resolver.resolvePath`.\n *\n * Pass alongside a `ResolverContext` to identify which file to resolve.\n * Provide `tag` for tag-based grouping or `path` for path-based grouping.\n *\n * @example\n * ```ts\n * resolver.resolvePath(\n * { baseName: 'petTypes.ts', tag: 'pets' },\n * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },\n * )\n * // → '/src/types/pets/petTypes.ts'\n * ```\n */\nexport type ResolverPathParams = {\n baseName: FileNode['baseName']\n /**\n * Tag value used when `group.type === 'tag'`.\n */\n tag?: string\n /**\n * Path value used when `group.type === 'path'`.\n */\n path?: string\n}\n\n/**\n * Shared context passed as the second argument to `Resolver.resolvePath` and `Resolver.resolveFile`.\n *\n * Describes where on disk output is rooted, which output config is active, and the optional\n * grouping strategy that controls subdirectory layout.\n *\n * @example\n * ```ts\n * const context: ResolverContext = {\n * root: config.root,\n * output,\n * group,\n * }\n * ```\n */\nexport type ResolverContext = {\n root: string\n output: Output\n group?: Group\n /**\n * Plugin name used to populate `meta.pluginName` on the resolved file.\n */\n pluginName?: string\n}\n\n/**\n * File-specific parameters for `Resolver.resolveFile`.\n *\n * Pass alongside a `ResolverContext` to fully describe the file to resolve.\n * `tag` and `path` are used only when a matching `group` is present in the context.\n *\n * @example\n * ```ts\n * resolver.resolveFile(\n * { name: 'listPets', extname: '.ts', tag: 'pets' },\n * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },\n * )\n * // → { baseName: 'listPets.ts', path: '/src/types/pets/listPets.ts', ... }\n * ```\n */\nexport type ResolverFileParams = {\n name: string\n extname: FileNode['extname']\n /**\n * Tag value used when `group.type === 'tag'`.\n */\n tag?: string\n /**\n * Path value used when `group.type === 'path'`.\n */\n path?: string\n}\n\n/**\n * Per-file context describing the file a banner/footer is being resolved for.\n *\n * Supplied by the generator (or the barrel plugin) at resolve-time and merged\n * into `BannerMeta` so a `banner`/`footer` function can branch on the file kind,\n * e.g. omit a `'use server'` directive on re-export files.\n */\nexport type ResolveBannerFile = {\n /**\n * Full output path of the file being generated.\n */\n path: string\n /**\n * File name only, e.g. `'stocks.ts'`.\n */\n baseName: string\n /**\n * `true` for `index.ts` re-export barrels.\n */\n isBarrel?: boolean\n /**\n * `true` for group `[dir]/[dir].ts` aggregation files.\n */\n isAggregation?: boolean\n}\n\n/**\n * Document metadata extended with per-file context, passed to a `banner`/`footer` function.\n *\n * Carries everything in {@link InputMeta} plus the file the banner is rendered into, so a\n * single function can decide per file (e.g. skip a directive on barrel/aggregation files).\n *\n * @example Skip a directive on re-export files\n * `banner: (meta) => (meta.isBarrel || meta.isAggregation) ? '' : \"'use server'\"`\n */\nexport type BannerMeta = InputMeta & {\n /**\n * Full output path of the file being generated.\n */\n filePath: string\n /**\n * File name only, e.g. `'stocks.ts'`.\n */\n baseName: string\n /**\n * `true` for `index.ts` re-export barrels.\n */\n isBarrel: boolean\n /**\n * `true` for group `[dir]/[dir].ts` aggregation files.\n */\n isAggregation: boolean\n}\n\n/**\n * Context passed to `Resolver.resolveBanner` and `Resolver.resolveFooter`.\n *\n * `output` is optional, since not every plugin configures a banner/footer.\n * `config` carries the global Kubb config, used to derive the default Kubb banner.\n * `file` carries per-file context forwarded to a `banner`/`footer` function.\n *\n * @example\n * ```ts\n * resolver.resolveBanner(meta, { output: { banner: '// generated' }, config })\n * // → '// generated'\n * ```\n */\nexport type ResolveBannerContext = {\n output?: Pick<Output, 'banner' | 'footer'>\n config: Config\n file?: ResolveBannerFile\n}\n\n/**\n * Merges document `meta` with per-file `file` context into the `BannerMeta` passed to a\n * `banner`/`footer` function. Missing fields default to empty/`false` so the object shape\n * is stable even when a caller (e.g. the barrel plugin) has no document metadata.\n */\nfunction buildBannerMeta({ meta, file }: { meta: InputMeta | undefined; file: ResolveBannerFile | undefined }): BannerMeta {\n return {\n title: meta?.title,\n description: meta?.description,\n version: meta?.version,\n baseURL: meta?.baseURL,\n circularNames: meta?.circularNames ?? [],\n enumNames: meta?.enumNames ?? [],\n filePath: file?.path ?? '',\n baseName: file?.baseName ?? '',\n isBarrel: file?.isBarrel ?? false,\n isAggregation: file?.isAggregation ?? false,\n }\n}\n\n/**\n * Builder type for the plugin-specific resolver fields.\n *\n * `default`, `resolveOptions`, `resolvePath`, `resolveFile`, `resolveBanner`, and `resolveFooter`\n * are optional, with built-in fallbacks injected when omitted.\n *\n * Methods in the returned object can call sibling resolver methods via `this`.\n */\ntype ResolverBuilder<T extends PluginFactoryOptions> = () => Omit<\n T['resolver'],\n 'default' | 'resolveOptions' | 'resolvePath' | 'resolveFile' | 'resolveBanner' | 'resolveFooter' | 'name' | 'pluginName'\n> &\n Partial<Pick<T['resolver'], 'default' | 'resolveOptions' | 'resolvePath' | 'resolveFile' | 'resolveBanner' | 'resolveFooter'>> & {\n name: string\n pluginName: T['name']\n } & ThisType<T['resolver']>\n\n// String patterns are compiled lazily and cached, so the same filter is reused for every node.\nconst stringPatternCache = new Map<string, RegExp>()\n\nfunction testPattern(value: string, pattern: string | RegExp): boolean {\n if (typeof pattern === 'string') {\n let regex = stringPatternCache.get(pattern)\n if (!regex) {\n regex = new RegExp(pattern)\n stringPatternCache.set(pattern, regex)\n }\n return regex.test(value)\n }\n // Use .match() for user-supplied RegExp to preserve semantics regardless of `g`/`y` flags.\n return value.match(pattern) !== null\n}\n\n/**\n * Checks if an operation matches a pattern for a given filter type (`tag`, `operationId`, `path`, `method`).\n */\nfunction matchesOperationPattern(node: OperationNode, type: string, pattern: string | RegExp): boolean {\n if (type === 'tag') return node.tags.some((tag) => testPattern(tag, pattern))\n if (type === 'operationId') return testPattern(node.operationId, pattern)\n if (type === 'path') return node.path !== undefined && testPattern(node.path, pattern)\n if (type === 'method') return node.method !== undefined && testPattern(node.method.toLowerCase(), pattern)\n if (type === 'contentType') return node.requestBody?.content?.some((c) => testPattern(c.contentType, pattern)) ?? false\n return false\n}\n\n/**\n * Checks if a schema matches a pattern for a given filter type (`schemaName`).\n *\n * Returns `null` when the filter type doesn't apply to schemas.\n */\nfunction matchesSchemaPattern(node: SchemaNode, type: string, pattern: string | RegExp): boolean | null {\n if (type === 'schemaName') return node.name ? testPattern(node.name, pattern) : false\n return null\n}\n\n/**\n * Default name resolver used by `defineResolver`.\n *\n * - `camelCase` for `file`, with dotted names split into `/`-joined nested paths.\n * - `PascalCase` for `type`.\n * - `camelCase` for `function` and everything else.\n */\nfunction defaultResolver(name: string, type?: 'file' | 'function' | 'type' | 'const'): string {\n if (type === 'file') return toFilePath(name)\n if (type === 'type') return pascalCase(name)\n return camelCase(name)\n}\n\n/**\n * Default option resolver. Applies include/exclude filters and merges matching override options.\n *\n * Returns `null` when the node is filtered out by an `exclude` rule or not matched by any `include` rule.\n *\n * @example Include/exclude filtering\n * ```ts\n * const options = defaultResolveOptions(operationNode, {\n * options: { output: 'types' },\n * exclude: [{ type: 'tag', pattern: 'internal' }],\n * })\n * // → null when node has tag 'internal'\n * ```\n *\n * @example Override merging\n * ```ts\n * const options = defaultResolveOptions(operationNode, {\n * options: { enumType: 'asConst' },\n * override: [{ type: 'operationId', pattern: 'listPets', options: { enumType: 'enum' } }],\n * })\n * // → { enumType: 'enum' } when operationId matches\n * ```\n */\nconst resolveOptionsCache = new WeakMap<object, WeakMap<Node, { value: unknown }>>()\n\nfunction computeOptions<TOptions>(\n node: Node,\n options: TOptions,\n exclude: Array<PatternFilter>,\n include: Array<PatternFilter> | undefined,\n override: Array<PatternOverride<TOptions>>,\n): TOptions | null {\n if (operationDef.is(node)) {\n if (exclude.some(({ type, pattern }) => matchesOperationPattern(node, type, pattern))) return null\n if (include && !include.some(({ type, pattern }) => matchesOperationPattern(node, type, pattern))) return null\n\n const overrideOptions = override.find(({ type, pattern }) => matchesOperationPattern(node, type, pattern))?.options\n\n return { ...options, ...overrideOptions }\n }\n\n if (schemaDef.is(node)) {\n if (exclude.some(({ type, pattern }) => matchesSchemaPattern(node, type, pattern) === true)) return null\n if (include) {\n const results = include.map(({ type, pattern }) => matchesSchemaPattern(node, type, pattern))\n const applicable = results.filter((result) => result !== null)\n\n if (applicable.length > 0 && !applicable.includes(true)) return null\n }\n const overrideOptions = override.find(({ type, pattern }) => matchesSchemaPattern(node, type, pattern) === true)?.options\n\n return { ...options, ...overrideOptions }\n }\n\n return options\n}\n\nfunction defaultResolveOptions<TOptions>(node: Node, { options, exclude = [], include, override = [] }: ResolveOptionsContext<TOptions>): TOptions | null {\n const optionsKey = options as object\n let byOptions = resolveOptionsCache.get(optionsKey)\n if (!byOptions) {\n byOptions = new WeakMap()\n resolveOptionsCache.set(optionsKey, byOptions)\n }\n const cached = byOptions.get(node)\n if (cached !== undefined) return cached.value as TOptions | null\n\n const result = computeOptions(node, options, exclude, include, override)\n\n byOptions.set(node, { value: result })\n\n return result\n}\n\n/**\n * Default path resolver used by `defineResolver`.\n *\n * - `mode: 'file'` resolves directly to `output.path` (the full file path, extension included).\n * - `mode: 'directory'` (default) resolves to `output.path/{baseName}`, or into a\n * subdirectory when `group` and a `tag`/`path` value are provided.\n *\n * A custom `group.name` function overrides the default subdirectory naming.\n * For `tag` groups the default is the camelCased tag.\n * For `path` groups the default is the first path segment after `/`.\n *\n * @example Flat output\n * ```ts\n * defaultResolvePath({ baseName: 'petTypes.ts' }, { root: '/src', output: { path: 'types' } })\n * // → '/src/types/petTypes.ts'\n * ```\n *\n * @example Tag-based grouping\n * ```ts\n * defaultResolvePath(\n * { baseName: 'petTypes.ts', tag: 'pets' },\n * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },\n * )\n * // → '/src/types/pets/petTypes.ts'\n * ```\n *\n * @example Path-based grouping\n * ```ts\n * defaultResolvePath(\n * { baseName: 'petTypes.ts', path: '/pets/list' },\n * { root: '/src', output: { path: 'types' }, group: { type: 'path' } },\n * )\n * // → '/src/types/pets/petTypes.ts'\n * ```\n *\n * @example Single file (`mode: 'file'`)\n * ```ts\n * defaultResolvePath(\n * { baseName: 'petTypes.ts' },\n * { root: '/src', output: { path: 'types.ts', mode: 'file' } },\n * )\n * // → '/src/types.ts'\n * ```\n */\nexport function defaultResolvePath({ baseName, tag, path: groupPath }: ResolverPathParams, { root, output, group }: ResolverContext): string {\n const mode = output.mode ?? 'directory'\n\n if (mode === 'file') {\n return path.resolve(root, output.path)\n }\n\n const result: string = (() => {\n if (group && (groupPath || tag)) {\n const groupValue = group.type === 'path' ? groupPath! : tag!\n const defaultName =\n group.type === 'tag'\n ? ({ group: groupName }: { group: string }) => camelCase(groupName)\n : ({ group: groupName }: { group: string }) => {\n // Strip traversal components (empty, '.', '..') before taking the first meaningful segment.\n // When every segment is a traversal component (e.g. '../../') we fall back to '' so the\n // file is placed directly in the output root, and the boundary check below ensures safety.\n const segment = groupName.split('/').filter((part) => part !== '' && part !== '.' && part !== '..')[0]\n return segment ? camelCase(segment) : ''\n }\n const resolveName = group.name ?? defaultName\n const groupName = resolveName({ group: groupValue })\n\n return path.resolve(root, output.path, groupName, baseName)\n }\n return path.resolve(root, output.path, baseName)\n })()\n\n // Ensure the resolved path stays within the configured output directory.\n // This prevents path traversal from malicious OpenAPI specs or custom group.name functions.\n // `result === outputDir` is intentionally permitted: it matches edge cases where baseName\n // resolves to the output directory itself.\n const outputDir = path.resolve(root, output.path)\n const outputDirWithSep = outputDir.endsWith(path.sep) ? outputDir : `${outputDir}${path.sep}`\n if (result !== outputDir && !result.startsWith(outputDirWithSep)) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.pathTraversal,\n severity: 'error',\n message: `Resolved path \"${result}\" is outside the output directory \"${outputDir}\".`,\n help: 'This can stem from a path traversal in the OpenAPI specification or a misconfigured `group.name` function. Keep generated paths within the output directory.',\n location: { kind: 'config' },\n })\n }\n\n return result\n}\n\n/**\n * Default file resolver used by `defineResolver`.\n *\n * Resolves a `FileNode` by combining name resolution (`resolver.default`) with\n * path resolution (`resolver.resolvePath`). The resolved file always has empty\n * `sources`, `imports`, and `exports` arrays, which consumers populate separately.\n *\n * In `mode: 'file'` the name is omitted and the file sits directly at the output path.\n *\n * @example Resolve a schema file\n * ```ts\n * const file = defaultResolveFile.call(\n * resolver,\n * { name: 'pet', extname: '.ts' },\n * { root: '/src', output: { path: 'types' } },\n * )\n * // → { baseName: 'pet.ts', path: '/src/types/pet.ts', sources: [], ... }\n * ```\n *\n * @example Resolve an operation file with tag grouping\n * ```ts\n * const file = defaultResolveFile.call(\n * resolver,\n * { name: 'listPets', extname: '.ts', tag: 'pets' },\n * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },\n * )\n * // → { baseName: 'listPets.ts', path: '/src/types/pets/listPets.ts', ... }\n * ```\n */\nexport function defaultResolveFile(this: Resolver, { name, extname, tag, path: groupPath }: ResolverFileParams, context: ResolverContext): FileNode {\n const mode = context.output.mode ?? 'directory'\n const resolvedName = mode === 'file' ? '' : this.default(name, 'file')\n const baseName = `${resolvedName}${extname}` as FileNode['baseName']\n const filePath = this.resolvePath({ baseName, tag, path: groupPath }, context)\n\n return ast.factory.createFile({\n path: filePath,\n baseName: path.basename(filePath) as `${string}.${string}`,\n meta: {\n pluginName: this.pluginName,\n },\n sources: [],\n imports: [],\n exports: [],\n })\n}\n\n/**\n * Generates the default \"Generated by Kubb\" banner from config and optional node metadata.\n */\nfunction buildDefaultBanner({ title, description, version, config }: { title?: string; description?: string; version?: string; config: Config }): string {\n try {\n const source = (() => {\n if (Array.isArray(config.input)) {\n const first = config.input[0]\n if (first && 'path' in first) return path.basename(first.path)\n return ''\n }\n if (config.input && 'path' in config.input) return path.basename(config.input.path)\n if (config.input && 'data' in config.input) return 'text content'\n return ''\n })()\n\n let banner = '/**\\n* Generated by Kubb (https://kubb.dev/).\\n* Do not edit manually.\\n'\n\n if (config.output.defaultBanner === 'simple') {\n banner += '*/\\n'\n return banner\n }\n\n if (source) {\n banner += `* Source: ${source}\\n`\n }\n\n if (title) {\n banner += `* Title: ${title}\\n`\n }\n\n if (description) {\n const formattedDescription = description.replace(/\\n/gm, '\\n* ')\n banner += `* Description: ${formattedDescription}\\n`\n }\n\n if (version) {\n banner += `* OpenAPI spec version: ${version}\\n`\n }\n\n banner += '*/\\n'\n return banner\n } catch (_error) {\n return '/**\\n* Generated by Kubb (https://kubb.dev/).\\n* Do not edit manually.\\n*/'\n }\n}\n\n/**\n * Default banner resolver. Returns the banner string for a generated file.\n *\n * A user-supplied `output.banner` overrides the default Kubb \"Generated by Kubb\" notice.\n * When no `output.banner` is set, the Kubb notice is used (including `title` and `version`\n * from the document metadata when `meta` is provided).\n *\n * - When `output.banner` is a function, calls it with the file's `BannerMeta` and returns the result.\n * - When `output.banner` is a string, returns it directly.\n * - When `config.output.defaultBanner` is `false`, returns `undefined`.\n * - Otherwise returns the Kubb \"Generated by Kubb\" notice.\n *\n * @example String banner overrides default\n * ```ts\n * defaultResolveBanner(undefined, { output: { banner: '// my banner' }, config })\n * // → '// my banner'\n * ```\n *\n * @example Function banner with metadata\n * ```ts\n * defaultResolveBanner(meta, { output: { banner: (m) => `// v${m.version}` }, config })\n * // → '// v3.0.0'\n * ```\n *\n * @example Function banner skips re-export files\n * ```ts\n * defaultResolveBanner(meta, { output: { banner: (m) => (m.isBarrel ? '' : \"'use server'\") }, config, file: { path, baseName, isBarrel: true } })\n * // → ''\n * ```\n *\n * @example No user banner, Kubb notice with OAS metadata\n * ```ts\n * defaultResolveBanner(meta, { config })\n * // → '/** Generated by Kubb ... Title: Pet Store ... *\\/'\n * ```\n *\n * @example Disabled default banner\n * ```ts\n * defaultResolveBanner(undefined, { config: { output: { defaultBanner: false }, ...config } })\n * // → null\n * ```\n */\nexport function defaultResolveBanner(meta: InputMeta | undefined, { output, config, file }: ResolveBannerContext): string | null {\n if (typeof output?.banner === 'function') {\n return output.banner(buildBannerMeta({ meta, file }))\n }\n\n if (typeof output?.banner === 'string') {\n return output.banner\n }\n\n if (config.output.defaultBanner === false) {\n return null\n }\n\n return buildDefaultBanner({\n title: meta?.title,\n version: meta?.version,\n config,\n })\n}\n\n/**\n * Default footer resolver. Returns the footer string for a generated file.\n *\n * - When `output.footer` is a function, calls it with the file's `BannerMeta` and returns the result.\n * - When `output.footer` is a string, returns it directly.\n * - Otherwise returns `undefined`.\n *\n * @example String footer\n * ```ts\n * defaultResolveFooter(undefined, { output: { footer: '// end of file' }, config })\n * // → '// end of file'\n * ```\n *\n * @example Function footer with metadata\n * ```ts\n * defaultResolveFooter(meta, { output: { footer: (m) => `// ${m.title}` }, config })\n * // → '// Pet Store'\n * ```\n */\nexport function defaultResolveFooter(meta: InputMeta | undefined, { output, file }: ResolveBannerContext): string | null {\n if (typeof output?.footer === 'function') {\n return output.footer(buildBannerMeta({ meta, file }))\n }\n if (typeof output?.footer === 'string') {\n return output.footer\n }\n return null\n}\n\n/**\n * Defines a plugin resolver. The resolver is the object that decides what\n * every generated symbol and file path is called. Built-in defaults handle\n * name casing, include/exclude/override filtering, output path computation,\n * and file construction. Supply your own to override any of them:\n *\n * - `default` sets the name casing strategy (camelCase or PascalCase).\n * - `resolveOptions` does include/exclude/override filtering.\n * - `resolvePath` computes the output path.\n * - `resolveFile` builds the full `FileNode`.\n * - `resolveBanner` and `resolveFooter` produce the top and bottom of file text.\n *\n * Methods in the returned object can call sibling resolver methods via `this`.\n * A custom rule can delegate to a default, for example `this.default(name, 'type')`.\n *\n * @example Basic resolver with naming helpers\n * ```ts\n * export const resolverTs = defineResolver<PluginTs>(() => ({\n * name: 'default',\n * resolveName(name) {\n * return this.default(name, 'function')\n * },\n * resolveTypeName(name) {\n * return this.default(name, 'type')\n * },\n * }))\n * ```\n *\n * @example Custom output path\n * ```ts\n * import path from 'node:path'\n *\n * export const resolverTs = defineResolver<PluginTs>(() => ({\n * name: 'custom',\n * resolvePath({ baseName }, { root, output }) {\n * return path.resolve(root, output.path, 'generated', baseName)\n * },\n * }))\n * ```\n */\nexport function defineResolver<T extends PluginFactoryOptions>(build: ResolverBuilder<T>): T['resolver'] {\n // `resolver` is kept so the default `resolveFile` wrapper can reference the fully assembled\n // object via `.call(resolver, ...)` at call-time, after the result is assigned below.\n let resolver: T['resolver']\n\n const result = {\n default: defaultResolver,\n resolveOptions: defaultResolveOptions,\n resolvePath: defaultResolvePath,\n resolveFile: (params: ResolverFileParams, context: ResolverContext) => defaultResolveFile.call(resolver as Resolver, params, context),\n resolveBanner: defaultResolveBanner,\n resolveFooter: defaultResolveFooter,\n ...build(),\n } as T['resolver']\n\n resolver = result\n\n return resolver\n}\n","import type { Macro, OperationNode, SchemaNode, Visitor } from '@kubb/ast'\nimport { composeMacros, transform } from '@kubb/ast'\n\n/**\n * Holds an ordered list of macros per plugin, keyed by plugin name. Each plugin's macros run in\n * isolation on the original adapter node and are composed into a single `Visitor` that the\n * `@kubb/ast` `transform` primitive applies. `applyTo` is a per-plugin lookup, not a cross-plugin\n * chain, so plugin A's macros never see plugin B's output. When a plugin has no macros, `applyTo`\n * returns the original node reference, and `transform` does the same when the composed visitor\n * leaves the tree untouched, so callers can detect a no-op by identity.\n *\n * Registration order matches the order setup hooks fire, which the driver has already sorted by\n * `enforce` and dependency edges. The registry preserves that order. Macro `enforce` only reorders\n * within a single plugin's list.\n */\nexport class Transform {\n readonly #macros = new Map<string, Array<Macro>>()\n // Composed visitor per plugin, rebuilt lazily after the macro list changes.\n readonly #composed = new Map<string, Visitor>()\n // Memoized results per plugin. Repeated `applyTo` calls return the same node identity, so\n // downstream WeakMap caches keyed by node (the resolver's resolveOptions memo) hit when the\n // driver resolves a node a second time, and a stateful macro runs once per node.\n readonly #memo = new Map<string, WeakMap<SchemaNode | OperationNode, SchemaNode | OperationNode>>()\n\n /**\n * Number of plugins with at least one registered macro.\n */\n get size(): number {\n return this.#macros.size\n }\n\n /**\n * Appends `macro` to the plugin's list, after any macros already registered.\n */\n add(pluginName: string, macro: Macro): void {\n const list = this.#macros.get(pluginName)\n if (list) list.push(macro)\n else this.#macros.set(pluginName, [macro])\n this.#invalidate(pluginName)\n }\n\n /**\n * Replaces the plugin's macro list with `macros`.\n */\n set(pluginName: string, macros: ReadonlyArray<Macro>): void {\n this.#macros.set(pluginName, [...macros])\n this.#invalidate(pluginName)\n }\n\n /**\n * Looks up the composed visitor for `pluginName`, or `undefined` when the plugin has no macros.\n */\n get(pluginName: string): Visitor | undefined {\n return this.#visitorFor(pluginName)\n }\n\n /**\n * Runs the plugin's macros on `node`. Returns the original node reference when the plugin has no\n * macros, so callers can compare by identity to detect a no-op.\n */\n applyTo<TNode extends SchemaNode | OperationNode>(pluginName: string, node: TNode): TNode {\n const visitor = this.#visitorFor(pluginName)\n if (!visitor) return node\n\n let memo = this.#memo.get(pluginName)\n if (!memo) {\n memo = new WeakMap()\n this.#memo.set(pluginName, memo)\n }\n\n const cached = memo.get(node)\n if (cached) return cached as TNode\n\n const result = transform(node, visitor) as TNode\n memo.set(node, result)\n return result\n }\n\n /**\n * Clears every registration. Called from the driver's `dispose()` so macros do not leak across\n * builds.\n */\n dispose(): void {\n this.#macros.clear()\n this.#composed.clear()\n this.#memo.clear()\n }\n\n #invalidate(pluginName: string): void {\n this.#composed.delete(pluginName)\n this.#memo.delete(pluginName)\n }\n\n #visitorFor(pluginName: string): Visitor | undefined {\n const macros = this.#macros.get(pluginName)\n if (!macros || macros.length === 0) return undefined\n\n let composed = this.#composed.get(pluginName)\n if (!composed) {\n composed = composeMacros(macros)\n this.#composed.set(pluginName, composed)\n }\n return composed\n }\n}\n","import { resolve } from 'node:path'\nimport { arrayToAsyncIterable, type AsyncEventEmitter, forBatches, getElapsedMs, isPromise, memoize, Url } from '@internals/utils'\nimport { collectUsedSchemaNames } from '@kubb/ast/utils'\nimport { ast, type Enforce, type FileNode, type InputMeta, type InputNode, type OperationNode, type SchemaNode } from '@kubb/ast'\nimport { OPERATION_FILTER_TYPES, SCHEMA_PARALLEL } from './constants.ts'\nimport { type Diagnostic, Diagnostics, type ProblemDiagnostic } from './diagnostics.ts'\nimport type { RendererFactory } from './createRenderer.ts'\nimport type { Storage } from './createStorage.ts'\nimport type { Generator } from './defineGenerator.ts'\nimport type { Parser } from './defineParser.ts'\nimport type { Plugin } from './definePlugin.ts'\nimport { normalizeOutput } from './definePlugin.ts'\nimport { defineResolver } from './defineResolver.ts'\nimport { FileManager } from './FileManager.ts'\nimport { FileProcessor } from './FileProcessor.ts'\nimport { Transform } from './Transform.ts'\n\nimport type {\n Adapter,\n AdapterSource,\n Config,\n GeneratorContext,\n Group,\n KubbHooks,\n KubbPluginSetupContext,\n NormalizedPlugin,\n PluginFactoryOptions,\n Resolver,\n} from './types.ts'\n\ntype Options = {\n hooks: AsyncEventEmitter<KubbHooks>\n}\n\ntype HookListener<TArgs extends Array<unknown>, TResult = void> = (...args: TArgs) => TResult | Promise<TResult>\n\ntype ListenerEntry = [event: keyof KubbHooks & string, handler: HookListener<Array<unknown>, unknown>]\n\ntype RequirePluginContext = {\n /**\n * Name of the plugin that declared the dependency, included in the error so users can\n * trace which plugin needs the missing one.\n */\n requiredBy?: string\n}\n\nfunction enforceOrder(enforce: Enforce | undefined): number {\n return enforce === 'pre' ? -1 : enforce === 'post' ? 1 : 0\n}\n\nexport class KubbDriver {\n readonly config: Config\n readonly options: Options\n\n /**\n * The streaming `InputNode<true>` produced by the adapter. Set after adapter setup.\n * Parse-only adapters are wrapped automatically.\n */\n inputNode: InputNode<true> | null = null\n adapter: Adapter | null = null\n /**\n * Raw adapter source so `adapter.parse()` / `adapter.stream()` can run lazily.\n * Intentionally outlives the build, cleared by `dispose()`.\n */\n #adapterSource: AdapterSource | null = null\n\n /**\n * Central file store for all generated files.\n * Plugins should use `this.addFile()` / `this.upsertFile()` (via their context) to\n * add files. This property gives direct read/write access when needed.\n */\n readonly fileManager = new FileManager()\n readonly plugins = new Map<string, NormalizedPlugin>()\n\n /**\n * Tracks which plugins have generators registered via `addGenerator()` (event-based path).\n * Used by the build loop to decide whether to emit generator events for a given plugin.\n */\n readonly #eventGeneratorPlugins = new Set<string>()\n readonly #resolvers = new Map<string, Resolver>()\n readonly #defaultResolvers = new Map<string, Resolver>()\n\n /**\n * Tracks every listener the driver added (plugin, generator) so `dispose()` can remove them\n * in one pass. External `hooks.on(...)` listeners are not tracked.\n */\n readonly #listeners: Array<ListenerEntry> = []\n\n /**\n * Transform registry. Plugins populate it during `kubb:plugin:setup` via `addMacro`/`setMacros`,\n * and `#runGenerators` reads it once per `(plugin, node)` pair through `applyTo`.\n */\n readonly #transforms = new Transform()\n\n constructor(config: Config, options: Options) {\n this.config = config\n this.options = options\n this.adapter = config.adapter ?? null\n }\n\n /**\n * Attaches a listener to the shared emitter and tracks it so `dispose()` can remove it later.\n * Listeners attached directly via `hooks.on(...)` are not tracked and survive disposal.\n */\n #trackListener<K extends keyof KubbHooks & string>(event: K, handler: HookListener<KubbHooks[K], unknown>): void {\n this.hooks.on(event, handler as HookListener<KubbHooks[K]>)\n this.#listeners.push([event, handler as HookListener<Array<unknown>, unknown>])\n }\n\n /**\n * Normalizes every configured plugin, orders them, and registers their lifecycle handlers.\n * A plugin that another lists as a dependency runs first, then `enforce: 'pre'` before\n * `'post'`. When the config has an adapter, the adapter source is resolved from the input\n * so `run` can parse it later.\n */\n async setup() {\n const normalized: Array<NormalizedPlugin> = this.config.plugins.map((rawPlugin) => this.#normalizePlugin(rawPlugin as Plugin))\n\n const dependenciesByName = new Map(normalized.map((plugin) => [plugin.name, new Set(plugin.dependencies ?? [])]))\n\n normalized.sort((a, b) => {\n if (dependenciesByName.get(b.name)?.has(a.name)) return -1\n if (dependenciesByName.get(a.name)?.has(b.name)) return 1\n\n return enforceOrder(a.enforce) - enforceOrder(b.enforce)\n })\n\n for (const plugin of normalized) {\n if (plugin.apply) {\n plugin.apply(this.config)\n }\n\n this.#registerPlugin(plugin)\n this.plugins.set(plugin.name, plugin)\n }\n\n if (this.config.adapter) {\n this.#adapterSource = inputToAdapterSource(this.config)\n }\n }\n\n get hooks() {\n return this.options.hooks\n }\n\n /**\n * Builds a `NormalizedPlugin` from a hook-style plugin, filling in default\n * options and copying `apply` when present. Registering its lifecycle handlers\n * on the `AsyncEventEmitter` is done separately by `#registerPlugin`.\n */\n #normalizePlugin(plugin: Plugin): NormalizedPlugin {\n const normalized: NormalizedPlugin = {\n name: plugin.name,\n dependencies: plugin.dependencies,\n enforce: plugin.enforce,\n hooks: plugin.hooks,\n options: plugin.options ?? { output: { path: '.', mode: 'directory' }, exclude: [], override: [] },\n } as NormalizedPlugin\n\n if ('apply' in plugin && typeof plugin.apply === 'function') {\n normalized.apply = plugin.apply as (config: Config) => boolean\n }\n\n return normalized\n }\n\n /**\n * Parses the adapter source into `this.inputNode`. Idempotent, so repeated calls from\n * `run` do not re-parse. Adapters with `stream()` are used directly.\n * Adapters with only `parse()` are wrapped via `ast.factory.createInput({ stream: true })` so the dispatch loop\n * stays stream-only.\n */\n async #parseInput(): Promise<void> {\n if (this.inputNode || !this.adapter || !this.#adapterSource) return\n\n const adapter = this.adapter\n const source = this.#adapterSource\n\n if (adapter.stream) {\n this.inputNode = await adapter.stream(source)\n return\n }\n\n const parsed = await adapter.parse(source)\n this.inputNode = ast.factory.createInput({\n stream: true,\n schemas: arrayToAsyncIterable(parsed.schemas),\n operations: arrayToAsyncIterable(parsed.operations),\n meta: parsed.meta,\n })\n }\n\n /**\n * Registers a hook-style plugin's lifecycle handlers on the shared `AsyncEventEmitter`.\n *\n * The `kubb:plugin:setup` listener wraps the global context in a plugin-specific one so\n * `addGenerator`, `setResolver`, and `setMacros` target the right `normalizedPlugin`.\n * Every other `KubbHooks` event registers as a pass-through listener that external tooling\n * can observe via `hooks.on(...)`.\n *\n * @internal\n */\n #registerPlugin(plugin: NormalizedPlugin): void {\n const { hooks } = plugin\n\n if (!hooks) return\n\n // kubb:plugin:setup gets special treatment: the globally emitted context is wrapped with\n // plugin-specific implementations so that addGenerator / setResolver / etc. target\n // this plugin's normalizedPlugin entry rather than being no-ops.\n if (hooks['kubb:plugin:setup']) {\n const setupHandler = (globalCtx: KubbPluginSetupContext) => {\n const pluginCtx: KubbPluginSetupContext = {\n ...globalCtx,\n options: plugin.options ?? {},\n addGenerator: (gen) => {\n this.registerGenerator(plugin.name, gen)\n },\n setResolver: (resolver) => {\n this.setPluginResolver(plugin.name, resolver)\n },\n addMacro: (macro) => {\n this.#transforms.add(plugin.name, macro)\n },\n setMacros: (macros) => {\n this.#transforms.set(plugin.name, macros)\n },\n setOptions: (opts) => {\n plugin.options = { ...plugin.options, ...opts }\n if (plugin.options.output) {\n const group = 'group' in plugin.options ? (plugin.options.group as Group | null | undefined) : undefined\n plugin.options.output = normalizeOutput({ output: plugin.options.output, group, pluginName: plugin.name })\n }\n },\n injectFile: (userFileNode) => {\n this.fileManager.add(ast.factory.createFile(userFileNode))\n },\n }\n return hooks['kubb:plugin:setup']!(pluginCtx)\n }\n\n this.#trackListener('kubb:plugin:setup', setupHandler)\n }\n\n // All other hooks are registered as direct pass-through listeners on the shared emitter.\n for (const event of Object.keys(hooks) as Array<keyof KubbHooks & string>) {\n if (event === 'kubb:plugin:setup') continue\n const handler = hooks[event]\n if (!handler) continue\n\n this.#trackListener(event, handler as HookListener<KubbHooks[typeof event], unknown>)\n }\n }\n\n /**\n * Emits the `kubb:plugin:setup` event so that all registered hook-style plugin listeners\n * can configure generators, resolvers, macros and renderers before `buildStart` runs.\n *\n * Called once from `run` before the plugin execution loop begins.\n */\n async emitSetupHooks(): Promise<void> {\n const noop = () => {}\n\n await this.hooks.emit('kubb:plugin:setup', {\n config: this.config,\n options: {},\n addGenerator: noop,\n setResolver: noop,\n addMacro: noop,\n setMacros: noop,\n setOptions: noop,\n injectFile: noop,\n updateConfig: noop,\n })\n }\n\n /**\n * Registers a generator for the given plugin on the shared event emitter.\n *\n * The generator's `schema`, `operation`, and `operations` methods are registered as\n * listeners on `kubb:generate:schema`, `kubb:generate:operation`, and `kubb:generate:operations`\n * respectively. Each listener is scoped to the owning plugin via a `ctx.plugin.name` check\n * so that generators from different plugins do not cross-fire.\n *\n * The renderer comes from `generator.renderer`. Set `generator.renderer = null` (or leave it\n * unset) to opt out of rendering.\n *\n * Call this method inside `addGenerator()` (in `kubb:plugin:setup`) to wire up a generator.\n */\n registerGenerator(pluginName: string, generator: Generator): void {\n const register = <TNode>(event: keyof KubbHooks & string, method: ((node: TNode, ctx: GeneratorContext) => unknown) | undefined): void => {\n if (!method) return\n\n const handler = async (node: TNode, ctx: GeneratorContext) => {\n if (ctx.plugin.name !== pluginName) return\n const result = await method(node, ctx)\n await this.dispatch({ result, renderer: generator.renderer })\n }\n\n this.#trackListener(event, handler as HookListener<KubbHooks[typeof event], unknown>)\n }\n\n register('kubb:generate:schema', generator.schema)\n register('kubb:generate:operation', generator.operation)\n register('kubb:generate:operations', generator.operations)\n\n this.#eventGeneratorPlugins.add(pluginName)\n }\n\n /**\n * Returns `true` when at least one generator was registered for the given plugin\n * via `addGenerator()` in `kubb:plugin:setup` (event-based path).\n *\n * Used by the build loop to decide whether to walk the AST and emit generator events\n * for a plugin that has no static `plugin.generators`.\n */\n hasEventGenerators(pluginName: string): boolean {\n return this.#eventGeneratorPlugins.has(pluginName)\n }\n\n /**\n * Runs the full plugin pipeline. Returns the diagnostics collected so far even\n * when an outer hook throws, since the orchestrator preserves partial state by capturing\n * the failure as a {@link Diagnostic} instead of propagating. Each plugin also\n * contributes a `timing` diagnostic for the run summary.\n */\n async run({ storage }: { storage: Storage }): Promise<{ diagnostics: Array<Diagnostic> }> {\n const { hooks, config } = this\n const diagnostics: Array<Diagnostic> = []\n const parsersMap = new Map<FileNode['extname'], Parser>()\n\n for (const parser of config.parsers) {\n if (parser.extNames) {\n for (const ext of parser.extNames) parsersMap.set(ext, parser)\n }\n }\n\n const processor = new FileProcessor({ parsers: parsersMap, storage, extension: config.output.extension })\n // Bridge processor lifecycle to the user-facing kubb hooks so existing listeners on\n // kubb:files:processing:* keep firing.\n processor.hooks.on('start', async (files) => {\n await hooks.emit('kubb:files:processing:start', { files })\n })\n const updateBuffer: Array<{ file: FileNode; source?: string; processed: number; total: number; percentage: number }> = []\n processor.hooks.on('update', (item) => {\n updateBuffer.push(item)\n })\n processor.hooks.on('end', async (files) => {\n await hooks.emit('kubb:files:processing:update', {\n files: updateBuffer.map((item) => ({ ...item, config })),\n })\n updateBuffer.length = 0\n await hooks.emit('kubb:files:processing:end', { files })\n })\n const onFileUpsert = (file: FileNode): void => {\n processor.enqueue(file)\n }\n this.fileManager.hooks.on('upsert', onFileUpsert)\n\n // Make `diagnostics` the active sink so deep code (adapter parse, lazily consumed\n // streams, generators) can report into this run via `Diagnostics.report`.\n return Diagnostics.scope(\n (diagnostic) => diagnostics.push(diagnostic),\n async () => {\n try {\n const outputRoot = resolve(config.root, config.output.path)\n\n // Parse the adapter source into the streaming `InputNode`.\n await this.#parseInput()\n // Emit `kubb:plugin:setup` so plugins can register macros via `addMacro`/`setMacros`.\n // Each call writes into `this.#transforms`, which `#runGenerators` later reads through\n // `transforms.applyTo`.\n await this.emitSetupHooks()\n\n if (this.adapter && this.inputNode) {\n await hooks.emit(\n 'kubb:build:start',\n Object.assign({ config, adapter: this.adapter, meta: this.inputNode.meta, getPlugin: this.getPlugin.bind(this) }, this.#filesPayload()),\n )\n }\n\n const generatorPlugins: Array<{ plugin: NormalizedPlugin; context: Omit<GeneratorContext, 'options'>; hrStart: ReturnType<typeof process.hrtime> }> =\n []\n\n for (const plugin of this.plugins.values()) {\n const context = this.getContext(plugin)\n const hrStart = process.hrtime()\n\n try {\n await hooks.emit('kubb:plugin:start', { plugin })\n } catch (caughtError) {\n const error = caughtError as Error\n const duration = getElapsedMs(hrStart)\n\n await this.#emitPluginEnd({ plugin, duration, success: false, error })\n\n diagnostics.push({ ...Diagnostics.from(error), plugin: plugin.name }, Diagnostics.performance({ plugin: plugin.name, duration }))\n\n continue\n }\n\n if (this.hasEventGenerators(plugin.name)) {\n generatorPlugins.push({ plugin, context, hrStart })\n\n continue\n }\n\n const duration = getElapsedMs(hrStart)\n diagnostics.push(Diagnostics.performance({ plugin: plugin.name, duration }))\n\n await this.#emitPluginEnd({ plugin, duration, success: true })\n }\n\n // Stream every node through the transform registry and into each plugin's generators.\n // When there are no entries it returns early. When `inputNode` is missing it still\n // closes out each entry's `kubb:plugin:end` directly.\n diagnostics.push(...(await this.#runGenerators(generatorPlugins, () => processor.flush())))\n // Wait for the last in-flight batch and write anything still pending.\n await processor.drain()\n\n await hooks.emit('kubb:plugins:end', Object.assign({ config }, this.#filesPayload()))\n\n // Plugins-end listeners (barrel plugin etc.) may have queued more files.\n await processor.drain()\n\n await hooks.emit('kubb:build:end', { files: this.fileManager.files, config, outputDir: outputRoot })\n\n return { diagnostics: Diagnostics.dedupe(diagnostics) }\n } catch (caughtError) {\n diagnostics.push(Diagnostics.from(caughtError))\n return { diagnostics: Diagnostics.dedupe(diagnostics) }\n } finally {\n this.fileManager.hooks.off('upsert', onFileUpsert)\n }\n },\n )\n }\n\n // Returns a fresh object with a lazy `files` getter and a bound `upsertFile`.\n // Caller must use `Object.assign(extra, this.#filesPayload())`, not object spread.\n // Spread would eagerly invoke the getter and freeze a stale snapshot into the payload.\n #filesPayload(): { readonly files: Array<FileNode>; upsertFile: (...files: Array<FileNode>) => Array<FileNode> } {\n const driver = this\n\n return {\n get files() {\n return driver.fileManager.files\n },\n upsertFile: (...files: Array<FileNode>) => driver.fileManager.upsert(...files),\n }\n }\n\n #emitPluginEnd({ plugin, duration, success, error }: { plugin: NormalizedPlugin; duration: number; success: boolean; error?: Error }): Promise<void> | void {\n return this.hooks.emit(\n 'kubb:plugin:end',\n Object.assign({ plugin, duration, success, ...(error ? { error } : {}), config: this.config }, this.#filesPayload()),\n )\n }\n\n /**\n * Streams schemas and operations through every plugin's generators. Each node is run\n * through the plugin's macros (from `this.#transforms`) before the generator sees it,\n * so plugins stay isolated and the hot path stays per-node. Schemas run before operations\n * because the two passes share `flushPending` and the FileProcessor's event emitter.\n * A failing plugin contributes an error diagnostic so the rest of the build continues.\n * Every plugin also contributes a `timing` diagnostic.\n *\n * Plugins run sequentially so `kubb:plugin:end` fires as each plugin completes, instead\n * of all at once after every plugin has marched through the parallel batches together.\n * That ordering is what drives the CLI's `Plugins N/M` counter. Without it the bar would\n * sit at the initial value until the very end of the run.\n *\n * When `this.inputNode` is `null`, every entry still gets a `kubb:plugin:end` so\n * post-plugin listeners (the barrel writer and friends) complete.\n */\n async #runGenerators(\n entries: Array<{ plugin: NormalizedPlugin; context: Omit<GeneratorContext, 'options'>; hrStart: ReturnType<typeof process.hrtime> }>,\n flushPending: () => Promise<void>,\n ): Promise<Array<Diagnostic>> {\n const diagnostics: Array<Diagnostic> = []\n\n if (entries.length === 0) return diagnostics\n\n if (!this.inputNode) {\n for (const { plugin, hrStart } of entries) {\n const duration = getElapsedMs(hrStart)\n diagnostics.push(Diagnostics.performance({ plugin: plugin.name, duration }))\n await this.#emitPluginEnd({ plugin, duration, success: true })\n }\n return diagnostics\n }\n\n const transforms = this.#transforms\n const { schemas, operations } = this.inputNode\n\n type PluginState = {\n plugin: NormalizedPlugin\n generatorContext: Omit<GeneratorContext, 'options'>\n generators: Array<Generator>\n hrStart: ReturnType<typeof process.hrtime>\n failed: boolean\n error: Error | null\n optionsAreStatic: boolean\n allowedSchemaNames: Set<string> | null\n }\n\n const states: Array<PluginState> = entries.map(({ plugin, context, hrStart }) => {\n const { exclude, include, override } = plugin.options\n const hasExclude = Array.isArray(exclude) && exclude.length > 0\n const hasInclude = Array.isArray(include) && include.length > 0\n const hasOverride = Array.isArray(override) && override.length > 0\n return {\n plugin,\n generatorContext: { ...context, resolver: this.getResolver(plugin.name) },\n generators: plugin.generators ?? [],\n hrStart,\n failed: false,\n error: null,\n optionsAreStatic: !hasExclude && !hasInclude && !hasOverride,\n allowedSchemaNames: null,\n }\n })\n\n const emitsSchemaHook = this.hooks.listenerCount('kubb:generate:schema') > 0\n const emitsOperationHook = this.hooks.listenerCount('kubb:generate:operation') > 0\n const emitsOperationsHook = this.hooks.listenerCount('kubb:generate:operations') > 0\n\n // Buffer the streaming adapter's nodes once. Each plugin reads the same buffer\n // instead of re-parsing the document per pass, and the pruning pre-scan below\n // shares it too (previously it iterated its own copies).\n const schemasBuffer: Array<SchemaNode> = await Array.fromAsync(schemas)\n const operationsBuffer: Array<OperationNode> = await Array.fromAsync(operations)\n\n // Pre-scan: plugins with operation-based includes (but no schemaName include) need\n // the reachable schema set. This requires the full schema graph in memory at once,\n // since transitive reachability can't be derived from a single node.\n const pruningStates = states.filter(({ plugin }) => {\n const { include } = plugin.options\n return (include?.some(({ type }) => OPERATION_FILTER_TYPES.has(type)) ?? false) && !(include?.some(({ type }) => type === 'schemaName') ?? false)\n })\n\n if (pruningStates.length > 0) {\n const includedOpsByState = new Map<PluginState, Array<OperationNode>>(pruningStates.map((state) => [state, []]))\n for (const operation of operationsBuffer) {\n for (const state of pruningStates) {\n const { exclude, include, override } = state.plugin.options\n const options = state.generatorContext.resolver.resolveOptions(operation, { options: state.plugin.options, exclude, include, override })\n if (options !== null) includedOpsByState.get(state)?.push(operation)\n }\n }\n\n for (const state of pruningStates) {\n state.allowedSchemaNames = collectUsedSchemaNames(includedOpsByState.get(state) ?? [], schemasBuffer)\n includedOpsByState.delete(state)\n }\n }\n\n // Apply the plugin's macros, then resolve options (skipping the resolver when\n // optionsAreStatic). Returns null when include/exclude/override rules out the node.\n // The per-node dispatch and the collected-operations tail both go through this so\n // they agree on what a plugin sees.\n const resolveForPlugin = <TNode extends SchemaNode | OperationNode>(\n state: PluginState,\n node: TNode,\n ): { transformedNode: TNode; options: NormalizedPlugin['options'] } | null => {\n const { plugin, generatorContext } = state\n const transformedNode = transforms.applyTo(plugin.name, node)\n if (state.optionsAreStatic) return { transformedNode, options: plugin.options }\n\n const { exclude, include, override } = plugin.options\n const options = generatorContext.resolver.resolveOptions(transformedNode, { options: plugin.options, exclude, include, override })\n if (options === null) return null\n return { transformedNode, options }\n }\n\n // Schema and operation passes share this body. They differ only in which generator\n // method runs, which hook is emitted, and the schema-only `allowedSchemaNames` prune\n // (operations don't carry that constraint).\n const dispatchNode = async <TNode extends SchemaNode | OperationNode>(\n state: PluginState,\n node: TNode,\n dispatch: {\n method: 'schema' | 'operation'\n checkAllowedNames: boolean\n emit: ((node: TNode, ctx: GeneratorContext) => Promise<void> | void) | null\n },\n ): Promise<void> => {\n if (state.failed) return\n try {\n const resolved = resolveForPlugin(state, node)\n if (!resolved) return\n\n const { transformedNode, options } = resolved\n if (\n dispatch.checkAllowedNames &&\n state.allowedSchemaNames !== null &&\n 'name' in transformedNode &&\n transformedNode.name &&\n !state.allowedSchemaNames.has(transformedNode.name)\n ) {\n return\n }\n\n const ctx = { ...state.generatorContext, options }\n for (const gen of state.generators) {\n const run = gen[dispatch.method] as ((node: TNode, ctx: GeneratorContext) => unknown) | undefined\n if (!run) continue\n const raw = run(transformedNode, ctx)\n const result = isPromise(raw) ? await raw : raw\n const applied = this.dispatch({ result, renderer: gen.renderer })\n if (isPromise(applied)) await applied\n }\n if (dispatch.emit) await dispatch.emit(transformedNode, ctx)\n } catch (caughtError) {\n state.failed = true\n state.error = caughtError as Error\n }\n }\n\n const schemaDispatch = {\n method: 'schema',\n checkAllowedNames: true,\n emit: emitsSchemaHook ? (node: SchemaNode, ctx: GeneratorContext) => this.hooks.emit('kubb:generate:schema', node, ctx) : null,\n } as const\n const operationDispatch = {\n method: 'operation',\n checkAllowedNames: false,\n emit: emitsOperationHook ? (node: OperationNode, ctx: GeneratorContext) => this.hooks.emit('kubb:generate:operation', node, ctx) : null,\n } as const\n\n for (const state of states) {\n // Skip building the aggregated operations array when this plugin doesn't consume it.\n // Saves an N-sized allocation when the plugin only defines per-node `gen.operation`.\n const needsCollectedOperations = emitsOperationsHook || state.generators.some((gen) => !!gen.operations)\n const collectedOperations: Array<OperationNode> | undefined = needsCollectedOperations ? [] : undefined\n\n // Run schemas before operations: the two passes share `flushPending` and the\n // FileProcessor's event emitter, so running them concurrently would interleave\n // `kubb:files:processing:start|end` events and race on the shared dirty list.\n await forBatches(schemasBuffer, (nodes) => Promise.all(nodes.map((node) => dispatchNode(state, node, schemaDispatch))), {\n concurrency: SCHEMA_PARALLEL,\n flush: flushPending,\n })\n\n await forBatches(\n operationsBuffer,\n (nodes) => {\n if (needsCollectedOperations) collectedOperations?.push(...nodes)\n return Promise.all(nodes.map((node) => dispatchNode(state, node, operationDispatch)))\n },\n { concurrency: SCHEMA_PARALLEL, flush: flushPending },\n )\n\n if (!state.failed && needsCollectedOperations) {\n try {\n const { plugin, generatorContext, generators } = state\n const ctx = { ...generatorContext, options: plugin.options }\n // Match what the per-node dispatch passes to gen.operation(): the transformed node,\n // already filtered by excludes/includes/overrides.\n const ops = collectedOperations ?? []\n const pluginOperations = ops.reduce<Array<OperationNode>>((acc, node) => {\n const resolved = resolveForPlugin(state, node)\n if (resolved) acc.push(resolved.transformedNode)\n return acc\n }, [])\n for (const gen of generators) {\n if (!gen.operations) continue\n const result = await gen.operations(pluginOperations, ctx)\n await this.dispatch({ result, renderer: gen.renderer })\n }\n await this.hooks.emit('kubb:generate:operations', pluginOperations, ctx)\n } catch (caughtError) {\n state.failed = true\n state.error = caughtError as Error\n }\n }\n\n const duration = getElapsedMs(state.hrStart)\n await this.#emitPluginEnd({ plugin: state.plugin, duration, success: !state.failed, error: state.failed && state.error ? state.error : undefined })\n\n if (state.failed && state.error) {\n diagnostics.push({ ...Diagnostics.from(state.error), plugin: state.plugin.name })\n }\n diagnostics.push(Diagnostics.performance({ plugin: state.plugin.name, duration }))\n }\n\n return diagnostics\n }\n\n /**\n * Stores whatever a generator method or `kubb:generate:*` hook returned.\n *\n * - An `Array<FileNode>` goes straight into `fileManager` via `upsert`.\n * - A renderer element runs through `renderer` (the renderer factory, e.g. JSX) and the\n * produced files go to `fileManager.upsert`.\n * - A falsy result is treated as a no-op. The generator wrote files itself via\n * `ctx.upsertFile`.\n *\n * Pass `renderer` when the result may be a renderer element. Generators that only return\n * `Array<FileNode>` do not need one.\n */\n async dispatch<TElement = unknown>({\n result,\n renderer,\n }: {\n result: TElement | Array<FileNode> | undefined | null\n renderer?: RendererFactory<TElement> | null\n }): Promise<void> {\n if (!result) return\n\n if (Array.isArray(result)) {\n this.fileManager.upsert(...(result as Array<FileNode>))\n return\n }\n\n if (!renderer) {\n return\n }\n\n using instance = renderer()\n if (instance.stream) {\n for (const file of instance.stream(result)) {\n this.fileManager.upsert(file)\n }\n return\n }\n\n await instance.render(result)\n this.fileManager.upsert(...instance.files)\n }\n\n /**\n * Removes every listener the driver added. Listeners attached directly to `hooks` from outside\n * the driver survive. Called at the end of a build to prevent leaks across repeated builds.\n *\n * @internal\n */\n dispose(): void {\n for (const [event, handler] of this.#listeners) {\n this.hooks.off(event, handler as HookListener<KubbHooks[typeof event]>)\n }\n this.#listeners.length = 0\n this.#eventGeneratorPlugins.clear()\n this.#transforms.dispose()\n // Release resolver closures. The driver is rebuilt for each build() call\n // so there is no value in retaining these maps after disposal.\n this.#resolvers.clear()\n this.#defaultResolvers.clear()\n // Release the FileNode cache and parsed adapter graph so memory is reclaimed\n // between builds. The returned `BuildOutput.files` array still references any\n // FileNodes the caller needs to inspect.\n this.fileManager.dispose()\n this.inputNode = null\n this.#adapterSource = null\n }\n\n [Symbol.dispose](): void {\n this.dispose()\n }\n\n #getDefaultResolver = memoize(\n this.#defaultResolvers,\n (pluginName: string): Resolver => defineResolver<PluginFactoryOptions>(() => ({ name: 'default', pluginName })),\n )\n\n /**\n * Merges `partial` with the plugin's default resolver and stores the result.\n * Also mirrors it onto `plugin.resolver` so callers using `getPlugin(name).resolver`\n * get the up-to-date resolver without going through `getResolver()`.\n */\n setPluginResolver(pluginName: string, partial: Partial<Resolver>): void {\n const defaultResolver = this.#getDefaultResolver(pluginName)\n const merged = { ...defaultResolver, ...partial }\n this.#resolvers.set(pluginName, merged)\n const plugin = this.plugins.get(pluginName)\n if (plugin) {\n plugin.resolver = merged\n }\n }\n\n /**\n * Returns the resolver for the given plugin.\n *\n * Resolution order: dynamic resolver set via `setPluginResolver` → static resolver on the\n * plugin → lazily created default resolver (identity name, no path transforms).\n */\n getResolver<TName extends keyof Kubb.PluginRegistry>(pluginName: TName): Kubb.PluginRegistry[TName]['resolver']\n getResolver<TResolver extends Resolver = Resolver>(pluginName: string): TResolver\n getResolver(pluginName: string): Resolver {\n return this.#resolvers.get(pluginName) ?? this.plugins.get(pluginName)?.resolver ?? this.#getDefaultResolver(pluginName)\n }\n\n getContext<TOptions extends PluginFactoryOptions>(plugin: NormalizedPlugin<TOptions>): Omit<GeneratorContext<TOptions>, 'options'> {\n const driver = this\n\n // Collect into the active build only. The host renders each collected diagnostic once after the\n // build (the CLI via `Diagnostics.emit`, the agent via its post-build loop), so emitting a live\n // `kubb:error`/`kubb:warn`/`kubb:info` here would render it twice.\n const report = (diagnostic: Omit<ProblemDiagnostic, 'plugin'>): void => {\n Diagnostics.report({ ...diagnostic, plugin: plugin.name })\n }\n\n return {\n config: driver.config,\n get root(): string {\n return resolve(driver.config.root, driver.config.output.path)\n },\n hooks: driver.hooks,\n plugin,\n getPlugin: driver.getPlugin.bind(driver),\n // Close over the owning plugin so a missing dependency error names who required it.\n requirePlugin: ((name: string) => driver.requirePlugin(name, { requiredBy: plugin.name })) as GeneratorContext<TOptions>['requirePlugin'],\n getResolver: driver.getResolver.bind(driver),\n driver,\n addFile: async (...files: Array<FileNode>) => {\n driver.fileManager.add(...files)\n },\n upsertFile: async (...files: Array<FileNode>) => {\n driver.fileManager.upsert(...files)\n },\n get meta(): InputMeta {\n return driver.inputNode?.meta ?? { circularNames: [], enumNames: [] }\n },\n get adapter(): Adapter {\n // Generators only read `adapter` during AST hooks, which run after the\n // adapter is set, so it is guaranteed defined at read time.\n return driver.adapter!\n },\n get resolver() {\n return driver.getResolver(plugin.name)\n },\n warn(message: string) {\n report({ code: Diagnostics.code.pluginWarning, severity: 'warning', message })\n },\n error(error: string | Error) {\n const cause = typeof error === 'string' ? undefined : error\n report({ code: Diagnostics.code.pluginFailed, severity: 'error', message: typeof error === 'string' ? error : error.message, cause })\n },\n info(message: string) {\n report({ code: Diagnostics.code.pluginInfo, severity: 'info', message })\n },\n }\n }\n\n getPlugin<TName extends keyof Kubb.PluginRegistry>(pluginName: TName): Plugin<Kubb.PluginRegistry[TName]> | undefined\n getPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>(pluginName: string): Plugin<TOptions> | undefined\n getPlugin(pluginName: string): Plugin | undefined {\n return this.plugins.get(pluginName)\n }\n\n /**\n * Like `getPlugin` but throws a descriptive error when the plugin is not found.\n */\n requirePlugin<TName extends keyof Kubb.PluginRegistry>(pluginName: TName, context?: RequirePluginContext): Plugin<Kubb.PluginRegistry[TName]>\n requirePlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>(pluginName: string, context?: RequirePluginContext): Plugin<TOptions>\n requirePlugin(pluginName: string, context?: RequirePluginContext): Plugin {\n const plugin = this.plugins.get(pluginName)\n if (!plugin) {\n const requiredBy = context?.requiredBy\n throw new Diagnostics.Error({\n code: Diagnostics.code.pluginNotFound,\n severity: 'error',\n message: requiredBy\n ? `Plugin \"${pluginName}\" is required by \"${requiredBy}\" but not found. Make sure it is included in your Kubb config.`\n : `Plugin \"${pluginName}\" is required but not found. Make sure it is included in your Kubb config.`,\n help: requiredBy\n ? `Add \"${pluginName}\" to the \\`plugins\\` array in kubb.config.ts (required by \"${requiredBy}\"), or remove the dependency on it.`\n : `Add \"${pluginName}\" to the \\`plugins\\` array in kubb.config.ts, or remove the dependency on it.`,\n location: { kind: 'config' },\n })\n }\n return plugin\n }\n}\n\nfunction inputToAdapterSource(config: Config): AdapterSource {\n const input = config.input\n if (!input) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.inputRequired,\n severity: 'error',\n message: 'An adapter is configured without an input.',\n help: 'Provide `input.path` (a file or URL) or `input.data` (an inline spec) in your Kubb config.',\n location: { kind: 'config' },\n })\n }\n\n if ('data' in input) {\n return { type: 'data', data: input.data }\n }\n\n if (Url.canParse(input.path)) {\n return { type: 'path', path: input.path }\n }\n\n const resolved = resolve(config.root, input.path)\n\n return { type: 'path', path: resolved }\n}\n","import { access, glob, readFile, rm } from 'node:fs/promises'\nimport { join, relative, resolve } from 'node:path'\nimport { clean, runtime, toPosixPath, write } from '@internals/utils'\nimport { createStorage } from '../createStorage.ts'\n\n/**\n * Built-in filesystem storage driver.\n *\n * This is the default storage when no `storage` option is configured in the root config.\n * Keys are resolved against `process.cwd()`, so root-relative paths such as\n * `src/gen/api/getPets.ts` are written to the correct location without extra configuration.\n *\n * Writes are deduplicated and directory-safe:\n * - leading and trailing whitespace is trimmed before writing\n * - the write is skipped when the file content is already identical\n * - missing parent directories are created automatically\n * - Bun's native file API is used when running under Bun\n *\n * @example\n * ```ts\n * import { fsStorage } from '@kubb/core'\n * import { defineConfig } from 'kubb'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * storage: fsStorage(),\n * })\n * ```\n */\nexport const fsStorage = createStorage(() => ({\n name: 'fs',\n async hasItem(key: string) {\n try {\n await access(resolve(key))\n return true\n } catch (_error) {\n return false\n }\n },\n async getItem(key: string) {\n try {\n return await readFile(resolve(key), 'utf8')\n } catch (_error) {\n return null\n }\n },\n async setItem(key: string, value: string) {\n await write(resolve(key), value, { sanity: false })\n },\n async removeItem(key: string) {\n await rm(resolve(key), { force: true })\n },\n async getKeys(base?: string) {\n const resolvedBase = resolve(base ?? process.cwd())\n\n if (runtime.isBun) {\n const bunGlob = new Bun.Glob('**/*')\n return Array.fromAsync(bunGlob.scan({ cwd: resolvedBase, onlyFiles: true, dot: true }))\n }\n\n const keys: Array<string> = []\n try {\n for await (const entry of glob('**/*', { cwd: resolvedBase, withFileTypes: true })) {\n if (entry.isFile()) {\n keys.push(toPosixPath(relative(resolvedBase, join(entry.parentPath, entry.name))))\n }\n }\n } catch (_error) {\n // base directory does not exist yet\n }\n\n return keys\n },\n async clear(base?: string) {\n if (!base) {\n return\n }\n\n await clean(resolve(base))\n },\n}))\n","import { resolve } from 'node:path'\nimport { AsyncEventEmitter, BuildError } from '@internals/utils'\nimport { HOOK_LISTENERS_PER_PLUGIN } from './constants.ts'\nimport { Diagnostics } from './diagnostics.ts'\nimport { createStorage, type Storage } from './createStorage.ts'\nimport { KubbDriver } from './KubbDriver.ts'\nimport { fsStorage } from './storages/fsStorage.ts'\nimport type { BuildOutput, Config, KubbHooks, UserConfig } from './types.ts'\n\n/**\n * Builds a `Storage` view scoped to the file paths produced by the current build.\n * Reads delegate to the underlying `storage` so source bytes stay where they were\n * written. Writes register the key so subsequent reads and `getKeys` are scoped\n * to this build's output.\n */\nfunction createSourcesView(storage: Storage): Storage {\n const paths = new Set<string>()\n\n return createStorage(() => ({\n name: `${storage.name}:sources`,\n async hasItem(key: string) {\n return paths.has(key) && (await storage.hasItem(key))\n },\n async getItem(key: string) {\n return paths.has(key) ? storage.getItem(key) : null\n },\n async setItem(key: string, value: string) {\n paths.add(key)\n await storage.setItem(key, value)\n },\n async removeItem(key: string) {\n paths.delete(key)\n await storage.removeItem(key)\n },\n async getKeys(base?: string) {\n if (!base) return [...paths]\n const result: Array<string> = []\n for (const key of paths) {\n if (key.startsWith(base)) result.push(key)\n }\n return result\n },\n async clear() {\n paths.clear()\n await storage.clear()\n },\n }))()\n}\n\nfunction resolveConfig(userConfig: UserConfig): Config {\n return {\n ...userConfig,\n root: userConfig.root || process.cwd(),\n parsers: userConfig.parsers ?? [],\n output: {\n format: false,\n lint: false,\n extension: { '.ts': '.ts' },\n defaultBanner: 'simple',\n ...userConfig.output,\n },\n storage: userConfig.storage ?? fsStorage(),\n reporters: userConfig.reporters ?? [],\n plugins: userConfig.plugins ?? [],\n }\n}\n\ntype CreateKubbOptions = {\n hooks?: AsyncEventEmitter<KubbHooks>\n}\n\n/**\n * Kubb code-generation instance bound to a single config entry. Resolves the user\n * config in the constructor, so `config` is available right away, and shares `hooks`,\n * `storage`, and `driver` across the `setup → build` lifecycle.\n *\n * `createKubb` takes a plain config object (the shape `defineConfig` produces),\n * not a fluent builder.\n *\n * Attach event listeners to `.hooks` before calling `setup()` or `build()`.\n *\n * @example\n * ```ts\n * const kubb = createKubb(userConfig)\n * kubb.hooks.on('kubb:plugin:end', ({ plugin, duration }) => console.log(plugin.name, duration))\n * const { files, diagnostics } = await kubb.safeBuild()\n * ```\n */\nexport class Kubb {\n readonly hooks: AsyncEventEmitter<KubbHooks>\n readonly config: Config\n #driver: KubbDriver | null = null\n #storage: Storage | null = null\n\n constructor(userConfig: UserConfig, options: CreateKubbOptions = {}) {\n this.config = resolveConfig(userConfig)\n this.hooks = options.hooks ?? new AsyncEventEmitter<KubbHooks>()\n }\n\n get storage(): Storage {\n if (!this.#storage) throw new Error('[kubb] setup() must be called before accessing storage')\n return this.#storage\n }\n\n get driver(): KubbDriver {\n if (!this.#driver) throw new Error('[kubb] setup() must be called before accessing driver')\n return this.#driver\n }\n\n /**\n * Initializes the driver and storage. `build()` calls this automatically.\n */\n async setup(): Promise<void> {\n const config = this.config\n const driver = new KubbDriver(config, { hooks: this.hooks })\n const storage = createSourcesView(config.storage)\n\n // Each generator a plugin registers adds a listener to the shared hooks emitter, so size the\n // ceiling to the plugin count. Without this, a multi-generator plugin set trips Node's\n // EventEmitter leak warning at the default 10.\n this.hooks.setMaxListeners(Math.max(10, config.plugins.length * HOOK_LISTENERS_PER_PLUGIN))\n\n if (config.output.clean) {\n await config.storage.clear(resolve(config.root, config.output.path))\n }\n\n await driver.setup()\n\n this.#driver = driver\n this.#storage = storage\n }\n\n /**\n * Runs the full pipeline and throws on any plugin error.\n * Automatically calls `setup()` if needed.\n */\n async build(): Promise<BuildOutput> {\n const out = await this.safeBuild()\n if (Diagnostics.hasError(out.diagnostics)) {\n const errors = out.diagnostics\n .filter(Diagnostics.isProblem)\n .filter((diagnostic) => diagnostic.severity === 'error')\n .map((diagnostic) => diagnostic.cause ?? new Diagnostics.Error(diagnostic))\n throw new BuildError(`Build failed with ${errors.length} ${errors.length === 1 ? 'error' : 'errors'}`, { errors })\n }\n return out\n }\n\n /**\n * Runs the full pipeline and captures errors in `BuildOutput` instead of throwing.\n * Automatically calls `setup()` if needed. This is the canonical call: it never throws on\n * plugin errors, so callers stay in control of how failures surface.\n */\n async safeBuild(): Promise<BuildOutput> {\n if (!this.#driver) await this.setup()\n using cleanup = this\n const driver = cleanup.driver\n const storage = cleanup.storage\n const { diagnostics } = await driver.run({ storage })\n\n return { diagnostics, files: driver.fileManager.files, driver, storage }\n }\n\n dispose(): void {\n this.#driver?.dispose()\n }\n\n [Symbol.dispose](): void {\n this.dispose()\n }\n}\n\n/**\n * Constructs a {@link Kubb} build orchestrator from a user config. Equivalent\n * to `new Kubb(userConfig, options)` and the canonical public entry point.\n *\n * @example\n * ```ts\n * import { createKubb } from '@kubb/core'\n * import { adapterOas } from '@kubb/adapter-oas'\n * import { pluginTs } from '@kubb/plugin-ts'\n *\n * const kubb = createKubb({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * adapter: adapterOas(),\n * plugins: [pluginTs()],\n * })\n *\n * await kubb.build()\n * ```\n */\nexport function createKubb(userConfig: UserConfig, options: CreateKubbOptions = {}): Kubb {\n return new Kubb(userConfig, options)\n}\n","import type { Config } from './types.ts'\nimport type { Diagnostic } from './diagnostics.ts'\n\n/**\n * Numeric log-level thresholds used internally to compare verbosity.\n *\n * Higher numbers are more verbose.\n */\nexport const logLevel = {\n silent: Number.NEGATIVE_INFINITY,\n error: 0,\n warn: 1,\n info: 3,\n verbose: 4,\n} as const\n\n/**\n * A built-in reporter that renders a run's output, independent of the live logger view.\n *\n * - `cli` renders the per-config summary to the terminal (the default).\n * - `json` writes a machine-readable report to stdout, for CI.\n * - `file` writes a config's diagnostics to `.kubb/kubb-<name>-<timestamp>.log`.\n */\nexport type ReporterName = 'cli' | 'json' | 'file'\n\n/**\n * One config's outcome within a run, as handed to a {@link Reporter}.\n */\nexport type GenerationResult = {\n config: Config\n /**\n * Diagnostics collected while generating this config.\n */\n diagnostics: Array<Diagnostic>\n /**\n * Number of files written for this config.\n */\n filesCreated: number\n status: 'success' | 'failed'\n /**\n * `process.hrtime()` snapshot taken when this config started generating.\n */\n hrStart: [number, number]\n}\n\n/**\n * Render settings passed alongside the {@link GenerationResult}. These are not part of the run\n * data, such as the output verbosity.\n */\nexport type ReporterContext = {\n /**\n * Output verbosity. Use the `logLevel` constants exported from `@kubb/core`\n * (`silent`, `error`, `warn`, `info`, `verbose`).\n */\n logLevel: (typeof logLevel)[keyof typeof logLevel]\n}\n\n/**\n * Host-facing reporter, as installed onto a run. Unlike a Logger (the live TUI view), a reporter\n * never sees the event emitter. `report` runs once per config. `drain`, when present, runs once\n * after the last config.\n */\nexport type Reporter = {\n /**\n * Display name, matching a {@link ReporterName} for the built-ins.\n */\n name: string\n /**\n * Called once per config with that config's result and the render context.\n */\n report: (result: GenerationResult, context: ReporterContext) => void | Promise<void>\n /**\n * Optional finalizer called once after the run's last config. The host wires it to\n * `kubb:lifecycle:end`. {@link createReporter} closes it over the values that `report` returned.\n */\n drain?: (context: ReporterContext) => void | Promise<void>\n}\n\n/**\n * Reporter definition passed to {@link createReporter}. `report` returns the value to collect for\n * this config (e.g. a built report), and the optional `drain` receives the collected reports to\n * emit as one document. `T` is inferred from `report`'s return type.\n */\nexport type UserReporter<T = void> = {\n name: string\n report: (result: GenerationResult, context: ReporterContext) => T | Promise<T>\n drain?: (context: ReporterContext, reports: Array<T>) => void | Promise<void>\n}\n\n/**\n * Defines a reporter. When the definition has a `drain`, the returned reporter buffers each value\n * `report` returns and hands the array to `drain` once, then clears it. Without a `drain`, nothing\n * is buffered. Wiring the reporter onto the run's events is the host's job, so the reporter only\n * ever deals with a {@link GenerationResult}.\n *\n * @example\n * ```ts\n * import { createReporter, Diagnostics } from '@kubb/core'\n *\n * export const jsonReporter = createReporter({\n * name: 'json',\n * report(result) {\n * return { status: Diagnostics.hasError(result.diagnostics) ? 'failed' : 'success', diagnostics: result.diagnostics }\n * },\n * drain(context, reports) {\n * process.stdout.write(`${JSON.stringify(reports, null, 2)}\\n`)\n * },\n * })\n * ```\n */\nexport function createReporter<T = void>(reporter: UserReporter<T>): Reporter {\n const drain = reporter.drain\n if (!drain) {\n return {\n name: reporter.name,\n async report(result, context) {\n await reporter.report(result, context)\n },\n }\n }\n\n const reports: Array<T> = []\n\n return {\n name: reporter.name,\n async report(result, context) {\n reports.push(await reporter.report(result, context))\n },\n async drain(context) {\n await drain(context, reports)\n reports.length = 0\n },\n }\n}\n","import { resolve } from 'node:path'\nimport { getElapsedMs } from '@internals/utils'\nimport type { GenerationResult } from '../createReporter.ts'\nimport { Diagnostics, type SerializedDiagnostic } from '../diagnostics.ts'\n\n/**\n * One plugin's elapsed time, derived from a `performance` diagnostic.\n */\ntype ReportTiming = {\n plugin: string\n durationMs: number\n}\n\n/**\n * The normalized result of generating one config, shared by every reporter. Each reporter renders\n * the same {@link Report} in its own format (the `cli` summary, the `json` document, the `file`\n * log), so they always agree on the numbers. Build it with {@link buildReport}.\n */\nexport type Report = {\n /**\n * The config name, or an empty string when it is unnamed.\n */\n name: string\n status: 'success' | 'failed'\n plugins: {\n passed: number\n /**\n * Names of the plugins that failed.\n */\n failed: Array<string>\n total: number\n }\n counts: {\n errors: number\n warnings: number\n infos: number\n }\n filesCreated: number\n /**\n * Wall-clock time spent generating this config, in milliseconds.\n */\n durationMs: number\n /**\n * Absolute output directory the files were written to.\n */\n output: string\n /**\n * Per-plugin durations, slowest first.\n */\n timings: Array<ReportTiming>\n /**\n * The build problems, serialized to their JSON-safe fields plus a `docsUrl`.\n */\n diagnostics: Array<SerializedDiagnostic>\n}\n\n/**\n * Builds the normalized {@link Report} for one config from its {@link GenerationResult}. Splits the\n * diagnostics into problems and per-plugin timings (slowest first) and derives the plugin and issue\n * counts, so every reporter renders the same data.\n */\nexport function buildReport(result: GenerationResult): Report {\n const { config, diagnostics, filesCreated, status, hrStart } = result\n\n const failed = Diagnostics.failedPlugins(diagnostics)\n const total = config.plugins?.length ?? 0\n const counts = Diagnostics.count(diagnostics)\n const problems = diagnostics.filter(Diagnostics.isProblem)\n const timings = diagnostics\n .filter(Diagnostics.isPerformance)\n .sort((a, b) => b.duration - a.duration)\n .map((diagnostic) => ({ plugin: diagnostic.plugin, durationMs: diagnostic.duration }))\n\n return {\n name: config.name ?? '',\n status,\n plugins: { passed: total - failed.length, failed, total },\n counts,\n filesCreated,\n durationMs: getElapsedMs(hrStart),\n output: resolve(config.root, config.output.path),\n timings,\n diagnostics: problems.map((diagnostic) => Diagnostics.serialize(diagnostic)),\n }\n}\n","import { styleText } from 'node:util'\nimport { formatMs, randomCliColor } from '@internals/utils'\nimport { SUMMARY_MAX_BAR_LENGTH, SUMMARY_TIME_SCALE_DIVISOR } from '../constants.ts'\nimport { createReporter, logLevel as logLevelMap } from '../createReporter.ts'\nimport { buildReport, type Report } from './report.ts'\n\n/**\n * Builds the vitest/jest-style summary for one {@link Report}: right-aligned dim labels with\n * `N passed (total)` counts, and a per-plugin `Timings` section when `showTimings`.\n */\nfunction buildSummaryLines(report: Report, { showTimings }: { showTimings: boolean }): Array<string> {\n const { status, plugins, counts, filesCreated, durationMs, output, timings } = report\n\n const rows: Array<[label: string, value: string]> = []\n\n rows.push([\n 'Plugins',\n status === 'success'\n ? `${styleText('green', `${plugins.passed} passed`)} (${plugins.total})`\n : `${styleText('green', `${plugins.passed} passed`)} | ${styleText('red', `${plugins.failed.length} failed`)} (${plugins.total})`,\n ])\n\n if (status === 'failed' && plugins.failed.length > 0) {\n rows.push(['Failed', plugins.failed.map((name) => randomCliColor(name)).join(', ')])\n }\n\n if (counts.errors > 0 || counts.warnings > 0) {\n const issues = [\n counts.errors > 0 ? styleText('red', `${counts.errors} ${counts.errors === 1 ? 'error' : 'errors'}`) : undefined,\n counts.warnings > 0 ? styleText('yellow', `${counts.warnings} ${counts.warnings === 1 ? 'warning' : 'warnings'}`) : undefined,\n ]\n .filter(Boolean)\n .join(' | ')\n rows.push(['Issues', issues])\n }\n\n rows.push(['Files', `${styleText('green', String(filesCreated))} generated`])\n rows.push(['Duration', styleText('green', formatMs(durationMs))])\n rows.push(['Output', output])\n\n const labelWidth = Math.max(...rows.map(([label]) => label.length), timings.length > 0 ? 'Timings'.length : 0)\n const lines = rows.map(([label, value]) => `${styleText('dim', label.padStart(labelWidth))} ${value}`)\n\n if (showTimings && timings.length > 0) {\n const nameWidth = Math.max(0, ...timings.map((timing) => timing.plugin.length))\n const indent = ' '.repeat(labelWidth + 2)\n\n lines.push(styleText('dim', 'Timings'.padStart(labelWidth)))\n for (const timing of timings) {\n const timeStr = formatMs(timing.durationMs)\n const barLength = Math.min(Math.ceil(timing.durationMs / SUMMARY_TIME_SCALE_DIVISOR), SUMMARY_MAX_BAR_LENGTH)\n const bar = styleText('dim', '█'.repeat(barLength))\n lines.push(`${indent}${styleText('dim', '•')} ${timing.plugin.padEnd(nameWidth)} ${bar} ${timeStr}`)\n }\n }\n\n return lines\n}\n\n/**\n * Renders the summary as plain `console.log` lines so it works in every CLI (no clack/TTY\n * dependency): a blank line, the config name colored by status, then the summary rows.\n */\nfunction renderSummary(lines: ReadonlyArray<string>, { title, status }: { title: string; status: 'success' | 'failed' }): void {\n console.log('')\n if (title) {\n console.log(styleText(status === 'failed' ? 'red' : 'green', title))\n }\n for (const line of lines) {\n console.log(line)\n }\n}\n\n/**\n * The default `cli` reporter. Renders the {@link Report} for each config as it finishes, independent\n * of the live logger view. Suppressed at `silent`. The `verbose` level adds the per-plugin timings.\n */\nexport const cliReporter = createReporter({\n name: 'cli',\n report(result, { logLevel }) {\n if (logLevel <= logLevelMap.silent) {\n return\n }\n\n const report = buildReport(result)\n const lines = buildSummaryLines(report, { showTimings: logLevel >= logLevelMap.verbose })\n renderSummary(lines, { title: report.name, status: report.status })\n },\n})\n","import { relative, resolve } from 'node:path'\nimport process from 'node:process'\nimport { stripVTControlCharacters } from 'node:util'\nimport { formatMs, write } from '@internals/utils'\nimport { createReporter } from '../createReporter.ts'\nimport { type Diagnostic, Diagnostics } from '../diagnostics.ts'\nimport { buildReport, type Report } from './report.ts'\n\n/**\n * Builds the `## Summary` section: the same counts the cli and json reporters expose, as a list of\n * `label value` rows with the labels padded to a common width.\n */\nfunction buildSummarySection(report: Report): Array<string> {\n const { status, plugins, counts, filesCreated, durationMs, output } = report\n\n const rows: Array<[label: string, value: string]> = [\n ['Status', status],\n [\n 'Plugins',\n status === 'success' ? `${plugins.passed} passed (${plugins.total})` : `${plugins.passed} passed | ${plugins.failed.length} failed (${plugins.total})`,\n ],\n ]\n\n if (plugins.failed.length > 0) {\n rows.push(['Failed', plugins.failed.join(', ')])\n }\n\n rows.push(['Issues', `${counts.errors} errors | ${counts.warnings} warnings | ${counts.infos} infos`])\n rows.push(['Files', `${filesCreated} generated`])\n rows.push(['Duration', formatMs(durationMs)])\n rows.push(['Output', output])\n\n const labelWidth = Math.max(...rows.map(([label]) => label.length))\n const lines = rows.map(([label, value]) => ` ${label.padEnd(labelWidth)} ${value}`)\n\n return ['## Summary', '', ...lines]\n}\n\n/**\n * Builds the `## Problems` section: each problem rendered in the miette block format, blocks\n * separated by a blank line. Returns an empty array when there are no problems, so the caller\n * can drop the heading.\n */\nfunction buildProblemSection(diagnostics: ReadonlyArray<Diagnostic>): Array<string> {\n const problems = diagnostics.filter(Diagnostics.isProblem)\n if (problems.length === 0) {\n return []\n }\n\n const blocks = problems.map((diagnostic) => Diagnostics.formatLines(diagnostic).join('\\n'))\n return ['## Problems', '', blocks.join('\\n\\n')]\n}\n\n/**\n * Builds the `## Timings` section from a {@link Report}: one `plugin duration` row per record,\n * slowest first with the plugin names left-aligned and the durations right-aligned. Returns an\n * empty array when there are no timings.\n */\nfunction buildTimingSection(report: Report): Array<string> {\n const { timings } = report\n if (timings.length === 0) {\n return []\n }\n\n const nameWidth = Math.max(...timings.map((timing) => timing.plugin.length))\n const durations = timings.map((timing) => formatMs(timing.durationMs))\n const durationWidth = Math.max(...durations.map((duration) => duration.length))\n const rows = timings.map((timing, index) => ` ${timing.plugin.padEnd(nameWidth)} ${durations[index]!.padStart(durationWidth)}`)\n\n return ['## Timings', '', ...rows]\n}\n\n/**\n * The `file` reporter. Writes a config's {@link Report} to `.kubb/kubb-<name>-<timestamp>.log` as a\n * plain-text document: a `# <name> — <timestamp>` header, a `## Summary` with the same counts the\n * cli and json reporters expose, a `## Problems` section in the miette block format, and a\n * `## Timings` section. Selected with `--reporter file` (or `reporters: ['file']`).\n *\n * @note It captures the collected diagnostics once a config finishes, not the live\n * `kubb:info`/`kubb:plugin` event stream. Color is stripped so the file stays plain text even when\n * the run is attached to a TTY.\n */\nexport const fileReporter = createReporter({\n name: 'file',\n async report(result) {\n const { diagnostics, config } = result\n if (diagnostics.length === 0) {\n return\n }\n\n const report = buildReport(result)\n const header = config.name ? `# ${config.name} — ${new Date().toISOString()}` : `# ${new Date().toISOString()}`\n const sections = [buildSummarySection(report), buildProblemSection(diagnostics), buildTimingSection(report)].filter((section) => section.length > 0)\n const content = stripVTControlCharacters([header, ...sections.map((section) => section.join('\\n'))].join('\\n\\n'))\n\n const baseName = `${['kubb', config.name, Date.now()].filter(Boolean).join('-')}.log`\n const pathName = resolve(process.cwd(), '.kubb', baseName)\n\n await write(pathName, `${content}\\n`)\n console.error(`Debug log written to ${relative(process.cwd(), pathName)}`)\n },\n})\n","import process from 'node:process'\nimport { createReporter } from '../createReporter.ts'\nimport { buildReport } from './report.ts'\n\n/**\n * The `json` reporter. `report` returns one config's {@link Report}, which {@link createReporter}\n * buffers, and `drain` writes them as a single pretty-printed JSON array on `kubb:lifecycle:end`.\n * Buffering keeps a multi-config run one valid JSON document on stdout instead of concatenated\n * objects that would break `jq .`. The terminal reporter is suppressed while `json` is active so\n * stdout stays valid JSON.\n */\nexport const jsonReporter = createReporter({\n name: 'json',\n report(result) {\n return buildReport(result)\n },\n drain(_context, reports) {\n process.stdout.write(`${JSON.stringify(reports, null, 2)}\\n`)\n },\n})\n","import type { FileNode } from '@kubb/ast'\n\n/**\n * Minimal interface any Kubb renderer must satisfy.\n *\n * `TElement` is the type the renderer accepts, for example `KubbReactElement`\n * for `@kubb/renderer-jsx` or a custom type for your own renderer. Defaults to\n * `unknown` so generators that don't care about the element type work without\n * specifying it.\n */\nexport type Renderer<TElement = unknown> = {\n /**\n * Renders `element` and populates {@link files} with the resulting {@link FileNode} objects.\n * Called once per render cycle. Must resolve before {@link files} is read.\n */\n render(element: TElement): Promise<void>\n /**\n * Accumulated {@link FileNode} results produced by the last {@link render} call.\n * Not populated when {@link stream} is implemented.\n */\n readonly files: Array<FileNode>\n /**\n * When present, core calls this instead of {@link render} and {@link files},\n * forwarding each file to `FileManager` as soon as it is ready.\n */\n stream?(element: TElement): Iterable<FileNode>\n /**\n * Disposer hook so renderers participate in `using` blocks: `using r = rendererFactory()`\n * runs cleanup on every exit path, including thrown errors.\n */\n [Symbol.dispose](): void\n}\n\n/**\n * A factory function that produces a fresh {@link Renderer} per render cycle.\n *\n * Generators use this to declare which renderer handles their output.\n */\nexport type RendererFactory<TElement = unknown> = () => Renderer<TElement>\n\n/**\n * Defines a renderer factory. Renderers turn the generator's return value\n * (JSX, a template string, a tree of any shape) into `FileNode`s that get\n * written to disk.\n *\n * A renderer can target output formats beyond JSX, for instance a Handlebars\n * renderer or one that writes binary files. Plugins and generators pick the\n * renderer to use via the `renderer` field on `defineGenerator`.\n *\n * @example A minimal renderer that wraps a custom runtime\n * ```ts\n * import { createRenderer } from '@kubb/core'\n *\n * export const myRenderer = createRenderer(() => {\n * const runtime = new MyRuntime()\n * return {\n * async render(element) {\n * await runtime.render(element)\n * },\n * get files() {\n * return runtime.files\n * },\n * [Symbol.dispose]() {\n * runtime.dispose()\n * },\n * }\n * })\n * ```\n */\nexport function createRenderer<TElement = unknown>(factory: RendererFactory<TElement>): RendererFactory<TElement> {\n return factory\n}\n","import type { AsyncEventEmitter, PossiblePromise } from '@internals/utils'\nimport type { FileNode, InputMeta, OperationNode, SchemaNode } from '@kubb/ast'\nimport type { Adapter } from './createAdapter.ts'\nimport type { RendererFactory } from './createRenderer.ts'\nimport type { KubbHooks } from './types.ts'\nimport type { KubbDriver } from './KubbDriver.ts'\nimport type { Plugin, PluginFactoryOptions } from './definePlugin.ts'\nimport type { Resolver } from './defineResolver.ts'\nimport type { Config } from './types.ts'\n\n/**\n * Context passed to a generator's `schema`, `operation`, and `operations` methods.\n *\n * The driver sets `adapter` on the context before it runs a generator, so methods can read it\n * without a null check. `ctx.options` carries the per-node options after exclude/include/override\n * filtering for `schema` and `operation`, or the plugin-level options for `operations`.\n */\nexport type GeneratorContext<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {\n /**\n * The resolved Kubb config for this build, including `root`, `input`, `output`, and the\n * full plugin list.\n */\n config: Config\n /**\n * Absolute path to the current plugin's output directory.\n */\n root: string\n /**\n * The driver running this build. Most generators never need it. Prefer the scoped helpers\n * on this context (`getPlugin`, `getResolver`, `upsertFile`) over reaching into the driver.\n */\n driver: KubbDriver\n /**\n * Get a plugin by name, typed via `Kubb.PluginRegistry` when registered.\n */\n getPlugin<TName extends keyof Kubb.PluginRegistry>(name: TName): Plugin<Kubb.PluginRegistry[TName]> | undefined\n getPlugin(name: string): Plugin | undefined\n /**\n * Get a plugin by name, throws an error if not found.\n */\n requirePlugin<TName extends keyof Kubb.PluginRegistry>(name: TName): Plugin<Kubb.PluginRegistry[TName]>\n requirePlugin(name: string): Plugin\n /**\n * Get a resolver by plugin name, typed via `Kubb.PluginRegistry` when registered.\n */\n getResolver<TName extends keyof Kubb.PluginRegistry>(name: TName): Kubb.PluginRegistry[TName]['resolver']\n getResolver(name: string): Resolver\n /**\n * Add files only if they don't exist.\n */\n addFile: (...file: Array<FileNode>) => Promise<void>\n /**\n * Merge sources into the same output file.\n */\n upsertFile: (...file: Array<FileNode>) => Promise<void>\n /**\n * The build's event bus. Emit or listen to any `KubbHooks` event, for example to react to\n * `kubb:build:end` from inside a generator.\n */\n hooks: AsyncEventEmitter<KubbHooks>\n /**\n * The current plugin instance.\n */\n plugin: Plugin<TOptions>\n /**\n * The current plugin's resolver. It decides what every generated symbol and file path is\n * called. Kubb picks a `setResolver` registration first, then the plugin's static\n * `resolver`, then the built-in default.\n *\n * @example Resolve a type name\n * `ctx.resolver.default('pet', 'type') // 'Pet'`\n *\n * @example Resolve an output file\n * `ctx.resolver.resolveFile({ name: 'pet', extname: '.ts' }, { root, output })`\n */\n resolver: TOptions['resolver']\n /**\n * Report a warning. Collected as a `warning` diagnostic attributed to the current\n * plugin. It surfaces in the run summary but does not fail the build. For a structured\n * diagnostic with a code and source location, use `Diagnostics.report` or throw a\n * `Diagnostics.Error` directly.\n */\n warn: (message: string) => void\n /**\n * Report an error. Collected as an `error` diagnostic attributed to the current\n * plugin, which fails the build.\n */\n error: (error: string | Error) => void\n /**\n * Report an informational message. Collected as an `info` diagnostic attributed to\n * the current plugin.\n */\n info: (message: string) => void\n /**\n * The configured adapter instance.\n */\n adapter: Adapter\n /**\n * Document metadata from the adapter: title, version, base URL, and pre-computed\n * schema index fields (`circularNames`, `enumNames`).\n */\n meta: InputMeta\n /**\n * Resolved options after exclude/include/override filtering.\n */\n options: TOptions['resolvedOptions']\n}\n\n/**\n * Declares a named generator unit that walks the AST and emits files.\n *\n * `schema` runs for each schema node and `operation` for each operation node. `operations` runs\n * once after every operation node is walked. JSX-based generators require a `renderer` factory.\n * Return `Array<FileNode>` directly, or call `ctx.upsertFile()` manually and return `null` to\n * bypass rendering.\n *\n * @note Generators are consumed by plugins and registered via `ctx.addGenerator()` in `kubb:plugin:setup`.\n *\n * @example\n * ```ts\n * import { defineGenerator } from '@kubb/core'\n * import { jsxRenderer } from '@kubb/renderer-jsx'\n *\n * export const typeGenerator = defineGenerator({\n * name: 'typescript',\n * renderer: jsxRenderer,\n * schema(node, ctx) {\n * const { adapter, resolver, root, options } = ctx\n * return <File ...><Type node={node} resolver={resolver} /></File>\n * },\n * })\n * ```\n */\nexport type Generator<TOptions extends PluginFactoryOptions = PluginFactoryOptions, TElement = unknown> = {\n /**\n * Used in diagnostic messages and debug output.\n */\n name: string\n /**\n * Optional renderer factory that produces a {@link Renderer} for each render cycle.\n *\n * Generators that return renderer elements (e.g. JSX via `@kubb/renderer-jsx`) must set this\n * to the matching renderer factory (e.g. `jsxRenderer` from `@kubb/renderer-jsx`).\n *\n * Generators that only return `Array<FileNode>` or `void` do not need to set this.\n *\n * Leave it unset or set `renderer: null` to opt out of rendering.\n *\n * @example\n * ```ts\n * import { jsxRenderer } from '@kubb/renderer-jsx'\n * export const myGenerator = defineGenerator<PluginTs>({\n * renderer: jsxRenderer,\n * schema(node, ctx) { return <File ...>...</File> },\n * })\n * ```\n */\n renderer?: RendererFactory<TElement> | null\n /**\n * Called for each schema node in the AST walk.\n * `ctx` carries the plugin context with `adapter` and `meta` (document metadata),\n * plus `ctx.options` with the per-node resolved options (after exclude/include/override).\n */\n schema?: (node: SchemaNode, ctx: GeneratorContext<TOptions>) => PossiblePromise<TElement | Array<FileNode> | undefined | null>\n /**\n * Called for each operation node in the AST walk.\n * `ctx` carries the plugin context with `adapter` and `meta` (document metadata),\n * plus `ctx.options` with the per-node resolved options (after exclude/include/override).\n */\n operation?: (node: OperationNode, ctx: GeneratorContext<TOptions>) => PossiblePromise<TElement | Array<FileNode> | undefined | null>\n /**\n * Called once after all operations have been walked.\n * `ctx` carries the plugin context with `adapter` and `meta` (document metadata),\n * plus `ctx.options` with the plugin-level options for the batch call.\n */\n operations?: (nodes: Array<OperationNode>, ctx: GeneratorContext<TOptions>) => PossiblePromise<TElement | Array<FileNode> | undefined | null>\n}\n\n/**\n * Defines a generator: a unit of work that runs during the plugin's AST walk\n * and produces files. Plugins register generators via `ctx.addGenerator()`\n * inside `kubb:plugin:setup`.\n *\n * The returned object is the input as-is, but with `this` types preserved so\n * `schema`/`operation`/`operations` methods are correctly typed against the\n * plugin's `PluginFactoryOptions`. Renderer elements and `FileNode[]` returns\n * are both handled by the runtime, so pick whichever style fits.\n *\n * @example JSX-based schema generator\n * ```tsx\n * import { defineGenerator } from '@kubb/core'\n * import { jsxRenderer } from '@kubb/renderer-jsx'\n *\n * export const typeGenerator = defineGenerator({\n * name: 'typescript',\n * renderer: jsxRenderer,\n * schema(node, ctx) {\n * return (\n * <File path={`${ctx.root}/${node.name}.ts`}>\n * <Type node={node} resolver={ctx.resolver} />\n * </File>\n * )\n * },\n * })\n * ```\n */\nexport function defineGenerator<TOptions extends PluginFactoryOptions = PluginFactoryOptions, TElement = unknown>(\n generator: Generator<TOptions, TElement>,\n): Generator<TOptions, TElement> {\n return generator\n}\n","import type { FileNode } from '@kubb/ast'\n\ntype PrintOptions = {\n extname?: FileNode['extname']\n}\n\n/**\n * Converts a resolved {@link FileNode} into the final source string that gets\n * written to disk. Kubb ships with TypeScript and TSX parsers. Add your own\n * for new file types (JSON, Markdown, ...).\n */\nexport type Parser<TMeta extends object = object, TNode = unknown> = {\n /**\n * Display name used in diagnostics and the parser registry.\n */\n name: string\n /**\n * File extensions this parser handles. The driver registers the parser for each\n * extension in this list. A parser with `undefined` here is not registered, so\n * files of an unclaimed extension fall back to joining their sources verbatim.\n *\n * @example\n * `['.ts', '.js']`\n */\n extNames: Array<FileNode['extname']> | undefined\n /**\n * Serialize the file's AST into source code.\n */\n parse(file: FileNode<TMeta>, options?: PrintOptions): string\n /**\n * Render compiler AST nodes for this parser's language into source text.\n * Plugins call this to format the nodes they assemble before handing them\n * back to the parser as `FileNode.sources`.\n */\n print(...nodes: Array<TNode>): string\n}\n\n/**\n * Defines a parser with type-safe `this`. Used to register handlers for new\n * file extensions or to plug a non-TypeScript output into the build.\n *\n * @example\n * ```ts\n * import { defineParser } from '@kubb/core'\n * import { extractStringsFromNodes } from '@kubb/ast/utils'\n *\n * export const jsonParser = defineParser({\n * name: 'json',\n * extNames: ['.json'],\n * parse(file) {\n * return file.sources\n * .map((source) => extractStringsFromNodes(source.nodes ?? []))\n * .join('\\n')\n * },\n * print(...nodes) {\n * return nodes.map(String).join('\\n')\n * },\n * })\n * ```\n */\nexport function defineParser<T extends Parser>(parser: T): T {\n return parser\n}\n"],"mappings":"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"}
|