@kubb/cli 5.13.1 → 5.14.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 (60) hide show
  1. package/dist/{Telemetry-0Sr_THx9.cjs → Telemetry-CZmpqKZm.cjs} +2 -2
  2. package/dist/{Telemetry-0Sr_THx9.cjs.map → Telemetry-CZmpqKZm.cjs.map} +1 -1
  3. package/dist/{Telemetry-B4hk3xGv.js → Telemetry-DdoOJOS1.js} +2 -2
  4. package/dist/{Telemetry-B4hk3xGv.js.map → Telemetry-DdoOJOS1.js.map} +1 -1
  5. package/dist/{background-6xlebN_Y.cjs → background-BrIJU43S.cjs} +2 -2
  6. package/dist/{background-6xlebN_Y.cjs.map → background-BrIJU43S.cjs.map} +1 -1
  7. package/dist/{background-B7oEWLZs.js → background-Bu07csqw.js} +1 -1
  8. package/dist/{background-DY4LTodc.js → background-D-ujLRoU.js} +2 -2
  9. package/dist/{background-DY4LTodc.js.map → background-D-ujLRoU.js.map} +1 -1
  10. package/dist/index.cjs +22 -19
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.js +22 -19
  13. package/dist/index.js.map +1 -1
  14. package/dist/{registry-9AEIs-Cm.cjs → registry-DhrOLJFK.cjs} +3 -3
  15. package/dist/{registry-9AEIs-Cm.cjs.map → registry-DhrOLJFK.cjs.map} +1 -1
  16. package/dist/{registry-DLasg7du.js → registry-DwppRxUh.js} +3 -3
  17. package/dist/{registry-DLasg7du.js.map → registry-DwppRxUh.js.map} +1 -1
  18. package/dist/{reporters-xwOZPZ42.cjs → reporters-B1Di1RhB.cjs} +4 -4
  19. package/dist/{reporters-xwOZPZ42.cjs.map → reporters-B1Di1RhB.cjs.map} +1 -1
  20. package/dist/{reporters-BfeB9jOt.js → reporters-CWaaFAP-.js} +4 -4
  21. package/dist/{reporters-BfeB9jOt.js.map → reporters-CWaaFAP-.js.map} +1 -1
  22. package/dist/{run-C2syKtAg.cjs → run-7bCAra2a.cjs} +6 -6
  23. package/dist/{run-C2syKtAg.cjs.map → run-7bCAra2a.cjs.map} +1 -1
  24. package/dist/{run-kRFuEqeA.js → run-A2hHeAoZ.js} +7 -7
  25. package/dist/{run-kRFuEqeA.js.map → run-A2hHeAoZ.js.map} +1 -1
  26. package/dist/{run--OOU4YSR.js → run-BIa0e0jZ.js} +4 -4
  27. package/dist/{run--OOU4YSR.js.map → run-BIa0e0jZ.js.map} +1 -1
  28. package/dist/{run-C9Q5R-p9.js → run-CJQrSCAD.js} +1 -1
  29. package/dist/{run-DoUk-2Xb.js → run-CQC0pL1s.js} +2 -2
  30. package/dist/{run-DoUk-2Xb.js.map → run-CQC0pL1s.js.map} +1 -1
  31. package/dist/{run-Bgr0F6xv.cjs → run-CQELKG3I.cjs} +4 -4
  32. package/dist/{run-Bgr0F6xv.cjs.map → run-CQELKG3I.cjs.map} +1 -1
  33. package/dist/{run-w92b045L.cjs → run-ChCjDopB.cjs} +7 -7
  34. package/dist/{run-w92b045L.cjs.map → run-ChCjDopB.cjs.map} +1 -1
  35. package/dist/{run-BTzmKup3.cjs → run-CiFYHgVY.cjs} +2 -2
  36. package/dist/{run-BTzmKup3.cjs.map → run-CiFYHgVY.cjs.map} +1 -1
  37. package/dist/{run-BDmTZPT7.js → run-DH7hJn3s.js} +6 -6
  38. package/dist/{run-BDmTZPT7.js.map → run-DH7hJn3s.js.map} +1 -1
  39. package/dist/{snapshot-O36QFuVw.js → snapshot-BxMMyWLK.js} +6 -6
  40. package/dist/{snapshot-O36QFuVw.js.map → snapshot-BxMMyWLK.js.map} +1 -1
  41. package/dist/{snapshot-B4eWToMC.cjs → snapshot-Cr6KSlPW.cjs} +6 -6
  42. package/dist/{snapshot-B4eWToMC.cjs.map → snapshot-Cr6KSlPW.cjs.map} +1 -1
  43. package/dist/{status-C5_IHiDc.js → status-BdjS4SMJ.js} +3 -3
  44. package/dist/{status-C5_IHiDc.js.map → status-BdjS4SMJ.js.map} +1 -1
  45. package/dist/{status-CteZmcug.cjs → status-BkXcEOmp.cjs} +3 -3
  46. package/dist/{status-CteZmcug.cjs.map → status-BkXcEOmp.cjs.map} +1 -1
  47. package/dist/studioWorker.js +2 -2
  48. package/dist/{summary-BuKuPfE_.cjs → summary-BdvaJ0_J.cjs} +3 -3
  49. package/dist/{summary-BuKuPfE_.cjs.map → summary-BdvaJ0_J.cjs.map} +1 -1
  50. package/dist/{summary-B1aj8T_V.js → summary-DKqx3K4w.js} +3 -3
  51. package/dist/{summary-B1aj8T_V.js.map → summary-DKqx3K4w.js.map} +1 -1
  52. package/dist/{text-CaZG0KF2.js → text-BK8L4Xtr.js} +2 -2
  53. package/dist/{text-CaZG0KF2.js.map → text-BK8L4Xtr.js.map} +1 -1
  54. package/dist/{text-DVPYqR74.cjs → text-CtdDig0T.cjs} +2 -2
  55. package/dist/{text-DVPYqR74.cjs.map → text-CtdDig0T.cjs.map} +1 -1
  56. package/dist/{utils--q06lp55.js → utils-3TiGzYuZ.js} +3 -3
  57. package/dist/{utils--q06lp55.js.map → utils-3TiGzYuZ.js.map} +1 -1
  58. package/dist/{utils-Ckbz012p.cjs → utils-SIv7oWeS.cjs} +3 -3
  59. package/dist/{utils-Ckbz012p.cjs.map → utils-SIv7oWeS.cjs.map} +1 -1
  60. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"run-BDmTZPT7.js","names":["logLevel","logLevelMap"],"sources":["../src/runners/generate/run.ts"],"sourcesContent":["import path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport { formatMs, formatters, getElapsedMs, linters } 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 '../../ui/text.ts'\nimport setupReporters, { selectReporters } from '../../loggers/reporters.ts'\nimport { createPlainWriter } from '../../loggers/plainWriter.ts'\nimport { logIntro, logOutro, logSpacer, logTip } from '../../ui/intro.ts'\nimport { logError, logInfo, logStep, logWarn } from '../../ui/log.ts'\nimport { logBanner } from '../../ui/mascot.ts'\nimport { createSpinner } from '../../ui/spinner.ts'\nimport { getConfigs } from '../../config.ts'\nimport { isOutdated } from '../../utils/registry.ts'\nimport { type BuildDiff, type BuildSnapshot, diffBuilds, listenForKeys, startWatcher, trackBuild } 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, skips formatting, linting, and\n * post-generate commands, and prints what would change on disk.\n */\n dryRun?: boolean\n}\n\nexport async 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 await report({\n // A setup that threw leaves no driver, so read the configured plugins instead.\n plugins: kubb.config.plugins.flatMap((p) =>\n p && typeof p === 'object' ? [{ name: p.meta?.name ?? p.name ?? '', options: (p.options ?? {}) as Record<string, unknown> }] : [],\n ),\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\n/** The latest published version, `undefined` when the registry does not answer in time. Never rejects. */\nasync function fetchLatestVersion(): Promise<string | undefined> {\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 return data.version\n } catch {\n // Ignore network errors\n return undefined\n }\n}\n\nasync function checkForUpdate({ hooks, latest }: { hooks: Hookable<KubbHooks>; latest: Promise<string | undefined> }): Promise<void> {\n const latestVersion = await latest\n if (latestVersion && isOutdated({ installed: version, latest: latestVersion })) {\n await Diagnostics.emit(hooks, Diagnostics.update({ currentVersion: version, latestVersion }))\n }\n}\n\n/** Prints `Rebuilt in 1.2s · +1 schema -2 operations`, without the names part when the spec kept the same names. */\nfunction logRebuild({ diff: { schemas, operations }, durationMs }: { diff: BuildDiff; durationMs: number }): void {\n const specChange = [\n schemas.added && styleText('green', `+${pluralize(schemas.added, 'schema')}`),\n schemas.removed && styleText('red', `-${pluralize(schemas.removed, 'schema')}`),\n operations.added && styleText('green', `+${pluralize(operations.added, 'operation')}`),\n operations.removed && styleText('red', `-${pluralize(operations.removed, 'operation')}`),\n ]\n .filter(Boolean)\n .join(' ')\n logStep([`Rebuilt in ${formatMs(durationMs)}`, specChange].filter(Boolean).join(styleText('dim', ' · ')))\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 // Started first so the registry request overlaps the banner and the config load.\n const latest = fetchLatestVersion()\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 json = requestedNames.includes('json')\n const quiet = logLevel <= logLevelMap.silent || json\n\n // Errors raised outside a build have no report entry. In `json` mode they go to a stderr logger,\n // so they are never silent and stdout stays one JSON document.\n const errorHooks = json ? new Hookable<KubbHooks>() : hooks\n if (json) setupReporters(errorHooks, { logLevel, reporters: [cliReporter], writer: createPlainWriter(console.error) })\n\n // The config loads while the banner plays; the output still prints in order once the banner is done.\n const banner = quiet ? undefined : logBanner(version)\n const loading = getConfigs({\n configPath,\n input,\n watch,\n logLevel: logLevelKey as CLIOptions['logLevel'],\n })\n // Handled below; this keeps a rejection during the banner from counting as unhandled.\n loading.catch(() => undefined)\n await banner\n\n if (!quiet) {\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 loading\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 if (!json) 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 await Diagnostics.emit(errorHooks, error)\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, dryRun })\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, latest })\n\n if (!quiet) logOutro(`${pluralize(configs.length, 'config')} ready`)\n\n try {\n let anyFailed = false\n // One tracker, one key listener and one build queue serve every watched config, so several configs never mix diffs or answer `r` twice.\n const tracker = watch ? trackBuild(hooks) : undefined\n const rebuilds: Array<() => Promise<void>> = []\n let armKeys: (() => void) | undefined\n // Configs share the hooks emitter, so every build, from any watcher or the `r` key, waits for the one before it.\n let queue = Promise.resolve()\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' ? (effectiveInput as string) : undefined\n if (watchPath && tracker) {\n const label = styleText('yellow', `Watching ${path.relative(process.cwd(), watchPath)}`)\n let previous: BuildSnapshot | undefined\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 () => {\n const hrStart = process.hrtime()\n const succeeded = await generate({ input, config, hooks, dryRun })\n const snapshot = tracker.take()\n if (previous) logRebuild({ diff: diffBuilds(previous, snapshot), durationMs: getElapsedMs(hrStart) })\n previous = snapshot\n\n logStep(armKeys ? `${label} ${styleText('dim', 'r rebuild · q quit')}` : label)\n armKeys?.()\n if (succeeded) {\n logSpacer()\n logTip()\n }\n }\n // A trigger that lands while this config's build is queued joins it; one that lands during the build queues one more. Never rejects.\n let pending = false\n const rebuild = (): Promise<void> => {\n if (pending) return queue\n pending = true\n queue = queue\n .then(() => {\n pending = false\n return build()\n })\n .catch((error) => void Diagnostics.emit(errorHooks, error))\n return queue\n }\n rebuilds.push(rebuild)\n if (!quiet) {\n armKeys ??= listenForKeys({\n rebuild: () => rebuilds.forEach((trigger) => void trigger()),\n quit: (code) => void Promise.resolve(hooks.callHook('kubb:lifecycle:end')).finally(() => process.exit(code)),\n })\n }\n\n // The watcher ignores its startup state, so run the first build here; a failing one keeps watching so the user can fix the input.\n await rebuild()\n\n await startWatcher([watchPath], rebuild, { info: logInfo, error: logError })\n } else {\n if (tracker && !quiet) logWarn('Watch mode only follows a local `input` file, so this config is generated once.')\n try {\n const succeeded = await generate({ input, config, hooks, dryRun })\n if (!succeeded) anyFailed = true\n } catch (configError) {\n await Diagnostics.emit(errorHooks, 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 Diagnostics.emit(errorHooks, error)\n process.exit(1)\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"run-DH7hJn3s.js","names":["logLevel","logLevelMap"],"sources":["../src/runners/generate/run.ts"],"sourcesContent":["import path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport { formatMs, formatters, getElapsedMs, linters } 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 '../../ui/text.ts'\nimport setupReporters, { selectReporters } from '../../loggers/reporters.ts'\nimport { createPlainWriter } from '../../loggers/plainWriter.ts'\nimport { logIntro, logOutro, logSpacer, logTip } from '../../ui/intro.ts'\nimport { logError, logInfo, logStep, logWarn } from '../../ui/log.ts'\nimport { logBanner } from '../../ui/mascot.ts'\nimport { createSpinner } from '../../ui/spinner.ts'\nimport { getConfigs } from '../../config.ts'\nimport { isOutdated } from '../../utils/registry.ts'\nimport { type BuildDiff, type BuildSnapshot, diffBuilds, listenForKeys, startWatcher, trackBuild } 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, skips formatting, linting, and\n * post-generate commands, and prints what would change on disk.\n */\n dryRun?: boolean\n}\n\nexport async 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 await report({\n // A setup that threw leaves no driver, so read the configured plugins instead.\n plugins: kubb.config.plugins.flatMap((p) =>\n p && typeof p === 'object' ? [{ name: p.meta?.name ?? p.name ?? '', options: (p.options ?? {}) as Record<string, unknown> }] : [],\n ),\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\n/** The latest published version, `undefined` when the registry does not answer in time. Never rejects. */\nasync function fetchLatestVersion(): Promise<string | undefined> {\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 return data.version\n } catch {\n // Ignore network errors\n return undefined\n }\n}\n\nasync function checkForUpdate({ hooks, latest }: { hooks: Hookable<KubbHooks>; latest: Promise<string | undefined> }): Promise<void> {\n const latestVersion = await latest\n if (latestVersion && isOutdated({ installed: version, latest: latestVersion })) {\n await Diagnostics.emit(hooks, Diagnostics.update({ currentVersion: version, latestVersion }))\n }\n}\n\n/** Prints `Rebuilt in 1.2s · +1 schema -2 operations`, without the names part when the spec kept the same names. */\nfunction logRebuild({ diff: { schemas, operations }, durationMs }: { diff: BuildDiff; durationMs: number }): void {\n const specChange = [\n schemas.added && styleText('green', `+${pluralize(schemas.added, 'schema')}`),\n schemas.removed && styleText('red', `-${pluralize(schemas.removed, 'schema')}`),\n operations.added && styleText('green', `+${pluralize(operations.added, 'operation')}`),\n operations.removed && styleText('red', `-${pluralize(operations.removed, 'operation')}`),\n ]\n .filter(Boolean)\n .join(' ')\n logStep([`Rebuilt in ${formatMs(durationMs)}`, specChange].filter(Boolean).join(styleText('dim', ' · ')))\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 // Started first so the registry request overlaps the banner and the config load.\n const latest = fetchLatestVersion()\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 json = requestedNames.includes('json')\n const quiet = logLevel <= logLevelMap.silent || json\n\n // Errors raised outside a build have no report entry. In `json` mode they go to a stderr logger,\n // so they are never silent and stdout stays one JSON document.\n const errorHooks = json ? new Hookable<KubbHooks>() : hooks\n if (json) setupReporters(errorHooks, { logLevel, reporters: [cliReporter], writer: createPlainWriter(console.error) })\n\n // The config loads while the banner plays; the output still prints in order once the banner is done.\n const banner = quiet ? undefined : logBanner(version)\n const loading = getConfigs({\n configPath,\n input,\n watch,\n logLevel: logLevelKey as CLIOptions['logLevel'],\n })\n // Handled below; this keeps a rejection during the banner from counting as unhandled.\n loading.catch(() => undefined)\n await banner\n\n if (!quiet) {\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 loading\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 if (!json) 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 await Diagnostics.emit(errorHooks, error)\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, dryRun })\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, latest })\n\n if (!quiet) logOutro(`${pluralize(configs.length, 'config')} ready`)\n\n try {\n let anyFailed = false\n // One tracker, one key listener and one build queue serve every watched config, so several configs never mix diffs or answer `r` twice.\n const tracker = watch ? trackBuild(hooks) : undefined\n const rebuilds: Array<() => Promise<void>> = []\n let armKeys: (() => void) | undefined\n // Configs share the hooks emitter, so every build, from any watcher or the `r` key, waits for the one before it.\n let queue = Promise.resolve()\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' ? (effectiveInput as string) : undefined\n if (watchPath && tracker) {\n const label = styleText('yellow', `Watching ${path.relative(process.cwd(), watchPath)}`)\n let previous: BuildSnapshot | undefined\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 () => {\n const hrStart = process.hrtime()\n const succeeded = await generate({ input, config, hooks, dryRun })\n const snapshot = tracker.take()\n if (previous) logRebuild({ diff: diffBuilds(previous, snapshot), durationMs: getElapsedMs(hrStart) })\n previous = snapshot\n\n logStep(armKeys ? `${label} ${styleText('dim', 'r rebuild · q quit')}` : label)\n armKeys?.()\n if (succeeded) {\n logSpacer()\n logTip()\n }\n }\n // A trigger that lands while this config's build is queued joins it; one that lands during the build queues one more. Never rejects.\n let pending = false\n const rebuild = (): Promise<void> => {\n if (pending) return queue\n pending = true\n queue = queue\n .then(() => {\n pending = false\n return build()\n })\n .catch((error) => void Diagnostics.emit(errorHooks, error))\n return queue\n }\n rebuilds.push(rebuild)\n if (!quiet) {\n armKeys ??= listenForKeys({\n rebuild: () => rebuilds.forEach((trigger) => void trigger()),\n quit: (code) => void Promise.resolve(hooks.callHook('kubb:lifecycle:end')).finally(() => process.exit(code)),\n })\n }\n\n // The watcher ignores its startup state, so run the first build here; a failing one keeps watching so the user can fix the input.\n await rebuild()\n\n await startWatcher([watchPath], rebuild, { info: logInfo, error: logError })\n } else {\n if (tracker && !quiet) logWarn('Watch mode only follows a local `input` file, so this config is generated once.')\n try {\n const succeeded = await generate({ input, config, hooks, dryRun })\n if (!succeeded) anyFailed = true\n } catch (configError) {\n await Diagnostics.emit(errorHooks, 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 Diagnostics.emit(errorHooks, error)\n process.exit(1)\n }\n}\n"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { a as getElapsedMs, i as formatMs } from "./Telemetry-B4hk3xGv.js";
3
- import { c as runStudio, i as loadConfigs } from "./run-kRFuEqeA.js";
4
- import { g as read } from "./utils--q06lp55.js";
5
- import { m as createPlainWriter, t as pluralize } from "./text-CaZG0KF2.js";
6
- import { n as setupReporters } from "./reporters-BfeB9jOt.js";
2
+ import { a as getElapsedMs, i as formatMs } from "./Telemetry-DdoOJOS1.js";
3
+ import { c as runStudio, i as loadConfigs } from "./run-A2hHeAoZ.js";
4
+ import { g as read } from "./utils-3TiGzYuZ.js";
5
+ import { m as createPlainWriter, t as pluralize } from "./text-BK8L4Xtr.js";
6
+ import { n as setupReporters } from "./reporters-CWaaFAP-.js";
7
7
  import { styleText } from "node:util";
8
8
  import process from "node:process";
9
9
  import { dirname, join } from "node:path";
@@ -247,4 +247,4 @@ const runner = ({ values }) => runStudio(values, (options) => snapshot({
247
247
  //#endregion
248
248
  export { runner };
249
249
 
250
- //# sourceMappingURL=snapshot-O36QFuVw.js.map
250
+ //# sourceMappingURL=snapshot-BxMMyWLK.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot-O36QFuVw.js","names":["logLevel","logLevelMap"],"sources":["../src/runners/studio/ci.ts","../src/runners/studio/snapshot.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport process from 'node:process'\n\n/**\n * Stable identity for the CI agent a snapshot run registers or reuses.\n */\nexport type CiContext = {\n /**\n * Fed into the machine token, so the same merge or pull request reuses one agent.\n */\n id: string\n /**\n * Agent display name shown in Studio.\n */\n name: string\n /** The commit this run builds, so the next snapshot can diff against it. */\n commit?: string\n /** The branch a pull request merges into, and the `id` runs on that branch register under. */\n base?: { branch: string; id: string }\n}\n\ntype GithubPullRequest = { number: number; head?: { sha?: string }; base?: { ref?: string } }\n\nfunction readGithubPullRequest(eventPath: string | undefined): GithubPullRequest | undefined {\n if (!eventPath) {\n return undefined\n }\n\n try {\n const event = JSON.parse(readFileSync(eventPath, 'utf8')) as { pull_request?: GithubPullRequest }\n return event.pull_request?.number ? event.pull_request : undefined\n } catch {\n return undefined\n }\n}\n\n/** Reproduces GitLab's `CI_COMMIT_REF_SLUG` for a branch it gives no slug of, like a merge request's target. */\nexport function gitlabRefSlug(ref: string): string {\n return ref\n .toLowerCase()\n .replace(/[^a-z0-9]/gu, '-')\n .slice(0, 63)\n .replace(/^-+|-+$/g, '')\n}\n\n/**\n * Detects the CI provider from its environment variables and derives a stable identity from it.\n * The GitHub row reproduces `gh:<repositoryId>:<prNumber>`, the identity `kubb-labs/action` has\n * always registered agents under, so an existing repository keeps reusing its agent.\n */\nexport function detectCi(env: Record<string, string | undefined> = process.env): CiContext | null {\n if (env.GITHUB_ACTIONS) {\n const pullRequest = readGithubPullRequest(env.GITHUB_EVENT_PATH)\n const repositoryId = env.GITHUB_REPOSITORY_ID ?? env.GITHUB_REPOSITORY ?? ''\n const branch = env.GITHUB_REF?.startsWith('refs/heads/') ? env.GITHUB_REF.slice('refs/heads/'.length) : undefined\n // A branch run is scoped by its ref, which a pull request number never collides with.\n const scope = pullRequest?.number ?? (branch ? `refs/heads/${branch}` : env.GITHUB_RUN_ID) ?? ''\n const baseBranch = pullRequest?.base?.ref\n\n return {\n id: `gh:${repositoryId}:${scope}`,\n name: `${env.GITHUB_REPOSITORY ?? 'github'}#${pullRequest?.number ?? branch ?? scope}`,\n // The head commit, not the merge commit a pull request run checks out.\n commit: pullRequest?.head?.sha ?? env.GITHUB_SHA,\n base: baseBranch ? { branch: baseBranch, id: `gh:${repositoryId}:refs/heads/${baseBranch}` } : undefined,\n }\n }\n\n if (env.GITLAB_CI) {\n const scope = env.CI_MERGE_REQUEST_IID ?? env.CI_COMMIT_REF_SLUG ?? ''\n const baseBranch = env.CI_MERGE_REQUEST_TARGET_BRANCH_NAME\n\n return {\n id: `gl:${env.CI_PROJECT_ID ?? ''}:${scope}`,\n name: `${env.CI_PROJECT_PATH ?? 'gitlab'}#${scope}`,\n commit: env.CI_MERGE_REQUEST_SOURCE_BRANCH_SHA || env.CI_COMMIT_SHA,\n base: baseBranch ? { branch: baseBranch, id: `gl:${env.CI_PROJECT_ID ?? ''}:${gitlabRefSlug(baseBranch)}` } : undefined,\n }\n }\n\n if (env.BITBUCKET_BUILD_NUMBER) {\n const scope = env.BITBUCKET_PR_ID ?? env.BITBUCKET_BRANCH ?? ''\n\n return { id: `bb:${env.BITBUCKET_REPO_UUID ?? ''}:${scope}`, name: `${env.BITBUCKET_REPO_FULL_NAME ?? 'bitbucket'}#${scope}`, commit: env.BITBUCKET_COMMIT }\n }\n\n if (env.CIRCLECI) {\n // Owner-qualified: two projects with the same name under different CircleCI orgs must not\n // collide on one agent, since registering it purges the other project's live sessions.\n const owner = env.CIRCLE_PROJECT_USERNAME ?? ''\n const project = env.CIRCLE_PROJECT_REPONAME ?? 'circleci'\n const scope = env.CIRCLE_PR_NUMBER ?? env.CIRCLE_BRANCH ?? ''\n\n return { id: `circle:${owner}:${project}:${scope}`, name: `${owner ? `${owner}/` : ''}${project}#${scope}`, commit: env.CIRCLE_SHA1 }\n }\n\n return null\n}\n","import { dirname, join } from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport { formatMs, getElapsedMs, read } from '@internals/utils'\nimport { cliReporter, Diagnostics, Hookable, type KubbHooks, logLevel as logLevelMap } from '@kubb/core'\nimport { createSnapshot } from '@kubb/studio'\nimport type { BranchSnapshotChanges, PublishedSnapshot, SnapshotChanges } from '@kubb/studio/protocol'\nimport { pluralize } from '../../ui/text.ts'\nimport { createPlainWriter } from '../../loggers/plainWriter.ts'\nimport setupReporters from '../../loggers/reporters.ts'\nimport { type CiContext, detectCi } from './ci.ts'\nimport { loadConfigs, runStudio, type SnapshotOptions } from './run.ts'\nimport type { command } from '../../commands/studio/snapshot.ts'\nimport type { CommandRunner } from 'gunshi'\n\n/**\n * Walks up from `directory` to the first package.json with a name and a version.\n */\nasync function findPackageJson(directory: string): Promise<{ name: string; version: string }> {\n const packageJson = JSON.parse(await read(join(directory, 'package.json')).catch(() => '{}')) as Partial<{ name: string; version: string }>\n if (packageJson.name && packageJson.version) return { name: packageJson.name, version: packageJson.version }\n\n const parent = dirname(directory)\n if (parent === directory)\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `No package.json with a name and a version found above ${process.cwd()}`,\n help: 'Pass `--name` and `--version`, or run from a package with a package.json.',\n })\n\n return findPackageJson(parent)\n}\n\nfunction resolveCiIdentity(options: SnapshotOptions): CiContext {\n const detected = detectCi()\n // A custom --id drops the detected base, since runs on that branch may use a custom id too.\n const ci = options.id ? { id: options.id, name: detected?.name ?? options.id, commit: detected?.commit } : detected\n\n if (!ci) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'Could not detect a supported CI provider (GitHub Actions, GitLab CI, Bitbucket Pipelines, CircleCI). Pass --id.',\n })\n }\n\n // An explicit --base-id may not name a branch, so it labels the comparison itself.\n const base = options.baseId ? { branch: options.baseId, id: options.baseId } : ci.base\n\n return { ...ci, base: base?.id === ci.id ? undefined : base }\n}\n\nfunction absoluteUrl(studioUrl: string, path: string): string {\n return new URL(path, `${studioUrl}/`).toString()\n}\n\ntype SnapshotResult = {\n id: string\n /** Sequence number on the CI agent, when Studio sends one. */\n number?: number\n name: string | null\n version: string | null\n integrity: string | null\n url: string\n snapshotIdUrl: string\n /** Studio page of the snapshot, when Studio sends one. */\n webUrl?: string\n expiresAt: string\n agentUrl: string\n /** What changed since the previous snapshot of this package on this agent. */\n changes?: SnapshotChanges\n /** What differs from the latest snapshot of the base branch, named by `branch`. */\n branchChanges?: BranchSnapshotChanges & { branch: string }\n}\n\nfunction toResult({ studioUrl, snapshot, ci }: { studioUrl: string; snapshot: PublishedSnapshot; ci: CiContext }): SnapshotResult {\n return {\n id: snapshot.id,\n number: snapshot.number,\n name: snapshot.name,\n version: snapshot.version,\n integrity: snapshot.integrity,\n url: absoluteUrl(studioUrl, snapshot.url),\n snapshotIdUrl: absoluteUrl(studioUrl, snapshot.snapshotIdUrl),\n webUrl: snapshot.webUrl ? absoluteUrl(studioUrl, snapshot.webUrl) : undefined,\n expiresAt: snapshot.expiresAt,\n agentUrl: absoluteUrl(studioUrl, `/agents/${snapshot.agent.slug ?? snapshot.agent.id}`),\n changes: snapshot.changes,\n branchChanges: snapshot.branchChanges && ci.base ? { ...snapshot.branchChanges, branch: ci.base.branch } : undefined,\n }\n}\n\n/** How many files differ, `against` what. */\nfunction describeChanges(changes: SnapshotChanges, against: string): string {\n const { added, changed, removed } = changes\n const parts = [\n added.length && `+${pluralize(added.length, 'file')}`,\n changed.length && `~${changed.length} changed`,\n removed.length && `-${removed.length} removed`,\n ].filter(Boolean)\n\n return parts.length ? `${parts.join(' ')} ${against}` : `No changes ${against}`\n}\n\n/** One summary line: how many files changed, and since which run. */\nexport function formatChanges(changes: SnapshotChanges): string {\n if (!changes.base) {\n return 'First snapshot'\n }\n const { number, commit, createdAt } = changes.base\n\n return describeChanges(changes, `vs ${number ? `#${number}` : (commit?.slice(0, 7) ?? createdAt)}`)\n}\n\n/** One summary line: how the snapshot differs from the base branch's latest one. */\nexport function formatBranchChanges(changes: BranchSnapshotChanges & { branch: string }): string {\n if (changes.base) return describeChanges(changes, `vs ${changes.branch}`)\n\n return changes.baseFound ? `No snapshot of ${changes.branch} for this package yet` : `No snapshot of ${changes.branch} to compare with`\n}\n\nfunction printSummary(result: SnapshotResult): void {\n const row = (label: string, value: string) => ` ${styleText('dim', label.padEnd(7))} ${value}`\n\n console.log(\n [\n '',\n ...(result.webUrl ? [row('View', styleText('cyan', result.webUrl))] : []),\n ...(result.changes ? [row('Diff', formatChanges(result.changes))] : []),\n ...(result.branchChanges ? [row('Branch', formatBranchChanges(result.branchChanges))] : []),\n row('Use', `npm i ${result.url}`),\n row('Expires', result.expiresAt.slice(0, 10)),\n ].join('\\n'),\n )\n}\n\n/**\n * Generates the project, packs it, and publishes it to Kubb Studio in one request, under the CI\n * agent the run's identity names.\n */\nexport async function snapshot(options: SnapshotOptions): Promise<void> {\n const token = options.token ?? process.env.KUBB_TOKEN\n if (!token) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'An organization CI API key is required. Pass --token or set KUBB_TOKEN.',\n })\n }\n // A snapshot publishes the first entry.\n const config = (await loadConfigs(options)).configs[0]!\n const ci = resolveCiIdentity(options)\n // package.json is read only for whichever of name/version --name and --version did not supply.\n const { name, version: packageVersion } =\n options.name && options.packageVersion\n ? { name: options.name, version: options.packageVersion }\n : await findPackageJson(process.cwd()).then((found) => ({ name: options.name ?? found.name, version: options.packageVersion ?? found.version }))\n const logLevel = logLevelMap[options.logLevel ?? 'info']\n\n const write = options.json ? (line: string) => console.error(line) : (line: string) => console.log(line)\n const hooks = new Hookable<KubbHooks>()\n // The steps below are the CI log; the run's own per-file output only shows when asked for with --log-level verbose.\n setupReporters(hooks, { logLevel: logLevel > logLevelMap.info ? logLevel : logLevelMap.silent, reporters: [cliReporter], writer: createPlainWriter(write) })\n const step = (message: string) => {\n if (logLevel > logLevelMap.silent) {\n write(message)\n }\n }\n\n hooks.hook('kubb:generation:end', ({ filesCreated = 0, status, hrStart }) => {\n if (status !== 'failed' && hrStart) step(`✓ Generated ${pluralize(filesCreated, 'file')} in ${formatMs(getElapsedMs(hrStart))}`)\n })\n\n try {\n const published = await createSnapshot({\n studioUrl: options.studioUrl,\n apiKey: token,\n config,\n hooks,\n id: ci.id,\n name: ci.name,\n packageName: name,\n version: packageVersion,\n commit: ci.commit,\n baseId: ci.base?.id,\n })\n const result = toResult({ studioUrl: options.studioUrl, snapshot: published, ci })\n\n step(`✓ Packed ${result.name ?? name}@${result.version ?? packageVersion}`)\n step(`✓ Published snapshot ${result.number ? `#${result.number}` : result.id} for ${ci.name}${ci.commit ? `@${ci.commit.slice(0, 7)}` : ''}`)\n\n if (options.json) console.log(JSON.stringify(result))\n else printSummary(result)\n } catch (error) {\n step('✖ Snapshot failed')\n throw error\n }\n}\n\nexport const runner: CommandRunner<{ args: typeof command.args; extensions: {} }> = ({ values }) =>\n runStudio(\n values,\n (options) =>\n snapshot({\n ...options,\n token: values.token,\n id: values.id,\n baseId: values.baseId,\n name: values.name,\n packageVersion: values.packageVersion,\n json: values.json,\n }),\n { json: values.json },\n )\n"],"mappings":"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"}
1
+ {"version":3,"file":"snapshot-BxMMyWLK.js","names":["logLevel","logLevelMap"],"sources":["../src/runners/studio/ci.ts","../src/runners/studio/snapshot.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport process from 'node:process'\n\n/**\n * Stable identity for the CI agent a snapshot run registers or reuses.\n */\nexport type CiContext = {\n /**\n * Fed into the machine token, so the same merge or pull request reuses one agent.\n */\n id: string\n /**\n * Agent display name shown in Studio.\n */\n name: string\n /** The commit this run builds, so the next snapshot can diff against it. */\n commit?: string\n /** The branch a pull request merges into, and the `id` runs on that branch register under. */\n base?: { branch: string; id: string }\n}\n\ntype GithubPullRequest = { number: number; head?: { sha?: string }; base?: { ref?: string } }\n\nfunction readGithubPullRequest(eventPath: string | undefined): GithubPullRequest | undefined {\n if (!eventPath) {\n return undefined\n }\n\n try {\n const event = JSON.parse(readFileSync(eventPath, 'utf8')) as { pull_request?: GithubPullRequest }\n return event.pull_request?.number ? event.pull_request : undefined\n } catch {\n return undefined\n }\n}\n\n/** Reproduces GitLab's `CI_COMMIT_REF_SLUG` for a branch it gives no slug of, like a merge request's target. */\nexport function gitlabRefSlug(ref: string): string {\n return ref\n .toLowerCase()\n .replace(/[^a-z0-9]/gu, '-')\n .slice(0, 63)\n .replace(/^-+|-+$/g, '')\n}\n\n/**\n * Detects the CI provider from its environment variables and derives a stable identity from it.\n * The GitHub row reproduces `gh:<repositoryId>:<prNumber>`, the identity `kubb-labs/action` has\n * always registered agents under, so an existing repository keeps reusing its agent.\n */\nexport function detectCi(env: Record<string, string | undefined> = process.env): CiContext | null {\n if (env.GITHUB_ACTIONS) {\n const pullRequest = readGithubPullRequest(env.GITHUB_EVENT_PATH)\n const repositoryId = env.GITHUB_REPOSITORY_ID ?? env.GITHUB_REPOSITORY ?? ''\n const branch = env.GITHUB_REF?.startsWith('refs/heads/') ? env.GITHUB_REF.slice('refs/heads/'.length) : undefined\n // A branch run is scoped by its ref, which a pull request number never collides with.\n const scope = pullRequest?.number ?? (branch ? `refs/heads/${branch}` : env.GITHUB_RUN_ID) ?? ''\n const baseBranch = pullRequest?.base?.ref\n\n return {\n id: `gh:${repositoryId}:${scope}`,\n name: `${env.GITHUB_REPOSITORY ?? 'github'}#${pullRequest?.number ?? branch ?? scope}`,\n // The head commit, not the merge commit a pull request run checks out.\n commit: pullRequest?.head?.sha ?? env.GITHUB_SHA,\n base: baseBranch ? { branch: baseBranch, id: `gh:${repositoryId}:refs/heads/${baseBranch}` } : undefined,\n }\n }\n\n if (env.GITLAB_CI) {\n const scope = env.CI_MERGE_REQUEST_IID ?? env.CI_COMMIT_REF_SLUG ?? ''\n const baseBranch = env.CI_MERGE_REQUEST_TARGET_BRANCH_NAME\n\n return {\n id: `gl:${env.CI_PROJECT_ID ?? ''}:${scope}`,\n name: `${env.CI_PROJECT_PATH ?? 'gitlab'}#${scope}`,\n commit: env.CI_MERGE_REQUEST_SOURCE_BRANCH_SHA || env.CI_COMMIT_SHA,\n base: baseBranch ? { branch: baseBranch, id: `gl:${env.CI_PROJECT_ID ?? ''}:${gitlabRefSlug(baseBranch)}` } : undefined,\n }\n }\n\n if (env.BITBUCKET_BUILD_NUMBER) {\n const scope = env.BITBUCKET_PR_ID ?? env.BITBUCKET_BRANCH ?? ''\n\n return { id: `bb:${env.BITBUCKET_REPO_UUID ?? ''}:${scope}`, name: `${env.BITBUCKET_REPO_FULL_NAME ?? 'bitbucket'}#${scope}`, commit: env.BITBUCKET_COMMIT }\n }\n\n if (env.CIRCLECI) {\n // Owner-qualified: two projects with the same name under different CircleCI orgs must not\n // collide on one agent, since registering it purges the other project's live sessions.\n const owner = env.CIRCLE_PROJECT_USERNAME ?? ''\n const project = env.CIRCLE_PROJECT_REPONAME ?? 'circleci'\n const scope = env.CIRCLE_PR_NUMBER ?? env.CIRCLE_BRANCH ?? ''\n\n return { id: `circle:${owner}:${project}:${scope}`, name: `${owner ? `${owner}/` : ''}${project}#${scope}`, commit: env.CIRCLE_SHA1 }\n }\n\n return null\n}\n","import { dirname, join } from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport { formatMs, getElapsedMs, read } from '@internals/utils'\nimport { cliReporter, Diagnostics, Hookable, type KubbHooks, logLevel as logLevelMap } from '@kubb/core'\nimport { createSnapshot } from '@kubb/studio'\nimport type { BranchSnapshotChanges, PublishedSnapshot, SnapshotChanges } from '@kubb/studio/protocol'\nimport { pluralize } from '../../ui/text.ts'\nimport { createPlainWriter } from '../../loggers/plainWriter.ts'\nimport setupReporters from '../../loggers/reporters.ts'\nimport { type CiContext, detectCi } from './ci.ts'\nimport { loadConfigs, runStudio, type SnapshotOptions } from './run.ts'\nimport type { command } from '../../commands/studio/snapshot.ts'\nimport type { CommandRunner } from 'gunshi'\n\n/**\n * Walks up from `directory` to the first package.json with a name and a version.\n */\nasync function findPackageJson(directory: string): Promise<{ name: string; version: string }> {\n const packageJson = JSON.parse(await read(join(directory, 'package.json')).catch(() => '{}')) as Partial<{ name: string; version: string }>\n if (packageJson.name && packageJson.version) return { name: packageJson.name, version: packageJson.version }\n\n const parent = dirname(directory)\n if (parent === directory)\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `No package.json with a name and a version found above ${process.cwd()}`,\n help: 'Pass `--name` and `--version`, or run from a package with a package.json.',\n })\n\n return findPackageJson(parent)\n}\n\nfunction resolveCiIdentity(options: SnapshotOptions): CiContext {\n const detected = detectCi()\n // A custom --id drops the detected base, since runs on that branch may use a custom id too.\n const ci = options.id ? { id: options.id, name: detected?.name ?? options.id, commit: detected?.commit } : detected\n\n if (!ci) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'Could not detect a supported CI provider (GitHub Actions, GitLab CI, Bitbucket Pipelines, CircleCI). Pass --id.',\n })\n }\n\n // An explicit --base-id may not name a branch, so it labels the comparison itself.\n const base = options.baseId ? { branch: options.baseId, id: options.baseId } : ci.base\n\n return { ...ci, base: base?.id === ci.id ? undefined : base }\n}\n\nfunction absoluteUrl(studioUrl: string, path: string): string {\n return new URL(path, `${studioUrl}/`).toString()\n}\n\ntype SnapshotResult = {\n id: string\n /** Sequence number on the CI agent, when Studio sends one. */\n number?: number\n name: string | null\n version: string | null\n integrity: string | null\n url: string\n snapshotIdUrl: string\n /** Studio page of the snapshot, when Studio sends one. */\n webUrl?: string\n expiresAt: string\n agentUrl: string\n /** What changed since the previous snapshot of this package on this agent. */\n changes?: SnapshotChanges\n /** What differs from the latest snapshot of the base branch, named by `branch`. */\n branchChanges?: BranchSnapshotChanges & { branch: string }\n}\n\nfunction toResult({ studioUrl, snapshot, ci }: { studioUrl: string; snapshot: PublishedSnapshot; ci: CiContext }): SnapshotResult {\n return {\n id: snapshot.id,\n number: snapshot.number,\n name: snapshot.name,\n version: snapshot.version,\n integrity: snapshot.integrity,\n url: absoluteUrl(studioUrl, snapshot.url),\n snapshotIdUrl: absoluteUrl(studioUrl, snapshot.snapshotIdUrl),\n webUrl: snapshot.webUrl ? absoluteUrl(studioUrl, snapshot.webUrl) : undefined,\n expiresAt: snapshot.expiresAt,\n agentUrl: absoluteUrl(studioUrl, `/agents/${snapshot.agent.slug ?? snapshot.agent.id}`),\n changes: snapshot.changes,\n branchChanges: snapshot.branchChanges && ci.base ? { ...snapshot.branchChanges, branch: ci.base.branch } : undefined,\n }\n}\n\n/** How many files differ, `against` what. */\nfunction describeChanges(changes: SnapshotChanges, against: string): string {\n const { added, changed, removed } = changes\n const parts = [\n added.length && `+${pluralize(added.length, 'file')}`,\n changed.length && `~${changed.length} changed`,\n removed.length && `-${removed.length} removed`,\n ].filter(Boolean)\n\n return parts.length ? `${parts.join(' ')} ${against}` : `No changes ${against}`\n}\n\n/** One summary line: how many files changed, and since which run. */\nexport function formatChanges(changes: SnapshotChanges): string {\n if (!changes.base) {\n return 'First snapshot'\n }\n const { number, commit, createdAt } = changes.base\n\n return describeChanges(changes, `vs ${number ? `#${number}` : (commit?.slice(0, 7) ?? createdAt)}`)\n}\n\n/** One summary line: how the snapshot differs from the base branch's latest one. */\nexport function formatBranchChanges(changes: BranchSnapshotChanges & { branch: string }): string {\n if (changes.base) return describeChanges(changes, `vs ${changes.branch}`)\n\n return changes.baseFound ? `No snapshot of ${changes.branch} for this package yet` : `No snapshot of ${changes.branch} to compare with`\n}\n\nfunction printSummary(result: SnapshotResult): void {\n const row = (label: string, value: string) => ` ${styleText('dim', label.padEnd(7))} ${value}`\n\n console.log(\n [\n '',\n ...(result.webUrl ? [row('View', styleText('cyan', result.webUrl))] : []),\n ...(result.changes ? [row('Diff', formatChanges(result.changes))] : []),\n ...(result.branchChanges ? [row('Branch', formatBranchChanges(result.branchChanges))] : []),\n row('Use', `npm i ${result.url}`),\n row('Expires', result.expiresAt.slice(0, 10)),\n ].join('\\n'),\n )\n}\n\n/**\n * Generates the project, packs it, and publishes it to Kubb Studio in one request, under the CI\n * agent the run's identity names.\n */\nexport async function snapshot(options: SnapshotOptions): Promise<void> {\n const token = options.token ?? process.env.KUBB_TOKEN\n if (!token) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'An organization CI API key is required. Pass --token or set KUBB_TOKEN.',\n })\n }\n // A snapshot publishes the first entry.\n const config = (await loadConfigs(options)).configs[0]!\n const ci = resolveCiIdentity(options)\n // package.json is read only for whichever of name/version --name and --version did not supply.\n const { name, version: packageVersion } =\n options.name && options.packageVersion\n ? { name: options.name, version: options.packageVersion }\n : await findPackageJson(process.cwd()).then((found) => ({ name: options.name ?? found.name, version: options.packageVersion ?? found.version }))\n const logLevel = logLevelMap[options.logLevel ?? 'info']\n\n const write = options.json ? (line: string) => console.error(line) : (line: string) => console.log(line)\n const hooks = new Hookable<KubbHooks>()\n // The steps below are the CI log; the run's own per-file output only shows when asked for with --log-level verbose.\n setupReporters(hooks, { logLevel: logLevel > logLevelMap.info ? logLevel : logLevelMap.silent, reporters: [cliReporter], writer: createPlainWriter(write) })\n const step = (message: string) => {\n if (logLevel > logLevelMap.silent) {\n write(message)\n }\n }\n\n hooks.hook('kubb:generation:end', ({ filesCreated = 0, status, hrStart }) => {\n if (status !== 'failed' && hrStart) step(`✓ Generated ${pluralize(filesCreated, 'file')} in ${formatMs(getElapsedMs(hrStart))}`)\n })\n\n try {\n const published = await createSnapshot({\n studioUrl: options.studioUrl,\n apiKey: token,\n config,\n hooks,\n id: ci.id,\n name: ci.name,\n packageName: name,\n version: packageVersion,\n commit: ci.commit,\n baseId: ci.base?.id,\n })\n const result = toResult({ studioUrl: options.studioUrl, snapshot: published, ci })\n\n step(`✓ Packed ${result.name ?? name}@${result.version ?? packageVersion}`)\n step(`✓ Published snapshot ${result.number ? `#${result.number}` : result.id} for ${ci.name}${ci.commit ? `@${ci.commit.slice(0, 7)}` : ''}`)\n\n if (options.json) console.log(JSON.stringify(result))\n else printSummary(result)\n } catch (error) {\n step('✖ Snapshot failed')\n throw error\n }\n}\n\nexport const runner: CommandRunner<{ args: typeof command.args; extensions: {} }> = ({ values }) =>\n runStudio(\n values,\n (options) =>\n snapshot({\n ...options,\n token: values.token,\n id: values.id,\n baseId: values.baseId,\n name: values.name,\n packageVersion: values.packageVersion,\n json: values.json,\n }),\n { json: values.json },\n )\n"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-CPE0t6oh.cjs");
2
- const require_Telemetry = require("./Telemetry-0Sr_THx9.cjs");
3
- const require_utils = require("./utils-Ckbz012p.cjs");
4
- const require_text = require("./text-DVPYqR74.cjs");
5
- const require_reporters = require("./reporters-xwOZPZ42.cjs");
6
- const require_run = require("./run-w92b045L.cjs");
2
+ const require_Telemetry = require("./Telemetry-CZmpqKZm.cjs");
3
+ const require_utils = require("./utils-SIv7oWeS.cjs");
4
+ const require_text = require("./text-CtdDig0T.cjs");
5
+ const require_reporters = require("./reporters-B1Di1RhB.cjs");
6
+ const require_run = require("./run-ChCjDopB.cjs");
7
7
  let node_util = require("node:util");
8
8
  let node_process = require("node:process");
9
9
  node_process = require_rolldown_runtime.__toESM(node_process, 1);
@@ -248,4 +248,4 @@ const runner = ({ values }) => require_run.runStudio(values, (options) => snapsh
248
248
  //#endregion
249
249
  exports.runner = runner;
250
250
 
251
- //# sourceMappingURL=snapshot-B4eWToMC.cjs.map
251
+ //# sourceMappingURL=snapshot-Cr6KSlPW.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot-B4eWToMC.cjs","names":["readFileSync","process","read","join","dirname","Diagnostics","process","pluralize","styleText","loadConfigs","logLevelMap","Hookable","cliReporter","createPlainWriter","formatMs","getElapsedMs","createSnapshot","runStudio"],"sources":["../src/runners/studio/ci.ts","../src/runners/studio/snapshot.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport process from 'node:process'\n\n/**\n * Stable identity for the CI agent a snapshot run registers or reuses.\n */\nexport type CiContext = {\n /**\n * Fed into the machine token, so the same merge or pull request reuses one agent.\n */\n id: string\n /**\n * Agent display name shown in Studio.\n */\n name: string\n /** The commit this run builds, so the next snapshot can diff against it. */\n commit?: string\n /** The branch a pull request merges into, and the `id` runs on that branch register under. */\n base?: { branch: string; id: string }\n}\n\ntype GithubPullRequest = { number: number; head?: { sha?: string }; base?: { ref?: string } }\n\nfunction readGithubPullRequest(eventPath: string | undefined): GithubPullRequest | undefined {\n if (!eventPath) {\n return undefined\n }\n\n try {\n const event = JSON.parse(readFileSync(eventPath, 'utf8')) as { pull_request?: GithubPullRequest }\n return event.pull_request?.number ? event.pull_request : undefined\n } catch {\n return undefined\n }\n}\n\n/** Reproduces GitLab's `CI_COMMIT_REF_SLUG` for a branch it gives no slug of, like a merge request's target. */\nexport function gitlabRefSlug(ref: string): string {\n return ref\n .toLowerCase()\n .replace(/[^a-z0-9]/gu, '-')\n .slice(0, 63)\n .replace(/^-+|-+$/g, '')\n}\n\n/**\n * Detects the CI provider from its environment variables and derives a stable identity from it.\n * The GitHub row reproduces `gh:<repositoryId>:<prNumber>`, the identity `kubb-labs/action` has\n * always registered agents under, so an existing repository keeps reusing its agent.\n */\nexport function detectCi(env: Record<string, string | undefined> = process.env): CiContext | null {\n if (env.GITHUB_ACTIONS) {\n const pullRequest = readGithubPullRequest(env.GITHUB_EVENT_PATH)\n const repositoryId = env.GITHUB_REPOSITORY_ID ?? env.GITHUB_REPOSITORY ?? ''\n const branch = env.GITHUB_REF?.startsWith('refs/heads/') ? env.GITHUB_REF.slice('refs/heads/'.length) : undefined\n // A branch run is scoped by its ref, which a pull request number never collides with.\n const scope = pullRequest?.number ?? (branch ? `refs/heads/${branch}` : env.GITHUB_RUN_ID) ?? ''\n const baseBranch = pullRequest?.base?.ref\n\n return {\n id: `gh:${repositoryId}:${scope}`,\n name: `${env.GITHUB_REPOSITORY ?? 'github'}#${pullRequest?.number ?? branch ?? scope}`,\n // The head commit, not the merge commit a pull request run checks out.\n commit: pullRequest?.head?.sha ?? env.GITHUB_SHA,\n base: baseBranch ? { branch: baseBranch, id: `gh:${repositoryId}:refs/heads/${baseBranch}` } : undefined,\n }\n }\n\n if (env.GITLAB_CI) {\n const scope = env.CI_MERGE_REQUEST_IID ?? env.CI_COMMIT_REF_SLUG ?? ''\n const baseBranch = env.CI_MERGE_REQUEST_TARGET_BRANCH_NAME\n\n return {\n id: `gl:${env.CI_PROJECT_ID ?? ''}:${scope}`,\n name: `${env.CI_PROJECT_PATH ?? 'gitlab'}#${scope}`,\n commit: env.CI_MERGE_REQUEST_SOURCE_BRANCH_SHA || env.CI_COMMIT_SHA,\n base: baseBranch ? { branch: baseBranch, id: `gl:${env.CI_PROJECT_ID ?? ''}:${gitlabRefSlug(baseBranch)}` } : undefined,\n }\n }\n\n if (env.BITBUCKET_BUILD_NUMBER) {\n const scope = env.BITBUCKET_PR_ID ?? env.BITBUCKET_BRANCH ?? ''\n\n return { id: `bb:${env.BITBUCKET_REPO_UUID ?? ''}:${scope}`, name: `${env.BITBUCKET_REPO_FULL_NAME ?? 'bitbucket'}#${scope}`, commit: env.BITBUCKET_COMMIT }\n }\n\n if (env.CIRCLECI) {\n // Owner-qualified: two projects with the same name under different CircleCI orgs must not\n // collide on one agent, since registering it purges the other project's live sessions.\n const owner = env.CIRCLE_PROJECT_USERNAME ?? ''\n const project = env.CIRCLE_PROJECT_REPONAME ?? 'circleci'\n const scope = env.CIRCLE_PR_NUMBER ?? env.CIRCLE_BRANCH ?? ''\n\n return { id: `circle:${owner}:${project}:${scope}`, name: `${owner ? `${owner}/` : ''}${project}#${scope}`, commit: env.CIRCLE_SHA1 }\n }\n\n return null\n}\n","import { dirname, join } from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport { formatMs, getElapsedMs, read } from '@internals/utils'\nimport { cliReporter, Diagnostics, Hookable, type KubbHooks, logLevel as logLevelMap } from '@kubb/core'\nimport { createSnapshot } from '@kubb/studio'\nimport type { BranchSnapshotChanges, PublishedSnapshot, SnapshotChanges } from '@kubb/studio/protocol'\nimport { pluralize } from '../../ui/text.ts'\nimport { createPlainWriter } from '../../loggers/plainWriter.ts'\nimport setupReporters from '../../loggers/reporters.ts'\nimport { type CiContext, detectCi } from './ci.ts'\nimport { loadConfigs, runStudio, type SnapshotOptions } from './run.ts'\nimport type { command } from '../../commands/studio/snapshot.ts'\nimport type { CommandRunner } from 'gunshi'\n\n/**\n * Walks up from `directory` to the first package.json with a name and a version.\n */\nasync function findPackageJson(directory: string): Promise<{ name: string; version: string }> {\n const packageJson = JSON.parse(await read(join(directory, 'package.json')).catch(() => '{}')) as Partial<{ name: string; version: string }>\n if (packageJson.name && packageJson.version) return { name: packageJson.name, version: packageJson.version }\n\n const parent = dirname(directory)\n if (parent === directory)\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `No package.json with a name and a version found above ${process.cwd()}`,\n help: 'Pass `--name` and `--version`, or run from a package with a package.json.',\n })\n\n return findPackageJson(parent)\n}\n\nfunction resolveCiIdentity(options: SnapshotOptions): CiContext {\n const detected = detectCi()\n // A custom --id drops the detected base, since runs on that branch may use a custom id too.\n const ci = options.id ? { id: options.id, name: detected?.name ?? options.id, commit: detected?.commit } : detected\n\n if (!ci) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'Could not detect a supported CI provider (GitHub Actions, GitLab CI, Bitbucket Pipelines, CircleCI). Pass --id.',\n })\n }\n\n // An explicit --base-id may not name a branch, so it labels the comparison itself.\n const base = options.baseId ? { branch: options.baseId, id: options.baseId } : ci.base\n\n return { ...ci, base: base?.id === ci.id ? undefined : base }\n}\n\nfunction absoluteUrl(studioUrl: string, path: string): string {\n return new URL(path, `${studioUrl}/`).toString()\n}\n\ntype SnapshotResult = {\n id: string\n /** Sequence number on the CI agent, when Studio sends one. */\n number?: number\n name: string | null\n version: string | null\n integrity: string | null\n url: string\n snapshotIdUrl: string\n /** Studio page of the snapshot, when Studio sends one. */\n webUrl?: string\n expiresAt: string\n agentUrl: string\n /** What changed since the previous snapshot of this package on this agent. */\n changes?: SnapshotChanges\n /** What differs from the latest snapshot of the base branch, named by `branch`. */\n branchChanges?: BranchSnapshotChanges & { branch: string }\n}\n\nfunction toResult({ studioUrl, snapshot, ci }: { studioUrl: string; snapshot: PublishedSnapshot; ci: CiContext }): SnapshotResult {\n return {\n id: snapshot.id,\n number: snapshot.number,\n name: snapshot.name,\n version: snapshot.version,\n integrity: snapshot.integrity,\n url: absoluteUrl(studioUrl, snapshot.url),\n snapshotIdUrl: absoluteUrl(studioUrl, snapshot.snapshotIdUrl),\n webUrl: snapshot.webUrl ? absoluteUrl(studioUrl, snapshot.webUrl) : undefined,\n expiresAt: snapshot.expiresAt,\n agentUrl: absoluteUrl(studioUrl, `/agents/${snapshot.agent.slug ?? snapshot.agent.id}`),\n changes: snapshot.changes,\n branchChanges: snapshot.branchChanges && ci.base ? { ...snapshot.branchChanges, branch: ci.base.branch } : undefined,\n }\n}\n\n/** How many files differ, `against` what. */\nfunction describeChanges(changes: SnapshotChanges, against: string): string {\n const { added, changed, removed } = changes\n const parts = [\n added.length && `+${pluralize(added.length, 'file')}`,\n changed.length && `~${changed.length} changed`,\n removed.length && `-${removed.length} removed`,\n ].filter(Boolean)\n\n return parts.length ? `${parts.join(' ')} ${against}` : `No changes ${against}`\n}\n\n/** One summary line: how many files changed, and since which run. */\nexport function formatChanges(changes: SnapshotChanges): string {\n if (!changes.base) {\n return 'First snapshot'\n }\n const { number, commit, createdAt } = changes.base\n\n return describeChanges(changes, `vs ${number ? `#${number}` : (commit?.slice(0, 7) ?? createdAt)}`)\n}\n\n/** One summary line: how the snapshot differs from the base branch's latest one. */\nexport function formatBranchChanges(changes: BranchSnapshotChanges & { branch: string }): string {\n if (changes.base) return describeChanges(changes, `vs ${changes.branch}`)\n\n return changes.baseFound ? `No snapshot of ${changes.branch} for this package yet` : `No snapshot of ${changes.branch} to compare with`\n}\n\nfunction printSummary(result: SnapshotResult): void {\n const row = (label: string, value: string) => ` ${styleText('dim', label.padEnd(7))} ${value}`\n\n console.log(\n [\n '',\n ...(result.webUrl ? [row('View', styleText('cyan', result.webUrl))] : []),\n ...(result.changes ? [row('Diff', formatChanges(result.changes))] : []),\n ...(result.branchChanges ? [row('Branch', formatBranchChanges(result.branchChanges))] : []),\n row('Use', `npm i ${result.url}`),\n row('Expires', result.expiresAt.slice(0, 10)),\n ].join('\\n'),\n )\n}\n\n/**\n * Generates the project, packs it, and publishes it to Kubb Studio in one request, under the CI\n * agent the run's identity names.\n */\nexport async function snapshot(options: SnapshotOptions): Promise<void> {\n const token = options.token ?? process.env.KUBB_TOKEN\n if (!token) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'An organization CI API key is required. Pass --token or set KUBB_TOKEN.',\n })\n }\n // A snapshot publishes the first entry.\n const config = (await loadConfigs(options)).configs[0]!\n const ci = resolveCiIdentity(options)\n // package.json is read only for whichever of name/version --name and --version did not supply.\n const { name, version: packageVersion } =\n options.name && options.packageVersion\n ? { name: options.name, version: options.packageVersion }\n : await findPackageJson(process.cwd()).then((found) => ({ name: options.name ?? found.name, version: options.packageVersion ?? found.version }))\n const logLevel = logLevelMap[options.logLevel ?? 'info']\n\n const write = options.json ? (line: string) => console.error(line) : (line: string) => console.log(line)\n const hooks = new Hookable<KubbHooks>()\n // The steps below are the CI log; the run's own per-file output only shows when asked for with --log-level verbose.\n setupReporters(hooks, { logLevel: logLevel > logLevelMap.info ? logLevel : logLevelMap.silent, reporters: [cliReporter], writer: createPlainWriter(write) })\n const step = (message: string) => {\n if (logLevel > logLevelMap.silent) {\n write(message)\n }\n }\n\n hooks.hook('kubb:generation:end', ({ filesCreated = 0, status, hrStart }) => {\n if (status !== 'failed' && hrStart) step(`✓ Generated ${pluralize(filesCreated, 'file')} in ${formatMs(getElapsedMs(hrStart))}`)\n })\n\n try {\n const published = await createSnapshot({\n studioUrl: options.studioUrl,\n apiKey: token,\n config,\n hooks,\n id: ci.id,\n name: ci.name,\n packageName: name,\n version: packageVersion,\n commit: ci.commit,\n baseId: ci.base?.id,\n })\n const result = toResult({ studioUrl: options.studioUrl, snapshot: published, ci })\n\n step(`✓ Packed ${result.name ?? name}@${result.version ?? packageVersion}`)\n step(`✓ Published snapshot ${result.number ? `#${result.number}` : result.id} for ${ci.name}${ci.commit ? `@${ci.commit.slice(0, 7)}` : ''}`)\n\n if (options.json) console.log(JSON.stringify(result))\n else printSummary(result)\n } catch (error) {\n step('✖ Snapshot failed')\n throw error\n }\n}\n\nexport const runner: CommandRunner<{ args: typeof command.args; extensions: {} }> = ({ values }) =>\n runStudio(\n values,\n (options) =>\n snapshot({\n ...options,\n token: values.token,\n id: values.id,\n baseId: values.baseId,\n name: values.name,\n packageVersion: values.packageVersion,\n json: values.json,\n }),\n { json: values.json },\n )\n"],"mappings":";;;;;;;;;;;;;;AAuBA,SAAS,sBAAsB,WAA8D;CAC3F,IAAI,CAAC,WACH;CAGF,IAAI;EACF,MAAM,QAAQ,KAAK,OAAA,GAAMA,QAAAA,aAAAA,CAAa,WAAW,MAAM,CAAC;EACxD,OAAO,MAAM,cAAc,SAAS,MAAM,eAAe,KAAA;CAC3D,QAAQ;EACN;CACF;AACF;;AAGA,SAAgB,cAAc,KAAqB;CACjD,OAAO,IACJ,YAAY,CAAC,CACb,QAAQ,eAAe,GAAG,CAAC,CAC3B,MAAM,GAAG,EAAE,CAAC,CACZ,QAAQ,YAAY,EAAE;AAC3B;;;;;;AAOA,SAAgB,SAAS,MAA0CC,aAAAA,QAAQ,KAAuB;CAChG,IAAI,IAAI,gBAAgB;EACtB,MAAM,cAAc,sBAAsB,IAAI,iBAAiB;EAC/D,MAAM,eAAe,IAAI,wBAAwB,IAAI,qBAAqB;EAC1E,MAAM,SAAS,IAAI,YAAY,WAAW,aAAa,IAAI,IAAI,WAAW,MAAM,EAAoB,IAAI,KAAA;EAExG,MAAM,QAAQ,aAAa,WAAW,SAAS,cAAc,WAAW,IAAI,kBAAkB;EAC9F,MAAM,aAAa,aAAa,MAAM;EAEtC,OAAO;GACL,IAAI,MAAM,aAAa,GAAG;GAC1B,MAAM,GAAG,IAAI,qBAAqB,SAAS,GAAG,aAAa,UAAU,UAAU;GAE/E,QAAQ,aAAa,MAAM,OAAO,IAAI;GACtC,MAAM,aAAa;IAAE,QAAQ;IAAY,IAAI,MAAM,aAAa,cAAc;GAAa,IAAI,KAAA;EACjG;CACF;CAEA,IAAI,IAAI,WAAW;EACjB,MAAM,QAAQ,IAAI,wBAAwB,IAAI,sBAAsB;EACpE,MAAM,aAAa,IAAI;EAEvB,OAAO;GACL,IAAI,MAAM,IAAI,iBAAiB,GAAG,GAAG;GACrC,MAAM,GAAG,IAAI,mBAAmB,SAAS,GAAG;GAC5C,QAAQ,IAAI,sCAAsC,IAAI;GACtD,MAAM,aAAa;IAAE,QAAQ;IAAY,IAAI,MAAM,IAAI,iBAAiB,GAAG,GAAG,cAAc,UAAU;GAAI,IAAI,KAAA;EAChH;CACF;CAEA,IAAI,IAAI,wBAAwB;EAC9B,MAAM,QAAQ,IAAI,mBAAmB,IAAI,oBAAoB;EAE7D,OAAO;GAAE,IAAI,MAAM,IAAI,uBAAuB,GAAG,GAAG;GAAS,MAAM,GAAG,IAAI,4BAA4B,YAAY,GAAG;GAAS,QAAQ,IAAI;EAAiB;CAC7J;CAEA,IAAI,IAAI,UAAU;EAGhB,MAAM,QAAQ,IAAI,2BAA2B;EAC7C,MAAM,UAAU,IAAI,2BAA2B;EAC/C,MAAM,QAAQ,IAAI,oBAAoB,IAAI,iBAAiB;EAE3D,OAAO;GAAE,IAAI,UAAU,MAAM,GAAG,QAAQ,GAAG;GAAS,MAAM,GAAG,QAAQ,GAAG,MAAM,KAAK,KAAK,QAAQ,GAAG;GAAS,QAAQ,IAAI;EAAY;CACtI;CAEA,OAAO;AACT;;;;;;AC/EA,eAAe,gBAAgB,WAA+D;CAC5F,MAAM,cAAc,KAAK,MAAM,MAAMC,cAAAA,MAAAA,GAAKC,UAAAA,KAAAA,CAAK,WAAW,cAAc,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC;CAC5F,IAAI,YAAY,QAAQ,YAAY,SAAS,OAAO;EAAE,MAAM,YAAY;EAAM,SAAS,YAAY;CAAQ;CAE3G,MAAM,UAAA,GAASC,UAAAA,QAAAA,CAAQ,SAAS;CAChC,IAAI,WAAW,WACb,MAAM,IAAIC,WAAAA,YAAY,MAAM;EAC1B,MAAMA,WAAAA,YAAY,KAAK;EACvB,UAAU;EACV,SAAS,yDAAyDC,aAAAA,QAAQ,IAAI;EAC9E,MAAM;CACR,CAAC;CAEH,OAAO,gBAAgB,MAAM;AAC/B;AAEA,SAAS,kBAAkB,SAAqC;CAC9D,MAAM,WAAW,SAAS;CAE1B,MAAM,KAAK,QAAQ,KAAK;EAAE,IAAI,QAAQ;EAAI,MAAM,UAAU,QAAQ,QAAQ;EAAI,QAAQ,UAAU;CAAO,IAAI;CAE3G,IAAI,CAAC,IACH,MAAM,IAAID,WAAAA,YAAY,MAAM;EAC1B,MAAMA,WAAAA,YAAY,KAAK;EACvB,UAAU;EACV,SAAS;CACX,CAAC;CAIH,MAAM,OAAO,QAAQ,SAAS;EAAE,QAAQ,QAAQ;EAAQ,IAAI,QAAQ;CAAO,IAAI,GAAG;CAElF,OAAO;EAAE,GAAG;EAAI,MAAM,MAAM,OAAO,GAAG,KAAK,KAAA,IAAY;CAAK;AAC9D;AAEA,SAAS,YAAY,WAAmB,MAAsB;CAC5D,OAAO,IAAI,IAAI,MAAM,GAAG,UAAU,EAAE,CAAC,CAAC,SAAS;AACjD;AAqBA,SAAS,SAAS,EAAE,WAAW,UAAU,MAAyF;CAChI,OAAO;EACL,IAAI,SAAS;EACb,QAAQ,SAAS;EACjB,MAAM,SAAS;EACf,SAAS,SAAS;EAClB,WAAW,SAAS;EACpB,KAAK,YAAY,WAAW,SAAS,GAAG;EACxC,eAAe,YAAY,WAAW,SAAS,aAAa;EAC5D,QAAQ,SAAS,SAAS,YAAY,WAAW,SAAS,MAAM,IAAI,KAAA;EACpE,WAAW,SAAS;EACpB,UAAU,YAAY,WAAW,WAAW,SAAS,MAAM,QAAQ,SAAS,MAAM,IAAI;EACtF,SAAS,SAAS;EAClB,eAAe,SAAS,iBAAiB,GAAG,OAAO;GAAE,GAAG,SAAS;GAAe,QAAQ,GAAG,KAAK;EAAO,IAAI,KAAA;CAC7G;AACF;;AAGA,SAAS,gBAAgB,SAA0B,SAAyB;CAC1E,MAAM,EAAE,OAAO,SAAS,YAAY;CACpC,MAAM,QAAQ;EACZ,MAAM,UAAU,IAAIE,aAAAA,UAAU,MAAM,QAAQ,MAAM;EAClD,QAAQ,UAAU,IAAI,QAAQ,OAAO;EACrC,QAAQ,UAAU,IAAI,QAAQ,OAAO;CACvC,CAAC,CAAC,OAAO,OAAO;CAEhB,OAAO,MAAM,SAAS,GAAG,MAAM,KAAK,IAAI,EAAE,IAAI,YAAY,cAAc;AAC1E;;AAGA,SAAgB,cAAc,SAAkC;CAC9D,IAAI,CAAC,QAAQ,MACX,OAAO;CAET,MAAM,EAAE,QAAQ,QAAQ,cAAc,QAAQ;CAE9C,OAAO,gBAAgB,SAAS,MAAM,SAAS,IAAI,WAAY,QAAQ,MAAM,GAAG,CAAC,KAAK,WAAY;AACpG;;AAGA,SAAgB,oBAAoB,SAA6D;CAC/F,IAAI,QAAQ,MAAM,OAAO,gBAAgB,SAAS,MAAM,QAAQ,QAAQ;CAExE,OAAO,QAAQ,YAAY,kBAAkB,QAAQ,OAAO,yBAAyB,kBAAkB,QAAQ,OAAO;AACxH;AAEA,SAAS,aAAa,QAA8B;CAClD,MAAM,OAAO,OAAe,UAAkB,MAAA,GAAKC,UAAAA,UAAAA,CAAU,OAAO,MAAM,OAAO,CAAC,CAAC,EAAE,GAAG;CAExF,QAAQ,IACN;EACE;EACA,GAAI,OAAO,SAAS,CAAC,IAAI,SAAA,GAAQA,UAAAA,UAAAA,CAAU,QAAQ,OAAO,MAAM,CAAC,CAAC,IAAI,CAAC;EACvE,GAAI,OAAO,UAAU,CAAC,IAAI,QAAQ,cAAc,OAAO,OAAO,CAAC,CAAC,IAAI,CAAC;EACrE,GAAI,OAAO,gBAAgB,CAAC,IAAI,UAAU,oBAAoB,OAAO,aAAa,CAAC,CAAC,IAAI,CAAC;EACzF,IAAI,OAAO,SAAS,OAAO,KAAK;EAChC,IAAI,WAAW,OAAO,UAAU,MAAM,GAAG,EAAE,CAAC;CAC9C,CAAC,CAAC,KAAK,IAAI,CACb;AACF;;;;;AAMA,eAAsB,SAAS,SAAyC;CACtE,MAAM,QAAQ,QAAQ,SAASF,aAAAA,QAAQ,IAAI;CAC3C,IAAI,CAAC,OACH,MAAM,IAAID,WAAAA,YAAY,MAAM;EAC1B,MAAMA,WAAAA,YAAY,KAAK;EACvB,UAAU;EACV,SAAS;CACX,CAAC;CAGH,MAAM,UAAU,MAAMI,YAAAA,YAAY,OAAO,EAAA,CAAG,QAAQ;CACpD,MAAM,KAAK,kBAAkB,OAAO;CAEpC,MAAM,EAAE,MAAM,SAAS,mBACrB,QAAQ,QAAQ,QAAQ,iBACpB;EAAE,MAAM,QAAQ;EAAM,SAAS,QAAQ;CAAe,IACtD,MAAM,gBAAgBH,aAAAA,QAAQ,IAAI,CAAC,CAAC,CAAC,MAAM,WAAW;EAAE,MAAM,QAAQ,QAAQ,MAAM;EAAM,SAAS,QAAQ,kBAAkB,MAAM;CAAQ,EAAE;CACnJ,MAAM,WAAWI,WAAAA,SAAY,QAAQ,YAAY;CAEjD,MAAM,QAAQ,QAAQ,QAAQ,SAAiB,QAAQ,MAAM,IAAI,KAAK,SAAiB,QAAQ,IAAI,IAAI;CACvG,MAAM,QAAQ,IAAIC,WAAAA,SAAoB;CAEtC,kBAAA,eAAe,OAAO;EAAE,UAAU,WAAWD,WAAAA,SAAY,OAAO,WAAWA,WAAAA,SAAY;EAAQ,WAAW,CAACE,WAAAA,WAAW;EAAG,QAAQC,aAAAA,kBAAkB,KAAK;CAAE,CAAC;CAC3J,MAAM,QAAQ,YAAoB;EAChC,IAAI,WAAWH,WAAAA,SAAY,QACzB,MAAM,OAAO;CAEjB;CAEA,MAAM,KAAK,wBAAwB,EAAE,eAAe,GAAG,QAAQ,cAAc;EAC3E,IAAI,WAAW,YAAY,SAAS,KAAK,eAAeH,aAAAA,UAAU,cAAc,MAAM,EAAE,MAAMO,kBAAAA,SAASC,kBAAAA,aAAa,OAAO,CAAC,GAAG;CACjI,CAAC;CAED,IAAI;EACF,MAAM,YAAY,OAAA,GAAMC,aAAAA,eAAAA,CAAe;GACrC,WAAW,QAAQ;GACnB,QAAQ;GACR;GACA;GACA,IAAI,GAAG;GACP,MAAM,GAAG;GACT,aAAa;GACb,SAAS;GACT,QAAQ,GAAG;GACX,QAAQ,GAAG,MAAM;EACnB,CAAC;EACD,MAAM,SAAS,SAAS;GAAE,WAAW,QAAQ;GAAW,UAAU;GAAW;EAAG,CAAC;EAEjF,KAAK,YAAY,OAAO,QAAQ,KAAK,GAAG,OAAO,WAAW,gBAAgB;EAC1E,KAAK,wBAAwB,OAAO,SAAS,IAAI,OAAO,WAAW,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,IAAI,GAAG,OAAO,MAAM,GAAG,CAAC,MAAM,IAAI;EAE5I,IAAI,QAAQ,MAAM,QAAQ,IAAI,KAAK,UAAU,MAAM,CAAC;OAC/C,aAAa,MAAM;CAC1B,SAAS,OAAO;EACd,KAAK,mBAAmB;EACxB,MAAM;CACR;AACF;AAEA,MAAa,UAAwE,EAAE,aACrFC,YAAAA,UACE,SACC,YACC,SAAS;CACP,GAAG;CACH,OAAO,OAAO;CACd,IAAI,OAAO;CACX,QAAQ,OAAO;CACf,MAAM,OAAO;CACb,gBAAgB,OAAO;CACvB,MAAM,OAAO;AACf,CAAC,GACH,EAAE,MAAM,OAAO,KAAK,CACtB"}
1
+ {"version":3,"file":"snapshot-Cr6KSlPW.cjs","names":["readFileSync","process","read","join","dirname","Diagnostics","process","pluralize","styleText","loadConfigs","logLevelMap","Hookable","cliReporter","createPlainWriter","formatMs","getElapsedMs","createSnapshot","runStudio"],"sources":["../src/runners/studio/ci.ts","../src/runners/studio/snapshot.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport process from 'node:process'\n\n/**\n * Stable identity for the CI agent a snapshot run registers or reuses.\n */\nexport type CiContext = {\n /**\n * Fed into the machine token, so the same merge or pull request reuses one agent.\n */\n id: string\n /**\n * Agent display name shown in Studio.\n */\n name: string\n /** The commit this run builds, so the next snapshot can diff against it. */\n commit?: string\n /** The branch a pull request merges into, and the `id` runs on that branch register under. */\n base?: { branch: string; id: string }\n}\n\ntype GithubPullRequest = { number: number; head?: { sha?: string }; base?: { ref?: string } }\n\nfunction readGithubPullRequest(eventPath: string | undefined): GithubPullRequest | undefined {\n if (!eventPath) {\n return undefined\n }\n\n try {\n const event = JSON.parse(readFileSync(eventPath, 'utf8')) as { pull_request?: GithubPullRequest }\n return event.pull_request?.number ? event.pull_request : undefined\n } catch {\n return undefined\n }\n}\n\n/** Reproduces GitLab's `CI_COMMIT_REF_SLUG` for a branch it gives no slug of, like a merge request's target. */\nexport function gitlabRefSlug(ref: string): string {\n return ref\n .toLowerCase()\n .replace(/[^a-z0-9]/gu, '-')\n .slice(0, 63)\n .replace(/^-+|-+$/g, '')\n}\n\n/**\n * Detects the CI provider from its environment variables and derives a stable identity from it.\n * The GitHub row reproduces `gh:<repositoryId>:<prNumber>`, the identity `kubb-labs/action` has\n * always registered agents under, so an existing repository keeps reusing its agent.\n */\nexport function detectCi(env: Record<string, string | undefined> = process.env): CiContext | null {\n if (env.GITHUB_ACTIONS) {\n const pullRequest = readGithubPullRequest(env.GITHUB_EVENT_PATH)\n const repositoryId = env.GITHUB_REPOSITORY_ID ?? env.GITHUB_REPOSITORY ?? ''\n const branch = env.GITHUB_REF?.startsWith('refs/heads/') ? env.GITHUB_REF.slice('refs/heads/'.length) : undefined\n // A branch run is scoped by its ref, which a pull request number never collides with.\n const scope = pullRequest?.number ?? (branch ? `refs/heads/${branch}` : env.GITHUB_RUN_ID) ?? ''\n const baseBranch = pullRequest?.base?.ref\n\n return {\n id: `gh:${repositoryId}:${scope}`,\n name: `${env.GITHUB_REPOSITORY ?? 'github'}#${pullRequest?.number ?? branch ?? scope}`,\n // The head commit, not the merge commit a pull request run checks out.\n commit: pullRequest?.head?.sha ?? env.GITHUB_SHA,\n base: baseBranch ? { branch: baseBranch, id: `gh:${repositoryId}:refs/heads/${baseBranch}` } : undefined,\n }\n }\n\n if (env.GITLAB_CI) {\n const scope = env.CI_MERGE_REQUEST_IID ?? env.CI_COMMIT_REF_SLUG ?? ''\n const baseBranch = env.CI_MERGE_REQUEST_TARGET_BRANCH_NAME\n\n return {\n id: `gl:${env.CI_PROJECT_ID ?? ''}:${scope}`,\n name: `${env.CI_PROJECT_PATH ?? 'gitlab'}#${scope}`,\n commit: env.CI_MERGE_REQUEST_SOURCE_BRANCH_SHA || env.CI_COMMIT_SHA,\n base: baseBranch ? { branch: baseBranch, id: `gl:${env.CI_PROJECT_ID ?? ''}:${gitlabRefSlug(baseBranch)}` } : undefined,\n }\n }\n\n if (env.BITBUCKET_BUILD_NUMBER) {\n const scope = env.BITBUCKET_PR_ID ?? env.BITBUCKET_BRANCH ?? ''\n\n return { id: `bb:${env.BITBUCKET_REPO_UUID ?? ''}:${scope}`, name: `${env.BITBUCKET_REPO_FULL_NAME ?? 'bitbucket'}#${scope}`, commit: env.BITBUCKET_COMMIT }\n }\n\n if (env.CIRCLECI) {\n // Owner-qualified: two projects with the same name under different CircleCI orgs must not\n // collide on one agent, since registering it purges the other project's live sessions.\n const owner = env.CIRCLE_PROJECT_USERNAME ?? ''\n const project = env.CIRCLE_PROJECT_REPONAME ?? 'circleci'\n const scope = env.CIRCLE_PR_NUMBER ?? env.CIRCLE_BRANCH ?? ''\n\n return { id: `circle:${owner}:${project}:${scope}`, name: `${owner ? `${owner}/` : ''}${project}#${scope}`, commit: env.CIRCLE_SHA1 }\n }\n\n return null\n}\n","import { dirname, join } from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport { formatMs, getElapsedMs, read } from '@internals/utils'\nimport { cliReporter, Diagnostics, Hookable, type KubbHooks, logLevel as logLevelMap } from '@kubb/core'\nimport { createSnapshot } from '@kubb/studio'\nimport type { BranchSnapshotChanges, PublishedSnapshot, SnapshotChanges } from '@kubb/studio/protocol'\nimport { pluralize } from '../../ui/text.ts'\nimport { createPlainWriter } from '../../loggers/plainWriter.ts'\nimport setupReporters from '../../loggers/reporters.ts'\nimport { type CiContext, detectCi } from './ci.ts'\nimport { loadConfigs, runStudio, type SnapshotOptions } from './run.ts'\nimport type { command } from '../../commands/studio/snapshot.ts'\nimport type { CommandRunner } from 'gunshi'\n\n/**\n * Walks up from `directory` to the first package.json with a name and a version.\n */\nasync function findPackageJson(directory: string): Promise<{ name: string; version: string }> {\n const packageJson = JSON.parse(await read(join(directory, 'package.json')).catch(() => '{}')) as Partial<{ name: string; version: string }>\n if (packageJson.name && packageJson.version) return { name: packageJson.name, version: packageJson.version }\n\n const parent = dirname(directory)\n if (parent === directory)\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `No package.json with a name and a version found above ${process.cwd()}`,\n help: 'Pass `--name` and `--version`, or run from a package with a package.json.',\n })\n\n return findPackageJson(parent)\n}\n\nfunction resolveCiIdentity(options: SnapshotOptions): CiContext {\n const detected = detectCi()\n // A custom --id drops the detected base, since runs on that branch may use a custom id too.\n const ci = options.id ? { id: options.id, name: detected?.name ?? options.id, commit: detected?.commit } : detected\n\n if (!ci) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'Could not detect a supported CI provider (GitHub Actions, GitLab CI, Bitbucket Pipelines, CircleCI). Pass --id.',\n })\n }\n\n // An explicit --base-id may not name a branch, so it labels the comparison itself.\n const base = options.baseId ? { branch: options.baseId, id: options.baseId } : ci.base\n\n return { ...ci, base: base?.id === ci.id ? undefined : base }\n}\n\nfunction absoluteUrl(studioUrl: string, path: string): string {\n return new URL(path, `${studioUrl}/`).toString()\n}\n\ntype SnapshotResult = {\n id: string\n /** Sequence number on the CI agent, when Studio sends one. */\n number?: number\n name: string | null\n version: string | null\n integrity: string | null\n url: string\n snapshotIdUrl: string\n /** Studio page of the snapshot, when Studio sends one. */\n webUrl?: string\n expiresAt: string\n agentUrl: string\n /** What changed since the previous snapshot of this package on this agent. */\n changes?: SnapshotChanges\n /** What differs from the latest snapshot of the base branch, named by `branch`. */\n branchChanges?: BranchSnapshotChanges & { branch: string }\n}\n\nfunction toResult({ studioUrl, snapshot, ci }: { studioUrl: string; snapshot: PublishedSnapshot; ci: CiContext }): SnapshotResult {\n return {\n id: snapshot.id,\n number: snapshot.number,\n name: snapshot.name,\n version: snapshot.version,\n integrity: snapshot.integrity,\n url: absoluteUrl(studioUrl, snapshot.url),\n snapshotIdUrl: absoluteUrl(studioUrl, snapshot.snapshotIdUrl),\n webUrl: snapshot.webUrl ? absoluteUrl(studioUrl, snapshot.webUrl) : undefined,\n expiresAt: snapshot.expiresAt,\n agentUrl: absoluteUrl(studioUrl, `/agents/${snapshot.agent.slug ?? snapshot.agent.id}`),\n changes: snapshot.changes,\n branchChanges: snapshot.branchChanges && ci.base ? { ...snapshot.branchChanges, branch: ci.base.branch } : undefined,\n }\n}\n\n/** How many files differ, `against` what. */\nfunction describeChanges(changes: SnapshotChanges, against: string): string {\n const { added, changed, removed } = changes\n const parts = [\n added.length && `+${pluralize(added.length, 'file')}`,\n changed.length && `~${changed.length} changed`,\n removed.length && `-${removed.length} removed`,\n ].filter(Boolean)\n\n return parts.length ? `${parts.join(' ')} ${against}` : `No changes ${against}`\n}\n\n/** One summary line: how many files changed, and since which run. */\nexport function formatChanges(changes: SnapshotChanges): string {\n if (!changes.base) {\n return 'First snapshot'\n }\n const { number, commit, createdAt } = changes.base\n\n return describeChanges(changes, `vs ${number ? `#${number}` : (commit?.slice(0, 7) ?? createdAt)}`)\n}\n\n/** One summary line: how the snapshot differs from the base branch's latest one. */\nexport function formatBranchChanges(changes: BranchSnapshotChanges & { branch: string }): string {\n if (changes.base) return describeChanges(changes, `vs ${changes.branch}`)\n\n return changes.baseFound ? `No snapshot of ${changes.branch} for this package yet` : `No snapshot of ${changes.branch} to compare with`\n}\n\nfunction printSummary(result: SnapshotResult): void {\n const row = (label: string, value: string) => ` ${styleText('dim', label.padEnd(7))} ${value}`\n\n console.log(\n [\n '',\n ...(result.webUrl ? [row('View', styleText('cyan', result.webUrl))] : []),\n ...(result.changes ? [row('Diff', formatChanges(result.changes))] : []),\n ...(result.branchChanges ? [row('Branch', formatBranchChanges(result.branchChanges))] : []),\n row('Use', `npm i ${result.url}`),\n row('Expires', result.expiresAt.slice(0, 10)),\n ].join('\\n'),\n )\n}\n\n/**\n * Generates the project, packs it, and publishes it to Kubb Studio in one request, under the CI\n * agent the run's identity names.\n */\nexport async function snapshot(options: SnapshotOptions): Promise<void> {\n const token = options.token ?? process.env.KUBB_TOKEN\n if (!token) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'An organization CI API key is required. Pass --token or set KUBB_TOKEN.',\n })\n }\n // A snapshot publishes the first entry.\n const config = (await loadConfigs(options)).configs[0]!\n const ci = resolveCiIdentity(options)\n // package.json is read only for whichever of name/version --name and --version did not supply.\n const { name, version: packageVersion } =\n options.name && options.packageVersion\n ? { name: options.name, version: options.packageVersion }\n : await findPackageJson(process.cwd()).then((found) => ({ name: options.name ?? found.name, version: options.packageVersion ?? found.version }))\n const logLevel = logLevelMap[options.logLevel ?? 'info']\n\n const write = options.json ? (line: string) => console.error(line) : (line: string) => console.log(line)\n const hooks = new Hookable<KubbHooks>()\n // The steps below are the CI log; the run's own per-file output only shows when asked for with --log-level verbose.\n setupReporters(hooks, { logLevel: logLevel > logLevelMap.info ? logLevel : logLevelMap.silent, reporters: [cliReporter], writer: createPlainWriter(write) })\n const step = (message: string) => {\n if (logLevel > logLevelMap.silent) {\n write(message)\n }\n }\n\n hooks.hook('kubb:generation:end', ({ filesCreated = 0, status, hrStart }) => {\n if (status !== 'failed' && hrStart) step(`✓ Generated ${pluralize(filesCreated, 'file')} in ${formatMs(getElapsedMs(hrStart))}`)\n })\n\n try {\n const published = await createSnapshot({\n studioUrl: options.studioUrl,\n apiKey: token,\n config,\n hooks,\n id: ci.id,\n name: ci.name,\n packageName: name,\n version: packageVersion,\n commit: ci.commit,\n baseId: ci.base?.id,\n })\n const result = toResult({ studioUrl: options.studioUrl, snapshot: published, ci })\n\n step(`✓ Packed ${result.name ?? name}@${result.version ?? packageVersion}`)\n step(`✓ Published snapshot ${result.number ? `#${result.number}` : result.id} for ${ci.name}${ci.commit ? `@${ci.commit.slice(0, 7)}` : ''}`)\n\n if (options.json) console.log(JSON.stringify(result))\n else printSummary(result)\n } catch (error) {\n step('✖ Snapshot failed')\n throw error\n }\n}\n\nexport const runner: CommandRunner<{ args: typeof command.args; extensions: {} }> = ({ values }) =>\n runStudio(\n values,\n (options) =>\n snapshot({\n ...options,\n token: values.token,\n id: values.id,\n baseId: values.baseId,\n name: values.name,\n packageVersion: values.packageVersion,\n json: values.json,\n }),\n { json: values.json },\n )\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { r as formatPermissionRows } from "./run-kRFuEqeA.js";
3
- import { h as isPathInside } from "./utils--q06lp55.js";
2
+ import { r as formatPermissionRows } from "./run-A2hHeAoZ.js";
3
+ import { h as isPathInside } from "./utils-3TiGzYuZ.js";
4
4
  import { stripVTControlCharacters, styleText } from "node:util";
5
5
  import { homedir } from "node:os";
6
6
  import path from "node:path";
@@ -74,4 +74,4 @@ function formatStatus({ studioUrl, credentials, worker, project, logPath, now =
74
74
  //#endregion
75
75
  export { formatStatus };
76
76
 
77
- //# sourceMappingURL=status-C5_IHiDc.js.map
77
+ //# sourceMappingURL=status-BdjS4SMJ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"status-C5_IHiDc.js","names":[],"sources":["../src/runners/studio/status.ts"],"sourcesContent":["import { homedir } from 'node:os'\nimport path from 'node:path'\nimport { stripVTControlCharacters, styleText } from 'node:util'\nimport { isPathInside } from '@internals/utils'\nimport type { Credentials } from './credentials.ts'\nimport { formatPermissionRows, type WorkerState } from './run.ts'\n\ntype StatusInput = {\n studioUrl: string\n credentials: Credentials | null\n worker: { running: boolean; state: WorkerState; pid?: number; startedAt?: number }\n project: string\n logPath: string\n now?: number\n}\n\n/** How long a worker has run, such as `2h 14m`, `5m` or `40s`. */\nexport function formatUptime(ms: number): string {\n const minutes = Math.floor(ms / 60_000)\n if (minutes < 1) return `${Math.max(0, Math.floor(ms / 1000))}s`\n if (minutes < 60) return `${minutes}m`\n\n return `${Math.floor(minutes / 60)}h ${minutes % 60}m`\n}\n\nconst tilde = (file: string) => (isPathInside(file, homedir()) ? `~${file.slice(homedir().length)}` : file)\n\n/**\n * The `kubb studio status` table: one row per topic, each ending with the command that changes it.\n */\nexport function formatStatus({ studioUrl, credentials, worker, project, logPath, now = Date.now() }: StatusInput): Array<string> {\n const pairing = (() => {\n if (!credentials) return { value: `${styleText('red', '✖')} not paired`, command: 'kubb studio login' }\n const name = `${credentials.agentSlug || credentials.agentId}${credentials.organizationSlug ? ` · org ${credentials.organizationSlug}` : ''}`\n if (credentials.studioUrl !== studioUrl) return { value: `${styleText('yellow', '!')} ${name} · ${credentials.studioUrl}`, command: 'kubb studio login' }\n return { value: `${styleText('green', '✓')} ${name}`, command: 'kubb studio logout' }\n })()\n const uptime = worker.startedAt ? ` · up ${formatUptime(now - worker.startedAt)}` : ''\n const workerRow = worker.running\n ? { value: `${styleText('green', '●')} ${worker.state} · PID ${worker.pid}${uptime}`, command: 'kubb studio stop' }\n : { value: `${styleText('dim', '○')} ${worker.state}`, command: 'kubb studio start' }\n const remembered = credentials?.projects?.[project]\n const permissions = remembered ? formatPermissionRows(remembered) : [styleText('dim', 'not chosen yet')]\n\n const rows: Array<{ label: string; value: string; command?: string }> = [\n { label: 'Pairing', ...pairing },\n { label: 'Worker', ...workerRow },\n { label: 'Project', value: `${path.basename(project)} · ${tilde(project)}` },\n ...permissions.map((value, index) => ({\n label: index === 0 ? 'Permissions' : '',\n value,\n command: !remembered && index === 0 ? 'kubb studio connect' : undefined,\n })),\n { label: 'Logs', value: tilde(logPath) },\n ]\n const width = Math.max(...rows.filter((row) => row.command).map((row) => stripVTControlCharacters(row.value).length))\n\n return rows.map(({ label, value, command }) => {\n const line = ` ${label.padEnd(11)} ${value}`\n return command ? `${line}${' '.repeat(width - stripVTControlCharacters(value).length + 3)}${styleText('dim', command)}` : line\n })\n}\n"],"mappings":";;;;;;;;AAiBA,SAAgB,aAAa,IAAoB;CAC/C,MAAM,UAAU,KAAK,MAAM,KAAK,GAAM;CACtC,IAAI,UAAU,GAAG,OAAO,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,GAAI,CAAC,EAAE;CAC9D,IAAI,UAAU,IAAI,OAAO,GAAG,QAAQ;CAEpC,OAAO,GAAG,KAAK,MAAM,UAAU,EAAE,EAAE,IAAI,UAAU,GAAG;AACtD;AAEA,MAAM,SAAS,SAAkB,aAAa,MAAM,QAAQ,CAAC,IAAI,IAAI,KAAK,MAAM,QAAQ,CAAC,CAAC,MAAM,MAAM;;;;AAKtG,SAAgB,aAAa,EAAE,WAAW,aAAa,QAAQ,SAAS,SAAS,MAAM,KAAK,IAAI,KAAiC;CAC/H,MAAM,iBAAiB;EACrB,IAAI,CAAC,aAAa,OAAO;GAAE,OAAO,GAAG,UAAU,OAAO,GAAG,EAAE;GAAc,SAAS;EAAoB;EACtG,MAAM,OAAO,GAAG,YAAY,aAAa,YAAY,UAAU,YAAY,mBAAmB,UAAU,YAAY,qBAAqB;EACzI,IAAI,YAAY,cAAc,WAAW,OAAO;GAAE,OAAO,GAAG,UAAU,UAAU,GAAG,EAAE,GAAG,KAAK,KAAK,YAAY;GAAa,SAAS;EAAoB;EACxJ,OAAO;GAAE,OAAO,GAAG,UAAU,SAAS,GAAG,EAAE,GAAG;GAAQ,SAAS;EAAqB;CACtF,EAAA,CAAG;CACH,MAAM,SAAS,OAAO,YAAY,SAAS,aAAa,MAAM,OAAO,SAAS,MAAM;CACpF,MAAM,YAAY,OAAO,UACrB;EAAE,OAAO,GAAG,UAAU,SAAS,GAAG,EAAE,GAAG,OAAO,MAAM,SAAS,OAAO,MAAM;EAAU,SAAS;CAAmB,IAChH;EAAE,OAAO,GAAG,UAAU,OAAO,GAAG,EAAE,GAAG,OAAO;EAAS,SAAS;CAAoB;CACtF,MAAM,aAAa,aAAa,WAAW;CAC3C,MAAM,cAAc,aAAa,qBAAqB,UAAU,IAAI,CAAC,UAAU,OAAO,gBAAgB,CAAC;CAEvG,MAAM,OAAkE;EACtE;GAAE,OAAO;GAAW,GAAG;EAAQ;EAC/B;GAAE,OAAO;GAAU,GAAG;EAAU;EAChC;GAAE,OAAO;GAAW,OAAO,GAAG,KAAK,SAAS,OAAO,EAAE,KAAK,MAAM,OAAO;EAAI;EAC3E,GAAG,YAAY,KAAK,OAAO,WAAW;GACpC,OAAO,UAAU,IAAI,gBAAgB;GACrC;GACA,SAAS,CAAC,cAAc,UAAU,IAAI,wBAAwB,KAAA;EAChE,EAAE;EACF;GAAE,OAAO;GAAQ,OAAO,MAAM,OAAO;EAAE;CACzC;CACA,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,QAAQ,QAAQ,IAAI,OAAO,CAAC,CAAC,KAAK,QAAQ,yBAAyB,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC;CAEpH,OAAO,KAAK,KAAK,EAAE,OAAO,OAAO,cAAc;EAC7C,MAAM,OAAO,KAAK,MAAM,OAAO,EAAE,EAAE,IAAI;EACvC,OAAO,UAAU,GAAG,OAAO,IAAI,OAAO,QAAQ,yBAAyB,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,UAAU,OAAO,OAAO,MAAM;CAC5H,CAAC;AACH"}
1
+ {"version":3,"file":"status-BdjS4SMJ.js","names":[],"sources":["../src/runners/studio/status.ts"],"sourcesContent":["import { homedir } from 'node:os'\nimport path from 'node:path'\nimport { stripVTControlCharacters, styleText } from 'node:util'\nimport { isPathInside } from '@internals/utils'\nimport type { Credentials } from './credentials.ts'\nimport { formatPermissionRows, type WorkerState } from './run.ts'\n\ntype StatusInput = {\n studioUrl: string\n credentials: Credentials | null\n worker: { running: boolean; state: WorkerState; pid?: number; startedAt?: number }\n project: string\n logPath: string\n now?: number\n}\n\n/** How long a worker has run, such as `2h 14m`, `5m` or `40s`. */\nexport function formatUptime(ms: number): string {\n const minutes = Math.floor(ms / 60_000)\n if (minutes < 1) return `${Math.max(0, Math.floor(ms / 1000))}s`\n if (minutes < 60) return `${minutes}m`\n\n return `${Math.floor(minutes / 60)}h ${minutes % 60}m`\n}\n\nconst tilde = (file: string) => (isPathInside(file, homedir()) ? `~${file.slice(homedir().length)}` : file)\n\n/**\n * The `kubb studio status` table: one row per topic, each ending with the command that changes it.\n */\nexport function formatStatus({ studioUrl, credentials, worker, project, logPath, now = Date.now() }: StatusInput): Array<string> {\n const pairing = (() => {\n if (!credentials) return { value: `${styleText('red', '✖')} not paired`, command: 'kubb studio login' }\n const name = `${credentials.agentSlug || credentials.agentId}${credentials.organizationSlug ? ` · org ${credentials.organizationSlug}` : ''}`\n if (credentials.studioUrl !== studioUrl) return { value: `${styleText('yellow', '!')} ${name} · ${credentials.studioUrl}`, command: 'kubb studio login' }\n return { value: `${styleText('green', '✓')} ${name}`, command: 'kubb studio logout' }\n })()\n const uptime = worker.startedAt ? ` · up ${formatUptime(now - worker.startedAt)}` : ''\n const workerRow = worker.running\n ? { value: `${styleText('green', '●')} ${worker.state} · PID ${worker.pid}${uptime}`, command: 'kubb studio stop' }\n : { value: `${styleText('dim', '○')} ${worker.state}`, command: 'kubb studio start' }\n const remembered = credentials?.projects?.[project]\n const permissions = remembered ? formatPermissionRows(remembered) : [styleText('dim', 'not chosen yet')]\n\n const rows: Array<{ label: string; value: string; command?: string }> = [\n { label: 'Pairing', ...pairing },\n { label: 'Worker', ...workerRow },\n { label: 'Project', value: `${path.basename(project)} · ${tilde(project)}` },\n ...permissions.map((value, index) => ({\n label: index === 0 ? 'Permissions' : '',\n value,\n command: !remembered && index === 0 ? 'kubb studio connect' : undefined,\n })),\n { label: 'Logs', value: tilde(logPath) },\n ]\n const width = Math.max(...rows.filter((row) => row.command).map((row) => stripVTControlCharacters(row.value).length))\n\n return rows.map(({ label, value, command }) => {\n const line = ` ${label.padEnd(11)} ${value}`\n return command ? `${line}${' '.repeat(width - stripVTControlCharacters(value).length + 3)}${styleText('dim', command)}` : line\n })\n}\n"],"mappings":";;;;;;;;AAiBA,SAAgB,aAAa,IAAoB;CAC/C,MAAM,UAAU,KAAK,MAAM,KAAK,GAAM;CACtC,IAAI,UAAU,GAAG,OAAO,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,GAAI,CAAC,EAAE;CAC9D,IAAI,UAAU,IAAI,OAAO,GAAG,QAAQ;CAEpC,OAAO,GAAG,KAAK,MAAM,UAAU,EAAE,EAAE,IAAI,UAAU,GAAG;AACtD;AAEA,MAAM,SAAS,SAAkB,aAAa,MAAM,QAAQ,CAAC,IAAI,IAAI,KAAK,MAAM,QAAQ,CAAC,CAAC,MAAM,MAAM;;;;AAKtG,SAAgB,aAAa,EAAE,WAAW,aAAa,QAAQ,SAAS,SAAS,MAAM,KAAK,IAAI,KAAiC;CAC/H,MAAM,iBAAiB;EACrB,IAAI,CAAC,aAAa,OAAO;GAAE,OAAO,GAAG,UAAU,OAAO,GAAG,EAAE;GAAc,SAAS;EAAoB;EACtG,MAAM,OAAO,GAAG,YAAY,aAAa,YAAY,UAAU,YAAY,mBAAmB,UAAU,YAAY,qBAAqB;EACzI,IAAI,YAAY,cAAc,WAAW,OAAO;GAAE,OAAO,GAAG,UAAU,UAAU,GAAG,EAAE,GAAG,KAAK,KAAK,YAAY;GAAa,SAAS;EAAoB;EACxJ,OAAO;GAAE,OAAO,GAAG,UAAU,SAAS,GAAG,EAAE,GAAG;GAAQ,SAAS;EAAqB;CACtF,EAAA,CAAG;CACH,MAAM,SAAS,OAAO,YAAY,SAAS,aAAa,MAAM,OAAO,SAAS,MAAM;CACpF,MAAM,YAAY,OAAO,UACrB;EAAE,OAAO,GAAG,UAAU,SAAS,GAAG,EAAE,GAAG,OAAO,MAAM,SAAS,OAAO,MAAM;EAAU,SAAS;CAAmB,IAChH;EAAE,OAAO,GAAG,UAAU,OAAO,GAAG,EAAE,GAAG,OAAO;EAAS,SAAS;CAAoB;CACtF,MAAM,aAAa,aAAa,WAAW;CAC3C,MAAM,cAAc,aAAa,qBAAqB,UAAU,IAAI,CAAC,UAAU,OAAO,gBAAgB,CAAC;CAEvG,MAAM,OAAkE;EACtE;GAAE,OAAO;GAAW,GAAG;EAAQ;EAC/B;GAAE,OAAO;GAAU,GAAG;EAAU;EAChC;GAAE,OAAO;GAAW,OAAO,GAAG,KAAK,SAAS,OAAO,EAAE,KAAK,MAAM,OAAO;EAAI;EAC3E,GAAG,YAAY,KAAK,OAAO,WAAW;GACpC,OAAO,UAAU,IAAI,gBAAgB;GACrC;GACA,SAAS,CAAC,cAAc,UAAU,IAAI,wBAAwB,KAAA;EAChE,EAAE;EACF;GAAE,OAAO;GAAQ,OAAO,MAAM,OAAO;EAAE;CACzC;CACA,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,QAAQ,QAAQ,IAAI,OAAO,CAAC,CAAC,KAAK,QAAQ,yBAAyB,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC;CAEpH,OAAO,KAAK,KAAK,EAAE,OAAO,OAAO,cAAc;EAC7C,MAAM,OAAO,KAAK,MAAM,OAAO,EAAE,EAAE,IAAI;EACvC,OAAO,UAAU,GAAG,OAAO,IAAI,OAAO,QAAQ,yBAAyB,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,UAAU,OAAO,OAAO,MAAM;CAC5H,CAAC;AACH"}
@@ -1,6 +1,6 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-CPE0t6oh.cjs");
2
- const require_utils = require("./utils-Ckbz012p.cjs");
3
- const require_run = require("./run-w92b045L.cjs");
2
+ const require_utils = require("./utils-SIv7oWeS.cjs");
3
+ const require_run = require("./run-ChCjDopB.cjs");
4
4
  let node_util = require("node:util");
5
5
  let node_os = require("node:os");
6
6
  let node_path = require("node:path");
@@ -75,4 +75,4 @@ function formatStatus({ studioUrl, credentials, worker, project, logPath, now =
75
75
  //#endregion
76
76
  exports.formatStatus = formatStatus;
77
77
 
78
- //# sourceMappingURL=status-CteZmcug.cjs.map
78
+ //# sourceMappingURL=status-BkXcEOmp.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"status-CteZmcug.cjs","names":["isPathInside","homedir","styleText","formatPermissionRows","path","stripVTControlCharacters"],"sources":["../src/runners/studio/status.ts"],"sourcesContent":["import { homedir } from 'node:os'\nimport path from 'node:path'\nimport { stripVTControlCharacters, styleText } from 'node:util'\nimport { isPathInside } from '@internals/utils'\nimport type { Credentials } from './credentials.ts'\nimport { formatPermissionRows, type WorkerState } from './run.ts'\n\ntype StatusInput = {\n studioUrl: string\n credentials: Credentials | null\n worker: { running: boolean; state: WorkerState; pid?: number; startedAt?: number }\n project: string\n logPath: string\n now?: number\n}\n\n/** How long a worker has run, such as `2h 14m`, `5m` or `40s`. */\nexport function formatUptime(ms: number): string {\n const minutes = Math.floor(ms / 60_000)\n if (minutes < 1) return `${Math.max(0, Math.floor(ms / 1000))}s`\n if (minutes < 60) return `${minutes}m`\n\n return `${Math.floor(minutes / 60)}h ${minutes % 60}m`\n}\n\nconst tilde = (file: string) => (isPathInside(file, homedir()) ? `~${file.slice(homedir().length)}` : file)\n\n/**\n * The `kubb studio status` table: one row per topic, each ending with the command that changes it.\n */\nexport function formatStatus({ studioUrl, credentials, worker, project, logPath, now = Date.now() }: StatusInput): Array<string> {\n const pairing = (() => {\n if (!credentials) return { value: `${styleText('red', '✖')} not paired`, command: 'kubb studio login' }\n const name = `${credentials.agentSlug || credentials.agentId}${credentials.organizationSlug ? ` · org ${credentials.organizationSlug}` : ''}`\n if (credentials.studioUrl !== studioUrl) return { value: `${styleText('yellow', '!')} ${name} · ${credentials.studioUrl}`, command: 'kubb studio login' }\n return { value: `${styleText('green', '✓')} ${name}`, command: 'kubb studio logout' }\n })()\n const uptime = worker.startedAt ? ` · up ${formatUptime(now - worker.startedAt)}` : ''\n const workerRow = worker.running\n ? { value: `${styleText('green', '●')} ${worker.state} · PID ${worker.pid}${uptime}`, command: 'kubb studio stop' }\n : { value: `${styleText('dim', '○')} ${worker.state}`, command: 'kubb studio start' }\n const remembered = credentials?.projects?.[project]\n const permissions = remembered ? formatPermissionRows(remembered) : [styleText('dim', 'not chosen yet')]\n\n const rows: Array<{ label: string; value: string; command?: string }> = [\n { label: 'Pairing', ...pairing },\n { label: 'Worker', ...workerRow },\n { label: 'Project', value: `${path.basename(project)} · ${tilde(project)}` },\n ...permissions.map((value, index) => ({\n label: index === 0 ? 'Permissions' : '',\n value,\n command: !remembered && index === 0 ? 'kubb studio connect' : undefined,\n })),\n { label: 'Logs', value: tilde(logPath) },\n ]\n const width = Math.max(...rows.filter((row) => row.command).map((row) => stripVTControlCharacters(row.value).length))\n\n return rows.map(({ label, value, command }) => {\n const line = ` ${label.padEnd(11)} ${value}`\n return command ? `${line}${' '.repeat(width - stripVTControlCharacters(value).length + 3)}${styleText('dim', command)}` : line\n })\n}\n"],"mappings":";;;;;;;;;AAiBA,SAAgB,aAAa,IAAoB;CAC/C,MAAM,UAAU,KAAK,MAAM,KAAK,GAAM;CACtC,IAAI,UAAU,GAAG,OAAO,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,GAAI,CAAC,EAAE;CAC9D,IAAI,UAAU,IAAI,OAAO,GAAG,QAAQ;CAEpC,OAAO,GAAG,KAAK,MAAM,UAAU,EAAE,EAAE,IAAI,UAAU,GAAG;AACtD;AAEA,MAAM,SAAS,SAAkBA,cAAAA,aAAa,OAAA,GAAMC,QAAAA,QAAAA,CAAQ,CAAC,IAAI,IAAI,KAAK,OAAA,GAAMA,QAAAA,QAAAA,CAAQ,CAAC,CAAC,MAAM,MAAM;;;;AAKtG,SAAgB,aAAa,EAAE,WAAW,aAAa,QAAQ,SAAS,SAAS,MAAM,KAAK,IAAI,KAAiC;CAC/H,MAAM,iBAAiB;EACrB,IAAI,CAAC,aAAa,OAAO;GAAE,OAAO,IAAA,GAAGC,UAAAA,UAAAA,CAAU,OAAO,GAAG,EAAE;GAAc,SAAS;EAAoB;EACtG,MAAM,OAAO,GAAG,YAAY,aAAa,YAAY,UAAU,YAAY,mBAAmB,UAAU,YAAY,qBAAqB;EACzI,IAAI,YAAY,cAAc,WAAW,OAAO;GAAE,OAAO,IAAA,GAAGA,UAAAA,UAAAA,CAAU,UAAU,GAAG,EAAE,GAAG,KAAK,KAAK,YAAY;GAAa,SAAS;EAAoB;EACxJ,OAAO;GAAE,OAAO,IAAA,GAAGA,UAAAA,UAAAA,CAAU,SAAS,GAAG,EAAE,GAAG;GAAQ,SAAS;EAAqB;CACtF,EAAA,CAAG;CACH,MAAM,SAAS,OAAO,YAAY,SAAS,aAAa,MAAM,OAAO,SAAS,MAAM;CACpF,MAAM,YAAY,OAAO,UACrB;EAAE,OAAO,IAAA,GAAGA,UAAAA,UAAAA,CAAU,SAAS,GAAG,EAAE,GAAG,OAAO,MAAM,SAAS,OAAO,MAAM;EAAU,SAAS;CAAmB,IAChH;EAAE,OAAO,IAAA,GAAGA,UAAAA,UAAAA,CAAU,OAAO,GAAG,EAAE,GAAG,OAAO;EAAS,SAAS;CAAoB;CACtF,MAAM,aAAa,aAAa,WAAW;CAC3C,MAAM,cAAc,aAAaC,YAAAA,qBAAqB,UAAU,IAAI,EAAA,GAACD,UAAAA,UAAAA,CAAU,OAAO,gBAAgB,CAAC;CAEvG,MAAM,OAAkE;EACtE;GAAE,OAAO;GAAW,GAAG;EAAQ;EAC/B;GAAE,OAAO;GAAU,GAAG;EAAU;EAChC;GAAE,OAAO;GAAW,OAAO,GAAGE,UAAAA,QAAK,SAAS,OAAO,EAAE,KAAK,MAAM,OAAO;EAAI;EAC3E,GAAG,YAAY,KAAK,OAAO,WAAW;GACpC,OAAO,UAAU,IAAI,gBAAgB;GACrC;GACA,SAAS,CAAC,cAAc,UAAU,IAAI,wBAAwB,KAAA;EAChE,EAAE;EACF;GAAE,OAAO;GAAQ,OAAO,MAAM,OAAO;EAAE;CACzC;CACA,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,QAAQ,QAAQ,IAAI,OAAO,CAAC,CAAC,KAAK,SAAA,GAAQC,UAAAA,yBAAAA,CAAyB,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC;CAEpH,OAAO,KAAK,KAAK,EAAE,OAAO,OAAO,cAAc;EAC7C,MAAM,OAAO,KAAK,MAAM,OAAO,EAAE,EAAE,IAAI;EACvC,OAAO,UAAU,GAAG,OAAO,IAAI,OAAO,SAAA,GAAQA,UAAAA,yBAAAA,CAAyB,KAAK,CAAC,CAAC,SAAS,CAAC,KAAA,GAAIH,UAAAA,UAAAA,CAAU,OAAO,OAAO,MAAM;CAC5H,CAAC;AACH"}
1
+ {"version":3,"file":"status-BkXcEOmp.cjs","names":["isPathInside","homedir","styleText","formatPermissionRows","path","stripVTControlCharacters"],"sources":["../src/runners/studio/status.ts"],"sourcesContent":["import { homedir } from 'node:os'\nimport path from 'node:path'\nimport { stripVTControlCharacters, styleText } from 'node:util'\nimport { isPathInside } from '@internals/utils'\nimport type { Credentials } from './credentials.ts'\nimport { formatPermissionRows, type WorkerState } from './run.ts'\n\ntype StatusInput = {\n studioUrl: string\n credentials: Credentials | null\n worker: { running: boolean; state: WorkerState; pid?: number; startedAt?: number }\n project: string\n logPath: string\n now?: number\n}\n\n/** How long a worker has run, such as `2h 14m`, `5m` or `40s`. */\nexport function formatUptime(ms: number): string {\n const minutes = Math.floor(ms / 60_000)\n if (minutes < 1) return `${Math.max(0, Math.floor(ms / 1000))}s`\n if (minutes < 60) return `${minutes}m`\n\n return `${Math.floor(minutes / 60)}h ${minutes % 60}m`\n}\n\nconst tilde = (file: string) => (isPathInside(file, homedir()) ? `~${file.slice(homedir().length)}` : file)\n\n/**\n * The `kubb studio status` table: one row per topic, each ending with the command that changes it.\n */\nexport function formatStatus({ studioUrl, credentials, worker, project, logPath, now = Date.now() }: StatusInput): Array<string> {\n const pairing = (() => {\n if (!credentials) return { value: `${styleText('red', '✖')} not paired`, command: 'kubb studio login' }\n const name = `${credentials.agentSlug || credentials.agentId}${credentials.organizationSlug ? ` · org ${credentials.organizationSlug}` : ''}`\n if (credentials.studioUrl !== studioUrl) return { value: `${styleText('yellow', '!')} ${name} · ${credentials.studioUrl}`, command: 'kubb studio login' }\n return { value: `${styleText('green', '✓')} ${name}`, command: 'kubb studio logout' }\n })()\n const uptime = worker.startedAt ? ` · up ${formatUptime(now - worker.startedAt)}` : ''\n const workerRow = worker.running\n ? { value: `${styleText('green', '●')} ${worker.state} · PID ${worker.pid}${uptime}`, command: 'kubb studio stop' }\n : { value: `${styleText('dim', '○')} ${worker.state}`, command: 'kubb studio start' }\n const remembered = credentials?.projects?.[project]\n const permissions = remembered ? formatPermissionRows(remembered) : [styleText('dim', 'not chosen yet')]\n\n const rows: Array<{ label: string; value: string; command?: string }> = [\n { label: 'Pairing', ...pairing },\n { label: 'Worker', ...workerRow },\n { label: 'Project', value: `${path.basename(project)} · ${tilde(project)}` },\n ...permissions.map((value, index) => ({\n label: index === 0 ? 'Permissions' : '',\n value,\n command: !remembered && index === 0 ? 'kubb studio connect' : undefined,\n })),\n { label: 'Logs', value: tilde(logPath) },\n ]\n const width = Math.max(...rows.filter((row) => row.command).map((row) => stripVTControlCharacters(row.value).length))\n\n return rows.map(({ label, value, command }) => {\n const line = ` ${label.padEnd(11)} ${value}`\n return command ? `${line}${' '.repeat(width - stripVTControlCharacters(value).length + 3)}${styleText('dim', command)}` : line\n })\n}\n"],"mappings":";;;;;;;;;AAiBA,SAAgB,aAAa,IAAoB;CAC/C,MAAM,UAAU,KAAK,MAAM,KAAK,GAAM;CACtC,IAAI,UAAU,GAAG,OAAO,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,GAAI,CAAC,EAAE;CAC9D,IAAI,UAAU,IAAI,OAAO,GAAG,QAAQ;CAEpC,OAAO,GAAG,KAAK,MAAM,UAAU,EAAE,EAAE,IAAI,UAAU,GAAG;AACtD;AAEA,MAAM,SAAS,SAAkBA,cAAAA,aAAa,OAAA,GAAMC,QAAAA,QAAAA,CAAQ,CAAC,IAAI,IAAI,KAAK,OAAA,GAAMA,QAAAA,QAAAA,CAAQ,CAAC,CAAC,MAAM,MAAM;;;;AAKtG,SAAgB,aAAa,EAAE,WAAW,aAAa,QAAQ,SAAS,SAAS,MAAM,KAAK,IAAI,KAAiC;CAC/H,MAAM,iBAAiB;EACrB,IAAI,CAAC,aAAa,OAAO;GAAE,OAAO,IAAA,GAAGC,UAAAA,UAAAA,CAAU,OAAO,GAAG,EAAE;GAAc,SAAS;EAAoB;EACtG,MAAM,OAAO,GAAG,YAAY,aAAa,YAAY,UAAU,YAAY,mBAAmB,UAAU,YAAY,qBAAqB;EACzI,IAAI,YAAY,cAAc,WAAW,OAAO;GAAE,OAAO,IAAA,GAAGA,UAAAA,UAAAA,CAAU,UAAU,GAAG,EAAE,GAAG,KAAK,KAAK,YAAY;GAAa,SAAS;EAAoB;EACxJ,OAAO;GAAE,OAAO,IAAA,GAAGA,UAAAA,UAAAA,CAAU,SAAS,GAAG,EAAE,GAAG;GAAQ,SAAS;EAAqB;CACtF,EAAA,CAAG;CACH,MAAM,SAAS,OAAO,YAAY,SAAS,aAAa,MAAM,OAAO,SAAS,MAAM;CACpF,MAAM,YAAY,OAAO,UACrB;EAAE,OAAO,IAAA,GAAGA,UAAAA,UAAAA,CAAU,SAAS,GAAG,EAAE,GAAG,OAAO,MAAM,SAAS,OAAO,MAAM;EAAU,SAAS;CAAmB,IAChH;EAAE,OAAO,IAAA,GAAGA,UAAAA,UAAAA,CAAU,OAAO,GAAG,EAAE,GAAG,OAAO;EAAS,SAAS;CAAoB;CACtF,MAAM,aAAa,aAAa,WAAW;CAC3C,MAAM,cAAc,aAAaC,YAAAA,qBAAqB,UAAU,IAAI,EAAA,GAACD,UAAAA,UAAAA,CAAU,OAAO,gBAAgB,CAAC;CAEvG,MAAM,OAAkE;EACtE;GAAE,OAAO;GAAW,GAAG;EAAQ;EAC/B;GAAE,OAAO;GAAU,GAAG;EAAU;EAChC;GAAE,OAAO;GAAW,OAAO,GAAGE,UAAAA,QAAK,SAAS,OAAO,EAAE,KAAK,MAAM,OAAO;EAAI;EAC3E,GAAG,YAAY,KAAK,OAAO,WAAW;GACpC,OAAO,UAAU,IAAI,gBAAgB;GACrC;GACA,SAAS,CAAC,cAAc,UAAU,IAAI,wBAAwB,KAAA;EAChE,EAAE;EACF;GAAE,OAAO;GAAQ,OAAO,MAAM,OAAO;EAAE;CACzC;CACA,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,QAAQ,QAAQ,IAAI,OAAO,CAAC,CAAC,KAAK,SAAA,GAAQC,UAAAA,yBAAAA,CAAyB,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC;CAEpH,OAAO,KAAK,KAAK,EAAE,OAAO,OAAO,cAAc;EAC7C,MAAM,OAAO,KAAK,MAAM,OAAO,EAAE,EAAE,IAAI;EACvC,OAAO,UAAU,GAAG,OAAO,IAAI,OAAO,SAAA,GAAQA,UAAAA,yBAAAA,CAAyB,KAAK,CAAC,CAAC,SAAS,CAAC,KAAA,GAAIH,UAAAA,UAAAA,CAAU,OAAO,OAAO,MAAM;CAC5H,CAAC;AACH"}
@@ -1,6 +1,6 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { t as connect } from "./run-kRFuEqeA.js";
3
- import { r as serveWorker, t as getWorkerLogPath } from "./background-DY4LTodc.js";
2
+ import { t as connect } from "./run-A2hHeAoZ.js";
3
+ import { r as serveWorker, t as getWorkerLogPath } from "./background-D-ujLRoU.js";
4
4
  import { format } from "node:util";
5
5
  import { appendFileSync, statSync, writeFileSync } from "node:fs";
6
6
  //#region src/runners/studio/worker.ts
@@ -1,6 +1,6 @@
1
1
  require("./rolldown-runtime-CPE0t6oh.cjs");
2
- const require_Telemetry = require("./Telemetry-0Sr_THx9.cjs");
3
- const require_text = require("./text-DVPYqR74.cjs");
2
+ const require_Telemetry = require("./Telemetry-CZmpqKZm.cjs");
3
+ const require_text = require("./text-CtdDig0T.cjs");
4
4
  let node_util = require("node:util");
5
5
  //#region src/ui/summary.ts
6
6
  /**
@@ -43,4 +43,4 @@ Object.defineProperty(exports, "logCommandSummary", {
43
43
  }
44
44
  });
45
45
 
46
- //# sourceMappingURL=summary-BuKuPfE_.cjs.map
46
+ //# sourceMappingURL=summary-BdvaJ0_J.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"summary-BuKuPfE_.cjs","names":["styleText","formatMs","getElapsedMs"],"sources":["../src/ui/summary.ts"],"sourcesContent":["import { styleText } from 'node:util'\nimport { formatMs, getElapsedMs } from '@internals/utils'\nimport { logOutro } from './intro.ts'\n\n/**\n * Finishes a command with its outcome and duration before the labeled details.\n * A command with prompts closes its existing block; validation writes a standalone summary.\n */\nexport function logCommandSummary({\n title,\n status,\n hrStart,\n lines,\n block = false,\n}: {\n title: string\n status: 'success' | 'failed' | 'warning' | 'planned' | 'canceled'\n hrStart: [number, number]\n lines: ReadonlyArray<string>\n block?: boolean\n}): void {\n const colors = { success: 'green', failed: 'red', warning: 'yellow', planned: 'cyan', canceled: 'dim' } as const\n const symbols = { success: '✓', failed: '✗', warning: '!', planned: '◇', canceled: '○' } as const\n const summary = [`${styleText(colors[status], `${symbols[status]} ${title}`)} ${styleText('dim', formatMs(getElapsedMs(hrStart)))}`, '', ...lines].join('\\n')\n if (block) {\n logOutro(summary)\n return\n }\n if (status === 'failed') {\n console.error(summary)\n return\n }\n console.log(summary)\n}\n"],"mappings":";;;;;;;;;AAQA,SAAgB,kBAAkB,EAChC,OACA,QACA,SACA,OACA,QAAQ,SAOD;CAGP,MAAM,UAAU;EAAC,IAAA,GAAGA,UAAAA,UAAAA,CAAU;GAFb,SAAS;GAAS,QAAQ;GAAO,SAAS;GAAU,SAAS;GAAQ,UAAU;EAE7D,EAAE,SAAS,GAAG;GAD/B,SAAS;GAAK,QAAQ;GAAK,SAAS;GAAK,SAAS;GAAK,UAAU;EAC5B,EAAE,QAAQ,GAAG,OAAO,EAAE,KAAA,GAAIA,UAAAA,UAAAA,CAAU,OAAOC,kBAAAA,SAASC,kBAAAA,aAAa,OAAO,CAAC,CAAC;EAAK;EAAI,GAAG;CAAK,CAAC,CAAC,KAAK,IAAI;CAC7J,IAAI,OAAO;EACT,aAAA,SAAS,OAAO;EAChB;CACF;CACA,IAAI,WAAW,UAAU;EACvB,QAAQ,MAAM,OAAO;EACrB;CACF;CACA,QAAQ,IAAI,OAAO;AACrB"}
1
+ {"version":3,"file":"summary-BdvaJ0_J.cjs","names":["styleText","formatMs","getElapsedMs"],"sources":["../src/ui/summary.ts"],"sourcesContent":["import { styleText } from 'node:util'\nimport { formatMs, getElapsedMs } from '@internals/utils'\nimport { logOutro } from './intro.ts'\n\n/**\n * Finishes a command with its outcome and duration before the labeled details.\n * A command with prompts closes its existing block; validation writes a standalone summary.\n */\nexport function logCommandSummary({\n title,\n status,\n hrStart,\n lines,\n block = false,\n}: {\n title: string\n status: 'success' | 'failed' | 'warning' | 'planned' | 'canceled'\n hrStart: [number, number]\n lines: ReadonlyArray<string>\n block?: boolean\n}): void {\n const colors = { success: 'green', failed: 'red', warning: 'yellow', planned: 'cyan', canceled: 'dim' } as const\n const symbols = { success: '✓', failed: '✗', warning: '!', planned: '◇', canceled: '○' } as const\n const summary = [`${styleText(colors[status], `${symbols[status]} ${title}`)} ${styleText('dim', formatMs(getElapsedMs(hrStart)))}`, '', ...lines].join('\\n')\n if (block) {\n logOutro(summary)\n return\n }\n if (status === 'failed') {\n console.error(summary)\n return\n }\n console.log(summary)\n}\n"],"mappings":";;;;;;;;;AAQA,SAAgB,kBAAkB,EAChC,OACA,QACA,SACA,OACA,QAAQ,SAOD;CAGP,MAAM,UAAU;EAAC,IAAA,GAAGA,UAAAA,UAAAA,CAAU;GAFb,SAAS;GAAS,QAAQ;GAAO,SAAS;GAAU,SAAS;GAAQ,UAAU;EAE7D,EAAE,SAAS,GAAG;GAD/B,SAAS;GAAK,QAAQ;GAAK,SAAS;GAAK,SAAS;GAAK,UAAU;EAC5B,EAAE,QAAQ,GAAG,OAAO,EAAE,KAAA,GAAIA,UAAAA,UAAAA,CAAU,OAAOC,kBAAAA,SAASC,kBAAAA,aAAa,OAAO,CAAC,CAAC;EAAK;EAAI,GAAG;CAAK,CAAC,CAAC,KAAK,IAAI;CAC7J,IAAI,OAAO;EACT,aAAA,SAAS,OAAO;EAChB;CACF;CACA,IAAI,WAAW,UAAU;EACvB,QAAQ,MAAM,OAAO;EACrB;CACF;CACA,QAAQ,IAAI,OAAO;AACrB"}
@@ -1,6 +1,6 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { a as getElapsedMs, i as formatMs } from "./Telemetry-B4hk3xGv.js";
3
- import { a as logOutro } from "./text-CaZG0KF2.js";
2
+ import { a as getElapsedMs, i as formatMs } from "./Telemetry-DdoOJOS1.js";
3
+ import { a as logOutro } from "./text-BK8L4Xtr.js";
4
4
  import { styleText } from "node:util";
5
5
  //#region src/ui/summary.ts
6
6
  /**
@@ -38,4 +38,4 @@ function logCommandSummary({ title, status, hrStart, lines, block = false }) {
38
38
  //#endregion
39
39
  export { logCommandSummary as t };
40
40
 
41
- //# sourceMappingURL=summary-B1aj8T_V.js.map
41
+ //# sourceMappingURL=summary-DKqx3K4w.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"summary-B1aj8T_V.js","names":[],"sources":["../src/ui/summary.ts"],"sourcesContent":["import { styleText } from 'node:util'\nimport { formatMs, getElapsedMs } from '@internals/utils'\nimport { logOutro } from './intro.ts'\n\n/**\n * Finishes a command with its outcome and duration before the labeled details.\n * A command with prompts closes its existing block; validation writes a standalone summary.\n */\nexport function logCommandSummary({\n title,\n status,\n hrStart,\n lines,\n block = false,\n}: {\n title: string\n status: 'success' | 'failed' | 'warning' | 'planned' | 'canceled'\n hrStart: [number, number]\n lines: ReadonlyArray<string>\n block?: boolean\n}): void {\n const colors = { success: 'green', failed: 'red', warning: 'yellow', planned: 'cyan', canceled: 'dim' } as const\n const symbols = { success: '✓', failed: '✗', warning: '!', planned: '◇', canceled: '○' } as const\n const summary = [`${styleText(colors[status], `${symbols[status]} ${title}`)} ${styleText('dim', formatMs(getElapsedMs(hrStart)))}`, '', ...lines].join('\\n')\n if (block) {\n logOutro(summary)\n return\n }\n if (status === 'failed') {\n console.error(summary)\n return\n }\n console.log(summary)\n}\n"],"mappings":";;;;;;;;;AAQA,SAAgB,kBAAkB,EAChC,OACA,QACA,SACA,OACA,QAAQ,SAOD;CAGP,MAAM,UAAU;EAAC,GAAG,UAAU;GAFb,SAAS;GAAS,QAAQ;GAAO,SAAS;GAAU,SAAS;GAAQ,UAAU;EAE7D,EAAE,SAAS,GAAG;GAD/B,SAAS;GAAK,QAAQ;GAAK,SAAS;GAAK,SAAS;GAAK,UAAU;EAC5B,EAAE,QAAQ,GAAG,OAAO,EAAE,IAAI,UAAU,OAAO,SAAS,aAAa,OAAO,CAAC,CAAC;EAAK;EAAI,GAAG;CAAK,CAAC,CAAC,KAAK,IAAI;CAC7J,IAAI,OAAO;EACT,SAAS,OAAO;EAChB;CACF;CACA,IAAI,WAAW,UAAU;EACvB,QAAQ,MAAM,OAAO;EACrB;CACF;CACA,QAAQ,IAAI,OAAO;AACrB"}
1
+ {"version":3,"file":"summary-DKqx3K4w.js","names":[],"sources":["../src/ui/summary.ts"],"sourcesContent":["import { styleText } from 'node:util'\nimport { formatMs, getElapsedMs } from '@internals/utils'\nimport { logOutro } from './intro.ts'\n\n/**\n * Finishes a command with its outcome and duration before the labeled details.\n * A command with prompts closes its existing block; validation writes a standalone summary.\n */\nexport function logCommandSummary({\n title,\n status,\n hrStart,\n lines,\n block = false,\n}: {\n title: string\n status: 'success' | 'failed' | 'warning' | 'planned' | 'canceled'\n hrStart: [number, number]\n lines: ReadonlyArray<string>\n block?: boolean\n}): void {\n const colors = { success: 'green', failed: 'red', warning: 'yellow', planned: 'cyan', canceled: 'dim' } as const\n const symbols = { success: '✓', failed: '✗', warning: '!', planned: '◇', canceled: '○' } as const\n const summary = [`${styleText(colors[status], `${symbols[status]} ${title}`)} ${styleText('dim', formatMs(getElapsedMs(hrStart)))}`, '', ...lines].join('\\n')\n if (block) {\n logOutro(summary)\n return\n }\n if (status === 'failed') {\n console.error(summary)\n return\n }\n console.log(summary)\n}\n"],"mappings":";;;;;;;;;AAQA,SAAgB,kBAAkB,EAChC,OACA,QACA,SACA,OACA,QAAQ,SAOD;CAGP,MAAM,UAAU;EAAC,GAAG,UAAU;GAFb,SAAS;GAAS,QAAQ;GAAO,SAAS;GAAU,SAAS;GAAQ,UAAU;EAE7D,EAAE,SAAS,GAAG;GAD/B,SAAS;GAAK,QAAQ;GAAK,SAAS;GAAK,SAAS;GAAK,UAAU;EAC5B,EAAE,QAAQ,GAAG,OAAO,EAAE,IAAI,UAAU,OAAO,SAAS,aAAa,OAAO,CAAC,CAAC;EAAK;EAAI,GAAG;CAAK,CAAC,CAAC,KAAK,IAAI;CAC7J,IAAI,OAAO;EACT,SAAS,OAAO;EAChB;CACF;CACA,IAAI,WAAW,UAAU;EACvB,QAAQ,MAAM,OAAO;EACrB;CACF;CACA,QAAQ,IAAI,OAAO;AACrB"}
@@ -1,5 +1,5 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { s as isCIEnvironment } from "./Telemetry-B4hk3xGv.js";
2
+ import { s as isCIEnvironment } from "./Telemetry-DdoOJOS1.js";
3
3
  import { styleText } from "node:util";
4
4
  import { getAgentProfile } from "gunshi/agent";
5
5
  import * as clack from "@clack/prompts";
@@ -236,4 +236,4 @@ function toPermissionFlag(key) {
236
236
  //#endregion
237
237
  export { isRichOutput as _, logOutro as a, logBlock as c, logStep as d, logWarn as f, canUseTTY as g, plainWriter as h, logIntro as i, logError as l, createPlainWriter as m, toPermissionFlag as n, logSpacer as o, writer as p, isInteractiveRun as r, logTip as s, pluralize as t, logInfo as u };
238
238
 
239
- //# sourceMappingURL=text-CaZG0KF2.js.map
239
+ //# sourceMappingURL=text-BK8L4Xtr.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"text-CaZG0KF2.js","names":[],"sources":["../src/utils/env.ts","../src/loggers/clackWriter.ts","../src/loggers/plainWriter.ts","../src/ui/log.ts","../src/ui/intro.ts","../src/ui/text.ts"],"sourcesContent":["import { isCIEnvironment } from '@internals/utils'\nimport { getAgentProfile } from 'gunshi/agent'\n\n/**\n * Returns `true` when the process has an interactive TTY with a valid terminal\n * width and is not running in CI.\n *\n * Some IDE-embedded terminals report `isTTY = true` but set `columns` to `0`,\n * which breaks clack's box-drawing helpers (they call `String.prototype.repeat`\n * with a negative count and throw a `RangeError`). A positive column count is\n * required before the TTY counts as usable.\n *\n * @example\n * ```ts\n * if (canUseTTY()) {\n * renderProgressBar()\n * }\n * ```\n */\nexport function canUseTTY(): boolean {\n return process.stdout.isTTY && (process.stdout.columns ?? 0) > 0 && !isCIEnvironment()\n}\n\n/**\n * Returns `true` when output can carry spinners and clack's gutter: an interactive TTY that no AI\n * coding agent is reading. Cursor-movement escapes are hard for an agent to parse even over a\n * pseudo-TTY, so it gets the plain writer.\n */\nexport function isRichOutput(): boolean {\n return canUseTTY() && !getAgentProfile().isAgent\n}\n","import { styleText } from 'node:util'\nimport * as clack from '@clack/prompts'\nimport type { LoggerWriter } from './types.ts'\n\n/**\n * Draws with clack for local development: a gutter bar per group, animated steps, and a progress\n * bar for the writes.\n */\nexport const clackWriter: LoggerWriter = {\n audience: 'human',\n group: (title) => clack.intro(title),\n groupEnd: (text) => clack.outro(text),\n step: (text) => clack.log.step(text, { spacing: 0 }),\n info: (text) => clack.log.info(text),\n success: (text) => clack.log.success(text),\n warn: (text) => clack.log.warn(text),\n error: (text) => clack.log.error(text),\n block: (lines) => clack.log.message(lines, { spacing: 0 }),\n // A subprocess's output is not Kubb's tree, so it goes out past clack and its gutter bar. The\n // step above it is already stopped by the time this runs.\n raw: (lines) => console.log(styleText('dim', lines.join('\\n'))),\n // The diagnostic carries its own code and indented rows, so clear clack's gutter and bar and let\n // the block stand on its own.\n diagnostic: (lines) => clack.log.message(lines, { symbol: '', secondarySymbol: '' }),\n update: (lines, title) =>\n clack.box(lines.join('\\n'), title, {\n width: 'auto',\n formatBorder: (border: string) => styleText('yellow', border),\n rounded: true,\n withGuide: false,\n contentAlign: 'center',\n titleAlign: 'center',\n }),\n spinner: () => clack.spinner(),\n progress(max) {\n const bar = clack.progress({ style: 'block', max, size: 30 })\n\n return {\n start: (text) => bar.start(text),\n advance: (text) => bar.advance(1, text),\n stop: (text) => bar.stop(text),\n }\n },\n}\n","import type { LoggerWriter } from './types.ts'\n\n/**\n * Prefixes that stand in for the symbols clack draws, so plain output reads the same way.\n */\nexport const SYMBOLS = { info: 'ℹ', warn: '⚠', error: '✗', step: '◇' } as const\n\n/**\n * Draws with one `write` call per line, e.g. `console.error` so stdout carries only JSON. Nothing\n * animates, so a step prints at start and end.\n */\nexport function createPlainWriter(write: (line: string) => void): LoggerWriter {\n return {\n audience: 'agent',\n group: write,\n groupEnd: write,\n step: (text) => write(`${SYMBOLS.step} ${text}`),\n info: write,\n success: write,\n warn: write,\n error: (text) => write(`${SYMBOLS.error} ${text}`),\n block: (lines) => write(lines.join('\\n')),\n raw: (lines) => write(lines.join('\\n')),\n diagnostic: (lines) => write(lines.join('\\n')),\n update: (lines, title) => write([title, ...lines].join('\\n')),\n spinner: () => ({\n start: write,\n message: write,\n clear: () => {},\n stop: (text) => text && write(text),\n error: (text) => write(`${SYMBOLS.error} ${text}`),\n }),\n progress: () => ({\n start: write,\n advance: write,\n stop: (text) => text && write(text),\n }),\n }\n}\n\n/**\n * Draws on the console, for non-TTY environments and for an AI coding agent reading the output.\n * Reports the same run in the same order as `clackWriter`, without the animation.\n */\nexport const plainWriter = createPlainWriter((line) => console.log(line))\n","import * as prompts from '@clack/prompts'\nimport { isRichOutput } from '../utils/env.ts'\nimport { clackWriter } from '../loggers/clackWriter.ts'\nimport { plainWriter, SYMBOLS } from '../loggers/plainWriter.ts'\nimport type { LoggerWriter } from '../loggers/types.ts'\n\n/** The writer the loggers draw with on this terminal, so a command's own lines look like its run. */\nexport function writer(): LoggerWriter {\n return isRichOutput() ? clackWriter : plainWriter\n}\n\ntype Level = keyof typeof SYMBOLS\n\n// Not through the writers: in plain output a command's own info and warning carry their symbol, and clack's step keeps its spacing.\nfunction write(level: Level, message: string): void {\n if (isRichOutput()) {\n prompts.log[level](message)\n\n return\n }\n\n console.log(`${SYMBOLS[level]} ${message}`)\n}\n\n/** Prints lines as one block, without a symbol in front of them. Not the writer's block, which drops clack's spacing around it. */\nexport function logBlock(lines: string | Array<string>): void {\n if (isRichOutput()) {\n prompts.log.message(lines)\n\n return\n }\n\n console.log([lines].flat().join('\\n'))\n}\n\nexport function logInfo(message: string): void {\n write('info', message)\n}\n\nexport function logWarn(message: string): void {\n write('warn', message)\n}\n\nexport function logError(message: string): void {\n write('error', message)\n}\n\n/**\n * Reports a step the command is taking, rather than something it found.\n */\nexport function logStep(message: string): void {\n write('step', message)\n}\n","import { styleText } from 'node:util'\nimport * as prompts from '@clack/prompts'\nimport { isRichOutput } from '../utils/env.ts'\nimport { writer } from './log.ts'\n\nconst SPONSOR_TIPS = [\n 'Your sponsorship keeps Kubb codegen, plugins, and docs maintained',\n 'Sponsor faster generators and better Kubb Studio workflows',\n 'Help keep Kubb free for TypeScript teams building APIs',\n 'Support React Query, Zod, Faker, and MSW integrations',\n 'Back open-source tools that turn OpenAPI into TypeScript',\n 'Sponsor fixes, releases, and new plugins for your API workflow',\n 'Help Kubb stay independent and focused on developer tools',\n] as const\n\nconst SPONSOR_LINKS = ['https://github.com/sponsors/stijnvanhulle', 'https://opencollective.com/kubb', 'https://kubb.dev/sponsors'] as const\n\nfunction nextTip(): string {\n const tip = SPONSOR_TIPS[Math.floor(Math.random() * SPONSOR_TIPS.length)]!\n const link = SPONSOR_LINKS[Math.floor(Math.random() * SPONSOR_LINKS.length)]!\n return `${tip}: ${link}`\n}\n\nfunction formatTip(tip: string): string {\n return styleText('magenta', ' Tip ') + styleText('yellow', tip)\n}\n\n/**\n * Prints one random tip outside every group. Rich terminals get the styled variant;\n * plain/CI output gets a stable text-only line so the tip is still visible as final output.\n */\nexport function logTip(): void {\n const tip = nextTip()\n if (!isRichOutput()) {\n console.log(`Tip: ${tip}`)\n return\n }\n\n console.log(`${styleText('magenta', '✦')}${formatTip(tip)}`)\n}\n\ntype IntroOptions = {\n title?: string\n /**\n * Printed under the title, for a command that has a caveat to lead with.\n */\n warning?: string\n /**\n * Whether to open a block a later {@link logOutro} closes. Pass `false` for a command that\n * prints and exits, since nothing would ever close the block.\n *\n * @default true\n */\n block?: boolean\n}\n\n/**\n * Opens a command's output. A command the banner already names passes no title.\n */\nexport function logIntro({ title, warning, block = true }: IntroOptions): void {\n if (block && isRichOutput()) {\n if (title) prompts.intro(title)\n\n if (warning) {\n prompts.log.warn(warning)\n }\n\n return\n }\n\n if (title) {\n console.log(title)\n }\n\n if (warning) {\n console.warn(warning)\n }\n\n if (title || warning) {\n console.log()\n }\n}\n\n/**\n * Closes the block {@link logIntro} opened. The closing gutter is not a written line, so plain\n * output prints the text on its own.\n */\nexport function logOutro(text: string): void {\n writer().groupEnd(text)\n}\n\n/**\n * Prints one empty line between two groups, without clack's gutter bar, since the bar belongs to a\n * group and a spacer sits outside every one.\n */\nexport function logSpacer(): void {\n console.log('')\n}\n\n/** Whether a run stops to ask something: no `--yes`, no `--dry-run`, and a person at a terminal. */\nexport function isInteractiveRun({ yes, dryRun }: { yes?: unknown; dryRun?: unknown }): boolean {\n return !yes && !dryRun && process.stdin.isTTY === true\n}\n","/** Counts a noun, so a message never reads `1 files`. */\nexport function pluralize(count: number, noun: string): string {\n return `${count} ${count === 1 ? noun : `${noun}s`}`\n}\n\n/** The flag that grants a permission, such as `--allow-read-ast`. */\nexport function toPermissionFlag(key: string): string {\n return `--${key.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`)}`\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"text-BK8L4Xtr.js","names":[],"sources":["../src/utils/env.ts","../src/loggers/clackWriter.ts","../src/loggers/plainWriter.ts","../src/ui/log.ts","../src/ui/intro.ts","../src/ui/text.ts"],"sourcesContent":["import { isCIEnvironment } from '@internals/utils'\nimport { getAgentProfile } from 'gunshi/agent'\n\n/**\n * Returns `true` when the process has an interactive TTY with a valid terminal\n * width and is not running in CI.\n *\n * Some IDE-embedded terminals report `isTTY = true` but set `columns` to `0`,\n * which breaks clack's box-drawing helpers (they call `String.prototype.repeat`\n * with a negative count and throw a `RangeError`). A positive column count is\n * required before the TTY counts as usable.\n *\n * @example\n * ```ts\n * if (canUseTTY()) {\n * renderProgressBar()\n * }\n * ```\n */\nexport function canUseTTY(): boolean {\n return process.stdout.isTTY && (process.stdout.columns ?? 0) > 0 && !isCIEnvironment()\n}\n\n/**\n * Returns `true` when output can carry spinners and clack's gutter: an interactive TTY that no AI\n * coding agent is reading. Cursor-movement escapes are hard for an agent to parse even over a\n * pseudo-TTY, so it gets the plain writer.\n */\nexport function isRichOutput(): boolean {\n return canUseTTY() && !getAgentProfile().isAgent\n}\n","import { styleText } from 'node:util'\nimport * as clack from '@clack/prompts'\nimport type { LoggerWriter } from './types.ts'\n\n/**\n * Draws with clack for local development: a gutter bar per group, animated steps, and a progress\n * bar for the writes.\n */\nexport const clackWriter: LoggerWriter = {\n audience: 'human',\n group: (title) => clack.intro(title),\n groupEnd: (text) => clack.outro(text),\n step: (text) => clack.log.step(text, { spacing: 0 }),\n info: (text) => clack.log.info(text),\n success: (text) => clack.log.success(text),\n warn: (text) => clack.log.warn(text),\n error: (text) => clack.log.error(text),\n block: (lines) => clack.log.message(lines, { spacing: 0 }),\n // A subprocess's output is not Kubb's tree, so it goes out past clack and its gutter bar. The\n // step above it is already stopped by the time this runs.\n raw: (lines) => console.log(styleText('dim', lines.join('\\n'))),\n // The diagnostic carries its own code and indented rows, so clear clack's gutter and bar and let\n // the block stand on its own.\n diagnostic: (lines) => clack.log.message(lines, { symbol: '', secondarySymbol: '' }),\n update: (lines, title) =>\n clack.box(lines.join('\\n'), title, {\n width: 'auto',\n formatBorder: (border: string) => styleText('yellow', border),\n rounded: true,\n withGuide: false,\n contentAlign: 'center',\n titleAlign: 'center',\n }),\n spinner: () => clack.spinner(),\n progress(max) {\n const bar = clack.progress({ style: 'block', max, size: 30 })\n\n return {\n start: (text) => bar.start(text),\n advance: (text) => bar.advance(1, text),\n stop: (text) => bar.stop(text),\n }\n },\n}\n","import type { LoggerWriter } from './types.ts'\n\n/**\n * Prefixes that stand in for the symbols clack draws, so plain output reads the same way.\n */\nexport const SYMBOLS = { info: 'ℹ', warn: '⚠', error: '✗', step: '◇' } as const\n\n/**\n * Draws with one `write` call per line, e.g. `console.error` so stdout carries only JSON. Nothing\n * animates, so a step prints at start and end.\n */\nexport function createPlainWriter(write: (line: string) => void): LoggerWriter {\n return {\n audience: 'agent',\n group: write,\n groupEnd: write,\n step: (text) => write(`${SYMBOLS.step} ${text}`),\n info: write,\n success: write,\n warn: write,\n error: (text) => write(`${SYMBOLS.error} ${text}`),\n block: (lines) => write(lines.join('\\n')),\n raw: (lines) => write(lines.join('\\n')),\n diagnostic: (lines) => write(lines.join('\\n')),\n update: (lines, title) => write([title, ...lines].join('\\n')),\n spinner: () => ({\n start: write,\n message: write,\n clear: () => {},\n stop: (text) => text && write(text),\n error: (text) => write(`${SYMBOLS.error} ${text}`),\n }),\n progress: () => ({\n start: write,\n advance: write,\n stop: (text) => text && write(text),\n }),\n }\n}\n\n/**\n * Draws on the console, for non-TTY environments and for an AI coding agent reading the output.\n * Reports the same run in the same order as `clackWriter`, without the animation.\n */\nexport const plainWriter = createPlainWriter((line) => console.log(line))\n","import * as prompts from '@clack/prompts'\nimport { isRichOutput } from '../utils/env.ts'\nimport { clackWriter } from '../loggers/clackWriter.ts'\nimport { plainWriter, SYMBOLS } from '../loggers/plainWriter.ts'\nimport type { LoggerWriter } from '../loggers/types.ts'\n\n/** The writer the loggers draw with on this terminal, so a command's own lines look like its run. */\nexport function writer(): LoggerWriter {\n return isRichOutput() ? clackWriter : plainWriter\n}\n\ntype Level = keyof typeof SYMBOLS\n\n// Not through the writers: in plain output a command's own info and warning carry their symbol, and clack's step keeps its spacing.\nfunction write(level: Level, message: string): void {\n if (isRichOutput()) {\n prompts.log[level](message)\n\n return\n }\n\n console.log(`${SYMBOLS[level]} ${message}`)\n}\n\n/** Prints lines as one block, without a symbol in front of them. Not the writer's block, which drops clack's spacing around it. */\nexport function logBlock(lines: string | Array<string>): void {\n if (isRichOutput()) {\n prompts.log.message(lines)\n\n return\n }\n\n console.log([lines].flat().join('\\n'))\n}\n\nexport function logInfo(message: string): void {\n write('info', message)\n}\n\nexport function logWarn(message: string): void {\n write('warn', message)\n}\n\nexport function logError(message: string): void {\n write('error', message)\n}\n\n/**\n * Reports a step the command is taking, rather than something it found.\n */\nexport function logStep(message: string): void {\n write('step', message)\n}\n","import { styleText } from 'node:util'\nimport * as prompts from '@clack/prompts'\nimport { isRichOutput } from '../utils/env.ts'\nimport { writer } from './log.ts'\n\nconst SPONSOR_TIPS = [\n 'Your sponsorship keeps Kubb codegen, plugins, and docs maintained',\n 'Sponsor faster generators and better Kubb Studio workflows',\n 'Help keep Kubb free for TypeScript teams building APIs',\n 'Support React Query, Zod, Faker, and MSW integrations',\n 'Back open-source tools that turn OpenAPI into TypeScript',\n 'Sponsor fixes, releases, and new plugins for your API workflow',\n 'Help Kubb stay independent and focused on developer tools',\n] as const\n\nconst SPONSOR_LINKS = ['https://github.com/sponsors/stijnvanhulle', 'https://opencollective.com/kubb', 'https://kubb.dev/sponsors'] as const\n\nfunction nextTip(): string {\n const tip = SPONSOR_TIPS[Math.floor(Math.random() * SPONSOR_TIPS.length)]!\n const link = SPONSOR_LINKS[Math.floor(Math.random() * SPONSOR_LINKS.length)]!\n return `${tip}: ${link}`\n}\n\nfunction formatTip(tip: string): string {\n return styleText('magenta', ' Tip ') + styleText('yellow', tip)\n}\n\n/**\n * Prints one random tip outside every group. Rich terminals get the styled variant;\n * plain/CI output gets a stable text-only line so the tip is still visible as final output.\n */\nexport function logTip(): void {\n const tip = nextTip()\n if (!isRichOutput()) {\n console.log(`Tip: ${tip}`)\n return\n }\n\n console.log(`${styleText('magenta', '✦')}${formatTip(tip)}`)\n}\n\ntype IntroOptions = {\n title?: string\n /**\n * Printed under the title, for a command that has a caveat to lead with.\n */\n warning?: string\n /**\n * Whether to open a block a later {@link logOutro} closes. Pass `false` for a command that\n * prints and exits, since nothing would ever close the block.\n *\n * @default true\n */\n block?: boolean\n}\n\n/**\n * Opens a command's output. A command the banner already names passes no title.\n */\nexport function logIntro({ title, warning, block = true }: IntroOptions): void {\n if (block && isRichOutput()) {\n if (title) prompts.intro(title)\n\n if (warning) {\n prompts.log.warn(warning)\n }\n\n return\n }\n\n if (title) {\n console.log(title)\n }\n\n if (warning) {\n console.warn(warning)\n }\n\n if (title || warning) {\n console.log()\n }\n}\n\n/**\n * Closes the block {@link logIntro} opened. The closing gutter is not a written line, so plain\n * output prints the text on its own.\n */\nexport function logOutro(text: string): void {\n writer().groupEnd(text)\n}\n\n/**\n * Prints one empty line between two groups, without clack's gutter bar, since the bar belongs to a\n * group and a spacer sits outside every one.\n */\nexport function logSpacer(): void {\n console.log('')\n}\n\n/** Whether a run stops to ask something: no `--yes`, no `--dry-run`, and a person at a terminal. */\nexport function isInteractiveRun({ yes, dryRun }: { yes?: unknown; dryRun?: unknown }): boolean {\n return !yes && !dryRun && process.stdin.isTTY === true\n}\n","/** Counts a noun, so a message never reads `1 files`. */\nexport function pluralize(count: number, noun: string): string {\n return `${count} ${count === 1 ? noun : `${noun}s`}`\n}\n\n/** The flag that grants a permission, such as `--allow-read-ast`. */\nexport function toPermissionFlag(key: string): string {\n return `--${key.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`)}`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,YAAqB;CACnC,OAAO,QAAQ,OAAO,UAAU,QAAQ,OAAO,WAAW,KAAK,KAAK,CAAC,gBAAgB;AACvF;;;;;;AAOA,SAAgB,eAAwB;CACtC,OAAO,UAAU,KAAK,CAAC,gBAAgB,CAAC,CAAC;AAC3C;;;;;;;ACtBA,MAAa,cAA4B;CACvC,UAAU;CACV,QAAQ,UAAU,MAAM,MAAM,KAAK;CACnC,WAAW,SAAS,MAAM,MAAM,IAAI;CACpC,OAAO,SAAS,MAAM,IAAI,KAAK,MAAM,EAAE,SAAS,EAAE,CAAC;CACnD,OAAO,SAAS,MAAM,IAAI,KAAK,IAAI;CACnC,UAAU,SAAS,MAAM,IAAI,QAAQ,IAAI;CACzC,OAAO,SAAS,MAAM,IAAI,KAAK,IAAI;CACnC,QAAQ,SAAS,MAAM,IAAI,MAAM,IAAI;CACrC,QAAQ,UAAU,MAAM,IAAI,QAAQ,OAAO,EAAE,SAAS,EAAE,CAAC;CAGzD,MAAM,UAAU,QAAQ,IAAI,UAAU,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC;CAG9D,aAAa,UAAU,MAAM,IAAI,QAAQ,OAAO;EAAE,QAAQ;EAAI,iBAAiB;CAAG,CAAC;CACnF,SAAS,OAAO,UACd,MAAM,IAAI,MAAM,KAAK,IAAI,GAAG,OAAO;EACjC,OAAO;EACP,eAAe,WAAmB,UAAU,UAAU,MAAM;EAC5D,SAAS;EACT,WAAW;EACX,cAAc;EACd,YAAY;CACd,CAAC;CACH,eAAe,MAAM,QAAQ;CAC7B,SAAS,KAAK;EACZ,MAAM,MAAM,MAAM,SAAS;GAAE,OAAO;GAAS;GAAK,MAAM;EAAG,CAAC;EAE5D,OAAO;GACL,QAAQ,SAAS,IAAI,MAAM,IAAI;GAC/B,UAAU,SAAS,IAAI,QAAQ,GAAG,IAAI;GACtC,OAAO,SAAS,IAAI,KAAK,IAAI;EAC/B;CACF;AACF;;;;;;ACtCA,MAAa,UAAU;CAAE,MAAM;CAAK,MAAM;CAAK,OAAO;CAAK,MAAM;AAAI;;;;;AAMrE,SAAgB,kBAAkB,OAA6C;CAC7E,OAAO;EACL,UAAU;EACV,OAAO;EACP,UAAU;EACV,OAAO,SAAS,MAAM,GAAG,QAAQ,KAAK,GAAG,MAAM;EAC/C,MAAM;EACN,SAAS;EACT,MAAM;EACN,QAAQ,SAAS,MAAM,GAAG,QAAQ,MAAM,GAAG,MAAM;EACjD,QAAQ,UAAU,MAAM,MAAM,KAAK,IAAI,CAAC;EACxC,MAAM,UAAU,MAAM,MAAM,KAAK,IAAI,CAAC;EACtC,aAAa,UAAU,MAAM,MAAM,KAAK,IAAI,CAAC;EAC7C,SAAS,OAAO,UAAU,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC;EAC5D,gBAAgB;GACd,OAAO;GACP,SAAS;GACT,aAAa,CAAC;GACd,OAAO,SAAS,QAAQ,MAAM,IAAI;GAClC,QAAQ,SAAS,MAAM,GAAG,QAAQ,MAAM,GAAG,MAAM;EACnD;EACA,iBAAiB;GACf,OAAO;GACP,SAAS;GACT,OAAO,SAAS,QAAQ,MAAM,IAAI;EACpC;CACF;AACF;;;;;AAMA,MAAa,cAAc,mBAAmB,SAAS,QAAQ,IAAI,IAAI,CAAC;;;;ACrCxE,SAAgB,SAAuB;CACrC,OAAO,aAAa,IAAI,cAAc;AACxC;AAKA,SAAS,MAAM,OAAc,SAAuB;CAClD,IAAI,aAAa,GAAG;EAClB,MAAQ,IAAI,MAAM,CAAC,OAAO;EAE1B;CACF;CAEA,QAAQ,IAAI,GAAG,QAAQ,OAAO,GAAG,SAAS;AAC5C;;AAGA,SAAgB,SAAS,OAAqC;CAC5D,IAAI,aAAa,GAAG;EAClB,MAAQ,IAAI,QAAQ,KAAK;EAEzB;CACF;CAEA,QAAQ,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC;AACvC;AAEA,SAAgB,QAAQ,SAAuB;CAC7C,MAAM,QAAQ,OAAO;AACvB;AAEA,SAAgB,QAAQ,SAAuB;CAC7C,MAAM,QAAQ,OAAO;AACvB;AAEA,SAAgB,SAAS,SAAuB;CAC9C,MAAM,SAAS,OAAO;AACxB;;;;AAKA,SAAgB,QAAQ,SAAuB;CAC7C,MAAM,QAAQ,OAAO;AACvB;;;AC/CA,MAAM,eAAe;CACnB;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,gBAAgB;CAAC;CAA6C;CAAmC;AAA2B;AAElI,SAAS,UAAkB;CAGzB,OAAO,GAFK,aAAa,KAAK,MAAM,KAAK,OAAO,IAAI,aAAa,MAAM,GAEzD,IADD,cAAc,KAAK,MAAM,KAAK,OAAO,IAAI,cAAc,MAAM;AAE5E;AAEA,SAAS,UAAU,KAAqB;CACtC,OAAO,UAAU,WAAW,QAAQ,IAAI,UAAU,UAAU,GAAG;AACjE;;;;;AAMA,SAAgB,SAAe;CAC7B,MAAM,MAAM,QAAQ;CACpB,IAAI,CAAC,aAAa,GAAG;EACnB,QAAQ,IAAI,QAAQ,KAAK;EACzB;CACF;CAEA,QAAQ,IAAI,GAAG,UAAU,WAAW,GAAG,IAAI,UAAU,GAAG,GAAG;AAC7D;;;;AAoBA,SAAgB,SAAS,EAAE,OAAO,SAAS,QAAQ,QAA4B;CAC7E,IAAI,SAAS,aAAa,GAAG;EAC3B,IAAI,OAAO,MAAQ,MAAM,KAAK;EAE9B,IAAI,SACF,MAAQ,IAAI,KAAK,OAAO;EAG1B;CACF;CAEA,IAAI,OACF,QAAQ,IAAI,KAAK;CAGnB,IAAI,SACF,QAAQ,KAAK,OAAO;CAGtB,IAAI,SAAS,SACX,QAAQ,IAAI;AAEhB;;;;;AAMA,SAAgB,SAAS,MAAoB;CAC3C,OAAO,CAAC,CAAC,SAAS,IAAI;AACxB;;;;;AAMA,SAAgB,YAAkB;CAChC,QAAQ,IAAI,EAAE;AAChB;;AAGA,SAAgB,iBAAiB,EAAE,KAAK,UAAwD;CAC9F,OAAO,CAAC,OAAO,CAAC,UAAU,QAAQ,MAAM,UAAU;AACpD;;;;ACrGA,SAAgB,UAAU,OAAe,MAAsB;CAC7D,OAAO,GAAG,MAAM,GAAG,UAAU,IAAI,OAAO,GAAG,KAAK;AAClD;;AAGA,SAAgB,iBAAiB,KAAqB;CACpD,OAAO,KAAK,IAAI,QAAQ,WAAW,SAAS,IAAI,KAAK,YAAY,GAAG;AACtE"}
@@ -1,5 +1,5 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-CPE0t6oh.cjs");
2
- const require_Telemetry = require("./Telemetry-0Sr_THx9.cjs");
2
+ const require_Telemetry = require("./Telemetry-CZmpqKZm.cjs");
3
3
  let node_util = require("node:util");
4
4
  let gunshi_agent = require("gunshi/agent");
5
5
  let _clack_prompts = require("@clack/prompts");
@@ -338,4 +338,4 @@ Object.defineProperty(exports, "writer", {
338
338
  }
339
339
  });
340
340
 
341
- //# sourceMappingURL=text-DVPYqR74.cjs.map
341
+ //# sourceMappingURL=text-CtdDig0T.cjs.map