@kubb/cli 5.9.6 → 5.10.1

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.
Files changed (57) hide show
  1. package/dist/{Telemetry-DZEM4fEd.js → Telemetry-Bf6lUdai.js} +11 -3
  2. package/dist/Telemetry-Bf6lUdai.js.map +1 -0
  3. package/dist/{Telemetry-D3X0YeTq.cjs → Telemetry-BfdvvZus.cjs} +11 -3
  4. package/dist/Telemetry-BfdvvZus.cjs.map +1 -0
  5. package/dist/{background-F6WVubmb.js → background-C8doa9-4.js} +1 -1
  6. package/dist/{background-rGfifheJ.js → background-D5K6ecEo.js} +2 -2
  7. package/dist/{background-rGfifheJ.js.map → background-D5K6ecEo.js.map} +1 -1
  8. package/dist/{background-B9Ymrpv9.cjs → background-obsD4Gj2.cjs} +2 -2
  9. package/dist/{background-B9Ymrpv9.cjs.map → background-obsD4Gj2.cjs.map} +1 -1
  10. package/dist/{config-DTaFUofU.cjs → config-CcqzzfB7.cjs} +2 -2
  11. package/dist/{config-DTaFUofU.cjs.map → config-CcqzzfB7.cjs.map} +1 -1
  12. package/dist/{config-DUoNrSP-.js → config-IMZ26zcb.js} +2 -2
  13. package/dist/{config-DUoNrSP-.js.map → config-IMZ26zcb.js.map} +1 -1
  14. package/dist/credentials-CZK6zPLv.js.map +1 -1
  15. package/dist/credentials-DDaKqtJn.cjs.map +1 -1
  16. package/dist/index.cjs +22 -15
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.js +22 -15
  19. package/dist/index.js.map +1 -1
  20. package/dist/{output-BgIxkmno.cjs → output-DLrxGtuN.cjs} +2 -2
  21. package/dist/{output-BgIxkmno.cjs.map → output-DLrxGtuN.cjs.map} +1 -1
  22. package/dist/{output-s6v7gGbY.js → output-mwVt_Vj9.js} +2 -2
  23. package/dist/{output-s6v7gGbY.js.map → output-mwVt_Vj9.js.map} +1 -1
  24. package/dist/{registry-Bkeh0ipY.js → registry-ChqX2AFQ.js} +2 -2
  25. package/dist/{registry-Bkeh0ipY.js.map → registry-ChqX2AFQ.js.map} +1 -1
  26. package/dist/{registry-BDHW1pwJ.cjs → registry-x-_nbYR6.cjs} +2 -2
  27. package/dist/{registry-BDHW1pwJ.cjs.map → registry-x-_nbYR6.cjs.map} +1 -1
  28. package/dist/{run-BtAxJ1jG.cjs → run-1MJA0P5x.cjs} +2 -2
  29. package/dist/{run-BtAxJ1jG.cjs.map → run-1MJA0P5x.cjs.map} +1 -1
  30. package/dist/{run-Dw6w0ugW.cjs → run-B13e9GQz.cjs} +6 -4
  31. package/dist/run-B13e9GQz.cjs.map +1 -0
  32. package/dist/{run-Bmq599S0.js → run-BAlcXyYw.js} +5 -5
  33. package/dist/{run-Bmq599S0.js.map → run-BAlcXyYw.js.map} +1 -1
  34. package/dist/{run-dKhoUR2-.cjs → run-CUyhuGlK.cjs} +5 -5
  35. package/dist/{run-dKhoUR2-.cjs.map → run-CUyhuGlK.cjs.map} +1 -1
  36. package/dist/{run-CPm_IUsT.js → run-Cm0sJO0h.js} +1 -1
  37. package/dist/{run-Do-yyhzu.js → run-Cu3pmezx.js} +6 -4
  38. package/dist/run-Cu3pmezx.js.map +1 -0
  39. package/dist/{run-D3j4O7FO.js → run-D4vOhfbJ.js} +2 -2
  40. package/dist/{run-D3j4O7FO.js.map → run-D4vOhfbJ.js.map} +1 -1
  41. package/dist/{run-B3bSqn5G.cjs → run-DHiVlG37.cjs} +19 -21
  42. package/dist/run-DHiVlG37.cjs.map +1 -0
  43. package/dist/{run-Ct5_WdiW.js → run-DTz7gAk1.js} +19 -21
  44. package/dist/run-DTz7gAk1.js.map +1 -0
  45. package/dist/{snapshot-BQ545stN.cjs → snapshot-C5cthCuU.cjs} +5 -5
  46. package/dist/{snapshot-BQ545stN.cjs.map → snapshot-C5cthCuU.cjs.map} +1 -1
  47. package/dist/{snapshot-C6W9ttzM.js → snapshot-DCG-Jf1A.js} +5 -5
  48. package/dist/{snapshot-C6W9ttzM.js.map → snapshot-DCG-Jf1A.js.map} +1 -1
  49. package/dist/studioWorker.js +3 -3
  50. package/dist/studioWorker.js.map +1 -1
  51. package/package.json +7 -7
  52. package/dist/Telemetry-D3X0YeTq.cjs.map +0 -1
  53. package/dist/Telemetry-DZEM4fEd.js.map +0 -1
  54. package/dist/run-B3bSqn5G.cjs.map +0 -1
  55. package/dist/run-Ct5_WdiW.js.map +0 -1
  56. package/dist/run-Do-yyhzu.js.map +0 -1
  57. package/dist/run-Dw6w0ugW.cjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-CPE0t6oh.cjs");
2
- const require_Telemetry = require("./Telemetry-D3X0YeTq.cjs");
2
+ const require_Telemetry = require("./Telemetry-BfdvvZus.cjs");
3
3
  let node_process = require("node:process");
4
4
  node_process = require_rolldown_runtime.__toESM(node_process, 1);
5
5
  let _kubb_core = require("@kubb/core");
@@ -120,4 +120,4 @@ Object.defineProperty(exports, "toRegistryId", {
120
120
  }
121
121
  });
122
122
 
123
- //# sourceMappingURL=registry-BDHW1pwJ.cjs.map
123
+ //# sourceMappingURL=registry-x-_nbYR6.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry-BDHW1pwJ.cjs","names":["process","getErrorMessage","isRegistryEntry","isValid","isLessThan"],"sources":["../src/utils/registry.ts"],"sourcesContent":["import process from 'node:process'\nimport { getErrorMessage } from '@internals/utils'\nimport { checkCompatibility, type ExtensionManifest, isRegistryEntry, type RegistryArtifact, type RegistryDetail, type RegistryEntry } from '@kubb/core'\nimport { isLessThan, isValid } from 'verkit'\n\nexport const DEFAULT_REGISTRY = 'https://kubb.dev/registry'\n\nconst SLUG = '[a-z0-9]+(?:-[a-z0-9]+)*'\nconst ID = new RegExp(`^${SLUG}(\\\\/${SLUG})?$`)\n\n/** The registry base URL: `KUBB_REGISTRY`, or kubb.dev. */\nexport function registryUrl(): string {\n const url = process.env.KUBB_REGISTRY || DEFAULT_REGISTRY\n if (!/^https?:\\/\\//.test(url)) throw new Error(`KUBB_REGISTRY must be an http(s) URL, got \"${url}\".`)\n return url.replace(/\\/+$/, '')\n}\n\n/**\n * Turns `owner/slug`, or a bare `slug` meaning `kubb-labs/<slug>`, into a registry id.\n *\n * @throws when the id has another shape, so it never reaches a URL unchecked.\n */\nexport function toRegistryId(input: string): string {\n if (!ID.test(input)) throw new Error(`\"${input}\" is not a registry id. Use owner/slug, such as kubb-labs/plugin-zod, or a slug, such as plugin-zod.`)\n return input.includes('/') ? input : `kubb-labs/${input}`\n}\n\n/** GETs `url` as JSON. A non-2xx answer returns only its status; a network error throws with the URL. */\nasync function fetchJSON(url: string): Promise<{ status: number; body?: unknown }> {\n try {\n const response = await globalThis.fetch(url, { headers: { accept: 'application/json' } })\n if (!response.ok) return { status: response.status }\n return { status: response.status, body: (await response.json()) as unknown }\n } catch (cause) {\n throw new Error(`Could not read ${url}: ${getErrorMessage(cause)}`, { cause })\n }\n}\n\n/** Fetches one extension's detail document. */\nexport async function fetchRegistryDetail({ id, registry }: { id: string; registry: string }): Promise<RegistryDetail> {\n const { status, body } = await fetchJSON(`${registry}/${id}.json`)\n if (status === 404) throw new Error(`\"${id}\" is not in the registry at ${registry}.`)\n if (status !== 200 || !isRegistryEntry(body) || body.id !== id)\n throw new Error(`The registry at ${registry} sent an invalid entry for \"${id}\" (HTTP ${status}).`)\n\n const { overview } = body as { overview?: unknown }\n return { ...body, overview: typeof overview === 'string' ? overview : null }\n}\n\n/** Fetches the registry index, leaving out entries that fail validation. */\nexport async function fetchRegistryIndex({ registry }: { registry: string }): Promise<Array<RegistryEntry>> {\n const { status, body } = await fetchJSON(`${registry}/index.json`)\n const index = body as { version?: unknown; extensions?: unknown } | null | undefined\n if (status !== 200 || index?.version !== 1 || !Array.isArray(index.extensions)) {\n throw new Error(`The registry at ${registry} sent an invalid index (HTTP ${status}).`)\n }\n return index.extensions.filter(isRegistryEntry)\n}\n\n/** What the package manager installs: `<package>@<version>`, or a GitHub release's commit, so the install cannot move with the tag. */\nexport function installSpec(artifact: RegistryArtifact): string {\n return artifact.kind === 'github' ? `github:${artifact.owner}/${artifact.repo}#${artifact.commit}` : `${artifact.package}@${artifact.version}`\n}\n\n/** Why the running Kubb or Node.js version cannot use this extension, or `undefined` when it can. */\nexport function incompatibility(manifest: ExtensionManifest): string | undefined {\n try {\n checkCompatibility({ name: manifest.name, compatibility: manifest.compatibility })\n return undefined\n } catch (error) {\n return getErrorMessage(error)\n }\n}\n\n/**\n * Whether `latest` is newer than `installed`. An unknown installed version counts as outdated, and an\n * invalid `latest` never does.\n */\nexport function isOutdated({ installed, latest }: { installed: string | undefined; latest: string }): boolean {\n if (!isValid(latest)) return false\n return !installed || !isValid(installed) || isLessThan(installed, latest)\n}\n"],"mappings":";;;;;;AAOA,MAAM,OAAO;AACb,MAAM,KAAK,IAAI,OAAO,IAAI,KAAK,MAAM,KAAK,IAAI;;AAG9C,SAAgB,cAAsB;CACpC,MAAM,MAAMA,aAAAA,QAAQ,IAAI,iBAAA;CACxB,IAAI,CAAC,eAAe,KAAK,GAAG,GAAG,MAAM,IAAI,MAAM,8CAA8C,IAAI,GAAG;CACpG,OAAO,IAAI,QAAQ,QAAQ,EAAE;AAC/B;;;;;;AAOA,SAAgB,aAAa,OAAuB;CAClD,IAAI,CAAC,GAAG,KAAK,KAAK,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,qGAAqG;CACpJ,OAAO,MAAM,SAAS,GAAG,IAAI,QAAQ,aAAa;AACpD;;AAGA,eAAe,UAAU,KAA0D;CACjF,IAAI;EACF,MAAM,WAAW,MAAM,WAAW,MAAM,KAAK,EAAE,SAAS,EAAE,QAAQ,mBAAmB,EAAE,CAAC;EACxF,IAAI,CAAC,SAAS,IAAI,OAAO,EAAE,QAAQ,SAAS,OAAO;EACnD,OAAO;GAAE,QAAQ,SAAS;GAAQ,MAAO,MAAM,SAAS,KAAK;EAAc;CAC7E,SAAS,OAAO;EACd,MAAM,IAAI,MAAM,kBAAkB,IAAI,IAAIC,kBAAAA,gBAAgB,KAAK,KAAK,EAAE,MAAM,CAAC;CAC/E;AACF;;AAGA,eAAsB,oBAAoB,EAAE,IAAI,YAAuE;CACrH,MAAM,EAAE,QAAQ,SAAS,MAAM,UAAU,GAAG,SAAS,GAAG,GAAG,MAAM;CACjE,IAAI,WAAW,KAAK,MAAM,IAAI,MAAM,IAAI,GAAG,8BAA8B,SAAS,EAAE;CACpF,IAAI,WAAW,OAAO,EAAA,GAACC,WAAAA,gBAAAA,CAAgB,IAAI,KAAK,KAAK,OAAO,IAC1D,MAAM,IAAI,MAAM,mBAAmB,SAAS,8BAA8B,GAAG,UAAU,OAAO,GAAG;CAEnG,MAAM,EAAE,aAAa;CACrB,OAAO;EAAE,GAAG;EAAM,UAAU,OAAO,aAAa,WAAW,WAAW;CAAK;AAC7E;;AAGA,eAAsB,mBAAmB,EAAE,YAAiE;CAC1G,MAAM,EAAE,QAAQ,SAAS,MAAM,UAAU,GAAG,SAAS,YAAY;CACjE,MAAM,QAAQ;CACd,IAAI,WAAW,OAAO,OAAO,YAAY,KAAK,CAAC,MAAM,QAAQ,MAAM,UAAU,GAC3E,MAAM,IAAI,MAAM,mBAAmB,SAAS,+BAA+B,OAAO,GAAG;CAEvF,OAAO,MAAM,WAAW,OAAOA,WAAAA,eAAe;AAChD;;AAGA,SAAgB,YAAY,UAAoC;CAC9D,OAAO,SAAS,SAAS,WAAW,UAAU,SAAS,MAAM,GAAG,SAAS,KAAK,GAAG,SAAS,WAAW,GAAG,SAAS,QAAQ,GAAG,SAAS;AACvI;;AAGA,SAAgB,gBAAgB,UAAiD;CAC/E,IAAI;EACF,CAAA,GAAA,WAAA,mBAAA,CAAmB;GAAE,MAAM,SAAS;GAAM,eAAe,SAAS;EAAc,CAAC;EACjF;CACF,SAAS,OAAO;EACd,OAAOD,kBAAAA,gBAAgB,KAAK;CAC9B;AACF;;;;;AAMA,SAAgB,WAAW,EAAE,WAAW,UAAsE;CAC5G,IAAI,EAAA,GAACE,OAAAA,QAAAA,CAAQ,MAAM,GAAG,OAAO;CAC7B,OAAO,CAAC,aAAa,EAAA,GAACA,OAAAA,QAAAA,CAAQ,SAAS,MAAA,GAAKC,OAAAA,WAAAA,CAAW,WAAW,MAAM;AAC1E"}
1
+ {"version":3,"file":"registry-x-_nbYR6.cjs","names":["process","getErrorMessage","isRegistryEntry","isValid","isLessThan"],"sources":["../src/utils/registry.ts"],"sourcesContent":["import process from 'node:process'\nimport { getErrorMessage } from '@internals/utils'\nimport { checkCompatibility, type ExtensionManifest, isRegistryEntry, type RegistryArtifact, type RegistryDetail, type RegistryEntry } from '@kubb/core'\nimport { isLessThan, isValid } from 'verkit'\n\nexport const DEFAULT_REGISTRY = 'https://kubb.dev/registry'\n\nconst SLUG = '[a-z0-9]+(?:-[a-z0-9]+)*'\nconst ID = new RegExp(`^${SLUG}(\\\\/${SLUG})?$`)\n\n/** The registry base URL: `KUBB_REGISTRY`, or kubb.dev. */\nexport function registryUrl(): string {\n const url = process.env.KUBB_REGISTRY || DEFAULT_REGISTRY\n if (!/^https?:\\/\\//.test(url)) throw new Error(`KUBB_REGISTRY must be an http(s) URL, got \"${url}\".`)\n return url.replace(/\\/+$/, '')\n}\n\n/**\n * Turns `owner/slug`, or a bare `slug` meaning `kubb-labs/<slug>`, into a registry id.\n *\n * @throws when the id has another shape, so it never reaches a URL unchecked.\n */\nexport function toRegistryId(input: string): string {\n if (!ID.test(input)) throw new Error(`\"${input}\" is not a registry id. Use owner/slug, such as kubb-labs/plugin-zod, or a slug, such as plugin-zod.`)\n return input.includes('/') ? input : `kubb-labs/${input}`\n}\n\n/** GETs `url` as JSON. A non-2xx answer returns only its status; a network error throws with the URL. */\nasync function fetchJSON(url: string): Promise<{ status: number; body?: unknown }> {\n try {\n const response = await globalThis.fetch(url, { headers: { accept: 'application/json' } })\n if (!response.ok) return { status: response.status }\n return { status: response.status, body: (await response.json()) as unknown }\n } catch (cause) {\n throw new Error(`Could not read ${url}: ${getErrorMessage(cause)}`, { cause })\n }\n}\n\n/** Fetches one extension's detail document. */\nexport async function fetchRegistryDetail({ id, registry }: { id: string; registry: string }): Promise<RegistryDetail> {\n const { status, body } = await fetchJSON(`${registry}/${id}.json`)\n if (status === 404) throw new Error(`\"${id}\" is not in the registry at ${registry}.`)\n if (status !== 200 || !isRegistryEntry(body) || body.id !== id)\n throw new Error(`The registry at ${registry} sent an invalid entry for \"${id}\" (HTTP ${status}).`)\n\n const { overview } = body as { overview?: unknown }\n return { ...body, overview: typeof overview === 'string' ? overview : null }\n}\n\n/** Fetches the registry index, leaving out entries that fail validation. */\nexport async function fetchRegistryIndex({ registry }: { registry: string }): Promise<Array<RegistryEntry>> {\n const { status, body } = await fetchJSON(`${registry}/index.json`)\n const index = body as { version?: unknown; extensions?: unknown } | null | undefined\n if (status !== 200 || index?.version !== 1 || !Array.isArray(index.extensions)) {\n throw new Error(`The registry at ${registry} sent an invalid index (HTTP ${status}).`)\n }\n return index.extensions.filter(isRegistryEntry)\n}\n\n/** What the package manager installs: `<package>@<version>`, or a GitHub release's commit, so the install cannot move with the tag. */\nexport function installSpec(artifact: RegistryArtifact): string {\n return artifact.kind === 'github' ? `github:${artifact.owner}/${artifact.repo}#${artifact.commit}` : `${artifact.package}@${artifact.version}`\n}\n\n/** Why the running Kubb or Node.js version cannot use this extension, or `undefined` when it can. */\nexport function incompatibility(manifest: ExtensionManifest): string | undefined {\n try {\n checkCompatibility({ name: manifest.name, compatibility: manifest.compatibility })\n return undefined\n } catch (error) {\n return getErrorMessage(error)\n }\n}\n\n/**\n * Whether `latest` is newer than `installed`. An unknown installed version counts as outdated, and an\n * invalid `latest` never does.\n */\nexport function isOutdated({ installed, latest }: { installed: string | undefined; latest: string }): boolean {\n if (!isValid(latest)) return false\n return !installed || !isValid(installed) || isLessThan(installed, latest)\n}\n"],"mappings":";;;;;;AAOA,MAAM,OAAO;AACb,MAAM,KAAK,IAAI,OAAO,IAAI,KAAK,MAAM,KAAK,IAAI;;AAG9C,SAAgB,cAAsB;CACpC,MAAM,MAAMA,aAAAA,QAAQ,IAAI,iBAAA;CACxB,IAAI,CAAC,eAAe,KAAK,GAAG,GAAG,MAAM,IAAI,MAAM,8CAA8C,IAAI,GAAG;CACpG,OAAO,IAAI,QAAQ,QAAQ,EAAE;AAC/B;;;;;;AAOA,SAAgB,aAAa,OAAuB;CAClD,IAAI,CAAC,GAAG,KAAK,KAAK,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,qGAAqG;CACpJ,OAAO,MAAM,SAAS,GAAG,IAAI,QAAQ,aAAa;AACpD;;AAGA,eAAe,UAAU,KAA0D;CACjF,IAAI;EACF,MAAM,WAAW,MAAM,WAAW,MAAM,KAAK,EAAE,SAAS,EAAE,QAAQ,mBAAmB,EAAE,CAAC;EACxF,IAAI,CAAC,SAAS,IAAI,OAAO,EAAE,QAAQ,SAAS,OAAO;EACnD,OAAO;GAAE,QAAQ,SAAS;GAAQ,MAAO,MAAM,SAAS,KAAK;EAAc;CAC7E,SAAS,OAAO;EACd,MAAM,IAAI,MAAM,kBAAkB,IAAI,IAAIC,kBAAAA,gBAAgB,KAAK,KAAK,EAAE,MAAM,CAAC;CAC/E;AACF;;AAGA,eAAsB,oBAAoB,EAAE,IAAI,YAAuE;CACrH,MAAM,EAAE,QAAQ,SAAS,MAAM,UAAU,GAAG,SAAS,GAAG,GAAG,MAAM;CACjE,IAAI,WAAW,KAAK,MAAM,IAAI,MAAM,IAAI,GAAG,8BAA8B,SAAS,EAAE;CACpF,IAAI,WAAW,OAAO,EAAA,GAACC,WAAAA,gBAAAA,CAAgB,IAAI,KAAK,KAAK,OAAO,IAC1D,MAAM,IAAI,MAAM,mBAAmB,SAAS,8BAA8B,GAAG,UAAU,OAAO,GAAG;CAEnG,MAAM,EAAE,aAAa;CACrB,OAAO;EAAE,GAAG;EAAM,UAAU,OAAO,aAAa,WAAW,WAAW;CAAK;AAC7E;;AAGA,eAAsB,mBAAmB,EAAE,YAAiE;CAC1G,MAAM,EAAE,QAAQ,SAAS,MAAM,UAAU,GAAG,SAAS,YAAY;CACjE,MAAM,QAAQ;CACd,IAAI,WAAW,OAAO,OAAO,YAAY,KAAK,CAAC,MAAM,QAAQ,MAAM,UAAU,GAC3E,MAAM,IAAI,MAAM,mBAAmB,SAAS,+BAA+B,OAAO,GAAG;CAEvF,OAAO,MAAM,WAAW,OAAOA,WAAAA,eAAe;AAChD;;AAGA,SAAgB,YAAY,UAAoC;CAC9D,OAAO,SAAS,SAAS,WAAW,UAAU,SAAS,MAAM,GAAG,SAAS,KAAK,GAAG,SAAS,WAAW,GAAG,SAAS,QAAQ,GAAG,SAAS;AACvI;;AAGA,SAAgB,gBAAgB,UAAiD;CAC/E,IAAI;EACF,CAAA,GAAA,WAAA,mBAAA,CAAmB;GAAE,MAAM,SAAS;GAAM,eAAe,SAAS;EAAc,CAAC;EACjF;CACF,SAAS,OAAO;EACd,OAAOD,kBAAAA,gBAAgB,KAAK;CAC9B;AACF;;;;;AAMA,SAAgB,WAAW,EAAE,WAAW,UAAsE;CAC5G,IAAI,EAAA,GAACE,OAAAA,QAAAA,CAAQ,MAAM,GAAG,OAAO;CAC7B,OAAO,CAAC,aAAa,EAAA,GAACA,OAAAA,QAAAA,CAAQ,SAAS,MAAA,GAAKC,OAAAA,WAAAA,CAAW,WAAW,MAAM;AAC1E"}
@@ -1,5 +1,5 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-CPE0t6oh.cjs");
2
- const require_Telemetry = require("./Telemetry-D3X0YeTq.cjs");
2
+ const require_Telemetry = require("./Telemetry-BfdvvZus.cjs");
3
3
  let node_util = require("node:util");
4
4
  let node_process = require("node:process");
5
5
  node_process = require_rolldown_runtime.__toESM(node_process, 1);
@@ -37,4 +37,4 @@ async function run({ input }) {
37
37
  //#endregion
38
38
  exports.run = run;
39
39
 
40
- //# sourceMappingURL=run-BtAxJ1jG.cjs.map
40
+ //# sourceMappingURL=run-1MJA0P5x.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-BtAxJ1jG.cjs","names":["trackRun","process","styleText","toError"],"sources":["../src/runners/validate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport { trackRun } from '../../Telemetry.ts'\n\ntype ValidateOptions = {\n /**\n * Path or URL to the OpenAPI/Swagger file to validate.\n */\n input: string\n}\n\n/**\n * Validates an OpenAPI/Swagger file at `input` using `@kubb/adapter-oas`.\n * Exits the process with code 1 on validation failure or missing dependency.\n */\nexport async function run({ input }: ValidateOptions): Promise<void> {\n const report = trackRun({ command: 'validate', hrStart: process.hrtime() })\n\n try {\n const { adapterOas } = await import('@kubb/adapter-oas')\n\n await adapterOas().validate(input, { throwOnError: true })\n await report({ status: 'success' })\n\n console.log('✅ Validation success')\n } catch (error) {\n await report({ status: 'failed' })\n if (error instanceof Error && /@kubb\\/adapter-oas/.test(error.message)) {\n console.error(styleText('red', 'The @kubb/adapter-oas package is not installed.'))\n console.error('')\n console.error('Install it with:')\n console.error(styleText('cyan', ' npm install @kubb/adapter-oas'))\n console.error(styleText('cyan', ' # or'))\n console.error(styleText('cyan', ' pnpm install @kubb/adapter-oas'))\n console.error('')\n }\n console.error('❌ Validation failed')\n console.error(toError(error).message)\n\n process.exit(1)\n }\n}\n"],"mappings":";;;;;;;;;;AAgBA,eAAsB,IAAI,EAAE,SAAyC;CACnE,MAAM,SAASA,kBAAAA,SAAS;EAAE,SAAS;EAAY,SAASC,aAAAA,QAAQ,OAAO;CAAE,CAAC;CAE1E,IAAI;EACF,MAAM,EAAE,eAAe,MAAM,OAAO;EAEpC,MAAM,WAAW,CAAC,CAAC,SAAS,OAAO,EAAE,cAAc,KAAK,CAAC;EACzD,MAAM,OAAO,EAAE,QAAQ,UAAU,CAAC;EAElC,QAAQ,IAAI,sBAAsB;CACpC,SAAS,OAAO;EACd,MAAM,OAAO,EAAE,QAAQ,SAAS,CAAC;EACjC,IAAI,iBAAiB,SAAS,qBAAqB,KAAK,MAAM,OAAO,GAAG;GACtE,QAAQ,OAAA,GAAMC,UAAAA,UAAAA,CAAU,OAAO,iDAAiD,CAAC;GACjF,QAAQ,MAAM,EAAE;GAChB,QAAQ,MAAM,kBAAkB;GAChC,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,iCAAiC,CAAC;GAClE,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,QAAQ,CAAC;GACzC,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,kCAAkC,CAAC;GACnE,QAAQ,MAAM,EAAE;EAClB;EACA,QAAQ,MAAM,qBAAqB;EACnC,QAAQ,MAAMC,kBAAAA,QAAQ,KAAK,CAAC,CAAC,OAAO;EAEpC,aAAA,QAAQ,KAAK,CAAC;CAChB;AACF"}
1
+ {"version":3,"file":"run-1MJA0P5x.cjs","names":["trackRun","process","styleText","toError"],"sources":["../src/runners/validate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport { trackRun } from '../../Telemetry.ts'\n\ntype ValidateOptions = {\n /**\n * Path or URL to the OpenAPI/Swagger file to validate.\n */\n input: string\n}\n\n/**\n * Validates an OpenAPI/Swagger file at `input` using `@kubb/adapter-oas`.\n * Exits the process with code 1 on validation failure or missing dependency.\n */\nexport async function run({ input }: ValidateOptions): Promise<void> {\n const report = trackRun({ command: 'validate', hrStart: process.hrtime() })\n\n try {\n const { adapterOas } = await import('@kubb/adapter-oas')\n\n await adapterOas().validate(input, { throwOnError: true })\n await report({ status: 'success' })\n\n console.log('✅ Validation success')\n } catch (error) {\n await report({ status: 'failed' })\n if (error instanceof Error && /@kubb\\/adapter-oas/.test(error.message)) {\n console.error(styleText('red', 'The @kubb/adapter-oas package is not installed.'))\n console.error('')\n console.error('Install it with:')\n console.error(styleText('cyan', ' npm install @kubb/adapter-oas'))\n console.error(styleText('cyan', ' # or'))\n console.error(styleText('cyan', ' pnpm install @kubb/adapter-oas'))\n console.error('')\n }\n console.error('❌ Validation failed')\n console.error(toError(error).message)\n\n process.exit(1)\n }\n}\n"],"mappings":";;;;;;;;;;AAgBA,eAAsB,IAAI,EAAE,SAAyC;CACnE,MAAM,SAASA,kBAAAA,SAAS;EAAE,SAAS;EAAY,SAASC,aAAAA,QAAQ,OAAO;CAAE,CAAC;CAE1E,IAAI;EACF,MAAM,EAAE,eAAe,MAAM,OAAO;EAEpC,MAAM,WAAW,CAAC,CAAC,SAAS,OAAO,EAAE,cAAc,KAAK,CAAC;EACzD,MAAM,OAAO,EAAE,QAAQ,UAAU,CAAC;EAElC,QAAQ,IAAI,sBAAsB;CACpC,SAAS,OAAO;EACd,MAAM,OAAO,EAAE,QAAQ,SAAS,CAAC;EACjC,IAAI,iBAAiB,SAAS,qBAAqB,KAAK,MAAM,OAAO,GAAG;GACtE,QAAQ,OAAA,GAAMC,UAAAA,UAAAA,CAAU,OAAO,iDAAiD,CAAC;GACjF,QAAQ,MAAM,EAAE;GAChB,QAAQ,MAAM,kBAAkB;GAChC,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,iCAAiC,CAAC;GAClE,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,QAAQ,CAAC;GACzC,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,kCAAkC,CAAC;GACnE,QAAQ,MAAM,EAAE;EAClB;EACA,QAAQ,MAAM,qBAAqB;EACnC,QAAQ,MAAMC,kBAAAA,QAAQ,KAAK,CAAC,CAAC,OAAO;EAEpC,aAAA,QAAQ,KAAK,CAAC;CAChB;AACF"}
@@ -1,5 +1,5 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-CPE0t6oh.cjs");
2
- const require_Telemetry = require("./Telemetry-D3X0YeTq.cjs");
2
+ const require_Telemetry = require("./Telemetry-BfdvvZus.cjs");
3
3
  let node_util = require("node:util");
4
4
  let node_process = require("node:process");
5
5
  node_process = require_rolldown_runtime.__toESM(node_process, 1);
@@ -16,8 +16,10 @@ async function run() {
16
16
  try {
17
17
  console.error((0, node_util.styleText)("cyan", "⏳ Starting MCP server..."));
18
18
  console.warn((0, node_util.styleText)("yellow", "This feature is still under development, use with caution"));
19
- await startMcpServer();
20
- await report({ status: "success" });
19
+ startMcpServer().on("initialize", ({ clientInfo }) => void report({
20
+ status: "success",
21
+ mcpClient: clientInfo.name
22
+ }), { once: true });
21
23
  } catch (error) {
22
24
  await report({ status: "failed" });
23
25
  console.error(require_Telemetry.toError(error).message);
@@ -27,4 +29,4 @@ async function run() {
27
29
  //#endregion
28
30
  exports.run = run;
29
31
 
30
- //# sourceMappingURL=run-Dw6w0ugW.cjs.map
32
+ //# sourceMappingURL=run-B13e9GQz.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-B13e9GQz.cjs","names":["trackRun","process","styleText","toError"],"sources":["../src/runners/mcp/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport type * as McpModule from '@kubb/mcp'\nimport { trackRun } from '../../Telemetry.ts'\n\n/**\n * Starts the `@kubb/mcp` server over stdio and reports the outcome to telemetry.\n */\nexport async function run(): Promise<void> {\n const { run: startMcpServer } = (await import('@kubb/mcp')) as typeof McpModule\n\n const report = trackRun({ command: 'mcp', hrStart: process.hrtime() })\n\n try {\n // The MCP stdio transport owns stdout: anything else written there corrupts the JSON-RPC stream.\n console.error(styleText('cyan', '⏳ Starting MCP server...'))\n console.warn(styleText('yellow', 'This feature is still under development, use with caution'))\n const server = startMcpServer()\n // Report once the client introduces itself, so the event names the client (e.g. `claude-code`, `cursor-vscode`).\n server.on('initialize', ({ clientInfo }) => void report({ status: 'success', mcpClient: clientInfo.name }), { once: true })\n } catch (error) {\n await report({ status: 'failed' })\n console.error(toError(error).message)\n process.exitCode = 1\n }\n}\n"],"mappings":";;;;;;;;;AASA,eAAsB,MAAqB;CACzC,MAAM,EAAE,KAAK,mBAAoB,MAAM,OAAO;CAE9C,MAAM,SAASA,kBAAAA,SAAS;EAAE,SAAS;EAAO,SAASC,aAAAA,QAAQ,OAAO;CAAE,CAAC;CAErE,IAAI;EAEF,QAAQ,OAAA,GAAMC,UAAAA,UAAAA,CAAU,QAAQ,0BAA0B,CAAC;EAC3D,QAAQ,MAAA,GAAKA,UAAAA,UAAAA,CAAU,UAAU,2DAA2D,CAAC;EAG7F,eAAK,CAAC,CAAC,GAAG,eAAe,EAAE,iBAAiB,KAAK,OAAO;GAAE,QAAQ;GAAW,WAAW,WAAW;EAAK,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC;CAC5H,SAAS,OAAO;EACd,MAAM,OAAO,EAAE,QAAQ,SAAS,CAAC;EACjC,QAAQ,MAAMC,kBAAAA,QAAQ,KAAK,CAAC,CAAC,OAAO;EACpC,aAAA,QAAA,WAAmB;CACrB;AACF"}
@@ -1,8 +1,8 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { l as toError, n as trackRun, r as version } from "./Telemetry-DZEM4fEd.js";
3
- import { a as logInfo, c as logSpacer, h as pluralize, i as logError, l as logStep, n as logBanner, o as logIntro, s as logOutro, t as createSpinner, u as logTip } from "./output-s6v7gGbY.js";
4
- import { a as isOutdated } from "./registry-Bkeh0ipY.js";
5
- import { n as selectReporters, r as setupReporters, t as getConfigs } from "./config-DUoNrSP-.js";
2
+ import { l as toError, n as trackRun, r as version } from "./Telemetry-Bf6lUdai.js";
3
+ import { a as logInfo, c as logSpacer, h as pluralize, i as logError, l as logStep, n as logBanner, o as logIntro, s as logOutro, t as createSpinner, u as logTip } from "./output-mwVt_Vj9.js";
4
+ import { a as isOutdated } from "./registry-ChqX2AFQ.js";
5
+ import { n as selectReporters, r as setupReporters, t as getConfigs } from "./config-IMZ26zcb.js";
6
6
  import { styleText } from "node:util";
7
7
  import process from "node:process";
8
8
  import path from "node:path";
@@ -334,4 +334,4 @@ async function run({ input, configPath, logLevel: logLevelKey, watch, reporters:
334
334
  //#endregion
335
335
  export { run };
336
336
 
337
- //# sourceMappingURL=run-Bmq599S0.js.map
337
+ //# sourceMappingURL=run-BAlcXyYw.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-Bmq599S0.js","names":["logLevel","logLevelMap"],"sources":["../src/runners/generate/utils.ts","../src/runners/generate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\n\n/** Glob pattern for paths the file watcher ignores. */\nconst WATCHER_IGNORED_PATHS = '**/{.git,node_modules}/**' as const\n\n/**\n * Quiet window in milliseconds that collapses a burst of watcher events (an editor save emits several) into one rebuild.\n * It outlasts chokidar's 100 ms atomic-save window, which holds back the event of a write-then-rename save.\n */\nconst WATCHER_DEBOUNCE_MS = 250\n\n/** Interval in milliseconds between polls of a remote `input` URL in watch mode, which emits no filesystem events. */\nconst URL_WATCHER_INTERVAL_MS = 2_000\n\n/** Upper bound in milliseconds for one URL watcher request, headers and body read, so a hung server never stalls polling. */\nconst URL_WATCHER_TIMEOUT_MS = 10_000\n\ntype SerialRunnerOptions = {\n /**\n * The async work to serialize.\n */\n run(): Promise<void>\n /**\n * Receives errors thrown by `run`, so a failure never rejects the returned trigger.\n */\n onError(error: Error): void\n}\n\n/**\n * Wraps `run` so invocations never overlap: a trigger that lands while a run is in flight\n * marks it dirty and runs once more after it finishes, no matter how many triggers arrived.\n * Useful for event-driven reruns (a file watcher, a queue drain) where bursts should\n * coalesce into a single trailing run.\n *\n * @example\n * ```ts\n * const rebuild = createSerialRunner({\n * run: () => build(),\n * onError: (error) => log.error(error.message),\n * })\n * watcher.on('change', () => void rebuild())\n * ```\n */\nexport function createSerialRunner({ run, onError }: SerialRunnerOptions): () => Promise<void> {\n let running = false\n let dirty = false\n\n return async (): Promise<void> => {\n if (running) {\n dirty = true\n return\n }\n running = true\n do {\n dirty = false\n try {\n await run()\n } catch (error) {\n onError(toError(error))\n }\n } while (dirty)\n running = false\n }\n}\n\ntype WatcherLog = {\n info: (message: string) => void\n error: (message: string) => void\n}\n\n/**\n * Starts a file watcher on the given paths and calls `cb` on any change.\n * Ignores `.git` and `node_modules` directories. Event bursts (an editor save emits several)\n * are debounced into one build, and builds never overlap: changes during a build queue exactly\n * one rebuild. Resolves to a function that stops watching.\n */\nexport async function startWatcher(\n path: Array<string>,\n cb: (path: Array<string>) => Promise<void>,\n log: WatcherLog = { info: console.log, error: console.log },\n): Promise<() => Promise<void>> {\n const { watch } = await import('chokidar')\n // `ignoreInitial` skips the `add` events chokidar fires for existing files at startup, which\n // would otherwise rebuild right after the initial run.\n const watcher = watch(path, { ignorePermissionErrors: true, ignored: WATCHER_IGNORED_PATHS, ignoreInitial: true })\n\n process.once('SIGINT', () => {\n watcher.close()\n })\n process.once('SIGTERM', () => {\n watcher.close()\n })\n\n // Bursts never overlap builds on the shared hooks emitter: a change during a build\n // queues exactly one rerun.\n const runBuild = createSerialRunner({\n run: () => cb(path),\n onError: () => log.error(styleText('red', 'Watcher failed')),\n })\n let debounceTimer: ReturnType<typeof setTimeout> | null = null\n\n watcher.on('all', (type, file) => {\n log.info(styleText('yellow', styleText('bold', `Change detected: ${type} ${file}`)))\n if (debounceTimer) clearTimeout(debounceTimer)\n debounceTimer = setTimeout(() => {\n debounceTimer = null\n void runBuild()\n }, WATCHER_DEBOUNCE_MS)\n })\n\n return async () => {\n if (debounceTimer) clearTimeout(debounceTimer)\n await watcher.close()\n }\n}\n\n/**\n * Fetches the body of a remote spec URL, `undefined` when the server does not answer with a\n * readable 2xx body before `signal` aborts. The caller seeds `startUrlWatcher` with the result, so\n * the watcher compares polls against the content the initial build ran on.\n */\nexport async function fetchUrlBody(url: string, signal: AbortSignal = AbortSignal.timeout(URL_WATCHER_TIMEOUT_MS)): Promise<string | undefined> {\n try {\n const response = await fetch(url, { signal })\n if (!response.ok) return undefined\n return await response.text()\n } catch {\n return undefined\n }\n}\n\ntype UrlWatcherOptions = {\n /**\n * Sink for watcher messages, `console.log` by default.\n */\n log?: WatcherLog\n /**\n * Time in milliseconds between polls.\n */\n intervalMs?: number\n /**\n * Upper bound in milliseconds for one poll request, covering headers and body read.\n */\n timeoutMs?: number\n /**\n * Body the initial build ran against, the baseline for change detection. When omitted (the\n * server was unreachable at startup), the first successful poll rebuilds so the output catches\n * up as soon as the server responds.\n */\n initialBody?: string\n}\n\n/**\n * Polls a remote spec URL and calls `cb` whenever the response body changes. A remote document\n * emits no filesystem events, so this is the URL counterpart of `startWatcher`.\n *\n * `initialBody` seeds the change detection, so an edit landing between the initial build and the\n * first poll still rebuilds. An unreachable server (the API restarting between saves) is reported\n * once per outage and polling continues; after it recovers, a rebuild happens only when the body\n * actually differs from the last one seen, so a plain restart with an unchanged spec stays quiet.\n * Each request is aborted after `timeoutMs`, so a hung response delays at most one poll.\n *\n * Returns a function that stops polling and aborts the in-flight request, so callers (and tests)\n * can shut the watcher down without signaling the process.\n */\nexport function startUrlWatcher(url: string, cb: (path: Array<string>) => Promise<void>, options: UrlWatcherOptions = {}): () => void {\n const { log = { info: console.log, error: console.log }, intervalMs = URL_WATCHER_INTERVAL_MS, timeoutMs = URL_WATCHER_TIMEOUT_MS, initialBody } = options\n\n let lastBody = initialBody\n let offline = false\n let timer: ReturnType<typeof setTimeout> | null = null\n let controller: AbortController | null = null\n let stopped = false\n\n const stop = () => {\n stopped = true\n if (timer) clearTimeout(timer)\n controller?.abort()\n }\n process.once('SIGINT', stop)\n process.once('SIGTERM', stop)\n\n // Builds never overlap on the shared hooks emitter: a change during a build queues exactly\n // one rerun.\n const runBuild = createSerialRunner({\n run: () => cb([url]),\n onError: () => log.error(styleText('red', 'Watcher failed')),\n })\n\n const schedule = () => {\n if (!stopped) {\n timer = setTimeout(() => void poll(), intervalMs)\n }\n }\n\n const poll = async (): Promise<void> => {\n controller = new AbortController()\n // The signal also aborts the body read, so a response that stalls mid-stream still times out.\n const body = await fetchUrlBody(url, AbortSignal.any([controller.signal, AbortSignal.timeout(timeoutMs)]))\n\n if (body === undefined) {\n // `lastBody` survives the outage so recovery rebuilds only on real content changes.\n if (!offline && !stopped) {\n offline = true\n log.error(styleText('red', `Cannot reach ${url}, polling until it responds again`))\n }\n schedule()\n return\n }\n\n if (offline) {\n offline = false\n log.info(styleText('yellow', `${url} is reachable again`))\n }\n const changed = lastBody !== undefined && body !== lastBody\n if (changed) {\n log.info(styleText('yellow', styleText('bold', `Change detected: ${url}`)))\n }\n if (changed || lastBody === undefined) {\n void runBuild()\n }\n lastBody = body\n schedule()\n }\n\n void poll()\n\n return stop\n}\n","import path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport { formatters, linters, toError } from '@internals/utils'\nimport {\n Hookable,\n type CLIOptions,\n cliReporter,\n type Config,\n createKubb,\n Diagnostics,\n fileReporter,\n getInputKind,\n htmlReporter,\n jsonReporter,\n type KubbHooks,\n logLevel as logLevelMap,\n memoryStorage,\n type ReporterName,\n} from '@kubb/core'\nimport { version } from '../../../package.json'\nimport { trackRun } from '../../Telemetry.ts'\nimport { pluralize } from '../../loggers/createLogger.ts'\nimport setupReporters, { selectReporters } from '../../loggers/reporters.ts'\nimport { createSpinner, logBanner, logError, logInfo, logIntro, logOutro, logSpacer, logStep, logTip } from '../../loggers/output.ts'\nimport { getConfigs } from '../../config.ts'\nimport { isOutdated } from '../../utils/registry.ts'\nimport { fetchUrlBody, startUrlWatcher, startWatcher } from './utils.ts'\n\n/** NPM registry endpoint used to check for @kubb/cli updates. */\nconst KUBB_NPM_PACKAGE_URL = 'https://registry.npmjs.org/@kubb/cli/latest' as const\n\n/** Upper bound in milliseconds for the npm update check, so a slow registry never stalls a run. */\nconst UPDATE_CHECK_TIMEOUT_MS = 3_000\n\n/** The formatter names from `Config['output'].format`, without `'auto'` (detection, not a tool) and `false` (skip). */\ntype FormatterName = Exclude<NonNullable<Config['output']['format']>, 'auto' | false>\ntype LinterName = Exclude<NonNullable<Config['output']['lint']>, 'auto' | false>\n\n// Pinned here, not in `@internals/utils` (which must not import `@kubb/core`): a tool added to the union without a descriptor fails to compile.\nformatters satisfies Record<FormatterName, unknown>\nlinters satisfies Record<LinterName, unknown>\n\ntype GenerateProps = {\n input?: string\n config: Config\n hooks: Hookable<KubbHooks>\n /**\n * When `true`, generates in memory instead of writing to disk, and skips formatting, linting,\n * and post-generate commands.\n */\n dryRun?: boolean\n}\n\nasync function generate(options: GenerateProps): Promise<boolean> {\n const { input, hooks, dryRun = false } = options\n\n const report = trackRun({ command: 'generate', hrStart: process.hrtime() })\n\n const config: Config = {\n ...options.config,\n input: input ?? options.config.input,\n // Dry-run never touches disk, regardless of the config's own storage driver.\n storage: dryRun ? memoryStorage() : options.config.storage,\n // Also keeps core's `hasOutputPasses` false, so dry-run skips the output manifest write too.\n output: dryRun ? { ...options.config.output, format: false, lint: false, postGenerate: [] } : options.config.output,\n }\n\n // Core formats, lints and runs `output.postGenerate` after an error-free build, and reports\n // their failures as coded diagnostics that reach the summary, the json report and the exit code.\n const kubb = createKubb(config, { hooks })\n const result = await kubb.generate()\n\n if (dryRun) {\n await hooks.callHook('kubb:info', { message: 'Dry run: no files were written', info: `${result.files.length} file(s) would be generated` })\n }\n\n await report({\n plugins: Array.from(kubb.driver.plugins.values(), (p) => ({ name: p.name, options: p.options as Record<string, unknown> })),\n filesCreated: result.files.length,\n status: result.success ? 'success' : 'failed',\n })\n\n return result.success\n}\n\ntype GenerateCommandOptions = {\n input?: string\n configPath?: string\n logLevel: string\n watch: boolean\n reporters?: Array<ReporterName>\n dryRun?: boolean\n}\n\nasync function checkForUpdate(hooks: Hookable<KubbHooks>): Promise<void> {\n try {\n const res = await fetch(KUBB_NPM_PACKAGE_URL, { signal: AbortSignal.timeout(UPDATE_CHECK_TIMEOUT_MS) })\n const data = (await res.json()) as { version: string }\n if (data.version && isOutdated({ installed: version, latest: data.version })) {\n await Diagnostics.emit(hooks, Diagnostics.update({ currentVersion: version, latestVersion: data.version }))\n }\n } catch {\n // Ignore network errors\n }\n}\n\n/**\n * Runs the full Kubb generation lifecycle for the given CLI options.\n * Loads configs, sets up the reporters (CLI `--reporter` picks which of `config.reporters` to trigger),\n * checks for a newer version, and calls `generate` for each config entry.\n */\nexport async function run({ input, configPath, logLevel: logLevelKey, watch, reporters: cliReporters, dryRun }: GenerateCommandOptions): Promise<void> {\n const logLevel = logLevelMap[logLevelKey as keyof typeof logLevelMap] ?? logLevelMap.info\n const hooks = new Hookable<KubbHooks>()\n\n // CLI `--reporter` selects which reporters to trigger by name, defaulting to `cli`. `defineConfig`\n // registers the built-in reporters on the config; a config exported without it falls back to them below.\n const requestedNames: Array<ReporterName> = cliReporters?.length ? cliReporters : ['cli']\n\n // The `json` reporter owns stdout, so the command writes nothing of its own around it.\n const quiet = logLevel <= logLevelMap.silent || requestedNames.includes('json')\n\n if (!quiet) {\n logBanner(version)\n logIntro({ title: 'Configuration' })\n }\n\n // Load the config first so `config.reporters` can pick the reporters. A failure here has no\n // reporter installed yet, so fall back to the default `cli` reporter to surface it.\n const configSpinner = createSpinner()\n let configs: Array<Config>\n let resolvedConfigPath: string\n try {\n if (!quiet) configSpinner.start('Loading config')\n\n const loaded = await getConfigs({\n configPath,\n input,\n watch,\n logLevel: logLevelKey as CLIOptions['logLevel'],\n })\n configs = loaded.configs\n resolvedConfigPath = loaded.configPath\n\n if (!quiet) configSpinner.stop(`Loaded ${styleText('dim', path.relative(process.cwd(), resolvedConfigPath))}`)\n } catch (error) {\n if (!quiet) configSpinner.error('Config failed loading')\n\n setupReporters(hooks, { logLevel, reporters: [cliReporter] })\n // A diagnostic thrown while the config file runs, such as invalid extension options, sits in the cause chain.\n const diagnostic = Diagnostics.from(error)\n await (diagnostic.code === Diagnostics.code.unknown ? hooks.callHook('kubb:error', { error: toError(error) }) : Diagnostics.emit(hooks, diagnostic))\n\n if (!quiet) logOutro(styleText('red', '✗ Configuration failed'))\n process.exit(1)\n }\n\n // Without a reporter nothing is printed, not even an error, so a config written without\n // `defineConfig` gets the same built-ins it would have registered.\n const available = configs[0]?.reporters?.length ? configs[0].reporters : [cliReporter, jsonReporter, fileReporter, htmlReporter]\n const reporters = selectReporters(available, requestedNames)\n setupReporters(hooks, { logLevel, reporters })\n\n await hooks.callHook('kubb:lifecycle:start', { version })\n\n // Inside the bootstrap group, so an update notice reads as part of the setup rather than as part\n // of the first config's generation.\n await checkForUpdate(hooks)\n\n if (!quiet) logOutro(`${pluralize(configs.length, 'config')} ready`)\n\n try {\n let anyFailed = false\n for (const config of configs) {\n const effectiveInput = input ?? config.input\n const inputKind = typeof effectiveInput === 'string' ? getInputKind(effectiveInput) : undefined\n const watchPath = inputKind === 'file' || inputKind === 'url' ? (effectiveInput as string) : undefined\n if (watchPath && watch) {\n const watchedPaths = [watchPath]\n // Don't removeAll() between builds, that would also drop logger and lifecycle\n // listeners. Plugin listeners are already disposed by safeBuild's dispose()\n // in its finally block, so re-running generate() on the same hooks emitter is safe.\n const build = async (paths: Array<string>) => {\n const succeeded = await generate({ input, config, hooks, dryRun })\n logStep(styleText('yellow', `Watching for changes in ${paths.join(' and ')}`))\n if (succeeded) {\n logSpacer()\n logTip()\n }\n }\n\n // For a URL input, capture the document before the build: it becomes the watcher's\n // change-detection baseline, so an edit landing before the first poll still rebuilds.\n // When the server is down the baseline stays undefined and the watcher rebuilds on its\n // first successful poll, so recovery with an unchanged document still generates output.\n const initialBody = inputKind === 'url' ? await fetchUrlBody(watchPath) : undefined\n\n // The watchers ignore their startup state, so run the first build here; a failing one keeps watching so the user can fix the input.\n try {\n await build(watchedPaths)\n } catch (buildError) {\n await hooks.callHook('kubb:error', { error: toError(buildError) })\n }\n\n if (inputKind === 'url') {\n startUrlWatcher(watchPath, build, { log: { info: logInfo, error: logError }, initialBody })\n } else {\n await startWatcher(watchedPaths, build, { info: logInfo, error: logError })\n }\n } else {\n try {\n const succeeded = await generate({ input, config, hooks, dryRun })\n if (!succeeded) anyFailed = true\n } catch (configError) {\n await hooks.callHook('kubb:error', { error: toError(configError) })\n anyFailed = true\n }\n }\n }\n\n await hooks.callHook('kubb:lifecycle:end')\n\n // Watch mode prints a tip after each successful build. Regular generate commands need to\n // print one explicitly after the lifecycle group has closed so it stays outside the group.\n if (!quiet && !watch && !anyFailed) {\n logTip()\n }\n\n if (anyFailed) {\n process.exit(1)\n }\n } catch (error) {\n await hooks.callHook('kubb:error', { error: toError(error) })\n process.exit(1)\n }\n}\n"],"mappings":";;;;;;;;;;;AAKA,MAAM,wBAAwB;;;;;AAM9B,MAAM,sBAAsB;;AAG5B,MAAM,0BAA0B;;AAGhC,MAAM,yBAAyB;;;;;;;;;;;;;;;;AA4B/B,SAAgB,mBAAmB,EAAE,KAAK,WAAqD;CAC7F,IAAI,UAAU;CACd,IAAI,QAAQ;CAEZ,OAAO,YAA2B;EAChC,IAAI,SAAS;GACX,QAAQ;GACR;EACF;EACA,UAAU;EACV,GAAG;GACD,QAAQ;GACR,IAAI;IACF,MAAM,IAAI;GACZ,SAAS,OAAO;IACd,QAAQ,QAAQ,KAAK,CAAC;GACxB;EACF,SAAS;EACT,UAAU;CACZ;AACF;;;;;;;AAaA,eAAsB,aACpB,MACA,IACA,MAAkB;CAAE,MAAM,QAAQ;CAAK,OAAO,QAAQ;AAAI,GAC5B;CAC9B,MAAM,EAAE,UAAU,MAAM,OAAO;CAG/B,MAAM,UAAU,MAAM,MAAM;EAAE,wBAAwB;EAAM,SAAS;EAAuB,eAAe;CAAK,CAAC;CAEjH,QAAQ,KAAK,gBAAgB;EAC3B,QAAQ,MAAM;CAChB,CAAC;CACD,QAAQ,KAAK,iBAAiB;EAC5B,QAAQ,MAAM;CAChB,CAAC;CAID,MAAM,WAAW,mBAAmB;EAClC,WAAW,GAAG,IAAI;EAClB,eAAe,IAAI,MAAM,UAAU,OAAO,gBAAgB,CAAC;CAC7D,CAAC;CACD,IAAI,gBAAsD;CAE1D,QAAQ,GAAG,QAAQ,MAAM,SAAS;EAChC,IAAI,KAAK,UAAU,UAAU,UAAU,QAAQ,oBAAoB,KAAK,GAAG,MAAM,CAAC,CAAC;EACnF,IAAI,eAAe,aAAa,aAAa;EAC7C,gBAAgB,iBAAiB;GAC/B,gBAAgB;GAChB,SAAc;EAChB,GAAG,mBAAmB;CACxB,CAAC;CAED,OAAO,YAAY;EACjB,IAAI,eAAe,aAAa,aAAa;EAC7C,MAAM,QAAQ,MAAM;CACtB;AACF;;;;;;AAOA,eAAsB,aAAa,KAAa,SAAsB,YAAY,QAAQ,sBAAsB,GAAgC;CAC9I,IAAI;EACF,MAAM,WAAW,MAAM,MAAM,KAAK,EAAE,OAAO,CAAC;EAC5C,IAAI,CAAC,SAAS,IAAI,OAAO,KAAA;EACzB,OAAO,MAAM,SAAS,KAAK;CAC7B,QAAQ;EACN;CACF;AACF;;;;;;;;;;;;;;AAoCA,SAAgB,gBAAgB,KAAa,IAA4C,UAA6B,CAAC,GAAe;CACpI,MAAM,EAAE,MAAM;EAAE,MAAM,QAAQ;EAAK,OAAO,QAAQ;CAAI,GAAG,aAAa,yBAAyB,YAAY,wBAAwB,gBAAgB;CAEnJ,IAAI,WAAW;CACf,IAAI,UAAU;CACd,IAAI,QAA8C;CAClD,IAAI,aAAqC;CACzC,IAAI,UAAU;CAEd,MAAM,aAAa;EACjB,UAAU;EACV,IAAI,OAAO,aAAa,KAAK;EAC7B,YAAY,MAAM;CACpB;CACA,QAAQ,KAAK,UAAU,IAAI;CAC3B,QAAQ,KAAK,WAAW,IAAI;CAI5B,MAAM,WAAW,mBAAmB;EAClC,WAAW,GAAG,CAAC,GAAG,CAAC;EACnB,eAAe,IAAI,MAAM,UAAU,OAAO,gBAAgB,CAAC;CAC7D,CAAC;CAED,MAAM,iBAAiB;EACrB,IAAI,CAAC,SACH,QAAQ,iBAAiB,KAAK,KAAK,GAAG,UAAU;CAEpD;CAEA,MAAM,OAAO,YAA2B;EACtC,aAAa,IAAI,gBAAgB;EAEjC,MAAM,OAAO,MAAM,aAAa,KAAK,YAAY,IAAI,CAAC,WAAW,QAAQ,YAAY,QAAQ,SAAS,CAAC,CAAC,CAAC;EAEzG,IAAI,SAAS,KAAA,GAAW;GAEtB,IAAI,CAAC,WAAW,CAAC,SAAS;IACxB,UAAU;IACV,IAAI,MAAM,UAAU,OAAO,gBAAgB,IAAI,kCAAkC,CAAC;GACpF;GACA,SAAS;GACT;EACF;EAEA,IAAI,SAAS;GACX,UAAU;GACV,IAAI,KAAK,UAAU,UAAU,GAAG,IAAI,oBAAoB,CAAC;EAC3D;EACA,MAAM,UAAU,aAAa,KAAA,KAAa,SAAS;EACnD,IAAI,SACF,IAAI,KAAK,UAAU,UAAU,UAAU,QAAQ,oBAAoB,KAAK,CAAC,CAAC;EAE5E,IAAI,WAAW,aAAa,KAAA,GAC1B,SAAc;EAEhB,WAAW;EACX,SAAS;CACX;CAEA,KAAU;CAEV,OAAO;AACT;;;;ACxMA,MAAM,uBAAuB;;AAG7B,MAAM,0BAA0B;AAqBhC,eAAe,SAAS,SAA0C;CAChE,MAAM,EAAE,OAAO,OAAO,SAAS,UAAU;CAEzC,MAAM,SAAS,SAAS;EAAE,SAAS;EAAY,SAAS,QAAQ,OAAO;CAAE,CAAC;CAE1E,MAAM,SAAiB;EACrB,GAAG,QAAQ;EACX,OAAO,SAAS,QAAQ,OAAO;EAE/B,SAAS,SAAS,cAAc,IAAI,QAAQ,OAAO;EAEnD,QAAQ,SAAS;GAAE,GAAG,QAAQ,OAAO;GAAQ,QAAQ;GAAO,MAAM;GAAO,cAAc,CAAC;EAAE,IAAI,QAAQ,OAAO;CAC/G;CAIA,MAAM,OAAO,WAAW,QAAQ,EAAE,MAAM,CAAC;CACzC,MAAM,SAAS,MAAM,KAAK,SAAS;CAEnC,IAAI,QACF,MAAM,MAAM,SAAS,aAAa;EAAE,SAAS;EAAkC,MAAM,GAAG,OAAO,MAAM,OAAO;CAA6B,CAAC;CAG5I,MAAM,OAAO;EACX,SAAS,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,IAAI,OAAO;GAAE,MAAM,EAAE;GAAM,SAAS,EAAE;EAAmC,EAAE;EAC1H,cAAc,OAAO,MAAM;EAC3B,QAAQ,OAAO,UAAU,YAAY;CACvC,CAAC;CAED,OAAO,OAAO;AAChB;AAWA,eAAe,eAAe,OAA2C;CACvE,IAAI;EAEF,MAAM,OAAQ,OAAM,MADF,MAAM,sBAAsB,EAAE,QAAQ,YAAY,QAAQ,uBAAuB,EAAE,CAAC,EAAA,CAC9E,KAAK;EAC7B,IAAI,KAAK,WAAW,WAAW;GAAE,WAAW;GAAS,QAAQ,KAAK;EAAQ,CAAC,GACzE,MAAM,YAAY,KAAK,OAAO,YAAY,OAAO;GAAE,gBAAgB;GAAS,eAAe,KAAK;EAAQ,CAAC,CAAC;CAE9G,QAAQ,CAER;AACF;;;;;;AAOA,eAAsB,IAAI,EAAE,OAAO,YAAY,UAAU,aAAa,OAAO,WAAW,cAAc,UAAiD;CACrJ,MAAMA,aAAWC,SAAY,gBAA4CA,SAAY;CACrF,MAAM,QAAQ,IAAI,SAAoB;CAItC,MAAM,iBAAsC,cAAc,SAAS,eAAe,CAAC,KAAK;CAGxF,MAAM,QAAQD,cAAYC,SAAY,UAAU,eAAe,SAAS,MAAM;CAE9E,IAAI,CAAC,OAAO;EACV,UAAU,OAAO;EACjB,SAAS,EAAE,OAAO,gBAAgB,CAAC;CACrC;CAIA,MAAM,gBAAgB,cAAc;CACpC,IAAI;CACJ,IAAI;CACJ,IAAI;EACF,IAAI,CAAC,OAAO,cAAc,MAAM,gBAAgB;EAEhD,MAAM,SAAS,MAAM,WAAW;GAC9B;GACA;GACA;GACA,UAAU;EACZ,CAAC;EACD,UAAU,OAAO;EACjB,qBAAqB,OAAO;EAE5B,IAAI,CAAC,OAAO,cAAc,KAAK,UAAU,UAAU,OAAO,KAAK,SAAS,QAAQ,IAAI,GAAG,kBAAkB,CAAC,GAAG;CAC/G,SAAS,OAAO;EACd,IAAI,CAAC,OAAO,cAAc,MAAM,uBAAuB;EAEvD,eAAe,OAAO;GAAE,UAAA;GAAU,WAAW,CAAC,WAAW;EAAE,CAAC;EAE5D,MAAM,aAAa,YAAY,KAAK,KAAK;EACzC,OAAO,WAAW,SAAS,YAAY,KAAK,UAAU,MAAM,SAAS,cAAc,EAAE,OAAO,QAAQ,KAAK,EAAE,CAAC,IAAI,YAAY,KAAK,OAAO,UAAU;EAElJ,IAAI,CAAC,OAAO,SAAS,UAAU,OAAO,wBAAwB,CAAC;EAC/D,QAAQ,KAAK,CAAC;CAChB;CAIA,MAAM,YAAY,QAAQ,EAAE,EAAE,WAAW,SAAS,QAAQ,EAAE,CAAC,YAAY;EAAC;EAAa;EAAc;EAAc;CAAY;CAC/H,MAAM,YAAY,gBAAgB,WAAW,cAAc;CAC3D,eAAe,OAAO;EAAE,UAAA;EAAU;CAAU,CAAC;CAE7C,MAAM,MAAM,SAAS,wBAAwB,EAAE,QAAQ,CAAC;CAIxD,MAAM,eAAe,KAAK;CAE1B,IAAI,CAAC,OAAO,SAAS,GAAG,UAAU,QAAQ,QAAQ,QAAQ,EAAE,OAAO;CAEnE,IAAI;EACF,IAAI,YAAY;EAChB,KAAK,MAAM,UAAU,SAAS;GAC5B,MAAM,iBAAiB,SAAS,OAAO;GACvC,MAAM,YAAY,OAAO,mBAAmB,WAAW,aAAa,cAAc,IAAI,KAAA;GACtF,MAAM,YAAY,cAAc,UAAU,cAAc,QAAS,iBAA4B,KAAA;GAC7F,IAAI,aAAa,OAAO;IACtB,MAAM,eAAe,CAAC,SAAS;IAI/B,MAAM,QAAQ,OAAO,UAAyB;KAC5C,MAAM,YAAY,MAAM,SAAS;MAAE;MAAO;MAAQ;MAAO;KAAO,CAAC;KACjE,QAAQ,UAAU,UAAU,2BAA2B,MAAM,KAAK,OAAO,GAAG,CAAC;KAC7E,IAAI,WAAW;MACb,UAAU;MACV,OAAO;KACT;IACF;IAMA,MAAM,cAAc,cAAc,QAAQ,MAAM,aAAa,SAAS,IAAI,KAAA;IAG1E,IAAI;KACF,MAAM,MAAM,YAAY;IAC1B,SAAS,YAAY;KACnB,MAAM,MAAM,SAAS,cAAc,EAAE,OAAO,QAAQ,UAAU,EAAE,CAAC;IACnE;IAEA,IAAI,cAAc,OAChB,gBAAgB,WAAW,OAAO;KAAE,KAAK;MAAE,MAAM;MAAS,OAAO;KAAS;KAAG;IAAY,CAAC;SAE1F,MAAM,aAAa,cAAc,OAAO;KAAE,MAAM;KAAS,OAAO;IAAS,CAAC;GAE9E,OACE,IAAI;IAEF,IAAI,CAAC,MADmB,SAAS;KAAE;KAAO;KAAQ;KAAO;IAAO,CAAC,GACjD,YAAY;GAC9B,SAAS,aAAa;IACpB,MAAM,MAAM,SAAS,cAAc,EAAE,OAAO,QAAQ,WAAW,EAAE,CAAC;IAClE,YAAY;GACd;EAEJ;EAEA,MAAM,MAAM,SAAS,oBAAoB;EAIzC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,WACvB,OAAO;EAGT,IAAI,WACF,QAAQ,KAAK,CAAC;CAElB,SAAS,OAAO;EACd,MAAM,MAAM,SAAS,cAAc,EAAE,OAAO,QAAQ,KAAK,EAAE,CAAC;EAC5D,QAAQ,KAAK,CAAC;CAChB;AACF"}
1
+ {"version":3,"file":"run-BAlcXyYw.js","names":["logLevel","logLevelMap"],"sources":["../src/runners/generate/utils.ts","../src/runners/generate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\n\n/** Glob pattern for paths the file watcher ignores. */\nconst WATCHER_IGNORED_PATHS = '**/{.git,node_modules}/**' as const\n\n/**\n * Quiet window in milliseconds that collapses a burst of watcher events (an editor save emits several) into one rebuild.\n * It outlasts chokidar's 100 ms atomic-save window, which holds back the event of a write-then-rename save.\n */\nconst WATCHER_DEBOUNCE_MS = 250\n\n/** Interval in milliseconds between polls of a remote `input` URL in watch mode, which emits no filesystem events. */\nconst URL_WATCHER_INTERVAL_MS = 2_000\n\n/** Upper bound in milliseconds for one URL watcher request, headers and body read, so a hung server never stalls polling. */\nconst URL_WATCHER_TIMEOUT_MS = 10_000\n\ntype SerialRunnerOptions = {\n /**\n * The async work to serialize.\n */\n run(): Promise<void>\n /**\n * Receives errors thrown by `run`, so a failure never rejects the returned trigger.\n */\n onError(error: Error): void\n}\n\n/**\n * Wraps `run` so invocations never overlap: a trigger that lands while a run is in flight\n * marks it dirty and runs once more after it finishes, no matter how many triggers arrived.\n * Useful for event-driven reruns (a file watcher, a queue drain) where bursts should\n * coalesce into a single trailing run.\n *\n * @example\n * ```ts\n * const rebuild = createSerialRunner({\n * run: () => build(),\n * onError: (error) => log.error(error.message),\n * })\n * watcher.on('change', () => void rebuild())\n * ```\n */\nexport function createSerialRunner({ run, onError }: SerialRunnerOptions): () => Promise<void> {\n let running = false\n let dirty = false\n\n return async (): Promise<void> => {\n if (running) {\n dirty = true\n return\n }\n running = true\n do {\n dirty = false\n try {\n await run()\n } catch (error) {\n onError(toError(error))\n }\n } while (dirty)\n running = false\n }\n}\n\ntype WatcherLog = {\n info: (message: string) => void\n error: (message: string) => void\n}\n\n/**\n * Starts a file watcher on the given paths and calls `cb` on any change.\n * Ignores `.git` and `node_modules` directories. Event bursts (an editor save emits several)\n * are debounced into one build, and builds never overlap: changes during a build queue exactly\n * one rebuild. Resolves to a function that stops watching.\n */\nexport async function startWatcher(\n path: Array<string>,\n cb: (path: Array<string>) => Promise<void>,\n log: WatcherLog = { info: console.log, error: console.log },\n): Promise<() => Promise<void>> {\n const { watch } = await import('chokidar')\n // `ignoreInitial` skips the `add` events chokidar fires for existing files at startup, which\n // would otherwise rebuild right after the initial run.\n const watcher = watch(path, { ignorePermissionErrors: true, ignored: WATCHER_IGNORED_PATHS, ignoreInitial: true })\n\n process.once('SIGINT', () => {\n watcher.close()\n })\n process.once('SIGTERM', () => {\n watcher.close()\n })\n\n // Bursts never overlap builds on the shared hooks emitter: a change during a build\n // queues exactly one rerun.\n const runBuild = createSerialRunner({\n run: () => cb(path),\n onError: () => log.error(styleText('red', 'Watcher failed')),\n })\n let debounceTimer: ReturnType<typeof setTimeout> | null = null\n\n watcher.on('all', (type, file) => {\n log.info(styleText('yellow', styleText('bold', `Change detected: ${type} ${file}`)))\n if (debounceTimer) clearTimeout(debounceTimer)\n debounceTimer = setTimeout(() => {\n debounceTimer = null\n void runBuild()\n }, WATCHER_DEBOUNCE_MS)\n })\n\n return async () => {\n if (debounceTimer) clearTimeout(debounceTimer)\n await watcher.close()\n }\n}\n\n/**\n * Fetches the body of a remote spec URL, `undefined` when the server does not answer with a\n * readable 2xx body before `signal` aborts. The caller seeds `startUrlWatcher` with the result, so\n * the watcher compares polls against the content the initial build ran on.\n */\nexport async function fetchUrlBody(url: string, signal: AbortSignal = AbortSignal.timeout(URL_WATCHER_TIMEOUT_MS)): Promise<string | undefined> {\n try {\n const response = await fetch(url, { signal })\n if (!response.ok) return undefined\n return await response.text()\n } catch {\n return undefined\n }\n}\n\ntype UrlWatcherOptions = {\n /**\n * Sink for watcher messages, `console.log` by default.\n */\n log?: WatcherLog\n /**\n * Time in milliseconds between polls.\n */\n intervalMs?: number\n /**\n * Upper bound in milliseconds for one poll request, covering headers and body read.\n */\n timeoutMs?: number\n /**\n * Body the initial build ran against, the baseline for change detection. When omitted (the\n * server was unreachable at startup), the first successful poll rebuilds so the output catches\n * up as soon as the server responds.\n */\n initialBody?: string\n}\n\n/**\n * Polls a remote spec URL and calls `cb` whenever the response body changes. A remote document\n * emits no filesystem events, so this is the URL counterpart of `startWatcher`.\n *\n * `initialBody` seeds the change detection, so an edit landing between the initial build and the\n * first poll still rebuilds. An unreachable server (the API restarting between saves) is reported\n * once per outage and polling continues; after it recovers, a rebuild happens only when the body\n * actually differs from the last one seen, so a plain restart with an unchanged spec stays quiet.\n * Each request is aborted after `timeoutMs`, so a hung response delays at most one poll.\n *\n * Returns a function that stops polling and aborts the in-flight request, so callers (and tests)\n * can shut the watcher down without signaling the process.\n */\nexport function startUrlWatcher(url: string, cb: (path: Array<string>) => Promise<void>, options: UrlWatcherOptions = {}): () => void {\n const { log = { info: console.log, error: console.log }, intervalMs = URL_WATCHER_INTERVAL_MS, timeoutMs = URL_WATCHER_TIMEOUT_MS, initialBody } = options\n\n let lastBody = initialBody\n let offline = false\n let timer: ReturnType<typeof setTimeout> | null = null\n let controller: AbortController | null = null\n let stopped = false\n\n const stop = () => {\n stopped = true\n if (timer) clearTimeout(timer)\n controller?.abort()\n }\n process.once('SIGINT', stop)\n process.once('SIGTERM', stop)\n\n // Builds never overlap on the shared hooks emitter: a change during a build queues exactly\n // one rerun.\n const runBuild = createSerialRunner({\n run: () => cb([url]),\n onError: () => log.error(styleText('red', 'Watcher failed')),\n })\n\n const schedule = () => {\n if (!stopped) {\n timer = setTimeout(() => void poll(), intervalMs)\n }\n }\n\n const poll = async (): Promise<void> => {\n controller = new AbortController()\n // The signal also aborts the body read, so a response that stalls mid-stream still times out.\n const body = await fetchUrlBody(url, AbortSignal.any([controller.signal, AbortSignal.timeout(timeoutMs)]))\n\n if (body === undefined) {\n // `lastBody` survives the outage so recovery rebuilds only on real content changes.\n if (!offline && !stopped) {\n offline = true\n log.error(styleText('red', `Cannot reach ${url}, polling until it responds again`))\n }\n schedule()\n return\n }\n\n if (offline) {\n offline = false\n log.info(styleText('yellow', `${url} is reachable again`))\n }\n const changed = lastBody !== undefined && body !== lastBody\n if (changed) {\n log.info(styleText('yellow', styleText('bold', `Change detected: ${url}`)))\n }\n if (changed || lastBody === undefined) {\n void runBuild()\n }\n lastBody = body\n schedule()\n }\n\n void poll()\n\n return stop\n}\n","import path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport { formatters, linters, toError } from '@internals/utils'\nimport {\n Hookable,\n type CLIOptions,\n cliReporter,\n type Config,\n createKubb,\n Diagnostics,\n fileReporter,\n getInputKind,\n htmlReporter,\n jsonReporter,\n type KubbHooks,\n logLevel as logLevelMap,\n memoryStorage,\n type ReporterName,\n} from '@kubb/core'\nimport { version } from '../../../package.json'\nimport { trackRun } from '../../Telemetry.ts'\nimport { pluralize } from '../../loggers/createLogger.ts'\nimport setupReporters, { selectReporters } from '../../loggers/reporters.ts'\nimport { createSpinner, logBanner, logError, logInfo, logIntro, logOutro, logSpacer, logStep, logTip } from '../../loggers/output.ts'\nimport { getConfigs } from '../../config.ts'\nimport { isOutdated } from '../../utils/registry.ts'\nimport { fetchUrlBody, startUrlWatcher, startWatcher } from './utils.ts'\n\n/** NPM registry endpoint used to check for @kubb/cli updates. */\nconst KUBB_NPM_PACKAGE_URL = 'https://registry.npmjs.org/@kubb/cli/latest' as const\n\n/** Upper bound in milliseconds for the npm update check, so a slow registry never stalls a run. */\nconst UPDATE_CHECK_TIMEOUT_MS = 3_000\n\n/** The formatter names from `Config['output'].format`, without `'auto'` (detection, not a tool) and `false` (skip). */\ntype FormatterName = Exclude<NonNullable<Config['output']['format']>, 'auto' | false>\ntype LinterName = Exclude<NonNullable<Config['output']['lint']>, 'auto' | false>\n\n// Pinned here, not in `@internals/utils` (which must not import `@kubb/core`): a tool added to the union without a descriptor fails to compile.\nformatters satisfies Record<FormatterName, unknown>\nlinters satisfies Record<LinterName, unknown>\n\ntype GenerateProps = {\n input?: string\n config: Config\n hooks: Hookable<KubbHooks>\n /**\n * When `true`, generates in memory instead of writing to disk, and skips formatting, linting,\n * and post-generate commands.\n */\n dryRun?: boolean\n}\n\nasync function generate(options: GenerateProps): Promise<boolean> {\n const { input, hooks, dryRun = false } = options\n\n const report = trackRun({ command: 'generate', hrStart: process.hrtime() })\n\n const config: Config = {\n ...options.config,\n input: input ?? options.config.input,\n // Dry-run never touches disk, regardless of the config's own storage driver.\n storage: dryRun ? memoryStorage() : options.config.storage,\n // Also keeps core's `hasOutputPasses` false, so dry-run skips the output manifest write too.\n output: dryRun ? { ...options.config.output, format: false, lint: false, postGenerate: [] } : options.config.output,\n }\n\n // Core formats, lints and runs `output.postGenerate` after an error-free build, and reports\n // their failures as coded diagnostics that reach the summary, the json report and the exit code.\n const kubb = createKubb(config, { hooks })\n const result = await kubb.generate()\n\n if (dryRun) {\n await hooks.callHook('kubb:info', { message: 'Dry run: no files were written', info: `${result.files.length} file(s) would be generated` })\n }\n\n await report({\n plugins: Array.from(kubb.driver.plugins.values(), (p) => ({ name: p.name, options: p.options as Record<string, unknown> })),\n filesCreated: result.files.length,\n status: result.success ? 'success' : 'failed',\n })\n\n return result.success\n}\n\ntype GenerateCommandOptions = {\n input?: string\n configPath?: string\n logLevel: string\n watch: boolean\n reporters?: Array<ReporterName>\n dryRun?: boolean\n}\n\nasync function checkForUpdate(hooks: Hookable<KubbHooks>): Promise<void> {\n try {\n const res = await fetch(KUBB_NPM_PACKAGE_URL, { signal: AbortSignal.timeout(UPDATE_CHECK_TIMEOUT_MS) })\n const data = (await res.json()) as { version: string }\n if (data.version && isOutdated({ installed: version, latest: data.version })) {\n await Diagnostics.emit(hooks, Diagnostics.update({ currentVersion: version, latestVersion: data.version }))\n }\n } catch {\n // Ignore network errors\n }\n}\n\n/**\n * Runs the full Kubb generation lifecycle for the given CLI options.\n * Loads configs, sets up the reporters (CLI `--reporter` picks which of `config.reporters` to trigger),\n * checks for a newer version, and calls `generate` for each config entry.\n */\nexport async function run({ input, configPath, logLevel: logLevelKey, watch, reporters: cliReporters, dryRun }: GenerateCommandOptions): Promise<void> {\n const logLevel = logLevelMap[logLevelKey as keyof typeof logLevelMap] ?? logLevelMap.info\n const hooks = new Hookable<KubbHooks>()\n\n // CLI `--reporter` selects which reporters to trigger by name, defaulting to `cli`. `defineConfig`\n // registers the built-in reporters on the config; a config exported without it falls back to them below.\n const requestedNames: Array<ReporterName> = cliReporters?.length ? cliReporters : ['cli']\n\n // The `json` reporter owns stdout, so the command writes nothing of its own around it.\n const quiet = logLevel <= logLevelMap.silent || requestedNames.includes('json')\n\n if (!quiet) {\n logBanner(version)\n logIntro({ title: 'Configuration' })\n }\n\n // Load the config first so `config.reporters` can pick the reporters. A failure here has no\n // reporter installed yet, so fall back to the default `cli` reporter to surface it.\n const configSpinner = createSpinner()\n let configs: Array<Config>\n let resolvedConfigPath: string\n try {\n if (!quiet) configSpinner.start('Loading config')\n\n const loaded = await getConfigs({\n configPath,\n input,\n watch,\n logLevel: logLevelKey as CLIOptions['logLevel'],\n })\n configs = loaded.configs\n resolvedConfigPath = loaded.configPath\n\n if (!quiet) configSpinner.stop(`Loaded ${styleText('dim', path.relative(process.cwd(), resolvedConfigPath))}`)\n } catch (error) {\n if (!quiet) configSpinner.error('Config failed loading')\n\n setupReporters(hooks, { logLevel, reporters: [cliReporter] })\n // A diagnostic thrown while the config file runs, such as invalid extension options, sits in the cause chain.\n const diagnostic = Diagnostics.from(error)\n await (diagnostic.code === Diagnostics.code.unknown ? hooks.callHook('kubb:error', { error: toError(error) }) : Diagnostics.emit(hooks, diagnostic))\n\n if (!quiet) logOutro(styleText('red', '✗ Configuration failed'))\n process.exit(1)\n }\n\n // Without a reporter nothing is printed, not even an error, so a config written without\n // `defineConfig` gets the same built-ins it would have registered.\n const available = configs[0]?.reporters?.length ? configs[0].reporters : [cliReporter, jsonReporter, fileReporter, htmlReporter]\n const reporters = selectReporters(available, requestedNames)\n setupReporters(hooks, { logLevel, reporters })\n\n await hooks.callHook('kubb:lifecycle:start', { version })\n\n // Inside the bootstrap group, so an update notice reads as part of the setup rather than as part\n // of the first config's generation.\n await checkForUpdate(hooks)\n\n if (!quiet) logOutro(`${pluralize(configs.length, 'config')} ready`)\n\n try {\n let anyFailed = false\n for (const config of configs) {\n const effectiveInput = input ?? config.input\n const inputKind = typeof effectiveInput === 'string' ? getInputKind(effectiveInput) : undefined\n const watchPath = inputKind === 'file' || inputKind === 'url' ? (effectiveInput as string) : undefined\n if (watchPath && watch) {\n const watchedPaths = [watchPath]\n // Don't removeAll() between builds, that would also drop logger and lifecycle\n // listeners. Plugin listeners are already disposed by safeBuild's dispose()\n // in its finally block, so re-running generate() on the same hooks emitter is safe.\n const build = async (paths: Array<string>) => {\n const succeeded = await generate({ input, config, hooks, dryRun })\n logStep(styleText('yellow', `Watching for changes in ${paths.join(' and ')}`))\n if (succeeded) {\n logSpacer()\n logTip()\n }\n }\n\n // For a URL input, capture the document before the build: it becomes the watcher's\n // change-detection baseline, so an edit landing before the first poll still rebuilds.\n // When the server is down the baseline stays undefined and the watcher rebuilds on its\n // first successful poll, so recovery with an unchanged document still generates output.\n const initialBody = inputKind === 'url' ? await fetchUrlBody(watchPath) : undefined\n\n // The watchers ignore their startup state, so run the first build here; a failing one keeps watching so the user can fix the input.\n try {\n await build(watchedPaths)\n } catch (buildError) {\n await hooks.callHook('kubb:error', { error: toError(buildError) })\n }\n\n if (inputKind === 'url') {\n startUrlWatcher(watchPath, build, { log: { info: logInfo, error: logError }, initialBody })\n } else {\n await startWatcher(watchedPaths, build, { info: logInfo, error: logError })\n }\n } else {\n try {\n const succeeded = await generate({ input, config, hooks, dryRun })\n if (!succeeded) anyFailed = true\n } catch (configError) {\n await hooks.callHook('kubb:error', { error: toError(configError) })\n anyFailed = true\n }\n }\n }\n\n await hooks.callHook('kubb:lifecycle:end')\n\n // Watch mode prints a tip after each successful build. Regular generate commands need to\n // print one explicitly after the lifecycle group has closed so it stays outside the group.\n if (!quiet && !watch && !anyFailed) {\n logTip()\n }\n\n if (anyFailed) {\n process.exit(1)\n }\n } catch (error) {\n await hooks.callHook('kubb:error', { error: toError(error) })\n process.exit(1)\n }\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-CPE0t6oh.cjs");
2
- const require_Telemetry = require("./Telemetry-D3X0YeTq.cjs");
3
- const require_output = require("./output-BgIxkmno.cjs");
4
- const require_registry = require("./registry-BDHW1pwJ.cjs");
5
- const require_config = require("./config-DTaFUofU.cjs");
2
+ const require_Telemetry = require("./Telemetry-BfdvvZus.cjs");
3
+ const require_output = require("./output-DLrxGtuN.cjs");
4
+ const require_registry = require("./registry-x-_nbYR6.cjs");
5
+ const require_config = require("./config-CcqzzfB7.cjs");
6
6
  let node_util = require("node:util");
7
7
  let node_process = require("node:process");
8
8
  node_process = require_rolldown_runtime.__toESM(node_process, 1);
@@ -336,4 +336,4 @@ async function run({ input, configPath, logLevel: logLevelKey, watch, reporters:
336
336
  //#endregion
337
337
  exports.run = run;
338
338
 
339
- //# sourceMappingURL=run-dKhoUR2-.cjs.map
339
+ //# sourceMappingURL=run-CUyhuGlK.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-dKhoUR2-.cjs","names":["toError","styleText","trackRun","process","memoryStorage","createKubb","isOutdated","version","Diagnostics","logLevelMap","Hookable","createSpinner","getConfigs","styleText","path","cliReporter","toError","jsonReporter","fileReporter","htmlReporter","selectReporters","pluralize","getInputKind","logInfo","logError"],"sources":["../src/runners/generate/utils.ts","../src/runners/generate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\n\n/** Glob pattern for paths the file watcher ignores. */\nconst WATCHER_IGNORED_PATHS = '**/{.git,node_modules}/**' as const\n\n/**\n * Quiet window in milliseconds that collapses a burst of watcher events (an editor save emits several) into one rebuild.\n * It outlasts chokidar's 100 ms atomic-save window, which holds back the event of a write-then-rename save.\n */\nconst WATCHER_DEBOUNCE_MS = 250\n\n/** Interval in milliseconds between polls of a remote `input` URL in watch mode, which emits no filesystem events. */\nconst URL_WATCHER_INTERVAL_MS = 2_000\n\n/** Upper bound in milliseconds for one URL watcher request, headers and body read, so a hung server never stalls polling. */\nconst URL_WATCHER_TIMEOUT_MS = 10_000\n\ntype SerialRunnerOptions = {\n /**\n * The async work to serialize.\n */\n run(): Promise<void>\n /**\n * Receives errors thrown by `run`, so a failure never rejects the returned trigger.\n */\n onError(error: Error): void\n}\n\n/**\n * Wraps `run` so invocations never overlap: a trigger that lands while a run is in flight\n * marks it dirty and runs once more after it finishes, no matter how many triggers arrived.\n * Useful for event-driven reruns (a file watcher, a queue drain) where bursts should\n * coalesce into a single trailing run.\n *\n * @example\n * ```ts\n * const rebuild = createSerialRunner({\n * run: () => build(),\n * onError: (error) => log.error(error.message),\n * })\n * watcher.on('change', () => void rebuild())\n * ```\n */\nexport function createSerialRunner({ run, onError }: SerialRunnerOptions): () => Promise<void> {\n let running = false\n let dirty = false\n\n return async (): Promise<void> => {\n if (running) {\n dirty = true\n return\n }\n running = true\n do {\n dirty = false\n try {\n await run()\n } catch (error) {\n onError(toError(error))\n }\n } while (dirty)\n running = false\n }\n}\n\ntype WatcherLog = {\n info: (message: string) => void\n error: (message: string) => void\n}\n\n/**\n * Starts a file watcher on the given paths and calls `cb` on any change.\n * Ignores `.git` and `node_modules` directories. Event bursts (an editor save emits several)\n * are debounced into one build, and builds never overlap: changes during a build queue exactly\n * one rebuild. Resolves to a function that stops watching.\n */\nexport async function startWatcher(\n path: Array<string>,\n cb: (path: Array<string>) => Promise<void>,\n log: WatcherLog = { info: console.log, error: console.log },\n): Promise<() => Promise<void>> {\n const { watch } = await import('chokidar')\n // `ignoreInitial` skips the `add` events chokidar fires for existing files at startup, which\n // would otherwise rebuild right after the initial run.\n const watcher = watch(path, { ignorePermissionErrors: true, ignored: WATCHER_IGNORED_PATHS, ignoreInitial: true })\n\n process.once('SIGINT', () => {\n watcher.close()\n })\n process.once('SIGTERM', () => {\n watcher.close()\n })\n\n // Bursts never overlap builds on the shared hooks emitter: a change during a build\n // queues exactly one rerun.\n const runBuild = createSerialRunner({\n run: () => cb(path),\n onError: () => log.error(styleText('red', 'Watcher failed')),\n })\n let debounceTimer: ReturnType<typeof setTimeout> | null = null\n\n watcher.on('all', (type, file) => {\n log.info(styleText('yellow', styleText('bold', `Change detected: ${type} ${file}`)))\n if (debounceTimer) clearTimeout(debounceTimer)\n debounceTimer = setTimeout(() => {\n debounceTimer = null\n void runBuild()\n }, WATCHER_DEBOUNCE_MS)\n })\n\n return async () => {\n if (debounceTimer) clearTimeout(debounceTimer)\n await watcher.close()\n }\n}\n\n/**\n * Fetches the body of a remote spec URL, `undefined` when the server does not answer with a\n * readable 2xx body before `signal` aborts. The caller seeds `startUrlWatcher` with the result, so\n * the watcher compares polls against the content the initial build ran on.\n */\nexport async function fetchUrlBody(url: string, signal: AbortSignal = AbortSignal.timeout(URL_WATCHER_TIMEOUT_MS)): Promise<string | undefined> {\n try {\n const response = await fetch(url, { signal })\n if (!response.ok) return undefined\n return await response.text()\n } catch {\n return undefined\n }\n}\n\ntype UrlWatcherOptions = {\n /**\n * Sink for watcher messages, `console.log` by default.\n */\n log?: WatcherLog\n /**\n * Time in milliseconds between polls.\n */\n intervalMs?: number\n /**\n * Upper bound in milliseconds for one poll request, covering headers and body read.\n */\n timeoutMs?: number\n /**\n * Body the initial build ran against, the baseline for change detection. When omitted (the\n * server was unreachable at startup), the first successful poll rebuilds so the output catches\n * up as soon as the server responds.\n */\n initialBody?: string\n}\n\n/**\n * Polls a remote spec URL and calls `cb` whenever the response body changes. A remote document\n * emits no filesystem events, so this is the URL counterpart of `startWatcher`.\n *\n * `initialBody` seeds the change detection, so an edit landing between the initial build and the\n * first poll still rebuilds. An unreachable server (the API restarting between saves) is reported\n * once per outage and polling continues; after it recovers, a rebuild happens only when the body\n * actually differs from the last one seen, so a plain restart with an unchanged spec stays quiet.\n * Each request is aborted after `timeoutMs`, so a hung response delays at most one poll.\n *\n * Returns a function that stops polling and aborts the in-flight request, so callers (and tests)\n * can shut the watcher down without signaling the process.\n */\nexport function startUrlWatcher(url: string, cb: (path: Array<string>) => Promise<void>, options: UrlWatcherOptions = {}): () => void {\n const { log = { info: console.log, error: console.log }, intervalMs = URL_WATCHER_INTERVAL_MS, timeoutMs = URL_WATCHER_TIMEOUT_MS, initialBody } = options\n\n let lastBody = initialBody\n let offline = false\n let timer: ReturnType<typeof setTimeout> | null = null\n let controller: AbortController | null = null\n let stopped = false\n\n const stop = () => {\n stopped = true\n if (timer) clearTimeout(timer)\n controller?.abort()\n }\n process.once('SIGINT', stop)\n process.once('SIGTERM', stop)\n\n // Builds never overlap on the shared hooks emitter: a change during a build queues exactly\n // one rerun.\n const runBuild = createSerialRunner({\n run: () => cb([url]),\n onError: () => log.error(styleText('red', 'Watcher failed')),\n })\n\n const schedule = () => {\n if (!stopped) {\n timer = setTimeout(() => void poll(), intervalMs)\n }\n }\n\n const poll = async (): Promise<void> => {\n controller = new AbortController()\n // The signal also aborts the body read, so a response that stalls mid-stream still times out.\n const body = await fetchUrlBody(url, AbortSignal.any([controller.signal, AbortSignal.timeout(timeoutMs)]))\n\n if (body === undefined) {\n // `lastBody` survives the outage so recovery rebuilds only on real content changes.\n if (!offline && !stopped) {\n offline = true\n log.error(styleText('red', `Cannot reach ${url}, polling until it responds again`))\n }\n schedule()\n return\n }\n\n if (offline) {\n offline = false\n log.info(styleText('yellow', `${url} is reachable again`))\n }\n const changed = lastBody !== undefined && body !== lastBody\n if (changed) {\n log.info(styleText('yellow', styleText('bold', `Change detected: ${url}`)))\n }\n if (changed || lastBody === undefined) {\n void runBuild()\n }\n lastBody = body\n schedule()\n }\n\n void poll()\n\n return stop\n}\n","import path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport { formatters, linters, toError } from '@internals/utils'\nimport {\n Hookable,\n type CLIOptions,\n cliReporter,\n type Config,\n createKubb,\n Diagnostics,\n fileReporter,\n getInputKind,\n htmlReporter,\n jsonReporter,\n type KubbHooks,\n logLevel as logLevelMap,\n memoryStorage,\n type ReporterName,\n} from '@kubb/core'\nimport { version } from '../../../package.json'\nimport { trackRun } from '../../Telemetry.ts'\nimport { pluralize } from '../../loggers/createLogger.ts'\nimport setupReporters, { selectReporters } from '../../loggers/reporters.ts'\nimport { createSpinner, logBanner, logError, logInfo, logIntro, logOutro, logSpacer, logStep, logTip } from '../../loggers/output.ts'\nimport { getConfigs } from '../../config.ts'\nimport { isOutdated } from '../../utils/registry.ts'\nimport { fetchUrlBody, startUrlWatcher, startWatcher } from './utils.ts'\n\n/** NPM registry endpoint used to check for @kubb/cli updates. */\nconst KUBB_NPM_PACKAGE_URL = 'https://registry.npmjs.org/@kubb/cli/latest' as const\n\n/** Upper bound in milliseconds for the npm update check, so a slow registry never stalls a run. */\nconst UPDATE_CHECK_TIMEOUT_MS = 3_000\n\n/** The formatter names from `Config['output'].format`, without `'auto'` (detection, not a tool) and `false` (skip). */\ntype FormatterName = Exclude<NonNullable<Config['output']['format']>, 'auto' | false>\ntype LinterName = Exclude<NonNullable<Config['output']['lint']>, 'auto' | false>\n\n// Pinned here, not in `@internals/utils` (which must not import `@kubb/core`): a tool added to the union without a descriptor fails to compile.\nformatters satisfies Record<FormatterName, unknown>\nlinters satisfies Record<LinterName, unknown>\n\ntype GenerateProps = {\n input?: string\n config: Config\n hooks: Hookable<KubbHooks>\n /**\n * When `true`, generates in memory instead of writing to disk, and skips formatting, linting,\n * and post-generate commands.\n */\n dryRun?: boolean\n}\n\nasync function generate(options: GenerateProps): Promise<boolean> {\n const { input, hooks, dryRun = false } = options\n\n const report = trackRun({ command: 'generate', hrStart: process.hrtime() })\n\n const config: Config = {\n ...options.config,\n input: input ?? options.config.input,\n // Dry-run never touches disk, regardless of the config's own storage driver.\n storage: dryRun ? memoryStorage() : options.config.storage,\n // Also keeps core's `hasOutputPasses` false, so dry-run skips the output manifest write too.\n output: dryRun ? { ...options.config.output, format: false, lint: false, postGenerate: [] } : options.config.output,\n }\n\n // Core formats, lints and runs `output.postGenerate` after an error-free build, and reports\n // their failures as coded diagnostics that reach the summary, the json report and the exit code.\n const kubb = createKubb(config, { hooks })\n const result = await kubb.generate()\n\n if (dryRun) {\n await hooks.callHook('kubb:info', { message: 'Dry run: no files were written', info: `${result.files.length} file(s) would be generated` })\n }\n\n await report({\n plugins: Array.from(kubb.driver.plugins.values(), (p) => ({ name: p.name, options: p.options as Record<string, unknown> })),\n filesCreated: result.files.length,\n status: result.success ? 'success' : 'failed',\n })\n\n return result.success\n}\n\ntype GenerateCommandOptions = {\n input?: string\n configPath?: string\n logLevel: string\n watch: boolean\n reporters?: Array<ReporterName>\n dryRun?: boolean\n}\n\nasync function checkForUpdate(hooks: Hookable<KubbHooks>): Promise<void> {\n try {\n const res = await fetch(KUBB_NPM_PACKAGE_URL, { signal: AbortSignal.timeout(UPDATE_CHECK_TIMEOUT_MS) })\n const data = (await res.json()) as { version: string }\n if (data.version && isOutdated({ installed: version, latest: data.version })) {\n await Diagnostics.emit(hooks, Diagnostics.update({ currentVersion: version, latestVersion: data.version }))\n }\n } catch {\n // Ignore network errors\n }\n}\n\n/**\n * Runs the full Kubb generation lifecycle for the given CLI options.\n * Loads configs, sets up the reporters (CLI `--reporter` picks which of `config.reporters` to trigger),\n * checks for a newer version, and calls `generate` for each config entry.\n */\nexport async function run({ input, configPath, logLevel: logLevelKey, watch, reporters: cliReporters, dryRun }: GenerateCommandOptions): Promise<void> {\n const logLevel = logLevelMap[logLevelKey as keyof typeof logLevelMap] ?? logLevelMap.info\n const hooks = new Hookable<KubbHooks>()\n\n // CLI `--reporter` selects which reporters to trigger by name, defaulting to `cli`. `defineConfig`\n // registers the built-in reporters on the config; a config exported without it falls back to them below.\n const requestedNames: Array<ReporterName> = cliReporters?.length ? cliReporters : ['cli']\n\n // The `json` reporter owns stdout, so the command writes nothing of its own around it.\n const quiet = logLevel <= logLevelMap.silent || requestedNames.includes('json')\n\n if (!quiet) {\n logBanner(version)\n logIntro({ title: 'Configuration' })\n }\n\n // Load the config first so `config.reporters` can pick the reporters. A failure here has no\n // reporter installed yet, so fall back to the default `cli` reporter to surface it.\n const configSpinner = createSpinner()\n let configs: Array<Config>\n let resolvedConfigPath: string\n try {\n if (!quiet) configSpinner.start('Loading config')\n\n const loaded = await getConfigs({\n configPath,\n input,\n watch,\n logLevel: logLevelKey as CLIOptions['logLevel'],\n })\n configs = loaded.configs\n resolvedConfigPath = loaded.configPath\n\n if (!quiet) configSpinner.stop(`Loaded ${styleText('dim', path.relative(process.cwd(), resolvedConfigPath))}`)\n } catch (error) {\n if (!quiet) configSpinner.error('Config failed loading')\n\n setupReporters(hooks, { logLevel, reporters: [cliReporter] })\n // A diagnostic thrown while the config file runs, such as invalid extension options, sits in the cause chain.\n const diagnostic = Diagnostics.from(error)\n await (diagnostic.code === Diagnostics.code.unknown ? hooks.callHook('kubb:error', { error: toError(error) }) : Diagnostics.emit(hooks, diagnostic))\n\n if (!quiet) logOutro(styleText('red', '✗ Configuration failed'))\n process.exit(1)\n }\n\n // Without a reporter nothing is printed, not even an error, so a config written without\n // `defineConfig` gets the same built-ins it would have registered.\n const available = configs[0]?.reporters?.length ? configs[0].reporters : [cliReporter, jsonReporter, fileReporter, htmlReporter]\n const reporters = selectReporters(available, requestedNames)\n setupReporters(hooks, { logLevel, reporters })\n\n await hooks.callHook('kubb:lifecycle:start', { version })\n\n // Inside the bootstrap group, so an update notice reads as part of the setup rather than as part\n // of the first config's generation.\n await checkForUpdate(hooks)\n\n if (!quiet) logOutro(`${pluralize(configs.length, 'config')} ready`)\n\n try {\n let anyFailed = false\n for (const config of configs) {\n const effectiveInput = input ?? config.input\n const inputKind = typeof effectiveInput === 'string' ? getInputKind(effectiveInput) : undefined\n const watchPath = inputKind === 'file' || inputKind === 'url' ? (effectiveInput as string) : undefined\n if (watchPath && watch) {\n const watchedPaths = [watchPath]\n // Don't removeAll() between builds, that would also drop logger and lifecycle\n // listeners. Plugin listeners are already disposed by safeBuild's dispose()\n // in its finally block, so re-running generate() on the same hooks emitter is safe.\n const build = async (paths: Array<string>) => {\n const succeeded = await generate({ input, config, hooks, dryRun })\n logStep(styleText('yellow', `Watching for changes in ${paths.join(' and ')}`))\n if (succeeded) {\n logSpacer()\n logTip()\n }\n }\n\n // For a URL input, capture the document before the build: it becomes the watcher's\n // change-detection baseline, so an edit landing before the first poll still rebuilds.\n // When the server is down the baseline stays undefined and the watcher rebuilds on its\n // first successful poll, so recovery with an unchanged document still generates output.\n const initialBody = inputKind === 'url' ? await fetchUrlBody(watchPath) : undefined\n\n // The watchers ignore their startup state, so run the first build here; a failing one keeps watching so the user can fix the input.\n try {\n await build(watchedPaths)\n } catch (buildError) {\n await hooks.callHook('kubb:error', { error: toError(buildError) })\n }\n\n if (inputKind === 'url') {\n startUrlWatcher(watchPath, build, { log: { info: logInfo, error: logError }, initialBody })\n } else {\n await startWatcher(watchedPaths, build, { info: logInfo, error: logError })\n }\n } else {\n try {\n const succeeded = await generate({ input, config, hooks, dryRun })\n if (!succeeded) anyFailed = true\n } catch (configError) {\n await hooks.callHook('kubb:error', { error: toError(configError) })\n anyFailed = true\n }\n }\n }\n\n await hooks.callHook('kubb:lifecycle:end')\n\n // Watch mode prints a tip after each successful build. Regular generate commands need to\n // print one explicitly after the lifecycle group has closed so it stays outside the group.\n if (!quiet && !watch && !anyFailed) {\n logTip()\n }\n\n if (anyFailed) {\n process.exit(1)\n }\n } catch (error) {\n await hooks.callHook('kubb:error', { error: toError(error) })\n process.exit(1)\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"run-CUyhuGlK.cjs","names":["toError","styleText","trackRun","process","memoryStorage","createKubb","isOutdated","version","Diagnostics","logLevelMap","Hookable","createSpinner","getConfigs","styleText","path","cliReporter","toError","jsonReporter","fileReporter","htmlReporter","selectReporters","pluralize","getInputKind","logInfo","logError"],"sources":["../src/runners/generate/utils.ts","../src/runners/generate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\n\n/** Glob pattern for paths the file watcher ignores. */\nconst WATCHER_IGNORED_PATHS = '**/{.git,node_modules}/**' as const\n\n/**\n * Quiet window in milliseconds that collapses a burst of watcher events (an editor save emits several) into one rebuild.\n * It outlasts chokidar's 100 ms atomic-save window, which holds back the event of a write-then-rename save.\n */\nconst WATCHER_DEBOUNCE_MS = 250\n\n/** Interval in milliseconds between polls of a remote `input` URL in watch mode, which emits no filesystem events. */\nconst URL_WATCHER_INTERVAL_MS = 2_000\n\n/** Upper bound in milliseconds for one URL watcher request, headers and body read, so a hung server never stalls polling. */\nconst URL_WATCHER_TIMEOUT_MS = 10_000\n\ntype SerialRunnerOptions = {\n /**\n * The async work to serialize.\n */\n run(): Promise<void>\n /**\n * Receives errors thrown by `run`, so a failure never rejects the returned trigger.\n */\n onError(error: Error): void\n}\n\n/**\n * Wraps `run` so invocations never overlap: a trigger that lands while a run is in flight\n * marks it dirty and runs once more after it finishes, no matter how many triggers arrived.\n * Useful for event-driven reruns (a file watcher, a queue drain) where bursts should\n * coalesce into a single trailing run.\n *\n * @example\n * ```ts\n * const rebuild = createSerialRunner({\n * run: () => build(),\n * onError: (error) => log.error(error.message),\n * })\n * watcher.on('change', () => void rebuild())\n * ```\n */\nexport function createSerialRunner({ run, onError }: SerialRunnerOptions): () => Promise<void> {\n let running = false\n let dirty = false\n\n return async (): Promise<void> => {\n if (running) {\n dirty = true\n return\n }\n running = true\n do {\n dirty = false\n try {\n await run()\n } catch (error) {\n onError(toError(error))\n }\n } while (dirty)\n running = false\n }\n}\n\ntype WatcherLog = {\n info: (message: string) => void\n error: (message: string) => void\n}\n\n/**\n * Starts a file watcher on the given paths and calls `cb` on any change.\n * Ignores `.git` and `node_modules` directories. Event bursts (an editor save emits several)\n * are debounced into one build, and builds never overlap: changes during a build queue exactly\n * one rebuild. Resolves to a function that stops watching.\n */\nexport async function startWatcher(\n path: Array<string>,\n cb: (path: Array<string>) => Promise<void>,\n log: WatcherLog = { info: console.log, error: console.log },\n): Promise<() => Promise<void>> {\n const { watch } = await import('chokidar')\n // `ignoreInitial` skips the `add` events chokidar fires for existing files at startup, which\n // would otherwise rebuild right after the initial run.\n const watcher = watch(path, { ignorePermissionErrors: true, ignored: WATCHER_IGNORED_PATHS, ignoreInitial: true })\n\n process.once('SIGINT', () => {\n watcher.close()\n })\n process.once('SIGTERM', () => {\n watcher.close()\n })\n\n // Bursts never overlap builds on the shared hooks emitter: a change during a build\n // queues exactly one rerun.\n const runBuild = createSerialRunner({\n run: () => cb(path),\n onError: () => log.error(styleText('red', 'Watcher failed')),\n })\n let debounceTimer: ReturnType<typeof setTimeout> | null = null\n\n watcher.on('all', (type, file) => {\n log.info(styleText('yellow', styleText('bold', `Change detected: ${type} ${file}`)))\n if (debounceTimer) clearTimeout(debounceTimer)\n debounceTimer = setTimeout(() => {\n debounceTimer = null\n void runBuild()\n }, WATCHER_DEBOUNCE_MS)\n })\n\n return async () => {\n if (debounceTimer) clearTimeout(debounceTimer)\n await watcher.close()\n }\n}\n\n/**\n * Fetches the body of a remote spec URL, `undefined` when the server does not answer with a\n * readable 2xx body before `signal` aborts. The caller seeds `startUrlWatcher` with the result, so\n * the watcher compares polls against the content the initial build ran on.\n */\nexport async function fetchUrlBody(url: string, signal: AbortSignal = AbortSignal.timeout(URL_WATCHER_TIMEOUT_MS)): Promise<string | undefined> {\n try {\n const response = await fetch(url, { signal })\n if (!response.ok) return undefined\n return await response.text()\n } catch {\n return undefined\n }\n}\n\ntype UrlWatcherOptions = {\n /**\n * Sink for watcher messages, `console.log` by default.\n */\n log?: WatcherLog\n /**\n * Time in milliseconds between polls.\n */\n intervalMs?: number\n /**\n * Upper bound in milliseconds for one poll request, covering headers and body read.\n */\n timeoutMs?: number\n /**\n * Body the initial build ran against, the baseline for change detection. When omitted (the\n * server was unreachable at startup), the first successful poll rebuilds so the output catches\n * up as soon as the server responds.\n */\n initialBody?: string\n}\n\n/**\n * Polls a remote spec URL and calls `cb` whenever the response body changes. A remote document\n * emits no filesystem events, so this is the URL counterpart of `startWatcher`.\n *\n * `initialBody` seeds the change detection, so an edit landing between the initial build and the\n * first poll still rebuilds. An unreachable server (the API restarting between saves) is reported\n * once per outage and polling continues; after it recovers, a rebuild happens only when the body\n * actually differs from the last one seen, so a plain restart with an unchanged spec stays quiet.\n * Each request is aborted after `timeoutMs`, so a hung response delays at most one poll.\n *\n * Returns a function that stops polling and aborts the in-flight request, so callers (and tests)\n * can shut the watcher down without signaling the process.\n */\nexport function startUrlWatcher(url: string, cb: (path: Array<string>) => Promise<void>, options: UrlWatcherOptions = {}): () => void {\n const { log = { info: console.log, error: console.log }, intervalMs = URL_WATCHER_INTERVAL_MS, timeoutMs = URL_WATCHER_TIMEOUT_MS, initialBody } = options\n\n let lastBody = initialBody\n let offline = false\n let timer: ReturnType<typeof setTimeout> | null = null\n let controller: AbortController | null = null\n let stopped = false\n\n const stop = () => {\n stopped = true\n if (timer) clearTimeout(timer)\n controller?.abort()\n }\n process.once('SIGINT', stop)\n process.once('SIGTERM', stop)\n\n // Builds never overlap on the shared hooks emitter: a change during a build queues exactly\n // one rerun.\n const runBuild = createSerialRunner({\n run: () => cb([url]),\n onError: () => log.error(styleText('red', 'Watcher failed')),\n })\n\n const schedule = () => {\n if (!stopped) {\n timer = setTimeout(() => void poll(), intervalMs)\n }\n }\n\n const poll = async (): Promise<void> => {\n controller = new AbortController()\n // The signal also aborts the body read, so a response that stalls mid-stream still times out.\n const body = await fetchUrlBody(url, AbortSignal.any([controller.signal, AbortSignal.timeout(timeoutMs)]))\n\n if (body === undefined) {\n // `lastBody` survives the outage so recovery rebuilds only on real content changes.\n if (!offline && !stopped) {\n offline = true\n log.error(styleText('red', `Cannot reach ${url}, polling until it responds again`))\n }\n schedule()\n return\n }\n\n if (offline) {\n offline = false\n log.info(styleText('yellow', `${url} is reachable again`))\n }\n const changed = lastBody !== undefined && body !== lastBody\n if (changed) {\n log.info(styleText('yellow', styleText('bold', `Change detected: ${url}`)))\n }\n if (changed || lastBody === undefined) {\n void runBuild()\n }\n lastBody = body\n schedule()\n }\n\n void poll()\n\n return stop\n}\n","import path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport { formatters, linters, toError } from '@internals/utils'\nimport {\n Hookable,\n type CLIOptions,\n cliReporter,\n type Config,\n createKubb,\n Diagnostics,\n fileReporter,\n getInputKind,\n htmlReporter,\n jsonReporter,\n type KubbHooks,\n logLevel as logLevelMap,\n memoryStorage,\n type ReporterName,\n} from '@kubb/core'\nimport { version } from '../../../package.json'\nimport { trackRun } from '../../Telemetry.ts'\nimport { pluralize } from '../../loggers/createLogger.ts'\nimport setupReporters, { selectReporters } from '../../loggers/reporters.ts'\nimport { createSpinner, logBanner, logError, logInfo, logIntro, logOutro, logSpacer, logStep, logTip } from '../../loggers/output.ts'\nimport { getConfigs } from '../../config.ts'\nimport { isOutdated } from '../../utils/registry.ts'\nimport { fetchUrlBody, startUrlWatcher, startWatcher } from './utils.ts'\n\n/** NPM registry endpoint used to check for @kubb/cli updates. */\nconst KUBB_NPM_PACKAGE_URL = 'https://registry.npmjs.org/@kubb/cli/latest' as const\n\n/** Upper bound in milliseconds for the npm update check, so a slow registry never stalls a run. */\nconst UPDATE_CHECK_TIMEOUT_MS = 3_000\n\n/** The formatter names from `Config['output'].format`, without `'auto'` (detection, not a tool) and `false` (skip). */\ntype FormatterName = Exclude<NonNullable<Config['output']['format']>, 'auto' | false>\ntype LinterName = Exclude<NonNullable<Config['output']['lint']>, 'auto' | false>\n\n// Pinned here, not in `@internals/utils` (which must not import `@kubb/core`): a tool added to the union without a descriptor fails to compile.\nformatters satisfies Record<FormatterName, unknown>\nlinters satisfies Record<LinterName, unknown>\n\ntype GenerateProps = {\n input?: string\n config: Config\n hooks: Hookable<KubbHooks>\n /**\n * When `true`, generates in memory instead of writing to disk, and skips formatting, linting,\n * and post-generate commands.\n */\n dryRun?: boolean\n}\n\nasync function generate(options: GenerateProps): Promise<boolean> {\n const { input, hooks, dryRun = false } = options\n\n const report = trackRun({ command: 'generate', hrStart: process.hrtime() })\n\n const config: Config = {\n ...options.config,\n input: input ?? options.config.input,\n // Dry-run never touches disk, regardless of the config's own storage driver.\n storage: dryRun ? memoryStorage() : options.config.storage,\n // Also keeps core's `hasOutputPasses` false, so dry-run skips the output manifest write too.\n output: dryRun ? { ...options.config.output, format: false, lint: false, postGenerate: [] } : options.config.output,\n }\n\n // Core formats, lints and runs `output.postGenerate` after an error-free build, and reports\n // their failures as coded diagnostics that reach the summary, the json report and the exit code.\n const kubb = createKubb(config, { hooks })\n const result = await kubb.generate()\n\n if (dryRun) {\n await hooks.callHook('kubb:info', { message: 'Dry run: no files were written', info: `${result.files.length} file(s) would be generated` })\n }\n\n await report({\n plugins: Array.from(kubb.driver.plugins.values(), (p) => ({ name: p.name, options: p.options as Record<string, unknown> })),\n filesCreated: result.files.length,\n status: result.success ? 'success' : 'failed',\n })\n\n return result.success\n}\n\ntype GenerateCommandOptions = {\n input?: string\n configPath?: string\n logLevel: string\n watch: boolean\n reporters?: Array<ReporterName>\n dryRun?: boolean\n}\n\nasync function checkForUpdate(hooks: Hookable<KubbHooks>): Promise<void> {\n try {\n const res = await fetch(KUBB_NPM_PACKAGE_URL, { signal: AbortSignal.timeout(UPDATE_CHECK_TIMEOUT_MS) })\n const data = (await res.json()) as { version: string }\n if (data.version && isOutdated({ installed: version, latest: data.version })) {\n await Diagnostics.emit(hooks, Diagnostics.update({ currentVersion: version, latestVersion: data.version }))\n }\n } catch {\n // Ignore network errors\n }\n}\n\n/**\n * Runs the full Kubb generation lifecycle for the given CLI options.\n * Loads configs, sets up the reporters (CLI `--reporter` picks which of `config.reporters` to trigger),\n * checks for a newer version, and calls `generate` for each config entry.\n */\nexport async function run({ input, configPath, logLevel: logLevelKey, watch, reporters: cliReporters, dryRun }: GenerateCommandOptions): Promise<void> {\n const logLevel = logLevelMap[logLevelKey as keyof typeof logLevelMap] ?? logLevelMap.info\n const hooks = new Hookable<KubbHooks>()\n\n // CLI `--reporter` selects which reporters to trigger by name, defaulting to `cli`. `defineConfig`\n // registers the built-in reporters on the config; a config exported without it falls back to them below.\n const requestedNames: Array<ReporterName> = cliReporters?.length ? cliReporters : ['cli']\n\n // The `json` reporter owns stdout, so the command writes nothing of its own around it.\n const quiet = logLevel <= logLevelMap.silent || requestedNames.includes('json')\n\n if (!quiet) {\n logBanner(version)\n logIntro({ title: 'Configuration' })\n }\n\n // Load the config first so `config.reporters` can pick the reporters. A failure here has no\n // reporter installed yet, so fall back to the default `cli` reporter to surface it.\n const configSpinner = createSpinner()\n let configs: Array<Config>\n let resolvedConfigPath: string\n try {\n if (!quiet) configSpinner.start('Loading config')\n\n const loaded = await getConfigs({\n configPath,\n input,\n watch,\n logLevel: logLevelKey as CLIOptions['logLevel'],\n })\n configs = loaded.configs\n resolvedConfigPath = loaded.configPath\n\n if (!quiet) configSpinner.stop(`Loaded ${styleText('dim', path.relative(process.cwd(), resolvedConfigPath))}`)\n } catch (error) {\n if (!quiet) configSpinner.error('Config failed loading')\n\n setupReporters(hooks, { logLevel, reporters: [cliReporter] })\n // A diagnostic thrown while the config file runs, such as invalid extension options, sits in the cause chain.\n const diagnostic = Diagnostics.from(error)\n await (diagnostic.code === Diagnostics.code.unknown ? hooks.callHook('kubb:error', { error: toError(error) }) : Diagnostics.emit(hooks, diagnostic))\n\n if (!quiet) logOutro(styleText('red', '✗ Configuration failed'))\n process.exit(1)\n }\n\n // Without a reporter nothing is printed, not even an error, so a config written without\n // `defineConfig` gets the same built-ins it would have registered.\n const available = configs[0]?.reporters?.length ? configs[0].reporters : [cliReporter, jsonReporter, fileReporter, htmlReporter]\n const reporters = selectReporters(available, requestedNames)\n setupReporters(hooks, { logLevel, reporters })\n\n await hooks.callHook('kubb:lifecycle:start', { version })\n\n // Inside the bootstrap group, so an update notice reads as part of the setup rather than as part\n // of the first config's generation.\n await checkForUpdate(hooks)\n\n if (!quiet) logOutro(`${pluralize(configs.length, 'config')} ready`)\n\n try {\n let anyFailed = false\n for (const config of configs) {\n const effectiveInput = input ?? config.input\n const inputKind = typeof effectiveInput === 'string' ? getInputKind(effectiveInput) : undefined\n const watchPath = inputKind === 'file' || inputKind === 'url' ? (effectiveInput as string) : undefined\n if (watchPath && watch) {\n const watchedPaths = [watchPath]\n // Don't removeAll() between builds, that would also drop logger and lifecycle\n // listeners. Plugin listeners are already disposed by safeBuild's dispose()\n // in its finally block, so re-running generate() on the same hooks emitter is safe.\n const build = async (paths: Array<string>) => {\n const succeeded = await generate({ input, config, hooks, dryRun })\n logStep(styleText('yellow', `Watching for changes in ${paths.join(' and ')}`))\n if (succeeded) {\n logSpacer()\n logTip()\n }\n }\n\n // For a URL input, capture the document before the build: it becomes the watcher's\n // change-detection baseline, so an edit landing before the first poll still rebuilds.\n // When the server is down the baseline stays undefined and the watcher rebuilds on its\n // first successful poll, so recovery with an unchanged document still generates output.\n const initialBody = inputKind === 'url' ? await fetchUrlBody(watchPath) : undefined\n\n // The watchers ignore their startup state, so run the first build here; a failing one keeps watching so the user can fix the input.\n try {\n await build(watchedPaths)\n } catch (buildError) {\n await hooks.callHook('kubb:error', { error: toError(buildError) })\n }\n\n if (inputKind === 'url') {\n startUrlWatcher(watchPath, build, { log: { info: logInfo, error: logError }, initialBody })\n } else {\n await startWatcher(watchedPaths, build, { info: logInfo, error: logError })\n }\n } else {\n try {\n const succeeded = await generate({ input, config, hooks, dryRun })\n if (!succeeded) anyFailed = true\n } catch (configError) {\n await hooks.callHook('kubb:error', { error: toError(configError) })\n anyFailed = true\n }\n }\n }\n\n await hooks.callHook('kubb:lifecycle:end')\n\n // Watch mode prints a tip after each successful build. Regular generate commands need to\n // print one explicitly after the lifecycle group has closed so it stays outside the group.\n if (!quiet && !watch && !anyFailed) {\n logTip()\n }\n\n if (anyFailed) {\n process.exit(1)\n }\n } catch (error) {\n await hooks.callHook('kubb:error', { error: toError(error) })\n process.exit(1)\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- export { t as connect, n as formatPermissionRows, i as login, s as runStudio } from "./run-Ct5_WdiW.js";
1
+ export { t as connect, n as formatPermissionRows, i as login, s as runStudio } from "./run-DTz7gAk1.js";
@@ -1,5 +1,5 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { l as toError, n as trackRun } from "./Telemetry-DZEM4fEd.js";
2
+ import { l as toError, n as trackRun } from "./Telemetry-Bf6lUdai.js";
3
3
  import { styleText } from "node:util";
4
4
  import process from "node:process";
5
5
  //#region src/runners/mcp/run.ts
@@ -15,8 +15,10 @@ async function run() {
15
15
  try {
16
16
  console.error(styleText("cyan", "⏳ Starting MCP server..."));
17
17
  console.warn(styleText("yellow", "This feature is still under development, use with caution"));
18
- await startMcpServer();
19
- await report({ status: "success" });
18
+ startMcpServer().on("initialize", ({ clientInfo }) => void report({
19
+ status: "success",
20
+ mcpClient: clientInfo.name
21
+ }), { once: true });
20
22
  } catch (error) {
21
23
  await report({ status: "failed" });
22
24
  console.error(toError(error).message);
@@ -26,4 +28,4 @@ async function run() {
26
28
  //#endregion
27
29
  export { run };
28
30
 
29
- //# sourceMappingURL=run-Do-yyhzu.js.map
31
+ //# sourceMappingURL=run-Cu3pmezx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-Cu3pmezx.js","names":[],"sources":["../src/runners/mcp/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport type * as McpModule from '@kubb/mcp'\nimport { trackRun } from '../../Telemetry.ts'\n\n/**\n * Starts the `@kubb/mcp` server over stdio and reports the outcome to telemetry.\n */\nexport async function run(): Promise<void> {\n const { run: startMcpServer } = (await import('@kubb/mcp')) as typeof McpModule\n\n const report = trackRun({ command: 'mcp', hrStart: process.hrtime() })\n\n try {\n // The MCP stdio transport owns stdout: anything else written there corrupts the JSON-RPC stream.\n console.error(styleText('cyan', '⏳ Starting MCP server...'))\n console.warn(styleText('yellow', 'This feature is still under development, use with caution'))\n const server = startMcpServer()\n // Report once the client introduces itself, so the event names the client (e.g. `claude-code`, `cursor-vscode`).\n server.on('initialize', ({ clientInfo }) => void report({ status: 'success', mcpClient: clientInfo.name }), { once: true })\n } catch (error) {\n await report({ status: 'failed' })\n console.error(toError(error).message)\n process.exitCode = 1\n }\n}\n"],"mappings":";;;;;;;;AASA,eAAsB,MAAqB;CACzC,MAAM,EAAE,KAAK,mBAAoB,MAAM,OAAO;CAE9C,MAAM,SAAS,SAAS;EAAE,SAAS;EAAO,SAAS,QAAQ,OAAO;CAAE,CAAC;CAErE,IAAI;EAEF,QAAQ,MAAM,UAAU,QAAQ,0BAA0B,CAAC;EAC3D,QAAQ,KAAK,UAAU,UAAU,2DAA2D,CAAC;EAG7F,eAAK,CAAC,CAAC,GAAG,eAAe,EAAE,iBAAiB,KAAK,OAAO;GAAE,QAAQ;GAAW,WAAW,WAAW;EAAK,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC;CAC5H,SAAS,OAAO;EACd,MAAM,OAAO,EAAE,QAAQ,SAAS,CAAC;EACjC,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC,OAAO;EACpC,QAAQ,WAAW;CACrB;AACF"}
@@ -1,5 +1,5 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { l as toError, n as trackRun } from "./Telemetry-DZEM4fEd.js";
2
+ import { l as toError, n as trackRun } from "./Telemetry-Bf6lUdai.js";
3
3
  import { styleText } from "node:util";
4
4
  import process from "node:process";
5
5
  //#region src/runners/validate/run.ts
@@ -36,4 +36,4 @@ async function run({ input }) {
36
36
  //#endregion
37
37
  export { run };
38
38
 
39
- //# sourceMappingURL=run-D3j4O7FO.js.map
39
+ //# sourceMappingURL=run-D4vOhfbJ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-D3j4O7FO.js","names":[],"sources":["../src/runners/validate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport { trackRun } from '../../Telemetry.ts'\n\ntype ValidateOptions = {\n /**\n * Path or URL to the OpenAPI/Swagger file to validate.\n */\n input: string\n}\n\n/**\n * Validates an OpenAPI/Swagger file at `input` using `@kubb/adapter-oas`.\n * Exits the process with code 1 on validation failure or missing dependency.\n */\nexport async function run({ input }: ValidateOptions): Promise<void> {\n const report = trackRun({ command: 'validate', hrStart: process.hrtime() })\n\n try {\n const { adapterOas } = await import('@kubb/adapter-oas')\n\n await adapterOas().validate(input, { throwOnError: true })\n await report({ status: 'success' })\n\n console.log('✅ Validation success')\n } catch (error) {\n await report({ status: 'failed' })\n if (error instanceof Error && /@kubb\\/adapter-oas/.test(error.message)) {\n console.error(styleText('red', 'The @kubb/adapter-oas package is not installed.'))\n console.error('')\n console.error('Install it with:')\n console.error(styleText('cyan', ' npm install @kubb/adapter-oas'))\n console.error(styleText('cyan', ' # or'))\n console.error(styleText('cyan', ' pnpm install @kubb/adapter-oas'))\n console.error('')\n }\n console.error('❌ Validation failed')\n console.error(toError(error).message)\n\n process.exit(1)\n }\n}\n"],"mappings":";;;;;;;;;AAgBA,eAAsB,IAAI,EAAE,SAAyC;CACnE,MAAM,SAAS,SAAS;EAAE,SAAS;EAAY,SAAS,QAAQ,OAAO;CAAE,CAAC;CAE1E,IAAI;EACF,MAAM,EAAE,eAAe,MAAM,OAAO;EAEpC,MAAM,WAAW,CAAC,CAAC,SAAS,OAAO,EAAE,cAAc,KAAK,CAAC;EACzD,MAAM,OAAO,EAAE,QAAQ,UAAU,CAAC;EAElC,QAAQ,IAAI,sBAAsB;CACpC,SAAS,OAAO;EACd,MAAM,OAAO,EAAE,QAAQ,SAAS,CAAC;EACjC,IAAI,iBAAiB,SAAS,qBAAqB,KAAK,MAAM,OAAO,GAAG;GACtE,QAAQ,MAAM,UAAU,OAAO,iDAAiD,CAAC;GACjF,QAAQ,MAAM,EAAE;GAChB,QAAQ,MAAM,kBAAkB;GAChC,QAAQ,MAAM,UAAU,QAAQ,iCAAiC,CAAC;GAClE,QAAQ,MAAM,UAAU,QAAQ,QAAQ,CAAC;GACzC,QAAQ,MAAM,UAAU,QAAQ,kCAAkC,CAAC;GACnE,QAAQ,MAAM,EAAE;EAClB;EACA,QAAQ,MAAM,qBAAqB;EACnC,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC,OAAO;EAEpC,QAAQ,KAAK,CAAC;CAChB;AACF"}
1
+ {"version":3,"file":"run-D4vOhfbJ.js","names":[],"sources":["../src/runners/validate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport { trackRun } from '../../Telemetry.ts'\n\ntype ValidateOptions = {\n /**\n * Path or URL to the OpenAPI/Swagger file to validate.\n */\n input: string\n}\n\n/**\n * Validates an OpenAPI/Swagger file at `input` using `@kubb/adapter-oas`.\n * Exits the process with code 1 on validation failure or missing dependency.\n */\nexport async function run({ input }: ValidateOptions): Promise<void> {\n const report = trackRun({ command: 'validate', hrStart: process.hrtime() })\n\n try {\n const { adapterOas } = await import('@kubb/adapter-oas')\n\n await adapterOas().validate(input, { throwOnError: true })\n await report({ status: 'success' })\n\n console.log('✅ Validation success')\n } catch (error) {\n await report({ status: 'failed' })\n if (error instanceof Error && /@kubb\\/adapter-oas/.test(error.message)) {\n console.error(styleText('red', 'The @kubb/adapter-oas package is not installed.'))\n console.error('')\n console.error('Install it with:')\n console.error(styleText('cyan', ' npm install @kubb/adapter-oas'))\n console.error(styleText('cyan', ' # or'))\n console.error(styleText('cyan', ' pnpm install @kubb/adapter-oas'))\n console.error('')\n }\n console.error('❌ Validation failed')\n console.error(toError(error).message)\n\n process.exit(1)\n }\n}\n"],"mappings":";;;;;;;;;AAgBA,eAAsB,IAAI,EAAE,SAAyC;CACnE,MAAM,SAAS,SAAS;EAAE,SAAS;EAAY,SAAS,QAAQ,OAAO;CAAE,CAAC;CAE1E,IAAI;EACF,MAAM,EAAE,eAAe,MAAM,OAAO;EAEpC,MAAM,WAAW,CAAC,CAAC,SAAS,OAAO,EAAE,cAAc,KAAK,CAAC;EACzD,MAAM,OAAO,EAAE,QAAQ,UAAU,CAAC;EAElC,QAAQ,IAAI,sBAAsB;CACpC,SAAS,OAAO;EACd,MAAM,OAAO,EAAE,QAAQ,SAAS,CAAC;EACjC,IAAI,iBAAiB,SAAS,qBAAqB,KAAK,MAAM,OAAO,GAAG;GACtE,QAAQ,MAAM,UAAU,OAAO,iDAAiD,CAAC;GACjF,QAAQ,MAAM,EAAE;GAChB,QAAQ,MAAM,kBAAkB;GAChC,QAAQ,MAAM,UAAU,QAAQ,iCAAiC,CAAC;GAClE,QAAQ,MAAM,UAAU,QAAQ,QAAQ,CAAC;GACzC,QAAQ,MAAM,UAAU,QAAQ,kCAAkC,CAAC;GACnE,QAAQ,MAAM,EAAE;EAClB;EACA,QAAQ,MAAM,qBAAqB;EACnC,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC,OAAO;EAEpC,QAAQ,KAAK,CAAC;CAChB;AACF"}
@@ -1,7 +1,7 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-CPE0t6oh.cjs");
2
- const require_Telemetry = require("./Telemetry-D3X0YeTq.cjs");
3
- const require_output = require("./output-BgIxkmno.cjs");
4
- const require_config = require("./config-DTaFUofU.cjs");
2
+ const require_Telemetry = require("./Telemetry-BfdvvZus.cjs");
3
+ const require_output = require("./output-DLrxGtuN.cjs");
4
+ const require_config = require("./config-CcqzzfB7.cjs");
5
5
  const require_credentials = require("./credentials-DDaKqtJn.cjs");
6
6
  let node_util = require("node:util");
7
7
  let node_os = require("node:os");
@@ -84,7 +84,12 @@ const PERMISSIONS = [
84
84
  {
85
85
  key: "allowRead",
86
86
  label: "read generated files",
87
- question: () => "Let Kubb Studio read the files a generation produced and its parsed spec?"
87
+ question: () => "Let Kubb Studio read the files a generation produced?"
88
+ },
89
+ {
90
+ key: "allowReadAst",
91
+ label: "read parsed spec",
92
+ question: () => "Let Kubb Studio read the parsed spec (the Kubb AST)?"
88
93
  },
89
94
  {
90
95
  key: "allowWrite",
@@ -111,13 +116,14 @@ function formatPermissionRows(granted) {
111
116
  }
112
117
  /**
113
118
  * Resolves Studio permissions for the current project.
114
- * Flags win, saved answers are reused, and new answers are stored unless `persist` is false.
119
+ * Flags win, saved answers are reused, and new answers are stored in `~/.kubb/credentials.json`.
115
120
  */
116
- async function resolvePermissions(options, credentials, configPath = require_output.KUBB_CONFIG_FILENAME, persist = true) {
121
+ async function resolvePermissions(options, credentials, configPath = require_output.KUBB_CONFIG_FILENAME) {
117
122
  const project = node_process.default.cwd();
118
123
  const remembered = credentials.projects?.[project];
119
124
  const granted = {
120
125
  allowRead: false,
126
+ allowReadAst: false,
121
127
  allowWrite: false,
122
128
  allowConfigEdit: false,
123
129
  allowExec: false
@@ -139,7 +145,7 @@ async function resolvePermissions(options, credentials, configPath = require_out
139
145
  }) === true;
140
146
  answers[key] = granted[key];
141
147
  }
142
- if (persist && Object.keys(answers).length) await require_credentials.writeCredentials({
148
+ if (Object.keys(answers).length) await require_credentials.writeCredentials({
143
149
  ...credentials,
144
150
  projects: {
145
151
  ...credentials.projects,
@@ -172,30 +178,22 @@ async function loadConfigs(options) {
172
178
  * decides what happens to the credentials.
173
179
  */
174
180
  function explainRejectedToken(error, reason) {
175
- if (reason === "envToken") return /* @__PURE__ */ new Error(`${error.message} Pair again and update KUBB_AGENT_TOKEN.`);
176
181
  if (reason === "reauthExhausted") return /* @__PURE__ */ new Error(`${error.message} Studio rejected the newly approved token too. Run \`kubb studio login\` and try again.`);
177
182
  return /* @__PURE__ */ new Error(`${error.message} Run \`kubb studio login\` to pair again.`);
178
183
  }
179
184
  /** Validates the project and resolves pairing and permissions before starting its worker. */
180
185
  async function prepareConnection(options, signal) {
181
186
  const { configPath } = await loadConfigs(options);
182
- const envToken = node_process.default.env.KUBB_AGENT_TOKEN;
183
- const stored = envToken ? null : await require_credentials.readCredentials();
187
+ const stored = await require_credentials.readCredentials();
184
188
  const credentials = await (async () => {
185
- if (envToken) return {
186
- studioUrl: options.studioUrl,
187
- token: envToken,
188
- agentId: "",
189
- agentSlug: ""
190
- };
191
189
  if (stored?.studioUrl === options.studioUrl) return stored;
192
- if (require_Telemetry.isCIEnvironment()) throw new Error(`Not paired with ${options.studioUrl}. Set KUBB_AGENT_TOKEN, or run \`kubb studio login\` on a machine with a browser.`);
190
+ if (require_Telemetry.isCIEnvironment()) throw new Error(`Not paired with ${options.studioUrl}. In CI, run \`kubb studio snapshot\` instead, or run \`kubb studio login\` on a machine with a browser.`);
193
191
  return login(options, { signal });
194
192
  })();
195
193
  return {
196
194
  configPath,
197
195
  credentials,
198
- permissions: await resolvePermissions(options, credentials, configPath, !envToken)
196
+ permissions: await resolvePermissions(options, credentials, configPath)
199
197
  };
200
198
  }
201
199
  /** Runs the same project connection in the foreground or in a background worker. */
@@ -210,7 +208,7 @@ async function connect(options, context = {}) {
210
208
  }
211
209
  try {
212
210
  if (!context.prepared) {
213
- const { getWorkerStatus } = await Promise.resolve().then(() => require("./background-B9Ymrpv9.cjs"));
211
+ const { getWorkerStatus } = await Promise.resolve().then(() => require("./background-obsD4Gj2.cjs"));
214
212
  if ((await getWorkerStatus()).running) throw new Error("This project is running in the background. Run `kubb studio stop` first.");
215
213
  }
216
214
  const prepared = context.prepared ?? await prepareConnection(options, signal);
@@ -249,7 +247,6 @@ async function connect(options, context = {}) {
249
247
  } catch (error) {
250
248
  if (!(error instanceof _kubb_studio.InvalidAgentTokenError)) throw error;
251
249
  await context.onState?.("authentication required");
252
- if (node_process.default.env.KUBB_AGENT_TOKEN) throw explainRejectedToken(error, "envToken");
253
250
  await require_credentials.clearCredentials();
254
251
  if (pairedAgain) throw explainRejectedToken(error, "reauthExhausted");
255
252
  if (context.onState || require_Telemetry.isCIEnvironment() || !require_output.canUseTTY()) throw explainRejectedToken(error, "nonInteractive");
@@ -280,6 +277,7 @@ async function runStudio(values, action, { block = false, json = false } = {}) {
280
277
  studioUrl: values.url ?? _kubb_studio.defaultStudioUrl,
281
278
  permission: {
282
279
  allowRead: values.allowRead ?? false,
280
+ allowReadAst: values.allowReadAst ?? false,
283
281
  allowWrite: values.allowWrite ?? false,
284
282
  allowConfigEdit: values.allowConfigEdit ?? false,
285
283
  allowExec: values.allowExec ?? false
@@ -312,4 +310,4 @@ exports.login = login;
312
310
  exports.prepareConnection = prepareConnection;
313
311
  exports.runStudio = runStudio;
314
312
 
315
- //# sourceMappingURL=run-B3bSqn5G.cjs.map
313
+ //# sourceMappingURL=run-DHiVlG37.cjs.map