@kubb/studio 5.6.1 → 5.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +84 -98
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -13
- package/dist/index.js +85 -99
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["readFile","createRequire","pathToFileURL","existsSync","require","readFile","builders","parseModule","detectCodeFormat","generateCode","writeFile","isAbsolute","relative","resolve","createHash","process","Diagnostics","createKubb","sep","fsStorage","stripVTControlCharacters","generationEventTypes","Diagnostics","RpcTarget","memoryStorage","cacheStorage","kubbVersion","version","mkdtemp","path","tmpdir","rm","resolveCacheDir","fsStorage","GENERATION_GONE_MESSAGE","MAX_PAGE_LINES","NodeWebSocket","AGENT_INSTANCE_HEADER","newWebSocketRpcSession","process","Hookable","AGENT_SOCKET_PATH","randomUUID","AgentCloseCode","delay","hash","delay","promisify","gzip","mkdtemp","join","tmpdir","mkdir","writeFile","fsStorage","readFile","rm","resolve","MAX_SNAPSHOT_BYTES"],"sources":["../../../internals/utils/src/casing.ts","../../../internals/utils/src/errors.ts","../../../internals/utils/src/runtime.ts","../../../internals/utils/src/fs.ts","../../../internals/utils/src/promise.ts","../../../internals/utils/src/time.ts","../package.json","../src/resolveConfig.ts","../src/configFile.ts","../src/generations.ts","../src/generationEvents.ts","../src/url.ts","../src/connect.ts","../src/pair.ts","../src/snapshot.ts"],"sourcesContent":["type Options = {\n /**\n * Text prepended before casing is applied.\n */\n prefix?: string\n /**\n * Text appended before casing is applied.\n */\n suffix?: string\n}\n\n/**\n * Shared implementation for camelCase and PascalCase conversion.\n * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)\n * and capitalizes each word according to `pascal`.\n *\n * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.\n */\nfunction toCamelOrPascal(text: string, pascal: boolean): string {\n return text\n .trim()\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([a-z])/g, '$1 $2')\n .split(/[\\s\\-_./\\\\:]+/)\n .filter(Boolean)\n .map((word, i) => {\n if (word.length > 1 && word === word.toUpperCase()) return word\n const head = i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()\n return head + word.slice(1)\n })\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '')\n}\n\n/**\n * Converts `text` to camelCase.\n *\n * @example Word boundaries\n * `camelCase('hello-world') // 'helloWorld'`\n *\n * @example With a prefix\n * `camelCase('tag', { prefix: 'create' }) // 'createTag'`\n */\nexport function camelCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false)\n}\n\n/**\n * Converts `text` to PascalCase.\n *\n * @example Word boundaries\n * `pascalCase('hello-world') // 'HelloWorld'`\n *\n * @example With a suffix\n * `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`\n */\nexport function pascalCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true)\n}\n","/**\n * Coerces an unknown thrown value to an `Error` instance.\n * Returns the value as-is when it is already an `Error`; otherwise wraps it with `String(value)`.\n *\n * @example\n * ```ts\n * try { ... } catch(err) {\n * throw new Error('Build failed', { cause: toError(err) })\n * }\n * ```\n */\nexport function toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value))\n}\n\n/**\n * Extracts a human-readable message from any thrown value.\n *\n * @example\n * ```ts\n * getErrorMessage(new Error('oops')) // 'oops'\n * getErrorMessage('plain string') // 'plain string'\n * ```\n */\nexport function getErrorMessage(value: unknown): string {\n return value instanceof Error ? value.message : String(value)\n}\n","/**\n * Name of the JavaScript runtime executing the current process.\n */\ntype RuntimeName = 'bun' | 'deno' | 'node'\n\n/**\n * Detects the JavaScript runtime executing the current process and exposes its name and version.\n *\n * Prefer the shared {@link runtime} instance over constructing your own.\n */\nclass Runtime {\n /**\n * `true` when the current process is running under Bun.\n *\n * Detection keys off the global `Bun` object rather than `process.versions`,\n * because Bun polyfills `process.versions.node` for Node compatibility and would\n * otherwise look like Node.\n *\n * @example\n * ```ts\n * if (runtime.isBun) {\n * await Bun.write(path, data)\n * }\n * ```\n */\n get isBun(): boolean {\n return typeof Bun !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Deno.\n */\n get isDeno(): boolean {\n return typeof (globalThis as { Deno?: unknown }).Deno !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Node.\n *\n * Bun and Deno are excluded first so a polyfilled `process` does not register as Node.\n */\n get isNode(): boolean {\n return !this.isBun && !this.isDeno && typeof process !== 'undefined' && process.versions?.node != null\n }\n\n /**\n * Name of the runtime executing the current process.\n *\n * @example\n * ```ts\n * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise\n * ```\n */\n get name(): RuntimeName {\n if (this.isBun) return 'bun'\n if (this.isDeno) return 'deno'\n\n return 'node'\n }\n\n /**\n * Version of the active runtime, or an empty string when it cannot be read.\n *\n * @example\n * ```ts\n * runtime.version // '1.3.11' under Bun, '22.22.2' under Node\n * ```\n */\n get version(): string {\n if (this.isBun) return process.versions.bun ?? ''\n if (this.isDeno) return (globalThis as { Deno?: { version?: { deno?: string } } }).Deno?.version?.deno ?? ''\n\n return process.versions?.node ?? ''\n }\n}\n\n/**\n * Shared {@link Runtime} instance describing the JavaScript runtime executing the current process.\n */\nexport const runtime = new Runtime()\n","import { access, mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { dirname, isAbsolute, relative, resolve } from 'node:path'\nimport { runtime } from './runtime.ts'\n\n/**\n * Resolves to `true` when the file or directory at `path` exists.\n * Uses `Bun.file().exists()` when running under Bun, `fs.access` otherwise.\n *\n * @example\n * ```ts\n * if (await exists('./kubb.config.ts')) {\n * const content = await read('./kubb.config.ts')\n * }\n * ```\n */\nexport async function exists(path: string): Promise<boolean> {\n if (runtime.isBun) {\n return Bun.file(path).exists()\n }\n return access(path).then(\n () => true,\n () => false,\n )\n}\n\n/**\n * Reads the file at `path` as a UTF-8 string.\n * Uses `Bun.file().text()` when running under Bun, `fs.readFile` otherwise.\n *\n * @example\n * ```ts\n * const source = await read('./src/Pet.ts')\n * ```\n */\nexport async function read(path: string): Promise<string> {\n if (runtime.isBun) {\n return Bun.file(path).text()\n }\n return readFile(path, { encoding: 'utf8' })\n}\n\ntype WriteOptions = {\n /**\n * Previously read content, or `null` when the file does not exist.\n * Omitting this value reads the file before writing.\n */\n stored?: string | null\n /**\n * When `true`, re-reads the file immediately after writing and throws if the\n * content does not match — useful for catching write failures on unreliable file systems.\n */\n sanity?: boolean\n}\n\n/**\n * Whether `stored` already holds `source`, comparing on the trimmed text rather than the exact\n * bytes. Surrounding whitespace is what a formatter adds and what editors strip, and neither is a\n * reason to rewrite the file.\n *\n * Both sides are trimmed, so a storage that keeps bytes verbatim settles on the same answer as one\n * that normalizes what it stores. Trimming only `stored` would leave a source with leading\n * whitespace rewritten on every build, since the stored copy keeps the whitespace the comparison\n * has already dropped.\n */\nexport function matchesStored({ stored, source }: { stored: string; source: string }): boolean {\n return stored.trim() === source.trim()\n}\n\n/**\n * Writes `data` to `path`, trimming surrounding whitespace and ending the file with a single newline\n * the way prettier, biome, and oxfmt all do.\n * Skips the write when the trimmed content is empty, or when the file already holds that content.\n * Creates any missing parent directories automatically.\n * When `sanity` is `true`, re-reads the file after writing and throws if the content does not match.\n *\n * @example\n * ```ts\n * await write('./src/Pet.ts', source) // writes and returns the trimmed content plus a newline\n * await write('./src/Pet.ts', source) // null — file unchanged\n * await write('./src/Pet.ts', ' ') // null — empty content skipped\n * ```\n */\nexport async function write(path: string, data: string, options: WriteOptions = {}): Promise<string | null> {\n const trimmed = data.trim()\n if (trimmed === '') return null\n\n const content = `${trimmed}\\n`\n const resolved = resolve(path)\n let stored = options.stored\n\n if (stored === undefined) {\n if (runtime.isBun) {\n const file = Bun.file(resolved)\n stored = (await file.exists()) ? await file.text() : null\n } else {\n try {\n stored = await readFile(resolved, { encoding: 'utf-8' })\n } catch {\n /* file doesn't exist yet */\n stored = null\n }\n }\n }\n if (matchesStored({ stored: stored ?? '', source: trimmed })) return null\n\n if (runtime.isBun) {\n await Bun.write(resolved, content)\n return content\n }\n\n // Creating the directory up front costs a syscall per file, and every file after the first in a\n // directory pays it for nothing. Write first and only fall back when the directory is missing,\n // which also stays correct when something removed it mid-run.\n try {\n await writeFile(resolved, content, { encoding: 'utf-8' })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n\n await mkdir(dirname(resolved), { recursive: true })\n await writeFile(resolved, content, { encoding: 'utf-8' })\n }\n\n if (options.sanity) {\n const savedData = await readFile(resolved, { encoding: 'utf-8' })\n if (savedData !== content) {\n throw new Error(`Sanity check failed for ${path}\\n\\nData[${data.length}]:\\n${data}\\n\\nSaved[${savedData.length}]:\\n${savedData}\\n`)\n }\n return savedData\n }\n\n return content\n}\n\n/**\n * Recursively removes `path`. Silently succeeds when `path` does not exist.\n *\n * @example\n * ```ts\n * await clean('./dist')\n * ```\n */\nexport async function clean(path: string): Promise<void> {\n return rm(path, { recursive: true, force: true })\n}\n\n/**\n * Converts a filesystem path to use POSIX (`/`) separators.\n *\n * Most of the codebase compares and composes paths as strings (prefix matching, joining for\n * import specifiers, splitting on `/`). On POSIX `path.resolve` already returns `/`-separated\n * paths, but on Windows it returns `\\`-separated paths, which breaks every such comparison.\n *\n * Routing every path that crosses a module boundary through `toPosixPath` keeps the rest of the\n * code platform-agnostic. The conversion runs unconditionally so Windows-specific behavior is\n * exercisable from POSIX CI.\n *\n * @example\n * toPosixPath('C:\\\\repo\\\\src\\\\pet.ts') // 'C:/repo/src/pet.ts'\n */\nexport function toPosixPath(filePath: string): string {\n return filePath.replaceAll('\\\\', '/')\n}\n\n/**\n * Strips the file extension from a path or file name.\n * Only removes the last `.ext` segment when the dot is not part of a directory name.\n *\n * @example\n * trimExtName('petStore.ts') // 'petStore'\n * trimExtName('/src/models/pet.ts') // '/src/models/pet'\n * trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'\n * trimExtName('noExtension') // 'noExtension'\n */\nexport function trimExtName(text: string): string {\n const dotIndex = text.lastIndexOf('.')\n if (dotIndex > 0 && !text.includes('/', dotIndex)) {\n return text.slice(0, dotIndex)\n }\n return text\n}\n\n/**\n * Resolves to `true` when `path` is `parent` itself or nested inside it. Both sides are resolved\n * to absolute paths first, so relative and `..`-containing inputs compare correctly.\n *\n * Guards a destructive or an out-of-tree operation: before wiping an output directory, check that\n * it does not contain the project root, and before loading a path a caller supplied, check that it\n * did not escape the directory it is allowed to read from.\n *\n * @example\n * isPathInside('./src/gen', '.') // true — nested inside the root\n * isPathInside('.', '.') // true — the same directory counts as inside\n * isPathInside('.', './src/gen') // false — the root is not inside its own output\n * isPathInside('../other', '.') // false — escapes the root\n */\nexport function isPathInside(path: string, parent: string): boolean {\n const resolvedPath = resolve(path)\n const resolvedParent = resolve(parent)\n if (resolvedPath === resolvedParent) {\n return true\n }\n\n const rel = relative(resolvedParent, resolvedPath)\n\n return rel !== '' && !rel.startsWith('..') && !isAbsolute(rel)\n}\n","/** A value that may already be resolved or still pending.\n *\n * @example\n * ```ts\n * function load(id: string): PossiblePromise<string> {\n * return cache.get(id) ?? fetchRemote(id)\n * }\n * ```\n */\nexport type PossiblePromise<T> = Promise<T> | T\n\n/** Returns `true` when `result` is a thenable `Promise`.\n *\n * @example\n * ```ts\n * isPromise(Promise.resolve(1)) // true\n * isPromise(42) // false\n * ```\n */\nexport function isPromise<T>(result: PossiblePromise<T>): result is Promise<T> {\n return result !== null && result !== undefined && typeof (result as Record<string, unknown>)['then'] === 'function'\n}\n\ntype Store<TKey, TValue> = {\n has(key: TKey): boolean\n get(key: TKey): TValue | undefined\n set(key: TKey, value: TValue): unknown\n}\n\n/**\n * Wraps `factory` with a keyed cache backed by the provided store.\n *\n * Pass a `WeakMap` for object keys (results are GC-eligible when the key is\n * collected) or a `Map` for primitive keys. For multi-argument functions,\n * nest two `memoize` calls — the outer keyed by the first argument, the\n * inner (created once per outer miss) keyed by the second.\n *\n * Because the cache is owned by the caller, it can be shared, inspected, or\n * cleared independently of the memoized function.\n *\n * @example Single WeakMap key\n * ```ts\n * const cache = new WeakMap<SchemaNode, Set<string>>()\n * const getRefs = memoize(cache, (node) => collectRefs(node))\n * ```\n *\n * @example Single Map key (primitive)\n * ```ts\n * const cache = new Map<string, Resolver>()\n * const getResolver = memoize(cache, (name) => buildResolver(name))\n * ```\n *\n * @example Two-level (object + primitive)\n * ```ts\n * const outer = new WeakMap<Params[], Map<string, Params[]>>()\n * const fn = memoize(outer, (params) => memoize(new Map(), (key) => transform(params, key)))\n * fn(params)('camelcase')\n * ```\n */\nexport function memoize<TKey, TValue>(store: Store<TKey, TValue>, factory: (key: TKey) => TValue): (key: TKey) => TValue {\n return (key: TKey): TValue => {\n if (store.has(key)) return store.get(key)!\n const value = factory(key)\n store.set(key, value)\n return value\n }\n}\n\ntype ParallelOptions<TItem> = {\n /**\n * Items to work through, handed out in order.\n */\n items: ReadonlyArray<TItem>\n /**\n * How many items may be in flight at once.\n */\n limit: number\n /**\n * Runs once per item, with the item's position so a caller can report progress.\n */\n run(item: TItem, index: number): Promise<void>\n}\n\n/**\n * Runs `run` over every item with at most `limit` in flight. Workers share one iterator, so each\n * takes the next item the moment it frees up instead of waiting for a batch to drain.\n *\n * @example\n * ```ts\n * await inParallel({ items: files, limit: 50, run: (file) => storage.writeItem(file.path, file.source) })\n * ```\n */\nexport async function inParallel<TItem>({ items, limit, run }: ParallelOptions<TItem>): Promise<void> {\n const queue = items.entries()\n\n const worker = async (): Promise<void> => {\n for (const [index, item] of queue) await run(item, index)\n }\n\n await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => worker()))\n}\n","/**\n * Calculates elapsed time in milliseconds from a high-resolution `process.hrtime` start time.\n * Rounds to 2 decimal places for sub-millisecond precision without noise.\n *\n * @example\n * ```ts\n * const start = process.hrtime()\n * doWork()\n * getElapsedMs(start) // 42.35\n * ```\n */\nexport function getElapsedMs(hrStart: [number, number]): number {\n const [seconds, nanoseconds] = process.hrtime(hrStart)\n const ms = seconds * 1000 + nanoseconds / 1e6\n return Math.round(ms * 100) / 100\n}\n\n/**\n * Converts a millisecond duration into a human-readable string (`ms`, `s`, or `m s`).\n *\n * @example\n * ```ts\n * formatMs(250) // '250ms'\n * formatMs(1500) // '1.50s'\n * formatMs(90000) // '1m 30.0s'\n * ```\n */\nexport function formatMs(ms: number): string {\n if (ms >= 60000) {\n const mins = Math.floor(ms / 60000)\n const secs = ((ms % 60000) / 1000).toFixed(1)\n return `${mins}m ${secs}s`\n }\n\n if (ms >= 1000) {\n return `${(ms / 1000).toFixed(2)}s`\n }\n return `${Math.round(ms)}ms`\n}\n","","import { existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport { pathToFileURL } from 'node:url'\nimport type { Adapter, Plugin } from '@kubb/core'\nimport { camelCase } from '@internals/utils'\nimport type { JSONKubbConfig, OptionValue } from './protocol.ts'\n\n/**\n * Turns the JSON config Studio sends back into live Kubb objects.\n *\n * A plugin or adapter instance carries closures (`parse`, `getImports`, ...) that cannot survive\n * JSON, so both sides pass options over the wire and the factory is re-invoked here with the merged\n * result. Only `@kubb/plugin-*` packages are resolved this way, so the reinstantiated factory is\n * always one Kubb ships, never an arbitrary module the payload names.\n */\n\ntype PluginFactory = (options: unknown) => Plugin\n\n/**\n * Imports a package, falling back to how the user's project would resolve it.\n *\n * `import()` resolves from this file, so a linked or globally installed Studio (`pnpm link`,\n * `npm i -g`) only sees its own `node_modules` and misses the plugins installed next to the user's\n * config. The retry resolves from `process.cwd()` instead.\n */\nasync function importFromProject(packageName: string): Promise<Record<string, unknown>> {\n try {\n return await import(packageName)\n } catch {\n const require = createRequire(pathToFileURL(`${process.cwd()}/`))\n // `require.resolve` picks the package's `require` condition, so prefer the ESM build sitting\n // next to it. Loading the CJS copy would pull in a second `@kubb/core` instance.\n const resolved = require.resolve(packageName)\n const esm = resolved.replace(/\\.cjs$/, '.js')\n\n return await import(pathToFileURL(esm !== resolved && existsSync(esm) ? esm : resolved).href)\n }\n}\n\n/**\n * Strips the `@kubb/` scope from a plugin package name, matching the `name` convention Kubb\n * plugin factories use internally.\n *\n * @example\n * ```ts\n * toPluginName('@kubb/plugin-ts') // 'plugin-ts'\n * ```\n */\nfunction toPluginName(packageName: string): string {\n return packageName.split('/').pop() ?? packageName\n}\n\n/**\n * Adds the `@kubb/` scope a plugin's package carries but its `name` does not, the inverse of\n * {@link toPluginName}. A name outside the `plugin-` convention is left alone, so a third-party\n * plugin is not reported as one of Kubb's.\n *\n * @example\n * ```ts\n * toPackageName('plugin-ts') // '@kubb/plugin-ts'\n * toPackageName('@acme/my-plugin') // '@acme/my-plugin'\n * ```\n */\nexport function toPackageName(name: string): string {\n return name.startsWith('plugin-') ? `@kubb/${name}` : name\n}\n\n/**\n * Derives the conventional named export for a `@kubb/*` plugin package from its package name.\n *\n * @example\n * ```ts\n * toExportName('@kubb/plugin-react-query') // 'pluginReactQuery'\n * toExportName('@kubb/plugin-ts') // 'pluginTs'\n * ```\n */\nexport function toExportName(packageName: string): string {\n return camelCase(toPluginName(packageName))\n}\n\n/**\n * A `@kubb/plugin-*` package specifier. Nothing else may reach `import()`: only Kubb's own\n * plugins are supported, so a payload naming anything else, a third-party package or a path, is\n * refused before it can execute.\n */\nconst KUBB_PLUGIN_SPECIFIER = /^@kubb\\/plugin-[\\w.-]+$/\n\n/**\n * Whether `name` is a `@kubb/plugin-*` specifier. Exported so `configFile.ts` can refuse the same\n * shape before printing a Studio-supplied plugin name into the config file's source text.\n */\nexport function isKubbPluginSpecifier(name: string): boolean {\n return KUBB_PLUGIN_SPECIFIER.test(name)\n}\n\n/**\n * Dynamically imports a `@kubb/plugin-*` package and returns its factory function.\n *\n * Packages must be pre-installed in the Docker image at build time via the `KUBB_PACKAGES`\n * build ARG, no runtime installation is possible in the distroless container.\n *\n * Resolution order: the camelCase named export the package name implies (e.g. `pluginTs`), then\n * the default export.\n *\n * @throws if the package cannot be imported or exports no callable factory.\n */\nasync function loadPluginFactory(packageName: string): Promise<PluginFactory> {\n if (!isKubbPluginSpecifier(packageName)) {\n throw new Error(`Plugin \"${packageName}\" is not a @kubb/plugin-* package. Kubb Studio only supports Kubb's own plugins.`)\n }\n\n let mod: Record<string, unknown>\n try {\n mod = await importFromProject(packageName)\n } catch (cause) {\n throw new Error(`Plugin \"${packageName}\" could not be loaded. Make sure it is installed: \\`npm install ${packageName}\\``, { cause })\n }\n\n const exportName = toExportName(packageName)\n\n if (typeof mod[exportName] === 'function') return mod[exportName] as PluginFactory\n\n if (typeof mod['default'] === 'function') return mod['default'] as PluginFactory\n\n throw new Error(`Plugin \"${packageName}\" does not export a callable factory. Tried the named export \"${exportName}\" and \"default\".`)\n}\n\n/**\n * Resolves each plugin entry by dynamically importing the `@kubb/plugin-*` package and\n * calling its factory with the provided options.\n *\n * Packages must be pre-installed in the Docker image at build time, use the `KUBB_PACKAGES`\n * build ARG to control which ones are available at runtime.\n *\n * @example\n * ```ts\n * { name: '@kubb/plugin-react-query', options: { output: { path: './hooks' } } }\n * { name: '@kubb/plugin-ts', options: { output: { path: './types' } } }\n * ```\n */\nexport async function resolvePlugins(plugins: NonNullable<JSONKubbConfig['plugins']>): Promise<Array<Plugin>> {\n return Promise.all(\n plugins.map(async ({ name, options }) => {\n const factory = await loadPluginFactory(name)\n return factory(options ?? {}) as Plugin\n }),\n )\n}\n\ntype PackageJSON = {\n version?: string\n}\n\n/** The installed version of each plugin's package, plus the names that could not be resolved. */\nexport async function resolvePeerDependencies(names: Array<string>): Promise<{\n peerDependencies: Record<string, string>\n missingDependencies: Array<string>\n}> {\n const require = createRequire(import.meta.url)\n const uniqueNames = [...new Set(names.map(toPackageName))]\n const peerDependencies: Record<string, string> = {}\n const missingDependencies: Array<string> = []\n\n const versions = await Promise.all(\n uniqueNames.map(async (name) => {\n try {\n const path = require.resolve(`${name}/package.json`)\n const packageJSON = JSON.parse(await readFile(path, 'utf8')) as PackageJSON\n return packageJSON.version\n } catch {\n return undefined\n }\n }),\n )\n\n for (const [index, name] of uniqueNames.entries()) {\n const version = versions[index]\n if (version) {\n peerDependencies[name] = version\n continue\n }\n missingDependencies.push(name)\n }\n\n return { peerDependencies, missingDependencies }\n}\n\n/**\n * Whether `value` is an object literal or a null-prototype object, not an array or class instance.\n */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null) return false\n const prototype = Object.getPrototypeOf(value)\n return prototype === null || prototype === Object.prototype\n}\n\n/**\n * Whether `value` survives a JSON round trip, so it can be printed into a config file as a literal.\n * A function, `undefined`, a non-finite number or a class instance comes back from Studio as a\n * lossy copy, so an edit carrying one is refused rather than written into the user's source.\n */\nexport function isOptionValue(value: unknown): value is OptionValue {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return true\n if (typeof value === 'number') return Number.isFinite(value)\n if (Array.isArray(value)) return value.every(isOptionValue)\n if (isPlainObject(value)) return Object.values(value).every(isOptionValue)\n\n return false\n}\n\n/**\n * Deep-merges Studio's options over the disk options, with Studio taking priority, except where the\n * disk value cannot survive JSON. Studio only ever saw a lossy copy of such a value, so the disk\n * value is kept rather than replaced by what Studio echoes back. Plain objects merge key by key, so\n * Studio can still change a literal that sits next to a function (e.g. `group.type` beside `group.name`).\n *\n * @example\n * ```ts\n * mergeOptions({ macros: [camelCaseMacro], syntaxType: 'type' }, { macros: [{ name: 'camelCase' }], syntaxType: 'interface' })\n * // { macros: [camelCaseMacro], syntaxType: 'interface' }\n * ```\n */\nexport function mergeOptions(disk: Record<string, unknown>, studio: Record<string, unknown>): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...disk }\n\n for (const [key, value] of Object.entries(studio)) {\n const current = disk[key]\n\n if (isPlainObject(current) && isPlainObject(value)) {\n merged[key] = mergeOptions(current, value)\n continue\n }\n if (current !== undefined && !isOptionValue(current)) continue\n\n merged[key] = value\n }\n\n return merged\n}\n\n/**\n * Merges studio plugin options with disk config plugins.\n * Studio takes priority: options from studio win over disk (except values only the disk config\n * can express, see {@link mergeOptions}), and a plugin Studio explicitly\n * disabled is dropped even when the disk config still lists it. Disk plugins without a studio\n * counterpart are kept as-is. Studio plugins not present on disk are appended.\n *\n * For plugins present in both configs, the plugin is re-instantiated with merged options\n * so that all internal closures correctly reference the merged values.\n */\nexport async function mergePlugins(\n diskPlugins: Array<Plugin> | undefined,\n studioPlugins: JSONKubbConfig['plugins'] | undefined,\n): Promise<Array<Plugin> | undefined> {\n // Matched on the package's base name rather than by instantiating first. Every Kubb plugin\n // factory returns exactly that (`@kubb/plugin-ts` → `plugin-ts`), enforced by the `satisfies` on\n // each factory's name.\n const disabledNames = new Set((studioPlugins ?? []).filter((entry) => entry.disabled).map((entry) => toPluginName(entry.name)))\n const activeDiskPlugins = disabledNames.size ? diskPlugins?.filter((plugin) => !disabledNames.has(plugin.name)) : diskPlugins\n const activeStudioPlugins = studioPlugins?.filter((entry) => !entry.disabled)\n\n if (!activeDiskPlugins && !activeStudioPlugins?.length) return undefined\n if (!activeStudioPlugins?.length) return activeDiskPlugins\n\n if (!activeDiskPlugins) return resolvePlugins(activeStudioPlugins)\n\n const studioEntryByName = new Map(activeStudioPlugins.map((entry) => [toPluginName(entry.name), entry] as const))\n const diskNames = new Set(activeDiskPlugins.map((plugin) => plugin.name))\n\n // Each plugin is instantiated once, with its final options. Resolving the whole payload first\n // just to read the names would build every overlapping plugin twice and discard the first.\n const merged = await Promise.all(\n activeDiskPlugins.map(async (diskPlugin) => {\n const studioEntry = studioEntryByName.get(diskPlugin.name)\n if (!studioEntry) return diskPlugin\n\n // Disk as base, studio overrides, then re-instantiate so the plugin's closures reference the\n // merged values. A plugin that never sets `options` (e.g. `@kubb/plugin-barrel`) leaves\n // `diskPlugin.options` undefined.\n const options = mergeOptions((diskPlugin.options as Record<string, unknown>) ?? {}, (studioEntry.options as Record<string, unknown>) ?? {})\n const [resolved] = await resolvePlugins([{ name: studioEntry.name, options }])\n\n return resolved ?? diskPlugin\n }),\n )\n\n const studioOnly = activeStudioPlugins.filter((entry) => !diskNames.has(toPluginName(entry.name)))\n\n return [...merged, ...(await resolvePlugins(studioOnly))]\n}\n\n/**\n * Merges Studio-provided adapter option overrides into the disk config's adapter.\n *\n * Adapter instances carry live functions (`parse`, `getImports`, ...) that can't survive\n * JSON serialization over the WebSocket, so `studioOptions` is treated as an options patch\n * rather than a replacement adapter. Re-invokes the same `@kubb/adapter-<name>` factory the\n * disk config used, with the merged options, so the resulting instance has fresh closures\n * over the merged values instead of a plain object missing `parse`.\n */\nexport async function mergeAdapter(diskAdapter: Adapter | undefined, studioOptions: object | undefined): Promise<Adapter | undefined> {\n if (!studioOptions || !diskAdapter) {\n return diskAdapter\n }\n\n const packageName = `@kubb/adapter-${diskAdapter.name}`\n const mod = await importFromProject(packageName)\n const factory = mod[toExportName(packageName)]\n\n if (typeof factory !== 'function') {\n return diskAdapter\n }\n\n const mergedOptions = mergeOptions((diskAdapter.options as Record<string, unknown>) ?? {}, studioOptions as Record<string, unknown>)\n\n return factory(mergedOptions) as Adapter\n}\n","import { writeFile } from 'node:fs/promises'\nimport { read } from '@internals/utils'\nimport { builders, detectCodeFormat, generateCode, parseModule } from 'magicast'\nimport type { ASTNode, ProxifiedModule } from 'magicast'\nimport type { ConfigEdit, ConfigEditOutcome, ConfigFileView, ConfigRef, ConfigView, OptionValue, PluginView } from './protocol.ts'\nimport { isKubbPluginSpecifier, isOptionValue, toExportName } from './resolveConfig.ts'\n\n/**\n * A valid JavaScript identifier, so an import name can only ever print as `import { name } from`,\n * never as source that breaks out of the import statement.\n */\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/\n\n/**\n * A config or plugin options object literal in the file.\n */\ntype ObjectNode = Extract<ASTNode, { type: 'ObjectExpression' }>\n\n/**\n * A `pluginX(...)` call in a config's `plugins` array.\n */\ntype CallNode = Extract<ASTNode, { type: 'CallExpression' }>\n\n/**\n * A `key: value` entry of an object literal.\n */\ntype ObjectPropertyNode = Extract<ASTNode, { type: 'ObjectProperty' }>\n\n/**\n * `key: value` as an object literal property, in the file's quote and key style.\n *\n * Uses magicast's literal builder for the key/value nodes, then wraps them as a Babel\n * `ObjectProperty`, the type the rest of this file reads.\n */\nfunction literalProperty({ key, value }: { key: string; value: OptionValue }): ObjectPropertyNode {\n const built = (builders.literal({ [key]: value }) as unknown as ObjectNode).properties[0] as unknown as ObjectPropertyNode\n return { type: 'ObjectProperty', key: built.key, value: built.value, computed: false, shorthand: false }\n}\n\n/**\n * What `applyConfigEdits` did to a config file.\n */\ntype ApplyResult = {\n /**\n * The file's text after every applicable edit, unchanged from the input when none applied.\n */\n source: string\n /**\n * One entry per edit, in the order they were given.\n */\n outcomes: Array<ConfigEditOutcome>\n /**\n * Whether `source` differs from the input.\n */\n changed: boolean\n}\n\n/**\n * Marks the comment block a `disable-plugin` leaves behind, so `enable-plugin` can find its way\n * back to the exact lines it commented out. Carries the block's line count, so `enable-plugin`\n * restores exactly those lines instead of scanning forward through whatever comments follow.\n */\nconst DISABLED_MARKER = 'kubb:disabled'\n\n/**\n * The plugin and comment-block length a marker line names, when `line` is one.\n */\nfunction parseMarker(line: string): { plugin: string; lineCount: number } | undefined {\n const trimmed = line.trim()\n if (!trimmed.startsWith(`// ${DISABLED_MARKER} `)) {\n return undefined\n }\n\n const match = trimmed.slice(`// ${DISABLED_MARKER} `.length).match(/^(.+)\\s+(\\d+)$/)\n return match ? { plugin: match[1]!, lineCount: Number(match[2]) } : undefined\n}\n\n/**\n * Steps through a config's wrappers to the object literal underneath: a `satisfies`/`as`\n * assertion, a `() => ...` factory, or a factory whose block body returns the config.\n */\nfunction unwrap(node: ASTNode | null | undefined): ASTNode | undefined {\n if (!node) {\n return undefined\n }\n if (node.type === 'TSAsExpression' || node.type === 'TSSatisfiesExpression') {\n return unwrap(node.expression)\n }\n if (node.type !== 'ArrowFunctionExpression' && node.type !== 'FunctionExpression') {\n return node\n }\n if (node.body.type !== 'BlockStatement') {\n return unwrap(node.body)\n }\n\n const returned = node.body.body.find((statement): statement is Extract<ASTNode, { type: 'ReturnStatement' }> => statement.type === 'ReturnStatement')\n return unwrap(returned?.argument)\n}\n\n/**\n * Every config object in `export default defineConfig(...)`, or why the file is unmanaged.\n *\n * An array export gets one entry per element, matching {@link ConfigRef}'s numeric index.\n *\n * Walks the parsed AST rather than magicast's proxies, which throw on node types they cannot\n * cast, most of what an unmanaged config file is made of.\n */\nfunction findConfigs(mod: ProxifiedModule): { configs: Array<ObjectNode> } | { reason: string } {\n const body = mod.$ast.type === 'Program' ? mod.$ast.body : []\n const declaration = body.find((node): node is Extract<ASTNode, { type: 'ExportDefaultDeclaration' }> => node.type === 'ExportDefaultDeclaration')\n\n const exported = unwrap(declaration?.declaration)\n if (!exported) {\n return { reason: 'no default export found' }\n }\n if (exported.type !== 'CallExpression' || exported.callee.type !== 'Identifier' || exported.callee.name !== 'defineConfig') {\n return { reason: 'default export is not a defineConfig(...) call' }\n }\n\n const argument = unwrap(exported.arguments[0])\n if (!argument) {\n return { reason: 'defineConfig(...) was called without a config' }\n }\n if (argument.type === 'ArrayExpression') {\n const configs: Array<ObjectNode> = []\n\n for (const element of argument.elements) {\n const entry = unwrap(element)\n if (entry?.type !== 'ObjectExpression') {\n return { reason: 'config is not an object literal' }\n }\n configs.push(entry)\n }\n return { configs }\n }\n if (argument.type !== 'ObjectExpression') {\n return { reason: 'config is not an object literal' }\n }\n return { configs: [argument] }\n}\n\n/**\n * The config entry an edit names, defaulting to the first when it names none.\n */\nfunction selectConfig(configs: Array<ObjectNode>, ref: ConfigRef | undefined): ObjectNode | undefined {\n if (ref === undefined) {\n return configs[0]\n }\n if (typeof ref === 'number') {\n return configs[ref]\n }\n return configs.find((config) => configName(config) === ref)\n}\n\nfunction configName(config: ObjectNode): string | undefined {\n const name = property(config, 'name')\n return name?.type === 'StringLiteral' ? name.value : undefined\n}\n\n/**\n * The name of an object literal property, for the two key shapes a config uses: `key: value` and\n * `'key': value`. `undefined` for a computed key, which the patcher never touches.\n */\nfunction propertyKey(entry: Extract<ASTNode, { type: 'ObjectProperty' }>): string | undefined {\n if (entry.key.type === 'Identifier') {\n return entry.key.name\n }\n if (entry.key.type === 'StringLiteral') {\n return entry.key.value\n }\n return undefined\n}\n\n/**\n * The index of an object literal's own property named `key`, `-1` when it has none.\n */\nfunction entryIndex({ node, key }: { node: ObjectNode; key: string }): number {\n return node.properties.findIndex((entry) => entry.type === 'ObjectProperty' && propertyKey(entry) === key)\n}\n\n/**\n * The value node of an object literal's own property.\n */\nfunction property(node: ObjectNode, key: string): ASTNode | undefined {\n const index = entryIndex({ node, key })\n return index === -1 ? undefined : (node.properties[index] as ObjectPropertyNode).value\n}\n\n/**\n * Writes `key: value` on an object literal, replacing the value when the property is already there.\n *\n * An existing property has its value swapped in place rather than being replaced whole, so recast\n * reprints only that value and leaves the object's own layout alone.\n */\nfunction setProperty({ node, key, value }: { node: ObjectNode; key: string; value: OptionValue }): void {\n const entry = literalProperty({ key, value })\n const index = entryIndex({ node, key })\n\n if (index === -1) {\n node.properties.push(entry)\n return\n }\n ;(node.properties[index] as ObjectPropertyNode).value = entry.value\n}\n\n/**\n * Drops `key` from an object literal.\n */\nfunction removeProperty({ node, key }: { node: ObjectNode; key: string }): void {\n const index = entryIndex({ node, key })\n if (index !== -1) {\n node.properties.splice(index, 1)\n }\n}\n\n/**\n * Reads a literal node's value: a primitive, or an object/array built only from primitives.\n * `undefined` for anything else, so a caller can use this both to read a value and to check\n * whether a node is a literal at all.\n */\nfunction readLiteral(node: ASTNode | undefined): OptionValue | undefined {\n if (!node) {\n return undefined\n }\n if (node.type === 'StringLiteral' || node.type === 'NumericLiteral' || node.type === 'BooleanLiteral') {\n return node.value\n }\n if (node.type === 'NullLiteral') {\n return null\n }\n if (node.type === 'TemplateLiteral') {\n return node.expressions.length === 0 ? (node.quasis[0]?.value.cooked ?? '') : undefined\n }\n if (node.type === 'UnaryExpression') {\n const value = readLiteral(node.argument)\n if (typeof value !== 'number') {\n return undefined\n }\n if (node.operator === '-') {\n return -value\n }\n if (node.operator === '+') {\n return value\n }\n return undefined\n }\n if (node.type === 'ArrayExpression') {\n const values = node.elements.map((element) => (element ? readLiteral(element) : undefined))\n return values.every((value) => value !== undefined) ? values : undefined\n }\n if (node.type === 'ObjectExpression') {\n const entries: Record<string, OptionValue> = {}\n for (const entry of node.properties) {\n if (entry.type !== 'ObjectProperty') {\n return undefined\n }\n const key = propertyKey(entry)\n const value = readLiteral(entry.value)\n if (key === undefined || value === undefined) {\n return undefined\n }\n entries[key] = value\n }\n return entries\n }\n return undefined\n}\n\n/**\n * Maps a factory identifier in the file back to the module it was imported from.\n */\nfunction importedFrom(mod: ProxifiedModule): Map<string, string> {\n return new Map(mod.imports.$items.map((item) => [item.local, item.from]))\n}\n\n/**\n * Every `pluginX(...)` element of a config's plugins array that resolves to an import.\n */\nfunction pluginCalls(mod: ProxifiedModule, config: ObjectNode): Array<{ importName: string; packageName: string; call: CallNode }> {\n const plugins = property(config, 'plugins')\n if (plugins?.type !== 'ArrayExpression') {\n return []\n }\n\n const imports = importedFrom(mod)\n\n return plugins.elements.flatMap((element) => {\n if (element?.type !== 'CallExpression' || element.callee.type !== 'Identifier') {\n return []\n }\n const packageName = imports.get(element.callee.name)\n return packageName ? [{ importName: element.callee.name, packageName, call: element }] : []\n })\n}\n\n/**\n * Plugins a previous `disable-plugin` commented out of this config, keyed by package name.\n *\n * Read from the marker lines rather than the AST, since a commented-out call is no longer a node.\n */\nfunction disabledMarkers(source: string): Array<{ packageName: string; line: number }> {\n return source.split('\\n').flatMap((line, index) => {\n const marker = parseMarker(line)\n return marker ? [{ packageName: marker.plugin, line: index + 1 }] : []\n })\n}\n\n/**\n * Reads which plugins the file declares and which of their options Studio may write.\n *\n * @example\n * ```ts\n * const view = readConfig(await readFile('kubb.config.ts', 'utf8'))\n * if (view.managed) {\n * view.configs.forEach((config) => console.log(config.name, config.plugins.length))\n * }\n * ```\n */\nexport function readConfig(source: string): ConfigFileView {\n const parsed = parseConfigs(source)\n if ('reason' in parsed) {\n return { managed: false, reason: parsed.reason }\n }\n\n const { mod, configs } = parsed\n const importNames = new Map([...importedFrom(mod)].map(([local, from]) => [from, local]))\n const disabled = disabledMarkers(source)\n\n return {\n managed: true,\n configs: configs.map((config): ConfigView => {\n const plugins = pluginCalls(mod, config).map(({ importName, packageName, call }): PluginView => {\n const entries: PluginView['options'] = {}\n const options = call.arguments[0]\n\n if (options?.type === 'ObjectExpression') {\n for (const entry of options.properties) {\n if (entry.type !== 'ObjectProperty') {\n continue\n }\n const key = propertyKey(entry)\n if (key === undefined) {\n continue\n }\n const value = readLiteral(entry.value)\n entries[key] = value === undefined ? { literal: false } : { literal: true, value }\n }\n }\n return { importName, packageName, options: entries }\n })\n\n const start = config.loc?.start.line ?? 0\n const end = config.loc?.end.line ?? Number.POSITIVE_INFINITY\n\n for (const { packageName } of disabled.filter((entry) => entry.line >= start && entry.line <= end)) {\n plugins.push({\n importName: importNames.get(packageName) ?? toExportName(packageName),\n packageName,\n options: {},\n disabled: true,\n })\n }\n\n return { name: configName(config), plugins }\n }),\n }\n}\n\n/**\n * The options object of a plugin call, when it was called with one.\n */\nfunction getOptions(call: CallNode): ObjectNode | undefined {\n const options = call.arguments[0]\n return options?.type === 'ObjectExpression' ? options : undefined\n}\n\n/**\n * The options object of a plugin call, creating an empty one when the plugin was called bare.\n */\nfunction ensureOptions(call: CallNode): ObjectNode | undefined {\n if (call.arguments.length === 0) {\n call.arguments.push({ type: 'ObjectExpression', properties: [] })\n }\n return getOptions(call)\n}\n\n/**\n * Walks `path` down to the object holding its last key, descending only through object literals.\n */\nfunction optionParent(options: ObjectNode, path: Array<string>): { object: ObjectNode; key: string } | { reason: string } {\n let object = options\n\n for (const [index, key] of path.entries()) {\n if (index === path.length - 1) {\n return { object, key }\n }\n\n if (property(object, key) === undefined) {\n setProperty({ node: object, key, value: {} })\n }\n\n const next = property(object, key)\n if (next?.type !== 'ObjectExpression') {\n return { reason: `${key} is not an object, so ${path.join('.')} cannot be reached` }\n }\n object = next\n }\n return { reason: 'no option path given' }\n}\n\n/**\n * Writes `value` at `path` inside a plugin call's options, creating the options object and any\n * intermediate object along the path as needed. Refuses when the current value at `path` is\n * something other than a literal, so an option customized in code is never overwritten.\n */\nfunction applySet(call: CallNode, path: Array<string>, value: unknown): string | undefined {\n if (!isOptionValue(value)) {\n return 'the value is not a literal that can be written to a config file'\n }\n\n const options = ensureOptions(call)\n if (!options) {\n return 'the plugin was not called with an object literal'\n }\n\n const target = optionParent(options, path)\n if ('reason' in target) {\n return target.reason\n }\n\n const current = property(target.object, target.key)\n if (current !== undefined && readLiteral(current) === undefined) {\n return `${path.join('.')} is customized in code`\n }\n\n setProperty({ node: target.object, key: target.key, value })\n return undefined\n}\n\n/**\n * Deletes the property at `path` inside a plugin call's options, falling the plugin back to its\n * default for that option. Refuses when the value at `path` is not a literal, for the same reason\n * `applySet` does.\n */\nfunction applyRemove(call: CallNode, path: Array<string>): string | undefined {\n const options = getOptions(call)\n if (!options) {\n return 'the plugin has no options to remove'\n }\n\n const target = optionParent(options, path)\n if ('reason' in target) {\n return target.reason\n }\n\n const current = property(target.object, target.key)\n if (current === undefined) {\n return `${path.join('.')} is not set`\n }\n if (readLiteral(current) === undefined) {\n return `${path.join('.')} is customized in code`\n }\n\n removeProperty({ node: target.object, key: target.key })\n return undefined\n}\n\n/**\n * Outcome of `applyAddPlugin`. `addImport` is set when the new plugin call needs an import line\n * the caller must still insert; absent when the import was already there.\n */\ntype AddPluginResult = { reason: string } | { noop: true } | { addImport?: { importName: string; moduleSpecifier: string } }\n\n/**\n * Adds a `pluginX(...)` call to a config's plugins array. Replaying the same add is a no-op, while\n * an import name collision with an unrelated package remains an error.\n */\nfunction applyAddPlugin(mod: ProxifiedModule, config: ObjectNode, edit: Extract<ConfigEdit, { operation: 'add-plugin' }>): AddPluginResult {\n if (!isKubbPluginSpecifier(edit.plugin)) {\n return { reason: `\"${edit.plugin}\" is not a @kubb/plugin-* package` }\n }\n\n const importName = edit.importName ?? toExportName(edit.plugin)\n if (!IDENTIFIER.test(importName)) {\n return { reason: `\"${importName}\" is not a valid import name` }\n }\n\n if (pluginCalls(mod, config).some((plugin) => plugin.packageName === edit.plugin)) {\n return { noop: true }\n }\n\n const taken = importedFrom(mod).get(importName)\n if (taken && taken !== edit.plugin) {\n return { reason: `${importName} is already imported from ${taken}` }\n }\n\n const options = edit.options ?? {}\n if (!isOptionValue(options)) {\n return { reason: 'the options are not literals that can be written to a config file' }\n }\n\n const plugins = property(config, 'plugins')\n if (plugins?.type !== 'ArrayExpression') {\n return { reason: 'plugins is not an array literal' }\n }\n\n const call = Object.keys(options).length ? builders.functionCall(importName, options) : builders.functionCall(importName)\n plugins.elements.push(call.$ast as CallNode)\n\n return taken ? {} : { addImport: { importName, moduleSpecifier: edit.plugin } }\n}\n\n/**\n * Comments out a plugin call in place, keeping its options on disk so `enable-plugin` can restore\n * them exactly. Operates on `source` text rather than the AST: a commented-out call is no longer a\n * node magicast can address, and the surrounding array must not reflow when its element count\n * never actually changes.\n */\nfunction disablePlugin(source: string, mod: ProxifiedModule, config: ObjectNode, plugin: string): { source: string } | { reason: string } {\n const target = pluginCalls(mod, config).find((entry) => entry.packageName === plugin)\n if (!target) {\n return { reason: `${plugin} is not in the plugins array` }\n }\n\n const loc = target.call.loc\n if (!loc?.start || !loc.end) {\n return { reason: `${plugin} has no source location to comment out` }\n }\n\n const lines = source.split('\\n')\n const from = loc.start.line - 1\n const to = loc.end.line - 1\n const firstLine = lines[from] ?? ''\n const lastLine = lines[to] ?? ''\n\n // Only safe to comment out when the call sits alone on its lines: anything else sharing the\n // first line before it, or the last line after it besides a trailing comma, would be swallowed\n // into the comment along with the call, corrupting the file.\n if (firstLine.slice(0, loc.start.column).trim() !== '' || !/^,?\\s*$/.test(lastLine.slice(loc.end.column))) {\n return { reason: `${plugin} shares a line with other code, so it cannot be commented out safely` }\n }\n\n const indent = firstLine.match(/^\\s*/)?.[0] ?? ''\n const commented = lines.slice(from, to + 1).map((line) => (line.trim() ? `${indent}// ${line.slice(indent.length)}` : indent ? `${indent}//` : '//'))\n lines.splice(from, to - from + 1, `${indent}// ${DISABLED_MARKER} ${plugin} ${commented.length}`, ...commented)\n\n return { source: lines.join('\\n') }\n}\n\n/**\n * Uncomments the block a previous `disable-plugin` left behind for `plugin`.\n */\nfunction enablePlugin(source: string, plugin: string): { source: string } | { reason: string } {\n const lines = source.split('\\n')\n\n for (const [index, line] of lines.entries()) {\n const marker = parseMarker(line)\n if (marker?.plugin !== plugin) {\n continue\n }\n\n // Bounded by the marker's own line count rather than scanning for trailing `//` lines, so a\n // comment or another disabled block right after this one is left untouched.\n const end = index + 1 + marker.lineCount\n const restored = lines.slice(index + 1, end).map((commented) => commented.replace(/^(\\s*)\\/\\/ ?/, '$1'))\n lines.splice(index, end - index, ...restored)\n\n return { source: lines.join('\\n') }\n }\n\n return { reason: `${plugin} is not disabled` }\n}\n\n/**\n * Parses `source` and finds the config entries it exports.\n */\nfunction parseConfigs(source: string): { mod: ProxifiedModule; configs: Array<ObjectNode> } | { reason: string } {\n let mod: ProxifiedModule\n try {\n mod = parseModule(source)\n } catch {\n return { reason: 'the config file could not be parsed' }\n }\n\n const found = findConfigs(mod)\n return 'reason' in found ? found : { mod, configs: found.configs }\n}\n\n/**\n * Re-parses `source` and resolves the config entry an edit targets. Every edit re-parses rather\n * than sharing one module across the batch, since the disable/enable edits rewrite `source` as\n * text and would otherwise leave the others working from a stale tree.\n */\nfunction parseTarget(source: string, ref: ConfigRef | undefined): { mod: ProxifiedModule; config: ObjectNode } | { reason: string } {\n const parsed = parseConfigs(source)\n if ('reason' in parsed) {\n return parsed\n }\n\n const config = selectConfig(parsed.configs, ref)\n if (!config) {\n return { reason: `no config entry found for ${JSON.stringify(ref)}` }\n }\n\n return { mod: parsed.mod, config }\n}\n\n/**\n * Applies edits to a `kubb.config.ts` in place. Every node the edits do not touch keeps its\n * original text, so comments, formatting, and hand-written code around the config survive.\n *\n * Edits are independent: one that cannot be applied is reported in `outcomes` and the rest still run.\n *\n * @example\n * ```ts\n * const { source, outcomes } = applyConfigEdits(current, [\n * { operation: 'set', plugin: '@kubb/plugin-ts', path: ['enum', 'type'], value: 'enum' },\n * ])\n * ```\n *\n * @note recast always reprints a semicolon on a reprinted statement, so editing a block-body\n * `defineConfig` in a semicolon-free file adds one to the `return` line. This is a known gap.\n * Strip it when `detectCodeFormat` reports `useSemi: false`, if it turns out to matter in practice.\n */\nexport function applyConfigEdits(source: string, edits: Array<ConfigEdit>): ApplyResult {\n let current = source\n const format = detectCodeFormat(source)\n const endsWithNewline = source.endsWith('\\n')\n\n const outcomes = edits.map((edit): ConfigEditOutcome => {\n const target = parseTarget(current, edit.config)\n if ('reason' in target) {\n return { edit, applied: false, reason: target.reason }\n }\n const { mod, config } = target\n\n if (edit.operation === 'disable-plugin' || edit.operation === 'enable-plugin') {\n const result = edit.operation === 'disable-plugin' ? disablePlugin(current, mod, config, edit.plugin) : enablePlugin(current, edit.plugin)\n if ('reason' in result) {\n return { edit, applied: false, reason: result.reason }\n }\n current = result.source\n return { edit, applied: true }\n }\n\n if (edit.operation === 'add-plugin') {\n const result = applyAddPlugin(mod, config, edit)\n if ('reason' in result) {\n return { edit, applied: false, reason: result.reason }\n }\n if ('noop' in result) {\n return { edit, applied: true }\n }\n const afterLine = lastImportEndLine(mod)\n let next = generateCode(mod, { format }).code\n if (result.addImport) {\n next = insertImportLine({ source: next, afterLine, ...result.addImport })\n }\n current = withTrailingNewline(next, endsWithNewline)\n return { edit, applied: true }\n }\n\n const pluginCall = pluginCalls(mod, config).find((plugin) => plugin.packageName === edit.plugin)\n if (!pluginCall) {\n return { edit, applied: false, reason: `${edit.plugin} is not in the plugins array` }\n }\n\n const reason = edit.operation === 'set' ? applySet(pluginCall.call, edit.path, edit.value) : applyRemove(pluginCall.call, edit.path)\n if (!reason) {\n current = withTrailingNewline(generateCode(mod, { format }).code, endsWithNewline)\n }\n return { edit, applied: !reason, reason }\n })\n\n return { source: current, outcomes, changed: current !== source }\n}\n\nexport async function writeConfigEdits({ filePath, edits }: { filePath: string; edits: Array<ConfigEdit> }): Promise<ApplyResult> {\n const current = await read(filePath)\n const result = applyConfigEdits(current, edits)\n if (result.changed) await writeFile(filePath, result.source, 'utf-8')\n return result\n}\n\n/**\n * The 1-based line where the file's last import declaration ends, or `0` when it has none. Read\n * off the parsed module, so a multi-line `import {\\n x,\\n} from '...'` reports its closing line\n * rather than the `import` keyword.\n */\nfunction lastImportEndLine(mod: ProxifiedModule): number {\n const body = mod.$ast.type === 'Program' ? mod.$ast.body : []\n\n return body.filter((node) => node.type === 'ImportDeclaration').at(-1)?.loc?.end.line ?? 0\n}\n\n/**\n * Writes an import after the last one already in the file, matching its quote style and whether it\n * ends in a semicolon. `afterLine` is where that last import ends, `0` for a file with none.\n *\n * Written as plain text rather than through magicast's import builder, which prints a brand-new\n * import declaration with its own default spacing and a semicolon regardless of `format`, since\n * that formatting only governs nodes recast can diff against the original source.\n */\nfunction insertImportLine({\n source,\n importName,\n moduleSpecifier,\n afterLine,\n}: {\n source: string\n importName: string\n moduleSpecifier: string\n afterLine: number\n}): string {\n const lines = source.split('\\n')\n\n const lastImportLine = afterLine > 0 ? lines[afterLine - 1] : undefined\n const quote = lastImportLine?.includes(`\"`) ? `\"` : `'`\n const semicolon = lastImportLine?.trimEnd().endsWith(';') ? ';' : ''\n const line = `import { ${importName} } from ${quote}${moduleSpecifier}${quote}${semicolon}`\n\n lines.splice(afterLine, 0, ...(afterLine > 0 ? [line] : [line, '']))\n\n return lines.join('\\n')\n}\n\n/**\n * `generateCode` always drops the file's trailing newline. Restore it when the input had one.\n */\nfunction withTrailingNewline(code: string, hadTrailingNewline: boolean): string {\n if (!hadTrailingNewline || code.endsWith('\\n')) {\n return code\n }\n return `${code}\\n`\n}\n","import { createHash } from 'node:crypto'\nimport { isAbsolute, relative, resolve, sep } from 'node:path'\nimport process from 'node:process'\nimport { inParallel } from '@internals/utils'\nimport { type Config, createKubb, type Diagnostic, Diagnostics, fsStorage, type Hookable, type KubbHooks, type Storage } from '@kubb/core'\nimport type { FilePage, FileSource, ReadFilesResult } from './protocol.ts'\n\nconst READ_CONCURRENCY = 50\nconst MB = 1024 * 1024\nconst INDEX_KEY = 'studio/generations.json'\n\n/**\n * Files a run produced, or the output directory held, keyed by path relative to `root`.\n */\nexport type SourceFiles = { storage: Storage; root: string; paths: Set<string> }\n\n/**\n * The path form {@link SourceFiles} keys on: relative to `root`, with forward slashes.\n */\nexport function relativeStoragePath({ root, filePath }: { root: string; filePath: string }): string {\n return (isAbsolute(filePath) ? relative(resolve(root), filePath) : filePath).replaceAll('\\\\', '/')\n}\n\n/**\n * A set as kept in the store.\n */\ntype KeptSet = {\n /**\n * The paths a read is checked against. Empty when the set was too large to keep its content.\n */\n paths: Array<string>\n hashes: Record<string, string>\n bytes: number\n}\n\ntype KeptGeneration = {\n jobId: string\n /** When the store took it, in epoch milliseconds. Absent on an index written before it existed. */\n keptAt?: number\n output: KeptSet\n disk?: KeptSet\n}\n\n/**\n * The content fingerprint Studio compares snapshots by. Agent runs and CI uploads must agree on it.\n */\nexport const hashOf = (content: string) => createHash('sha1').update(content).digest('hex').slice(0, 16)\n\nconst totalBytes = (entries: Array<KeptGeneration>) => entries.reduce((sum, { output, disk }) => sum + output.bytes + (disk?.bytes ?? 0), 0)\n\nfunction positiveNumber(value: string | undefined): number | undefined {\n const parsed = Number(value)\n return value && Number.isFinite(parsed) && parsed > 0 ? parsed : undefined\n}\n\n/**\n * How many generations an agent keeps and how large they may get, read from\n * `KUBB_AGENT_MAX_GENERATIONS`, `KUBB_AGENT_MAX_GENERATIONS_MB` and `KUBB_AGENT_MAX_SNAPSHOT_MB`.\n * An unset or invalid value keeps the default.\n */\nexport function resolveGenerationLimits(): { maxCount: number; maxMb: number; maxSnapshotMb: number } {\n return {\n maxCount: Math.max(1, Math.floor(positiveNumber(process.env.KUBB_AGENT_MAX_GENERATIONS) ?? 8)),\n maxMb: positiveNumber(process.env.KUBB_AGENT_MAX_GENERATIONS_MB) ?? 100,\n maxSnapshotMb: positiveNumber(process.env.KUBB_AGENT_MAX_SNAPSHOT_MB) ?? 50,\n }\n}\n\n/**\n * Folds error-severity diagnostics into one thrown error so logs name the failing plugin or pass.\n */\nfunction generationFailure(diagnostics: ReadonlyArray<Diagnostic>): Error {\n const reasons = diagnostics\n .filter(Diagnostics.isProblem)\n .filter((diagnostic) => diagnostic.severity === 'error')\n .map((diagnostic) => (diagnostic.plugin ? `${diagnostic.plugin}: ${diagnostic.message}` : diagnostic.message))\n\n if (!reasons.length) return new Error('Generation failed')\n\n return new Error(`Generation failed: ${reasons.length} error${reasons.length === 1 ? '' : 's'}: ${reasons.join('; ')}`)\n}\n\n/**\n * Runs one generation and returns the files it produced. The formatter, the linter, and\n * `output.postGenerate` only run with `allowExec`. Throws when any plugin reports an error.\n */\nexport async function generate({\n config,\n hooks,\n signal,\n allowExec,\n}: {\n config: Config\n hooks?: Hookable<KubbHooks>\n signal?: AbortSignal\n allowExec: boolean\n}): Promise<SourceFiles> {\n const output = allowExec ? config.output : { ...config.output, format: false as const, lint: false as const, postGenerate: [] }\n const result = await createKubb({ ...config, output }, { hooks, signal }).generate()\n if (!result.success) throw generationFailure(result.diagnostics)\n\n return {\n storage: config.storage,\n root: config.root,\n paths: new Set(result.files.map((file) => relativeStoragePath({ root: config.root, filePath: file.path }))),\n }\n}\n\n/**\n * What the output directory holds on disk before a run. `undefined` when `outputPath` is not a real\n * subdirectory of `root` (listing the root would take in every source file) or holds more than `maxFiles`.\n */\nexport async function listDisk({ root, outputPath, maxFiles }: { root: string; outputPath: string; maxFiles: number }): Promise<SourceFiles | undefined> {\n const outputDir = resolve(root, outputPath)\n const fromRoot = relative(resolve(root), outputDir)\n if (!fromRoot || fromRoot.startsWith('..') || fromRoot.startsWith(sep)) return undefined\n\n const storage = fsStorage()\n const keys = await storage.readKeys(outputDir)\n if (keys.length > maxFiles) return undefined\n\n const paths = keys\n .filter((key) => !key.split('/').includes('node_modules'))\n .map((key) => relative(resolve(root), resolve(outputDir, key)).replaceAll('\\\\', '/'))\n return { storage, root, paths: new Set(paths) }\n}\n\n/**\n * Keeps recent generations by job id in `storage`, with an index next to them so a store on disk\n * survives a restart. A generation is only ever looked up by its job id, so on a pooled sandbox one\n * tenant never reaches another's output. The oldest go past `maxCount` or `maxMb`, but the newest\n * always stays.\n */\nexport function createGenerationStore({\n storage,\n maxCount,\n maxMb,\n ttlMs,\n now = Date.now,\n}: {\n storage: Storage\n maxCount: number\n maxMb: number\n /** How long a generation stays readable. Unset, it stays until count or size pushes it out. */\n ttlMs?: number\n now?: () => number\n}) {\n let index: Array<KeptGeneration> | undefined\n\n // An entry from before `keptAt` existed never expires, so upgrading drops nothing.\n const isLive = (generation: KeptGeneration) => ttlMs === undefined || generation.keptAt === undefined || now() - generation.keptAt < ttlMs\n\n // Hashed so a job id from the wire can never point outside the store.\n const dirOf = (jobId: string) => `studio/generations/${hashOf(jobId)}/`\n\n async function load(): Promise<Array<KeptGeneration>> {\n if (index) return index\n const stored = await storage.readItem(INDEX_KEY).catch(() => null)\n try {\n index = stored ? (JSON.parse(stored) as Array<KeptGeneration>) : []\n } catch {\n index = []\n }\n return index\n }\n\n /**\n * Copies `files` into the store as one set of `jobId`. Above `maxSetMb` only the hashes are kept.\n */\n async function keep({ jobId, source, files, maxSetMb }: { jobId: string; source: FileSource; files: SourceFiles; maxSetMb: number }): Promise<KeptSet> {\n const maxSetBytes = maxSetMb * MB\n const hashes: Record<string, string> = {}\n let bytes = 0\n await inParallel({\n items: [...files.paths],\n limit: READ_CONCURRENCY,\n run: async (path) => {\n // Output outside the root would land outside the store too.\n if (path.split('/').includes('..')) return\n const content = await files.storage.readItem(resolve(files.root, path))\n if (content === null) return\n hashes[path] = hashOf(content)\n bytes += Buffer.byteLength(content)\n if (bytes <= maxSetBytes) await storage.writeItem(`${dirOf(jobId)}${source}/${path}`, content)\n },\n })\n if (bytes > maxSetBytes) {\n await storage.empty(`${dirOf(jobId)}${source}/`)\n return { paths: [], hashes, bytes: 0 }\n }\n return { paths: Object.keys(hashes), hashes, bytes }\n }\n\n async function drop(jobId: string): Promise<void> {\n await storage.empty(dirOf(jobId))\n }\n\n return {\n keep,\n drop,\n get: async (jobId: string) => (await load()).find((generation) => generation.jobId === jobId && isLive(generation)),\n async add(generation: KeptGeneration): Promise<void> {\n const current = await load()\n for (const expired of current.filter((entry) => !isLive(entry))) await drop(expired.jobId)\n const entries = current.filter((entry) => entry.jobId !== generation.jobId && isLive(entry))\n entries.push({ ...generation, keptAt: now() })\n while (entries.length > 1 && (entries.length > maxCount || totalBytes(entries) > maxMb * MB)) {\n await drop(entries.shift()!.jobId)\n }\n index = entries\n await storage.writeItem(INDEX_KEY, JSON.stringify(entries))\n },\n /**\n * Reads the requested paths the set holds, skipping any it does not, one page of lines when `limit` is given.\n */\n async read({\n generation,\n source,\n paths,\n cursor = 0,\n limit,\n }: {\n generation: KeptGeneration\n source: FileSource\n paths: Array<string>\n cursor?: number\n limit?: number\n }): Promise<ReadFilesResult> {\n const kept = new Set(generation[source]?.paths)\n const files: Record<string, string> = {}\n const pages: Record<string, FilePage> = {}\n await inParallel({\n items: paths.filter((path) => kept.has(path)),\n limit: READ_CONCURRENCY,\n run: async (path) => {\n const content = await storage.readItem(`${dirOf(generation.jobId)}${source}/${path}`)\n if (content === null) return\n if (limit === undefined) {\n files[path] = content\n return\n }\n const lines = content.split(/\\r\\n|\\r|\\n/)\n const end = Math.min(cursor + limit, lines.length)\n files[path] = lines.slice(cursor, end).join('\\n')\n pages[path] = { nextCursor: end < lines.length ? end : null, totalLines: lines.length }\n },\n })\n return limit === undefined ? { files } : { files, pages }\n },\n }\n}\n\nexport type GenerationStore = ReturnType<typeof createGenerationStore>\n","import { stripVTControlCharacters } from 'node:util'\nimport { getElapsedMs } from '@internals/utils'\nimport { Diagnostics, type Hookable, type KubbHooks } from '@kubb/core'\nimport { type GenerationEvent, type GenerationEventPayloads, type GenerationEventType, generationEventTypes } from './protocol.ts'\nimport { relativeStoragePath } from './generations.ts'\n\n/** How each published hook's context becomes its wire payload; a hook without a projection fails to compile. */\ntype Projections = { [Type in GenerationEventType]: (...args: KubbHooks[Type]) => GenerationEventPayloads[Type] }\n\nconst MAX_QUEUED_EVENTS = 1_024\nconst RESERVED_EVENTS = 64\nconst isDiscardable = (event: GenerationEvent) => event.type === 'kubb:files:processing:update' || event.type === 'kubb:info' || event.type === 'kubb:success'\n\n/** Forwards selected Kubb lifecycle events to a native Cap'n Web stream. */\nexport function createGenerationStream(\n hooks: Hookable<KubbHooks>,\n jobId: string,\n): { stream: ReadableStream<GenerationEvent>; close: () => Promise<void>; dispose: () => void; fail: (error: unknown) => void } {\n const unhooks: Array<() => void> = []\n let root = ''\n let controller!: ReadableStreamDefaultController<GenerationEvent>\n let closed = false\n const stream = new ReadableStream<GenerationEvent>(\n {\n start: (value) => {\n controller = value\n },\n cancel: () => {\n closed = true\n detach()\n },\n },\n { highWaterMark: MAX_QUEUED_EVENTS },\n )\n\n /**\n * Registers a listener and keeps its remover, so one generation's listeners come off the session\n * emitter again when that generation ends.\n */\n function on<TName extends keyof KubbHooks & string>(name: TName, handler: (...args: KubbHooks[TName]) => unknown): void {\n unhooks.push(hooks.hook(name, handler))\n }\n\n function emitEvent<Type extends GenerationEventType>(type: Type, data: GenerationEventPayloads[Type]): void {\n if (closed) return\n const event = { jobId, type, data, version: 1 as const, timestamp: Date.now() } as unknown as GenerationEvent\n if (controller.desiredSize! <= RESERVED_EVENTS && isDiscardable(event)) return\n if (controller.desiredSize! <= 0) {\n fail(new Error(`Generation event stream exceeded ${MAX_QUEUED_EVENTS} queued events`))\n return\n }\n controller.enqueue(event)\n }\n\n const projections: Projections = {\n 'kubb:plugin:start': ({ plugin }) => [{ plugin: { name: plugin.name } }],\n 'kubb:plugin:end': ({ plugin, duration, success }) => [{ plugin: { name: plugin.name }, duration, success }],\n 'kubb:build:start': ({ config, adapter }) => [{ config: { name: config.name }, adapter: { name: adapter.name } }],\n 'kubb:build:end': ({ files, config, outputDir }) => [\n { files: files.map((file) => ({ path: relativeStoragePath({ root: config.root, filePath: file.path }), name: file.name })), outputDir },\n ],\n 'kubb:files:processing:start': ({ files }) => [{ total: files.length }],\n 'kubb:files:processing:update': ({ files }) => [\n {\n files: files.map(({ file, processed, total, percentage }) => ({\n file: relativeStoragePath({ root, filePath: file.path }),\n processed,\n total,\n percentage,\n })),\n },\n ],\n 'kubb:files:processing:end': ({ files }) => [{ total: files.length }],\n 'kubb:info': ({ message, info }) => [{ message: stripVTControlCharacters(message), info }],\n 'kubb:success': ({ message, info }) => [{ message: stripVTControlCharacters(message), info }],\n 'kubb:warn': ({ message, info }) => [{ message: stripVTControlCharacters(message), info }],\n 'kubb:error': ({ error }) => [{ message: error.message, stack: error.stack }],\n 'kubb:diagnostic': ({ diagnostic }) => [\n {\n code: diagnostic.code,\n message: diagnostic.message,\n severity: diagnostic.severity,\n location: 'location' in diagnostic ? diagnostic.location : undefined,\n help: 'help' in diagnostic ? diagnostic.help : undefined,\n plugin: 'plugin' in diagnostic ? diagnostic.plugin : undefined,\n stack: 'cause' in diagnostic ? diagnostic.cause?.stack : undefined,\n },\n ],\n 'kubb:generation:start': ({ config }) => [{ name: config.name, plugins: config.plugins.length }],\n 'kubb:generation:end': () => [],\n 'kubb:generation:summary': ({ duration, fileCount, failedPlugins, status }) => [{ duration, fileCount, failedPlugins, status }],\n 'kubb:lifecycle:start': () => [],\n 'kubb:lifecycle:end': () => [],\n 'kubb:format:start': () => [],\n 'kubb:format:end': () => [],\n 'kubb:lint:start': () => [],\n 'kubb:lint:end': () => [],\n 'kubb:hooks:start': () => [],\n 'kubb:hooks:end': () => [],\n 'kubb:hook:start': ({ id, command, args }) => [{ id, command, args: args ? [...args] : undefined }],\n 'kubb:hook:line': ({ id, line }) => [{ id, line }],\n 'kubb:hook:end': ({ id, command, args, success, error }) => [\n { id, command, args: args ? [...args] : undefined, success, error: error ? { message: error.message, stack: error.stack } : undefined },\n ],\n }\n\n function forward<Type extends GenerationEventType>(type: Type): void {\n on(type, (...args: KubbHooks[Type]) => emitEvent(type, projections[type](...args)))\n }\n\n // Paths in `kubb:files:processing:update` are made relative to the root the build announced.\n on('kubb:build:start', ({ config }) => {\n root = config.root\n })\n\n for (const type of generationEventTypes) forward(type)\n\n // Registered after the loop so the summary follows its `kubb:generation:end`; core never emits it.\n on('kubb:generation:end', ({ diagnostics = [], status, hrStart, filesCreated }) => {\n if (!hrStart) {\n return\n }\n\n const duration = Math.round(getElapsedMs(hrStart))\n\n emitEvent('kubb:generation:summary', [\n { duration, fileCount: filesCreated ?? 0, failedPlugins: Diagnostics.failedPlugins(diagnostics).length, status: status ?? 'success' },\n ])\n })\n\n /**\n * Takes this generation's listeners off the session emitter. Safe to call twice.\n */\n function detach(): void {\n for (const unhook of unhooks) unhook()\n unhooks.length = 0\n }\n\n async function close(): Promise<void> {\n if (closed) {\n return\n }\n closed = true\n detach()\n controller.close()\n }\n\n function fail(error?: unknown): void {\n detach()\n if (closed) {\n return\n }\n closed = true\n controller.error(error)\n }\n\n return { stream, close, dispose: () => fail(), fail }\n}\n","/**\n * Hosted Kubb Studio URL, used when a host passes none.\n */\nexport const defaultStudioUrl = 'https://kubb.studio'\n\n// `URL` keeps IPv6 brackets, so `::1` is `[::1]`.\nfunction isLoopbackHost(hostname: string): boolean {\n return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]'\n}\n\n/**\n * Appends `path` to the Studio URL and refuses plaintext to anything but this machine, so a token\n * or API key never crosses the network unencrypted. `socket` switches the scheme to `ws:`/`wss:`.\n *\n * @example\n * ```ts\n * secureUrl({ studioUrl: 'https://kubb.studio', path: '/api/agent/socket', socket: true }).href // 'wss://kubb.studio/api/agent/socket'\n * ```\n */\nexport function secureUrl({ studioUrl, path, socket = false }: { studioUrl: string; path: string; socket?: boolean }): URL {\n const url = new URL(`${studioUrl.replace(/\\/+$/, '')}${path}`)\n\n if (url.protocol !== 'https:' && !(url.protocol === 'http:' && isLoopbackHost(url.hostname))) {\n throw new Error(`Refusing to reach Kubb Studio at ${url.origin}: use an https:// URL, or a loopback host for local development`)\n }\n if (socket) url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'\n\n return url\n}\n","import { randomUUID } from 'node:crypto'\nimport { mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { setTimeout as delay } from 'node:timers/promises'\nimport { getErrorMessage, read, toError } from '@internals/utils'\nimport { cacheStorage, type Config, fsStorage, Hookable, type KubbHooks, memoryStorage, resolveCacheDir } from '@kubb/core'\nimport { newWebSocketRpcSession, RpcTarget } from 'capnweb'\nimport { version as kubbVersion } from '../package.json'\nimport { readConfig, writeConfigEdits } from './configFile.ts'\nimport { createGenerationStream } from './generationEvents.ts'\nimport { createGenerationStore, generate, type GenerationStore, listDisk, resolveGenerationLimits } from './generations.ts'\nimport {\n AGENT_INSTANCE_HEADER,\n AGENT_SOCKET_PATH,\n type AgentApi,\n AgentCloseCode,\n type AgentConnectInfo,\n type AgentPermissions,\n type ConfigFileView,\n type ConnectMessagePayload,\n type GenerateInput,\n type GenerateResult,\n type GenerationEvent,\n type GenerationRun,\n GENERATION_GONE_MESSAGE,\n MAX_FILES_PER_REQUEST,\n MAX_PAGE_LINES,\n type ReadFilesInput,\n type ReadFilesResult,\n type SaveConfigInput,\n type SaveResult,\n type StudioApi,\n} from './protocol.ts'\nimport { mergeAdapter, mergePlugins, toPackageName } from './resolveConfig.ts'\nimport { defaultStudioUrl, secureUrl } from './url.ts'\n\nconst HEARTBEAT_INTERVAL_MS = 30_000\n// Studio marks an agent offline after its liveness window, so a slower cadence would look dead.\nconst MAX_HEARTBEAT_INTERVAL_MS = 60_000\nconst PING_TIMEOUT_MS = 10_000\nconst OPEN_TIMEOUT_MS = 5_000\nconst MAX_RETRY_DELAY_MS = 30_000\nconst DISK_SNAPSHOT_MAX_FILES = 10_000\n// A sandbox shares one in-memory store across tenants, so old generations expire.\nconst SANDBOX_GENERATION_TTL_MS = 15 * 60_000\n\n/**\n * Studio closed with {@link AgentCloseCode.UNAUTHORIZED}. Hosts forget the token and pair again.\n */\nexport class InvalidAgentTokenError extends Error {\n constructor(studioUrl: string) {\n super(`Kubb Studio rejected this agent's token. It expired or was revoked, or the agent was deleted in ${studioUrl}.`)\n this.name = 'InvalidAgentTokenError'\n }\n}\n\n/**\n * Studio closed with {@link AgentCloseCode.INCOMPATIBLE}. Only an upgrade helps.\n */\nexport class IncompatibleAgentError extends Error {\n constructor({ studioUrl, detail }: { studioUrl: string; detail?: string }) {\n super(`Kubb Studio at ${studioUrl} requires a newer agent${detail ? `: ${detail}` : ''}. Upgrade kubb or the Kubb agent image.`)\n this.name = 'IncompatibleAgentError'\n }\n}\n\nexport type StudioConnectedContext = AgentConnectInfo & {\n url: string\n /**\n * The Studio, runtime, and host versions, so a host can show a mismatch.\n */\n versions: { studio: string; kubb: string; agent: string }\n}\n\ndeclare global {\n namespace Kubb {\n interface KubbHooksRegistry {\n /**\n * Fired after each handshake, including reconnects.\n */\n 'studio:connected': [ctx: StudioConnectedContext]\n 'studio:disconnected': [ctx: { code: number; reason: string }]\n 'studio:reconnecting': [ctx: { delayMs: number }]\n /**\n * A finished command and what it did, such as `applied 2/3 edits to kubb.config.ts`.\n */\n 'studio:command': [ctx: { command: 'generate' | 'saveConfig' | 'readFiles'; info: string }]\n /**\n * A refused or ignored request, with the missing permission so the host can add a remedy.\n */\n 'studio:warn': [ctx: { message: string; permission?: keyof AgentPermissions }]\n 'studio:error': [ctx: { error: Error }]\n }\n }\n}\n\nexport type ConnectAgentOptions = {\n /**\n * The agent's bearer token, from {@link pairAgent}.\n */\n token: string\n studioUrl?: string\n /**\n * The config path shown in Studio, relative to `root` unless absolute.\n */\n configPath: string\n /**\n * Called for every handshake and every generation, so edits on disk show up.\n */\n loadConfig: () => Promise<Config>\n /**\n * The host's own version, reported to Studio next to the runtime's.\n */\n version: string\n /**\n * The project root generation runs against.\n * @default process.cwd()\n */\n root?: string\n /**\n * What Studio may do in this project. Every permission is off unless granted.\n */\n permissions?: Partial<AgentPermissions>\n /**\n * Receives the `studio:*` hooks and the `kubb:*` hooks of every generation.\n */\n hooks?: Hookable<KubbHooks>\n signal?: AbortSignal\n /**\n * Longest wait between reconnect attempts, in milliseconds.\n * @default 30000\n */\n maxRetryDelay?: number\n /**\n * Milliseconds between keep-alive pings, at most 60000.\n * @default 30000\n */\n heartbeatInterval?: number\n}\n\ntype ResolvedOptions = Required<Omit<ConnectAgentOptions, 'signal'>> & {\n signal?: AbortSignal\n permissions: AgentPermissions\n configFile: string\n}\n\ntype Rpc = { studio: StudioApi; closed: Promise<{ code: number; reason: string }>; close: () => void }\n\n// Tests swap in an in-process pair.\nexport type OpenRpc = (input: { url: URL; token: string; instanceId: string; agent: AgentApi }) => Rpc\n\ntype Session = {\n info?: AgentConnectInfo\n connected: PromiseWithResolvers<AgentConnectInfo>\n closed: boolean\n active?: { jobId: string; abort: () => void; settled: Promise<void> }\n}\n\n// A throwing host listener must not break the connection.\nfunction emit<TName extends keyof KubbHooks & string>(hooks: Hookable<KubbHooks>, name: TName, ...args: KubbHooks[TName]): Promise<void> {\n return Promise.resolve(hooks.callHook(name, ...args)).catch(() => {})\n}\n\nfunction isValidPage({ cursor, limit }: Pick<ReadFilesInput, 'cursor' | 'limit'>): boolean {\n if (limit === undefined) return cursor === undefined\n if (cursor !== undefined && (!Number.isSafeInteger(cursor) || cursor < 0)) return false\n return Number.isSafeInteger(limit) && limit >= 1 && limit <= MAX_PAGE_LINES\n}\n\ntype RunHandle = { stream: ReadableStream<GenerationEvent>; result: Promise<GenerateResult>; stop: () => void }\n\nclass GenerationRunTarget extends RpcTarget implements GenerationRun {\n readonly #run: RunHandle\n\n constructor(run: RunHandle) {\n super()\n this.#run = run\n }\n\n async events() {\n return this.#run.stream\n }\n result() {\n return this.#run.result\n }\n async cancel() {\n this.#run.stop()\n }\n // Cap'n Web also calls this when the peer session is torn down, so a dropped socket stops the run.\n [Symbol.dispose]() {\n this.#run.stop()\n }\n}\n\n// Cap'n Web exposes only prototype methods, so the public methods are exactly `AgentApi`.\nclass Agent extends RpcTarget implements AgentApi {\n readonly #options: ResolvedOptions\n readonly #session: Session\n readonly #limits = resolveGenerationLimits()\n #store: GenerationStore | undefined\n\n constructor({ options, session }: { options: ResolvedOptions; session: Session }) {\n super()\n this.#options = options\n this.#session = session\n }\n\n get #sandbox(): boolean {\n return this.#session.info?.sandbox === true\n }\n\n // A sandbox has no project to write to or edit, and Studio may always read what it generated there.\n get #permissions(): AgentPermissions {\n const { permissions } = this.#options\n return this.#sandbox ? { ...permissions, allowWrite: false, allowConfigEdit: false, allowRead: true } : permissions\n }\n\n // Kept in the project's cache directory so it survives a restart. A sandbox keeps them in memory,\n // because its pool runs every tenant's jobs.\n get #generations(): GenerationStore {\n this.#store ??= createGenerationStore({\n storage: this.#sandbox ? memoryStorage() : cacheStorage({ root: this.#options.root }),\n maxCount: this.#limits.maxCount,\n maxMb: this.#limits.maxMb,\n ttlMs: this.#sandbox ? SANDBOX_GENERATION_TTL_MS : undefined,\n })\n return this.#store\n }\n\n #warn({ message, permission }: { message: string; permission?: keyof AgentPermissions }): Promise<void> {\n return emit(this.#options.hooks, 'studio:warn', { message, permission })\n }\n\n // Studio shows the thrown message, and the host logs the same text.\n async #refuse({ message, permission }: { message: string; permission?: keyof AgentPermissions }): Promise<never> {\n await this.#warn({ message, permission })\n throw new Error(message)\n }\n\n async #command<T>({ command, run }: { command: KubbHooks['studio:command'][0]['command']; run: () => Promise<{ value: T; info?: string }> }): Promise<T> {\n if (!this.#session.info) throw new Error('Studio must call connect() before any other command')\n const { value, info } = await run()\n if (info !== undefined) await emit(this.#options.hooks, 'studio:command', { command, info })\n return value\n }\n\n // Not cached: the user can edit the file between two Studio actions.\n async #readConfigFileView(source?: string): Promise<ConfigFileView | undefined> {\n if (!this.#permissions.allowConfigEdit) return undefined\n\n try {\n return readConfig(source ?? (await read(this.#options.configFile)))\n } catch (error) {\n await this.#warn({ message: `Could not read ${this.#options.configFile}: ${getErrorMessage(error)}` })\n return undefined\n }\n }\n\n async connect(info: AgentConnectInfo): Promise<ConnectMessagePayload> {\n this.#session.info = info\n const { configPath, root, version, loadConfig } = this.#options\n const [config, file] = await Promise.all([loadConfig(), this.#readConfigFileView()])\n this.#session.connected.resolve(info)\n\n return {\n versions: { kubb: kubbVersion, agent: version },\n root,\n config: { path: configPath, file, plugins: config.plugins.map((plugin) => ({ name: toPackageName(plugin.name), options: plugin.options ?? {} })) },\n permissions: this.#permissions,\n }\n }\n\n startGeneration(input: GenerateInput): GenerationRun {\n const stream = createGenerationStream(this.#options.hooks, input.jobId)\n const controller = new AbortController()\n const result = this.#runGeneration(input, controller).then(\n (value) => stream.close().then(() => value),\n (error: unknown) => {\n stream.fail(error)\n throw error\n },\n )\n // A disconnect can reject this after the remote caller disappeared.\n void result.catch(() => {})\n\n return new GenerationRunTarget({\n stream: stream.stream,\n result,\n stop: () => {\n controller.abort(new Error('Generation canceled'))\n stream.dispose()\n },\n })\n }\n\n async #runGeneration(input: GenerateInput, controller: AbortController): Promise<GenerateResult> {\n // Checked before the first `await`, so two calls in the same tick can't both pass.\n if (this.#session.closed) throw new Error('Connection is closed')\n if (this.#session.active) return this.#refuse({ message: 'A generation is already in progress, please wait for it to finish' })\n const settled = Promise.withResolvers<void>()\n this.#session.active = { jobId: input.jobId, abort: () => controller.abort(new Error('Generation canceled')), settled: settled.promise }\n let root = this.#options.root\n\n try {\n // Kubb keys its manifest cache by root, so sandbox tenants sharing one root would read each other's.\n if (this.#sandbox) root = await mkdtemp(path.join(tmpdir(), 'kubb-job-'))\n return await this.#command({ command: 'generate', run: () => this.#generate({ input, root, signal: controller.signal }) })\n } finally {\n if (root !== this.#options.root) {\n await Promise.all([rm(root, { recursive: true, force: true }), rm(resolveCacheDir(root), { recursive: true, force: true })]).catch(() => {})\n }\n this.#session.active = undefined\n settled.resolve()\n }\n }\n\n async #generate({ input, root, signal }: { input: GenerateInput; root: string; signal: AbortSignal }): Promise<{ value: GenerateResult; info: string }> {\n const { jobId, config: patch } = input\n const config = await this.#options.loadConfig()\n const plugins = (await mergePlugins(config.plugins, patch?.plugins)) ?? config.plugins\n const adapter = await mergeAdapter(config.adapter, patch?.adapter)\n // A sandbox has no spec on disk, so it always generates from Studio's, empty string included.\n const studioInput = this.#sandbox ? (patch?.input ?? '') : undefined\n\n if (patch?.input && !this.#sandbox) {\n await this.#warn({ message: 'Ignored the spec from Studio: generating from a Studio spec is only available to a sandbox agent' })\n }\n\n const hasProjectOnDisk = !this.#sandbox && this.#permissions.allowRead\n const diskFiles = hasProjectOnDisk ? await listDisk({ root, outputPath: config.output.path, maxFiles: DISK_SNAPSHOT_MAX_FILES }) : undefined\n const disk = diskFiles ? await this.#generations.keep({ jobId, source: 'disk', files: diskFiles, maxSetMb: this.#limits.maxSnapshotMb }) : undefined\n\n const files = await generate({\n config: { ...config, root, input: studioInput ?? config.input, storage: this.#permissions.allowWrite ? fsStorage() : memoryStorage(), plugins, adapter },\n hooks: this.#options.hooks,\n signal,\n allowExec: this.#permissions.allowExec,\n }).catch(async (error: unknown) => {\n await this.#generations.drop(jobId)\n throw error\n })\n\n const output = await this.#generations.keep({ jobId, source: 'output', files, maxSetMb: this.#limits.maxMb })\n if (!output.paths.length && Object.keys(output.hashes).length) {\n await this.#warn({ message: 'Kept only the hashes of this generation: its output is too large to keep' })\n }\n await this.#generations.add({ jobId, output, disk })\n\n return {\n value: {\n status: 'success',\n files: [...files.paths],\n fileCount: files.paths.size,\n hashes: output.hashes,\n disk: disk ? { hashes: disk.hashes } : undefined,\n },\n info: `${plugins.length} plugin${plugins.length === 1 ? '' : 's'}, ${this.#permissions.allowWrite ? 'written to disk' : 'in memory'}${studioInput !== undefined ? ', from a Studio spec' : ''}`,\n }\n }\n\n saveConfig(input: SaveConfigInput): Promise<SaveResult> {\n return this.#command({ command: 'saveConfig', run: () => this.#saveConfig(input) })\n }\n\n async #saveConfig(input: SaveConfigInput): Promise<{ value: SaveResult; info?: string }> {\n const { configPath, configFile } = this.#options\n\n if (!Array.isArray(input.edits)) {\n await this.#warn({ message: 'Ignored save: the message carried no edits' })\n return { value: { outcomes: [], changed: false } }\n }\n\n const edits = input.edits\n const refuse = (reason: string): SaveResult => ({ outcomes: edits.map((edit) => ({ edit, applied: false, reason })), changed: false })\n\n if (!this.#permissions.allowConfigEdit) {\n await this.#warn({ message: 'Ignored save: editing kubb.config.ts was not granted' })\n return { value: refuse('the agent was not granted permission to edit kubb.config.ts') }\n }\n\n // A running generation reloads the config, so it would see half the change.\n if (this.#session.active) return { value: refuse('a generation is in progress') }\n\n try {\n const { source, outcomes, changed } = await writeConfigEdits({ filePath: configFile, edits })\n const applied = outcomes.filter((outcome) => outcome.applied).length\n\n return {\n value: { outcomes, changed, file: changed ? await this.#readConfigFileView(source) : undefined },\n info: `applied ${applied}/${outcomes.length} edits to ${configPath}`,\n }\n } catch (error) {\n // Refuse every edit so Studio hears back instead of waiting.\n await emit(this.#options.hooks, 'studio:error', { error: toError(error) })\n return { value: refuse(getErrorMessage(error)) }\n }\n }\n\n readFiles(input: ReadFilesInput): Promise<ReadFilesResult> {\n return this.#command({ command: 'readFiles', run: () => this.#readFiles(input) })\n }\n\n async #readFiles(input: ReadFilesInput): Promise<{ value: ReadFilesResult; info: string }> {\n if (!this.#permissions.allowRead) return this.#refuse({ message: 'The agent was not granted permission to read generated files', permission: 'allowRead' })\n if (!Array.isArray(input.paths) || typeof input.jobId !== 'string' || !input.jobId) {\n return this.#refuse({ message: 'The request must name a job and carry paths' })\n }\n const { paths } = input\n if (paths.length > MAX_FILES_PER_REQUEST) return this.#refuse({ message: `At most ${MAX_FILES_PER_REQUEST} paths may be requested at once` })\n\n const generation = await this.#generations.get(input.jobId)\n if (!generation) return this.#refuse({ message: GENERATION_GONE_MESSAGE })\n if (!isValidPage(input)) return this.#refuse({ message: `The cursor must be a whole line from 0 and come with a limit of 1 to ${MAX_PAGE_LINES} lines` })\n\n const source = input.source === 'disk' ? 'disk' : 'output'\n if (!generation[source]) return this.#refuse({ message: 'This agent kept no snapshot of the files on disk for that job' })\n\n // Only paths the set holds are read, never an arbitrary path.\n const result = await this.#generations.read({ generation, source, paths, cursor: input.cursor, limit: input.limit })\n\n return { value: result, info: `read ${Object.keys(result.files).length}/${paths.length} requested file${paths.length === 1 ? '' : 's'}` }\n }\n}\n\nconst openWebSocketRpc: OpenRpc = ({ url, token, instanceId, agent }) => {\n // Node's `WebSocket` takes undici's `headers` option, which the DOM typing leaves out.\n const NodeWebSocket = WebSocket as unknown as new (url: URL, init: { headers: Record<string, string> }) => WebSocket\n const socket = new NodeWebSocket(url, { headers: { Authorization: `Bearer ${token}`, [AGENT_INSTANCE_HEADER]: instanceId } })\n const timer = setTimeout(() => socket.close(3008, 'Connection timeout'), OPEN_TIMEOUT_MS)\n socket.addEventListener('open', () => clearTimeout(timer), { once: true })\n\n const closed = new Promise<Awaited<Rpc['closed']>>((resolve) => {\n socket.addEventListener('close', ({ code, reason }) => resolve({ code, reason }), { once: true })\n // Node fires only `error` when the handshake itself fails.\n socket.addEventListener('error', () => {\n if (socket.readyState !== WebSocket.OPEN) resolve({ code: 1006, reason: '' })\n })\n }).finally(() => clearTimeout(timer))\n\n const studio = newWebSocketRpcSession<StudioApi>(socket, agent)\n studio.onRpcBroken(() => socket.close())\n\n return {\n studio,\n closed,\n close: () => {\n studio[Symbol.dispose]()\n socket.close()\n },\n }\n}\n\nasync function runSession({ options, openRpc, url, instanceId }: { options: ResolvedOptions; openRpc: OpenRpc; url: URL; instanceId: string }) {\n const { hooks, signal, heartbeatInterval, token, studioUrl, version } = options\n const session: Session = { connected: Promise.withResolvers(), closed: false }\n const rpc = openRpc({ url, token, instanceId, agent: new Agent({ options, session }) })\n signal?.addEventListener('abort', rpc.close, { once: true })\n let timer: ReturnType<typeof setTimeout> | undefined\n\n // Races each ping against a deadline, so a half-open socket can't hang it forever.\n const heartbeat = async (): Promise<void> => {\n let deadline: ReturnType<typeof setTimeout> | undefined\n const timedOut = new Promise<boolean>((resolve) => (deadline = setTimeout(resolve, PING_TIMEOUT_MS, true)))\n const failed = await Promise.race([\n Promise.resolve(rpc.studio.ping()).then(\n () => false,\n () => true,\n ),\n timedOut,\n ])\n clearTimeout(deadline)\n if (failed) return rpc.close()\n if (!session.closed) timer = setTimeout(heartbeat, heartbeatInterval)\n }\n\n void session.connected.promise.then(\n async (info) => {\n await emit(hooks, 'studio:connected', { ...info, url: studioUrl, versions: { studio: info.studioVersion, kubb: kubbVersion, agent: version } })\n if (!session.closed) timer = setTimeout(heartbeat, heartbeatInterval)\n },\n () => {},\n )\n\n const close = await rpc.closed\n session.closed = true\n clearTimeout(timer)\n signal?.removeEventListener('abort', rpc.close)\n session.connected.reject(new Error('The socket closed before Studio called connect()'))\n session.active?.abort()\n await session.active?.settled\n\n return { ...close, connected: session.info !== undefined }\n}\n\n/**\n * The connection loop with a swappable transport. {@link connectAgent} passes a real WebSocket.\n */\nexport async function runAgent({ options, openRpc }: { options: ConnectAgentOptions; openRpc: OpenRpc }): Promise<void> {\n const root = options.root ?? process.cwd()\n const resolved: ResolvedOptions = {\n ...options,\n studioUrl: options.studioUrl ?? defaultStudioUrl,\n root,\n configFile: path.resolve(root, options.configPath),\n permissions: { allowWrite: false, allowConfigEdit: false, allowExec: false, allowRead: false, ...options.permissions },\n hooks: options.hooks ?? new Hookable<KubbHooks>(),\n maxRetryDelay: options.maxRetryDelay ?? MAX_RETRY_DELAY_MS,\n heartbeatInterval: Math.min(options.heartbeatInterval ?? HEARTBEAT_INTERVAL_MS, MAX_HEARTBEAT_INTERVAL_MS),\n }\n const { studioUrl, hooks, signal, maxRetryDelay } = resolved\n const url = secureUrl({ studioUrl, path: AGENT_SOCKET_PATH, socket: true })\n // One per call, so a reconnect is the same process to Studio and a restart is a new one.\n const instanceId = randomUUID()\n let attempt = 0\n\n while (!signal?.aborted) {\n const { code, reason, connected } = await runSession({ options: resolved, openRpc, url, instanceId })\n if (signal?.aborted) return\n await emit(hooks, 'studio:disconnected', { code, reason })\n\n if (code === AgentCloseCode.UNAUTHORIZED) throw new InvalidAgentTokenError(studioUrl)\n if (code === AgentCloseCode.INCOMPATIBLE) throw new IncompatibleAgentError({ studioUrl, detail: reason })\n if (code === AgentCloseCode.SUPERSEDED) return\n\n // Reset only once Studio called connect(), so a socket that opens and closes again backs off.\n if (connected) attempt = 0\n const delayMs = Math.random() * Math.min(1_000 * 2 ** Math.min(attempt++, 16), maxRetryDelay)\n await emit(hooks, 'studio:reconnecting', { delayMs })\n await delay(delayMs, undefined, { signal }).catch(() => {})\n }\n}\n\n/**\n * Connects this project to Kubb Studio and serves its commands until `signal` aborts. Reconnects\n * with jittered backoff, and resolves when another process of the agent takes over. Rejects with\n * {@link InvalidAgentTokenError} so the host can pair again, or {@link IncompatibleAgentError}.\n *\n * @example\n * ```ts\n * const hooks = new Hookable<KubbHooks>()\n * hooks.hook('studio:connected', ({ agentSlug }) => console.log(`Connected as ${agentSlug}`))\n *\n * await connectAgent({ token, configPath: 'kubb.config.ts', loadConfig, version: '1.0.0', hooks, signal })\n * ```\n */\nexport function connectAgent(options: ConnectAgentOptions): Promise<void> {\n return runAgent({ options, openRpc: openWebSocketRpc })\n}\n","import { hash } from 'node:crypto'\nimport { setTimeout as delay } from 'node:timers/promises'\nimport { toError } from '@internals/utils'\nimport { ofetch } from 'ofetch'\nimport { defaultStudioUrl, secureUrl } from './url.ts'\n\n/**\n * RFC 8628 device-authorization response from Studio's `/api/auth/device/code` endpoint.\n * Field names match the RFC; the CLI polls with `device_code` and shows `user_code` to the user.\n */\nexport type PairingSession = {\n device_code: string\n user_code: string\n verification_uri: string\n verification_uri_complete: string\n expires_in: number\n interval: number\n}\n\ntype PairingResult = {\n /**\n * Bearer token for this machine. Write credentials with mode 0600 and never log the value.\n */\n token: string\n agent: {\n /**\n * Stable agent id in Studio.\n */\n id: string\n /**\n * Short slug used in logs and the UI (for example `brave-otter`).\n */\n slug: string\n /**\n * Display name chosen at pairing time.\n */\n name: string\n /**\n * This agent's organization slug, absent for a sandbox or global agent, which has none.\n */\n organizationSlug?: string\n }\n}\n\n/**\n * What this machine registers as. Any member may approve `cli` (`kubb studio`); only an admin may\n * approve `user` and `sandbox` (the Docker image). A `ci` agent never pairs.\n */\ntype PairingAgentType = 'cli' | 'user' | 'sandbox'\n\n/** Labels, not secrets: a person approving the code in the browser is what authorizes a pairing. */\nconst CLIENT_IDS = { cli: 'kubb-cli', agent: 'kubb-agent' } as const\n\n/**\n * Thrown when a caller aborts `startPairing` or `pollForPairingToken` through their `signal`, such\n * as a `kubb studio` shutdown mid-pairing. Distinct from a denial or an expired code, so a host can\n * exit quietly instead of reporting a pairing failure.\n */\nexport class PairingCanceledError extends Error {\n constructor() {\n super('Pairing was canceled')\n this.name = 'PairingCanceledError'\n }\n}\n\n/** Thrown when the code expired unapproved. A fresh code can still succeed. */\nexport class PairingExpiredError extends Error {\n constructor(message = 'The pairing code expired, pair again') {\n super(message)\n this.name = 'PairingExpiredError'\n }\n}\n\n/** Thrown when the pairing was denied in the browser, including by the organization's agent limit. */\nexport class PairingDeniedError extends Error {\n constructor(message = 'Pairing was denied in the browser') {\n super(message)\n this.name = 'PairingDeniedError'\n }\n}\n\ntype StartPairingOptions = {\n studioUrl?: string\n type: PairingAgentType\n /**\n * Display name for the agent, usually the project or machine name.\n */\n name: string\n hostname: string\n /**\n * A stable secret the host keeps for this machine. Studio stores its hash against the agent, so\n * the same machine pairing again rotates one agent's token instead of creating a second agent.\n */\n machineId: string\n /**\n * Aborting this cancels the request in flight and rejects with {@link PairingCanceledError}.\n */\n signal?: AbortSignal\n}\n\n/**\n * Asks Studio for a pairing code, sending the hashed machine id with it.\n */\nexport async function startPairing({ studioUrl = defaultStudioUrl, type, name, hostname, machineId, signal }: StartPairingOptions): Promise<PairingSession> {\n try {\n const pairing = await ofetch<PairingSession>(secureUrl({ studioUrl, path: '/api/auth/device/code' }).href, {\n method: 'POST',\n body: {\n client_id: type === 'cli' ? CLIENT_IDS.cli : CLIENT_IDS.agent,\n name,\n hostname,\n machine_token: hash('sha256', machineId),\n agent_kind: type === 'cli' ? undefined : type,\n },\n signal,\n })\n if (typeof pairing?.device_code !== 'string') throw new Error('Kubb Studio returned no pairing code')\n\n return pairing\n } catch (error) {\n if (signal?.aborted) {\n throw new PairingCanceledError()\n }\n\n throw error\n }\n}\n\ntype PollOptions = {\n studioUrl?: string\n session: PairingSession\n /**\n * Aborting this stops polling and rejects with {@link PairingCanceledError}, whether the abort\n * lands between polls or during the wait for the next one.\n */\n signal?: AbortSignal\n /** Called when a poll could not reach Studio. Polling carries on. */\n onRetry?: (error: Error) => void\n}\n\ntype PollError = 'authorization_pending' | 'slow_down' | 'expired_token' | 'access_denied' | 'invalid_grant'\n\ntype PollResponse =\n | PairingResult\n | {\n error: PollError | string\n /**\n * Why, when Studio has something more useful to say than the RFC code. An approval that hits\n * the organization's agent limit comes back as `access_denied` with the limit spelled out.\n */\n error_description?: string\n }\n\nfunction isPairingResult(response: PollResponse): response is PairingResult {\n return 'token' in response && typeof response.token === 'string'\n}\n\n/**\n * Polls until the user approves or denies, honoring the server's `slow_down` back-off.\n *\n * Studio's own endpoint is used rather than the auth layer's `/device/token`, because an approved\n * Kubb pairing is worth an agent bearer token, not a user session.\n *\n * @throws {PairingExpiredError} when the code expires before anyone approves it.\n * @throws {PairingDeniedError} when the pairing is denied in the browser.\n * @throws {PairingCanceledError} when `signal` aborts.\n */\nexport async function pollForPairingToken({ studioUrl = defaultStudioUrl, session, signal, onRetry }: PollOptions): Promise<PairingResult> {\n // Both fields cross the network, so neither is trusted as-is: a missing or zero `interval` would\n // spin the poll loop, and a missing or zero `expires_in` would expire the code before the first\n // poll. `> 0` is also false for `NaN` and for a missing field, so it doubles as the type guard.\n const deadline = Date.now() + (session.expires_in > 0 ? session.expires_in : 600) * 1000\n let intervalMs = (session.interval > 0 ? session.interval : 5) * 1000\n\n while (Date.now() < deadline) {\n if (signal?.aborted) {\n throw new PairingCanceledError()\n }\n\n try {\n await delay(intervalMs, undefined, { signal })\n } catch {\n throw new PairingCanceledError()\n }\n\n let response: PollResponse\n try {\n // A denial, an expiry, and \"not yet\" all come back as 4xx with a body to switch on.\n const { status, _data } = await ofetch.raw<PollResponse>(secureUrl({ studioUrl, path: '/api/agent/token' }).href, {\n method: 'POST',\n body: { device_code: session.device_code },\n signal,\n ignoreResponseError: true,\n })\n if (status >= 500 || !_data || typeof _data !== 'object') throw new Error(`Kubb Studio answered with status ${status}`)\n response = _data\n } catch (error) {\n if (signal?.aborted) {\n throw new PairingCanceledError()\n }\n\n // Studio can be briefly unreachable (a deploy) while the code is still valid, so retry.\n onRetry?.(toError(error))\n continue\n }\n\n if (isPairingResult(response)) {\n return response\n }\n\n if (!('error' in response) || typeof response.error !== 'string') {\n throw new Error('Kubb Studio returned an empty pairing response, pair again')\n }\n\n if (response.error === 'authorization_pending') {\n continue\n }\n\n if (response.error === 'slow_down') {\n intervalMs += 5_000\n continue\n }\n\n if (response.error === 'access_denied') {\n throw new PairingDeniedError(response.error_description)\n }\n\n if (response.error === 'expired_token' || response.error === 'invalid_grant') {\n throw new PairingExpiredError(response.error_description)\n }\n\n throw new Error(response.error_description ?? `Pairing failed (${response.error})`)\n }\n\n throw new PairingExpiredError()\n}\n\ntype PairAgentOptions = StartPairingOptions & {\n /** Shows the code to whoever approves it. Called again for each fresh code. */\n onCode: (session: PairingSession, attempt: number) => void | Promise<void>\n /** Called when a poll could not reach Studio. Polling carries on. */\n onRetry?: (error: Error) => void\n /**\n * Codes to ask for in total when one expires unapproved. A denial or abort ends it at once.\n * @default 1\n */\n maxAttempts?: number\n}\n\n/**\n * Pairs this machine with Studio: asks for a code, hands it to the host to show, and waits for approval.\n */\nexport async function pairAgent({ onCode, onRetry, maxAttempts = 1, ...options }: PairAgentOptions): Promise<PairingResult> {\n for (let attempt = 1; ; attempt++) {\n const session = await startPairing(options)\n await onCode(session, attempt)\n\n try {\n return await pollForPairingToken({ studioUrl: options.studioUrl, session, signal: options.signal, onRetry })\n } catch (error) {\n if (!(error instanceof PairingExpiredError) || attempt >= maxAttempts) {\n throw error\n }\n }\n }\n}\n","import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join, resolve } from 'node:path'\nimport { promisify } from 'node:util'\nimport { gzip } from 'node:zlib'\nimport { type Config, fsStorage, type Hookable, type KubbHooks } from '@kubb/core'\nimport { type FetchResponse, ofetch } from 'ofetch'\nimport { generate, hashOf } from './generations.ts'\nimport { MAX_SNAPSHOT_BYTES, type PublishedSnapshot, type SnapshotUploadMetadata } from './protocol.ts'\nimport { resolvePeerDependencies } from './resolveConfig.ts'\nimport { defaultStudioUrl, secureUrl } from './url.ts'\n\nconst gzipAsync = promisify(gzip)\nconst UPLOAD_TIMEOUT_MS = 120_000\n\n// Plugins whose output a snapshot carries without depending on the plugin package.\nconst BUNDLED_DEPENDENCIES = ['@kubb/plugin-barrel']\n\ntype SnapshotFiles = Record<string, string>\ntype SnapshotPackage = { name: string; version: string; peerDependencies: Record<string, string> }\n\n/**\n * Maps a generated file's path to its place inside the tarball, stripping everything before a\n * `src`/`dist` segment and any `..`/empty path segment so a crafted file name cannot escape the\n * `package/` root.\n */\nfunction packagePath(filePath: string): string {\n const normalized = filePath.replaceAll('\\\\', '/')\n const relativePath = normalized.match(/\\/(?:src|dist)\\/.*$/)?.[0].slice(1) ?? normalized.replace(/^\\/+/, '')\n const safe = relativePath\n .split('/')\n .filter((part) => part && part !== '.' && part !== '..')\n .join('/')\n return `package/${safe}`\n}\n\n/**\n * Splits a tarball entry path into the legacy 100-byte `name` field and, when the path does not\n * fit, the 155-byte USTAR `prefix` field that extends it. Throws rather than silently truncating\n * a path the format cannot address (max 256 bytes: 100 name + 1 separator + 155 prefix).\n */\nfunction splitEntryPath(path: string): { name: string; prefix: string } {\n if (Buffer.byteLength(path, 'utf8') <= 100) {\n return { name: path, prefix: '' }\n }\n\n for (let i = path.length - 1; i >= 0; i--) {\n if (path[i] !== '/') continue\n\n const prefix = path.slice(0, i)\n const name = path.slice(i + 1)\n if (Buffer.byteLength(prefix, 'utf8') <= 155 && Buffer.byteLength(name, 'utf8') <= 100) {\n return { name, prefix }\n }\n }\n\n throw new Error(`Snapshot path is too long for a tar entry: ${path}`)\n}\n\nfunction header(path: string, size: number): Buffer {\n const { name, prefix } = splitEntryPath(path)\n const value = Buffer.alloc(512)\n value.write(name, 0, 'utf8')\n value.write('0000644\\0', 100, 'ascii')\n value.write('0000000\\0', 108, 'ascii')\n value.write('0000000\\0', 116, 'ascii')\n value.write(`${size.toString(8).padStart(11, '0')}\\0`, 124, 'ascii')\n // npm's fixed mtime, so the same files always pack to the same integrity.\n value.write('03560116604\\0', 136, 'ascii')\n value.fill(32, 148, 156)\n value.write('0', 156, 'ascii')\n value.write('ustar\\0', 257, 'ascii')\n value.write('00', 263, 'ascii')\n value.write('0000000\\0', 265, 'ascii')\n value.write('0000000\\0', 297, 'ascii')\n value.write(prefix, 345, 'utf8')\n const checksum = [...value].reduce((sum, byte) => sum + byte, 0)\n value.write(`${checksum.toString(8).padStart(6, '0')}\\0 `, 148, 'ascii')\n return value\n}\n\n/**\n * Packs a generation's files into a gzipped, npm-installable tarball: a `package/` root with the\n * generated sources, a `tsdown`-built `dist/` (esm + cjs), and a `package.json` manifest.\n */\nexport async function createSnapshotPackage({ files, packageInfo }: { files: SnapshotFiles; packageInfo: SnapshotPackage }): Promise<Buffer> {\n const root = await mkdtemp(join(tmpdir(), 'kubb-snapshot-'))\n const dist = join(root, 'dist')\n\n // Resolved once so the sanitized target for each file is computed exactly one way, and any two\n // generated files that collide after sanitizing (e.g. `a/../index.ts` and `a/index.ts`) are\n // caught here instead of silently overwriting one another later.\n const resolvedPaths = Object.entries(files).map(([name, content]) => ({ name, content, target: packagePath(name) }))\n const targetOwners = new Map<string, string>()\n for (const { name, target } of resolvedPaths) {\n const owner = targetOwners.get(target)\n if (owner) {\n throw new Error(`Snapshot has two generated files that sanitize to the same path \"${target}\": \"${owner}\" and \"${name}\"`)\n }\n targetOwners.set(target, name)\n }\n\n try {\n await mkdir(dist)\n await Promise.all(\n resolvedPaths.map(async ({ content, target }) => {\n const path = join(root, target.slice('package/'.length))\n await mkdir(join(path, '..'), { recursive: true })\n await writeFile(path, content)\n }),\n )\n const sourceEntries = resolvedPaths.filter(({ name }) => /\\.(?:[cm]?[jt]sx?)$/.test(name)).map(({ target }) => join(root, target.slice('package/'.length)))\n if (sourceEntries.length) {\n // Loaded on first use: tsdown is large, and most agent processes never pack a snapshot.\n const { build } = await import('tsdown')\n await build({\n entry: sourceEntries,\n outDir: dist,\n format: ['esm', 'cjs'],\n dts: false,\n sourcemap: false,\n unbundle: true,\n report: false,\n logLevel: 'silent',\n // The manifest below always points at `.mjs`/`.cjs`, so the build must produce those\n // extensions regardless of the host process's own `package.json` \"type\" (tsdown otherwise\n // infers it from the nearest ancestor package.json, which differs by host).\n fixedExtension: true,\n })\n }\n const builtEntries = await Promise.all(\n (await fsStorage().readKeys(dist)).map(async (key) => [`package/dist/${key}`, await readFile(join(dist, key), 'utf8')] as const),\n )\n // Without `@kubb/plugin-barrel` the build produces no `dist/index.*`, so pointing\n // `main`/`module`/`exports['.']` at it would ship a manifest with missing files.\n const builtPaths = new Set(builtEntries.map(([path]) => path))\n const hasBarrel = builtPaths.has('package/dist/index.mjs') && builtPaths.has('package/dist/index.cjs')\n const barrelFields = hasBarrel ? { main: './dist/index.cjs', module: './dist/index.mjs' } : {}\n const barrelExport = hasBarrel ? { '.': { import: './dist/index.mjs', require: './dist/index.cjs' } } : {}\n\n const entries = {\n 'package/package.json': JSON.stringify(\n {\n ...packageInfo,\n type: 'module',\n ...barrelFields,\n // `exports` denies any subpath it doesn't list, so the wildcard keeps individual\n // generated files (e.g. `models/Pet`) importable without a barrel.\n exports: { ...barrelExport, './*': { import: './dist/*.mjs', require: './dist/*.cjs' } },\n },\n null,\n 2,\n ),\n ...Object.fromEntries(resolvedPaths.map(({ content, target }) => [target, content])),\n ...Object.fromEntries(builtEntries),\n }\n const chunks: Array<Buffer> = []\n\n for (const [name, content] of Object.entries(entries)) {\n const bytes = Buffer.from(content)\n chunks.push(header(name, bytes.length), bytes, Buffer.alloc((512 - (bytes.length % 512)) % 512))\n }\n\n return await gzipAsync(Buffer.concat([...chunks, Buffer.alloc(1024)]))\n } finally {\n await rm(root, { recursive: true, force: true })\n }\n}\n\ntype CreateSnapshotOptions = Omit<SnapshotUploadMetadata, 'hashes' | 'peerDependencies'> & {\n studioUrl?: string\n /**\n * Organization CI API key, sent as `x-api-key`.\n */\n apiKey: string\n /**\n * The project's Kubb config. Like `kubb generate`, it writes to `output.path`, then runs the\n * formatter, the linter, and `output.postGenerate`.\n */\n config: Config\n hooks?: Hookable<KubbHooks>\n signal?: AbortSignal\n}\n\ntype UploadResponse = { snapshot?: PublishedSnapshot; message?: string; data?: { upgradeUrl?: string } }\n\nfunction failureMessage({ status, _data }: FetchResponse<UploadResponse>): string {\n const upgrade = _data?.data?.upgradeUrl ? ` Upgrade at ${_data.data.upgradeUrl}.` : ''\n\n return `Kubb Studio refused the snapshot (status ${status})${_data?.message ? `: ${_data.message}` : ''}.${upgrade}`\n}\n\n/**\n * Generates the project, packs it as an npm tarball, and publishes it to Studio in one\n * `POST /api/snapshots` request.\n *\n * @example\n * ```ts\n * const snapshot = await createSnapshot({\n * apiKey: process.env.KUBB_TOKEN!,\n * config,\n * id: 'gh:123:pr-4',\n * name: 'acme/api#4',\n * packageName: '@acme/api',\n * version: '1.0.0',\n * })\n * console.log(snapshot.url, snapshot.changes)\n * ```\n */\nexport async function createSnapshot({\n studioUrl = defaultStudioUrl,\n apiKey,\n config,\n hooks,\n signal,\n ...metadata\n}: CreateSnapshotOptions): Promise<PublishedSnapshot> {\n const url = secureUrl({ studioUrl, path: '/api/snapshots' })\n const generated = await generate({ config, hooks, signal, allowExec: true })\n const files = Object.fromEntries(\n await Promise.all(\n [...generated.paths].map(async (path) => {\n const content = await generated.storage.readItem(resolve(generated.root, path))\n if (content === null) throw new Error(`The generation listed ${path} but did not keep its content`)\n return [path, content] as const\n }),\n ),\n )\n const { peerDependencies, missingDependencies } = await resolvePeerDependencies(config.plugins.map(({ name }) => name))\n // The package would declare no version for a plugin that is not installed.\n const missing = missingDependencies.filter((dependency) => !BUNDLED_DEPENDENCIES.includes(dependency))\n if (missing.length) throw new Error(`Missing dependencies: ${missing.join(', ')}`)\n\n const bytes = await createSnapshotPackage({ files, packageInfo: { name: metadata.packageName, version: metadata.version, peerDependencies } })\n if (bytes.length > MAX_SNAPSHOT_BYTES) {\n throw new Error(`The snapshot is ${Math.ceil(bytes.length / 1024 / 1024)} MB, over the ${MAX_SNAPSHOT_BYTES / 1024 / 1024} MB limit`)\n }\n\n const hashes = Object.fromEntries(Object.entries(files).map(([path, content]) => [path, hashOf(content)]))\n const body = new FormData()\n body.set('metadata', JSON.stringify({ ...metadata, hashes, peerDependencies } satisfies SnapshotUploadMetadata))\n body.set('tarball', new Blob([new Uint8Array(bytes)], { type: 'application/gzip' }), 'snapshot.tgz')\n\n const timeout = AbortSignal.timeout(UPLOAD_TIMEOUT_MS)\n // A redirect would forward the CI key and tarball to wherever it points.\n const response = await ofetch.raw<UploadResponse>(url.href, {\n method: 'POST',\n headers: { 'x-api-key': apiKey },\n body,\n redirect: 'error',\n signal: signal ? AbortSignal.any([signal, timeout]) : timeout,\n ignoreResponseError: true,\n })\n if (!response.ok) throw new Error(failureMessage(response))\n\n const snapshot = response._data?.snapshot\n if (!snapshot) throw new Error(`Kubb Studio returned no snapshot (status ${response.status})`)\n return snapshot\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["readFile","createRequire","pathToFileURL","existsSync","require","readFile","builders","parseModule","detectCodeFormat","generateCode","writeFile","isAbsolute","relative","resolve","createHash","process","Diagnostics","createKubb","sep","fsStorage","stripVTControlCharacters","generationEventTypes","Diagnostics","RpcTarget","memoryStorage","cacheStorage","kubbVersion","version","mkdtemp","path","tmpdir","rm","resolveCacheDir","fsStorage","GENERATION_GONE_MESSAGE","MAX_PAGE_LINES","NodeWebSocket","AGENT_INSTANCE_HEADER","newWebSocketRpcSession","process","Hookable","AGENT_SOCKET_PATH","randomUUID","AgentCloseCode","delay","hash","delay","promisify","gzip","mkdtemp","join","tmpdir","mkdir","dirname","writeFile","fsStorage","readFile","rm","resolve","MAX_SNAPSHOT_BYTES"],"sources":["../../../internals/utils/src/casing.ts","../../../internals/utils/src/errors.ts","../../../internals/utils/src/runtime.ts","../../../internals/utils/src/fs.ts","../../../internals/utils/src/promise.ts","../../../internals/utils/src/time.ts","../package.json","../src/resolveConfig.ts","../src/configFile.ts","../src/generations.ts","../src/generationEvents.ts","../src/url.ts","../src/connect.ts","../src/pair.ts","../src/snapshot.ts"],"sourcesContent":["type Options = {\n /**\n * Text prepended before casing is applied.\n */\n prefix?: string\n /**\n * Text appended before casing is applied.\n */\n suffix?: string\n}\n\n/**\n * Shared implementation for camelCase and PascalCase conversion.\n * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)\n * and capitalizes each word according to `pascal`.\n *\n * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.\n */\nfunction toCamelOrPascal(text: string, pascal: boolean): string {\n return text\n .trim()\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([a-z])/g, '$1 $2')\n .split(/[\\s\\-_./\\\\:]+/)\n .filter(Boolean)\n .map((word, i) => {\n if (word.length > 1 && word === word.toUpperCase()) return word\n const head = i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()\n return head + word.slice(1)\n })\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '')\n}\n\n/**\n * Converts `text` to camelCase.\n *\n * @example Word boundaries\n * `camelCase('hello-world') // 'helloWorld'`\n *\n * @example With a prefix\n * `camelCase('tag', { prefix: 'create' }) // 'createTag'`\n */\nexport function camelCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false)\n}\n\n/**\n * Converts `text` to PascalCase.\n *\n * @example Word boundaries\n * `pascalCase('hello-world') // 'HelloWorld'`\n *\n * @example With a suffix\n * `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`\n */\nexport function pascalCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true)\n}\n","/**\n * Coerces an unknown thrown value to an `Error` instance.\n * Returns the value as-is when it is already an `Error`; otherwise wraps it with `String(value)`.\n *\n * @example\n * ```ts\n * try { ... } catch(err) {\n * throw new Error('Build failed', { cause: toError(err) })\n * }\n * ```\n */\nexport function toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value))\n}\n\n/**\n * Extracts a human-readable message from any thrown value.\n *\n * @example\n * ```ts\n * getErrorMessage(new Error('oops')) // 'oops'\n * getErrorMessage('plain string') // 'plain string'\n * ```\n */\nexport function getErrorMessage(value: unknown): string {\n return value instanceof Error ? value.message : String(value)\n}\n","/**\n * Name of the JavaScript runtime executing the current process.\n */\ntype RuntimeName = 'bun' | 'deno' | 'node'\n\n/**\n * Detects the JavaScript runtime executing the current process and exposes its name and version.\n *\n * Prefer the shared {@link runtime} instance over constructing your own.\n */\nclass Runtime {\n /**\n * `true` when the current process is running under Bun.\n *\n * Detection keys off the global `Bun` object rather than `process.versions`,\n * because Bun polyfills `process.versions.node` for Node compatibility and would\n * otherwise look like Node.\n *\n * @example\n * ```ts\n * if (runtime.isBun) {\n * await Bun.write(path, data)\n * }\n * ```\n */\n get isBun(): boolean {\n return typeof Bun !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Deno.\n */\n get isDeno(): boolean {\n return typeof (globalThis as { Deno?: unknown }).Deno !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Node.\n *\n * Bun and Deno are excluded first so a polyfilled `process` does not register as Node.\n */\n get isNode(): boolean {\n return !this.isBun && !this.isDeno && typeof process !== 'undefined' && process.versions?.node != null\n }\n\n /**\n * Name of the runtime executing the current process.\n *\n * @example\n * ```ts\n * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise\n * ```\n */\n get name(): RuntimeName {\n if (this.isBun) return 'bun'\n if (this.isDeno) return 'deno'\n\n return 'node'\n }\n\n /**\n * Version of the active runtime, or an empty string when it cannot be read.\n *\n * @example\n * ```ts\n * runtime.version // '1.3.11' under Bun, '22.22.2' under Node\n * ```\n */\n get version(): string {\n if (this.isBun) return process.versions.bun ?? ''\n if (this.isDeno) return (globalThis as { Deno?: { version?: { deno?: string } } }).Deno?.version?.deno ?? ''\n\n return process.versions?.node ?? ''\n }\n}\n\n/**\n * Shared {@link Runtime} instance describing the JavaScript runtime executing the current process.\n */\nexport const runtime = new Runtime()\n","import { access, mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { dirname, isAbsolute, relative, resolve } from 'node:path'\nimport { runtime } from './runtime.ts'\n\n/**\n * Resolves to `true` when the file or directory at `path` exists.\n * Uses `Bun.file().exists()` when running under Bun, `fs.access` otherwise.\n *\n * @example\n * ```ts\n * if (await exists('./kubb.config.ts')) {\n * const content = await read('./kubb.config.ts')\n * }\n * ```\n */\nexport async function exists(path: string): Promise<boolean> {\n if (runtime.isBun) {\n return Bun.file(path).exists()\n }\n return access(path).then(\n () => true,\n () => false,\n )\n}\n\n/**\n * Reads the file at `path` as a UTF-8 string.\n * Uses `Bun.file().text()` when running under Bun, `fs.readFile` otherwise.\n *\n * @example\n * ```ts\n * const source = await read('./src/Pet.ts')\n * ```\n */\nexport async function read(path: string): Promise<string> {\n if (runtime.isBun) {\n return Bun.file(path).text()\n }\n return readFile(path, { encoding: 'utf8' })\n}\n\ntype WriteOptions = {\n /**\n * Previously read content, or `null` when the file does not exist.\n * Omitting this value reads the file before writing.\n */\n stored?: string | null\n /**\n * When `true`, re-reads the file immediately after writing and throws if the\n * content does not match — useful for catching write failures on unreliable file systems.\n */\n sanity?: boolean\n}\n\n/**\n * Whether `stored` already holds `source`, comparing on the trimmed text rather than the exact\n * bytes. Surrounding whitespace is what a formatter adds and what editors strip, and neither is a\n * reason to rewrite the file.\n *\n * Both sides are trimmed, so a storage that keeps bytes verbatim settles on the same answer as one\n * that normalizes what it stores. Trimming only `stored` would leave a source with leading\n * whitespace rewritten on every build, since the stored copy keeps the whitespace the comparison\n * has already dropped.\n */\nexport function matchesStored({ stored, source }: { stored: string; source: string }): boolean {\n return stored.trim() === source.trim()\n}\n\n/**\n * Writes `data` to `path`, trimming surrounding whitespace and ending the file with a single newline\n * the way prettier, biome, and oxfmt all do.\n * Skips the write when the trimmed content is empty, or when the file already holds that content.\n * Creates any missing parent directories automatically.\n * When `sanity` is `true`, re-reads the file after writing and throws if the content does not match.\n *\n * @example\n * ```ts\n * await write('./src/Pet.ts', source) // writes and returns the trimmed content plus a newline\n * await write('./src/Pet.ts', source) // null — file unchanged\n * await write('./src/Pet.ts', ' ') // null — empty content skipped\n * ```\n */\nexport async function write(path: string, data: string, options: WriteOptions = {}): Promise<string | null> {\n const trimmed = data.trim()\n if (trimmed === '') return null\n\n const content = `${trimmed}\\n`\n const resolved = resolve(path)\n let stored = options.stored\n\n if (stored === undefined) {\n if (runtime.isBun) {\n const file = Bun.file(resolved)\n stored = (await file.exists()) ? await file.text() : null\n } else {\n try {\n stored = await readFile(resolved, { encoding: 'utf-8' })\n } catch {\n /* file doesn't exist yet */\n stored = null\n }\n }\n }\n if (matchesStored({ stored: stored ?? '', source: trimmed })) return null\n\n if (runtime.isBun) {\n await Bun.write(resolved, content)\n return content\n }\n\n // Creating the directory up front costs a syscall per file, and every file after the first in a\n // directory pays it for nothing. Write first and only fall back when the directory is missing,\n // which also stays correct when something removed it mid-run.\n try {\n await writeFile(resolved, content, { encoding: 'utf-8' })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n\n await mkdir(dirname(resolved), { recursive: true })\n await writeFile(resolved, content, { encoding: 'utf-8' })\n }\n\n if (options.sanity) {\n const savedData = await readFile(resolved, { encoding: 'utf-8' })\n if (savedData !== content) {\n throw new Error(`Sanity check failed for ${path}\\n\\nData[${data.length}]:\\n${data}\\n\\nSaved[${savedData.length}]:\\n${savedData}\\n`)\n }\n return savedData\n }\n\n return content\n}\n\n/**\n * Recursively removes `path`. Silently succeeds when `path` does not exist.\n *\n * @example\n * ```ts\n * await clean('./dist')\n * ```\n */\nexport async function clean(path: string): Promise<void> {\n return rm(path, { recursive: true, force: true })\n}\n\n/**\n * Converts a filesystem path to use POSIX (`/`) separators.\n *\n * Most of the codebase compares and composes paths as strings (prefix matching, joining for\n * import specifiers, splitting on `/`). On POSIX `path.resolve` already returns `/`-separated\n * paths, but on Windows it returns `\\`-separated paths, which breaks every such comparison.\n *\n * Routing every path that crosses a module boundary through `toPosixPath` keeps the rest of the\n * code platform-agnostic. The conversion runs unconditionally so Windows-specific behavior is\n * exercisable from POSIX CI.\n *\n * @example\n * toPosixPath('C:\\\\repo\\\\src\\\\pet.ts') // 'C:/repo/src/pet.ts'\n */\nexport function toPosixPath(filePath: string): string {\n return filePath.replaceAll('\\\\', '/')\n}\n\n/**\n * Strips the file extension from a path or file name.\n * Only removes the last `.ext` segment when the dot is not part of a directory name.\n *\n * @example\n * trimExtName('petStore.ts') // 'petStore'\n * trimExtName('/src/models/pet.ts') // '/src/models/pet'\n * trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'\n * trimExtName('noExtension') // 'noExtension'\n */\nexport function trimExtName(text: string): string {\n const dotIndex = text.lastIndexOf('.')\n if (dotIndex > 0 && !text.includes('/', dotIndex)) {\n return text.slice(0, dotIndex)\n }\n return text\n}\n\n/**\n * Resolves to `true` when `path` is `parent` itself or nested inside it. Both sides are resolved\n * to absolute paths first, so relative and `..`-containing inputs compare correctly.\n *\n * Guards a destructive or an out-of-tree operation: before wiping an output directory, check that\n * it does not contain the project root, and before loading a path a caller supplied, check that it\n * did not escape the directory it is allowed to read from.\n *\n * @example\n * isPathInside('./src/gen', '.') // true — nested inside the root\n * isPathInside('.', '.') // true — the same directory counts as inside\n * isPathInside('.', './src/gen') // false — the root is not inside its own output\n * isPathInside('../other', '.') // false — escapes the root\n */\nexport function isPathInside(path: string, parent: string): boolean {\n const resolvedPath = resolve(path)\n const resolvedParent = resolve(parent)\n if (resolvedPath === resolvedParent) {\n return true\n }\n\n const rel = relative(resolvedParent, resolvedPath)\n\n return rel !== '' && !rel.startsWith('..') && !isAbsolute(rel)\n}\n","/** A value that may already be resolved or still pending.\n *\n * @example\n * ```ts\n * function load(id: string): PossiblePromise<string> {\n * return cache.get(id) ?? fetchRemote(id)\n * }\n * ```\n */\nexport type PossiblePromise<T> = Promise<T> | T\n\n/** Returns `true` when `result` is a thenable `Promise`.\n *\n * @example\n * ```ts\n * isPromise(Promise.resolve(1)) // true\n * isPromise(42) // false\n * ```\n */\nexport function isPromise<T>(result: PossiblePromise<T>): result is Promise<T> {\n return result !== null && result !== undefined && typeof (result as Record<string, unknown>)['then'] === 'function'\n}\n\ntype Store<TKey, TValue> = {\n has(key: TKey): boolean\n get(key: TKey): TValue | undefined\n set(key: TKey, value: TValue): unknown\n}\n\n/**\n * Wraps `factory` with a keyed cache backed by the provided store.\n *\n * Pass a `WeakMap` for object keys (results are GC-eligible when the key is\n * collected) or a `Map` for primitive keys. For multi-argument functions,\n * nest two `memoize` calls — the outer keyed by the first argument, the\n * inner (created once per outer miss) keyed by the second.\n *\n * Because the cache is owned by the caller, it can be shared, inspected, or\n * cleared independently of the memoized function.\n *\n * @example Single WeakMap key\n * ```ts\n * const cache = new WeakMap<SchemaNode, Set<string>>()\n * const getRefs = memoize(cache, (node) => collectRefs(node))\n * ```\n *\n * @example Single Map key (primitive)\n * ```ts\n * const cache = new Map<string, Resolver>()\n * const getResolver = memoize(cache, (name) => buildResolver(name))\n * ```\n *\n * @example Two-level (object + primitive)\n * ```ts\n * const outer = new WeakMap<Params[], Map<string, Params[]>>()\n * const fn = memoize(outer, (params) => memoize(new Map(), (key) => transform(params, key)))\n * fn(params)('camelcase')\n * ```\n */\nexport function memoize<TKey, TValue>(store: Store<TKey, TValue>, factory: (key: TKey) => TValue): (key: TKey) => TValue {\n return (key: TKey): TValue => {\n if (store.has(key)) return store.get(key)!\n const value = factory(key)\n store.set(key, value)\n return value\n }\n}\n\ntype ParallelOptions<TItem> = {\n /**\n * Items to work through, handed out in order.\n */\n items: ReadonlyArray<TItem>\n /**\n * How many items may be in flight at once.\n */\n limit: number\n /**\n * Runs once per item, with the item's position so a caller can report progress.\n */\n run(item: TItem, index: number): Promise<void>\n}\n\n/**\n * Runs `run` over every item with at most `limit` in flight. Workers share one iterator, so each\n * takes the next item the moment it frees up instead of waiting for a batch to drain.\n *\n * @example\n * ```ts\n * await inParallel({ items: files, limit: 50, run: (file) => storage.writeItem(file.path, file.source) })\n * ```\n */\nexport async function inParallel<TItem>({ items, limit, run }: ParallelOptions<TItem>): Promise<void> {\n const queue = items.entries()\n\n const worker = async (): Promise<void> => {\n for (const [index, item] of queue) await run(item, index)\n }\n\n await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => worker()))\n}\n","/**\n * Calculates elapsed time in milliseconds from a high-resolution `process.hrtime` start time.\n * Rounds to 2 decimal places for sub-millisecond precision without noise.\n *\n * @example\n * ```ts\n * const start = process.hrtime()\n * doWork()\n * getElapsedMs(start) // 42.35\n * ```\n */\nexport function getElapsedMs(hrStart: [number, number]): number {\n const [seconds, nanoseconds] = process.hrtime(hrStart)\n const ms = seconds * 1000 + nanoseconds / 1e6\n return Math.round(ms * 100) / 100\n}\n\n/**\n * Converts a millisecond duration into a human-readable string (`ms`, `s`, or `m s`).\n *\n * @example\n * ```ts\n * formatMs(250) // '250ms'\n * formatMs(1500) // '1.50s'\n * formatMs(90000) // '1m 30.0s'\n * ```\n */\nexport function formatMs(ms: number): string {\n if (ms >= 60000) {\n const mins = Math.floor(ms / 60000)\n const secs = ((ms % 60000) / 1000).toFixed(1)\n return `${mins}m ${secs}s`\n }\n\n if (ms >= 1000) {\n return `${(ms / 1000).toFixed(2)}s`\n }\n return `${Math.round(ms)}ms`\n}\n","","import { existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport { pathToFileURL } from 'node:url'\nimport type { Adapter, Plugin } from '@kubb/core'\nimport { camelCase } from '@internals/utils'\nimport type { JSONKubbConfig, OptionValue } from './protocol.ts'\n\n/**\n * Turns the JSON config Studio sends back into live Kubb objects.\n *\n * A plugin or adapter instance carries closures (`parse`, `getImports`, ...) that cannot survive\n * JSON, so both sides pass options over the wire and the factory is re-invoked here with the merged\n * result. Only `@kubb/plugin-*` packages are resolved this way, so the reinstantiated factory is\n * always one Kubb ships, never an arbitrary module the payload names.\n */\n\ntype PluginFactory = (options: unknown) => Plugin\n\n/**\n * Imports a package, falling back to how the user's project would resolve it.\n *\n * `import()` resolves from this file, so a linked or globally installed Studio (`pnpm link`,\n * `npm i -g`) only sees its own `node_modules` and misses the plugins installed next to the user's\n * config. The retry resolves from `process.cwd()` instead.\n */\nasync function importFromProject(packageName: string): Promise<Record<string, unknown>> {\n try {\n return await import(packageName)\n } catch {\n const require = createRequire(pathToFileURL(`${process.cwd()}/`))\n // `require.resolve` picks the package's `require` condition, so prefer the ESM build sitting\n // next to it. Loading the CJS copy would pull in a second `@kubb/core` instance.\n const resolved = require.resolve(packageName)\n const esm = resolved.replace(/\\.cjs$/, '.js')\n\n return await import(pathToFileURL(esm !== resolved && existsSync(esm) ? esm : resolved).href)\n }\n}\n\n/**\n * Strips the `@kubb/` scope from a plugin package name, matching the `name` convention Kubb\n * plugin factories use internally.\n *\n * @example\n * ```ts\n * toPluginName('@kubb/plugin-ts') // 'plugin-ts'\n * ```\n */\nfunction toPluginName(packageName: string): string {\n return packageName.split('/').pop() ?? packageName\n}\n\n/**\n * Adds the `@kubb/` scope a plugin's package carries but its `name` does not, the inverse of\n * {@link toPluginName}. A name outside the `plugin-` convention is left alone, so a third-party\n * plugin is not reported as one of Kubb's.\n *\n * @example\n * ```ts\n * toPackageName('plugin-ts') // '@kubb/plugin-ts'\n * toPackageName('@acme/my-plugin') // '@acme/my-plugin'\n * ```\n */\nexport function toPackageName(name: string): string {\n return name.startsWith('plugin-') ? `@kubb/${name}` : name\n}\n\n/**\n * Derives the conventional named export for a `@kubb/*` plugin package from its package name.\n *\n * @example\n * ```ts\n * toExportName('@kubb/plugin-react-query') // 'pluginReactQuery'\n * toExportName('@kubb/plugin-ts') // 'pluginTs'\n * ```\n */\nexport function toExportName(packageName: string): string {\n return camelCase(toPluginName(packageName))\n}\n\n/**\n * A `@kubb/plugin-*` package specifier. Nothing else may reach `import()`: only Kubb's own\n * plugins are supported, so a payload naming anything else, a third-party package or a path, is\n * refused before it can execute.\n */\nconst KUBB_PLUGIN_SPECIFIER = /^@kubb\\/plugin-[\\w.-]+$/\n\n/**\n * Whether `name` is a `@kubb/plugin-*` specifier. Exported so `configFile.ts` can refuse the same\n * shape before printing a Studio-supplied plugin name into the config file's source text.\n */\nexport function isKubbPluginSpecifier(name: string): boolean {\n return KUBB_PLUGIN_SPECIFIER.test(name)\n}\n\n/**\n * Dynamically imports a `@kubb/plugin-*` package and returns its factory function.\n *\n * Packages must be pre-installed in the Docker image at build time via the `KUBB_PACKAGES`\n * build ARG, no runtime installation is possible in the distroless container.\n *\n * Resolution order: the camelCase named export the package name implies (e.g. `pluginTs`), then\n * the default export.\n *\n * @throws if the package cannot be imported or exports no callable factory.\n */\nasync function loadPluginFactory(packageName: string): Promise<PluginFactory> {\n if (!isKubbPluginSpecifier(packageName)) {\n throw new Error(`Plugin \"${packageName}\" is not a @kubb/plugin-* package. Kubb Studio only supports Kubb's own plugins.`)\n }\n\n let mod: Record<string, unknown>\n try {\n mod = await importFromProject(packageName)\n } catch (cause) {\n throw new Error(`Plugin \"${packageName}\" could not be loaded. Make sure it is installed: \\`npm install ${packageName}\\``, { cause })\n }\n\n const exportName = toExportName(packageName)\n\n if (typeof mod[exportName] === 'function') return mod[exportName] as PluginFactory\n\n if (typeof mod['default'] === 'function') return mod['default'] as PluginFactory\n\n throw new Error(`Plugin \"${packageName}\" does not export a callable factory. Tried the named export \"${exportName}\" and \"default\".`)\n}\n\n/**\n * Resolves each plugin entry by dynamically importing the `@kubb/plugin-*` package and\n * calling its factory with the provided options.\n *\n * Packages must be pre-installed in the Docker image at build time, use the `KUBB_PACKAGES`\n * build ARG to control which ones are available at runtime.\n *\n * @example\n * ```ts\n * { name: '@kubb/plugin-react-query', options: { output: { path: './hooks' } } }\n * { name: '@kubb/plugin-ts', options: { output: { path: './types' } } }\n * ```\n */\nexport async function resolvePlugins(plugins: NonNullable<JSONKubbConfig['plugins']>): Promise<Array<Plugin>> {\n return Promise.all(\n plugins.map(async ({ name, options }) => {\n const factory = await loadPluginFactory(name)\n return factory(options ?? {}) as Plugin\n }),\n )\n}\n\ntype PackageJSON = {\n version?: string\n}\n\n/** The installed version of each plugin's package, plus the names that could not be resolved. */\nexport async function resolvePeerDependencies(names: Array<string>): Promise<{\n peerDependencies: Record<string, string>\n missingDependencies: Array<string>\n}> {\n const require = createRequire(import.meta.url)\n const uniqueNames = [...new Set(names.map(toPackageName))]\n const peerDependencies: Record<string, string> = {}\n const missingDependencies: Array<string> = []\n\n const versions = await Promise.all(\n uniqueNames.map(async (name) => {\n try {\n const path = require.resolve(`${name}/package.json`)\n const packageJSON = JSON.parse(await readFile(path, 'utf8')) as PackageJSON\n return packageJSON.version\n } catch {\n return undefined\n }\n }),\n )\n\n for (const [index, name] of uniqueNames.entries()) {\n const version = versions[index]\n if (version) {\n peerDependencies[name] = version\n continue\n }\n missingDependencies.push(name)\n }\n\n return { peerDependencies, missingDependencies }\n}\n\n/**\n * Whether `value` is an object literal or a null-prototype object, not an array or class instance.\n */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null) return false\n const prototype = Object.getPrototypeOf(value)\n return prototype === null || prototype === Object.prototype\n}\n\n/**\n * Whether `value` survives a JSON round trip, so it can be printed into a config file as a literal.\n * A function, `undefined`, a non-finite number or a class instance comes back from Studio as a\n * lossy copy, so an edit carrying one is refused rather than written into the user's source.\n */\nexport function isOptionValue(value: unknown): value is OptionValue {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return true\n if (typeof value === 'number') return Number.isFinite(value)\n if (Array.isArray(value)) return value.every(isOptionValue)\n if (isPlainObject(value)) return Object.values(value).every(isOptionValue)\n\n return false\n}\n\n/**\n * Deep-merges Studio's options over the disk options, with Studio taking priority, except where the\n * disk value cannot survive JSON. Studio only ever saw a lossy copy of such a value, so the disk\n * value is kept rather than replaced by what Studio echoes back. Plain objects merge key by key, so\n * Studio can still change a literal that sits next to a function (e.g. `group.type` beside `group.name`).\n *\n * @example\n * ```ts\n * mergeOptions({ macros: [camelCaseMacro], syntaxType: 'type' }, { macros: [{ name: 'camelCase' }], syntaxType: 'interface' })\n * // { macros: [camelCaseMacro], syntaxType: 'interface' }\n * ```\n */\nexport function mergeOptions(disk: Record<string, unknown>, studio: Record<string, unknown>): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...disk }\n\n for (const [key, value] of Object.entries(studio)) {\n const current = disk[key]\n\n if (isPlainObject(current) && isPlainObject(value)) {\n merged[key] = mergeOptions(current, value)\n continue\n }\n if (current !== undefined && !isOptionValue(current)) continue\n\n merged[key] = value\n }\n\n return merged\n}\n\n/**\n * Merges studio plugin options with disk config plugins.\n * Studio takes priority: options from studio win over disk (except values only the disk config\n * can express, see {@link mergeOptions}), and a plugin Studio explicitly\n * disabled is dropped even when the disk config still lists it. Disk plugins without a studio\n * counterpart are kept as-is. Studio plugins not present on disk are appended.\n *\n * For plugins present in both configs, the plugin is re-instantiated with merged options\n * so that all internal closures correctly reference the merged values.\n */\nexport async function mergePlugins(\n diskPlugins: Array<Plugin> | undefined,\n studioPlugins: JSONKubbConfig['plugins'] | undefined,\n): Promise<Array<Plugin> | undefined> {\n // Matched on the package's base name rather than by instantiating first. Every Kubb plugin\n // factory returns exactly that (`@kubb/plugin-ts` → `plugin-ts`), enforced by the `satisfies` on\n // each factory's name.\n const disabledNames = new Set((studioPlugins ?? []).filter((entry) => entry.disabled).map((entry) => toPluginName(entry.name)))\n const activeDiskPlugins = disabledNames.size ? diskPlugins?.filter((plugin) => !disabledNames.has(plugin.name)) : diskPlugins\n const activeStudioPlugins = studioPlugins?.filter((entry) => !entry.disabled)\n\n if (!activeDiskPlugins && !activeStudioPlugins?.length) return undefined\n if (!activeStudioPlugins?.length) return activeDiskPlugins\n\n if (!activeDiskPlugins) return resolvePlugins(activeStudioPlugins)\n\n const studioEntryByName = new Map(activeStudioPlugins.map((entry) => [toPluginName(entry.name), entry] as const))\n const diskNames = new Set(activeDiskPlugins.map((plugin) => plugin.name))\n\n // Each plugin is instantiated once, with its final options. Resolving the whole payload first\n // just to read the names would build every overlapping plugin twice and discard the first.\n const merged = await Promise.all(\n activeDiskPlugins.map(async (diskPlugin) => {\n const studioEntry = studioEntryByName.get(diskPlugin.name)\n if (!studioEntry) return diskPlugin\n\n // Disk as base, studio overrides, then re-instantiate so the plugin's closures reference the\n // merged values. A plugin that never sets `options` (e.g. `@kubb/plugin-barrel`) leaves\n // `diskPlugin.options` undefined.\n const options = mergeOptions((diskPlugin.options as Record<string, unknown>) ?? {}, (studioEntry.options as Record<string, unknown>) ?? {})\n const [resolved] = await resolvePlugins([{ name: studioEntry.name, options }])\n\n return resolved ?? diskPlugin\n }),\n )\n\n const studioOnly = activeStudioPlugins.filter((entry) => !diskNames.has(toPluginName(entry.name)))\n\n return [...merged, ...(await resolvePlugins(studioOnly))]\n}\n\n/**\n * Merges Studio-provided adapter option overrides into the disk config's adapter.\n *\n * Adapter instances carry live functions (`parse`, `getImports`, ...) that can't survive\n * JSON serialization over the WebSocket, so `studioOptions` is treated as an options patch\n * rather than a replacement adapter. Re-invokes the same `@kubb/adapter-<name>` factory the\n * disk config used, with the merged options, so the resulting instance has fresh closures\n * over the merged values instead of a plain object missing `parse`.\n */\nexport async function mergeAdapter(diskAdapter: Adapter | undefined, studioOptions: object | undefined): Promise<Adapter | undefined> {\n if (!studioOptions || !diskAdapter) {\n return diskAdapter\n }\n\n const packageName = `@kubb/adapter-${diskAdapter.name}`\n const mod = await importFromProject(packageName)\n const factory = mod[toExportName(packageName)]\n\n if (typeof factory !== 'function') {\n return diskAdapter\n }\n\n const mergedOptions = mergeOptions((diskAdapter.options as Record<string, unknown>) ?? {}, studioOptions as Record<string, unknown>)\n\n return factory(mergedOptions) as Adapter\n}\n","import { writeFile } from 'node:fs/promises'\nimport { read } from '@internals/utils'\nimport { builders, detectCodeFormat, generateCode, parseModule } from 'magicast'\nimport type { ASTNode, ProxifiedModule } from 'magicast'\nimport type { ConfigEdit, ConfigEditOutcome, ConfigFileView, ConfigRef, ConfigView, OptionValue, PluginView } from './protocol.ts'\nimport { isKubbPluginSpecifier, isOptionValue, toExportName } from './resolveConfig.ts'\n\n/**\n * A valid JavaScript identifier, so an import name can only ever print as `import { name } from`,\n * never as source that breaks out of the import statement.\n */\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/\n\n/**\n * A config or plugin options object literal in the file.\n */\ntype ObjectNode = Extract<ASTNode, { type: 'ObjectExpression' }>\n\n/**\n * A `pluginX(...)` call in a config's `plugins` array.\n */\ntype CallNode = Extract<ASTNode, { type: 'CallExpression' }>\n\n/**\n * A `key: value` entry of an object literal.\n */\ntype ObjectPropertyNode = Extract<ASTNode, { type: 'ObjectProperty' }>\n\n/**\n * `key: value` as an object literal property, in the file's quote and key style.\n *\n * Uses magicast's literal builder for the key/value nodes, then wraps them as a Babel\n * `ObjectProperty`, the type the rest of this file reads.\n */\nfunction literalProperty({ key, value }: { key: string; value: OptionValue }): ObjectPropertyNode {\n const built = (builders.literal({ [key]: value }) as unknown as ObjectNode).properties[0] as unknown as ObjectPropertyNode\n return { type: 'ObjectProperty', key: built.key, value: built.value, computed: false, shorthand: false }\n}\n\n/**\n * What `applyConfigEdits` did to a config file.\n */\ntype ApplyResult = {\n /**\n * The file's text after every applicable edit, unchanged from the input when none applied.\n */\n source: string\n /**\n * One entry per edit, in the order they were given.\n */\n outcomes: Array<ConfigEditOutcome>\n /**\n * Whether `source` differs from the input.\n */\n changed: boolean\n}\n\n/**\n * Marks the comment block a `disable-plugin` leaves behind, so `enable-plugin` can find its way\n * back to the exact lines it commented out. Carries the block's line count, so `enable-plugin`\n * restores exactly those lines instead of scanning forward through whatever comments follow.\n */\nconst DISABLED_MARKER = 'kubb:disabled'\n\n/**\n * The plugin and comment-block length a marker line names, when `line` is one.\n */\nfunction parseMarker(line: string): { plugin: string; lineCount: number } | undefined {\n const trimmed = line.trim()\n if (!trimmed.startsWith(`// ${DISABLED_MARKER} `)) {\n return undefined\n }\n\n const match = trimmed.slice(`// ${DISABLED_MARKER} `.length).match(/^(.+)\\s+(\\d+)$/)\n return match ? { plugin: match[1]!, lineCount: Number(match[2]) } : undefined\n}\n\n/**\n * Steps through a config's wrappers to the object literal underneath: a `satisfies`/`as`\n * assertion, a `() => ...` factory, or a factory whose block body returns the config.\n */\nfunction unwrap(node: ASTNode | null | undefined): ASTNode | undefined {\n if (!node) {\n return undefined\n }\n if (node.type === 'TSAsExpression' || node.type === 'TSSatisfiesExpression') {\n return unwrap(node.expression)\n }\n if (node.type !== 'ArrowFunctionExpression' && node.type !== 'FunctionExpression') {\n return node\n }\n if (node.body.type !== 'BlockStatement') {\n return unwrap(node.body)\n }\n\n const returned = node.body.body.find((statement): statement is Extract<ASTNode, { type: 'ReturnStatement' }> => statement.type === 'ReturnStatement')\n return unwrap(returned?.argument)\n}\n\n/**\n * Every config object in `export default defineConfig(...)`, or why the file is unmanaged.\n *\n * An array export gets one entry per element, matching {@link ConfigRef}'s numeric index.\n *\n * Walks the parsed AST rather than magicast's proxies, which throw on node types they cannot\n * cast, most of what an unmanaged config file is made of.\n */\nfunction findConfigs(mod: ProxifiedModule): { configs: Array<ObjectNode> } | { reason: string } {\n const body = mod.$ast.type === 'Program' ? mod.$ast.body : []\n const declaration = body.find((node): node is Extract<ASTNode, { type: 'ExportDefaultDeclaration' }> => node.type === 'ExportDefaultDeclaration')\n\n const exported = unwrap(declaration?.declaration)\n if (!exported) {\n return { reason: 'no default export found' }\n }\n if (exported.type !== 'CallExpression' || exported.callee.type !== 'Identifier' || exported.callee.name !== 'defineConfig') {\n return { reason: 'default export is not a defineConfig(...) call' }\n }\n\n const argument = unwrap(exported.arguments[0])\n if (!argument) {\n return { reason: 'defineConfig(...) was called without a config' }\n }\n if (argument.type === 'ArrayExpression') {\n const configs: Array<ObjectNode> = []\n\n for (const element of argument.elements) {\n const entry = unwrap(element)\n if (entry?.type !== 'ObjectExpression') {\n return { reason: 'config is not an object literal' }\n }\n configs.push(entry)\n }\n return { configs }\n }\n if (argument.type !== 'ObjectExpression') {\n return { reason: 'config is not an object literal' }\n }\n return { configs: [argument] }\n}\n\n/**\n * The config entry an edit names, defaulting to the first when it names none.\n */\nfunction selectConfig(configs: Array<ObjectNode>, ref: ConfigRef | undefined): ObjectNode | undefined {\n if (ref === undefined) {\n return configs[0]\n }\n if (typeof ref === 'number') {\n return configs[ref]\n }\n return configs.find((config) => configName(config) === ref)\n}\n\nfunction configName(config: ObjectNode): string | undefined {\n const name = property(config, 'name')\n return name?.type === 'StringLiteral' ? name.value : undefined\n}\n\n/**\n * The name of an object literal property, for the two key shapes a config uses: `key: value` and\n * `'key': value`. `undefined` for a computed key, which the patcher never touches.\n */\nfunction propertyKey(entry: Extract<ASTNode, { type: 'ObjectProperty' }>): string | undefined {\n if (entry.key.type === 'Identifier') {\n return entry.key.name\n }\n if (entry.key.type === 'StringLiteral') {\n return entry.key.value\n }\n return undefined\n}\n\n/**\n * The index of an object literal's own property named `key`, `-1` when it has none.\n */\nfunction entryIndex({ node, key }: { node: ObjectNode; key: string }): number {\n return node.properties.findIndex((entry) => entry.type === 'ObjectProperty' && propertyKey(entry) === key)\n}\n\n/**\n * The value node of an object literal's own property.\n */\nfunction property(node: ObjectNode, key: string): ASTNode | undefined {\n const index = entryIndex({ node, key })\n return index === -1 ? undefined : (node.properties[index] as ObjectPropertyNode).value\n}\n\n/**\n * Writes `key: value` on an object literal, replacing the value when the property is already there.\n *\n * An existing property has its value swapped in place rather than being replaced whole, so recast\n * reprints only that value and leaves the object's own layout alone.\n */\nfunction setProperty({ node, key, value }: { node: ObjectNode; key: string; value: OptionValue }): void {\n const entry = literalProperty({ key, value })\n const index = entryIndex({ node, key })\n\n if (index === -1) {\n node.properties.push(entry)\n return\n }\n ;(node.properties[index] as ObjectPropertyNode).value = entry.value\n}\n\n/**\n * Drops `key` from an object literal.\n */\nfunction removeProperty({ node, key }: { node: ObjectNode; key: string }): void {\n const index = entryIndex({ node, key })\n if (index !== -1) {\n node.properties.splice(index, 1)\n }\n}\n\n/**\n * Reads a literal node's value: a primitive, or an object/array built only from primitives.\n * `undefined` for anything else, so a caller can use this both to read a value and to check\n * whether a node is a literal at all.\n */\nfunction readLiteral(node: ASTNode | undefined): OptionValue | undefined {\n if (!node) {\n return undefined\n }\n if (node.type === 'StringLiteral' || node.type === 'NumericLiteral' || node.type === 'BooleanLiteral') {\n return node.value\n }\n if (node.type === 'NullLiteral') {\n return null\n }\n if (node.type === 'TemplateLiteral') {\n return node.expressions.length === 0 ? (node.quasis[0]?.value.cooked ?? '') : undefined\n }\n if (node.type === 'UnaryExpression') {\n const value = readLiteral(node.argument)\n if (typeof value !== 'number') {\n return undefined\n }\n if (node.operator === '-') {\n return -value\n }\n if (node.operator === '+') {\n return value\n }\n return undefined\n }\n if (node.type === 'ArrayExpression') {\n const values = node.elements.map((element) => (element ? readLiteral(element) : undefined))\n return values.every((value) => value !== undefined) ? values : undefined\n }\n if (node.type === 'ObjectExpression') {\n const entries: Record<string, OptionValue> = {}\n for (const entry of node.properties) {\n if (entry.type !== 'ObjectProperty') {\n return undefined\n }\n const key = propertyKey(entry)\n const value = readLiteral(entry.value)\n if (key === undefined || value === undefined) {\n return undefined\n }\n entries[key] = value\n }\n return entries\n }\n return undefined\n}\n\n/**\n * Maps a factory identifier in the file back to the module it was imported from.\n */\nfunction importedFrom(mod: ProxifiedModule): Map<string, string> {\n return new Map(mod.imports.$items.map((item) => [item.local, item.from]))\n}\n\n/**\n * Every `pluginX(...)` element of a config's plugins array that resolves to an import.\n */\nfunction pluginCalls(mod: ProxifiedModule, config: ObjectNode): Array<{ importName: string; packageName: string; call: CallNode }> {\n const plugins = property(config, 'plugins')\n if (plugins?.type !== 'ArrayExpression') {\n return []\n }\n\n const imports = importedFrom(mod)\n\n return plugins.elements.flatMap((element) => {\n if (element?.type !== 'CallExpression' || element.callee.type !== 'Identifier') {\n return []\n }\n const packageName = imports.get(element.callee.name)\n return packageName ? [{ importName: element.callee.name, packageName, call: element }] : []\n })\n}\n\n/**\n * Plugins a previous `disable-plugin` commented out of this config, keyed by package name.\n *\n * Read from the marker lines rather than the AST, since a commented-out call is no longer a node.\n */\nfunction disabledMarkers(source: string): Array<{ packageName: string; line: number }> {\n return source.split('\\n').flatMap((line, index) => {\n const marker = parseMarker(line)\n return marker ? [{ packageName: marker.plugin, line: index + 1 }] : []\n })\n}\n\n/**\n * Reads which plugins the file declares and which of their options Studio may write.\n *\n * @example\n * ```ts\n * const view = readConfig(await readFile('kubb.config.ts', 'utf8'))\n * if (view.managed) {\n * view.configs.forEach((config) => console.log(config.name, config.plugins.length))\n * }\n * ```\n */\nexport function readConfig(source: string): ConfigFileView {\n const parsed = parseConfigs(source)\n if ('reason' in parsed) {\n return { managed: false, reason: parsed.reason }\n }\n\n const { mod, configs } = parsed\n const importNames = new Map([...importedFrom(mod)].map(([local, from]) => [from, local]))\n const disabled = disabledMarkers(source)\n\n return {\n managed: true,\n configs: configs.map((config): ConfigView => {\n const plugins = pluginCalls(mod, config).map(({ importName, packageName, call }): PluginView => {\n const entries: PluginView['options'] = {}\n const options = call.arguments[0]\n\n if (options?.type === 'ObjectExpression') {\n for (const entry of options.properties) {\n if (entry.type !== 'ObjectProperty') {\n continue\n }\n const key = propertyKey(entry)\n if (key === undefined) {\n continue\n }\n const value = readLiteral(entry.value)\n entries[key] = value === undefined ? { literal: false } : { literal: true, value }\n }\n }\n return { importName, packageName, options: entries }\n })\n\n const start = config.loc?.start.line ?? 0\n const end = config.loc?.end.line ?? Number.POSITIVE_INFINITY\n\n for (const { packageName } of disabled.filter((entry) => entry.line >= start && entry.line <= end)) {\n plugins.push({\n importName: importNames.get(packageName) ?? toExportName(packageName),\n packageName,\n options: {},\n disabled: true,\n })\n }\n\n return { name: configName(config), plugins }\n }),\n }\n}\n\n/**\n * The options object of a plugin call, when it was called with one.\n */\nfunction getOptions(call: CallNode): ObjectNode | undefined {\n const options = call.arguments[0]\n return options?.type === 'ObjectExpression' ? options : undefined\n}\n\n/**\n * The options object of a plugin call, creating an empty one when the plugin was called bare.\n */\nfunction ensureOptions(call: CallNode): ObjectNode | undefined {\n if (call.arguments.length === 0) {\n call.arguments.push({ type: 'ObjectExpression', properties: [] })\n }\n return getOptions(call)\n}\n\n/**\n * Walks `path` down to the object holding its last key, descending only through object literals.\n */\nfunction optionParent(options: ObjectNode, path: Array<string>): { object: ObjectNode; key: string } | { reason: string } {\n let object = options\n\n for (const [index, key] of path.entries()) {\n if (index === path.length - 1) {\n return { object, key }\n }\n\n if (property(object, key) === undefined) {\n setProperty({ node: object, key, value: {} })\n }\n\n const next = property(object, key)\n if (next?.type !== 'ObjectExpression') {\n return { reason: `${key} is not an object, so ${path.join('.')} cannot be reached` }\n }\n object = next\n }\n return { reason: 'no option path given' }\n}\n\n/**\n * Writes `value` at `path` inside a plugin call's options, creating the options object and any\n * intermediate object along the path as needed. Refuses when the current value at `path` is\n * something other than a literal, so an option customized in code is never overwritten.\n */\nfunction applySet(call: CallNode, path: Array<string>, value: unknown): string | undefined {\n if (!isOptionValue(value)) {\n return 'the value is not a literal that can be written to a config file'\n }\n\n const options = ensureOptions(call)\n if (!options) {\n return 'the plugin was not called with an object literal'\n }\n\n const target = optionParent(options, path)\n if ('reason' in target) {\n return target.reason\n }\n\n const current = property(target.object, target.key)\n if (current !== undefined && readLiteral(current) === undefined) {\n return `${path.join('.')} is customized in code`\n }\n\n setProperty({ node: target.object, key: target.key, value })\n return undefined\n}\n\n/**\n * Deletes the property at `path` inside a plugin call's options, falling the plugin back to its\n * default for that option. Refuses when the value at `path` is not a literal, for the same reason\n * `applySet` does.\n */\nfunction applyRemove(call: CallNode, path: Array<string>): string | undefined {\n const options = getOptions(call)\n if (!options) {\n return 'the plugin has no options to remove'\n }\n\n const target = optionParent(options, path)\n if ('reason' in target) {\n return target.reason\n }\n\n const current = property(target.object, target.key)\n if (current === undefined) {\n return `${path.join('.')} is not set`\n }\n if (readLiteral(current) === undefined) {\n return `${path.join('.')} is customized in code`\n }\n\n removeProperty({ node: target.object, key: target.key })\n return undefined\n}\n\n/**\n * Outcome of `applyAddPlugin`. `addImport` is set when the new plugin call needs an import line\n * the caller must still insert; absent when the import was already there.\n */\ntype AddPluginResult = { reason: string } | { noop: true } | { addImport?: { importName: string; moduleSpecifier: string } }\n\n/**\n * Adds a `pluginX(...)` call to a config's plugins array. Replaying the same add is a no-op, while\n * an import name collision with an unrelated package remains an error.\n */\nfunction applyAddPlugin(mod: ProxifiedModule, config: ObjectNode, edit: Extract<ConfigEdit, { operation: 'add-plugin' }>): AddPluginResult {\n if (!isKubbPluginSpecifier(edit.plugin)) {\n return { reason: `\"${edit.plugin}\" is not a @kubb/plugin-* package` }\n }\n\n const importName = edit.importName ?? toExportName(edit.plugin)\n if (!IDENTIFIER.test(importName)) {\n return { reason: `\"${importName}\" is not a valid import name` }\n }\n\n if (pluginCalls(mod, config).some((plugin) => plugin.packageName === edit.plugin)) {\n return { noop: true }\n }\n\n const taken = importedFrom(mod).get(importName)\n if (taken && taken !== edit.plugin) {\n return { reason: `${importName} is already imported from ${taken}` }\n }\n\n const options = edit.options ?? {}\n if (!isOptionValue(options)) {\n return { reason: 'the options are not literals that can be written to a config file' }\n }\n\n const plugins = property(config, 'plugins')\n if (plugins?.type !== 'ArrayExpression') {\n return { reason: 'plugins is not an array literal' }\n }\n\n const call = Object.keys(options).length ? builders.functionCall(importName, options) : builders.functionCall(importName)\n plugins.elements.push(call.$ast as CallNode)\n\n return taken ? {} : { addImport: { importName, moduleSpecifier: edit.plugin } }\n}\n\n/**\n * Comments out a plugin call in place, keeping its options on disk so `enable-plugin` can restore\n * them exactly. Operates on `source` text rather than the AST: a commented-out call is no longer a\n * node magicast can address, and the surrounding array must not reflow when its element count\n * never actually changes.\n */\nfunction disablePlugin(source: string, mod: ProxifiedModule, config: ObjectNode, plugin: string): { source: string } | { reason: string } {\n const target = pluginCalls(mod, config).find((entry) => entry.packageName === plugin)\n if (!target) {\n return { reason: `${plugin} is not in the plugins array` }\n }\n\n const loc = target.call.loc\n if (!loc?.start || !loc.end) {\n return { reason: `${plugin} has no source location to comment out` }\n }\n\n const lines = source.split('\\n')\n const from = loc.start.line - 1\n const to = loc.end.line - 1\n const firstLine = lines[from] ?? ''\n const lastLine = lines[to] ?? ''\n\n // Only safe to comment out when the call sits alone on its lines: anything else sharing the\n // first line before it, or the last line after it besides a trailing comma, would be swallowed\n // into the comment along with the call, corrupting the file.\n if (firstLine.slice(0, loc.start.column).trim() !== '' || !/^,?\\s*$/.test(lastLine.slice(loc.end.column))) {\n return { reason: `${plugin} shares a line with other code, so it cannot be commented out safely` }\n }\n\n const indent = firstLine.match(/^\\s*/)?.[0] ?? ''\n const commented = lines.slice(from, to + 1).map((line) => (line.trim() ? `${indent}// ${line.slice(indent.length)}` : indent ? `${indent}//` : '//'))\n lines.splice(from, to - from + 1, `${indent}// ${DISABLED_MARKER} ${plugin} ${commented.length}`, ...commented)\n\n return { source: lines.join('\\n') }\n}\n\n/**\n * Uncomments the block a previous `disable-plugin` left behind for `plugin`.\n */\nfunction enablePlugin(source: string, plugin: string): { source: string } | { reason: string } {\n const lines = source.split('\\n')\n\n for (const [index, line] of lines.entries()) {\n const marker = parseMarker(line)\n if (marker?.plugin !== plugin) {\n continue\n }\n\n // Bounded by the marker's own line count rather than scanning for trailing `//` lines, so a\n // comment or another disabled block right after this one is left untouched.\n const end = index + 1 + marker.lineCount\n const restored = lines.slice(index + 1, end).map((commented) => commented.replace(/^(\\s*)\\/\\/ ?/, '$1'))\n lines.splice(index, end - index, ...restored)\n\n return { source: lines.join('\\n') }\n }\n\n return { reason: `${plugin} is not disabled` }\n}\n\n/**\n * Parses `source` and finds the config entries it exports.\n */\nfunction parseConfigs(source: string): { mod: ProxifiedModule; configs: Array<ObjectNode> } | { reason: string } {\n let mod: ProxifiedModule\n try {\n mod = parseModule(source)\n } catch {\n return { reason: 'the config file could not be parsed' }\n }\n\n const found = findConfigs(mod)\n return 'reason' in found ? found : { mod, configs: found.configs }\n}\n\n/**\n * Re-parses `source` and resolves the config entry an edit targets. Every edit re-parses rather\n * than sharing one module across the batch, since the disable/enable edits rewrite `source` as\n * text and would otherwise leave the others working from a stale tree.\n */\nfunction parseTarget(source: string, ref: ConfigRef | undefined): { mod: ProxifiedModule; config: ObjectNode } | { reason: string } {\n const parsed = parseConfigs(source)\n if ('reason' in parsed) {\n return parsed\n }\n\n const config = selectConfig(parsed.configs, ref)\n if (!config) {\n return { reason: `no config entry found for ${JSON.stringify(ref)}` }\n }\n\n return { mod: parsed.mod, config }\n}\n\n/**\n * Applies edits to a `kubb.config.ts` in place. Every node the edits do not touch keeps its\n * original text, so comments, formatting, and hand-written code around the config survive.\n *\n * Edits are independent: one that cannot be applied is reported in `outcomes` and the rest still run.\n *\n * @example\n * ```ts\n * const { source, outcomes } = applyConfigEdits(current, [\n * { operation: 'set', plugin: '@kubb/plugin-ts', path: ['enum', 'type'], value: 'enum' },\n * ])\n * ```\n *\n * @note recast always reprints a semicolon on a reprinted statement, so editing a block-body\n * `defineConfig` in a semicolon-free file adds one to the `return` line. This is a known gap.\n * Strip it when `detectCodeFormat` reports `useSemi: false`, if it turns out to matter in practice.\n */\nexport function applyConfigEdits(source: string, edits: Array<ConfigEdit>): ApplyResult {\n let current = source\n const format = detectCodeFormat(source)\n const endsWithNewline = source.endsWith('\\n')\n\n const outcomes = edits.map((edit): ConfigEditOutcome => {\n const target = parseTarget(current, edit.config)\n if ('reason' in target) {\n return { edit, applied: false, reason: target.reason }\n }\n const { mod, config } = target\n\n if (edit.operation === 'disable-plugin' || edit.operation === 'enable-plugin') {\n const result = edit.operation === 'disable-plugin' ? disablePlugin(current, mod, config, edit.plugin) : enablePlugin(current, edit.plugin)\n if ('reason' in result) {\n return { edit, applied: false, reason: result.reason }\n }\n current = result.source\n return { edit, applied: true }\n }\n\n if (edit.operation === 'add-plugin') {\n const result = applyAddPlugin(mod, config, edit)\n if ('reason' in result) {\n return { edit, applied: false, reason: result.reason }\n }\n if ('noop' in result) {\n return { edit, applied: true }\n }\n const afterLine = lastImportEndLine(mod)\n let next = generateCode(mod, { format }).code\n if (result.addImport) {\n next = insertImportLine({ source: next, afterLine, ...result.addImport })\n }\n current = withTrailingNewline(next, endsWithNewline)\n return { edit, applied: true }\n }\n\n const pluginCall = pluginCalls(mod, config).find((plugin) => plugin.packageName === edit.plugin)\n if (!pluginCall) {\n return { edit, applied: false, reason: `${edit.plugin} is not in the plugins array` }\n }\n\n const reason = edit.operation === 'set' ? applySet(pluginCall.call, edit.path, edit.value) : applyRemove(pluginCall.call, edit.path)\n if (!reason) {\n current = withTrailingNewline(generateCode(mod, { format }).code, endsWithNewline)\n }\n return { edit, applied: !reason, reason }\n })\n\n return { source: current, outcomes, changed: current !== source }\n}\n\nexport async function writeConfigEdits({ filePath, edits }: { filePath: string; edits: Array<ConfigEdit> }): Promise<ApplyResult> {\n const current = await read(filePath)\n const result = applyConfigEdits(current, edits)\n if (result.changed) await writeFile(filePath, result.source, 'utf-8')\n return result\n}\n\n/**\n * The 1-based line where the file's last import declaration ends, or `0` when it has none. Read\n * off the parsed module, so a multi-line `import {\\n x,\\n} from '...'` reports its closing line\n * rather than the `import` keyword.\n */\nfunction lastImportEndLine(mod: ProxifiedModule): number {\n const body = mod.$ast.type === 'Program' ? mod.$ast.body : []\n\n return body.filter((node) => node.type === 'ImportDeclaration').at(-1)?.loc?.end.line ?? 0\n}\n\n/**\n * Writes an import after the last one already in the file, matching its quote style and whether it\n * ends in a semicolon. `afterLine` is where that last import ends, `0` for a file with none.\n *\n * Written as plain text rather than through magicast's import builder, which prints a brand-new\n * import declaration with its own default spacing and a semicolon regardless of `format`, since\n * that formatting only governs nodes recast can diff against the original source.\n */\nfunction insertImportLine({\n source,\n importName,\n moduleSpecifier,\n afterLine,\n}: {\n source: string\n importName: string\n moduleSpecifier: string\n afterLine: number\n}): string {\n const lines = source.split('\\n')\n\n const lastImportLine = afterLine > 0 ? lines[afterLine - 1] : undefined\n const quote = lastImportLine?.includes(`\"`) ? `\"` : `'`\n const semicolon = lastImportLine?.trimEnd().endsWith(';') ? ';' : ''\n const line = `import { ${importName} } from ${quote}${moduleSpecifier}${quote}${semicolon}`\n\n lines.splice(afterLine, 0, ...(afterLine > 0 ? [line] : [line, '']))\n\n return lines.join('\\n')\n}\n\n/**\n * `generateCode` always drops the file's trailing newline. Restore it when the input had one.\n */\nfunction withTrailingNewline(code: string, hadTrailingNewline: boolean): string {\n if (!hadTrailingNewline || code.endsWith('\\n')) {\n return code\n }\n return `${code}\\n`\n}\n","import { createHash } from 'node:crypto'\nimport { isAbsolute, relative, resolve, sep } from 'node:path'\nimport process from 'node:process'\nimport { inParallel } from '@internals/utils'\nimport { type Config, createKubb, type Diagnostic, Diagnostics, fsStorage, type Hookable, type KubbHooks, type Storage } from '@kubb/core'\nimport type { FilePage, FileSource, ReadFilesResult } from './protocol.ts'\n\nconst READ_CONCURRENCY = 50\nconst MB = 1024 * 1024\nconst INDEX_KEY = 'studio/generations.json'\n\n/**\n * Files a run produced, or the output directory held, keyed by path relative to `root`.\n */\nexport type SourceFiles = { storage: Storage; root: string; paths: Set<string> }\n\n/**\n * The path form {@link SourceFiles} keys on: relative to `root`, with forward slashes.\n */\nexport function relativeStoragePath({ root, filePath }: { root: string; filePath: string }): string {\n return (isAbsolute(filePath) ? relative(resolve(root), filePath) : filePath).replaceAll('\\\\', '/')\n}\n\n/**\n * A set as kept in the store.\n */\ntype KeptSet = {\n /**\n * The paths a read is checked against. Empty when the set was too large to keep its content.\n */\n paths: Array<string>\n hashes: Record<string, string>\n bytes: number\n}\n\ntype KeptGeneration = {\n jobId: string\n /** When the store took it, in epoch milliseconds. Absent on an index written before it existed. */\n keptAt?: number\n output: KeptSet\n disk?: KeptSet\n}\n\n/**\n * The content fingerprint Studio compares snapshots by. Agent runs and CI uploads must agree on it.\n */\nexport const hashOf = (content: string) => createHash('sha1').update(content).digest('hex').slice(0, 16)\n\nconst totalBytes = (entries: Array<KeptGeneration>) => entries.reduce((sum, { output, disk }) => sum + output.bytes + (disk?.bytes ?? 0), 0)\n\nfunction positiveNumber(value: string | undefined): number | undefined {\n const parsed = Number(value)\n return value && Number.isFinite(parsed) && parsed > 0 ? parsed : undefined\n}\n\n/**\n * How many generations an agent keeps and how large they may get, read from\n * `KUBB_AGENT_MAX_GENERATIONS`, `KUBB_AGENT_MAX_GENERATIONS_MB` and `KUBB_AGENT_MAX_SNAPSHOT_MB`.\n * An unset or invalid value keeps the default.\n */\nexport function resolveGenerationLimits(): { maxCount: number; maxMb: number; maxSnapshotMb: number } {\n return {\n maxCount: Math.max(1, Math.floor(positiveNumber(process.env.KUBB_AGENT_MAX_GENERATIONS) ?? 8)),\n maxMb: positiveNumber(process.env.KUBB_AGENT_MAX_GENERATIONS_MB) ?? 100,\n maxSnapshotMb: positiveNumber(process.env.KUBB_AGENT_MAX_SNAPSHOT_MB) ?? 50,\n }\n}\n\n/**\n * Folds error-severity diagnostics into one thrown error so logs name the failing plugin or pass.\n */\nfunction generationFailure(diagnostics: ReadonlyArray<Diagnostic>): Error {\n const reasons = diagnostics\n .filter(Diagnostics.isProblem)\n .filter((diagnostic) => diagnostic.severity === 'error')\n .map((diagnostic) => (diagnostic.plugin ? `${diagnostic.plugin}: ${diagnostic.message}` : diagnostic.message))\n\n if (!reasons.length) return new Error('Generation failed')\n\n return new Error(`Generation failed: ${reasons.length} error${reasons.length === 1 ? '' : 's'}: ${reasons.join('; ')}`)\n}\n\n/**\n * Runs one generation and returns the files it produced. The formatter, the linter, and\n * `output.postGenerate` only run with `allowExec`. Throws when any plugin reports an error.\n */\nexport async function generate({\n config,\n hooks,\n signal,\n allowExec,\n}: {\n config: Config\n hooks?: Hookable<KubbHooks>\n signal?: AbortSignal\n allowExec: boolean\n}): Promise<SourceFiles> {\n const output = allowExec ? config.output : { ...config.output, format: false as const, lint: false as const, postGenerate: [] }\n const kubb = createKubb({ ...config, output }, { hooks, signal })\n const result = await kubb.generate()\n if (!result.success) throw generationFailure(result.diagnostics)\n\n // `kubb.config` carries the defaults, such as the fs storage a config loaded by the CLI leaves unset.\n const { storage, root } = kubb.config\n return {\n storage,\n root,\n paths: new Set(result.files.map((file) => relativeStoragePath({ root, filePath: file.path }))),\n }\n}\n\n/**\n * What the output directory holds on disk before a run. `undefined` when `outputPath` is not a real\n * subdirectory of `root` (listing the root would take in every source file) or holds more than `maxFiles`.\n */\nexport async function listDisk({ root, outputPath, maxFiles }: { root: string; outputPath: string; maxFiles: number }): Promise<SourceFiles | undefined> {\n const outputDir = resolve(root, outputPath)\n const fromRoot = relative(resolve(root), outputDir)\n if (!fromRoot || fromRoot.startsWith('..') || fromRoot.startsWith(sep)) return undefined\n\n const storage = fsStorage()\n const keys = await storage.readKeys(outputDir)\n if (keys.length > maxFiles) return undefined\n\n const paths = keys\n .filter((key) => !key.split('/').includes('node_modules'))\n .map((key) => relative(resolve(root), resolve(outputDir, key)).replaceAll('\\\\', '/'))\n return { storage, root, paths: new Set(paths) }\n}\n\n/**\n * Keeps recent generations by job id in `storage`, with an index next to them so a store on disk\n * survives a restart. A generation is only ever looked up by its job id, so on a pooled sandbox one\n * tenant never reaches another's output. The oldest go past `maxCount` or `maxMb`, but the newest\n * always stays.\n */\nexport function createGenerationStore({\n storage,\n maxCount,\n maxMb,\n ttlMs,\n now = Date.now,\n}: {\n storage: Storage\n maxCount: number\n maxMb: number\n /** How long a generation stays readable. Unset, it stays until count or size pushes it out. */\n ttlMs?: number\n now?: () => number\n}) {\n let index: Array<KeptGeneration> | undefined\n\n // An entry from before `keptAt` existed never expires, so upgrading drops nothing.\n const isLive = (generation: KeptGeneration) => ttlMs === undefined || generation.keptAt === undefined || now() - generation.keptAt < ttlMs\n\n // Hashed so a job id from the wire can never point outside the store.\n const dirOf = (jobId: string) => `studio/generations/${hashOf(jobId)}/`\n\n async function load(): Promise<Array<KeptGeneration>> {\n if (index) return index\n const stored = await storage.readItem(INDEX_KEY).catch(() => null)\n try {\n index = stored ? (JSON.parse(stored) as Array<KeptGeneration>) : []\n } catch {\n index = []\n }\n return index\n }\n\n /**\n * Copies `files` into the store as one set of `jobId`. Above `maxSetMb` only the hashes are kept.\n */\n async function keep({ jobId, source, files, maxSetMb }: { jobId: string; source: FileSource; files: SourceFiles; maxSetMb: number }): Promise<KeptSet> {\n const maxSetBytes = maxSetMb * MB\n const hashes: Record<string, string> = {}\n let bytes = 0\n await inParallel({\n items: [...files.paths],\n limit: READ_CONCURRENCY,\n run: async (path) => {\n // Output outside the root would land outside the store too.\n if (path.split('/').includes('..')) return\n const content = await files.storage.readItem(resolve(files.root, path))\n if (content === null) return\n hashes[path] = hashOf(content)\n bytes += Buffer.byteLength(content)\n if (bytes <= maxSetBytes) await storage.writeItem(`${dirOf(jobId)}${source}/${path}`, content)\n },\n })\n if (bytes > maxSetBytes) {\n await storage.empty(`${dirOf(jobId)}${source}/`)\n return { paths: [], hashes, bytes: 0 }\n }\n return { paths: Object.keys(hashes), hashes, bytes }\n }\n\n async function drop(jobId: string): Promise<void> {\n await storage.empty(dirOf(jobId))\n }\n\n return {\n keep,\n drop,\n get: async (jobId: string) => (await load()).find((generation) => generation.jobId === jobId && isLive(generation)),\n async add(generation: KeptGeneration): Promise<void> {\n const current = await load()\n for (const expired of current.filter((entry) => !isLive(entry))) await drop(expired.jobId)\n const entries = current.filter((entry) => entry.jobId !== generation.jobId && isLive(entry))\n entries.push({ ...generation, keptAt: now() })\n while (entries.length > 1 && (entries.length > maxCount || totalBytes(entries) > maxMb * MB)) {\n await drop(entries.shift()!.jobId)\n }\n index = entries\n await storage.writeItem(INDEX_KEY, JSON.stringify(entries))\n },\n /**\n * Reads the requested paths the set holds, skipping any it does not, one page of lines when `limit` is given.\n */\n async read({\n generation,\n source,\n paths,\n cursor = 0,\n limit,\n }: {\n generation: KeptGeneration\n source: FileSource\n paths: Array<string>\n cursor?: number\n limit?: number\n }): Promise<ReadFilesResult> {\n const kept = new Set(generation[source]?.paths)\n const files: Record<string, string> = {}\n const pages: Record<string, FilePage> = {}\n await inParallel({\n items: paths.filter((path) => kept.has(path)),\n limit: READ_CONCURRENCY,\n run: async (path) => {\n const content = await storage.readItem(`${dirOf(generation.jobId)}${source}/${path}`)\n if (content === null) return\n if (limit === undefined) {\n files[path] = content\n return\n }\n const lines = content.split(/\\r\\n|\\r|\\n/)\n const end = Math.min(cursor + limit, lines.length)\n files[path] = lines.slice(cursor, end).join('\\n')\n pages[path] = { nextCursor: end < lines.length ? end : null, totalLines: lines.length }\n },\n })\n return limit === undefined ? { files } : { files, pages }\n },\n }\n}\n\nexport type GenerationStore = ReturnType<typeof createGenerationStore>\n","import { stripVTControlCharacters } from 'node:util'\nimport { getElapsedMs } from '@internals/utils'\nimport { Diagnostics, type Hookable, type KubbHooks } from '@kubb/core'\nimport { type GenerationEvent, type GenerationEventPayloads, type GenerationEventType, generationEventTypes } from './protocol.ts'\nimport { relativeStoragePath } from './generations.ts'\n\n/** How each published hook's context becomes its wire payload; a hook without a projection fails to compile. */\ntype Projections = { [Type in GenerationEventType]: (...args: KubbHooks[Type]) => GenerationEventPayloads[Type] }\n\nconst MAX_QUEUED_EVENTS = 1_024\nconst RESERVED_EVENTS = 64\nconst isDiscardable = (event: GenerationEvent) => event.type === 'kubb:files:processing:update' || event.type === 'kubb:info' || event.type === 'kubb:success'\n\n/** Forwards selected Kubb lifecycle events to a native Cap'n Web stream. */\nexport function createGenerationStream(\n hooks: Hookable<KubbHooks>,\n jobId: string,\n): { stream: ReadableStream<GenerationEvent>; close: () => Promise<void>; dispose: () => void; fail: (error: unknown) => void } {\n const unhooks: Array<() => void> = []\n let root = ''\n let controller!: ReadableStreamDefaultController<GenerationEvent>\n let closed = false\n const stream = new ReadableStream<GenerationEvent>(\n {\n start: (value) => {\n controller = value\n },\n cancel: () => {\n closed = true\n detach()\n },\n },\n { highWaterMark: MAX_QUEUED_EVENTS },\n )\n\n /**\n * Registers a listener and keeps its remover, so one generation's listeners come off the session\n * emitter again when that generation ends.\n */\n function on<TName extends keyof KubbHooks & string>(name: TName, handler: (...args: KubbHooks[TName]) => unknown): void {\n unhooks.push(hooks.hook(name, handler))\n }\n\n function emitEvent<Type extends GenerationEventType>(type: Type, data: GenerationEventPayloads[Type]): void {\n if (closed) return\n const event = { jobId, type, data, version: 1 as const, timestamp: Date.now() } as unknown as GenerationEvent\n if (controller.desiredSize! <= RESERVED_EVENTS && isDiscardable(event)) return\n if (controller.desiredSize! <= 0) {\n fail(new Error(`Generation event stream exceeded ${MAX_QUEUED_EVENTS} queued events`))\n return\n }\n controller.enqueue(event)\n }\n\n const projections: Projections = {\n 'kubb:plugin:start': ({ plugin }) => [{ plugin: { name: plugin.name } }],\n 'kubb:plugin:end': ({ plugin, duration, success }) => [{ plugin: { name: plugin.name }, duration, success }],\n 'kubb:build:start': ({ config, adapter }) => [{ config: { name: config.name }, adapter: { name: adapter.name } }],\n 'kubb:build:end': ({ files, config, outputDir }) => [\n { files: files.map((file) => ({ path: relativeStoragePath({ root: config.root, filePath: file.path }), name: file.name })), outputDir },\n ],\n 'kubb:files:processing:start': ({ files }) => [{ total: files.length }],\n 'kubb:files:processing:update': ({ files }) => [\n {\n files: files.map(({ file, processed, total, percentage }) => ({\n file: relativeStoragePath({ root, filePath: file.path }),\n processed,\n total,\n percentage,\n })),\n },\n ],\n 'kubb:files:processing:end': ({ files }) => [{ total: files.length }],\n 'kubb:info': ({ message, info }) => [{ message: stripVTControlCharacters(message), info }],\n 'kubb:success': ({ message, info }) => [{ message: stripVTControlCharacters(message), info }],\n 'kubb:warn': ({ message, info }) => [{ message: stripVTControlCharacters(message), info }],\n 'kubb:error': ({ error }) => [{ message: error.message, stack: error.stack }],\n 'kubb:diagnostic': ({ diagnostic }) => [\n {\n code: diagnostic.code,\n message: diagnostic.message,\n severity: diagnostic.severity,\n location: 'location' in diagnostic ? diagnostic.location : undefined,\n help: 'help' in diagnostic ? diagnostic.help : undefined,\n plugin: 'plugin' in diagnostic ? diagnostic.plugin : undefined,\n stack: 'cause' in diagnostic ? diagnostic.cause?.stack : undefined,\n },\n ],\n 'kubb:generation:start': ({ config }) => [{ name: config.name, plugins: config.plugins.length }],\n 'kubb:generation:end': () => [],\n 'kubb:generation:summary': ({ duration, fileCount, failedPlugins, status }) => [{ duration, fileCount, failedPlugins, status }],\n 'kubb:lifecycle:start': () => [],\n 'kubb:lifecycle:end': () => [],\n 'kubb:format:start': () => [],\n 'kubb:format:end': () => [],\n 'kubb:lint:start': () => [],\n 'kubb:lint:end': () => [],\n 'kubb:hooks:start': () => [],\n 'kubb:hooks:end': () => [],\n 'kubb:hook:start': ({ id, command, args }) => [{ id, command, args: args ? [...args] : undefined }],\n 'kubb:hook:line': ({ id, line }) => [{ id, line }],\n 'kubb:hook:end': ({ id, command, args, success, error }) => [\n { id, command, args: args ? [...args] : undefined, success, error: error ? { message: error.message, stack: error.stack } : undefined },\n ],\n }\n\n function forward<Type extends GenerationEventType>(type: Type): void {\n on(type, (...args: KubbHooks[Type]) => emitEvent(type, projections[type](...args)))\n }\n\n // Paths in `kubb:files:processing:update` are made relative to the root the build announced.\n on('kubb:build:start', ({ config }) => {\n root = config.root\n })\n\n for (const type of generationEventTypes) forward(type)\n\n // Registered after the loop so the summary follows its `kubb:generation:end`; core never emits it.\n on('kubb:generation:end', ({ diagnostics = [], status, hrStart, filesCreated }) => {\n if (!hrStart) {\n return\n }\n\n const duration = Math.round(getElapsedMs(hrStart))\n\n emitEvent('kubb:generation:summary', [\n { duration, fileCount: filesCreated ?? 0, failedPlugins: Diagnostics.failedPlugins(diagnostics).length, status: status ?? 'success' },\n ])\n })\n\n /**\n * Takes this generation's listeners off the session emitter. Safe to call twice.\n */\n function detach(): void {\n for (const unhook of unhooks) unhook()\n unhooks.length = 0\n }\n\n async function close(): Promise<void> {\n if (closed) {\n return\n }\n closed = true\n detach()\n controller.close()\n }\n\n function fail(error?: unknown): void {\n detach()\n if (closed) {\n return\n }\n closed = true\n controller.error(error)\n }\n\n return { stream, close, dispose: () => fail(), fail }\n}\n","/**\n * Hosted Kubb Studio URL, used when a host passes none.\n */\nexport const defaultStudioUrl = 'https://kubb.studio'\n\n// `URL` keeps IPv6 brackets, so `::1` is `[::1]`.\nfunction isLoopbackHost(hostname: string): boolean {\n return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]'\n}\n\n/**\n * Appends `path` to the Studio URL and refuses plaintext to anything but this machine, so a token\n * or API key never crosses the network unencrypted. `socket` switches the scheme to `ws:`/`wss:`.\n *\n * @example\n * ```ts\n * secureUrl({ studioUrl: 'https://kubb.studio', path: '/api/agent/socket', socket: true }).href // 'wss://kubb.studio/api/agent/socket'\n * ```\n */\nexport function secureUrl({ studioUrl, path, socket = false }: { studioUrl: string; path: string; socket?: boolean }): URL {\n const url = new URL(`${studioUrl.replace(/\\/+$/, '')}${path}`)\n\n if (url.protocol !== 'https:' && !(url.protocol === 'http:' && isLoopbackHost(url.hostname))) {\n throw new Error(`Refusing to reach Kubb Studio at ${url.origin}: use an https:// URL, or a loopback host for local development`)\n }\n if (socket) url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'\n\n return url\n}\n","import { randomUUID } from 'node:crypto'\nimport { mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { setTimeout as delay } from 'node:timers/promises'\nimport { getErrorMessage, read, toError } from '@internals/utils'\nimport { cacheStorage, type Config, fsStorage, Hookable, type KubbHooks, memoryStorage, resolveCacheDir } from '@kubb/core'\nimport { newWebSocketRpcSession, RpcTarget } from 'capnweb'\nimport { version as kubbVersion } from '../package.json'\nimport { readConfig, writeConfigEdits } from './configFile.ts'\nimport { createGenerationStream } from './generationEvents.ts'\nimport { createGenerationStore, generate, type GenerationStore, listDisk, resolveGenerationLimits } from './generations.ts'\nimport {\n AGENT_INSTANCE_HEADER,\n AGENT_SOCKET_PATH,\n type AgentApi,\n AgentCloseCode,\n type AgentConnectInfo,\n type AgentPermissions,\n type ConfigFileView,\n type ConnectMessagePayload,\n type GenerateInput,\n type GenerateResult,\n type GenerationEvent,\n type GenerationRun,\n GENERATION_GONE_MESSAGE,\n MAX_FILES_PER_REQUEST,\n MAX_PAGE_LINES,\n type ReadFilesInput,\n type ReadFilesResult,\n type SaveConfigInput,\n type SaveResult,\n type StudioApi,\n} from './protocol.ts'\nimport { mergeAdapter, mergePlugins, toPackageName } from './resolveConfig.ts'\nimport { defaultStudioUrl, secureUrl } from './url.ts'\n\nconst HEARTBEAT_INTERVAL_MS = 30_000\n// Studio marks an agent offline after its liveness window, so a slower cadence would look dead.\nconst MAX_HEARTBEAT_INTERVAL_MS = 60_000\nconst PING_TIMEOUT_MS = 10_000\nconst OPEN_TIMEOUT_MS = 5_000\nconst MAX_RETRY_DELAY_MS = 30_000\nconst DISK_SNAPSHOT_MAX_FILES = 10_000\n// A sandbox shares one in-memory store across tenants, so old generations expire.\nconst SANDBOX_GENERATION_TTL_MS = 15 * 60_000\n\n/**\n * Studio closed with {@link AgentCloseCode.UNAUTHORIZED}. Hosts forget the token and pair again.\n */\nexport class InvalidAgentTokenError extends Error {\n constructor(studioUrl: string) {\n super(`Kubb Studio rejected this agent's token. It expired or was revoked, or the agent was deleted in ${studioUrl}.`)\n this.name = 'InvalidAgentTokenError'\n }\n}\n\n/**\n * Studio closed with {@link AgentCloseCode.INCOMPATIBLE}. Only an upgrade helps.\n */\nexport class IncompatibleAgentError extends Error {\n constructor({ studioUrl, detail }: { studioUrl: string; detail?: string }) {\n super(`Kubb Studio at ${studioUrl} requires a newer agent${detail ? `: ${detail}` : ''}. Upgrade kubb or the Kubb agent image.`)\n this.name = 'IncompatibleAgentError'\n }\n}\n\nexport type StudioConnectedContext = AgentConnectInfo & {\n url: string\n /**\n * The Studio, runtime, and host versions, so a host can show a mismatch.\n */\n versions: { studio: string; kubb: string; agent: string }\n}\n\ndeclare global {\n namespace Kubb {\n interface KubbHooksRegistry {\n /**\n * Fired after each handshake, including reconnects.\n */\n 'studio:connected': [ctx: StudioConnectedContext]\n 'studio:disconnected': [ctx: { code: number; reason: string }]\n 'studio:reconnecting': [ctx: { delayMs: number }]\n /**\n * A finished command and what it did, such as `applied 2/3 edits to kubb.config.ts`.\n */\n 'studio:command': [ctx: { command: 'generate' | 'saveConfig' | 'readFiles'; info: string }]\n /**\n * A refused or ignored request, with the missing permission so the host can add a remedy.\n */\n 'studio:warn': [ctx: { message: string; permission?: keyof AgentPermissions }]\n 'studio:error': [ctx: { error: Error }]\n }\n }\n}\n\nexport type ConnectAgentOptions = {\n /**\n * The agent's bearer token, from {@link pairAgent}.\n */\n token: string\n studioUrl?: string\n /**\n * The config path shown in Studio, relative to `root` unless absolute.\n */\n configPath: string\n /**\n * Called for every handshake and every generation, so edits on disk show up.\n */\n loadConfig: () => Promise<Config>\n /**\n * The host's own version, reported to Studio next to the runtime's.\n */\n version: string\n /**\n * The project root generation runs against.\n * @default process.cwd()\n */\n root?: string\n /**\n * What Studio may do in this project. Every permission is off unless granted.\n */\n permissions?: Partial<AgentPermissions>\n /**\n * Receives the `studio:*` hooks and the `kubb:*` hooks of every generation.\n */\n hooks?: Hookable<KubbHooks>\n signal?: AbortSignal\n /**\n * Longest wait between reconnect attempts, in milliseconds.\n * @default 30000\n */\n maxRetryDelay?: number\n /**\n * Milliseconds between keep-alive pings, at most 60000.\n * @default 30000\n */\n heartbeatInterval?: number\n}\n\ntype ResolvedOptions = Required<Omit<ConnectAgentOptions, 'signal'>> & {\n signal?: AbortSignal\n permissions: AgentPermissions\n configFile: string\n}\n\ntype Rpc = { studio: StudioApi; closed: Promise<{ code: number; reason: string }>; close: () => void }\n\n// Tests swap in an in-process pair.\nexport type OpenRpc = (input: { url: URL; token: string; instanceId: string; agent: AgentApi }) => Rpc\n\ntype Session = {\n info?: AgentConnectInfo\n connected: PromiseWithResolvers<AgentConnectInfo>\n closed: boolean\n active?: { jobId: string; abort: () => void; settled: Promise<void> }\n}\n\n// A throwing host listener must not break the connection.\nfunction emit<TName extends keyof KubbHooks & string>(hooks: Hookable<KubbHooks>, name: TName, ...args: KubbHooks[TName]): Promise<void> {\n return Promise.resolve(hooks.callHook(name, ...args)).catch(() => {})\n}\n\nfunction isValidPage({ cursor, limit }: Pick<ReadFilesInput, 'cursor' | 'limit'>): boolean {\n if (limit === undefined) return cursor === undefined\n if (cursor !== undefined && (!Number.isSafeInteger(cursor) || cursor < 0)) return false\n return Number.isSafeInteger(limit) && limit >= 1 && limit <= MAX_PAGE_LINES\n}\n\ntype RunHandle = { stream: ReadableStream<GenerationEvent>; result: Promise<GenerateResult>; stop: () => void }\n\nclass GenerationRunTarget extends RpcTarget implements GenerationRun {\n readonly #run: RunHandle\n\n constructor(run: RunHandle) {\n super()\n this.#run = run\n }\n\n async events() {\n return this.#run.stream\n }\n result() {\n return this.#run.result\n }\n async cancel() {\n this.#run.stop()\n }\n // Cap'n Web also calls this when the peer session is torn down, so a dropped socket stops the run.\n [Symbol.dispose]() {\n this.#run.stop()\n }\n}\n\n// Cap'n Web exposes only prototype methods, so the public methods are exactly `AgentApi`.\nclass Agent extends RpcTarget implements AgentApi {\n readonly #options: ResolvedOptions\n readonly #session: Session\n readonly #limits = resolveGenerationLimits()\n #store: GenerationStore | undefined\n\n constructor({ options, session }: { options: ResolvedOptions; session: Session }) {\n super()\n this.#options = options\n this.#session = session\n }\n\n get #sandbox(): boolean {\n return this.#session.info?.sandbox === true\n }\n\n // A sandbox has no project to write to or edit, and Studio may always read what it generated there.\n get #permissions(): AgentPermissions {\n const { permissions } = this.#options\n return this.#sandbox ? { ...permissions, allowWrite: false, allowConfigEdit: false, allowRead: true } : permissions\n }\n\n // Kept in the project's cache directory so it survives a restart. A sandbox keeps them in memory,\n // because its pool runs every tenant's jobs.\n get #generations(): GenerationStore {\n this.#store ??= createGenerationStore({\n storage: this.#sandbox ? memoryStorage() : cacheStorage({ root: this.#options.root }),\n maxCount: this.#limits.maxCount,\n maxMb: this.#limits.maxMb,\n ttlMs: this.#sandbox ? SANDBOX_GENERATION_TTL_MS : undefined,\n })\n return this.#store\n }\n\n #warn({ message, permission }: { message: string; permission?: keyof AgentPermissions }): Promise<void> {\n return emit(this.#options.hooks, 'studio:warn', { message, permission })\n }\n\n // Studio shows the thrown message, and the host logs the same text.\n async #refuse({ message, permission }: { message: string; permission?: keyof AgentPermissions }): Promise<never> {\n await this.#warn({ message, permission })\n throw new Error(message)\n }\n\n async #command<T>({ command, run }: { command: KubbHooks['studio:command'][0]['command']; run: () => Promise<{ value: T; info?: string }> }): Promise<T> {\n if (!this.#session.info) throw new Error('Studio must call connect() before any other command')\n const { value, info } = await run()\n if (info !== undefined) await emit(this.#options.hooks, 'studio:command', { command, info })\n return value\n }\n\n // Not cached: the user can edit the file between two Studio actions.\n async #readConfigFileView(source?: string): Promise<ConfigFileView | undefined> {\n if (!this.#permissions.allowConfigEdit) return undefined\n\n try {\n return readConfig(source ?? (await read(this.#options.configFile)))\n } catch (error) {\n await this.#warn({ message: `Could not read ${this.#options.configFile}: ${getErrorMessage(error)}` })\n return undefined\n }\n }\n\n async connect(info: AgentConnectInfo): Promise<ConnectMessagePayload> {\n this.#session.info = info\n const { configPath, root, version, loadConfig } = this.#options\n const [config, file] = await Promise.all([loadConfig(), this.#readConfigFileView()])\n this.#session.connected.resolve(info)\n\n return {\n versions: { kubb: kubbVersion, agent: version },\n root,\n config: { path: configPath, file, plugins: config.plugins.map((plugin) => ({ name: toPackageName(plugin.name), options: plugin.options ?? {} })) },\n permissions: this.#permissions,\n }\n }\n\n startGeneration(input: GenerateInput): GenerationRun {\n const stream = createGenerationStream(this.#options.hooks, input.jobId)\n const controller = new AbortController()\n const result = this.#runGeneration(input, controller).then(\n (value) => stream.close().then(() => value),\n (error: unknown) => {\n stream.fail(error)\n throw error\n },\n )\n // A disconnect can reject this after the remote caller disappeared.\n void result.catch(() => {})\n\n return new GenerationRunTarget({\n stream: stream.stream,\n result,\n stop: () => {\n controller.abort(new Error('Generation canceled'))\n stream.dispose()\n },\n })\n }\n\n async #runGeneration(input: GenerateInput, controller: AbortController): Promise<GenerateResult> {\n // Checked before the first `await`, so two calls in the same tick can't both pass.\n if (this.#session.closed) throw new Error('Connection is closed')\n if (this.#session.active) return this.#refuse({ message: 'A generation is already in progress, please wait for it to finish' })\n const settled = Promise.withResolvers<void>()\n this.#session.active = { jobId: input.jobId, abort: () => controller.abort(new Error('Generation canceled')), settled: settled.promise }\n let root = this.#options.root\n\n try {\n // Kubb keys its manifest cache by root, so sandbox tenants sharing one root would read each other's.\n if (this.#sandbox) root = await mkdtemp(path.join(tmpdir(), 'kubb-job-'))\n return await this.#command({ command: 'generate', run: () => this.#generate({ input, root, signal: controller.signal }) })\n } finally {\n if (root !== this.#options.root) {\n await Promise.all([rm(root, { recursive: true, force: true }), rm(resolveCacheDir(root), { recursive: true, force: true })]).catch(() => {})\n }\n this.#session.active = undefined\n settled.resolve()\n }\n }\n\n async #generate({ input, root, signal }: { input: GenerateInput; root: string; signal: AbortSignal }): Promise<{ value: GenerateResult; info: string }> {\n const { jobId, config: patch } = input\n const config = await this.#options.loadConfig()\n const plugins = (await mergePlugins(config.plugins, patch?.plugins)) ?? config.plugins\n const adapter = await mergeAdapter(config.adapter, patch?.adapter)\n // A sandbox has no spec on disk, so it always generates from Studio's, empty string included.\n const studioInput = this.#sandbox ? (patch?.input ?? '') : undefined\n\n if (patch?.input && !this.#sandbox) {\n await this.#warn({ message: 'Ignored the spec from Studio: generating from a Studio spec is only available to a sandbox agent' })\n }\n\n const hasProjectOnDisk = !this.#sandbox && this.#permissions.allowRead\n const diskFiles = hasProjectOnDisk ? await listDisk({ root, outputPath: config.output.path, maxFiles: DISK_SNAPSHOT_MAX_FILES }) : undefined\n const disk = diskFiles ? await this.#generations.keep({ jobId, source: 'disk', files: diskFiles, maxSetMb: this.#limits.maxSnapshotMb }) : undefined\n\n const files = await generate({\n config: { ...config, root, input: studioInput ?? config.input, storage: this.#permissions.allowWrite ? fsStorage() : memoryStorage(), plugins, adapter },\n hooks: this.#options.hooks,\n signal,\n allowExec: this.#permissions.allowExec,\n }).catch(async (error: unknown) => {\n await this.#generations.drop(jobId)\n throw error\n })\n\n const output = await this.#generations.keep({ jobId, source: 'output', files, maxSetMb: this.#limits.maxMb })\n if (!output.paths.length && Object.keys(output.hashes).length) {\n await this.#warn({ message: 'Kept only the hashes of this generation: its output is too large to keep' })\n }\n await this.#generations.add({ jobId, output, disk })\n\n return {\n value: {\n status: 'success',\n files: [...files.paths],\n fileCount: files.paths.size,\n hashes: output.hashes,\n disk: disk ? { hashes: disk.hashes } : undefined,\n },\n info: `${plugins.length} plugin${plugins.length === 1 ? '' : 's'}, ${this.#permissions.allowWrite ? 'written to disk' : 'in memory'}${studioInput !== undefined ? ', from a Studio spec' : ''}`,\n }\n }\n\n saveConfig(input: SaveConfigInput): Promise<SaveResult> {\n return this.#command({ command: 'saveConfig', run: () => this.#saveConfig(input) })\n }\n\n async #saveConfig(input: SaveConfigInput): Promise<{ value: SaveResult; info?: string }> {\n const { configPath, configFile } = this.#options\n\n if (!Array.isArray(input.edits)) {\n await this.#warn({ message: 'Ignored save: the message carried no edits' })\n return { value: { outcomes: [], changed: false } }\n }\n\n const edits = input.edits\n const refuse = (reason: string): SaveResult => ({ outcomes: edits.map((edit) => ({ edit, applied: false, reason })), changed: false })\n\n if (!this.#permissions.allowConfigEdit) {\n await this.#warn({ message: 'Ignored save: editing kubb.config.ts was not granted' })\n return { value: refuse('the agent was not granted permission to edit kubb.config.ts') }\n }\n\n // A running generation reloads the config, so it would see half the change.\n if (this.#session.active) return { value: refuse('a generation is in progress') }\n\n try {\n const { source, outcomes, changed } = await writeConfigEdits({ filePath: configFile, edits })\n const applied = outcomes.filter((outcome) => outcome.applied).length\n\n return {\n value: { outcomes, changed, file: changed ? await this.#readConfigFileView(source) : undefined },\n info: `applied ${applied}/${outcomes.length} edits to ${configPath}`,\n }\n } catch (error) {\n // Refuse every edit so Studio hears back instead of waiting.\n await emit(this.#options.hooks, 'studio:error', { error: toError(error) })\n return { value: refuse(getErrorMessage(error)) }\n }\n }\n\n readFiles(input: ReadFilesInput): Promise<ReadFilesResult> {\n return this.#command({ command: 'readFiles', run: () => this.#readFiles(input) })\n }\n\n async #readFiles(input: ReadFilesInput): Promise<{ value: ReadFilesResult; info: string }> {\n if (!this.#permissions.allowRead) return this.#refuse({ message: 'The agent was not granted permission to read generated files', permission: 'allowRead' })\n if (!Array.isArray(input.paths) || typeof input.jobId !== 'string' || !input.jobId) {\n return this.#refuse({ message: 'The request must name a job and carry paths' })\n }\n const { paths } = input\n if (paths.length > MAX_FILES_PER_REQUEST) return this.#refuse({ message: `At most ${MAX_FILES_PER_REQUEST} paths may be requested at once` })\n\n const generation = await this.#generations.get(input.jobId)\n if (!generation) return this.#refuse({ message: GENERATION_GONE_MESSAGE })\n if (!isValidPage(input)) return this.#refuse({ message: `The cursor must be a whole line from 0 and come with a limit of 1 to ${MAX_PAGE_LINES} lines` })\n\n const source = input.source === 'disk' ? 'disk' : 'output'\n if (!generation[source]) return this.#refuse({ message: 'This agent kept no snapshot of the files on disk for that job' })\n\n // Only paths the set holds are read, never an arbitrary path.\n const result = await this.#generations.read({ generation, source, paths, cursor: input.cursor, limit: input.limit })\n\n return { value: result, info: `read ${Object.keys(result.files).length}/${paths.length} requested file${paths.length === 1 ? '' : 's'}` }\n }\n}\n\nconst openWebSocketRpc: OpenRpc = ({ url, token, instanceId, agent }) => {\n // Node's `WebSocket` takes undici's `headers` option, which the DOM typing leaves out.\n const NodeWebSocket = WebSocket as unknown as new (url: URL, init: { headers: Record<string, string> }) => WebSocket\n const socket = new NodeWebSocket(url, { headers: { Authorization: `Bearer ${token}`, [AGENT_INSTANCE_HEADER]: instanceId } })\n const timer = setTimeout(() => socket.close(3008, 'Connection timeout'), OPEN_TIMEOUT_MS)\n socket.addEventListener('open', () => clearTimeout(timer), { once: true })\n\n const closed = new Promise<Awaited<Rpc['closed']>>((resolve) => {\n socket.addEventListener('close', ({ code, reason }) => resolve({ code, reason }), { once: true })\n // Node fires only `error` when the handshake itself fails.\n socket.addEventListener('error', () => {\n if (socket.readyState !== WebSocket.OPEN) resolve({ code: 1006, reason: '' })\n })\n }).finally(() => clearTimeout(timer))\n\n const studio = newWebSocketRpcSession<StudioApi>(socket, agent)\n studio.onRpcBroken(() => socket.close())\n\n return {\n studio,\n closed,\n close: () => {\n studio[Symbol.dispose]()\n socket.close()\n },\n }\n}\n\nasync function runSession({ options, openRpc, url, instanceId }: { options: ResolvedOptions; openRpc: OpenRpc; url: URL; instanceId: string }) {\n const { hooks, signal, heartbeatInterval, token, studioUrl, version } = options\n const session: Session = { connected: Promise.withResolvers(), closed: false }\n const rpc = openRpc({ url, token, instanceId, agent: new Agent({ options, session }) })\n signal?.addEventListener('abort', rpc.close, { once: true })\n let timer: ReturnType<typeof setTimeout> | undefined\n\n // Races each ping against a deadline, so a half-open socket can't hang it forever.\n const heartbeat = async (): Promise<void> => {\n let deadline: ReturnType<typeof setTimeout> | undefined\n const timedOut = new Promise<boolean>((resolve) => (deadline = setTimeout(resolve, PING_TIMEOUT_MS, true)))\n const failed = await Promise.race([\n Promise.resolve(rpc.studio.ping()).then(\n () => false,\n () => true,\n ),\n timedOut,\n ])\n clearTimeout(deadline)\n if (failed) return rpc.close()\n if (!session.closed) timer = setTimeout(heartbeat, heartbeatInterval)\n }\n\n void session.connected.promise.then(\n async (info) => {\n await emit(hooks, 'studio:connected', { ...info, url: studioUrl, versions: { studio: info.studioVersion, kubb: kubbVersion, agent: version } })\n if (!session.closed) timer = setTimeout(heartbeat, heartbeatInterval)\n },\n () => {},\n )\n\n const close = await rpc.closed\n session.closed = true\n clearTimeout(timer)\n signal?.removeEventListener('abort', rpc.close)\n session.connected.reject(new Error('The socket closed before Studio called connect()'))\n session.active?.abort()\n await session.active?.settled\n\n return { ...close, connected: session.info !== undefined }\n}\n\n/**\n * The connection loop with a swappable transport. {@link connectAgent} passes a real WebSocket.\n */\nexport async function runAgent({ options, openRpc }: { options: ConnectAgentOptions; openRpc: OpenRpc }): Promise<void> {\n const root = options.root ?? process.cwd()\n const resolved: ResolvedOptions = {\n ...options,\n studioUrl: options.studioUrl ?? defaultStudioUrl,\n root,\n configFile: path.resolve(root, options.configPath),\n permissions: { allowWrite: false, allowConfigEdit: false, allowExec: false, allowRead: false, ...options.permissions },\n hooks: options.hooks ?? new Hookable<KubbHooks>(),\n maxRetryDelay: options.maxRetryDelay ?? MAX_RETRY_DELAY_MS,\n heartbeatInterval: Math.min(options.heartbeatInterval ?? HEARTBEAT_INTERVAL_MS, MAX_HEARTBEAT_INTERVAL_MS),\n }\n const { studioUrl, hooks, signal, maxRetryDelay } = resolved\n const url = secureUrl({ studioUrl, path: AGENT_SOCKET_PATH, socket: true })\n // One per call, so a reconnect is the same process to Studio and a restart is a new one.\n const instanceId = randomUUID()\n let attempt = 0\n\n while (!signal?.aborted) {\n const { code, reason, connected } = await runSession({ options: resolved, openRpc, url, instanceId })\n if (signal?.aborted) return\n await emit(hooks, 'studio:disconnected', { code, reason })\n\n if (code === AgentCloseCode.UNAUTHORIZED) throw new InvalidAgentTokenError(studioUrl)\n if (code === AgentCloseCode.INCOMPATIBLE) throw new IncompatibleAgentError({ studioUrl, detail: reason })\n if (code === AgentCloseCode.SUPERSEDED) return\n\n // Reset only once Studio called connect(), so a socket that opens and closes again backs off.\n if (connected) attempt = 0\n const delayMs = Math.random() * Math.min(1_000 * 2 ** Math.min(attempt++, 16), maxRetryDelay)\n await emit(hooks, 'studio:reconnecting', { delayMs })\n await delay(delayMs, undefined, { signal }).catch(() => {})\n }\n}\n\n/**\n * Connects this project to Kubb Studio and serves its commands until `signal` aborts. Reconnects\n * with jittered backoff, and resolves when another process of the agent takes over. Rejects with\n * {@link InvalidAgentTokenError} so the host can pair again, or {@link IncompatibleAgentError}.\n *\n * @example\n * ```ts\n * const hooks = new Hookable<KubbHooks>()\n * hooks.hook('studio:connected', ({ agentSlug }) => console.log(`Connected as ${agentSlug}`))\n *\n * await connectAgent({ token, configPath: 'kubb.config.ts', loadConfig, version: '1.0.0', hooks, signal })\n * ```\n */\nexport function connectAgent(options: ConnectAgentOptions): Promise<void> {\n return runAgent({ options, openRpc: openWebSocketRpc })\n}\n","import { hash } from 'node:crypto'\nimport { setTimeout as delay } from 'node:timers/promises'\nimport { toError } from '@internals/utils'\nimport { ofetch } from 'ofetch'\nimport { defaultStudioUrl, secureUrl } from './url.ts'\n\n/**\n * RFC 8628 device-authorization response from Studio's `/api/auth/device/code` endpoint.\n * Field names match the RFC; the CLI polls with `device_code` and shows `user_code` to the user.\n */\nexport type PairingSession = {\n device_code: string\n user_code: string\n verification_uri: string\n verification_uri_complete: string\n expires_in: number\n interval: number\n}\n\ntype PairingResult = {\n /**\n * Bearer token for this machine. Write credentials with mode 0600 and never log the value.\n */\n token: string\n agent: {\n /**\n * Stable agent id in Studio.\n */\n id: string\n /**\n * Short slug used in logs and the UI (for example `brave-otter`).\n */\n slug: string\n /**\n * Display name chosen at pairing time.\n */\n name: string\n /**\n * This agent's organization slug, absent for a sandbox or global agent, which has none.\n */\n organizationSlug?: string\n }\n}\n\n/**\n * What this machine registers as. Any member may approve `cli` (`kubb studio`); only an admin may\n * approve `user` and `sandbox` (the Docker image). A `ci` agent never pairs.\n */\ntype PairingAgentType = 'cli' | 'user' | 'sandbox'\n\n/** Labels, not secrets: a person approving the code in the browser is what authorizes a pairing. */\nconst CLIENT_IDS = { cli: 'kubb-cli', agent: 'kubb-agent' } as const\n\n/**\n * Thrown when a caller aborts `startPairing` or `pollForPairingToken` through their `signal`, such\n * as a `kubb studio` shutdown mid-pairing. Distinct from a denial or an expired code, so a host can\n * exit quietly instead of reporting a pairing failure.\n */\nexport class PairingCanceledError extends Error {\n constructor() {\n super('Pairing was canceled')\n this.name = 'PairingCanceledError'\n }\n}\n\n/** Thrown when the code expired unapproved. A fresh code can still succeed. */\nexport class PairingExpiredError extends Error {\n constructor(message = 'The pairing code expired, pair again') {\n super(message)\n this.name = 'PairingExpiredError'\n }\n}\n\n/** Thrown when the pairing was denied in the browser, including by the organization's agent limit. */\nexport class PairingDeniedError extends Error {\n constructor(message = 'Pairing was denied in the browser') {\n super(message)\n this.name = 'PairingDeniedError'\n }\n}\n\ntype StartPairingOptions = {\n studioUrl?: string\n type: PairingAgentType\n /**\n * Display name for the agent, usually the project or machine name.\n */\n name: string\n hostname: string\n /**\n * A stable secret the host keeps for this machine. Studio stores its hash against the agent, so\n * the same machine pairing again rotates one agent's token instead of creating a second agent.\n */\n machineId: string\n /**\n * Aborting this cancels the request in flight and rejects with {@link PairingCanceledError}.\n */\n signal?: AbortSignal\n}\n\n/**\n * Asks Studio for a pairing code, sending the hashed machine id with it.\n */\nexport async function startPairing({ studioUrl = defaultStudioUrl, type, name, hostname, machineId, signal }: StartPairingOptions): Promise<PairingSession> {\n try {\n const pairing = await ofetch<PairingSession>(secureUrl({ studioUrl, path: '/api/auth/device/code' }).href, {\n method: 'POST',\n body: {\n client_id: type === 'cli' ? CLIENT_IDS.cli : CLIENT_IDS.agent,\n name,\n hostname,\n machine_token: hash('sha256', machineId),\n agent_kind: type === 'cli' ? undefined : type,\n },\n signal,\n })\n if (typeof pairing?.device_code !== 'string') throw new Error('Kubb Studio returned no pairing code')\n\n return pairing\n } catch (error) {\n if (signal?.aborted) {\n throw new PairingCanceledError()\n }\n\n throw error\n }\n}\n\ntype PollOptions = {\n studioUrl?: string\n session: PairingSession\n /**\n * Aborting this stops polling and rejects with {@link PairingCanceledError}, whether the abort\n * lands between polls or during the wait for the next one.\n */\n signal?: AbortSignal\n /** Called when a poll could not reach Studio. Polling carries on. */\n onRetry?: (error: Error) => void\n}\n\ntype PollError = 'authorization_pending' | 'slow_down' | 'expired_token' | 'access_denied' | 'invalid_grant'\n\ntype PollResponse =\n | PairingResult\n | {\n error: PollError | string\n /**\n * Why, when Studio has something more useful to say than the RFC code. An approval that hits\n * the organization's agent limit comes back as `access_denied` with the limit spelled out.\n */\n error_description?: string\n }\n\nfunction isPairingResult(response: PollResponse): response is PairingResult {\n return 'token' in response && typeof response.token === 'string'\n}\n\n/**\n * Polls until the user approves or denies, honoring the server's `slow_down` back-off.\n *\n * Studio's own endpoint is used rather than the auth layer's `/device/token`, because an approved\n * Kubb pairing is worth an agent bearer token, not a user session.\n *\n * @throws {PairingExpiredError} when the code expires before anyone approves it.\n * @throws {PairingDeniedError} when the pairing is denied in the browser.\n * @throws {PairingCanceledError} when `signal` aborts.\n */\nexport async function pollForPairingToken({ studioUrl = defaultStudioUrl, session, signal, onRetry }: PollOptions): Promise<PairingResult> {\n // Both fields cross the network, so neither is trusted as-is: a missing or zero `interval` would\n // spin the poll loop, and a missing or zero `expires_in` would expire the code before the first\n // poll. `> 0` is also false for `NaN` and for a missing field, so it doubles as the type guard.\n const deadline = Date.now() + (session.expires_in > 0 ? session.expires_in : 600) * 1000\n let intervalMs = (session.interval > 0 ? session.interval : 5) * 1000\n\n while (Date.now() < deadline) {\n if (signal?.aborted) {\n throw new PairingCanceledError()\n }\n\n try {\n await delay(intervalMs, undefined, { signal })\n } catch {\n throw new PairingCanceledError()\n }\n\n let response: PollResponse\n try {\n // A denial, an expiry, and \"not yet\" all come back as 4xx with a body to switch on.\n const { status, _data } = await ofetch.raw<PollResponse>(secureUrl({ studioUrl, path: '/api/agent/token' }).href, {\n method: 'POST',\n body: { device_code: session.device_code },\n signal,\n ignoreResponseError: true,\n })\n if (status >= 500 || !_data || typeof _data !== 'object') throw new Error(`Kubb Studio answered with status ${status}`)\n response = _data\n } catch (error) {\n if (signal?.aborted) {\n throw new PairingCanceledError()\n }\n\n // Studio can be briefly unreachable (a deploy) while the code is still valid, so retry.\n onRetry?.(toError(error))\n continue\n }\n\n if (isPairingResult(response)) {\n return response\n }\n\n if (!('error' in response) || typeof response.error !== 'string') {\n throw new Error('Kubb Studio returned an empty pairing response, pair again')\n }\n\n if (response.error === 'authorization_pending') {\n continue\n }\n\n if (response.error === 'slow_down') {\n intervalMs += 5_000\n continue\n }\n\n if (response.error === 'access_denied') {\n throw new PairingDeniedError(response.error_description)\n }\n\n if (response.error === 'expired_token' || response.error === 'invalid_grant') {\n throw new PairingExpiredError(response.error_description)\n }\n\n throw new Error(response.error_description ?? `Pairing failed (${response.error})`)\n }\n\n throw new PairingExpiredError()\n}\n\ntype PairAgentOptions = StartPairingOptions & {\n /** Shows the code to whoever approves it. Called again for each fresh code. */\n onCode: (session: PairingSession, attempt: number) => void | Promise<void>\n /** Called when a poll could not reach Studio. Polling carries on. */\n onRetry?: (error: Error) => void\n /**\n * Codes to ask for in total when one expires unapproved. A denial or abort ends it at once.\n * @default 1\n */\n maxAttempts?: number\n}\n\n/**\n * Pairs this machine with Studio: asks for a code, hands it to the host to show, and waits for approval.\n */\nexport async function pairAgent({ onCode, onRetry, maxAttempts = 1, ...options }: PairAgentOptions): Promise<PairingResult> {\n for (let attempt = 1; ; attempt++) {\n const session = await startPairing(options)\n await onCode(session, attempt)\n\n try {\n return await pollForPairingToken({ studioUrl: options.studioUrl, session, signal: options.signal, onRetry })\n } catch (error) {\n if (!(error instanceof PairingExpiredError) || attempt >= maxAttempts) {\n throw error\n }\n }\n }\n}\n","import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { dirname, join, resolve } from 'node:path'\nimport { promisify } from 'node:util'\nimport { gzip } from 'node:zlib'\nimport { type Config, fsStorage, type Hookable, type KubbHooks } from '@kubb/core'\nimport { ofetch } from 'ofetch'\nimport { generate, hashOf } from './generations.ts'\nimport { MAX_SNAPSHOT_BYTES, type PublishedSnapshot, type SnapshotUploadMetadata } from './protocol.ts'\nimport { resolvePeerDependencies } from './resolveConfig.ts'\nimport { defaultStudioUrl, secureUrl } from './url.ts'\n\nconst gzipAsync = promisify(gzip)\nconst UPLOAD_TIMEOUT_MS = 120_000\n\n// Plugins whose output a snapshot carries without depending on the plugin package.\nconst BUNDLED_DEPENDENCIES = ['@kubb/plugin-barrel']\n\ntype SnapshotFiles = Record<string, string>\ntype SnapshotPackage = { name: string; version: string; peerDependencies: Record<string, string> }\n\n/**\n * Maps a generated file to its path in the package, from its `src`/`dist` segment on, without `..` parts that could escape it.\n */\nfunction packagePath(filePath: string): string {\n const normalized = filePath.replaceAll('\\\\', '/')\n const relativePath = normalized.match(/\\/(?:src|dist)\\/.*$/)?.[0] ?? normalized\n return relativePath\n .split('/')\n .filter((part) => part && part !== '.' && part !== '..')\n .join('/')\n}\n\n/**\n * Splits a tar path into the 100-byte USTAR `name` and the 155-byte `prefix`, and throws for a path that fits neither.\n */\nfunction splitEntryPath(path: string): { name: string; prefix: string } {\n if (Buffer.byteLength(path) <= 100) return { name: path, prefix: '' }\n for (let i = path.lastIndexOf('/'); i > 0; i = path.lastIndexOf('/', i - 1)) {\n const prefix = path.slice(0, i)\n const name = path.slice(i + 1)\n if (Buffer.byteLength(prefix) <= 155 && Buffer.byteLength(name) <= 100) return { name, prefix }\n }\n throw new Error(`Snapshot path is too long for a tar entry: ${path}`)\n}\n\nfunction header(path: string, size: number): Buffer {\n const { name, prefix } = splitEntryPath(path)\n const value = Buffer.alloc(512)\n value.write(name)\n value.write('0000644\\0', 100)\n for (const offset of [108, 116, 265, 297]) value.write('0000000\\0', offset)\n value.write(`${size.toString(8).padStart(11, '0')}\\0`, 124)\n // npm's fixed mtime, so the same files always pack to the same integrity.\n value.write('03560116604\\0', 136)\n value.fill(32, 148, 156)\n value.write('0', 156)\n value.write('ustar\\0', 257)\n value.write('00', 263)\n value.write(prefix, 345)\n const checksum = value.reduce((sum, byte) => sum + byte, 0)\n value.write(`${checksum.toString(8).padStart(6, '0')}\\0 `, 148)\n return value\n}\n\n/**\n * Packs a generation's files into a gzipped, npm-installable tarball: a `package/` root with the\n * generated sources, a `tsdown`-built `dist/` (esm + cjs), and a `package.json` manifest.\n */\nexport async function createSnapshotPackage({ files, packageInfo }: { files: SnapshotFiles; packageInfo: SnapshotPackage }): Promise<Buffer> {\n const sources = new Map<string, { name: string; content: string }>()\n for (const [name, content] of Object.entries(files)) {\n const path = packagePath(name)\n const owner = sources.get(path)?.name\n if (owner) throw new Error(`Snapshot has two generated files that sanitize to the same path \"package/${path}\": \"${owner}\" and \"${name}\"`)\n sources.set(path, { name, content })\n }\n const root = await mkdtemp(join(tmpdir(), 'kubb-snapshot-'))\n const dist = join(root, 'dist')\n\n try {\n await mkdir(dist)\n await Promise.all(\n [...sources].map(async ([path, { content }]) => {\n await mkdir(dirname(join(root, path)), { recursive: true })\n await writeFile(join(root, path), content)\n }),\n )\n const entry = [...sources.keys()].filter((path) => /\\.(?:[cm]?[jt]sx?)$/.test(path)).map((path) => join(root, path))\n if (entry.length) {\n // Loaded on first use: tsdown is large, and most agent processes never pack a snapshot.\n const { build } = await import('tsdown')\n // `fixedExtension` emits the `.mjs`/`.cjs` the manifest names, whatever \"type\" the host's own package.json sets.\n await build({\n entry,\n outDir: dist,\n format: ['esm', 'cjs'],\n dts: false,\n sourcemap: false,\n unbundle: true,\n report: false,\n logLevel: 'silent',\n fixedExtension: true,\n })\n }\n const built = await fsStorage().readKeys(dist)\n // Only `@kubb/plugin-barrel` produces a `dist/index.*` for `main`, `module`, and `exports['.']` to name.\n const hasBarrel = built.includes('index.mjs') && built.includes('index.cjs')\n const manifest = {\n ...packageInfo,\n type: 'module',\n ...(hasBarrel ? { main: './dist/index.cjs', module: './dist/index.mjs' } : {}),\n // `exports` denies any subpath it does not list, so the wildcard keeps each generated file importable.\n exports: {\n ...(hasBarrel ? { '.': { import: './dist/index.mjs', require: './dist/index.cjs' } } : {}),\n './*': { import: './dist/*.mjs', require: './dist/*.cjs' },\n },\n }\n const entries = new Map<string, string>([\n ['package.json', JSON.stringify(manifest, null, 2)],\n ...[...sources].map(([path, { content }]) => [path, content] as const),\n ...(await Promise.all(built.map(async (key) => [`dist/${key}`, await readFile(join(dist, key), 'utf8')] as const))),\n ])\n const chunks = [...entries].flatMap(([path, content]) => {\n const bytes = Buffer.from(content)\n return [header(`package/${path}`, bytes.length), bytes, Buffer.alloc((512 - (bytes.length % 512)) % 512)]\n })\n return await gzipAsync(Buffer.concat([...chunks, Buffer.alloc(1024)]))\n } finally {\n await rm(root, { recursive: true, force: true })\n }\n}\n\ntype CreateSnapshotOptions = Omit<SnapshotUploadMetadata, 'hashes' | 'peerDependencies'> & {\n studioUrl?: string\n /**\n * Organization CI API key, sent as `x-api-key`.\n */\n apiKey: string\n /**\n * The project's Kubb config, generated like `kubb generate`: formatter, linter, and `output.postGenerate` included.\n */\n config: Config\n hooks?: Hookable<KubbHooks>\n signal?: AbortSignal\n}\n\n/**\n * Generates the project, packs it as an npm tarball, and publishes it to Studio in one `POST /api/snapshots` request.\n *\n * @example\n * ```ts\n * const { url } = await createSnapshot({ apiKey: process.env.KUBB_TOKEN!, config, id: 'gh:123:pr-4', name: 'acme/api#4', packageName: '@acme/api', version: '1.0.0' })\n * ```\n */\nexport async function createSnapshot({\n studioUrl = defaultStudioUrl,\n apiKey,\n config,\n hooks,\n signal,\n ...metadata\n}: CreateSnapshotOptions): Promise<PublishedSnapshot> {\n const url = secureUrl({ studioUrl, path: '/api/snapshots' })\n const generated = await generate({ config, hooks, signal, allowExec: true })\n const files = Object.fromEntries(\n await Promise.all(\n [...generated.paths].map(async (path) => {\n const content = await generated.storage.readItem(resolve(generated.root, path))\n if (content === null) throw new Error(`The generation listed ${path} but did not keep its content`)\n return [path, content] as const\n }),\n ),\n )\n const { peerDependencies, missingDependencies } = await resolvePeerDependencies(config.plugins.map(({ name }) => name))\n // The package would declare no version for a plugin that is not installed.\n const missing = missingDependencies.filter((dependency) => !BUNDLED_DEPENDENCIES.includes(dependency))\n if (missing.length) throw new Error(`Missing dependencies: ${missing.join(', ')}`)\n\n const bytes = await createSnapshotPackage({ files, packageInfo: { name: metadata.packageName, version: metadata.version, peerDependencies } })\n if (bytes.length > MAX_SNAPSHOT_BYTES) {\n throw new Error(`The snapshot is ${Math.ceil(bytes.length / 1024 / 1024)} MB, over the ${MAX_SNAPSHOT_BYTES / 1024 / 1024} MB limit`)\n }\n\n const hashes = Object.fromEntries(Object.entries(files).map(([path, content]) => [path, hashOf(content)]))\n const body = new FormData()\n body.set('metadata', JSON.stringify({ ...metadata, hashes, peerDependencies } satisfies SnapshotUploadMetadata))\n body.set('tarball', new Blob([new Uint8Array(bytes)], { type: 'application/gzip' }), 'snapshot.tgz')\n\n const timeout = AbortSignal.timeout(UPLOAD_TIMEOUT_MS)\n // A redirect would forward the CI key and tarball to wherever it points.\n const { ok, status, _data } = await ofetch.raw<{ snapshot?: PublishedSnapshot; message?: string; data?: { upgradeUrl?: string } }>(url.href, {\n method: 'POST',\n headers: { 'x-api-key': apiKey },\n body,\n redirect: 'error',\n signal: signal ? AbortSignal.any([signal, timeout]) : timeout,\n ignoreResponseError: true,\n })\n if (!ok) {\n const upgrade = _data?.data?.upgradeUrl ? ` Upgrade at ${_data.data.upgradeUrl}.` : ''\n throw new Error(`Kubb Studio refused the snapshot (status ${status})${_data?.message ? `: ${_data.message}` : ''}.${upgrade}`)\n }\n if (!_data?.snapshot) throw new Error(`Kubb Studio returned no snapshot (status ${status})`)\n return _data.snapshot\n}\n"],"mappings":"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"}
|