@kubb/core 5.10.2 → 5.10.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["process","process","process","logLevel","logLevelMap","process","createUnstorage","process"],"sources":["../../../internals/utils/src/isCIEnvironment.ts","../../../internals/utils/src/openInBrowser.ts","../../../internals/utils/src/tools.ts","../src/createAdapter.ts","../src/outputManifest.ts","../src/createStorage.ts","../src/storages/fsStorage.ts","../src/storages/cacheStorage.ts","../src/output/runHook.ts","../src/output/runOutputPasses.ts","../src/createKubb.ts","../src/createReporter.ts","../src/reporters/report.ts","../src/reporters/summary.ts","../src/reporters/cliReporter.ts","../src/storages/kubbStorage.ts","../src/reporters/fileReporter.ts","../src/reporters/jsonReporter.ts","../src/reporters/htmlReporter.ts","../src/createRenderer.ts","../src/defineGenerator.ts","../src/defineParser.ts","../src/storages/memoryStorage.ts","../src/manifest.ts","../src/installedPackages.ts"],"sourcesContent":["import process from 'node:process'\n\n/**\n * Returns `true` when a known CI provider has set its environment variable.\n * `CI=false` and `CI=0` count as not CI, so a user can opt out locally.\n */\nexport function isCIEnvironment(): boolean {\n const ci = process.env.CI\n return !!(\n (ci && ci !== 'false' && ci !== '0') ||\n process.env.GITHUB_ACTIONS ||\n process.env.GITLAB_CI ||\n process.env.BITBUCKET_BUILD_NUMBER ||\n process.env.JENKINS_URL ||\n process.env.CIRCLECI ||\n process.env.TRAVIS ||\n process.env.TEAMCITY_VERSION ||\n process.env.BUILDKITE ||\n process.env.TF_BUILD\n )\n}\n","import process from 'node:process'\nimport { x } from 'tinyexec'\nimport { isCIEnvironment } from './isCIEnvironment.ts'\n\nconst ignore = () => {}\n\n/**\n * Opens a URL or local file in the default browser, unless running in CI.\n */\nexport function openInBrowser(target: string): void {\n if (isCIEnvironment()) return\n\n if (process.platform === 'win32') {\n x('cmd', ['/c', 'start', '', target]).then(ignore, ignore)\n return\n }\n x(process.platform === 'darwin' ? 'open' : 'xdg-open', [target]).then(ignore, ignore)\n}\n","import { x } from 'tinyexec'\n\n/**\n * How one formatter or linter is invoked: the executable, the argv it takes for an output\n * directory, and what to report when it is not installed.\n */\nexport type ToolCommand = {\n command: string\n args: (outputPath: string) => Array<string>\n errorMessage: string\n}\n\n/**\n * CLI command descriptors for each supported code formatter.\n */\nexport const formatters = {\n prettier: {\n command: 'prettier',\n args: (outputPath: string) => ['--ignore-unknown', '--write', outputPath],\n errorMessage: 'Prettier not found',\n },\n biome: {\n command: 'biome',\n args: (outputPath: string) => ['format', '--write', outputPath],\n errorMessage: 'Biome not found',\n },\n oxfmt: {\n command: 'oxfmt',\n args: (outputPath: string) => [outputPath],\n errorMessage: 'Oxfmt not found',\n },\n} as const satisfies Record<string, ToolCommand>\n\n/**\n * CLI command descriptors for each supported linter.\n */\nexport const linters = {\n eslint: {\n command: 'eslint',\n args: (outputPath: string) => [outputPath, '--fix'],\n errorMessage: 'Eslint not found',\n },\n biome: {\n command: 'biome',\n args: (outputPath: string) => ['lint', '--fix', outputPath],\n errorMessage: 'Biome not found',\n },\n oxlint: {\n command: 'oxlint',\n // --no-ignore so oxlint lints the folder even when it's gitignored (generated output dirs usually are).\n args: (outputPath: string) => ['--fix', '--no-ignore', outputPath],\n errorMessage: 'Oxlint not found',\n },\n} as const satisfies Record<string, ToolCommand>\n\n/**\n * Preference order for `format: 'auto'`, most-preferred first. Spelled out rather than taken from\n * the table's key order, which is arbitrary and would silently change what `auto` picks.\n */\nexport const FORMATTER_PREFERENCE = ['oxfmt', 'biome', 'prettier'] as const\n\n/**\n * Preference order for `lint: 'auto'`, most-preferred first.\n */\nexport const LINTER_PREFERENCE = ['oxlint', 'biome', 'eslint'] as const\n\n/**\n * Whether `name` is on PATH or in a `node_modules/.bin` above `cwd` and answers `--version` with a zero exit.\n */\nasync function isToolAvailable(name: string, cwd?: string): Promise<boolean> {\n return x(name, ['--version'], { throwOnError: false, nodeOptions: { cwd, stdio: 'ignore' } }).then(\n ({ exitCode }) => exitCode === 0,\n () => false,\n )\n}\n\n/**\n * Returns the first installed executable from `candidates`, or `null` when none are found.\n *\n * Not memoized: a long-running host that probes repeatedly should cache the result itself, and a\n * `--watch` build should keep noticing a tool installed mid-session.\n */\nexport async function detectTool<TName extends string>(candidates: ReadonlyArray<TName>, cwd?: string): Promise<TName | null> {\n for (const candidate of candidates) {\n if (await isToolAvailable(candidate, cwd)) {\n return candidate\n }\n }\n\n return null\n}\n\n/**\n * Tokenizes a shell command string, respecting single and double quotes.\n *\n * @example\n * ```ts\n * tokenize('git commit -m \"initial commit\"')\n * // → ['git', 'commit', '-m', 'initial commit']\n * ```\n */\nexport function tokenize(command: string): Array<string> {\n return (command.match(/[^\\s\"']+|\"([^\"]*)\"|'([^']*)'/g) ?? []).map((token) => token.replace(/^[\"']|[\"']$/g, ''))\n}\n","import type { PossiblePromise } from '@internals/utils'\nimport type { InputNode } from '@kubb/ast'\nimport { defineExtension } from './defineExtension.ts'\nimport type { ExtensionFactory, ExtensionMeta } from './defineExtension.ts'\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 `defineExtension` with `kind: 'adapter'` 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: './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 meta?: ExtensionMeta<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 * An adapter that renames schemas (e.g. collision handling) must stamp `targetName` on\n * every ref node pointing at a renamed schema, so `resolveRefName` and `resolver.imports`\n * resolve a `$ref` to the file that is actually generated. Refs that keep their pointer's\n * last segment need no stamp.\n */\n parse: (source: AdapterSource, options?: { signal?: AbortSignal }) => PossiblePromise<InputNode>\n /**\n * Validate the document at the given path or URL.\n */\n validate: (input: string, options?: { throwOnError?: boolean }) => Promise<void>\n}\n\n/**\n * The object passed to `defineExtension` with `kind: 'adapter'`.\n */\nexport type AdapterDefinition<T extends AdapterFactoryOptions = AdapterFactoryOptions> = {\n meta: ExtensionMeta<T['name']>\n /**\n * Takes the user's options and returns the resolved options, which `build` receives and the adapter exposes as `options`.\n * Without `setup`, the user's options are the resolved options.\n */\n setup?(options: T['options']): T['resolvedOptions']\n /**\n * Returns the adapter's document and methods for the resolved options.\n */\n build(options: T['resolvedOptions']): Omit<Adapter<T>, 'name' | 'meta' | 'options'>\n}\n\n/**\n * The function `defineExtension` returns for an adapter. Call it with user options to get an `Adapter`.\n */\nexport type AdapterFactory<T extends AdapterFactoryOptions = AdapterFactoryOptions> = ExtensionFactory<'adapter', T['options'], Adapter<T>, T['name']>\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 * @deprecated Use `defineExtension` with `kind: 'adapter'` instead.\n */\nexport function createAdapter<T extends AdapterFactoryOptions = AdapterFactoryOptions>(definition: AdapterDefinition<T>): AdapterFactory<T> {\n return defineExtension({ kind: 'adapter', ...definition })\n}\n","import { hash } from 'node:crypto'\nimport { inParallel } from '@internals/utils'\nimport type { Storage } from './createStorage.ts'\nimport { FILE_CONCURRENCY } from './FileManager.ts'\n\n/**\n * Bumped when the stored shape changes, so an older cache is discarded instead of misread.\n */\nconst VERSION = 1\n\n/**\n * How one generated file looked on either side of the output passes.\n */\ntype OutputManifestEntry = {\n /**\n * Hash of the content Kubb handed to the storage.\n */\n source: string\n /**\n * Hash of what the storage held once the output passes were done with it.\n */\n output: string\n}\n\ntype ManifestData = {\n version: number\n entries: Record<string, OutputManifestEntry>\n}\n\n/**\n * Remembers what the output passes did to each generated file, so the next run can tell \"the\n * formatter already turned this exact source into what is stored\" apart from a real change.\n * Without it the storage compares Kubb's bytes against the formatter's, never matches, and\n * rewrites the whole output tree on every build.\n */\nexport type OutputManifest = {\n /**\n * `true` when `source` is known to come out of the output passes as exactly the content stored,\n * meaning the write can be skipped.\n */\n isUpToDate(options: { key: string; source: string; disk: string }): boolean\n /**\n * Records the source Kubb wrote for `key`, marking it as the only kind of file the output passes\n * can have changed and so the only kind `commit` has to re-read.\n */\n track(options: { key: string; source: string }): void\n /**\n * Re-reads the files written this run and persists their source/output pairs on top of what is\n * stored. Nothing is pruned: a run generating a different set of files, or writing to a different\n * storage in the same root, must not evict what another run recorded.\n */\n commit(): Promise<void>\n}\n\nconst MANIFEST_KEY = 'output-manifest.json'\n\nasync function loadEntries({ cache }: { cache: Storage }): Promise<Record<string, OutputManifestEntry>> {\n try {\n const stored = await cache.readItem(MANIFEST_KEY)\n if (stored === null) return {}\n\n const data = JSON.parse(stored) as ManifestData\n if (data.version !== VERSION) return {}\n if (typeof data.entries !== 'object' || data.entries === null || Array.isArray(data.entries)) return {}\n\n return data.entries\n } catch {\n return {}\n }\n}\n\n/**\n * Loads the stored manifest, starting empty when it is missing, unreadable, or from an older\n * version. `storage` holds the generated files, `cache` holds the manifest itself.\n *\n * @example\n * ```ts\n * const manifest = await createOutputManifest({ storage: config.storage, cache: cacheStorage({ root: config.root }) })\n * ```\n */\nexport async function createOutputManifest({ storage, cache }: { storage: Storage; cache: Storage }): Promise<OutputManifest> {\n const entries = await loadEntries({ cache })\n const tracked = new Map<string, string>()\n\n return {\n isUpToDate({ key, source, disk }) {\n const entry = entries[key]\n if (!entry) return false\n\n return entry.source === hash('sha256', source) && entry.output === hash('sha256', disk)\n },\n track({ key, source }) {\n tracked.set(key, hash('sha256', source))\n },\n async commit() {\n try {\n const next = { ...entries }\n\n // Reads the tree back through the same pool that wrote it, rather than one file at a time.\n await inParallel({\n items: [...tracked],\n limit: FILE_CONCURRENCY,\n run: async ([key, source]) => {\n const stored = await storage.readItem(key)\n if (stored === null) return\n\n next[key] = { source, output: hash('sha256', stored) }\n },\n })\n\n await cache.writeItem(MANIFEST_KEY, JSON.stringify({ version: VERSION, entries: next } satisfies ManifestData))\n } catch {\n /* the record is an optimization, so a storage failure here must not fail a finished build */\n }\n },\n }\n}\n","/**\n * Backend that persists generated files. Kubb ships with `fsStorage` (writes\n * to disk) and `memoryStorage` (keeps everything in RAM). Implement this\n * interface to write somewhere else, such as S3 or a database.\n *\n * Method names follow Node's filesystem vocabulary, so `readItem` reads like\n * `readFile` and `writeItem` like `writeFile`.\n */\nexport type Storage = {\n /**\n * Identifier used in logs and diagnostics (`'fs'`, `'memory'`, `'s3'`).\n */\n readonly name: string\n /**\n * Reads the stored string. Returns `null` when the key is missing.\n */\n readItem(key: string): Promise<string | null>\n /**\n * Stores `value` under `key`, creating any required structure (directories,\n * buckets, ...).\n *\n * Pass `stored` when the caller already read the previous value to avoid\n * reading it again in storage implementations that support the optimization.\n */\n writeItem(key: string, value: string, options?: { stored?: string | null }): Promise<void>\n /**\n * Deletes the entry for `key`. No-op when the key does not exist.\n */\n removeItem(key: string): Promise<void>\n /**\n * Returns every key. Pass `base` to filter to keys starting with that prefix.\n */\n readKeys(base?: string): Promise<Array<string>>\n /**\n * Removes stored entries. Pass `base` to scope the wipe to a key prefix.\n *\n * Omitting `base` is implementation-defined: in-memory stores wipe every\n * entry, while filesystem-backed stores treat a missing `base` as a no-op so\n * a bare `empty()` can never delete outside a known output directory.\n */\n empty(base?: string): Promise<void>\n}\n\n/**\n * Defines a custom storage backend. The builder receives user options and\n * returns a `Storage` implementation. Kubb ships with filesystem and in-memory\n * storages. A custom backend writes generated files elsewhere, such as cloud\n * storage or a database.\n *\n * @example In-memory storage (the built-in implementation)\n * ```ts\n * import { createStorage } from '@kubb/core'\n *\n * export const memoryStorage = createStorage(() => {\n * const store = new Map<string, string>()\n *\n * return {\n * name: 'memory',\n * async readItem(key) {\n * return store.get(key) ?? null\n * },\n * async writeItem(key, value) {\n * store.set(key, value)\n * },\n * async removeItem(key) {\n * store.delete(key)\n * },\n * async readKeys(base) {\n * const keys = [...store.keys()]\n * return base ? keys.filter((k) => k.startsWith(base)) : keys\n * },\n * async empty(base) {\n * if (!base) store.clear()\n * },\n * }\n * })\n * ```\n */\nexport const createStorage =\n <TOptions = Record<string, never>>(build: (options: TOptions) => Storage) =>\n (options?: TOptions): Storage =>\n build((options ?? {}) as TOptions)\n","import { glob, readFile, rm } from 'node:fs/promises'\nimport { join, relative, resolve } from 'node:path'\nimport { 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 already holds that content, ignoring any trailing newline\n * a formatter left behind\n * - missing parent directories are created automatically\n * - `FileManager.write` bounds in-flight writes, so this driver does not pace itself\n *\n * @example\n * ```ts\n * import { fsStorage } from '@kubb/core'\n * import { defineConfig } from 'kubb'\n *\n * export default defineConfig({\n * input: './petStore.yaml',\n * output: { path: './src/gen' },\n * storage: fsStorage(),\n * })\n * ```\n */\nexport const fsStorage = createStorage(() => ({\n name: 'fs',\n async readItem(key: string) {\n try {\n return await readFile(resolve(key), 'utf8')\n } catch (_error) {\n return null\n }\n },\n async writeItem(key: string, value: string, options?: { stored?: string | null }) {\n await write(resolve(key), value, { sanity: false, stored: options?.stored })\n },\n async removeItem(key: string) {\n await rm(resolve(key), { force: true })\n },\n async readKeys(base?: string) {\n const resolvedBase = resolve(base ?? process.cwd())\n const keys: Array<string> = []\n\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 empty(base?: string) {\n if (!base) {\n return\n }\n\n await rm(resolve(base), { recursive: true, force: true })\n },\n}))\n","import { hash } from 'node:crypto'\nimport { existsSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { createStorage } from '../createStorage.ts'\nimport { fsStorage } from './fsStorage.ts'\n\ntype CacheStorageOptions = {\n /**\n * Project root the cache directory is derived from.\n *\n * @default process.cwd()\n */\n root?: string\n}\n\n/**\n * Directory Kubb keeps build caches in. A project with a `node_modules` gets\n * `node_modules/.cache/kubb`, the convention babel and eslint already use, so the cache stays out\n * of version control. Without one it falls back to the OS temp directory, keyed by root so two\n * projects sharing that directory keep their own cache.\n *\n * @example Inside a project\n * `resolveCacheDir('/project') // '/project/node_modules/.cache/kubb'`\n */\nexport function resolveCacheDir(root: string): string {\n const nodeModules = join(root, 'node_modules')\n if (existsSync(nodeModules)) return join(nodeModules, '.cache', 'kubb')\n\n return join(tmpdir(), 'kubb', hash('sha256', root).slice(0, 16))\n}\n\n/**\n * Filesystem storage for build caches rather than generated code. Keys are plain names resolved\n * inside {@link resolveCacheDir}, so a caller stores `'x.json'` without knowing where the cache\n * lives. Kept apart from the configured output storage, which may not be a local disk at all.\n *\n * @example\n * ```ts\n * const cache = cacheStorage({ root: config.root })\n * await cache.writeItem('output-manifest.json', JSON.stringify(entries))\n * ```\n */\nexport const cacheStorage = createStorage(({ root = process.cwd() }: CacheStorageOptions) => {\n const dir = resolveCacheDir(root)\n const fs = fsStorage()\n const toPath = (key: string) => join(dir, key)\n\n return {\n name: 'cache',\n readItem: (key) => fs.readItem(toPath(key)),\n writeItem: (key, value) => fs.writeItem(toPath(key), value),\n removeItem: (key) => fs.removeItem(toPath(key)),\n readKeys: (base) => fs.readKeys(base ? toPath(base) : dir),\n // Same rule as `fsStorage`: a bare `empty()` deletes nothing, so storage-generic code cannot wipe the cache directory by accident.\n empty: async (base) => (base ? fs.empty(toPath(base)) : undefined),\n }\n})\n","import { randomUUID } from 'node:crypto'\nimport process from 'node:process'\nimport { createInterface } from 'node:readline'\nimport { toError } from '@internals/utils'\nimport { type Result, x } from 'tinyexec'\nimport type { Hookable } from '../Hookable.ts'\nimport type { KubbHooks } from '../types.ts'\n\n/**\n * Outcome of one hook subprocess, also carried by the `kubb:hook:end` hook it emits.\n */\nexport type HookResult = { success: true; error: null } | { success: false; error: Error; stdout?: string; stderr?: string }\n\nexport type RunHookOptions = {\n hooks: Hookable<KubbHooks>\n /** Executable to run, resolved on `PATH` and in every `node_modules/.bin` above `cwd`. */\n command: string\n args?: ReadonlyArray<string>\n /** Label shown instead of the command line, for example a `postGenerate` step name. */\n name?: string\n /** Working directory for the command. Defaults to the current process directory. */\n cwd?: string\n signal?: AbortSignal\n}\n\nconst KILL_GRACE_MS = 2_000\n\nasync function settle(proc: Result, hooks: Hookable<KubbHooks>, id: string, commandWithArgs: string): Promise<HookResult> {\n let childError: Error | null = null\n let lineError: Error | null = null\n let lines: Promise<void> = Promise.resolve()\n let killTimer: NodeJS.Timeout | undefined\n proc.process?.once('error', (error) => {\n childError = error\n // An abort only asks the child to stop; one that swallows SIGTERM would otherwise hang the run.\n killTimer = setTimeout(() => proc.kill('SIGKILL'), KILL_GRACE_MS).unref()\n })\n // Lines are only read when a logger listens, so a quiet host does not pay to iterate them.\n if (hooks.listenerCount('kubb:hook:line') > 0) {\n for (const input of [proc.process?.stdout, proc.process?.stderr]) {\n if (!input) continue\n createInterface({ input }).on('line', (line) => {\n lines = lines\n .then(() => hooks.callHook('kubb:hook:line', { id, line }))\n .catch((error) => {\n lineError ??= toError(error)\n })\n })\n }\n }\n const output = await Promise.resolve(proc).catch(() => null)\n clearTimeout(killTimer)\n await lines\n\n const error = childError ?? lineError\n if (error) return { success: false, error }\n if (output?.exitCode === 0) return { success: true, error: null }\n return { success: false, error: new Error(`Hook execute failed: ${commandWithArgs}`), stdout: output?.stdout, stderr: output?.stderr }\n}\n\n/**\n * Spawns a command and returns its outcome, announcing it through `kubb:hook:start`,\n * `kubb:hook:line` (one per stdout or stderr line, only while a listener is attached) and\n * `kubb:hook:end`. A non-zero exit, a spawn failure, an abort or a throwing line listener returns\n * `success: false` instead of throwing. The failure travels on the result and `kubb:hook:end`\n * only, and the caller emits `kubb:success` or a diagnostic, so nothing is reported twice.\n */\nexport async function runHook({ hooks, command, args = [], name, cwd = process.cwd(), signal }: RunHookOptions): Promise<HookResult> {\n const id = randomUUID()\n await hooks.callHook('kubb:hook:start', { id, command, name, args })\n\n const proc = x(command, [...args], {\n signal,\n throwOnError: false,\n nodeOptions: { cwd, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'], detached: process.platform !== 'win32' },\n })\n const result = await settle(proc, hooks, id, [command, ...args].join(' '))\n await hooks.callHook('kubb:hook:end', { id, command, name, args, ...result })\n\n return result\n}\n","import { existsSync } from 'node:fs'\nimport { styleText } from 'node:util'\nimport { detectTool, FORMATTER_PREFERENCE, formatters, LINTER_PREFERENCE, linters, type ToolCommand, tokenize } from '@internals/utils'\nimport { Diagnostics } from '../Diagnostics.ts'\nimport type { Hookable } from '../Hookable.ts'\nimport type { Config, KubbHooks } from '../types.ts'\nimport type { Diagnostic, ProblemDiagnostic } from '../Diagnostics.ts'\nimport { runHook } from './runHook.ts'\n\nexport type RunOutputPassesOptions = {\n config: Config\n /**\n * Absolute directory the formatter and linter run over.\n */\n outputPath: string\n hooks: Hookable<KubbHooks>\n signal?: AbortSignal\n}\n\ntype ToolPass = {\n kind: 'format' | 'lint'\n label: string\n verb: string\n tools: Record<string, ToolCommand>\n preference: ReadonlyArray<string>\n code: ProblemDiagnostic['code']\n}\n\n/**\n * Format and lint are one pass over the output directory that differs only in these values.\n * `label` and `verb` are spelled out: deriving them from `kind` gives \"lintter\" and \"lintting\".\n */\nconst TOOL_PASSES: ReadonlyArray<ToolPass> = [\n { kind: 'format', label: 'formatter', verb: 'Formatting', tools: formatters, preference: FORMATTER_PREFERENCE, code: Diagnostics.code.formatFailed },\n { kind: 'lint', label: 'linter', verb: 'Linting', tools: linters, preference: LINTER_PREFERENCE, code: Diagnostics.code.lintFailed },\n]\n\ntype ToolPassRun = Pick<RunOutputPassesOptions, 'hooks' | 'outputPath' | 'signal'> & { pass: ToolPass; setting: string; cwd: string }\n\n/**\n * Resolves `auto` to an installed tool and runs it. Returns the failure instead of throwing.\n */\nasync function runToolPass({ pass, setting, outputPath, hooks, cwd, signal }: ToolPassRun): Promise<Error | null> {\n const detected = setting === 'auto' ? await detectTool(pass.preference, cwd) : setting\n if (!detected) {\n await hooks.callHook('kubb:warn', { message: `No ${pass.label} found (${pass.preference.join(', ')}). Skipping ${pass.verb.toLowerCase()}.` })\n return null\n }\n if (setting === 'auto') {\n await hooks.callHook('kubb:info', { message: `Auto-detected ${pass.label}: ${styleText('dim', detected)}` })\n }\n\n const tool = pass.tools[detected]\n // Nothing to run over when the output directory was never written: the tool would fail on an\n // empty target (oxlint with --no-ignore reports \"No files found to lint\").\n if (!tool || !existsSync(outputPath)) return null\n\n const result = await runHook({ hooks, command: tool.command, args: tool.args(outputPath), cwd, signal })\n if (result.success) {\n await hooks.callHook('kubb:success', { message: `${pass.verb} with ${styleText('dim', detected)} on ${styleText('dim', outputPath)} successfully` })\n return null\n }\n return result.error\n}\n\n/**\n * Runs `output.format`, `output.lint` and `output.postGenerate` over the generated output and\n * returns the diagnostics they produced. Each failure is emitted through `Diagnostics.emit` and\n * returned, so it reaches the summary, the reporters and the exit code; the passes keep going so\n * one failing tool does not hide the next. `Kubb.generate()` runs this after an error-free build\n * unless the host passes its own `processOutput`.\n *\n * @example\n * ```ts\n * const diagnostics = await runOutputPasses({ config, outputPath: '/repo/src/gen', hooks })\n * ```\n */\nexport async function runOutputPasses({ config, outputPath, hooks, signal }: RunOutputPassesOptions): Promise<Array<Diagnostic>> {\n const diagnostics: Array<Diagnostic> = []\n const report = async (code: ProblemDiagnostic['code'], label: string, error: Error) => {\n const diagnostic: ProblemDiagnostic = {\n code,\n severity: 'error',\n message: `${label} failed: ${error.message}`,\n help: 'Check that the tool is installed and that the command and its config are correct.',\n location: { kind: 'config' },\n cause: error,\n }\n diagnostics.push(diagnostic)\n await Diagnostics.emit(hooks, diagnostic)\n }\n\n for (const pass of TOOL_PASSES) {\n const setting = config.output[pass.kind]\n if (!setting) continue\n\n await hooks.callHook(`kubb:${pass.kind}:start`)\n const error = await runToolPass({ pass, setting, outputPath, hooks, cwd: config.root, signal })\n if (error) await report(pass.code, pass.label, error)\n await hooks.callHook(`kubb:${pass.kind}:end`)\n signal?.throwIfAborted()\n }\n\n const commands = config.output.postGenerate ?? []\n if (commands.length === 0) return diagnostics\n\n await hooks.callHook('kubb:hooks:start')\n for (const entry of commands) {\n const { command, name } = typeof entry === 'string' ? { command: entry, name: undefined } : entry\n const [executable, ...args] = tokenize(command)\n if (!executable) continue\n\n const result = await runHook({ hooks, command: executable, args, name, cwd: config.root, signal })\n if (result.success) await hooks.callHook('kubb:success', { message: `${styleText('dim', name ?? command)} successfully executed` })\n if (!result.success) await report(Diagnostics.code.postGenerateFailed, 'Post-generate command', result.error)\n signal?.throwIfAborted()\n }\n await hooks.callHook('kubb:hooks:end')\n\n return diagnostics\n}\n","import { resolve } from 'node:path'\nimport { isPathInside } from '@internals/utils'\nimport type { FileNode } from '@kubb/ast'\nimport { type Diagnostic, Diagnostics } from './Diagnostics.ts'\nimport type { Storage } from './createStorage.ts'\nimport { KubbDriver } from './KubbDriver.ts'\nimport { createOutputManifest, type OutputManifest } from './outputManifest.ts'\nimport { cacheStorage } from './storages/cacheStorage.ts'\nimport { fsStorage } from './storages/fsStorage.ts'\nimport type { BuildOutput, Config, KubbHooks, UserConfig } from './types.ts'\nimport { Hookable } from './Hookable.ts'\nimport { runOutputPasses, type RunOutputPassesOptions } from './output/runOutputPasses.ts'\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 defaultBanner: 'simple',\n ...userConfig.output,\n },\n storage: userConfig.storage ?? fsStorage(),\n reporters: userConfig.reporters ?? [],\n plugins: userConfig.plugins ?? [],\n }\n}\n\n/**\n * Only the fs storage writes `output.path`, so only then do the passes have fresh files to run\n * over; a memory or custom storage would leave them formatting whatever an earlier run left there.\n */\nfunction writesOutputDirectory(storage: Storage): boolean {\n return storage.name === 'fs'\n}\n\n/**\n * Whether anything runs over the output directory after the files are written. Only then can the\n * bytes on disk stop matching what Kubb wrote, which is what the manifest exists to track.\n */\nfunction hasOutputPasses({ output, storage }: Pick<Config, 'output' | 'storage'>): boolean {\n return writesOutputDirectory(storage) && Boolean(output.format || output.lint || output.postGenerate?.length)\n}\n\nexport type CreateKubbOptions = {\n /**\n * Receives Kubb lifecycle hooks for the run.\n */\n hooks?: Hookable<KubbHooks>\n /**\n * Stops the build at the next safe checkpoint.\n */\n signal?: AbortSignal\n}\n\n/**\n * Host hooks for a single {@link Kubb.generate} call. All optional. Progress narration rides the\n * `kubb:*` lifecycle hooks on `.hooks`, so hosts subscribe there rather than pass a callback.\n */\nexport type GenerateOptions = {\n /**\n * Replaces the output passes that run after an error-free build. The default,\n * {@link runOutputPasses}, formats, lints and runs `output.postGenerate` over the generated\n * output and returns the diagnostics they emitted.\n */\n processOutput?: (context: RunOutputPassesOptions) => Promise<Array<Diagnostic>>\n}\n\n/**\n * What a {@link Kubb.generate} call produced, for the host to map onto its own result shape.\n */\nexport type GenerateResult = {\n /**\n * `true` when the build and every output pass completed without an error-level diagnostic.\n */\n success: boolean\n /**\n * All files generated during the build.\n */\n files: Array<FileNode>\n /**\n * Build diagnostics plus any collected from the output passes.\n */\n diagnostics: Array<Diagnostic>\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 hook listeners to `.hooks` before calling `setup()` or `build()`.\n *\n * @example\n * ```ts\n * const kubb = createKubb(userConfig)\n * kubb.hooks.hook('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: Hookable<KubbHooks>\n readonly config: Config\n #driver: KubbDriver | null = null\n #manifest: OutputManifest | null = null\n readonly #signal: AbortSignal | undefined\n\n constructor(userConfig: UserConfig, options: CreateKubbOptions = {}) {\n this.config = resolveConfig(userConfig)\n this.hooks = options.hooks ?? new Hookable<KubbHooks>()\n this.#signal = options.signal\n }\n\n get storage(): Storage {\n return this.config.storage\n }\n\n get driver(): KubbDriver {\n if (!this.#driver)\n throw new Diagnostics.Error({ code: Diagnostics.code.internalError, severity: 'error', message: '[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 signal = this.#signal\n signal?.throwIfAborted()\n const config = this.config\n const manifest = hasOutputPasses(config) ? await createOutputManifest({ storage: config.storage, cache: cacheStorage({ root: config.root }) }) : undefined\n\n const cleanPath = config.output.clean ? resolve(config.root, config.output.path) : undefined\n\n // clean only removes generated code. Refuse when the output resolves to the project root or\n // an ancestor of it, otherwise the wipe would delete kubb.config and every source file.\n if (cleanPath && isPathInside(config.root, cleanPath)) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.cleanRoot,\n severity: 'error',\n message: `output.clean cannot delete \"${cleanPath}\" because it is the project root or a parent of it.`,\n help: 'Point `output.path` at a subdirectory such as `./src/gen` so clean only removes generated code.',\n location: { kind: 'config' },\n })\n }\n\n // The driver empties `cleanPath` right before it writes the new files, so a run that fails\n // earlier, on an invalid spec or a plugin that throws, leaves the previous output in place.\n const driver = new KubbDriver(config, { hooks: this.hooks, manifest, signal, cleanPath })\n await driver.setup()\n\n this.#driver = driver\n this.#manifest = manifest ?? null\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 AggregateError(errors, `Build failed with ${errors.length} ${errors.length === 1 ? 'error' : '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 this.#signal?.throwIfAborted()\n if (!this.#driver) await this.setup()\n using self = this\n const driver = self.driver\n const storage = self.storage\n const { diagnostics } = await driver.run()\n\n return { diagnostics, files: driver.fileManager.files, driver, storage }\n }\n\n /**\n * Run one build and its output passes end to end, emitting the surrounding `kubb:generation:*`\n * hooks. Never throws on a build error: the outcome comes back in {@link GenerateResult} so the\n * host decides how failures surface. Telemetry and progress narration stay with the host, which\n * reads the result and subscribes to the `kubb:*` hooks.\n *\n * @example\n * ```ts\n * const result = await createKubb(config, { hooks }).generate()\n * if (!result.success) process.exitCode = 1\n * ```\n */\n async generate(options: GenerateOptions = {}): Promise<GenerateResult> {\n const signal = this.#signal\n signal?.throwIfAborted()\n const { hooks, config } = this\n const hrStart = process.hrtime()\n\n await hooks.callHook('kubb:generation:start', { config })\n\n // A setup failure, such as an invalid plugin entry, becomes a diagnostic like any build\n // problem, so reporters still get a failed `kubb:generation:end` for this config.\n let output: Pick<BuildOutput, 'files' | 'diagnostics'>\n try {\n await hooks.callHook('kubb:setup:start')\n await this.setup()\n await hooks.callHook('kubb:setup:end')\n\n output = await this.safeBuild()\n } catch (caughtError) {\n if (signal?.aborted) throw caughtError\n output = { files: [], diagnostics: [Diagnostics.from(caughtError)] }\n }\n const { files, diagnostics } = output\n const storage = this.storage\n signal?.throwIfAborted()\n\n // Surface every problem on the hooks. `performance` diagnostics feed the summary, not the\n // log, so they are skipped.\n for (const diagnostic of diagnostics) {\n if (Diagnostics.isProblem(diagnostic)) await Diagnostics.emit(hooks, diagnostic)\n }\n\n if (Diagnostics.hasError(diagnostics)) {\n await hooks.callHook('kubb:generation:end', { config, storage, diagnostics, filesCreated: files.length, status: 'failed', hrStart })\n return { success: false, files, diagnostics }\n }\n\n const processOutput = options.processOutput ?? runOutputPasses\n const outputDiagnostics = writesOutputDirectory(config.storage)\n ? await processOutput({ config, outputPath: resolve(config.root, config.output.path), hooks, signal })\n : []\n\n const finalDiagnostics = [...diagnostics, ...outputDiagnostics]\n const failed = Diagnostics.hasError(outputDiagnostics)\n\n // The formatter and linter have had their turn, so what sits on disk now is what the next run\n // has to recognize as unchanged. Only record it when they finished: a pass that failed halfway\n // leaves files Kubb has to stay free to regenerate.\n if (!failed) await this.#manifest?.commit()\n\n await hooks.callHook('kubb:generation:end', {\n config,\n storage,\n diagnostics: finalDiagnostics,\n filesCreated: files.length,\n status: failed ? 'failed' : 'success',\n hrStart,\n })\n\n return { success: !failed, files, diagnostics: finalDiagnostics }\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: './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 { LiteralUnion } from '@internals/utils'\nimport 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 * - `html` writes a browsable report directory to `.kubb/kubb-<name>-<timestamp>/`.\n */\nexport type ReporterName = 'cli' | 'json' | 'file' | 'html'\n\n/**\n * Files attributed to the plugin that first added them.\n */\nexport type ReporterPluginFiles = Array<{\n /** Plugin name. */\n plugin: string\n /** Generated file paths. */\n files: Array<string>\n}>\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 * Files attributed to the plugin that first added them, when requested by a reporter.\n */\n pluginFiles?: ReporterPluginFiles\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 hook 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: LiteralUnion<ReporterName>\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 * Whether the host should collect files from `kubb:plugin:end` hooks.\n */\n needsPluginFiles?: boolean\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: LiteralUnion<ReporterName>\n /**\n * Whether the host should collect files from `kubb:plugin:end` hooks.\n */\n needsPluginFiles?: boolean\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. The returned reporter buffers each value `report` returns in order and, when\n * the definition has a `drain`, hands the array to `drain` once and then clears it. Wiring the\n * reporter onto the run's hooks is the host's job, so the reporter only ever deals with a\n * {@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 reports: Array<T> = []\n\n return {\n name: reporter.name,\n needsPluginFiles: reporter.needsPluginFiles,\n async report(result, context) {\n const report = await reporter.report(result, context)\n if (reporter.drain) {\n reports.push(report)\n }\n },\n async drain(context) {\n await reporter.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 } from '../Diagnostics.ts'\nimport type { SerializedDiagnostic } from '../formatDiagnostic.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 // A failed run without timings stopped before any plugin ran, such as on an invalid plugin entry.\n plugins: { passed: status === 'failed' && timings.length === 0 ? 0 : 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 } from '@internals/utils'\nimport type { Report } from './report.ts'\n\n/**\n * Writes a finished summary. The `cli` reporter formats the lines and hands them to one of these,\n * so the caller decides where they land: plain `console.log` by default, or the active logger's own\n * output when a host installs one.\n */\nexport type SummaryRenderer = (lines: ReadonlyArray<string>, meta: { title: string; status: 'success' | 'failed' }) => void\n\n/**\n * Formats 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`. Pure, so a host\n * can render the same lines through whatever output it already owns.\n */\nexport function formatSummary(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 const notRun = plugins.total - plugins.passed - plugins.failed.length\n rows.push([\n 'Plugins',\n status === 'success'\n ? `${styleText('green', `${plugins.passed} passed`)} (${plugins.total})`\n : [\n styleText('green', `${plugins.passed} passed`),\n styleText('red', `${plugins.failed.length} failed`),\n notRun > 0 ? styleText('dim', `${notRun} not run`) : undefined,\n ]\n .filter(Boolean)\n .join(' | ') + ` (${plugins.total})`,\n ])\n\n if (status === 'failed' && plugins.failed.length > 0) {\n rows.push(['Failed', plugins.failed.map((name) => styleText('red', 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 / 100), 10)\n // One block per 100 ms, capped at ten.\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","import { styleText } from 'node:util'\nimport { createReporter, logLevel as logLevelMap, type Reporter } from '../createReporter.ts'\nimport { buildReport } from './report.ts'\nimport { formatSummary, type SummaryRenderer } from './summary.ts'\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 */\nconst consoleRenderer: SummaryRenderer = (lines, { title, status }) => {\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 * Builds a `cli` reporter that renders the {@link Report} for each config as it finishes.\n * Suppressed at `silent`. The `verbose` level adds the per-plugin timings.\n *\n * Pass `render` to send the summary through output the host already owns, so it lands inside that\n * host's grouping instead of alongside it. Omit it for the plain `console.log` writer.\n *\n * @example\n * ```ts\n * const reporter = createCliReporter({ render: (lines) => lines.forEach((line) => clack.log.message(line)) })\n * ```\n */\nexport function createCliReporter({ render = consoleRenderer }: { render?: SummaryRenderer } = {}): Reporter {\n return createReporter({\n name: 'cli',\n report(result, { logLevel }) {\n if (logLevel <= logLevelMap.silent) {\n return\n }\n\n const report = buildReport(result)\n\n render(formatSummary(report, { showTimings: logLevel >= logLevelMap.verbose }), { title: report.name, status: report.status })\n },\n })\n}\n\n/**\n * The default `cli` reporter, writing its summary straight to the console. Independent of the live\n * logger view.\n */\nexport const cliReporter = createCliReporter()\n","import { hash } from 'node:crypto'\nimport { chmodSync, mkdirSync } from 'node:fs'\nimport { homedir, tmpdir } from 'node:os'\nimport { join, resolve } from 'node:path'\nimport process from 'node:process'\nimport { createStorage as createUnstorage } from 'unstorage'\nimport fsDriver from 'unstorage/drivers/fs'\n\ntype KubbStorageOptions = {\n /**\n * Folder inside the Kubb home, or an absolute path such as `<cwd>/.kubb`.\n */\n base?: string\n}\n\nfunction ensurePrivateDir(dir: string): string {\n mkdirSync(dir, { recursive: true, mode: 0o700 })\n chmodSync(dir, 0o700)\n return dir\n}\n\n/**\n * Folder Kubb keeps its own files in, created with mode 0700. `base` resolves inside `KUBB_HOME`\n * (default `~/.kubb`). When that folder is not writable, it falls back to a folder in the OS temp directory.\n *\n * @example\n * `resolveKubbDir('cache') // '/home/me/.kubb/cache'`\n */\nexport function resolveKubbDir(base = ''): string {\n const dir = resolve(process.env.KUBB_HOME ?? join(homedir(), '.kubb'), base)\n try {\n return ensurePrivateDir(dir)\n } catch {\n return ensurePrivateDir(join(tmpdir(), 'kubb', hash('sha256', dir).slice(0, 16)))\n }\n}\n\n/**\n * unstorage on the fs driver, rooted at {@link resolveKubbDir}. The fs driver cannot set a file\n * mode, so the 0700 folder keeps files such as a stored token private.\n *\n * @example\n * ```ts\n * const storage = kubbStorage({ base: 'cache' })\n * await storage.setItem('machine-secret', secret)\n * ```\n */\nexport function kubbStorage({ base }: KubbStorageOptions = {}) {\n return createUnstorage({ driver: fsDriver({ base: resolveKubbDir(base) }) })\n}\n","import { join, relative, resolve } from 'node:path'\nimport process from 'node:process'\nimport { stripVTControlCharacters } from 'node:util'\nimport { createReporter } from '../createReporter.ts'\nimport { type Diagnostic, Diagnostics } from '../Diagnostics.ts'\nimport { kubbStorage, resolveKubbDir } from '../storages/kubbStorage.ts'\nimport { buildReport } from './report.ts'\nimport { formatSummary } from './summary.ts'\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 // The full stack, since a log file is what a bug report attaches.\n const blocks = problems.map((diagnostic) => Diagnostics.format(diagnostic, { verbose: true }).join('\\n'))\n return ['## Problems', '', blocks.join('\\n\\n')]\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 lines the\n * cli reporter prints (timings included), and a `## Problems` section in the miette block format.\n * 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` hook 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 summary = ['## Summary', '', ...formatSummary(report, { showTimings: true })]\n const sections = [summary, buildProblemSection(diagnostics)].filter((section) => section.length > 0)\n const content = stripVTControlCharacters([header, ...sections.map((section) => section.join('\\n'))].join('\\n\\n'))\n\n const name = config.name?.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, '')\n const baseName = `${['kubb', name, Date.now()].filter(Boolean).join('-')}.log`\n const dir = resolveKubbDir(resolve(process.cwd(), '.kubb'))\n\n await kubbStorage({ base: dir }).setItem(baseName, `${content}\\n`)\n console.error(`Debug log written to ${relative(process.cwd(), join(dir, baseName))}`)\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 { join, relative, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { openInBrowser, read } from '@internals/utils'\nimport { createReporter, type GenerationResult } from '../createReporter.ts'\nimport { kubbStorage, resolveKubbDir } from '../storages/kubbStorage.ts'\nimport { buildReport } from './report.ts'\n\nfunction serializeReport(result: GenerationResult): string {\n const data = JSON.stringify({ generatedAt: new Date().toISOString(), report: buildReport(result), pluginFiles: result.pluginFiles ?? [] })\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026')\n return `globalThis.__KUBB_REPORT__ = ${data}\\n`\n}\n\n/**\n * Writes a static HTML report directory selected with `--reporter html`.\n */\nexport const htmlReporter = createReporter({\n name: 'html',\n needsPluginFiles: true,\n async report(result) {\n const name = result.config.name?.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, '')\n const baseName = ['kubb', name, Date.now()].filter(Boolean).join('-')\n const dir = resolveKubbDir(resolve(process.cwd(), '.kubb'))\n const storage = kubbStorage({ base: dir })\n const assets = new URL('./html/', import.meta.url)\n const [html, ui] = await Promise.all([read(fileURLToPath(new URL('index.html', assets))), read(fileURLToPath(new URL('ui.iife.js', assets)))])\n\n await Promise.all([\n storage.setItem(`${baseName}/index.html`, html),\n storage.setItem(`${baseName}/ui.iife.js`, ui),\n storage.setItem(`${baseName}/data.js`, serializeReport(result)),\n ])\n const reportPath = join(dir, baseName, 'index.html')\n console.error(`HTML report written to ${relative(process.cwd(), reportPath)}`)\n openInBrowser(reportPath)\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 */\n readonly files: Array<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 { PossiblePromise } from '@internals/utils'\nimport type { FileNode, InputMeta, OperationNode, SchemaNode } from '@kubb/ast'\nimport type { Adapter } from './createAdapter.ts'\nimport type { ProblemDiagnostic } from './Diagnostics.ts'\nimport type { RendererFactory } from './createRenderer.ts'\nimport type { KubbHooks } from './types.ts'\nimport type { KubbDriver } from './KubbDriver.ts'\nimport type { ExtensionMeta } from './defineExtension.ts'\nimport type { Plugin, PluginType, PluginName, ResolvePluginOptions } from './definePlugin.ts'\nimport type { NodeCache } from './nodeCache.ts'\nimport type { Config } from './types.ts'\nimport type { Hookable } from './Hookable.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 PluginType = PluginType> = {\n /**\n * Stops cooperative generation work at the next safe checkpoint.\n */\n signal?: AbortSignal\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 PluginName>(name: TName): Plugin<ResolvePluginOptions<TName>> | undefined\n /**\n * Get a plugin by name, throws an error if not found.\n */\n requirePlugin<TName extends PluginName>(name: TName): Plugin<ResolvePluginOptions<TName>>\n /**\n * Get a resolver by plugin name, typed via `Kubb.PluginRegistry` when registered.\n */\n getResolver<TName extends PluginName>(name: TName): ResolvePluginOptions<TName>['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 hook bus. Emit or listen to any `KubbHooks` hook, for example to react to\n * `kubb:build:end` from inside a generator.\n */\n hooks: Hookable<KubbHooks>\n /**\n * The current plugin instance.\n */\n plugin: Plugin<TOptions> & { name: string; meta: ExtensionMeta }\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 name\n * `ctx.resolver.name('pet') // 'pet'`\n *\n * @example Resolve an output file\n * `ctx.resolver.file({ 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. Pass `options` to set\n * the `code`, the `help` text, or the source `location`.\n *\n * @example\n * `ctx.warn('Enum has no values', { help: 'Add values to the enum.', location: { kind: 'schema', pointer: '#/components/schemas/Status' } })`\n */\n warn: (message: string, options?: Partial<Pick<ProblemDiagnostic, 'code' | 'help' | 'location'>>) => void\n /**\n * Report an error. Collected as an `error` diagnostic attributed to the current\n * plugin, which fails the build. A `Diagnostics.Error` keeps its own code, help, and location.\n * Pass `options` to set them for a plain message or error.\n */\n error: (error: string | Error, options?: Partial<Pick<ProblemDiagnostic, 'code' | 'help' | 'location'>>) => void\n /**\n * Report an informational message. Collected as an `info` diagnostic attributed to\n * the current plugin. Pass `options` to set the `code`, the `help` text, or the source `location`.\n */\n info: (message: string, options?: Partial<Pick<ProblemDiagnostic, 'code' | 'help' | 'location'>>) => 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 * Cache scoped to the node being generated, shared by every plugin that generates from that\n * same node in the current pass. Use it to compute node-derived work (resolved names, imports,\n * parameters) once and let the other plugins reuse it. For the `operations` batch call, where\n * there is no single node, the cache is a fresh scratch scope for that call.\n */\n cache: NodeCache\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 PluginType = PluginType, 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 * Predicate checked before `schema` or `operation` runs for a node, mirroring `Macro['match']`\n * in `@kubb/ast`. Returning `false` skips the call for that node entirely, with no context work\n * beyond what the driver already builds per node and no render call, instead of the generator\n * itself being invoked and returning early. Omit it to run for every node, the default when\n * unset.\n *\n * Does not gate `operations`, which already runs once per plugin on the full batch rather than\n * per node.\n *\n * @example Only match GET operations\n * ```ts\n * match(node, ctx) {\n * return ast.isHttpOperationNode(node) && node.method.toLowerCase() === 'get'\n * }\n * ```\n */\n match?: (node: SchemaNode | OperationNode, ctx: GeneratorContext<TOptions>) => PossiblePromise<boolean>\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 `PluginType`. 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 PluginType = PluginType, TElement = unknown>(\n generator: Generator<TOptions, TElement>,\n): Generator<TOptions, TElement> {\n return generator\n}\n","import type { FileNode, UserFileNode } from '@kubb/ast'\nimport { defineExtension } from './defineExtension.ts'\nimport type { ExtensionFactory, ExtensionMeta, ExtensionNamed } from './defineExtension.ts'\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, TOptions extends object = object> = ExtensionNamed & {\n /**\n * The options passed to the parser factory.\n */\n options?: TOptions\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>): string\n /**\n * Turn the content of a `copy` file into a file node that `parse` prints. Omit to copy the file verbatim.\n */\n copy?(file: FileNode<TMeta>, source: string): UserFileNode<TMeta>\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 * Takes the user's options and returns the parser methods.\n */\nexport type ParserBuild<TOptions extends object, TMeta extends object, TNode> = (options: TOptions) => Omit<Parser<TMeta, TNode>, 'name' | 'meta' | 'options'>\n\n/**\n * The object passed to `defineExtension` with `kind: 'parser'`. `build` receives the user's options and returns the parser methods.\n */\nexport type ParserDefinition<TOptions extends object = object, TMeta extends object = object, TNode = unknown> = {\n meta: ExtensionMeta\n build: ParserBuild<TOptions, TMeta, TNode>\n}\n\n/**\n * The function `defineExtension` returns for a parser. Call it with user options to get a `Parser`.\n */\nexport type ParserFactory<TOptions extends object = object, TMeta extends object = object, TNode = unknown> = ExtensionFactory<\n 'parser',\n TOptions,\n Parser<TMeta, TNode, TOptions>\n>\n\n/**\n * Defines a parser from one object and returns a factory that takes the user's options.\n * Register the result in the `parsers` array on `defineConfig`.\n *\n * @deprecated Use `defineExtension` with `kind: 'parser'` instead.\n */\nexport function defineParser<TOptions extends object = object, TMeta extends object = object, TNode = unknown>(\n definition: ParserDefinition<TOptions, TMeta, TNode>,\n): ParserFactory<TOptions, TMeta, TNode> {\n return defineExtension({ kind: 'parser', ...definition })\n}\n","import { createStorage } from '../createStorage.ts'\n\n/**\n * In-memory storage driver. Useful for testing and dry-run scenarios where\n * generated output should be captured without touching the filesystem.\n *\n * All data lives in a `Map` scoped to the storage instance and is discarded\n * when the instance is garbage-collected.\n *\n * @example\n * ```ts\n * import { memoryStorage } from '@kubb/core'\n * import { defineConfig } from 'kubb'\n *\n * export default defineConfig({\n * input: './petStore.yaml',\n * output: { path: './src/gen' },\n * storage: memoryStorage(),\n * })\n * ```\n */\nexport const memoryStorage = createStorage(() => {\n const store = new Map<string, string>()\n\n return {\n name: 'memory',\n async readItem(key: string) {\n return store.get(key) ?? null\n },\n async writeItem(key: string, value: string) {\n store.set(key, value)\n },\n async removeItem(key: string) {\n store.delete(key)\n },\n async readKeys(base?: string) {\n const keys = [...store.keys()]\n return base ? keys.filter((k) => k.startsWith(base)) : keys\n },\n async empty(base?: string) {\n if (!base) {\n store.clear()\n return\n }\n for (const key of store.keys()) {\n if (key.startsWith(base)) {\n store.delete(key)\n }\n }\n },\n }\n})\n","import { isValid } from 'verkit'\nimport type { ExtensionKind } from './defineExtension.ts'\n\n/** A value that survives `JSON.stringify` and `JSON.parse` unchanged. */\nexport type JSONValue = string | number | boolean | null | Array<JSONValue> | { [key: string]: JSONValue }\n\n/**\n * One form field Studio renders for an extension. It edits the value at `path` in the options\n * object the user passes to the factory.\n */\nexport type ExtensionManifestOption = {\n /** Stable UI key, unique within the manifest. */\n key: string\n /** Where the value lives, such as `['output', 'path']`. */\n path: Array<string>\n label: string\n description?: string\n type: 'select' | 'boolean' | 'text' | 'number' | 'list'\n /** The extension's runtime default, shown when the option is unset. */\n default?: JSONValue\n /** For `select`. A choice with value `null` leaves the option unset. */\n choices?: Array<{ label?: string; value: JSONValue }>\n /** For `boolean`: the value written for `true`, `true` when unset. */\n trueValue?: JSONValue\n /** For `boolean`: the value written for `false`, `false` when unset. */\n falseValue?: JSONValue\n /** For `list`: template for each entry, where every `\"$item\"` string is replaced by the entry. */\n item?: JSONValue\n /** For `list`: upper-case each entry before writing it. */\n itemCase?: 'upper'\n}\n\n/**\n * The `kubb-extension.json` file an extension package ships at its root. Studio, the kubb.dev\n * registry, and `kubb add` read it.\n */\nexport type ExtensionManifest = {\n $schema?: string\n kind: ExtensionKind\n /** Equals the extension's `meta.name`. */\n name: string\n /** The factory export users call in `kubb.config.ts`, such as `pluginZod`. */\n export: string\n displayName: string\n description: string\n category?: string\n icon?: { light: string; dark?: string }\n /** HTTPS image or video URLs. */\n media?: Array<string>\n tags?: Array<string>\n docs?: string\n /** People who maintain the extension, shown on its kubb.dev page. */\n maintainers?: Array<{ name: string; github?: string }>\n /** Names of the extensions that must be in the same config, such as `['plugin-ts']`. */\n dependencies?: Array<string>\n /** Names of the extensions used when they are in the config, or needed only for some option values, such as `['plugin-faker']`. */\n optionalDependencies?: Array<string>\n compatibility?: { kubb?: string; node?: string }\n /** Plugins only: `client` ships the HTTP client runtime, `consumer` calls one but ships none. */\n role?: 'client' | 'consumer'\n options?: Array<ExtensionManifestOption>\n}\n\n/** What `kubb add` installs: a reviewed npm version, or a GitHub release tag and the commit it points to. */\nexport type RegistryArtifact =\n | { kind: 'npm'; package: string; version: string }\n | {\n kind: 'github'\n /** The `name` in the root `package.json`, so the package installs under this name. */\n package: string\n /** The release version, equal to `tag` without a leading `v`. */\n version: string\n owner: string\n repo: string\n tag: string\n /** The full commit SHA the tag points to. */\n commit: string\n }\n\n/** One extension in a registry's `index.json`. */\nexport type RegistryEntry = {\n /** `<owner>/<slug>`, such as `kubb-labs/plugin-zod`. */\n id: string\n kind: ExtensionKind\n type: 'official' | 'community'\n artifact: RegistryArtifact\n repository?: { url: string }\n manifest: ExtensionManifest\n stats?: { downloads?: number; weekly?: number; stars?: number }\n submittedAt: string\n publishedAt: string\n reviewedAt: string\n}\n\n/** The registry's `index.json`. */\nexport type RegistryIndex = { version: 1; generatedAt: string; extensions: Array<RegistryEntry> }\n\n/** One `docs/guides/<id>.md`: `id` is the file name, `title` its `#` heading, `description` the first paragraph. */\nexport type RegistryGuide = {\n id: string\n title: string\n description: string\n content: string\n}\n\n/** The registry's `<owner>/<slug>.json`: an entry plus the Markdown docs its pinned version ships. */\nexport type RegistryDetail = RegistryEntry & { overview: string | null; options?: string | null; guides?: Array<RegistryGuide> }\n\nconst EXTENSION_KINDS = new Set<unknown>(['plugin', 'adapter', 'parser'] satisfies Array<ExtensionKind>)\nconst OPTION_TYPES = new Set<unknown>(['select', 'boolean', 'text', 'number', 'list'] satisfies Array<ExtensionManifestOption['type']>)\nconst PACKAGE_NAME = /^(?:@[a-z0-9~][a-z0-9._~-]*\\/)?[a-z0-9~][a-z0-9._~-]*$/\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/\nconst REGISTRY_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*\\/[a-z0-9]+(?:-[a-z0-9]+)*$/\nconst GITHUB_OWNER = /^[A-Za-z0-9](?:[A-Za-z0-9]|-(?=[A-Za-z0-9])){0,38}$/\nconst GITHUB_REPO = /^(?!\\.\\.?$)[A-Za-z0-9._-]{1,100}$/\nconst COMMIT = /^[0-9a-f]{40}$/\n/** Option path segments that would reach an object's prototype when Studio writes the value by path. */\nconst UNSAFE_KEYS = new Set<unknown>(['__proto__', 'constructor', 'prototype'])\n\nconst isObject = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null && !Array.isArray(value)\nconst isOptionalString = (value: unknown) => value === undefined || typeof value === 'string'\nconst isFilledString = (value: unknown) => typeof value === 'string' && value !== ''\nconst matches = (pattern: RegExp, value: unknown) => typeof value === 'string' && pattern.test(value)\n/** Serializes with sorted object keys, so equal JSON values give equal strings whatever their key order. */\nconst canonicalJSON = (value: unknown) =>\n JSON.stringify(value, (_key, item: unknown) =>\n isObject(item)\n ? Object.fromEntries(\n Object.keys(item)\n .sort()\n .map((key) => [key, item[key]]),\n )\n : item,\n )\n\n/**\n * Whether `name` is a valid npm package name, such as `@kubb/plugin-ts`. Rejects paths, URLs,\n * `node:` specifiers, and names that start with `-`, so the result is safe to pass to `import()` or\n * a package manager.\n */\nexport function isPackageName(name: unknown): name is string {\n return typeof name === 'string' && name.length <= 214 && PACKAGE_NAME.test(name)\n}\n\nfunction isMaintainer(value: unknown): boolean {\n return (\n isObject(value) &&\n Object.keys(value).every((key) => key === 'name' || key === 'github') &&\n isFilledString(value.name) &&\n (value.github === undefined || isFilledString(value.github))\n )\n}\n\n/** Checks the shape of one manifest option, including that its path cannot reach a prototype. */\nfunction isOption(value: unknown): value is ExtensionManifestOption {\n if (!isObject(value)) return false\n const { key, path, label, description, type, choices, itemCase } = value\n return (\n isFilledString(key) &&\n Array.isArray(path) &&\n path.length > 0 &&\n path.every((segment) => isFilledString(segment) && !UNSAFE_KEYS.has(segment)) &&\n isFilledString(label) &&\n isOptionalString(description) &&\n OPTION_TYPES.has(type) &&\n (choices === undefined || (Array.isArray(choices) && choices.every((choice) => isObject(choice) && 'value' in choice && isOptionalString(choice.label)))) &&\n (itemCase === undefined || itemCase === 'upper')\n )\n}\n\n/**\n * What is wrong with the options of a well-formed manifest, beyond their shape: keys are unique, a\n * select has choices, and a select's default is one of its choice values. Empty when they pass.\n */\nexport function manifestProblems({ options = [] }: ExtensionManifest): Array<string> {\n const seen = new Set<string>()\n return options.flatMap((option) => {\n const problems = seen.has(option.key) ? [`option \"${option.key}\" is declared more than once`] : []\n seen.add(option.key)\n if (option.type !== 'select') return problems\n if (!option.choices?.length) return [...problems, `option \"${option.key}\" is a select without choices`]\n const knownDefault = !('default' in option) || option.choices.some((choice) => canonicalJSON(choice.value) === canonicalJSON(option.default))\n return knownDefault ? problems : [...problems, `option \"${option.key}\" has a default that is not one of its choices`]\n })\n}\n\n/**\n * Checks a parsed `kubb-extension.json` or a registry response before Kubb or Studio uses it: the\n * fields Kubb reads, every option's shape (including option paths that cannot reach a prototype),\n * and `manifestProblems`. A malformed manifest is skipped instead of trusted.\n */\nexport function isExtensionManifest(value: unknown): value is ExtensionManifest {\n if (!isObject(value)) return false\n const { kind, name, export: exportName, displayName, description, maintainers, dependencies, optionalDependencies, compatibility, role, options } = value\n return (\n EXTENSION_KINDS.has(kind) &&\n isPackageName(name) &&\n typeof exportName === 'string' &&\n IDENTIFIER.test(exportName) &&\n typeof displayName === 'string' &&\n typeof description === 'string' &&\n (maintainers === undefined || (Array.isArray(maintainers) && maintainers.every(isMaintainer))) &&\n (dependencies === undefined || (Array.isArray(dependencies) && dependencies.every(isPackageName))) &&\n (optionalDependencies === undefined || (Array.isArray(optionalDependencies) && optionalDependencies.every(isPackageName))) &&\n (compatibility === undefined ||\n (isObject(compatibility) && Object.entries(compatibility).every(([key, range]) => (key === 'kubb' || key === 'node') && typeof range === 'string'))) &&\n (role === undefined || role === 'client' || role === 'consumer') &&\n (options === undefined || (Array.isArray(options) && options.every(isOption))) &&\n manifestProblems(value as ExtensionManifest).length === 0\n )\n}\n\n/** Checks that no artifact field can reach a package manager as a flag or path, and that a GitHub tag names the version. */\nfunction isRegistryArtifact(value: unknown): value is RegistryArtifact {\n if (!isObject(value) || !isPackageName(value.package) || typeof value.version !== 'string' || !isValid(value.version)) return false\n if (value.kind === 'npm') return true\n return (\n value.kind === 'github' &&\n matches(GITHUB_OWNER, value.owner) &&\n matches(GITHUB_REPO, value.repo) &&\n (value.tag === value.version || value.tag === `v${value.version}`) &&\n matches(COMMIT, value.commit)\n )\n}\n\n/**\n * Checks one entry of a registry's `index.json` or `<owner>/<slug>.json`: a full `<owner>/<slug>` id,\n * an npm or GitHub artifact pinned to a valid version, and a valid manifest of the entry's kind.\n */\nexport function isRegistryEntry(value: unknown): value is RegistryEntry {\n if (!isObject(value)) return false\n const { id, kind, type, artifact, manifest } = value\n return (\n typeof id === 'string' &&\n REGISTRY_ID.test(id) &&\n EXTENSION_KINDS.has(kind) &&\n (type === 'official' || type === 'community') &&\n isRegistryArtifact(artifact) &&\n isExtensionManifest(manifest) &&\n manifest.kind === kind\n )\n}\n","import { existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport path from 'node:path'\nimport { type ExtensionManifest, isExtensionManifest, isPackageName } from './manifest.ts'\n\nexport type InstalledPackage = { package: string; version?: string; manifest?: ExtensionManifest }\n\n/** Reads and parses a JSON file. Throws when it is missing or not JSON. */\nconst readJSON = async (file: string): Promise<unknown> => JSON.parse(await readFile(file, 'utf8'))\n\n/**\n * The `dependencies` and `devDependencies` of the project at `root`, plus `packages`, with the\n * installed version and the valid `kubb-extension.json` each one ships, when it does. A package\n * also counts as installed when it resolves from one of the `resolveFrom` packages, such as `kubb`\n * for the extensions it ships with.\n */\nexport async function readInstalledPackages({\n root,\n packages = [],\n resolveFrom = [],\n}: {\n root: string\n packages?: Iterable<string>\n resolveFrom?: Array<string>\n}): Promise<Array<InstalledPackage>> {\n const project = createRequire(path.resolve(root, 'package.json'))\n const requires = [\n project,\n ...resolveFrom.flatMap((name) => {\n try {\n return [createRequire(project.resolve(`${name}/package.json`))]\n } catch {\n return []\n }\n }),\n ]\n const packageJSON = (await readJSON(path.join(root, 'package.json')).catch(() => null)) as { dependencies?: unknown; devDependencies?: unknown } | null\n const dependencies = [packageJSON?.dependencies, packageJSON?.devDependencies].flatMap((record) =>\n typeof record === 'object' && record !== null ? Object.keys(record) : [],\n )\n\n return Promise.all(\n [...new Set([...dependencies, ...packages])].filter(isPackageName).map(async (name): Promise<InstalledPackage> => {\n // Found on disk rather than resolved, because an `exports` map may hide `package.json` and the manifest.\n const dir = requires\n .flatMap((require) => require.resolve.paths(name) ?? [])\n .map((dir) => path.join(dir, name))\n .find((dir) => existsSync(path.join(dir, 'package.json')))\n if (!dir) return { package: name }\n try {\n const { version } = (await readJSON(path.join(dir, 'package.json'))) as { version?: unknown }\n const manifest = await readJSON(path.join(dir, 'kubb-extension.json')).catch(() => undefined)\n return { package: name, version: typeof version === 'string' ? version : undefined, manifest: isExtensionManifest(manifest) ? manifest : undefined }\n } catch {\n return { package: name }\n }\n }),\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["process","process","process","logLevel","logLevelMap","process","createUnstorage","process"],"sources":["../../../internals/utils/src/isCIEnvironment.ts","../../../internals/utils/src/openInBrowser.ts","../../../internals/utils/src/tools.ts","../src/createAdapter.ts","../src/outputManifest.ts","../src/createStorage.ts","../src/storages/fsStorage.ts","../src/storages/cacheStorage.ts","../src/output/runHook.ts","../src/output/runOutputPasses.ts","../src/createKubb.ts","../src/createReporter.ts","../src/reporters/report.ts","../src/reporters/summary.ts","../src/reporters/cliReporter.ts","../src/storages/kubbStorage.ts","../src/reporters/fileReporter.ts","../src/reporters/jsonReporter.ts","../src/reporters/htmlReporter.ts","../src/createRenderer.ts","../src/defineGenerator.ts","../src/defineParser.ts","../src/storages/memoryStorage.ts","../src/manifest.ts","../src/installedPackages.ts"],"sourcesContent":["import process from 'node:process'\n\n/**\n * Returns `true` when a known CI provider has set its environment variable.\n * `CI=false` and `CI=0` count as not CI, so a user can opt out locally.\n */\nexport function isCIEnvironment(): boolean {\n const ci = process.env.CI\n return !!(\n (ci && ci !== 'false' && ci !== '0') ||\n process.env.GITHUB_ACTIONS ||\n process.env.GITLAB_CI ||\n process.env.BITBUCKET_BUILD_NUMBER ||\n process.env.JENKINS_URL ||\n process.env.CIRCLECI ||\n process.env.TRAVIS ||\n process.env.TEAMCITY_VERSION ||\n process.env.BUILDKITE ||\n process.env.TF_BUILD\n )\n}\n","import process from 'node:process'\nimport { x } from 'tinyexec'\nimport { isCIEnvironment } from './isCIEnvironment.ts'\n\nconst ignore = () => {}\n\n/**\n * Opens a URL or local file in the default browser, unless running in CI.\n */\nexport function openInBrowser(target: string): void {\n if (isCIEnvironment()) return\n\n if (process.platform === 'win32') {\n x('cmd', ['/c', 'start', '', target]).then(ignore, ignore)\n return\n }\n x(process.platform === 'darwin' ? 'open' : 'xdg-open', [target]).then(ignore, ignore)\n}\n","import { x } from 'tinyexec'\n\n/**\n * How one formatter or linter is invoked: the executable, the argv it takes for an output\n * directory, and what to report when it is not installed.\n */\nexport type ToolCommand = {\n command: string\n args: (outputPath: string) => Array<string>\n errorMessage: string\n}\n\n/**\n * CLI command descriptors for each supported code formatter.\n */\nexport const formatters = {\n prettier: {\n command: 'prettier',\n args: (outputPath: string) => ['--ignore-unknown', '--write', outputPath],\n errorMessage: 'Prettier not found',\n },\n biome: {\n command: 'biome',\n args: (outputPath: string) => ['format', '--write', outputPath],\n errorMessage: 'Biome not found',\n },\n oxfmt: {\n command: 'oxfmt',\n args: (outputPath: string) => [outputPath],\n errorMessage: 'Oxfmt not found',\n },\n} as const satisfies Record<string, ToolCommand>\n\n/**\n * CLI command descriptors for each supported linter.\n */\nexport const linters = {\n eslint: {\n command: 'eslint',\n args: (outputPath: string) => [outputPath, '--fix'],\n errorMessage: 'Eslint not found',\n },\n biome: {\n command: 'biome',\n args: (outputPath: string) => ['lint', '--fix', outputPath],\n errorMessage: 'Biome not found',\n },\n oxlint: {\n command: 'oxlint',\n // --no-ignore so oxlint lints the folder even when it's gitignored (generated output dirs usually are).\n args: (outputPath: string) => ['--fix', '--no-ignore', outputPath],\n errorMessage: 'Oxlint not found',\n },\n} as const satisfies Record<string, ToolCommand>\n\n/**\n * Preference order for `format: 'auto'`, most-preferred first. Spelled out rather than taken from\n * the table's key order, which is arbitrary and would silently change what `auto` picks.\n */\nexport const FORMATTER_PREFERENCE = ['oxfmt', 'biome', 'prettier'] as const\n\n/**\n * Preference order for `lint: 'auto'`, most-preferred first.\n */\nexport const LINTER_PREFERENCE = ['oxlint', 'biome', 'eslint'] as const\n\n/**\n * Whether `name` is on PATH or in a `node_modules/.bin` above `cwd` and answers `--version` with a zero exit.\n */\nasync function isToolAvailable(name: string, cwd?: string): Promise<boolean> {\n return x(name, ['--version'], { throwOnError: false, nodeOptions: { cwd, stdio: 'ignore' } }).then(\n ({ exitCode }) => exitCode === 0,\n () => false,\n )\n}\n\n/**\n * Returns the first installed executable from `candidates`, or `null` when none are found.\n *\n * Not memoized: a long-running host that probes repeatedly should cache the result itself, and a\n * `--watch` build should keep noticing a tool installed mid-session.\n */\nexport async function detectTool<TName extends string>(candidates: ReadonlyArray<TName>, cwd?: string): Promise<TName | null> {\n for (const candidate of candidates) {\n if (await isToolAvailable(candidate, cwd)) {\n return candidate\n }\n }\n\n return null\n}\n\n/**\n * Tokenizes a shell command string, respecting single and double quotes.\n *\n * @example\n * ```ts\n * tokenize('git commit -m \"initial commit\"')\n * // → ['git', 'commit', '-m', 'initial commit']\n * ```\n */\nexport function tokenize(command: string): Array<string> {\n return (command.match(/[^\\s\"']+|\"([^\"]*)\"|'([^']*)'/g) ?? []).map((token) => token.replace(/^[\"']|[\"']$/g, ''))\n}\n","import type { PossiblePromise } from '@internals/utils'\nimport type { InputNode } from '@kubb/ast'\nimport { defineExtension } from './defineExtension.ts'\nimport type { ExtensionFactory, ExtensionMeta } from './defineExtension.ts'\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 `defineExtension` with `kind: 'adapter'` 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: './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 meta?: ExtensionMeta<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 * An adapter that renames schemas (e.g. collision handling) must stamp `targetName` on\n * every ref node pointing at a renamed schema, so `resolveRefName` and `resolver.imports`\n * resolve a `$ref` to the file that is actually generated. Refs that keep their pointer's\n * last segment need no stamp.\n */\n parse: (source: AdapterSource, options?: { signal?: AbortSignal }) => PossiblePromise<InputNode>\n /**\n * Validate the document at the given path or URL.\n */\n validate: (input: string, options?: { throwOnError?: boolean }) => Promise<void>\n}\n\n/**\n * The object passed to `defineExtension` with `kind: 'adapter'`.\n */\nexport type AdapterDefinition<T extends AdapterFactoryOptions = AdapterFactoryOptions> = {\n meta: ExtensionMeta<T['name']>\n /**\n * Takes the user's options and returns the resolved options, which `build` receives and the adapter exposes as `options`.\n * Without `setup`, the user's options are the resolved options.\n */\n setup?(options: T['options']): T['resolvedOptions']\n /**\n * Returns the adapter's document and methods for the resolved options.\n */\n build(options: T['resolvedOptions']): Omit<Adapter<T>, 'name' | 'meta' | 'options'>\n}\n\n/**\n * The function `defineExtension` returns for an adapter. Call it with user options to get an `Adapter`.\n */\nexport type AdapterFactory<T extends AdapterFactoryOptions = AdapterFactoryOptions> = ExtensionFactory<'adapter', T['options'], Adapter<T>, T['name']>\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 * @deprecated Use `defineExtension` with `kind: 'adapter'` instead.\n */\nexport function createAdapter<T extends AdapterFactoryOptions = AdapterFactoryOptions>(definition: AdapterDefinition<T>): AdapterFactory<T> {\n return defineExtension({ kind: 'adapter', ...definition })\n}\n","import { hash } from 'node:crypto'\nimport { inParallel } from '@internals/utils'\nimport type { Storage } from './createStorage.ts'\nimport { FILE_CONCURRENCY } from './FileManager.ts'\n\n/**\n * Bumped when the stored shape changes, so an older cache is discarded instead of misread.\n */\nconst VERSION = 1\n\n/**\n * How one generated file looked on either side of the output passes.\n */\ntype OutputManifestEntry = {\n /**\n * Hash of the content Kubb handed to the storage.\n */\n source: string\n /**\n * Hash of what the storage held once the output passes were done with it.\n */\n output: string\n}\n\ntype ManifestData = {\n version: number\n entries: Record<string, OutputManifestEntry>\n}\n\n/**\n * Remembers what the output passes did to each generated file, so the next run can tell \"the\n * formatter already turned this exact source into what is stored\" apart from a real change.\n * Without it the storage compares Kubb's bytes against the formatter's, never matches, and\n * rewrites the whole output tree on every build.\n */\nexport type OutputManifest = {\n /**\n * `true` when `source` is known to come out of the output passes as exactly the content stored,\n * meaning the write can be skipped.\n */\n isUpToDate(options: { key: string; source: string; disk: string }): boolean\n /**\n * Records the source Kubb wrote for `key`, marking it as the only kind of file the output passes\n * can have changed and so the only kind `commit` has to re-read.\n */\n track(options: { key: string; source: string }): void\n /**\n * Re-reads the files written this run and persists their source/output pairs on top of what is\n * stored. Nothing is pruned: a run generating a different set of files, or writing to a different\n * storage in the same root, must not evict what another run recorded.\n */\n commit(): Promise<void>\n}\n\nconst MANIFEST_KEY = 'output-manifest.json'\n\nasync function loadEntries({ cache }: { cache: Storage }): Promise<Record<string, OutputManifestEntry>> {\n try {\n const stored = await cache.readItem(MANIFEST_KEY)\n if (stored === null) return {}\n\n const data = JSON.parse(stored) as ManifestData\n if (data.version !== VERSION) return {}\n if (typeof data.entries !== 'object' || data.entries === null || Array.isArray(data.entries)) return {}\n\n return data.entries\n } catch {\n return {}\n }\n}\n\n/**\n * Loads the stored manifest, starting empty when it is missing, unreadable, or from an older\n * version. `storage` holds the generated files, `cache` holds the manifest itself.\n *\n * @example\n * ```ts\n * const manifest = await createOutputManifest({ storage: config.storage, cache: cacheStorage({ root: config.root }) })\n * ```\n */\nexport async function createOutputManifest({ storage, cache }: { storage: Storage; cache: Storage }): Promise<OutputManifest> {\n const entries = await loadEntries({ cache })\n const tracked = new Map<string, string>()\n\n return {\n isUpToDate({ key, source, disk }) {\n const entry = entries[key]\n if (!entry) return false\n\n return entry.source === hash('sha256', source) && entry.output === hash('sha256', disk)\n },\n track({ key, source }) {\n tracked.set(key, hash('sha256', source))\n },\n async commit() {\n try {\n const next = { ...entries }\n\n // Reads the tree back through the same pool that wrote it, rather than one file at a time.\n await inParallel({\n items: [...tracked],\n limit: FILE_CONCURRENCY,\n run: async ([key, source]) => {\n const stored = await storage.readItem(key)\n if (stored === null) return\n\n next[key] = { source, output: hash('sha256', stored) }\n },\n })\n\n await cache.writeItem(MANIFEST_KEY, JSON.stringify({ version: VERSION, entries: next } satisfies ManifestData))\n } catch {\n /* the record is an optimization, so a storage failure here must not fail a finished build */\n }\n },\n }\n}\n","/**\n * Backend that persists generated files. Kubb ships with `fsStorage` (writes\n * to disk) and `memoryStorage` (keeps everything in RAM). Implement this\n * interface to write somewhere else, such as S3 or a database.\n *\n * Method names follow Node's filesystem vocabulary, so `readItem` reads like\n * `readFile` and `writeItem` like `writeFile`.\n */\nexport type Storage = {\n /**\n * Identifier used in logs and diagnostics (`'fs'`, `'memory'`, `'s3'`).\n */\n readonly name: string\n /**\n * Reads the stored string. Returns `null` when the key is missing.\n */\n readItem(key: string): Promise<string | null>\n /**\n * Stores `value` under `key`, creating any required structure (directories,\n * buckets, ...).\n *\n * Pass `stored` when the caller already read the previous value to avoid\n * reading it again in storage implementations that support the optimization.\n */\n writeItem(key: string, value: string, options?: { stored?: string | null }): Promise<void>\n /**\n * Deletes the entry for `key`. No-op when the key does not exist.\n */\n removeItem(key: string): Promise<void>\n /**\n * Returns every key. Pass `base` to filter to keys starting with that prefix.\n */\n readKeys(base?: string): Promise<Array<string>>\n /**\n * Removes stored entries. Pass `base` to scope the wipe to a key prefix.\n *\n * Omitting `base` is implementation-defined: in-memory stores wipe every\n * entry, while filesystem-backed stores treat a missing `base` as a no-op so\n * a bare `empty()` can never delete outside a known output directory.\n */\n empty(base?: string): Promise<void>\n}\n\n/**\n * Defines a custom storage backend. The builder receives user options and\n * returns a `Storage` implementation. Kubb ships with filesystem and in-memory\n * storages. A custom backend writes generated files elsewhere, such as cloud\n * storage or a database.\n *\n * @example In-memory storage (the built-in implementation)\n * ```ts\n * import { createStorage } from '@kubb/core'\n *\n * export const memoryStorage = createStorage(() => {\n * const store = new Map<string, string>()\n *\n * return {\n * name: 'memory',\n * async readItem(key) {\n * return store.get(key) ?? null\n * },\n * async writeItem(key, value) {\n * store.set(key, value)\n * },\n * async removeItem(key) {\n * store.delete(key)\n * },\n * async readKeys(base) {\n * const keys = [...store.keys()]\n * return base ? keys.filter((k) => k.startsWith(base)) : keys\n * },\n * async empty(base) {\n * if (!base) store.clear()\n * },\n * }\n * })\n * ```\n */\nexport const createStorage =\n <TOptions = Record<string, never>>(build: (options: TOptions) => Storage) =>\n (options?: TOptions): Storage =>\n build((options ?? {}) as TOptions)\n","import { glob, readFile, rm } from 'node:fs/promises'\nimport { join, relative, resolve } from 'node:path'\nimport { 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 already holds that content, ignoring any trailing newline\n * a formatter left behind\n * - missing parent directories are created automatically\n * - `FileManager.write` bounds in-flight writes, so this driver does not pace itself\n *\n * @example\n * ```ts\n * import { fsStorage } from '@kubb/core'\n * import { defineConfig } from 'kubb'\n *\n * export default defineConfig({\n * input: './petStore.yaml',\n * output: { path: './src/gen' },\n * storage: fsStorage(),\n * })\n * ```\n */\nexport const fsStorage = createStorage(() => ({\n name: 'fs',\n async readItem(key: string) {\n try {\n return await readFile(resolve(key), 'utf8')\n } catch (_error) {\n return null\n }\n },\n async writeItem(key: string, value: string, options?: { stored?: string | null }) {\n await write(resolve(key), value, { sanity: false, stored: options?.stored })\n },\n async removeItem(key: string) {\n await rm(resolve(key), { force: true })\n },\n async readKeys(base?: string) {\n const resolvedBase = resolve(base ?? process.cwd())\n const keys: Array<string> = []\n\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 empty(base?: string) {\n if (!base) {\n return\n }\n\n await rm(resolve(base), { recursive: true, force: true })\n },\n}))\n","import { hash } from 'node:crypto'\nimport { existsSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { createStorage } from '../createStorage.ts'\nimport { fsStorage } from './fsStorage.ts'\n\ntype CacheStorageOptions = {\n /**\n * Project root the cache directory is derived from.\n *\n * @default process.cwd()\n */\n root?: string\n}\n\n/**\n * Directory Kubb keeps build caches in. A project with a `node_modules` gets\n * `node_modules/.cache/kubb`, the convention babel and eslint already use, so the cache stays out\n * of version control. Without one it falls back to the OS temp directory, keyed by root so two\n * projects sharing that directory keep their own cache.\n *\n * @example Inside a project\n * `resolveCacheDir('/project') // '/project/node_modules/.cache/kubb'`\n */\nexport function resolveCacheDir(root: string): string {\n const nodeModules = join(root, 'node_modules')\n if (existsSync(nodeModules)) return join(nodeModules, '.cache', 'kubb')\n\n return join(tmpdir(), 'kubb', hash('sha256', root).slice(0, 16))\n}\n\n/**\n * Filesystem storage for build caches rather than generated code. Keys are plain names resolved\n * inside {@link resolveCacheDir}, so a caller stores `'x.json'` without knowing where the cache\n * lives. Kept apart from the configured output storage, which may not be a local disk at all.\n *\n * @example\n * ```ts\n * const cache = cacheStorage({ root: config.root })\n * await cache.writeItem('output-manifest.json', JSON.stringify(entries))\n * ```\n */\nexport const cacheStorage = createStorage(({ root = process.cwd() }: CacheStorageOptions) => {\n const dir = resolveCacheDir(root)\n const fs = fsStorage()\n const toPath = (key: string) => join(dir, key)\n\n return {\n name: 'cache',\n readItem: (key) => fs.readItem(toPath(key)),\n writeItem: (key, value) => fs.writeItem(toPath(key), value),\n removeItem: (key) => fs.removeItem(toPath(key)),\n readKeys: (base) => fs.readKeys(base ? toPath(base) : dir),\n // Same rule as `fsStorage`: a bare `empty()` deletes nothing, so storage-generic code cannot wipe the cache directory by accident.\n empty: async (base) => (base ? fs.empty(toPath(base)) : undefined),\n }\n})\n","import { randomUUID } from 'node:crypto'\nimport process from 'node:process'\nimport { createInterface } from 'node:readline'\nimport { toError } from '@internals/utils'\nimport { type Result, x } from 'tinyexec'\nimport type { Hookable } from '../Hookable.ts'\nimport type { KubbHooks } from '../types.ts'\n\n/**\n * Outcome of one hook subprocess, also carried by the `kubb:hook:end` hook it emits.\n */\nexport type HookResult = { success: true; error: null } | { success: false; error: Error; stdout?: string; stderr?: string }\n\nexport type RunHookOptions = {\n hooks: Hookable<KubbHooks>\n /** Executable to run, resolved on `PATH` and in every `node_modules/.bin` above `cwd`. */\n command: string\n args?: ReadonlyArray<string>\n /** Label shown instead of the command line, for example a `postGenerate` step name. */\n name?: string\n /** Working directory for the command. Defaults to the current process directory. */\n cwd?: string\n signal?: AbortSignal\n}\n\nconst KILL_GRACE_MS = 2_000\n\nasync function settle(proc: Result, hooks: Hookable<KubbHooks>, id: string, commandWithArgs: string): Promise<HookResult> {\n let childError: Error | null = null\n let lineError: Error | null = null\n let lines: Promise<void> = Promise.resolve()\n let killTimer: NodeJS.Timeout | undefined\n proc.process?.once('error', (error) => {\n childError = error\n // An abort only asks the child to stop; one that swallows SIGTERM would otherwise hang the run.\n killTimer = setTimeout(() => proc.kill('SIGKILL'), KILL_GRACE_MS).unref()\n })\n // Lines are only read when a logger listens, so a quiet host does not pay to iterate them.\n if (hooks.listenerCount('kubb:hook:line') > 0) {\n for (const input of [proc.process?.stdout, proc.process?.stderr]) {\n if (!input) continue\n createInterface({ input }).on('line', (line) => {\n lines = lines\n .then(() => hooks.callHook('kubb:hook:line', { id, line }))\n .catch((error) => {\n lineError ??= toError(error)\n })\n })\n }\n }\n const output = await Promise.resolve(proc).catch(() => null)\n clearTimeout(killTimer)\n await lines\n\n const error = childError ?? lineError\n if (error) return { success: false, error }\n if (output?.exitCode === 0) return { success: true, error: null }\n return { success: false, error: new Error(`Hook execute failed: ${commandWithArgs}`), stdout: output?.stdout, stderr: output?.stderr }\n}\n\n/**\n * Spawns a command and returns its outcome, announcing it through `kubb:hook:start`,\n * `kubb:hook:line` (one per stdout or stderr line, only while a listener is attached) and\n * `kubb:hook:end`. A non-zero exit, a spawn failure, an abort or a throwing line listener returns\n * `success: false` instead of throwing. The failure travels on the result and `kubb:hook:end`\n * only, and the caller emits `kubb:success` or a diagnostic, so nothing is reported twice.\n */\nexport async function runHook({ hooks, command, args = [], name, cwd = process.cwd(), signal }: RunHookOptions): Promise<HookResult> {\n const id = randomUUID()\n await hooks.callHook('kubb:hook:start', { id, command, name, args })\n\n const proc = x(command, [...args], {\n signal,\n throwOnError: false,\n nodeOptions: { cwd, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'], detached: process.platform !== 'win32' },\n })\n const result = await settle(proc, hooks, id, [command, ...args].join(' '))\n await hooks.callHook('kubb:hook:end', { id, command, name, args, ...result })\n\n return result\n}\n","import { existsSync } from 'node:fs'\nimport { styleText } from 'node:util'\nimport { detectTool, FORMATTER_PREFERENCE, formatters, LINTER_PREFERENCE, linters, type ToolCommand, tokenize } from '@internals/utils'\nimport { Diagnostics } from '../Diagnostics.ts'\nimport type { Hookable } from '../Hookable.ts'\nimport type { Config, KubbHooks } from '../types.ts'\nimport type { Diagnostic, ProblemDiagnostic } from '../Diagnostics.ts'\nimport { runHook } from './runHook.ts'\n\nexport type RunOutputPassesOptions = {\n config: Config\n /**\n * Absolute directory the formatter and linter run over.\n */\n outputPath: string\n hooks: Hookable<KubbHooks>\n signal?: AbortSignal\n}\n\ntype ToolPass = {\n kind: 'format' | 'lint'\n label: string\n verb: string\n tools: Record<string, ToolCommand>\n preference: ReadonlyArray<string>\n code: ProblemDiagnostic['code']\n}\n\n/**\n * Format and lint are one pass over the output directory that differs only in these values.\n * `label` and `verb` are spelled out: deriving them from `kind` gives \"lintter\" and \"lintting\".\n */\nconst TOOL_PASSES: ReadonlyArray<ToolPass> = [\n { kind: 'format', label: 'formatter', verb: 'Formatting', tools: formatters, preference: FORMATTER_PREFERENCE, code: Diagnostics.code.formatFailed },\n { kind: 'lint', label: 'linter', verb: 'Linting', tools: linters, preference: LINTER_PREFERENCE, code: Diagnostics.code.lintFailed },\n]\n\ntype ToolPassRun = Pick<RunOutputPassesOptions, 'hooks' | 'outputPath' | 'signal'> & { pass: ToolPass; setting: string; cwd: string }\n\n/**\n * Resolves `auto` to an installed tool and runs it. Returns the failure instead of throwing.\n */\nasync function runToolPass({ pass, setting, outputPath, hooks, cwd, signal }: ToolPassRun): Promise<Error | null> {\n const detected = setting === 'auto' ? await detectTool(pass.preference, cwd) : setting\n if (!detected) {\n await hooks.callHook('kubb:warn', { message: `No ${pass.label} found (${pass.preference.join(', ')}). Skipping ${pass.verb.toLowerCase()}.` })\n return null\n }\n if (setting === 'auto') {\n await hooks.callHook('kubb:info', { message: `Auto-detected ${pass.label}: ${styleText('dim', detected)}` })\n }\n\n const tool = pass.tools[detected]\n // Nothing to run over when the output directory was never written: the tool would fail on an\n // empty target (oxlint with --no-ignore reports \"No files found to lint\").\n if (!tool || !existsSync(outputPath)) return null\n\n const result = await runHook({ hooks, command: tool.command, args: tool.args(outputPath), cwd, signal })\n if (result.success) {\n await hooks.callHook('kubb:success', { message: `${pass.verb} with ${styleText('dim', detected)} on ${styleText('dim', outputPath)} successfully` })\n return null\n }\n return result.error\n}\n\n/**\n * Runs `output.format`, `output.lint` and `output.postGenerate` over the generated output and\n * returns the diagnostics they produced. Each failure is emitted through `Diagnostics.emit` and\n * returned, so it reaches the summary, the reporters and the exit code; the passes keep going so\n * one failing tool does not hide the next. `Kubb.generate()` runs this after an error-free build\n * unless the host passes its own `processOutput`.\n *\n * @example\n * ```ts\n * const diagnostics = await runOutputPasses({ config, outputPath: '/repo/src/gen', hooks })\n * ```\n */\nexport async function runOutputPasses({ config, outputPath, hooks, signal }: RunOutputPassesOptions): Promise<Array<Diagnostic>> {\n const diagnostics: Array<Diagnostic> = []\n const report = async (code: ProblemDiagnostic['code'], label: string, error: Error) => {\n const diagnostic: ProblemDiagnostic = {\n code,\n severity: 'error',\n message: `${label} failed: ${error.message}`,\n help: 'Check that the tool is installed and that the command and its config are correct.',\n location: { kind: 'config' },\n cause: error,\n }\n diagnostics.push(diagnostic)\n await Diagnostics.emit(hooks, diagnostic)\n }\n\n for (const pass of TOOL_PASSES) {\n const setting = config.output[pass.kind]\n if (!setting) continue\n\n await hooks.callHook(`kubb:${pass.kind}:start`)\n const error = await runToolPass({ pass, setting, outputPath, hooks, cwd: config.root, signal })\n if (error) await report(pass.code, pass.label, error)\n await hooks.callHook(`kubb:${pass.kind}:end`)\n signal?.throwIfAborted()\n }\n\n const commands = config.output.postGenerate ?? []\n if (commands.length === 0) return diagnostics\n\n await hooks.callHook('kubb:hooks:start')\n for (const entry of commands) {\n const { command, name } = typeof entry === 'string' ? { command: entry, name: undefined } : entry\n const [executable, ...args] = tokenize(command)\n if (!executable) continue\n\n const result = await runHook({ hooks, command: executable, args, name, cwd: config.root, signal })\n if (result.success) await hooks.callHook('kubb:success', { message: `${styleText('dim', name ?? command)} successfully executed` })\n if (!result.success) await report(Diagnostics.code.postGenerateFailed, 'Post-generate command', result.error)\n signal?.throwIfAborted()\n }\n await hooks.callHook('kubb:hooks:end')\n\n return diagnostics\n}\n","import { resolve } from 'node:path'\nimport { isPathInside } from '@internals/utils'\nimport type { FileNode } from '@kubb/ast'\nimport { type Diagnostic, Diagnostics } from './Diagnostics.ts'\nimport type { Storage } from './createStorage.ts'\nimport { KubbDriver } from './KubbDriver.ts'\nimport { createOutputManifest, type OutputManifest } from './outputManifest.ts'\nimport { cacheStorage } from './storages/cacheStorage.ts'\nimport { fsStorage } from './storages/fsStorage.ts'\nimport type { BuildOutput, Config, KubbHooks, UserConfig } from './types.ts'\nimport { Hookable } from './Hookable.ts'\nimport { runOutputPasses, type RunOutputPassesOptions } from './output/runOutputPasses.ts'\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 defaultBanner: 'simple',\n ...userConfig.output,\n },\n storage: userConfig.storage ?? fsStorage(),\n reporters: userConfig.reporters ?? [],\n plugins: userConfig.plugins ?? [],\n }\n}\n\n/**\n * Only the fs storage writes `output.path`, so only then do the passes have fresh files to run\n * over; a memory or custom storage would leave them formatting whatever an earlier run left there.\n */\nfunction writesOutputDirectory(storage: Storage): boolean {\n return storage.name === 'fs'\n}\n\n/**\n * Whether anything runs over the output directory after the files are written. Only then can the\n * bytes on disk stop matching what Kubb wrote, which is what the manifest exists to track.\n */\nfunction hasOutputPasses({ output, storage }: Pick<Config, 'output' | 'storage'>): boolean {\n return writesOutputDirectory(storage) && Boolean(output.format || output.lint || output.postGenerate?.length)\n}\n\nexport type CreateKubbOptions = {\n /**\n * Receives Kubb lifecycle hooks for the run.\n */\n hooks?: Hookable<KubbHooks>\n /**\n * Stops the build at the next safe checkpoint.\n */\n signal?: AbortSignal\n}\n\n/**\n * Host hooks for a single {@link Kubb.generate} call. All optional. Progress narration rides the\n * `kubb:*` lifecycle hooks on `.hooks`, so hosts subscribe there rather than pass a callback.\n */\nexport type GenerateOptions = {\n /**\n * Replaces the output passes that run after an error-free build. The default,\n * {@link runOutputPasses}, formats, lints and runs `output.postGenerate` over the generated\n * output and returns the diagnostics they emitted.\n */\n processOutput?: (context: RunOutputPassesOptions) => Promise<Array<Diagnostic>>\n}\n\n/**\n * What a {@link Kubb.generate} call produced, for the host to map onto its own result shape.\n */\nexport type GenerateResult = {\n /**\n * `true` when the build and every output pass completed without an error-level diagnostic.\n */\n success: boolean\n /**\n * All files generated during the build.\n */\n files: Array<FileNode>\n /**\n * Build diagnostics plus any collected from the output passes.\n */\n diagnostics: Array<Diagnostic>\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 hook listeners to `.hooks` before calling `setup()` or `build()`.\n *\n * @example\n * ```ts\n * const kubb = createKubb(userConfig)\n * kubb.hooks.hook('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: Hookable<KubbHooks>\n readonly config: Config\n #driver: KubbDriver | null = null\n #manifest: OutputManifest | null = null\n readonly #signal: AbortSignal | undefined\n\n constructor(userConfig: UserConfig, options: CreateKubbOptions = {}) {\n this.config = resolveConfig(userConfig)\n this.hooks = options.hooks ?? new Hookable<KubbHooks>()\n this.#signal = options.signal\n }\n\n get storage(): Storage {\n return this.config.storage\n }\n\n get driver(): KubbDriver {\n if (!this.#driver)\n throw new Diagnostics.Error({ code: Diagnostics.code.internalError, severity: 'error', message: '[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 signal = this.#signal\n signal?.throwIfAborted()\n const config = this.config\n const manifest = hasOutputPasses(config) ? await createOutputManifest({ storage: config.storage, cache: cacheStorage({ root: config.root }) }) : undefined\n\n const cleanPath = config.output.clean ? resolve(config.root, config.output.path) : undefined\n\n // clean only removes generated code. Refuse when the output resolves to the project root or\n // an ancestor of it, otherwise the wipe would delete kubb.config and every source file.\n if (cleanPath && isPathInside(config.root, cleanPath)) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.cleanRoot,\n severity: 'error',\n message: `output.clean cannot delete \"${cleanPath}\" because it is the project root or a parent of it.`,\n help: 'Point `output.path` at a subdirectory such as `./src/gen` so clean only removes generated code.',\n location: { kind: 'config' },\n })\n }\n\n // The driver empties `cleanPath` right before it writes the new files, so a run that fails\n // earlier, on an invalid spec or a plugin that throws, leaves the previous output in place.\n const driver = new KubbDriver(config, { hooks: this.hooks, manifest, signal, cleanPath })\n await driver.setup()\n\n this.#driver = driver\n this.#manifest = manifest ?? null\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 AggregateError(errors, `Build failed with ${errors.length} ${errors.length === 1 ? 'error' : '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 this.#signal?.throwIfAborted()\n if (!this.#driver) await this.setup()\n using self = this\n const driver = self.driver\n const storage = self.storage\n const { diagnostics } = await driver.run()\n\n return { diagnostics, files: driver.fileManager.files, driver, storage }\n }\n\n /**\n * Run one build and its output passes end to end, emitting the surrounding `kubb:generation:*`\n * hooks. Never throws on a build error: the outcome comes back in {@link GenerateResult} so the\n * host decides how failures surface. Telemetry and progress narration stay with the host, which\n * reads the result and subscribes to the `kubb:*` hooks.\n *\n * @example\n * ```ts\n * const result = await createKubb(config, { hooks }).generate()\n * if (!result.success) process.exitCode = 1\n * ```\n */\n async generate(options: GenerateOptions = {}): Promise<GenerateResult> {\n const signal = this.#signal\n signal?.throwIfAborted()\n const { hooks, config } = this\n const hrStart = process.hrtime()\n\n await hooks.callHook('kubb:generation:start', { config })\n\n // A setup failure, such as an invalid plugin entry, becomes a diagnostic like any build\n // problem, so reporters still get a failed `kubb:generation:end` for this config.\n let output: Pick<BuildOutput, 'files' | 'diagnostics'>\n try {\n await hooks.callHook('kubb:setup:start')\n await this.setup()\n await hooks.callHook('kubb:setup:end')\n\n output = await this.safeBuild()\n } catch (caughtError) {\n if (signal?.aborted) throw caughtError\n output = { files: [], diagnostics: [Diagnostics.from(caughtError)] }\n }\n const { files, diagnostics } = output\n const storage = this.storage\n signal?.throwIfAborted()\n\n // Surface every problem on the hooks. `performance` diagnostics feed the summary, not the\n // log, so they are skipped.\n for (const diagnostic of diagnostics) {\n if (Diagnostics.isProblem(diagnostic)) await Diagnostics.emit(hooks, diagnostic)\n }\n\n if (Diagnostics.hasError(diagnostics)) {\n await hooks.callHook('kubb:generation:end', { config, storage, diagnostics, filesCreated: files.length, status: 'failed', hrStart })\n return { success: false, files, diagnostics }\n }\n\n const processOutput = options.processOutput ?? runOutputPasses\n const outputDiagnostics = writesOutputDirectory(config.storage)\n ? await processOutput({ config, outputPath: resolve(config.root, config.output.path), hooks, signal })\n : []\n\n const finalDiagnostics = [...diagnostics, ...outputDiagnostics]\n const failed = Diagnostics.hasError(outputDiagnostics)\n\n // The formatter and linter have had their turn, so what sits on disk now is what the next run\n // has to recognize as unchanged. Only record it when they finished: a pass that failed halfway\n // leaves files Kubb has to stay free to regenerate.\n if (!failed) await this.#manifest?.commit()\n\n await hooks.callHook('kubb:generation:end', {\n config,\n storage,\n diagnostics: finalDiagnostics,\n filesCreated: files.length,\n status: failed ? 'failed' : 'success',\n hrStart,\n })\n\n return { success: !failed, files, diagnostics: finalDiagnostics }\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: './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 { LiteralUnion } from '@internals/utils'\nimport 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 * - `html` writes a browsable report directory to `.kubb/kubb-<name>-<timestamp>/`.\n */\nexport type ReporterName = 'cli' | 'json' | 'file' | 'html'\n\n/**\n * Files attributed to the plugin that first added them.\n */\nexport type ReporterPluginFiles = Array<{\n /** Plugin name. */\n plugin: string\n /** Generated file paths. */\n files: Array<string>\n}>\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 * Files attributed to the plugin that first added them, when requested by a reporter.\n */\n pluginFiles?: ReporterPluginFiles\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 hook 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: LiteralUnion<ReporterName>\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 * Whether the host should collect files from `kubb:plugin:end` hooks.\n */\n needsPluginFiles?: boolean\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: LiteralUnion<ReporterName>\n /**\n * Whether the host should collect files from `kubb:plugin:end` hooks.\n */\n needsPluginFiles?: boolean\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. The returned reporter buffers each value `report` returns in order and, when\n * the definition has a `drain`, hands the array to `drain` once and then clears it. Wiring the\n * reporter onto the run's hooks is the host's job, so the reporter only ever deals with a\n * {@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 reports: Array<T> = []\n\n return {\n name: reporter.name,\n needsPluginFiles: reporter.needsPluginFiles,\n async report(result, context) {\n const report = await reporter.report(result, context)\n if (reporter.drain) {\n reports.push(report)\n }\n },\n async drain(context) {\n await reporter.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 } from '../Diagnostics.ts'\nimport type { SerializedDiagnostic } from '../formatDiagnostic.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 // A failed run without timings stopped before any plugin ran, such as on an invalid plugin entry.\n plugins: { passed: status === 'failed' && timings.length === 0 ? 0 : 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 } from '@internals/utils'\nimport type { Report } from './report.ts'\n\n/**\n * Writes a finished summary. The `cli` reporter formats the lines and hands them to one of these,\n * so the caller decides where they land: plain `console.log` by default, or the active logger's own\n * output when a host installs one.\n */\nexport type SummaryRenderer = (lines: ReadonlyArray<string>, meta: { title: string; status: 'success' | 'failed' }) => void\n\n/**\n * Formats 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`. Pure, so a host\n * can render the same lines through whatever output it already owns.\n */\nexport function formatSummary(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 const notRun = plugins.total - plugins.passed - plugins.failed.length\n rows.push([\n 'Plugins',\n status === 'success'\n ? `${styleText('green', `${plugins.passed} passed`)} (${plugins.total})`\n : [\n styleText('green', `${plugins.passed} passed`),\n styleText('red', `${plugins.failed.length} failed`),\n notRun > 0 ? styleText('dim', `${notRun} not run`) : undefined,\n ]\n .filter(Boolean)\n .join(' | ') + ` (${plugins.total})`,\n ])\n\n if (status === 'failed' && plugins.failed.length > 0) {\n rows.push(['Failed', plugins.failed.map((name) => styleText('red', 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 / 100), 10)\n // One block per 100 ms, capped at ten.\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","import { styleText } from 'node:util'\nimport { createReporter, logLevel as logLevelMap, type Reporter } from '../createReporter.ts'\nimport { buildReport } from './report.ts'\nimport { formatSummary, type SummaryRenderer } from './summary.ts'\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 */\nconst consoleRenderer: SummaryRenderer = (lines, { title, status }) => {\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 * Builds a `cli` reporter that renders the {@link Report} for each config as it finishes.\n * Suppressed at `silent`. The `verbose` level adds the per-plugin timings.\n *\n * Pass `render` to send the summary through output the host already owns, so it lands inside that\n * host's grouping instead of alongside it. Omit it for the plain `console.log` writer.\n *\n * @example\n * ```ts\n * const reporter = createCliReporter({ render: (lines) => lines.forEach((line) => clack.log.message(line)) })\n * ```\n */\nexport function createCliReporter({ render = consoleRenderer }: { render?: SummaryRenderer } = {}): Reporter {\n return createReporter({\n name: 'cli',\n report(result, { logLevel }) {\n if (logLevel <= logLevelMap.silent) {\n return\n }\n\n const report = buildReport(result)\n\n render(formatSummary(report, { showTimings: logLevel >= logLevelMap.verbose }), { title: report.name, status: report.status })\n },\n })\n}\n\n/**\n * The default `cli` reporter, writing its summary straight to the console. Independent of the live\n * logger view.\n */\nexport const cliReporter = createCliReporter()\n","import { hash } from 'node:crypto'\nimport { chmodSync, mkdirSync } from 'node:fs'\nimport { homedir, tmpdir } from 'node:os'\nimport { join, resolve } from 'node:path'\nimport process from 'node:process'\nimport { createStorage as createUnstorage } from 'unstorage'\nimport fsDriver from 'unstorage/drivers/fs'\n\ntype KubbStorageOptions = {\n /**\n * Folder inside the Kubb home, or an absolute path such as `<cwd>/.kubb`.\n */\n base?: string\n}\n\nfunction ensurePrivateDir(dir: string): string {\n mkdirSync(dir, { recursive: true, mode: 0o700 })\n chmodSync(dir, 0o700)\n return dir\n}\n\n/**\n * Folder Kubb keeps its own files in, created with mode 0700. `base` resolves inside `KUBB_HOME`\n * (default `~/.kubb`). When that folder is not writable, it falls back to a folder in the OS temp directory.\n *\n * @example\n * `resolveKubbDir('cache') // '/home/me/.kubb/cache'`\n */\nexport function resolveKubbDir(base = ''): string {\n const dir = resolve(process.env.KUBB_HOME ?? join(homedir(), '.kubb'), base)\n try {\n return ensurePrivateDir(dir)\n } catch {\n return ensurePrivateDir(join(tmpdir(), 'kubb', hash('sha256', dir).slice(0, 16)))\n }\n}\n\n/**\n * unstorage on the fs driver, rooted at {@link resolveKubbDir}. The fs driver cannot set a file\n * mode, so the 0700 folder keeps files such as a stored token private.\n *\n * @example\n * ```ts\n * const storage = kubbStorage({ base: 'cache' })\n * await storage.setItem('machine-secret', secret)\n * ```\n */\nexport function kubbStorage({ base }: KubbStorageOptions = {}) {\n return createUnstorage({ driver: fsDriver({ base: resolveKubbDir(base) }) })\n}\n","import { join, relative, resolve } from 'node:path'\nimport process from 'node:process'\nimport { stripVTControlCharacters } from 'node:util'\nimport { createReporter } from '../createReporter.ts'\nimport { type Diagnostic, Diagnostics } from '../Diagnostics.ts'\nimport { kubbStorage, resolveKubbDir } from '../storages/kubbStorage.ts'\nimport { buildReport } from './report.ts'\nimport { formatSummary } from './summary.ts'\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 // The full stack, since a log file is what a bug report attaches.\n const blocks = problems.map((diagnostic) => Diagnostics.format(diagnostic, { verbose: true }).join('\\n'))\n return ['## Problems', '', blocks.join('\\n\\n')]\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 lines the\n * cli reporter prints (timings included), and a `## Problems` section in the miette block format.\n * 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` hook 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 summary = ['## Summary', '', ...formatSummary(report, { showTimings: true })]\n const sections = [summary, buildProblemSection(diagnostics)].filter((section) => section.length > 0)\n const content = stripVTControlCharacters([header, ...sections.map((section) => section.join('\\n'))].join('\\n\\n'))\n\n const name = config.name?.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, '')\n const baseName = `${['kubb', name, Date.now()].filter(Boolean).join('-')}.log`\n const dir = resolveKubbDir(resolve(process.cwd(), '.kubb'))\n\n await kubbStorage({ base: dir }).setItem(baseName, `${content}\\n`)\n console.error(`Debug log written to ${relative(process.cwd(), join(dir, baseName))}`)\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 { join, relative, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { openInBrowser, read } from '@internals/utils'\nimport { createReporter, type GenerationResult } from '../createReporter.ts'\nimport { kubbStorage, resolveKubbDir } from '../storages/kubbStorage.ts'\nimport { buildReport } from './report.ts'\n\nfunction serializeReport(result: GenerationResult): string {\n const data = JSON.stringify({ generatedAt: new Date().toISOString(), report: buildReport(result), pluginFiles: result.pluginFiles ?? [] })\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026')\n return `globalThis.__KUBB_REPORT__ = ${data}\\n`\n}\n\n/**\n * Writes a static HTML report directory selected with `--reporter html`.\n */\nexport const htmlReporter = createReporter({\n name: 'html',\n needsPluginFiles: true,\n async report(result) {\n const name = result.config.name?.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, '')\n const baseName = ['kubb', name, Date.now()].filter(Boolean).join('-')\n const dir = resolveKubbDir(resolve(process.cwd(), '.kubb'))\n const storage = kubbStorage({ base: dir })\n const assets = new URL('./html/', import.meta.url)\n const [html, ui] = await Promise.all([read(fileURLToPath(new URL('index.html', assets))), read(fileURLToPath(new URL('ui.iife.js', assets)))])\n\n await Promise.all([\n storage.setItem(`${baseName}/index.html`, html),\n storage.setItem(`${baseName}/ui.iife.js`, ui),\n storage.setItem(`${baseName}/data.js`, serializeReport(result)),\n ])\n const reportPath = join(dir, baseName, 'index.html')\n console.error(`HTML report written to ${relative(process.cwd(), reportPath)}`)\n openInBrowser(reportPath)\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 */\n readonly files: Array<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 { PossiblePromise } from '@internals/utils'\nimport type { FileNode, InputMeta, OperationNode, SchemaNode } from '@kubb/ast'\nimport type { Adapter } from './createAdapter.ts'\nimport type { ProblemDiagnostic } from './Diagnostics.ts'\nimport type { RendererFactory } from './createRenderer.ts'\nimport type { KubbHooks } from './types.ts'\nimport type { KubbDriver } from './KubbDriver.ts'\nimport type { ExtensionMeta } from './defineExtension.ts'\nimport type { Plugin, PluginType, PluginName, ResolvePluginOptions } from './definePlugin.ts'\nimport type { NodeCache } from './nodeCache.ts'\nimport type { Config } from './types.ts'\nimport type { Hookable } from './Hookable.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 PluginType = PluginType> = {\n /**\n * Stops cooperative generation work at the next safe checkpoint.\n */\n signal?: AbortSignal\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 PluginName>(name: TName): Plugin<ResolvePluginOptions<TName>> | undefined\n /**\n * Get a plugin by name, throws an error if not found.\n */\n requirePlugin<TName extends PluginName>(name: TName): Plugin<ResolvePluginOptions<TName>>\n /**\n * Get a resolver by plugin name, typed via `Kubb.PluginRegistry` when registered.\n */\n getResolver<TName extends PluginName>(name: TName): ResolvePluginOptions<TName>['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 hook bus. Emit or listen to any `KubbHooks` hook, for example to react to\n * `kubb:build:end` from inside a generator.\n */\n hooks: Hookable<KubbHooks>\n /**\n * The current plugin instance.\n */\n plugin: Plugin<TOptions> & { name: string; meta: ExtensionMeta }\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 name\n * `ctx.resolver.name('pet') // 'pet'`\n *\n * @example Resolve an output file\n * `ctx.resolver.file({ 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. Pass `options` to set\n * the `code`, the `help` text, or the source `location`.\n *\n * @example\n * `ctx.warn('Enum has no values', { help: 'Add values to the enum.', location: { kind: 'schema', pointer: '#/components/schemas/Status' } })`\n */\n warn: (message: string, options?: Partial<Pick<ProblemDiagnostic, 'code' | 'help' | 'location'>>) => void\n /**\n * Report an error. Collected as an `error` diagnostic attributed to the current\n * plugin, which fails the build. A `Diagnostics.Error` keeps its own code, help, and location.\n * Pass `options` to set them for a plain message or error.\n */\n error: (error: string | Error, options?: Partial<Pick<ProblemDiagnostic, 'code' | 'help' | 'location'>>) => void\n /**\n * Report an informational message. Collected as an `info` diagnostic attributed to\n * the current plugin. Pass `options` to set the `code`, the `help` text, or the source `location`.\n */\n info: (message: string, options?: Partial<Pick<ProblemDiagnostic, 'code' | 'help' | 'location'>>) => 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 * Cache scoped to the node being generated, shared by every plugin that generates from that\n * same node in the current pass. Use it to compute node-derived work (resolved names, imports,\n * parameters) once and let the other plugins reuse it. For the `operations` batch call, where\n * there is no single node, the cache is a fresh scratch scope for that call.\n */\n cache: NodeCache\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 PluginType = PluginType, 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 * Predicate checked before `schema` or `operation` runs for a node, mirroring `Macro['match']`\n * in `@kubb/ast`. Returning `false` skips the call for that node entirely, with no context work\n * beyond what the driver already builds per node and no render call, instead of the generator\n * itself being invoked and returning early. Omit it to run for every node, the default when\n * unset.\n *\n * Does not gate `operations`, which already runs once per plugin on the full batch rather than\n * per node.\n *\n * @example Only match GET operations\n * ```ts\n * match(node, ctx) {\n * return ast.isHttpOperationNode(node) && node.method.toLowerCase() === 'get'\n * }\n * ```\n */\n match?: (node: SchemaNode | OperationNode, ctx: GeneratorContext<TOptions>) => PossiblePromise<boolean>\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 `PluginType`. 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 PluginType = PluginType, TElement = unknown>(\n generator: Generator<TOptions, TElement>,\n): Generator<TOptions, TElement> {\n return generator\n}\n","import type { FileNode, UserFileNode } from '@kubb/ast'\nimport { defineExtension } from './defineExtension.ts'\nimport type { ExtensionFactory, ExtensionMeta, ExtensionNamed } from './defineExtension.ts'\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, TOptions extends object = object> = ExtensionNamed & {\n /**\n * The options passed to the parser factory.\n */\n options?: TOptions\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>): string\n /**\n * Turn the content of a `copy` file into a file node that `parse` prints. Omit to copy the file verbatim.\n */\n copy?(file: FileNode<TMeta>, source: string): UserFileNode<TMeta>\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 * Takes the user's options and returns the parser methods.\n */\nexport type ParserBuild<TOptions extends object, TMeta extends object, TNode> = (options: TOptions) => Omit<Parser<TMeta, TNode>, 'name' | 'meta' | 'options'>\n\n/**\n * The object passed to `defineExtension` with `kind: 'parser'`. `build` receives the user's options and returns the parser methods.\n */\nexport type ParserDefinition<TOptions extends object = object, TMeta extends object = object, TNode = unknown> = {\n meta: ExtensionMeta\n build: ParserBuild<TOptions, TMeta, TNode>\n}\n\n/**\n * The function `defineExtension` returns for a parser. Call it with user options to get a `Parser`.\n */\nexport type ParserFactory<TOptions extends object = object, TMeta extends object = object, TNode = unknown> = ExtensionFactory<\n 'parser',\n TOptions,\n Parser<TMeta, TNode, TOptions>\n>\n\n/**\n * Defines a parser from one object and returns a factory that takes the user's options.\n * Register the result in the `parsers` array on `defineConfig`.\n *\n * @deprecated Use `defineExtension` with `kind: 'parser'` instead.\n */\nexport function defineParser<TOptions extends object = object, TMeta extends object = object, TNode = unknown>(\n definition: ParserDefinition<TOptions, TMeta, TNode>,\n): ParserFactory<TOptions, TMeta, TNode> {\n return defineExtension({ kind: 'parser', ...definition })\n}\n","import { createStorage } from '../createStorage.ts'\n\n/**\n * In-memory storage driver. Useful for testing and dry-run scenarios where\n * generated output should be captured without touching the filesystem.\n *\n * All data lives in a `Map` scoped to the storage instance and is discarded\n * when the instance is garbage-collected.\n *\n * @example\n * ```ts\n * import { memoryStorage } from '@kubb/core'\n * import { defineConfig } from 'kubb'\n *\n * export default defineConfig({\n * input: './petStore.yaml',\n * output: { path: './src/gen' },\n * storage: memoryStorage(),\n * })\n * ```\n */\nexport const memoryStorage = createStorage(() => {\n const store = new Map<string, string>()\n\n return {\n name: 'memory',\n async readItem(key: string) {\n return store.get(key) ?? null\n },\n async writeItem(key: string, value: string) {\n store.set(key, value)\n },\n async removeItem(key: string) {\n store.delete(key)\n },\n async readKeys(base?: string) {\n const keys = [...store.keys()]\n return base ? keys.filter((k) => k.startsWith(base)) : keys\n },\n async empty(base?: string) {\n if (!base) {\n store.clear()\n return\n }\n for (const key of store.keys()) {\n if (key.startsWith(base)) {\n store.delete(key)\n }\n }\n },\n }\n})\n","import { isValid } from 'verkit'\nimport type { ExtensionKind } from './defineExtension.ts'\n\n/** A value that survives `JSON.stringify` and `JSON.parse` unchanged. */\nexport type JSONValue = string | number | boolean | null | Array<JSONValue> | { [key: string]: JSONValue }\n\n/**\n * One form field Studio renders for an extension. It edits the value at `path` in the options\n * object the user passes to the factory.\n */\nexport type ExtensionManifestOption = {\n /** Stable UI key, unique within the manifest. */\n key: string\n /** Where the value lives, such as `['output', 'path']`. */\n path: Array<string>\n label: string\n description?: string\n type: 'select' | 'boolean' | 'text' | 'number' | 'list'\n /** The extension's runtime default, shown when the option is unset. */\n default?: JSONValue\n /** For `select`. A choice with value `null` leaves the option unset. */\n choices?: Array<{ label?: string; value: JSONValue }>\n /** For `boolean`: the value written for `true`, `true` when unset. */\n trueValue?: JSONValue\n /** For `boolean`: the value written for `false`, `false` when unset. */\n falseValue?: JSONValue\n /** For `list`: template for each entry, where every `\"$item\"` string is replaced by the entry. */\n item?: JSONValue\n /** For `list`: upper-case each entry before writing it. */\n itemCase?: 'upper'\n}\n\n/**\n * The `kubb-extension.json` file an extension package ships at its root. Studio, the kubb.dev\n * registry, and `kubb add` read it.\n */\nexport type ExtensionManifest = {\n $schema?: string\n kind: ExtensionKind\n /** Equals the extension's `meta.name`. */\n name: string\n /** The factory export users call in `kubb.config.ts`, such as `pluginZod`. */\n export: string\n displayName: string\n description: string\n category?: string\n icon?: { light: string; dark?: string }\n /** HTTPS image or video URLs. */\n media?: Array<string>\n tags?: Array<string>\n docs?: string\n /** People who maintain the extension, shown on its kubb.dev page. */\n maintainers?: Array<{ name: string; github?: string }>\n /** Names of the extensions that must be in the same config, such as `['plugin-ts']`. */\n dependencies?: Array<string>\n /** Names of the extensions used when they are in the config, or needed only for some option values, such as `['plugin-faker']`. */\n optionalDependencies?: Array<string>\n compatibility?: { kubb?: string; node?: string }\n /** Plugins only: `client` ships the HTTP client runtime, `consumer` calls one but ships none. */\n role?: 'client' | 'consumer'\n options?: Array<ExtensionManifestOption>\n}\n\n/** What `kubb add` installs: a reviewed npm version, or a GitHub release tag and the commit it points to. */\nexport type RegistryArtifact =\n | { kind: 'npm'; package: string; version: string }\n | {\n kind: 'github'\n /** The `name` in the root `package.json`, so the package installs under this name. */\n package: string\n /** The release version, equal to `tag` without a leading `v`. */\n version: string\n owner: string\n repo: string\n tag: string\n /** The full commit SHA the tag points to. */\n commit: string\n }\n\n/** One extension in a registry's `index.json`. */\nexport type RegistryEntry = {\n /** `<owner>/<slug>`, such as `kubb-labs/plugin-zod`. */\n id: string\n kind: ExtensionKind\n type: 'official' | 'community'\n artifact: RegistryArtifact\n repository?: { url: string }\n manifest: ExtensionManifest\n stats?: { downloads?: number; weekly?: number; stars?: number }\n submittedAt: string\n publishedAt: string\n reviewedAt: string\n}\n\n/** The registry's `index.json`. */\nexport type RegistryIndex = { version: 1; generatedAt: string; extensions: Array<RegistryEntry> }\n\n/** One `docs/guides/<id>.md`: `id` is the file name, `title` its `#` heading, `description` the first paragraph. */\nexport type RegistryGuide = {\n id: string\n title: string\n description: string\n content: string\n}\n\n/** The registry's `<owner>/<slug>.json`: an entry plus the Markdown docs its pinned version ships. */\nexport type RegistryDetail = RegistryEntry & { overview: string | null; options?: string | null; guides?: Array<RegistryGuide> }\n\nconst EXTENSION_KINDS = new Set<unknown>(['plugin', 'adapter', 'parser'] satisfies Array<ExtensionKind>)\nconst OPTION_TYPES = new Set<unknown>(['select', 'boolean', 'text', 'number', 'list'] satisfies Array<ExtensionManifestOption['type']>)\nconst PACKAGE_NAME = /^(?:@[a-z0-9~][a-z0-9._~-]*\\/)?[a-z0-9~][a-z0-9._~-]*$/\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/\nconst REGISTRY_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*\\/[a-z0-9]+(?:-[a-z0-9]+)*$/\nconst GITHUB_OWNER = /^[A-Za-z0-9](?:[A-Za-z0-9]|-(?=[A-Za-z0-9])){0,38}$/\nconst GITHUB_REPO = /^(?!\\.\\.?$)[A-Za-z0-9._-]{1,100}$/\nconst COMMIT = /^[0-9a-f]{40}$/\n/** Option path segments that would reach an object's prototype when Studio writes the value by path. */\nconst UNSAFE_KEYS = new Set<unknown>(['__proto__', 'constructor', 'prototype'])\n\nconst isObject = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null && !Array.isArray(value)\nconst isOptionalString = (value: unknown) => value === undefined || typeof value === 'string'\nconst isFilledString = (value: unknown) => typeof value === 'string' && value !== ''\nconst matches = (pattern: RegExp, value: unknown) => typeof value === 'string' && pattern.test(value)\n/** Serializes with sorted object keys, so equal JSON values give equal strings whatever their key order. */\nconst canonicalJSON = (value: unknown) =>\n JSON.stringify(value, (_key, item: unknown) =>\n isObject(item)\n ? Object.fromEntries(\n Object.keys(item)\n .sort()\n .map((key) => [key, item[key]]),\n )\n : item,\n )\n\n/**\n * Whether `name` is a valid npm package name, such as `@kubb/plugin-ts`. Rejects paths, URLs,\n * `node:` specifiers, and names that start with `-`, so the result is safe to pass to `import()` or\n * a package manager.\n */\nexport function isPackageName(name: unknown): name is string {\n return typeof name === 'string' && name.length <= 214 && PACKAGE_NAME.test(name)\n}\n\nfunction isMaintainer(value: unknown): boolean {\n return (\n isObject(value) &&\n Object.keys(value).every((key) => key === 'name' || key === 'github') &&\n isFilledString(value.name) &&\n (value.github === undefined || isFilledString(value.github))\n )\n}\n\n/** Checks the shape of one manifest option, including that its path cannot reach a prototype. */\nfunction isOption(value: unknown): value is ExtensionManifestOption {\n if (!isObject(value)) return false\n const { key, path, label, description, type, choices, itemCase } = value\n return (\n isFilledString(key) &&\n Array.isArray(path) &&\n path.length > 0 &&\n path.every((segment) => isFilledString(segment) && !UNSAFE_KEYS.has(segment)) &&\n isFilledString(label) &&\n isOptionalString(description) &&\n OPTION_TYPES.has(type) &&\n (choices === undefined || (Array.isArray(choices) && choices.every((choice) => isObject(choice) && 'value' in choice && isOptionalString(choice.label)))) &&\n (itemCase === undefined || itemCase === 'upper')\n )\n}\n\n/**\n * What is wrong with the options of a well-formed manifest, beyond their shape: keys are unique, a\n * select has choices, and a select's default is one of its choice values. Empty when they pass.\n */\nexport function manifestProblems({ options = [] }: ExtensionManifest): Array<string> {\n const seen = new Set<string>()\n return options.flatMap((option) => {\n const problems = seen.has(option.key) ? [`option \"${option.key}\" is declared more than once`] : []\n seen.add(option.key)\n if (option.type !== 'select') return problems\n if (!option.choices?.length) return [...problems, `option \"${option.key}\" is a select without choices`]\n const knownDefault = !('default' in option) || option.choices.some((choice) => canonicalJSON(choice.value) === canonicalJSON(option.default))\n return knownDefault ? problems : [...problems, `option \"${option.key}\" has a default that is not one of its choices`]\n })\n}\n\n/**\n * Checks a parsed `kubb-extension.json` or a registry response before Kubb or Studio uses it: the\n * fields Kubb reads, every option's shape (including option paths that cannot reach a prototype),\n * and `manifestProblems`. A malformed manifest is skipped instead of trusted.\n */\nexport function isExtensionManifest(value: unknown): value is ExtensionManifest {\n if (!isObject(value)) return false\n const { kind, name, export: exportName, displayName, description, maintainers, dependencies, optionalDependencies, compatibility, role, options } = value\n return (\n EXTENSION_KINDS.has(kind) &&\n isPackageName(name) &&\n typeof exportName === 'string' &&\n IDENTIFIER.test(exportName) &&\n typeof displayName === 'string' &&\n typeof description === 'string' &&\n (maintainers === undefined || (Array.isArray(maintainers) && maintainers.every(isMaintainer))) &&\n (dependencies === undefined || (Array.isArray(dependencies) && dependencies.every(isPackageName))) &&\n (optionalDependencies === undefined || (Array.isArray(optionalDependencies) && optionalDependencies.every(isPackageName))) &&\n (compatibility === undefined ||\n (isObject(compatibility) && Object.entries(compatibility).every(([key, range]) => (key === 'kubb' || key === 'node') && typeof range === 'string'))) &&\n (role === undefined || role === 'client' || role === 'consumer') &&\n (options === undefined || (Array.isArray(options) && options.every(isOption))) &&\n manifestProblems(value as ExtensionManifest).length === 0\n )\n}\n\n/** Checks that no artifact field can reach a package manager as a flag or path, and that a GitHub tag names the version. */\nfunction isRegistryArtifact(value: unknown): value is RegistryArtifact {\n if (!isObject(value) || !isPackageName(value.package) || typeof value.version !== 'string' || !isValid(value.version)) return false\n if (value.kind === 'npm') return true\n return (\n value.kind === 'github' &&\n matches(GITHUB_OWNER, value.owner) &&\n matches(GITHUB_REPO, value.repo) &&\n (value.tag === value.version || value.tag === `v${value.version}`) &&\n matches(COMMIT, value.commit)\n )\n}\n\n/**\n * Checks one entry of a registry's `index.json` or `<owner>/<slug>.json`: a full `<owner>/<slug>` id,\n * an npm or GitHub artifact pinned to a valid version, and a valid manifest of the entry's kind.\n */\nexport function isRegistryEntry(value: unknown): value is RegistryEntry {\n if (!isObject(value)) return false\n const { id, kind, type, artifact, manifest } = value\n return (\n typeof id === 'string' &&\n REGISTRY_ID.test(id) &&\n EXTENSION_KINDS.has(kind) &&\n (type === 'official' || type === 'community') &&\n isRegistryArtifact(artifact) &&\n isExtensionManifest(manifest) &&\n manifest.kind === kind\n )\n}\n","import { existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport path from 'node:path'\nimport { type ExtensionManifest, isExtensionManifest, isPackageName } from './manifest.ts'\n\nexport type InstalledPackage = { package: string; version?: string; manifest?: ExtensionManifest }\n\n/** Reads and parses a JSON file. Throws when it is missing or not JSON. */\nconst readJSON = async (file: string): Promise<unknown> => JSON.parse(await readFile(file, 'utf8'))\n\n/**\n * The `dependencies` and `devDependencies` of the project at `root`, plus `packages`, with the\n * installed version and the valid `kubb-extension.json` each one ships, when it does. A package\n * also counts as installed when it resolves from one of the `resolveFrom` packages, such as `kubb`\n * for the extensions it ships with.\n */\nexport async function readInstalledPackages({\n root,\n packages = [],\n resolveFrom = [],\n}: {\n root: string\n packages?: Iterable<string>\n resolveFrom?: Array<string>\n}): Promise<Array<InstalledPackage>> {\n const project = createRequire(path.resolve(root, 'package.json'))\n const requires = [\n project,\n ...resolveFrom.flatMap((name) => {\n try {\n return [createRequire(project.resolve(`${name}/package.json`))]\n } catch {\n return []\n }\n }),\n ]\n const packageJSON = (await readJSON(path.join(root, 'package.json')).catch(() => null)) as { dependencies?: unknown; devDependencies?: unknown } | null\n const dependencies = [packageJSON?.dependencies, packageJSON?.devDependencies].flatMap((record) =>\n typeof record === 'object' && record !== null ? Object.keys(record) : [],\n )\n\n return Promise.all(\n [...new Set([...dependencies, ...packages])].filter(isPackageName).map(async (name): Promise<InstalledPackage> => {\n // Found on disk rather than resolved, because an `exports` map may hide `package.json` and the manifest.\n const dir = requires\n .flatMap((require) => require.resolve.paths(name) ?? [])\n .map((dir) => path.join(dir, name))\n .find((dir) => existsSync(path.join(dir, 'package.json')))\n if (!dir) return { package: name }\n try {\n const { version } = (await readJSON(path.join(dir, 'package.json'))) as { version?: unknown }\n const manifest = await readJSON(path.join(dir, 'kubb-extension.json')).catch(() => undefined)\n return { package: name, version: typeof version === 'string' ? version : undefined, manifest: isExtensionManifest(manifest) ? manifest : undefined }\n } catch {\n return { package: name }\n }\n }),\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAMA,SAAgB,kBAA2B;CACzC,MAAM,KAAKA,UAAQ,IAAI;CACvB,OAAO,CAAC,EACL,MAAM,OAAO,WAAW,OAAO,OAChCA,UAAQ,IAAI,kBACZA,UAAQ,IAAI,aACZA,UAAQ,IAAI,0BACZA,UAAQ,IAAI,eACZA,UAAQ,IAAI,YACZA,UAAQ,IAAI,UACZA,UAAQ,IAAI,oBACZA,UAAQ,IAAI,aACZA,UAAQ,IAAI;AAEhB;;;AChBA,MAAM,eAAe,CAAC;;;;AAKtB,SAAgB,cAAc,QAAsB;CAClD,IAAI,gBAAgB,GAAG;CAEvB,IAAIC,UAAQ,aAAa,SAAS;EAChC,EAAE,OAAO;GAAC;GAAM;GAAS;GAAI;EAAM,CAAC,CAAC,CAAC,KAAK,QAAQ,MAAM;EACzD;CACF;CACA,EAAEA,UAAQ,aAAa,WAAW,SAAS,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ,MAAM;AACtF;;;;;;ACFA,MAAa,aAAa;CACxB,UAAU;EACR,SAAS;EACT,OAAO,eAAuB;GAAC;GAAoB;GAAW;EAAU;EACxE,cAAc;CAChB;CACA,OAAO;EACL,SAAS;EACT,OAAO,eAAuB;GAAC;GAAU;GAAW;EAAU;EAC9D,cAAc;CAChB;CACA,OAAO;EACL,SAAS;EACT,OAAO,eAAuB,CAAC,UAAU;EACzC,cAAc;CAChB;AACF;;;;AAKA,MAAa,UAAU;CACrB,QAAQ;EACN,SAAS;EACT,OAAO,eAAuB,CAAC,YAAY,OAAO;EAClD,cAAc;CAChB;CACA,OAAO;EACL,SAAS;EACT,OAAO,eAAuB;GAAC;GAAQ;GAAS;EAAU;EAC1D,cAAc;CAChB;CACA,QAAQ;EACN,SAAS;EAET,OAAO,eAAuB;GAAC;GAAS;GAAe;EAAU;EACjE,cAAc;CAChB;AACF;;;;;AAMA,MAAa,uBAAuB;CAAC;CAAS;CAAS;AAAU;;;;AAKjE,MAAa,oBAAoB;CAAC;CAAU;CAAS;AAAQ;;;;AAK7D,eAAe,gBAAgB,MAAc,KAAgC;CAC3E,OAAO,EAAE,MAAM,CAAC,WAAW,GAAG;EAAE,cAAc;EAAO,aAAa;GAAE;GAAK,OAAO;EAAS;CAAE,CAAC,CAAC,CAAC,MAC3F,EAAE,eAAe,aAAa,SACzB,KACR;AACF;;;;;;;AAQA,eAAsB,WAAiC,YAAkC,KAAqC;CAC5H,KAAK,MAAM,aAAa,YACtB,IAAI,MAAM,gBAAgB,WAAW,GAAG,GACtC,OAAO;CAIX,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,SAAS,SAAgC;CACvD,QAAQ,QAAQ,MAAM,+BAA+B,KAAK,CAAC,EAAA,CAAG,KAAK,UAAU,MAAM,QAAQ,gBAAgB,EAAE,CAAC;AAChH;;;;;;;;;;;;;ACYA,SAAgB,cAAuE,YAAqD;CAC1I,OAAO,gBAAgB;EAAE,MAAM;EAAW,GAAG;CAAW,CAAC;AAC3D;;;;;;AC7GA,MAAM,UAAU;AA8ChB,MAAM,eAAe;AAErB,eAAe,YAAY,EAAE,SAA2E;CACtG,IAAI;EACF,MAAM,SAAS,MAAM,MAAM,SAAS,YAAY;EAChD,IAAI,WAAW,MAAM,OAAO,CAAC;EAE7B,MAAM,OAAO,KAAK,MAAM,MAAM;EAC9B,IAAI,KAAK,YAAY,SAAS,OAAO,CAAC;EACtC,IAAI,OAAO,KAAK,YAAY,YAAY,KAAK,YAAY,QAAQ,MAAM,QAAQ,KAAK,OAAO,GAAG,OAAO,CAAC;EAEtG,OAAO,KAAK;CACd,QAAQ;EACN,OAAO,CAAC;CACV;AACF;;;;;;;;;;AAWA,eAAsB,qBAAqB,EAAE,SAAS,SAAwE;CAC5H,MAAM,UAAU,MAAM,YAAY,EAAE,MAAM,CAAC;CAC3C,MAAM,0BAAU,IAAI,IAAoB;CAExC,OAAO;EACL,WAAW,EAAE,KAAK,QAAQ,QAAQ;GAChC,MAAM,QAAQ,QAAQ;GACtB,IAAI,CAAC,OAAO,OAAO;GAEnB,OAAO,MAAM,WAAW,KAAK,UAAU,MAAM,KAAK,MAAM,WAAW,KAAK,UAAU,IAAI;EACxF;EACA,MAAM,EAAE,KAAK,UAAU;GACrB,QAAQ,IAAI,KAAK,KAAK,UAAU,MAAM,CAAC;EACzC;EACA,MAAM,SAAS;GACb,IAAI;IACF,MAAM,OAAO,EAAE,GAAG,QAAQ;IAG1B,MAAM,WAAW;KACf,OAAO,CAAC,GAAG,OAAO;KAClB,OAAA;KACA,KAAK,OAAO,CAAC,KAAK,YAAY;MAC5B,MAAM,SAAS,MAAM,QAAQ,SAAS,GAAG;MACzC,IAAI,WAAW,MAAM;MAErB,KAAK,OAAO;OAAE;OAAQ,QAAQ,KAAK,UAAU,MAAM;MAAE;KACvD;IACF,CAAC;IAED,MAAM,MAAM,UAAU,cAAc,KAAK,UAAU;KAAE,SAAS;KAAS,SAAS;IAAK,CAAwB,CAAC;GAChH,QAAQ,CAER;EACF;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtCA,MAAa,iBACwB,WAClC,YACC,MAAO,WAAW,CAAC,CAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AClDrC,MAAa,YAAY,qBAAqB;CAC5C,MAAM;CACN,MAAM,SAAS,KAAa;EAC1B,IAAI;GACF,OAAO,MAAM,SAAS,QAAQ,GAAG,GAAG,MAAM;EAC5C,SAAS,QAAQ;GACf,OAAO;EACT;CACF;CACA,MAAM,UAAU,KAAa,OAAe,SAAsC;EAChF,MAAM,MAAM,QAAQ,GAAG,GAAG,OAAO;GAAE,QAAQ;GAAO,QAAQ,SAAS;EAAO,CAAC;CAC7E;CACA,MAAM,WAAW,KAAa;EAC5B,MAAM,GAAG,QAAQ,GAAG,GAAG,EAAE,OAAO,KAAK,CAAC;CACxC;CACA,MAAM,SAAS,MAAe;EAC5B,MAAM,eAAe,QAAQ,QAAQ,QAAQ,IAAI,CAAC;EAClD,MAAM,OAAsB,CAAC;EAE7B,IAAI;GACF,WAAW,MAAM,SAAS,KAAK,QAAQ;IAAE,KAAK;IAAc,eAAe;GAAK,CAAC,GAC/E,IAAI,MAAM,OAAO,GACf,KAAK,KAAK,YAAY,SAAS,cAAc,KAAK,MAAM,YAAY,MAAM,IAAI,CAAC,CAAC,CAAC;EAGvF,SAAS,QAAQ,CAEjB;EAEA,OAAO;CACT;CACA,MAAM,MAAM,MAAe;EACzB,IAAI,CAAC,MACH;EAGF,MAAM,GAAG,QAAQ,IAAI,GAAG;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;CAC1D;AACF,EAAE;;;;;;;;;;;;AC5CF,SAAgB,gBAAgB,MAAsB;CACpD,MAAM,cAAc,KAAK,MAAM,cAAc;CAC7C,IAAI,WAAW,WAAW,GAAG,OAAO,KAAK,aAAa,UAAU,MAAM;CAEtE,OAAO,KAAK,OAAO,GAAG,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC;AACjE;;;;;;;;;;;;AAaA,MAAa,eAAe,eAAe,EAAE,OAAO,QAAQ,IAAI,QAA6B;CAC3F,MAAM,MAAM,gBAAgB,IAAI;CAChC,MAAM,KAAK,UAAU;CACrB,MAAM,UAAU,QAAgB,KAAK,KAAK,GAAG;CAE7C,OAAO;EACL,MAAM;EACN,WAAW,QAAQ,GAAG,SAAS,OAAO,GAAG,CAAC;EAC1C,YAAY,KAAK,UAAU,GAAG,UAAU,OAAO,GAAG,GAAG,KAAK;EAC1D,aAAa,QAAQ,GAAG,WAAW,OAAO,GAAG,CAAC;EAC9C,WAAW,SAAS,GAAG,SAAS,OAAO,OAAO,IAAI,IAAI,GAAG;EAEzD,OAAO,OAAO,SAAU,OAAO,GAAG,MAAM,OAAO,IAAI,CAAC,IAAI,KAAA;CAC1D;AACF,CAAC;;;AChCD,MAAM,gBAAgB;AAEtB,eAAe,OAAO,MAAc,OAA4B,IAAY,iBAA8C;CACxH,IAAI,aAA2B;CAC/B,IAAI,YAA0B;CAC9B,IAAI,QAAuB,QAAQ,QAAQ;CAC3C,IAAI;CACJ,KAAK,SAAS,KAAK,UAAU,UAAU;EACrC,aAAa;EAEb,YAAY,iBAAiB,KAAK,KAAK,SAAS,GAAG,aAAa,CAAC,CAAC,MAAM;CAC1E,CAAC;CAED,IAAI,MAAM,cAAc,gBAAgB,IAAI,GAC1C,KAAK,MAAM,SAAS,CAAC,KAAK,SAAS,QAAQ,KAAK,SAAS,MAAM,GAAG;EAChE,IAAI,CAAC,OAAO;EACZ,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS,SAAS;GAC9C,QAAQ,MACL,WAAW,MAAM,SAAS,kBAAkB;IAAE;IAAI;GAAK,CAAC,CAAC,CAAC,CAC1D,OAAO,UAAU;IAChB,cAAc,QAAQ,KAAK;GAC7B,CAAC;EACL,CAAC;CACH;CAEF,MAAM,SAAS,MAAM,QAAQ,QAAQ,IAAI,CAAC,CAAC,YAAY,IAAI;CAC3D,aAAa,SAAS;CACtB,MAAM;CAEN,MAAM,QAAQ,cAAc;CAC5B,IAAI,OAAO,OAAO;EAAE,SAAS;EAAO;CAAM;CAC1C,IAAI,QAAQ,aAAa,GAAG,OAAO;EAAE,SAAS;EAAM,OAAO;CAAK;CAChE,OAAO;EAAE,SAAS;EAAO,uBAAO,IAAI,MAAM,wBAAwB,iBAAiB;EAAG,QAAQ,QAAQ;EAAQ,QAAQ,QAAQ;CAAO;AACvI;;;;;;;;AASA,eAAsB,QAAQ,EAAE,OAAO,SAAS,OAAO,CAAC,GAAG,MAAM,MAAMC,UAAQ,IAAI,GAAG,UAA+C;CACnI,MAAM,KAAK,WAAW;CACtB,MAAM,MAAM,SAAS,mBAAmB;EAAE;EAAI;EAAS;EAAM;CAAK,CAAC;CAOnE,MAAM,SAAS,MAAM,OALR,EAAE,SAAS,CAAC,GAAG,IAAI,GAAG;EACjC;EACA,cAAc;EACd,aAAa;GAAE;GAAK,aAAa;GAAM,OAAO;IAAC;IAAU;IAAQ;GAAM;GAAG,UAAUA,UAAQ,aAAa;EAAQ;CACnH,CAC+B,GAAG,OAAO,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC;CACzE,MAAM,MAAM,SAAS,iBAAiB;EAAE;EAAI;EAAS;EAAM;EAAM,GAAG;CAAO,CAAC;CAE5E,OAAO;AACT;;;;;;;AChDA,MAAM,cAAuC,CAC3C;CAAE,MAAM;CAAU,OAAO;CAAa,MAAM;CAAc,OAAO;CAAY,YAAY;CAAsB,MAAM,YAAY,KAAK;AAAa,GACnJ;CAAE,MAAM;CAAQ,OAAO;CAAU,MAAM;CAAW,OAAO;CAAS,YAAY;CAAmB,MAAM,YAAY,KAAK;AAAW,CACrI;;;;AAOA,eAAe,YAAY,EAAE,MAAM,SAAS,YAAY,OAAO,KAAK,UAA8C;CAChH,MAAM,WAAW,YAAY,SAAS,MAAM,WAAW,KAAK,YAAY,GAAG,IAAI;CAC/E,IAAI,CAAC,UAAU;EACb,MAAM,MAAM,SAAS,aAAa,EAAE,SAAS,MAAM,KAAK,MAAM,UAAU,KAAK,WAAW,KAAK,IAAI,EAAE,cAAc,KAAK,KAAK,YAAY,EAAE,GAAG,CAAC;EAC7I,OAAO;CACT;CACA,IAAI,YAAY,QACd,MAAM,MAAM,SAAS,aAAa,EAAE,SAAS,iBAAiB,KAAK,MAAM,IAAI,UAAU,OAAO,QAAQ,IAAI,CAAC;CAG7G,MAAM,OAAO,KAAK,MAAM;CAGxB,IAAI,CAAC,QAAQ,CAAC,WAAW,UAAU,GAAG,OAAO;CAE7C,MAAM,SAAS,MAAM,QAAQ;EAAE;EAAO,SAAS,KAAK;EAAS,MAAM,KAAK,KAAK,UAAU;EAAG;EAAK;CAAO,CAAC;CACvG,IAAI,OAAO,SAAS;EAClB,MAAM,MAAM,SAAS,gBAAgB,EAAE,SAAS,GAAG,KAAK,KAAK,QAAQ,UAAU,OAAO,QAAQ,EAAE,MAAM,UAAU,OAAO,UAAU,EAAE,eAAe,CAAC;EACnJ,OAAO;CACT;CACA,OAAO,OAAO;AAChB;;;;;;;;;;;;;AAcA,eAAsB,gBAAgB,EAAE,QAAQ,YAAY,OAAO,UAA8D;CAC/H,MAAM,cAAiC,CAAC;CACxC,MAAM,SAAS,OAAO,MAAiC,OAAe,UAAiB;EACrF,MAAM,aAAgC;GACpC;GACA,UAAU;GACV,SAAS,GAAG,MAAM,WAAW,MAAM;GACnC,MAAM;GACN,UAAU,EAAE,MAAM,SAAS;GAC3B,OAAO;EACT;EACA,YAAY,KAAK,UAAU;EAC3B,MAAM,YAAY,KAAK,OAAO,UAAU;CAC1C;CAEA,KAAK,MAAM,QAAQ,aAAa;EAC9B,MAAM,UAAU,OAAO,OAAO,KAAK;EACnC,IAAI,CAAC,SAAS;EAEd,MAAM,MAAM,SAAS,QAAQ,KAAK,KAAK,OAAO;EAC9C,MAAM,QAAQ,MAAM,YAAY;GAAE;GAAM;GAAS;GAAY;GAAO,KAAK,OAAO;GAAM;EAAO,CAAC;EAC9F,IAAI,OAAO,MAAM,OAAO,KAAK,MAAM,KAAK,OAAO,KAAK;EACpD,MAAM,MAAM,SAAS,QAAQ,KAAK,KAAK,KAAK;EAC5C,QAAQ,eAAe;CACzB;CAEA,MAAM,WAAW,OAAO,OAAO,gBAAgB,CAAC;CAChD,IAAI,SAAS,WAAW,GAAG,OAAO;CAElC,MAAM,MAAM,SAAS,kBAAkB;CACvC,KAAK,MAAM,SAAS,UAAU;EAC5B,MAAM,EAAE,SAAS,SAAS,OAAO,UAAU,WAAW;GAAE,SAAS;GAAO,MAAM,KAAA;EAAU,IAAI;EAC5F,MAAM,CAAC,YAAY,GAAG,QAAQ,SAAS,OAAO;EAC9C,IAAI,CAAC,YAAY;EAEjB,MAAM,SAAS,MAAM,QAAQ;GAAE;GAAO,SAAS;GAAY;GAAM;GAAM,KAAK,OAAO;GAAM;EAAO,CAAC;EACjG,IAAI,OAAO,SAAS,MAAM,MAAM,SAAS,gBAAgB,EAAE,SAAS,GAAG,UAAU,OAAO,QAAQ,OAAO,EAAE,wBAAwB,CAAC;EAClI,IAAI,CAAC,OAAO,SAAS,MAAM,OAAO,YAAY,KAAK,oBAAoB,yBAAyB,OAAO,KAAK;EAC5G,QAAQ,eAAe;CACzB;CACA,MAAM,MAAM,SAAS,gBAAgB;CAErC,OAAO;AACT;;;AC3GA,SAAS,cAAc,YAAgC;CACrD,OAAO;EACL,GAAG;EACH,MAAM,WAAW,QAAQ,QAAQ,IAAI;EACrC,SAAS,WAAW,WAAW,CAAC;EAChC,QAAQ;GACN,QAAQ;GACR,MAAM;GACN,eAAe;GACf,GAAG,WAAW;EAChB;EACA,SAAS,WAAW,WAAW,UAAU;EACzC,WAAW,WAAW,aAAa,CAAC;EACpC,SAAS,WAAW,WAAW,CAAC;CAClC;AACF;;;;;AAMA,SAAS,sBAAsB,SAA2B;CACxD,OAAO,QAAQ,SAAS;AAC1B;;;;;AAMA,SAAS,gBAAgB,EAAE,QAAQ,WAAwD;CACzF,OAAO,sBAAsB,OAAO,KAAK,QAAQ,OAAO,UAAU,OAAO,QAAQ,OAAO,cAAc,MAAM;AAC9G;;;;;;;;;;;;;;;;;;AA6DA,IAAa,OAAb,MAAkB;CAChB;CACA;CACA,UAA6B;CAC7B,YAAmC;CACnC;CAEA,YAAY,YAAwB,UAA6B,CAAC,GAAG;EACnE,KAAK,SAAS,cAAc,UAAU;EACtC,KAAK,QAAQ,QAAQ,SAAS,IAAI,SAAoB;EACtD,KAAK,UAAU,QAAQ;CACzB;CAEA,IAAI,UAAmB;EACrB,OAAO,KAAK,OAAO;CACrB;CAEA,IAAI,SAAqB;EACvB,IAAI,CAAC,KAAK,SACR,MAAM,IAAI,YAAY,MAAM;GAAE,MAAM,YAAY,KAAK;GAAe,UAAU;GAAS,SAAS;EAAwD,CAAC;EAC3J,OAAO,KAAK;CACd;;;;CAKA,MAAM,QAAuB;EAC3B,MAAM,SAAS,KAAK;EACpB,QAAQ,eAAe;EACvB,MAAM,SAAS,KAAK;EACpB,MAAM,WAAW,gBAAgB,MAAM,IAAI,MAAM,qBAAqB;GAAE,SAAS,OAAO;GAAS,OAAO,aAAa,EAAE,MAAM,OAAO,KAAK,CAAC;EAAE,CAAC,IAAI,KAAA;EAEjJ,MAAM,YAAY,OAAO,OAAO,QAAQ,QAAQ,OAAO,MAAM,OAAO,OAAO,IAAI,IAAI,KAAA;EAInF,IAAI,aAAa,aAAa,OAAO,MAAM,SAAS,GAClD,MAAM,IAAI,YAAY,MAAM;GAC1B,MAAM,YAAY,KAAK;GACvB,UAAU;GACV,SAAS,+BAA+B,UAAU;GAClD,MAAM;GACN,UAAU,EAAE,MAAM,SAAS;EAC7B,CAAC;EAKH,MAAM,SAAS,IAAI,WAAW,QAAQ;GAAE,OAAO,KAAK;GAAO;GAAU;GAAQ;EAAU,CAAC;EACxF,MAAM,OAAO,MAAM;EAEnB,KAAK,UAAU;EACf,KAAK,YAAY,YAAY;CAC/B;;;;;CAMA,MAAM,QAA8B;EAClC,MAAM,MAAM,MAAM,KAAK,UAAU;EACjC,IAAI,YAAY,SAAS,IAAI,WAAW,GAAG;GACzC,MAAM,SAAS,IAAI,YAChB,OAAO,YAAY,SAAS,CAAC,CAC7B,QAAQ,eAAe,WAAW,aAAa,OAAO,CAAC,CACvD,KAAK,eAAe,WAAW,SAAS,IAAI,YAAY,MAAM,UAAU,CAAC;GAC5E,MAAM,IAAI,eAAe,QAAQ,qBAAqB,OAAO,OAAO,GAAG,OAAO,WAAW,IAAI,UAAU,UAAU;EACnH;EACA,OAAO;CACT;;;;;;CAOA,MAAM,YAAkC;;;GACtC,KAAK,SAAS,eAAe;GAC7B,IAAI,CAAC,KAAK,SAAS,MAAM,KAAK,MAAM;GACpC,MAAM,OAAA,YAAA,EAAO,IAAA;GACb,MAAM,SAAS,KAAK;GACpB,MAAM,UAAU,KAAK;GACrB,MAAM,EAAE,gBAAgB,MAAM,OAAO,IAAI;GAEzC,OAAO;IAAE;IAAa,OAAO,OAAO,YAAY;IAAO;IAAQ;GAAQ;;;;;;CACzE;;;;;;;;;;;;;CAcA,MAAM,SAAS,UAA2B,CAAC,GAA4B;EACrE,MAAM,SAAS,KAAK;EACpB,QAAQ,eAAe;EACvB,MAAM,EAAE,OAAO,WAAW;EAC1B,MAAM,UAAU,QAAQ,OAAO;EAE/B,MAAM,MAAM,SAAS,yBAAyB,EAAE,OAAO,CAAC;EAIxD,IAAI;EACJ,IAAI;GACF,MAAM,MAAM,SAAS,kBAAkB;GACvC,MAAM,KAAK,MAAM;GACjB,MAAM,MAAM,SAAS,gBAAgB;GAErC,SAAS,MAAM,KAAK,UAAU;EAChC,SAAS,aAAa;GACpB,IAAI,QAAQ,SAAS,MAAM;GAC3B,SAAS;IAAE,OAAO,CAAC;IAAG,aAAa,CAAC,YAAY,KAAK,WAAW,CAAC;GAAE;EACrE;EACA,MAAM,EAAE,OAAO,gBAAgB;EAC/B,MAAM,UAAU,KAAK;EACrB,QAAQ,eAAe;EAIvB,KAAK,MAAM,cAAc,aACvB,IAAI,YAAY,UAAU,UAAU,GAAG,MAAM,YAAY,KAAK,OAAO,UAAU;EAGjF,IAAI,YAAY,SAAS,WAAW,GAAG;GACrC,MAAM,MAAM,SAAS,uBAAuB;IAAE;IAAQ;IAAS;IAAa,cAAc,MAAM;IAAQ,QAAQ;IAAU;GAAQ,CAAC;GACnI,OAAO;IAAE,SAAS;IAAO;IAAO;GAAY;EAC9C;EAEA,MAAM,gBAAgB,QAAQ,iBAAiB;EAC/C,MAAM,oBAAoB,sBAAsB,OAAO,OAAO,IAC1D,MAAM,cAAc;GAAE;GAAQ,YAAY,QAAQ,OAAO,MAAM,OAAO,OAAO,IAAI;GAAG;GAAO;EAAO,CAAC,IACnG,CAAC;EAEL,MAAM,mBAAmB,CAAC,GAAG,aAAa,GAAG,iBAAiB;EAC9D,MAAM,SAAS,YAAY,SAAS,iBAAiB;EAKrD,IAAI,CAAC,QAAQ,MAAM,KAAK,WAAW,OAAO;EAE1C,MAAM,MAAM,SAAS,uBAAuB;GAC1C;GACA;GACA,aAAa;GACb,cAAc,MAAM;GACpB,QAAQ,SAAS,WAAW;GAC5B;EACF,CAAC;EAED,OAAO;GAAE,SAAS,CAAC;GAAQ;GAAO,aAAa;EAAiB;CAClE;CAEA,UAAgB;EACd,KAAK,SAAS,QAAQ;CACxB;CAEA,CAAC,OAAO,WAAiB;EACvB,KAAK,QAAQ;CACf;AACF;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,WAAW,YAAwB,UAA6B,CAAC,GAAS;CACxF,OAAO,IAAI,KAAK,YAAY,OAAO;AACrC;;;;;;;;AC/RA,MAAa,WAAW;CACtB,QAAQ,OAAO;CACf,OAAO;CACP,MAAM;CACN,MAAM;CACN,SAAS;AACX;;;;;;;;;;;;;;;;;;;;;;AAuHA,SAAgB,eAAyB,UAAqC;CAC5E,MAAM,UAAoB,CAAC;CAE3B,OAAO;EACL,MAAM,SAAS;EACf,kBAAkB,SAAS;EAC3B,MAAM,OAAO,QAAQ,SAAS;GAC5B,MAAM,SAAS,MAAM,SAAS,OAAO,QAAQ,OAAO;GACpD,IAAI,SAAS,OACX,QAAQ,KAAK,MAAM;EAEvB;EACA,MAAM,MAAM,SAAS;GACnB,MAAM,SAAS,QAAQ,SAAS,CAAC,GAAG,OAAO,CAAC;GAC5C,QAAQ,SAAS;EACnB;CACF;AACF;;;;;;;;ACzFA,SAAgB,YAAY,QAAkC;CAC5D,MAAM,EAAE,QAAQ,aAAa,cAAc,QAAQ,YAAY;CAE/D,MAAM,SAAS,YAAY,cAAc,WAAW;CACpD,MAAM,QAAQ,OAAO,SAAS,UAAU;CACxC,MAAM,SAAS,YAAY,MAAM,WAAW;CAC5C,MAAM,WAAW,YAAY,OAAO,YAAY,SAAS;CACzD,MAAM,UAAU,YACb,OAAO,YAAY,aAAa,CAAC,CACjC,MAAM,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAC,CACvC,KAAK,gBAAgB;EAAE,QAAQ,WAAW;EAAQ,YAAY,WAAW;CAAS,EAAE;CAEvF,OAAO;EACL,MAAM,OAAO,QAAQ;EACrB;EAEA,SAAS;GAAE,QAAQ,WAAW,YAAY,QAAQ,WAAW,IAAI,IAAI,QAAQ,OAAO;GAAQ;GAAQ;EAAM;EAC1G;EACA;EACA,YAAY,aAAa,OAAO;EAChC,QAAQ,QAAQ,OAAO,MAAM,OAAO,OAAO,IAAI;EAC/C;EACA,aAAa,SAAS,KAAK,eAAe,YAAY,UAAU,UAAU,CAAC;CAC7E;AACF;;;;;;;;ACtEA,SAAgB,cAAc,QAAgB,EAAE,eAAwD;CACtG,MAAM,EAAE,QAAQ,SAAS,QAAQ,cAAc,YAAY,QAAQ,YAAY;CAE/E,MAAM,OAA8C,CAAC;CAErD,MAAM,SAAS,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,OAAO;CAC/D,KAAK,KAAK,CACR,WACA,WAAW,YACP,GAAG,UAAU,SAAS,GAAG,QAAQ,OAAO,QAAQ,EAAE,IAAI,QAAQ,MAAM,KACpE;EACE,UAAU,SAAS,GAAG,QAAQ,OAAO,QAAQ;EAC7C,UAAU,OAAO,GAAG,QAAQ,OAAO,OAAO,QAAQ;EAClD,SAAS,IAAI,UAAU,OAAO,GAAG,OAAO,SAAS,IAAI,KAAA;CACvD,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,KAAK,IAAI,KAAK,QAAQ,MAAM,EAC1C,CAAC;CAED,IAAI,WAAW,YAAY,QAAQ,OAAO,SAAS,GACjD,KAAK,KAAK,CAAC,UAAU,QAAQ,OAAO,KAAK,SAAS,UAAU,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;CAGvF,IAAI,OAAO,SAAS,KAAK,OAAO,WAAW,GAAG;EAC5C,MAAM,SAAS,CACb,OAAO,SAAS,IAAI,UAAU,OAAO,GAAG,OAAO,OAAO,GAAG,OAAO,WAAW,IAAI,UAAU,UAAU,IAAI,KAAA,GACvG,OAAO,WAAW,IAAI,UAAU,UAAU,GAAG,OAAO,SAAS,GAAG,OAAO,aAAa,IAAI,YAAY,YAAY,IAAI,KAAA,CACtH,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,KAAK;EACb,KAAK,KAAK,CAAC,UAAU,MAAM,CAAC;CAC9B;CAEA,KAAK,KAAK,CAAC,SAAS,GAAG,UAAU,SAAS,OAAO,YAAY,CAAC,EAAE,WAAW,CAAC;CAC5E,KAAK,KAAK,CAAC,YAAY,UAAU,SAAS,SAAS,UAAU,CAAC,CAAC,CAAC;CAChE,KAAK,KAAK,CAAC,UAAU,MAAM,CAAC;CAE5B,MAAM,aAAa,KAAK,IAAI,GAAG,KAAK,KAAK,CAAC,WAAW,MAAM,MAAM,GAAG,QAAQ,SAAS,IAAI,IAAmB,CAAC;CAC7G,MAAM,QAAQ,KAAK,KAAK,CAAC,OAAO,WAAW,GAAG,UAAU,OAAO,MAAM,SAAS,UAAU,CAAC,EAAE,IAAI,OAAO;CAEtG,IAAI,eAAe,QAAQ,SAAS,GAAG;EACrC,MAAM,YAAY,KAAK,IAAI,GAAG,GAAG,QAAQ,KAAK,WAAW,OAAO,OAAO,MAAM,CAAC;EAC9E,MAAM,SAAS,IAAI,OAAO,aAAa,CAAC;EAExC,MAAM,KAAK,UAAU,OAAO,UAAU,SAAS,UAAU,CAAC,CAAC;EAC3D,KAAK,MAAM,UAAU,SAAS;GAC5B,MAAM,UAAU,SAAS,OAAO,UAAU;GAC1C,MAAM,YAAY,KAAK,IAAI,KAAK,KAAK,OAAO,aAAa,GAAG,GAAG,EAAE;GAEjE,MAAM,MAAM,UAAU,OAAO,IAAI,OAAO,SAAS,CAAC;GAClD,MAAM,KAAK,GAAG,SAAS,UAAU,OAAO,GAAG,EAAE,GAAG,OAAO,OAAO,OAAO,SAAS,EAAE,GAAG,IAAI,GAAG,SAAS;EACrG;CACF;CAEA,OAAO;AACT;;;;;;;AC9DA,MAAM,mBAAoC,OAAO,EAAE,OAAO,aAAa;CACrE,QAAQ,IAAI,EAAE;CACd,IAAI,OACF,QAAQ,IAAI,UAAU,WAAW,WAAW,QAAQ,SAAS,KAAK,CAAC;CAErE,KAAK,MAAM,QAAQ,OACjB,QAAQ,IAAI,IAAI;AAEpB;;;;;;;;;;;;;AAcA,SAAgB,kBAAkB,EAAE,SAAS,oBAAkD,CAAC,GAAa;CAC3G,OAAO,eAAe;EACpB,MAAM;EACN,OAAO,QAAQ,EAAE,UAAA,cAAY;GAC3B,IAAIC,cAAYC,SAAY,QAC1B;GAGF,MAAM,SAAS,YAAY,MAAM;GAEjC,OAAO,cAAc,QAAQ,EAAE,aAAaD,cAAYC,SAAY,QAAQ,CAAC,GAAG;IAAE,OAAO,OAAO;IAAM,QAAQ,OAAO;GAAO,CAAC;EAC/H;CACF,CAAC;AACH;;;;;AAMA,MAAa,cAAc,kBAAkB;;;ACnC7C,SAAS,iBAAiB,KAAqB;CAC7C,UAAU,KAAK;EAAE,WAAW;EAAM,MAAM;CAAM,CAAC;CAC/C,UAAU,KAAK,GAAK;CACpB,OAAO;AACT;;;;;;;;AASA,SAAgB,eAAe,OAAO,IAAY;CAChD,MAAM,MAAM,QAAQC,UAAQ,IAAI,aAAa,KAAK,QAAQ,GAAG,OAAO,GAAG,IAAI;CAC3E,IAAI;EACF,OAAO,iBAAiB,GAAG;CAC7B,QAAQ;EACN,OAAO,iBAAiB,KAAK,OAAO,GAAG,QAAQ,KAAK,UAAU,GAAG,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;CAClF;AACF;;;;;;;;;;;AAYA,SAAgB,YAAY,EAAE,SAA6B,CAAC,GAAG;CAC7D,OAAOC,gBAAgB,EAAE,QAAQ,SAAS,EAAE,MAAM,eAAe,IAAI,EAAE,CAAC,EAAE,CAAC;AAC7E;;;;;;;;ACnCA,SAAS,oBAAoB,aAAuD;CAClF,MAAM,WAAW,YAAY,OAAO,YAAY,SAAS;CACzD,IAAI,SAAS,WAAW,GACtB,OAAO,CAAC;CAKV,OAAO;EAAC;EAAe;EADR,SAAS,KAAK,eAAe,YAAY,OAAO,YAAY,EAAE,SAAS,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CACvE,CAAC,CAAC,KAAK,MAAM;CAAC;AAChD;;;;;;;;;;;AAYA,MAAa,eAAe,eAAe;CACzC,MAAM;CACN,MAAM,OAAO,QAAQ;EACnB,MAAM,EAAE,aAAa,WAAW;EAChC,IAAI,YAAY,WAAW,GACzB;EAGF,MAAM,SAAS,YAAY,MAAM;EACjC,MAAM,SAAS,OAAO,OAAO,KAAK,OAAO,KAAK,sBAAK,IAAI,KAAK,EAAA,CAAE,YAAY,MAAM,sBAAK,IAAI,KAAK,EAAA,CAAE,YAAY;EAE5G,MAAM,WAAW,CAAC;GADD;GAAc;GAAI,GAAG,cAAc,QAAQ,EAAE,aAAa,KAAK,CAAC;EACzD,GAAG,oBAAoB,WAAW,CAAC,CAAC,CAAC,QAAQ,YAAY,QAAQ,SAAS,CAAC;EACnG,MAAM,UAAU,yBAAyB,CAAC,QAAQ,GAAG,SAAS,KAAK,YAAY,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC;EAGhH,MAAM,WAAW,GAAG;GAAC;GADR,OAAO,MAAM,QAAQ,oBAAoB,GAAG,CAAC,CAAC,QAAQ,YAAY,EAAE;GAC9C,KAAK,IAAI;EAAC,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAAE;EACzE,MAAM,MAAM,eAAe,QAAQC,UAAQ,IAAI,GAAG,OAAO,CAAC;EAE1D,MAAM,YAAY,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC,QAAQ,UAAU,GAAG,QAAQ,GAAG;EACjE,QAAQ,MAAM,wBAAwB,SAASA,UAAQ,IAAI,GAAG,KAAK,KAAK,QAAQ,CAAC,GAAG;CACtF;AACF,CAAC;;;;;;;;;;AC7CD,MAAa,eAAe,eAAe;CACzC,MAAM;CACN,OAAO,QAAQ;EACb,OAAO,YAAY,MAAM;CAC3B;CACA,MAAM,UAAU,SAAS;EACvB,UAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,EAAE,GAAG;CAC9D;AACF,CAAC;;;ACZD,SAAS,gBAAgB,QAAkC;CAKzD,OAAO,gCAJM,KAAK,UAAU;EAAE,8BAAa,IAAI,KAAK,EAAA,CAAE,YAAY;EAAG,QAAQ,YAAY,MAAM;EAAG,aAAa,OAAO,eAAe,CAAC;CAAE,CAAC,CAAC,CACvI,QAAQ,MAAM,SAAS,CAAC,CACxB,QAAQ,MAAM,SAAS,CAAC,CACxB,QAAQ,MAAM,SACyB,EAAE;AAC9C;;;;AAKA,MAAa,eAAe,eAAe;CACzC,MAAM;CACN,kBAAkB;CAClB,MAAM,OAAO,QAAQ;EAEnB,MAAM,WAAW;GAAC;GADL,OAAO,OAAO,MAAM,QAAQ,oBAAoB,GAAG,CAAC,CAAC,QAAQ,YAAY,EAAE;GACxD,KAAK,IAAI;EAAC,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EACpE,MAAM,MAAM,eAAe,QAAQ,QAAQ,IAAI,GAAG,OAAO,CAAC;EAC1D,MAAM,UAAU,YAAY,EAAE,MAAM,IAAI,CAAC;EACzC,MAAM,SAAS,IAAI,IAAI,WAAW,YAAY,GAAG;EACjD,MAAM,CAAC,MAAM,MAAM,MAAM,QAAQ,IAAI,CAAC,KAAK,cAAc,IAAI,IAAI,cAAc,MAAM,CAAC,CAAC,GAAG,KAAK,cAAc,IAAI,IAAI,cAAc,MAAM,CAAC,CAAC,CAAC,CAAC;EAE7I,MAAM,QAAQ,IAAI;GAChB,QAAQ,QAAQ,GAAG,SAAS,cAAc,IAAI;GAC9C,QAAQ,QAAQ,GAAG,SAAS,cAAc,EAAE;GAC5C,QAAQ,QAAQ,GAAG,SAAS,WAAW,gBAAgB,MAAM,CAAC;EAChE,CAAC;EACD,MAAM,aAAa,KAAK,KAAK,UAAU,YAAY;EACnD,QAAQ,MAAM,0BAA0B,SAAS,QAAQ,IAAI,GAAG,UAAU,GAAG;EAC7E,cAAc,UAAU;CAC1B;AACF,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACyBD,SAAgB,eAAmC,SAA+D;CAChH,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC6KA,SAAgB,gBACd,WAC+B;CAC/B,OAAO;AACT;;;;;;;;;AC/KA,SAAgB,aACd,YACuC;CACvC,OAAO,gBAAgB;EAAE,MAAM;EAAU,GAAG;CAAW,CAAC;AAC1D;;;;;;;;;;;;;;;;;;;;;;AClDA,MAAa,gBAAgB,oBAAoB;CAC/C,MAAM,wBAAQ,IAAI,IAAoB;CAEtC,OAAO;EACL,MAAM;EACN,MAAM,SAAS,KAAa;GAC1B,OAAO,MAAM,IAAI,GAAG,KAAK;EAC3B;EACA,MAAM,UAAU,KAAa,OAAe;GAC1C,MAAM,IAAI,KAAK,KAAK;EACtB;EACA,MAAM,WAAW,KAAa;GAC5B,MAAM,OAAO,GAAG;EAClB;EACA,MAAM,SAAS,MAAe;GAC5B,MAAM,OAAO,CAAC,GAAG,MAAM,KAAK,CAAC;GAC7B,OAAO,OAAO,KAAK,QAAQ,MAAM,EAAE,WAAW,IAAI,CAAC,IAAI;EACzD;EACA,MAAM,MAAM,MAAe;GACzB,IAAI,CAAC,MAAM;IACT,MAAM,MAAM;IACZ;GACF;GACA,KAAK,MAAM,OAAO,MAAM,KAAK,GAC3B,IAAI,IAAI,WAAW,IAAI,GACrB,MAAM,OAAO,GAAG;EAGtB;CACF;AACF,CAAC;;;ACyDD,MAAM,kCAAkB,IAAI,IAAa;CAAC;CAAU;CAAW;AAAQ,CAAgC;AACvG,MAAM,+BAAe,IAAI,IAAa;CAAC;CAAU;CAAW;CAAQ;CAAU;AAAM,CAAkD;AACtI,MAAM,eAAe;AACrB,MAAM,aAAa;AACnB,MAAM,cAAc;AACpB,MAAM,eAAe;AACrB,MAAM,cAAc;AACpB,MAAM,SAAS;;AAEf,MAAM,8BAAc,IAAI,IAAa;CAAC;CAAa;CAAe;AAAW,CAAC;AAE9E,MAAM,YAAY,UAAqD,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC1I,MAAM,oBAAoB,UAAmB,UAAU,KAAA,KAAa,OAAO,UAAU;AACrF,MAAM,kBAAkB,UAAmB,OAAO,UAAU,YAAY,UAAU;AAClF,MAAM,WAAW,SAAiB,UAAmB,OAAO,UAAU,YAAY,QAAQ,KAAK,KAAK;;AAEpG,MAAM,iBAAiB,UACrB,KAAK,UAAU,QAAQ,MAAM,SAC3B,SAAS,IAAI,IACT,OAAO,YACL,OAAO,KAAK,IAAI,CAAC,CACd,KAAK,CAAC,CACN,KAAK,QAAQ,CAAC,KAAK,KAAK,IAAI,CAAC,CAClC,IACA,IACN;;;;;;AAOF,SAAgB,cAAc,MAA+B;CAC3D,OAAO,OAAO,SAAS,YAAY,KAAK,UAAU,OAAO,aAAa,KAAK,IAAI;AACjF;AAEA,SAAS,aAAa,OAAyB;CAC7C,OACE,SAAS,KAAK,KACd,OAAO,KAAK,KAAK,CAAC,CAAC,OAAO,QAAQ,QAAQ,UAAU,QAAQ,QAAQ,KACpE,eAAe,MAAM,IAAI,MACxB,MAAM,WAAW,KAAA,KAAa,eAAe,MAAM,MAAM;AAE9D;;AAGA,SAAS,SAAS,OAAkD;CAClE,IAAI,CAAC,SAAS,KAAK,GAAG,OAAO;CAC7B,MAAM,EAAE,KAAK,MAAM,OAAO,aAAa,MAAM,SAAS,aAAa;CACnE,OACE,eAAe,GAAG,KAClB,MAAM,QAAQ,IAAI,KAClB,KAAK,SAAS,KACd,KAAK,OAAO,YAAY,eAAe,OAAO,KAAK,CAAC,YAAY,IAAI,OAAO,CAAC,KAC5E,eAAe,KAAK,KACpB,iBAAiB,WAAW,KAC5B,aAAa,IAAI,IAAI,MACpB,YAAY,KAAA,KAAc,MAAM,QAAQ,OAAO,KAAK,QAAQ,OAAO,WAAW,SAAS,MAAM,KAAK,WAAW,UAAU,iBAAiB,OAAO,KAAK,CAAC,OACrJ,aAAa,KAAA,KAAa,aAAa;AAE5C;;;;;AAMA,SAAgB,iBAAiB,EAAE,UAAU,CAAC,KAAuC;CACnF,MAAM,uBAAO,IAAI,IAAY;CAC7B,OAAO,QAAQ,SAAS,WAAW;EACjC,MAAM,WAAW,KAAK,IAAI,OAAO,GAAG,IAAI,CAAC,WAAW,OAAO,IAAI,6BAA6B,IAAI,CAAC;EACjG,KAAK,IAAI,OAAO,GAAG;EACnB,IAAI,OAAO,SAAS,UAAU,OAAO;EACrC,IAAI,CAAC,OAAO,SAAS,QAAQ,OAAO,CAAC,GAAG,UAAU,WAAW,OAAO,IAAI,8BAA8B;EAEtG,OADqB,EAAE,aAAa,WAAW,OAAO,QAAQ,MAAM,WAAW,cAAc,OAAO,KAAK,MAAM,cAAc,OAAO,OAAO,CAAC,IACtH,WAAW,CAAC,GAAG,UAAU,WAAW,OAAO,IAAI,+CAA+C;CACtH,CAAC;AACH;;;;;;AAOA,SAAgB,oBAAoB,OAA4C;CAC9E,IAAI,CAAC,SAAS,KAAK,GAAG,OAAO;CAC7B,MAAM,EAAE,MAAM,MAAM,QAAQ,YAAY,aAAa,aAAa,aAAa,cAAc,sBAAsB,eAAe,MAAM,YAAY;CACpJ,OACE,gBAAgB,IAAI,IAAI,KACxB,cAAc,IAAI,KAClB,OAAO,eAAe,YACtB,WAAW,KAAK,UAAU,KAC1B,OAAO,gBAAgB,YACvB,OAAO,gBAAgB,aACtB,gBAAgB,KAAA,KAAc,MAAM,QAAQ,WAAW,KAAK,YAAY,MAAM,YAAY,OAC1F,iBAAiB,KAAA,KAAc,MAAM,QAAQ,YAAY,KAAK,aAAa,MAAM,aAAa,OAC9F,yBAAyB,KAAA,KAAc,MAAM,QAAQ,oBAAoB,KAAK,qBAAqB,MAAM,aAAa,OACtH,kBAAkB,KAAA,KAChB,SAAS,aAAa,KAAK,OAAO,QAAQ,aAAa,CAAC,CAAC,OAAO,CAAC,KAAK,YAAY,QAAQ,UAAU,QAAQ,WAAW,OAAO,UAAU,QAAQ,OAClJ,SAAS,KAAA,KAAa,SAAS,YAAY,SAAS,gBACpD,YAAY,KAAA,KAAc,MAAM,QAAQ,OAAO,KAAK,QAAQ,MAAM,QAAQ,MAC3E,iBAAiB,KAA0B,CAAC,CAAC,WAAW;AAE5D;;AAGA,SAAS,mBAAmB,OAA2C;CACrE,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,cAAc,MAAM,OAAO,KAAK,OAAO,MAAM,YAAY,YAAY,CAAC,QAAQ,MAAM,OAAO,GAAG,OAAO;CAC9H,IAAI,MAAM,SAAS,OAAO,OAAO;CACjC,OACE,MAAM,SAAS,YACf,QAAQ,cAAc,MAAM,KAAK,KACjC,QAAQ,aAAa,MAAM,IAAI,MAC9B,MAAM,QAAQ,MAAM,WAAW,MAAM,QAAQ,IAAI,MAAM,cACxD,QAAQ,QAAQ,MAAM,MAAM;AAEhC;;;;;AAMA,SAAgB,gBAAgB,OAAwC;CACtE,IAAI,CAAC,SAAS,KAAK,GAAG,OAAO;CAC7B,MAAM,EAAE,IAAI,MAAM,MAAM,UAAU,aAAa;CAC/C,OACE,OAAO,OAAO,YACd,YAAY,KAAK,EAAE,KACnB,gBAAgB,IAAI,IAAI,MACvB,SAAS,cAAc,SAAS,gBACjC,mBAAmB,QAAQ,KAC3B,oBAAoB,QAAQ,KAC5B,SAAS,SAAS;AAEtB;;;;ACxOA,MAAM,WAAW,OAAO,SAAmC,KAAK,MAAM,MAAM,SAAS,MAAM,MAAM,CAAC;;;;;;;AAQlG,eAAsB,sBAAsB,EAC1C,MACA,WAAW,CAAC,GACZ,cAAc,CAAC,KAKoB;CACnC,MAAM,UAAU,cAAc,KAAK,QAAQ,MAAM,cAAc,CAAC;CAChE,MAAM,WAAW,CACf,SACA,GAAG,YAAY,SAAS,SAAS;EAC/B,IAAI;GACF,OAAO,CAAC,cAAc,QAAQ,QAAQ,GAAG,KAAK,cAAc,CAAC,CAAC;EAChE,QAAQ;GACN,OAAO,CAAC;EACV;CACF,CAAC,CACH;CACA,MAAM,cAAe,MAAM,SAAS,KAAK,KAAK,MAAM,cAAc,CAAC,CAAC,CAAC,YAAY,IAAI;CACrF,MAAM,eAAe,CAAC,aAAa,cAAc,aAAa,eAAe,CAAC,CAAC,SAAS,WACtF,OAAO,WAAW,YAAY,WAAW,OAAO,OAAO,KAAK,MAAM,IAAI,CAAC,CACzE;CAEA,OAAO,QAAQ,IACb,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAG,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,aAAa,CAAC,CAAC,IAAI,OAAO,SAAoC;EAEhH,MAAM,MAAM,SACT,SAAS,YAAY,QAAQ,QAAQ,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,CACvD,KAAK,QAAQ,KAAK,KAAK,KAAK,IAAI,CAAC,CAAC,CAClC,MAAM,QAAQ,WAAW,KAAK,KAAK,KAAK,cAAc,CAAC,CAAC;EAC3D,IAAI,CAAC,KAAK,OAAO,EAAE,SAAS,KAAK;EACjC,IAAI;GACF,MAAM,EAAE,YAAa,MAAM,SAAS,KAAK,KAAK,KAAK,cAAc,CAAC;GAClE,MAAM,WAAW,MAAM,SAAS,KAAK,KAAK,KAAK,qBAAqB,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;GAC5F,OAAO;IAAE,SAAS;IAAM,SAAS,OAAO,YAAY,WAAW,UAAU,KAAA;IAAW,UAAU,oBAAoB,QAAQ,IAAI,WAAW,KAAA;GAAU;EACrJ,QAAQ;GACN,OAAO,EAAE,SAAS,KAAK;EACzB;CACF,CAAC,CACH;AACF"}
package/dist/mocks.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- import { t as __name } from "./rolldown-runtime-CRm0XQPb.js";
2
- import { C as NormalizedPlugin, Ht as KubbDriver, M as PluginType, X as Generator, an as Parser, ft as Config, i as AdapterFactoryOptions, t as Adapter, x as KubbPluginSetupContext } from "./createAdapter-CMnLz31B.js";
1
+ import { C as NormalizedPlugin, Ht as KubbDriver, M as PluginType, X as Generator, an as Parser, ft as Config, i as AdapterFactoryOptions, t as Adapter, x as KubbPluginSetupContext } from "./createAdapter-B5kKMsWV.js";
3
2
  import { FileNode, InputMeta, Macro, OperationNode, SchemaNode } from "@kubb/ast";
4
3
  //#region src/mocks.d.ts
5
4
  /**
package/dist/mocks.js CHANGED
@@ -1,5 +1,4 @@
1
- import "./rolldown-runtime-CRm0XQPb.js";
2
- import { I as camelCase, a as FileManager, i as createNodeCache, r as pluginNotFoundError, t as Hookable } from "./Hookable-Bjfoua7Y.js";
1
+ import { I as camelCase, a as FileManager, i as createNodeCache, r as pluginNotFoundError, t as Hookable } from "./Hookable-D_Eafz_X.js";
3
2
  import path, { resolve } from "node:path";
4
3
  import { applyMacros, ast } from "@kubb/ast";
5
4
  import { expect, vi } from "vitest";