@kubb/cli 5.12.4 → 5.12.6

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 (66) hide show
  1. package/dist/{Telemetry-CstxHeyx.js → Telemetry-Bjn0mrII.js} +2 -2
  2. package/dist/{Telemetry-CstxHeyx.js.map → Telemetry-Bjn0mrII.js.map} +1 -1
  3. package/dist/{Telemetry-BkicoE-Z.cjs → Telemetry-CnmBUj6w.cjs} +2 -2
  4. package/dist/{Telemetry-BkicoE-Z.cjs.map → Telemetry-CnmBUj6w.cjs.map} +1 -1
  5. package/dist/{background-70s5rqtb.cjs → background-B0GVKZGZ.cjs} +2 -2
  6. package/dist/{background-70s5rqtb.cjs.map → background-B0GVKZGZ.cjs.map} +1 -1
  7. package/dist/{background-CPq1NAJT.js → background-BdcvoIOa.js} +2 -2
  8. package/dist/{background-CPq1NAJT.js.map → background-BdcvoIOa.js.map} +1 -1
  9. package/dist/{background-Dwiy0N4c.js → background-BeAXQscS.js} +1 -1
  10. package/dist/{config-Bh00Hwpw.js → config-BD5d6yQG.js} +8 -2
  11. package/dist/config-BD5d6yQG.js.map +1 -0
  12. package/dist/{config-D63Gum4F.cjs → config-CsRWusL0.cjs} +8 -2
  13. package/dist/config-CsRWusL0.cjs.map +1 -0
  14. package/dist/config-CueFKxKs.js +1 -0
  15. package/dist/index.cjs +19 -19
  16. package/dist/index.js +19 -19
  17. package/dist/{registry-BRWRpTro.js → registry-D1QHBcNK.js} +3 -3
  18. package/dist/{registry-BRWRpTro.js.map → registry-D1QHBcNK.js.map} +1 -1
  19. package/dist/{registry-C0e_AKBs.cjs → registry-DsAPRl9s.cjs} +3 -3
  20. package/dist/{registry-C0e_AKBs.cjs.map → registry-DsAPRl9s.cjs.map} +1 -1
  21. package/dist/{reporters-B4bdZbKM.js → reporters-CqYdEotX.js} +4 -4
  22. package/dist/{reporters-B4bdZbKM.js.map → reporters-CqYdEotX.js.map} +1 -1
  23. package/dist/{reporters-BCr1sLhx.cjs → reporters-D9P1Fj5L.cjs} +4 -4
  24. package/dist/{reporters-BCr1sLhx.cjs.map → reporters-D9P1Fj5L.cjs.map} +1 -1
  25. package/dist/{run-DAiTuC3q.js → run-BAav-oJX.js} +8 -8
  26. package/dist/{run-DAiTuC3q.js.map → run-BAav-oJX.js.map} +1 -1
  27. package/dist/{run-D9ji3RFo.js → run-BeTIeaKr.js} +2 -2
  28. package/dist/{run-D9ji3RFo.js.map → run-BeTIeaKr.js.map} +1 -1
  29. package/dist/{run-BBbDMKQV.js → run-Bu3NVhF_.js} +5 -5
  30. package/dist/{run-BBbDMKQV.js.map → run-Bu3NVhF_.js.map} +1 -1
  31. package/dist/{run-DKY7q4MO.cjs → run-CiL76_Ox.cjs} +8 -8
  32. package/dist/{run-DKY7q4MO.cjs.map → run-CiL76_Ox.cjs.map} +1 -1
  33. package/dist/{run-BTCJEgx1.js → run-DKSzq1gZ.js} +7 -7
  34. package/dist/{run-BTCJEgx1.js.map → run-DKSzq1gZ.js.map} +1 -1
  35. package/dist/{run-ybmOzOWQ.cjs → run-DRd-hex3.cjs} +5 -5
  36. package/dist/{run-ybmOzOWQ.cjs.map → run-DRd-hex3.cjs.map} +1 -1
  37. package/dist/{run-n6CWcR7D.js → run-DSqcCfzJ.js} +1 -1
  38. package/dist/{run-Bep5DR9M.cjs → run-u1kyLMfG.cjs} +2 -2
  39. package/dist/{run-Bep5DR9M.cjs.map → run-u1kyLMfG.cjs.map} +1 -1
  40. package/dist/{run-DeCB4qsZ.cjs → run-zM8LuA9X.cjs} +7 -7
  41. package/dist/{run-DeCB4qsZ.cjs.map → run-zM8LuA9X.cjs.map} +1 -1
  42. package/dist/{snapshot-CFFW4xh5.cjs → snapshot-BmTdkg9_.cjs} +6 -6
  43. package/dist/{snapshot-CFFW4xh5.cjs.map → snapshot-BmTdkg9_.cjs.map} +1 -1
  44. package/dist/{snapshot-C67BxRxn.js → snapshot-o_BPMJIu.js} +6 -6
  45. package/dist/{snapshot-C67BxRxn.js.map → snapshot-o_BPMJIu.js.map} +1 -1
  46. package/dist/{status-vo86HTqZ.cjs → status-C47VdG48.cjs} +3 -3
  47. package/dist/{status-vo86HTqZ.cjs.map → status-C47VdG48.cjs.map} +1 -1
  48. package/dist/{status-C0SdSTAE.js → status-DKnQ4Uty.js} +3 -3
  49. package/dist/{status-C0SdSTAE.js.map → status-DKnQ4Uty.js.map} +1 -1
  50. package/dist/studioWorker.js +2 -2
  51. package/dist/{summary-CCEwKLOi.cjs → summary-WFRQVDNp.cjs} +3 -3
  52. package/dist/{summary-CCEwKLOi.cjs.map → summary-WFRQVDNp.cjs.map} +1 -1
  53. package/dist/{summary-JL96aI9h.js → summary-rD3DP405.js} +3 -3
  54. package/dist/{summary-JL96aI9h.js.map → summary-rD3DP405.js.map} +1 -1
  55. package/dist/{text-ul0IR1pq.js → text-BbK3UX0I.js} +2 -2
  56. package/dist/{text-ul0IR1pq.js.map → text-BbK3UX0I.js.map} +1 -1
  57. package/dist/{text-BFXVEEQp.cjs → text-DOD7hw-U.cjs} +2 -2
  58. package/dist/{text-BFXVEEQp.cjs.map → text-DOD7hw-U.cjs.map} +1 -1
  59. package/dist/{utils-A-f-U1E7.cjs → utils-0MRBnDLb.cjs} +3 -3
  60. package/dist/{utils-A-f-U1E7.cjs.map → utils-0MRBnDLb.cjs.map} +1 -1
  61. package/dist/{utils-BZYbuZTD.js → utils-DnkrY3vN.js} +3 -3
  62. package/dist/{utils-BZYbuZTD.js.map → utils-DnkrY3vN.js.map} +1 -1
  63. package/package.json +7 -7
  64. package/dist/config-Bh00Hwpw.js.map +0 -1
  65. package/dist/config-D63Gum4F.cjs.map +0 -1
  66. package/dist/config-iVdOcpro.js +0 -1
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { t as __name } from "./rolldown-runtime-CRm0XQPb.js";
2
2
  import { t as getErrorMessage } from "./errors-DmC83ALX.js";
3
- import { a as getElapsedMs, i as formatMs, r as version, t as isDisabled } from "./Telemetry-CstxHeyx.js";
4
- import { _ as write, a as readOutputFiles, c as createSpinner, g as read, l as withSpinner, m as exists, n as diffFiles } from "./utils-BZYbuZTD.js";
5
- import { _ as isRichOutput, a as logOutro, c as logBlock, d as logStep, f as logWarn, i as logIntro, l as logError, r as isInteractiveRun, t as pluralize } from "./text-ul0IR1pq.js";
6
- import { a as installSpec, c as toRegistryId, f as wantsMascot, i as incompatibility, l as toShortId, n as closestIds, o as isOutdated, r as fetchRegistryIndex, s as registryUrl, t as bumpOf, u as getBanner } from "./registry-BRWRpTro.js";
7
- import { a as initDefaults, i as KUBB_PACKAGE_NAME, n as findConfigFile, r as KUBB_CONFIG_FILENAME, t as getConfigs } from "./config-Bh00Hwpw.js";
8
- import { t as logCommandSummary } from "./summary-JL96aI9h.js";
3
+ import { a as getElapsedMs, i as formatMs, r as version, t as isDisabled } from "./Telemetry-Bjn0mrII.js";
4
+ import { _ as write, a as readOutputFiles, c as createSpinner, g as read, l as withSpinner, m as exists, n as diffFiles } from "./utils-DnkrY3vN.js";
5
+ import { _ as isRichOutput, a as logOutro, c as logBlock, d as logStep, f as logWarn, i as logIntro, l as logError, r as isInteractiveRun, t as pluralize } from "./text-BbK3UX0I.js";
6
+ import { a as installSpec, c as toRegistryId, f as wantsMascot, i as incompatibility, l as toShortId, n as closestIds, o as isOutdated, r as fetchRegistryIndex, s as registryUrl, t as bumpOf, u as getBanner } from "./registry-D1QHBcNK.js";
7
+ import { a as initDefaults, i as KUBB_PACKAGE_NAME, n as findConfigFile, r as KUBB_CONFIG_FILENAME, t as getConfigs } from "./config-BD5d6yQG.js";
8
+ import { t as logCommandSummary } from "./summary-rD3DP405.js";
9
9
  import { styleText } from "node:util";
10
10
  import dryrun, { pluginId as dryRunId } from "@gunshi/plugin-dryrun";
11
11
  import { cli, define, defineWithTypes } from "gunshi";
@@ -179,7 +179,7 @@ const command$13 = defineWithTypes()({
179
179
  async run(ctx) {
180
180
  const { values } = ctx;
181
181
  const logLevel = resolveLogLevel(values);
182
- const { run } = await import("./run-BTCJEgx1.js");
182
+ const { run } = await import("./run-DKSzq1gZ.js");
183
183
  await run({
184
184
  input: values.input,
185
185
  configPath: values.config,
@@ -203,7 +203,7 @@ const command$12 = define({
203
203
  ].join("\n"),
204
204
  rendering: { header: null },
205
205
  async run() {
206
- const { run } = await import("./run-D9ji3RFo.js");
206
+ const { run } = await import("./run-BeTIeaKr.js");
207
207
  await run();
208
208
  }
209
209
  });
@@ -218,7 +218,7 @@ function studioCommand({ action, block, ...definition }) {
218
218
  ...definition,
219
219
  toKebab: true,
220
220
  async run({ values }) {
221
- const { runStudio } = await import("./run-n6CWcR7D.js");
221
+ const { runStudio } = await import("./run-DSqcCfzJ.js");
222
222
  await runStudio(values, action, { block });
223
223
  }
224
224
  });
@@ -248,7 +248,7 @@ const command$11 = studioCommand({
248
248
  },
249
249
  block: true,
250
250
  async action(options) {
251
- const { connect } = await import("./run-n6CWcR7D.js");
251
+ const { connect } = await import("./run-DSqcCfzJ.js");
252
252
  await connect(options);
253
253
  }
254
254
  });
@@ -260,7 +260,7 @@ const command$10 = studioCommand({
260
260
  examples: ["kubb studio login", "kubb studio login --url http://localhost:3000"].join("\n"),
261
261
  args: command$11.args,
262
262
  async action(options) {
263
- const { login } = await import("./run-n6CWcR7D.js");
263
+ const { login } = await import("./run-DSqcCfzJ.js");
264
264
  await login(options);
265
265
  }
266
266
  });
@@ -272,7 +272,7 @@ const command$9 = studioCommand({
272
272
  examples: "kubb studio logout",
273
273
  args: {},
274
274
  async action() {
275
- const { stopWorker } = await import("./background-Dwiy0N4c.js");
275
+ const { stopWorker } = await import("./background-BeAXQscS.js");
276
276
  const { clearCredentials } = await import("./credentials-C8tjAhTo.js");
277
277
  await stopWorker();
278
278
  await clearCredentials();
@@ -315,7 +315,7 @@ const command$8 = define({
315
315
  ...logLevelArg
316
316
  },
317
317
  async run(ctx) {
318
- const { runner } = await import("./snapshot-C67BxRxn.js");
318
+ const { runner } = await import("./snapshot-o_BPMJIu.js");
319
319
  await runner(ctx);
320
320
  }
321
321
  });
@@ -326,7 +326,7 @@ const command$7 = studioCommand({
326
326
  description: "Keep this project connected to Kubb Studio in the background.",
327
327
  args: command$11.args,
328
328
  async action(options) {
329
- const { startWorker } = await import("./background-Dwiy0N4c.js");
329
+ const { startWorker } = await import("./background-BeAXQscS.js");
330
330
  await startWorker(options);
331
331
  }
332
332
  });
@@ -334,7 +334,7 @@ const stopCommand = define({
334
334
  name: "stop",
335
335
  description: "Stop this project's background connection and keep its pairing.",
336
336
  async run() {
337
- const { stopWorker } = await import("./background-Dwiy0N4c.js");
337
+ const { stopWorker } = await import("./background-BeAXQscS.js");
338
338
  await stopWorker();
339
339
  console.log("Background connection stopped.");
340
340
  }
@@ -347,9 +347,9 @@ const command$6 = studioCommand({
347
347
  examples: "kubb studio status",
348
348
  args: { url: studioConnectionArgs.url },
349
349
  async action(options) {
350
- const { getWorkerLogPath, getWorkerStatus } = await import("./background-Dwiy0N4c.js");
350
+ const { getWorkerLogPath, getWorkerStatus } = await import("./background-BeAXQscS.js");
351
351
  const { readCredentials } = await import("./credentials-C8tjAhTo.js");
352
- const { formatStatus } = await import("./status-C0SdSTAE.js");
352
+ const { formatStatus } = await import("./status-DKnQ4Uty.js");
353
353
  const [worker, credentials] = await Promise.all([getWorkerStatus(), readCredentials()]);
354
354
  console.log([
355
355
  "",
@@ -417,7 +417,7 @@ const command$4 = define({
417
417
  }
418
418
  },
419
419
  async run({ values }) {
420
- const { run } = await import("./run-BBbDMKQV.js");
420
+ const { run } = await import("./run-Bu3NVhF_.js");
421
421
  await run({
422
422
  input: values.input,
423
423
  configPath: values.config
@@ -1449,7 +1449,7 @@ async function regenerate({ cwd, configPath }) {
1449
1449
  const spinner = createSpinner();
1450
1450
  spinner.start("Generating with the new versions");
1451
1451
  try {
1452
- const [{ getConfigs }, { generate }] = await Promise.all([import("./config-iVdOcpro.js"), import("./run-BTCJEgx1.js")]);
1452
+ const [{ getConfigs }, { generate }] = await Promise.all([import("./config-CueFKxKs.js"), import("./run-DKSzq1gZ.js")]);
1453
1453
  const { configs } = await getConfigs({ configPath });
1454
1454
  const dirs = configs.map((config) => path.resolve(config.root ?? cwd, config.output.path));
1455
1455
  const before = new Map((await Promise.all(dirs.map(readOutputFiles))).flatMap((files) => [...files]));
@@ -1,7 +1,7 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
2
  import { n as toError, t as getErrorMessage } from "./errors-DmC83ALX.js";
3
- import { f as getIntro, p as wakeUp } from "./utils-BZYbuZTD.js";
4
- import { _ as isRichOutput, r as isInteractiveRun } from "./text-ul0IR1pq.js";
3
+ import { f as getIntro, p as wakeUp } from "./utils-DnkrY3vN.js";
4
+ import { _ as isRichOutput, r as isInteractiveRun } from "./text-BbK3UX0I.js";
5
5
  import { stripVTControlCharacters } from "node:util";
6
6
  import process$1 from "node:process";
7
7
  import { setTimeout } from "node:timers/promises";
@@ -197,4 +197,4 @@ function closestIds({ input, ids }) {
197
197
  //#endregion
198
198
  export { installSpec as a, toRegistryId as c, logBanner as d, wantsMascot as f, incompatibility as i, toShortId as l, closestIds as n, isOutdated as o, fetchRegistryIndex as r, registryUrl as s, bumpOf as t, getBanner as u };
199
199
 
200
- //# sourceMappingURL=registry-BRWRpTro.js.map
200
+ //# sourceMappingURL=registry-D1QHBcNK.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry-BRWRpTro.js","names":["sleep","process"],"sources":["../src/ui/mascot.ts","../src/utils/registry.ts"],"sourcesContent":["import { setTimeout as sleep } from 'node:timers/promises'\nimport { stripVTControlCharacters } from 'node:util'\nimport { isRichOutput } from '../utils/env.ts'\nimport { type Expression, getIntro, wakeUp } from '../loggers/banner.ts'\nimport { isInteractiveRun } from './intro.ts'\n\nfunction bannerIntro(version: string, expression: Expression, command: string): string {\n return getIntro({ title: 'Turn your API spec into type-safe code', description: `kubb ${command}`, version, expression })\n}\n\n/** Whether the mascot can be drawn: a rich, 256-color terminal wide enough that no line wraps and throws off a redraw. */\nfunction canDrawMascot(version: string, command: string): boolean {\n if (!isRichOutput() || !process.stdout.hasColors(256)) return false\n\n return stripVTControlCharacters(bannerIntro(version, 'open', command))\n .split('\\n')\n .every((line) => line.length <= process.stdout.columns)\n}\n\n/**\n * Whether a command opens with the mascot. Only the long-running ones do: `generate`, a Studio\n * session or pairing, and `add` or `update` while they ask questions. Quick commands print only\n * their result.\n */\nexport function wantsMascot({ commandPath, values }: { commandPath: ReadonlyArray<string>; values: Record<string, unknown> }): boolean {\n const [command, subCommand] = commandPath\n if (values.help || values.version) return false\n if (command === 'studio') return subCommand === undefined || subCommand === 'connect' || subCommand === 'login'\n if (command === 'add' || command === 'update' || command === 'init') return isInteractiveRun({ yes: values.yes, dryRun: values.dryRun ?? values['dry-run'] })\n\n return command === undefined || command === 'generate'\n}\n\n/**\n * The still Kubb mascot with the version and the running command, such as `studio connect`, or a\n * single version line where the terminal cannot draw it. Commands print it as their header; it\n * draws at once, with no wake-up frames.\n */\nexport function getBanner(version: string, command: string): string {\n return canDrawMascot(version, command) ? `\\n${bannerIntro(version, 'open', command)}` : `Kubb CLI v${version}`\n}\n\n/**\n * Opens `kubb generate` with the mascot playing its wake-up frames in place, which takes under a\n * second and overlaps the config load. Elsewhere the still {@link getBanner} is the header.\n */\nexport async function logBanner(version: string): Promise<void> {\n if (!canDrawMascot(version, 'generate')) {\n console.log(getBanner(version, 'generate'))\n\n return\n }\n\n console.log('')\n for (const [index, [expression, ms]] of wakeUp.entries()) {\n const frame = bannerIntro(version, expression, 'generate')\n if (index > 0) process.stdout.moveCursor(0, -frame.split('\\n').length)\n console.log(frame)\n await sleep(ms)\n }\n}\n","import process from 'node:process'\nimport { getErrorMessage, toError } from '@internals/utils'\nimport { checkCompatibility, Diagnostics, type ExtensionManifest, isRegistryEntry, type RegistryArtifact, type RegistryEntry } from '@kubb/core'\nimport { difference, isLessThan, isValid } from 'verkit'\n\nconst 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))\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `KUBB_REGISTRY must be an http(s) URL, got \"${url}\".`,\n help: 'Set `KUBB_REGISTRY` to an http(s) URL, or unset it to use https://kubb.dev/registry.',\n })\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))\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `\"${input}\" is not a registry id. Use owner/slug, such as kubb-labs/plugin-zod, or a slug, such as plugin-zod.`,\n })\n return input.includes('/') ? input : `kubb-labs/${input}`\n}\n\n/** The shortest id `kubb add` and `kubb update` accept: the slug for an official extension, else `owner/slug`. */\nexport function toShortId(id: string): string {\n return id.startsWith('kubb-labs/') ? id.slice('kubb-labs/'.length) : id\n}\n\n/**\n * GETs `url` as JSON. A non-2xx answer or a body that is not JSON returns no `body`.\n * A network error throws with the URL.\n */\nasync function fetchJSON(url: string): Promise<{ status: number; body?: unknown }> {\n let response: Response\n try {\n response = await globalThis.fetch(url, { headers: { accept: 'application/json' } })\n } catch (cause) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.inputUnreachable,\n severity: 'error',\n message: `Could not read ${url}: ${getErrorMessage(cause)}`,\n help: 'Check your network connection and that the registry is reachable.',\n cause: toError(cause),\n })\n }\n if (!response.ok) return { status: response.status }\n return { status: response.status, body: await response.json().catch(() => undefined) }\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 Diagnostics.Error({\n code: Diagnostics.code.inputRequestFailed,\n severity: 'error',\n message: `The registry at ${registry} sent an invalid index (HTTP ${status}).`,\n help: 'Try again later, or check that `KUBB_REGISTRY` points at a Kubb registry.',\n })\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\n/** `major`, `minor`, or `patch` from `installed` to `latest`, or `undefined` when either is unknown or invalid. */\nexport function bumpOf({ installed, latest }: { installed: string | undefined; latest: string }): 'major' | 'minor' | 'patch' | undefined {\n if (!installed || !isValid(installed) || !isValid(latest)) return undefined\n const kind = difference(installed, latest)\n if (!kind) return undefined\n if (kind.endsWith('major')) return 'major'\n return kind.endsWith('minor') ? 'minor' : 'patch'\n}\n\nfunction editDistance(a: string, b: string): number {\n const row = Array.from({ length: b.length + 1 }, (_, index) => index)\n for (let i = 1; i <= a.length; i++) {\n let previous = row[0]!\n row[0] = i\n for (let j = 1; j <= b.length; j++) {\n const current = row[j]!\n row[j] = Math.min(row[j]! + 1, row[j - 1]! + 1, previous + (a[i - 1] === b[j - 1] ? 0 : 1))\n previous = current\n }\n }\n return row[b.length]!\n}\n\n/** Words every extension shares, so they never make two ids look alike. */\nconst COMMON_TOKENS = new Set(['kubb', 'plugin', 'adapter', 'parser'])\n\n/**\n * The ids closest to a mistyped `input`, best first, at most three: those within a few edits of it,\n * or sharing a word such as `zod` in any order. Compares slugs, so the owner may be left out.\n */\nexport function closestIds({ input, ids }: { input: string; ids: Array<string> }): Array<string> {\n const slug = (id: string) => id.slice(id.indexOf('/') + 1)\n const tokens = new Set(\n slug(input)\n .split('-')\n .filter((token) => !COMMON_TOKENS.has(token)),\n )\n return ids\n .map((id) => ({\n id,\n distance: editDistance(slug(input), slug(id)),\n shared: slug(id)\n .split('-')\n .some((token) => tokens.has(token)),\n }))\n .filter(({ distance, shared }) => shared || distance <= Math.max(2, Math.floor(slug(input).length / 4)))\n .sort((a, b) => Number(b.shared) - Number(a.shared) || a.distance - b.distance)\n .slice(0, 3)\n .map(({ id }) => id)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"registry-D1QHBcNK.js","names":["sleep","process"],"sources":["../src/ui/mascot.ts","../src/utils/registry.ts"],"sourcesContent":["import { setTimeout as sleep } from 'node:timers/promises'\nimport { stripVTControlCharacters } from 'node:util'\nimport { isRichOutput } from '../utils/env.ts'\nimport { type Expression, getIntro, wakeUp } from '../loggers/banner.ts'\nimport { isInteractiveRun } from './intro.ts'\n\nfunction bannerIntro(version: string, expression: Expression, command: string): string {\n return getIntro({ title: 'Turn your API spec into type-safe code', description: `kubb ${command}`, version, expression })\n}\n\n/** Whether the mascot can be drawn: a rich, 256-color terminal wide enough that no line wraps and throws off a redraw. */\nfunction canDrawMascot(version: string, command: string): boolean {\n if (!isRichOutput() || !process.stdout.hasColors(256)) return false\n\n return stripVTControlCharacters(bannerIntro(version, 'open', command))\n .split('\\n')\n .every((line) => line.length <= process.stdout.columns)\n}\n\n/**\n * Whether a command opens with the mascot. Only the long-running ones do: `generate`, a Studio\n * session or pairing, and `add` or `update` while they ask questions. Quick commands print only\n * their result.\n */\nexport function wantsMascot({ commandPath, values }: { commandPath: ReadonlyArray<string>; values: Record<string, unknown> }): boolean {\n const [command, subCommand] = commandPath\n if (values.help || values.version) return false\n if (command === 'studio') return subCommand === undefined || subCommand === 'connect' || subCommand === 'login'\n if (command === 'add' || command === 'update' || command === 'init') return isInteractiveRun({ yes: values.yes, dryRun: values.dryRun ?? values['dry-run'] })\n\n return command === undefined || command === 'generate'\n}\n\n/**\n * The still Kubb mascot with the version and the running command, such as `studio connect`, or a\n * single version line where the terminal cannot draw it. Commands print it as their header; it\n * draws at once, with no wake-up frames.\n */\nexport function getBanner(version: string, command: string): string {\n return canDrawMascot(version, command) ? `\\n${bannerIntro(version, 'open', command)}` : `Kubb CLI v${version}`\n}\n\n/**\n * Opens `kubb generate` with the mascot playing its wake-up frames in place, which takes under a\n * second and overlaps the config load. Elsewhere the still {@link getBanner} is the header.\n */\nexport async function logBanner(version: string): Promise<void> {\n if (!canDrawMascot(version, 'generate')) {\n console.log(getBanner(version, 'generate'))\n\n return\n }\n\n console.log('')\n for (const [index, [expression, ms]] of wakeUp.entries()) {\n const frame = bannerIntro(version, expression, 'generate')\n if (index > 0) process.stdout.moveCursor(0, -frame.split('\\n').length)\n console.log(frame)\n await sleep(ms)\n }\n}\n","import process from 'node:process'\nimport { getErrorMessage, toError } from '@internals/utils'\nimport { checkCompatibility, Diagnostics, type ExtensionManifest, isRegistryEntry, type RegistryArtifact, type RegistryEntry } from '@kubb/core'\nimport { difference, isLessThan, isValid } from 'verkit'\n\nconst 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))\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `KUBB_REGISTRY must be an http(s) URL, got \"${url}\".`,\n help: 'Set `KUBB_REGISTRY` to an http(s) URL, or unset it to use https://kubb.dev/registry.',\n })\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))\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `\"${input}\" is not a registry id. Use owner/slug, such as kubb-labs/plugin-zod, or a slug, such as plugin-zod.`,\n })\n return input.includes('/') ? input : `kubb-labs/${input}`\n}\n\n/** The shortest id `kubb add` and `kubb update` accept: the slug for an official extension, else `owner/slug`. */\nexport function toShortId(id: string): string {\n return id.startsWith('kubb-labs/') ? id.slice('kubb-labs/'.length) : id\n}\n\n/**\n * GETs `url` as JSON. A non-2xx answer or a body that is not JSON returns no `body`.\n * A network error throws with the URL.\n */\nasync function fetchJSON(url: string): Promise<{ status: number; body?: unknown }> {\n let response: Response\n try {\n response = await globalThis.fetch(url, { headers: { accept: 'application/json' } })\n } catch (cause) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.inputUnreachable,\n severity: 'error',\n message: `Could not read ${url}: ${getErrorMessage(cause)}`,\n help: 'Check your network connection and that the registry is reachable.',\n cause: toError(cause),\n })\n }\n if (!response.ok) return { status: response.status }\n return { status: response.status, body: await response.json().catch(() => undefined) }\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 Diagnostics.Error({\n code: Diagnostics.code.inputRequestFailed,\n severity: 'error',\n message: `The registry at ${registry} sent an invalid index (HTTP ${status}).`,\n help: 'Try again later, or check that `KUBB_REGISTRY` points at a Kubb registry.',\n })\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\n/** `major`, `minor`, or `patch` from `installed` to `latest`, or `undefined` when either is unknown or invalid. */\nexport function bumpOf({ installed, latest }: { installed: string | undefined; latest: string }): 'major' | 'minor' | 'patch' | undefined {\n if (!installed || !isValid(installed) || !isValid(latest)) return undefined\n const kind = difference(installed, latest)\n if (!kind) return undefined\n if (kind.endsWith('major')) return 'major'\n return kind.endsWith('minor') ? 'minor' : 'patch'\n}\n\nfunction editDistance(a: string, b: string): number {\n const row = Array.from({ length: b.length + 1 }, (_, index) => index)\n for (let i = 1; i <= a.length; i++) {\n let previous = row[0]!\n row[0] = i\n for (let j = 1; j <= b.length; j++) {\n const current = row[j]!\n row[j] = Math.min(row[j]! + 1, row[j - 1]! + 1, previous + (a[i - 1] === b[j - 1] ? 0 : 1))\n previous = current\n }\n }\n return row[b.length]!\n}\n\n/** Words every extension shares, so they never make two ids look alike. */\nconst COMMON_TOKENS = new Set(['kubb', 'plugin', 'adapter', 'parser'])\n\n/**\n * The ids closest to a mistyped `input`, best first, at most three: those within a few edits of it,\n * or sharing a word such as `zod` in any order. Compares slugs, so the owner may be left out.\n */\nexport function closestIds({ input, ids }: { input: string; ids: Array<string> }): Array<string> {\n const slug = (id: string) => id.slice(id.indexOf('/') + 1)\n const tokens = new Set(\n slug(input)\n .split('-')\n .filter((token) => !COMMON_TOKENS.has(token)),\n )\n return ids\n .map((id) => ({\n id,\n distance: editDistance(slug(input), slug(id)),\n shared: slug(id)\n .split('-')\n .some((token) => tokens.has(token)),\n }))\n .filter(({ distance, shared }) => shared || distance <= Math.max(2, Math.floor(slug(input).length / 4)))\n .sort((a, b) => Number(b.shared) - Number(a.shared) || a.distance - b.distance)\n .slice(0, 3)\n .map(({ id }) => id)\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-CPE0t6oh.cjs");
2
2
  const require_errors = require("./errors-Cl69p_vI.cjs");
3
- const require_utils = require("./utils-A-f-U1E7.cjs");
4
- const require_text = require("./text-BFXVEEQp.cjs");
3
+ const require_utils = require("./utils-0MRBnDLb.cjs");
4
+ const require_text = require("./text-DOD7hw-U.cjs");
5
5
  let node_util = require("node:util");
6
6
  let node_process = require("node:process");
7
7
  node_process = require_rolldown_runtime.__toESM(node_process, 1);
@@ -269,4 +269,4 @@ Object.defineProperty(exports, "wantsMascot", {
269
269
  }
270
270
  });
271
271
 
272
- //# sourceMappingURL=registry-C0e_AKBs.cjs.map
272
+ //# sourceMappingURL=registry-DsAPRl9s.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry-C0e_AKBs.cjs","names":["getIntro","isRichOutput","stripVTControlCharacters","isInteractiveRun","wakeUp","sleep","process","Diagnostics","getErrorMessage","toError","isRegistryEntry","isValid","isLessThan","difference"],"sources":["../src/ui/mascot.ts","../src/utils/registry.ts"],"sourcesContent":["import { setTimeout as sleep } from 'node:timers/promises'\nimport { stripVTControlCharacters } from 'node:util'\nimport { isRichOutput } from '../utils/env.ts'\nimport { type Expression, getIntro, wakeUp } from '../loggers/banner.ts'\nimport { isInteractiveRun } from './intro.ts'\n\nfunction bannerIntro(version: string, expression: Expression, command: string): string {\n return getIntro({ title: 'Turn your API spec into type-safe code', description: `kubb ${command}`, version, expression })\n}\n\n/** Whether the mascot can be drawn: a rich, 256-color terminal wide enough that no line wraps and throws off a redraw. */\nfunction canDrawMascot(version: string, command: string): boolean {\n if (!isRichOutput() || !process.stdout.hasColors(256)) return false\n\n return stripVTControlCharacters(bannerIntro(version, 'open', command))\n .split('\\n')\n .every((line) => line.length <= process.stdout.columns)\n}\n\n/**\n * Whether a command opens with the mascot. Only the long-running ones do: `generate`, a Studio\n * session or pairing, and `add` or `update` while they ask questions. Quick commands print only\n * their result.\n */\nexport function wantsMascot({ commandPath, values }: { commandPath: ReadonlyArray<string>; values: Record<string, unknown> }): boolean {\n const [command, subCommand] = commandPath\n if (values.help || values.version) return false\n if (command === 'studio') return subCommand === undefined || subCommand === 'connect' || subCommand === 'login'\n if (command === 'add' || command === 'update' || command === 'init') return isInteractiveRun({ yes: values.yes, dryRun: values.dryRun ?? values['dry-run'] })\n\n return command === undefined || command === 'generate'\n}\n\n/**\n * The still Kubb mascot with the version and the running command, such as `studio connect`, or a\n * single version line where the terminal cannot draw it. Commands print it as their header; it\n * draws at once, with no wake-up frames.\n */\nexport function getBanner(version: string, command: string): string {\n return canDrawMascot(version, command) ? `\\n${bannerIntro(version, 'open', command)}` : `Kubb CLI v${version}`\n}\n\n/**\n * Opens `kubb generate` with the mascot playing its wake-up frames in place, which takes under a\n * second and overlaps the config load. Elsewhere the still {@link getBanner} is the header.\n */\nexport async function logBanner(version: string): Promise<void> {\n if (!canDrawMascot(version, 'generate')) {\n console.log(getBanner(version, 'generate'))\n\n return\n }\n\n console.log('')\n for (const [index, [expression, ms]] of wakeUp.entries()) {\n const frame = bannerIntro(version, expression, 'generate')\n if (index > 0) process.stdout.moveCursor(0, -frame.split('\\n').length)\n console.log(frame)\n await sleep(ms)\n }\n}\n","import process from 'node:process'\nimport { getErrorMessage, toError } from '@internals/utils'\nimport { checkCompatibility, Diagnostics, type ExtensionManifest, isRegistryEntry, type RegistryArtifact, type RegistryEntry } from '@kubb/core'\nimport { difference, isLessThan, isValid } from 'verkit'\n\nconst 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))\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `KUBB_REGISTRY must be an http(s) URL, got \"${url}\".`,\n help: 'Set `KUBB_REGISTRY` to an http(s) URL, or unset it to use https://kubb.dev/registry.',\n })\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))\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `\"${input}\" is not a registry id. Use owner/slug, such as kubb-labs/plugin-zod, or a slug, such as plugin-zod.`,\n })\n return input.includes('/') ? input : `kubb-labs/${input}`\n}\n\n/** The shortest id `kubb add` and `kubb update` accept: the slug for an official extension, else `owner/slug`. */\nexport function toShortId(id: string): string {\n return id.startsWith('kubb-labs/') ? id.slice('kubb-labs/'.length) : id\n}\n\n/**\n * GETs `url` as JSON. A non-2xx answer or a body that is not JSON returns no `body`.\n * A network error throws with the URL.\n */\nasync function fetchJSON(url: string): Promise<{ status: number; body?: unknown }> {\n let response: Response\n try {\n response = await globalThis.fetch(url, { headers: { accept: 'application/json' } })\n } catch (cause) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.inputUnreachable,\n severity: 'error',\n message: `Could not read ${url}: ${getErrorMessage(cause)}`,\n help: 'Check your network connection and that the registry is reachable.',\n cause: toError(cause),\n })\n }\n if (!response.ok) return { status: response.status }\n return { status: response.status, body: await response.json().catch(() => undefined) }\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 Diagnostics.Error({\n code: Diagnostics.code.inputRequestFailed,\n severity: 'error',\n message: `The registry at ${registry} sent an invalid index (HTTP ${status}).`,\n help: 'Try again later, or check that `KUBB_REGISTRY` points at a Kubb registry.',\n })\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\n/** `major`, `minor`, or `patch` from `installed` to `latest`, or `undefined` when either is unknown or invalid. */\nexport function bumpOf({ installed, latest }: { installed: string | undefined; latest: string }): 'major' | 'minor' | 'patch' | undefined {\n if (!installed || !isValid(installed) || !isValid(latest)) return undefined\n const kind = difference(installed, latest)\n if (!kind) return undefined\n if (kind.endsWith('major')) return 'major'\n return kind.endsWith('minor') ? 'minor' : 'patch'\n}\n\nfunction editDistance(a: string, b: string): number {\n const row = Array.from({ length: b.length + 1 }, (_, index) => index)\n for (let i = 1; i <= a.length; i++) {\n let previous = row[0]!\n row[0] = i\n for (let j = 1; j <= b.length; j++) {\n const current = row[j]!\n row[j] = Math.min(row[j]! + 1, row[j - 1]! + 1, previous + (a[i - 1] === b[j - 1] ? 0 : 1))\n previous = current\n }\n }\n return row[b.length]!\n}\n\n/** Words every extension shares, so they never make two ids look alike. */\nconst COMMON_TOKENS = new Set(['kubb', 'plugin', 'adapter', 'parser'])\n\n/**\n * The ids closest to a mistyped `input`, best first, at most three: those within a few edits of it,\n * or sharing a word such as `zod` in any order. Compares slugs, so the owner may be left out.\n */\nexport function closestIds({ input, ids }: { input: string; ids: Array<string> }): Array<string> {\n const slug = (id: string) => id.slice(id.indexOf('/') + 1)\n const tokens = new Set(\n slug(input)\n .split('-')\n .filter((token) => !COMMON_TOKENS.has(token)),\n )\n return ids\n .map((id) => ({\n id,\n distance: editDistance(slug(input), slug(id)),\n shared: slug(id)\n .split('-')\n .some((token) => tokens.has(token)),\n }))\n .filter(({ distance, shared }) => shared || distance <= Math.max(2, Math.floor(slug(input).length / 4)))\n .sort((a, b) => Number(b.shared) - Number(a.shared) || a.distance - b.distance)\n .slice(0, 3)\n .map(({ id }) => id)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"registry-DsAPRl9s.cjs","names":["getIntro","isRichOutput","stripVTControlCharacters","isInteractiveRun","wakeUp","sleep","process","Diagnostics","getErrorMessage","toError","isRegistryEntry","isValid","isLessThan","difference"],"sources":["../src/ui/mascot.ts","../src/utils/registry.ts"],"sourcesContent":["import { setTimeout as sleep } from 'node:timers/promises'\nimport { stripVTControlCharacters } from 'node:util'\nimport { isRichOutput } from '../utils/env.ts'\nimport { type Expression, getIntro, wakeUp } from '../loggers/banner.ts'\nimport { isInteractiveRun } from './intro.ts'\n\nfunction bannerIntro(version: string, expression: Expression, command: string): string {\n return getIntro({ title: 'Turn your API spec into type-safe code', description: `kubb ${command}`, version, expression })\n}\n\n/** Whether the mascot can be drawn: a rich, 256-color terminal wide enough that no line wraps and throws off a redraw. */\nfunction canDrawMascot(version: string, command: string): boolean {\n if (!isRichOutput() || !process.stdout.hasColors(256)) return false\n\n return stripVTControlCharacters(bannerIntro(version, 'open', command))\n .split('\\n')\n .every((line) => line.length <= process.stdout.columns)\n}\n\n/**\n * Whether a command opens with the mascot. Only the long-running ones do: `generate`, a Studio\n * session or pairing, and `add` or `update` while they ask questions. Quick commands print only\n * their result.\n */\nexport function wantsMascot({ commandPath, values }: { commandPath: ReadonlyArray<string>; values: Record<string, unknown> }): boolean {\n const [command, subCommand] = commandPath\n if (values.help || values.version) return false\n if (command === 'studio') return subCommand === undefined || subCommand === 'connect' || subCommand === 'login'\n if (command === 'add' || command === 'update' || command === 'init') return isInteractiveRun({ yes: values.yes, dryRun: values.dryRun ?? values['dry-run'] })\n\n return command === undefined || command === 'generate'\n}\n\n/**\n * The still Kubb mascot with the version and the running command, such as `studio connect`, or a\n * single version line where the terminal cannot draw it. Commands print it as their header; it\n * draws at once, with no wake-up frames.\n */\nexport function getBanner(version: string, command: string): string {\n return canDrawMascot(version, command) ? `\\n${bannerIntro(version, 'open', command)}` : `Kubb CLI v${version}`\n}\n\n/**\n * Opens `kubb generate` with the mascot playing its wake-up frames in place, which takes under a\n * second and overlaps the config load. Elsewhere the still {@link getBanner} is the header.\n */\nexport async function logBanner(version: string): Promise<void> {\n if (!canDrawMascot(version, 'generate')) {\n console.log(getBanner(version, 'generate'))\n\n return\n }\n\n console.log('')\n for (const [index, [expression, ms]] of wakeUp.entries()) {\n const frame = bannerIntro(version, expression, 'generate')\n if (index > 0) process.stdout.moveCursor(0, -frame.split('\\n').length)\n console.log(frame)\n await sleep(ms)\n }\n}\n","import process from 'node:process'\nimport { getErrorMessage, toError } from '@internals/utils'\nimport { checkCompatibility, Diagnostics, type ExtensionManifest, isRegistryEntry, type RegistryArtifact, type RegistryEntry } from '@kubb/core'\nimport { difference, isLessThan, isValid } from 'verkit'\n\nconst 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))\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `KUBB_REGISTRY must be an http(s) URL, got \"${url}\".`,\n help: 'Set `KUBB_REGISTRY` to an http(s) URL, or unset it to use https://kubb.dev/registry.',\n })\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))\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `\"${input}\" is not a registry id. Use owner/slug, such as kubb-labs/plugin-zod, or a slug, such as plugin-zod.`,\n })\n return input.includes('/') ? input : `kubb-labs/${input}`\n}\n\n/** The shortest id `kubb add` and `kubb update` accept: the slug for an official extension, else `owner/slug`. */\nexport function toShortId(id: string): string {\n return id.startsWith('kubb-labs/') ? id.slice('kubb-labs/'.length) : id\n}\n\n/**\n * GETs `url` as JSON. A non-2xx answer or a body that is not JSON returns no `body`.\n * A network error throws with the URL.\n */\nasync function fetchJSON(url: string): Promise<{ status: number; body?: unknown }> {\n let response: Response\n try {\n response = await globalThis.fetch(url, { headers: { accept: 'application/json' } })\n } catch (cause) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.inputUnreachable,\n severity: 'error',\n message: `Could not read ${url}: ${getErrorMessage(cause)}`,\n help: 'Check your network connection and that the registry is reachable.',\n cause: toError(cause),\n })\n }\n if (!response.ok) return { status: response.status }\n return { status: response.status, body: await response.json().catch(() => undefined) }\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 Diagnostics.Error({\n code: Diagnostics.code.inputRequestFailed,\n severity: 'error',\n message: `The registry at ${registry} sent an invalid index (HTTP ${status}).`,\n help: 'Try again later, or check that `KUBB_REGISTRY` points at a Kubb registry.',\n })\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\n/** `major`, `minor`, or `patch` from `installed` to `latest`, or `undefined` when either is unknown or invalid. */\nexport function bumpOf({ installed, latest }: { installed: string | undefined; latest: string }): 'major' | 'minor' | 'patch' | undefined {\n if (!installed || !isValid(installed) || !isValid(latest)) return undefined\n const kind = difference(installed, latest)\n if (!kind) return undefined\n if (kind.endsWith('major')) return 'major'\n return kind.endsWith('minor') ? 'minor' : 'patch'\n}\n\nfunction editDistance(a: string, b: string): number {\n const row = Array.from({ length: b.length + 1 }, (_, index) => index)\n for (let i = 1; i <= a.length; i++) {\n let previous = row[0]!\n row[0] = i\n for (let j = 1; j <= b.length; j++) {\n const current = row[j]!\n row[j] = Math.min(row[j]! + 1, row[j - 1]! + 1, previous + (a[i - 1] === b[j - 1] ? 0 : 1))\n previous = current\n }\n }\n return row[b.length]!\n}\n\n/** Words every extension shares, so they never make two ids look alike. */\nconst COMMON_TOKENS = new Set(['kubb', 'plugin', 'adapter', 'parser'])\n\n/**\n * The ids closest to a mistyped `input`, best first, at most three: those within a few edits of it,\n * or sharing a word such as `zod` in any order. Compares slugs, so the owner may be left out.\n */\nexport function closestIds({ input, ids }: { input: string; ids: Array<string> }): Array<string> {\n const slug = (id: string) => id.slice(id.indexOf('/') + 1)\n const tokens = new Set(\n slug(input)\n .split('-')\n .filter((token) => !COMMON_TOKENS.has(token)),\n )\n return ids\n .map((id) => ({\n id,\n distance: editDistance(slug(input), slug(id)),\n shared: slug(id)\n .split('-')\n .some((token) => tokens.has(token)),\n }))\n .filter(({ distance, shared }) => shared || distance <= Math.max(2, Math.floor(slug(input).length / 4)))\n .sort((a, b) => Number(b.shared) - Number(a.shared) || a.distance - b.distance)\n .slice(0, 3)\n .map(({ id }) => id)\n}\n"],"mappings":";;;;;;;;;;;AAMA,SAAS,YAAY,SAAiB,YAAwB,SAAyB;CACrF,OAAOA,cAAAA,SAAS;EAAE,OAAO;EAA0C,aAAa,QAAQ;EAAW;EAAS;CAAW,CAAC;AAC1H;;AAGA,SAAS,cAAc,SAAiB,SAA0B;CAChE,IAAI,CAACC,aAAAA,aAAa,KAAK,CAAC,QAAQ,OAAO,UAAU,GAAG,GAAG,OAAO;CAE9D,QAAA,GAAOC,UAAAA,yBAAAA,CAAyB,YAAY,SAAS,QAAQ,OAAO,CAAC,CAAC,CACnE,MAAM,IAAI,CAAC,CACX,OAAO,SAAS,KAAK,UAAU,QAAQ,OAAO,OAAO;AAC1D;;;;;;AAOA,SAAgB,YAAY,EAAE,aAAa,UAA4F;CACrI,MAAM,CAAC,SAAS,cAAc;CAC9B,IAAI,OAAO,QAAQ,OAAO,SAAS,OAAO;CAC1C,IAAI,YAAY,UAAU,OAAO,eAAe,KAAA,KAAa,eAAe,aAAa,eAAe;CACxG,IAAI,YAAY,SAAS,YAAY,YAAY,YAAY,QAAQ,OAAOC,aAAAA,iBAAiB;EAAE,KAAK,OAAO;EAAK,QAAQ,OAAO,UAAU,OAAO;CAAW,CAAC;CAE5J,OAAO,YAAY,KAAA,KAAa,YAAY;AAC9C;;;;;;AAOA,SAAgB,UAAU,SAAiB,SAAyB;CAClE,OAAO,cAAc,SAAS,OAAO,IAAI,KAAK,YAAY,SAAS,QAAQ,OAAO,MAAM,aAAa;AACvG;;;;;AAMA,eAAsB,UAAU,SAAgC;CAC9D,IAAI,CAAC,cAAc,SAAS,UAAU,GAAG;EACvC,QAAQ,IAAI,UAAU,SAAS,UAAU,CAAC;EAE1C;CACF;CAEA,QAAQ,IAAI,EAAE;CACd,KAAK,MAAM,CAAC,OAAO,CAAC,YAAY,QAAQC,cAAAA,OAAO,QAAQ,GAAG;EACxD,MAAM,QAAQ,YAAY,SAAS,YAAY,UAAU;EACzD,IAAI,QAAQ,GAAG,QAAQ,OAAO,WAAW,GAAG,CAAC,MAAM,MAAM,IAAI,CAAC,CAAC,MAAM;EACrE,QAAQ,IAAI,KAAK;EACjB,OAAA,GAAMC,qBAAAA,WAAAA,CAAM,EAAE;CAChB;AACF;;;ACvDA,MAAM,mBAAmB;AAEzB,MAAM,OAAO;AACb,MAAM,KAAK,IAAI,OAAO,IAAI,KAAK,MAAM,KAAK,IAAI;;AAG9C,SAAgB,cAAsB;CACpC,MAAM,MAAMC,aAAAA,QAAQ,IAAI,iBAAiB;CACzC,IAAI,CAAC,eAAe,KAAK,GAAG,GAC1B,MAAM,IAAIC,WAAAA,YAAY,MAAM;EAC1B,MAAMA,WAAAA,YAAY,KAAK;EACvB,UAAU;EACV,SAAS,8CAA8C,IAAI;EAC3D,MAAM;CACR,CAAC;CACH,OAAO,IAAI,QAAQ,QAAQ,EAAE;AAC/B;;;;;;AAOA,SAAgB,aAAa,OAAuB;CAClD,IAAI,CAAC,GAAG,KAAK,KAAK,GAChB,MAAM,IAAIA,WAAAA,YAAY,MAAM;EAC1B,MAAMA,WAAAA,YAAY,KAAK;EACvB,UAAU;EACV,SAAS,IAAI,MAAM;CACrB,CAAC;CACH,OAAO,MAAM,SAAS,GAAG,IAAI,QAAQ,aAAa;AACpD;;AAGA,SAAgB,UAAU,IAAoB;CAC5C,OAAO,GAAG,WAAW,YAAY,IAAI,GAAG,MAAM,EAAmB,IAAI;AACvE;;;;;AAMA,eAAe,UAAU,KAA0D;CACjF,IAAI;CACJ,IAAI;EACF,WAAW,MAAM,WAAW,MAAM,KAAK,EAAE,SAAS,EAAE,QAAQ,mBAAmB,EAAE,CAAC;CACpF,SAAS,OAAO;EACd,MAAM,IAAIA,WAAAA,YAAY,MAAM;GAC1B,MAAMA,WAAAA,YAAY,KAAK;GACvB,UAAU;GACV,SAAS,kBAAkB,IAAI,IAAIC,eAAAA,gBAAgB,KAAK;GACxD,MAAM;GACN,OAAOC,eAAAA,QAAQ,KAAK;EACtB,CAAC;CACH;CACA,IAAI,CAAC,SAAS,IAAI,OAAO,EAAE,QAAQ,SAAS,OAAO;CACnD,OAAO;EAAE,QAAQ,SAAS;EAAQ,MAAM,MAAM,SAAS,KAAK,CAAC,CAAC,YAAY,KAAA,CAAS;CAAE;AACvF;;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,IAAIF,WAAAA,YAAY,MAAM;EAC1B,MAAMA,WAAAA,YAAY,KAAK;EACvB,UAAU;EACV,SAAS,mBAAmB,SAAS,+BAA+B,OAAO;EAC3E,MAAM;CACR,CAAC;CAEH,OAAO,MAAM,WAAW,OAAOG,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,OAAOF,eAAAA,gBAAgB,KAAK;CAC9B;AACF;;;;;AAMA,SAAgB,WAAW,EAAE,WAAW,UAAsE;CAC5G,IAAI,EAAA,GAACG,OAAAA,QAAAA,CAAQ,MAAM,GAAG,OAAO;CAC7B,OAAO,CAAC,aAAa,EAAA,GAACA,OAAAA,QAAAA,CAAQ,SAAS,MAAA,GAAKC,OAAAA,WAAAA,CAAW,WAAW,MAAM;AAC1E;;AAGA,SAAgB,OAAO,EAAE,WAAW,UAAsG;CACxI,IAAI,CAAC,aAAa,EAAA,GAACD,OAAAA,QAAAA,CAAQ,SAAS,KAAK,EAAA,GAACA,OAAAA,QAAAA,CAAQ,MAAM,GAAG,OAAO,KAAA;CAClE,MAAM,QAAA,GAAOE,OAAAA,WAAAA,CAAW,WAAW,MAAM;CACzC,IAAI,CAAC,MAAM,OAAO,KAAA;CAClB,IAAI,KAAK,SAAS,OAAO,GAAG,OAAO;CACnC,OAAO,KAAK,SAAS,OAAO,IAAI,UAAU;AAC5C;AAEA,SAAS,aAAa,GAAW,GAAmB;CAClD,MAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,GAAG,UAAU,KAAK;CACpE,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;EAClC,IAAI,WAAW,IAAI;EACnB,IAAI,KAAK;EACT,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;GAClC,MAAM,UAAU,IAAI;GACpB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAM,GAAG,IAAI,IAAI,KAAM,GAAG,YAAY,EAAE,IAAI,OAAO,EAAE,IAAI,KAAK,IAAI,EAAE;GAC1F,WAAW;EACb;CACF;CACA,OAAO,IAAI,EAAE;AACf;;AAGA,MAAM,gCAAgB,IAAI,IAAI;CAAC;CAAQ;CAAU;CAAW;AAAQ,CAAC;;;;;AAMrE,SAAgB,WAAW,EAAE,OAAO,OAA6D;CAC/F,MAAM,QAAQ,OAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;CACzD,MAAM,SAAS,IAAI,IACjB,KAAK,KAAK,CAAC,CACR,MAAM,GAAG,CAAC,CACV,QAAQ,UAAU,CAAC,cAAc,IAAI,KAAK,CAAC,CAChD;CACA,OAAO,IACJ,KAAK,QAAQ;EACZ;EACA,UAAU,aAAa,KAAK,KAAK,GAAG,KAAK,EAAE,CAAC;EAC5C,QAAQ,KAAK,EAAE,CAAC,CACb,MAAM,GAAG,CAAC,CACV,MAAM,UAAU,OAAO,IAAI,KAAK,CAAC;CACtC,EAAE,CAAC,CACF,QAAQ,EAAE,UAAU,aAAa,UAAU,YAAY,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CACvG,MAAM,GAAG,MAAM,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,KAAK,EAAE,WAAW,EAAE,QAAQ,CAAC,CAC9E,MAAM,GAAG,CAAC,CAAC,CACX,KAAK,EAAE,SAAS,EAAE;AACvB"}
@@ -1,7 +1,7 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { a as getElapsedMs, i as formatMs } from "./Telemetry-CstxHeyx.js";
3
- import { a as readOutputFiles, d as formatMsWithColor, g as read, h as isPathInside, r as diffOutput, u as formatBar } from "./utils-BZYbuZTD.js";
4
- import { n as toPermissionFlag, p as writer, t as pluralize } from "./text-ul0IR1pq.js";
2
+ import { a as getElapsedMs, i as formatMs } from "./Telemetry-Bjn0mrII.js";
3
+ import { a as readOutputFiles, d as formatMsWithColor, g as read, h as isPathInside, r as diffOutput, u as formatBar } from "./utils-DnkrY3vN.js";
4
+ import { n as toPermissionFlag, p as writer, t as pluralize } from "./text-BbK3UX0I.js";
5
5
  import { styleText } from "node:util";
6
6
  import process from "node:process";
7
7
  import { readFile } from "node:fs/promises";
@@ -814,4 +814,4 @@ function selectReporters(reporters, names) {
814
814
  //#endregion
815
815
  export { setupReporters as n, selectReporters as t };
816
816
 
817
- //# sourceMappingURL=reporters-B4bdZbKM.js.map
817
+ //# sourceMappingURL=reporters-CqYdEotX.js.map