@kubb/cli 5.3.19 → 5.4.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 (97) hide show
  1. package/dist/{Telemetry-Dw5s6abr.js → Telemetry-cHHOzBW8.js} +3 -3
  2. package/dist/{Telemetry-Dw5s6abr.js.map → Telemetry-cHHOzBW8.js.map} +1 -1
  3. package/dist/{agent-3JmkMghp.js → agent-w0Hlq4mG.js} +2 -2
  4. package/dist/{agent-3JmkMghp.js.map → agent-w0Hlq4mG.js.map} +1 -1
  5. package/dist/background-BDZa6MJS.js +252 -0
  6. package/dist/background-BDZa6MJS.js.map +1 -0
  7. package/dist/background-CNHhnQ5M.cjs +171 -0
  8. package/dist/background-CNHhnQ5M.cjs.map +1 -0
  9. package/dist/background-CS7jIBAY.js +2 -0
  10. package/dist/{connect-BjIZWrx8.js → connect-CIVmP_6l.js} +3 -3
  11. package/dist/{connect-BjIZWrx8.js.map → connect-CIVmP_6l.js.map} +1 -1
  12. package/dist/{connect-D9g-WltE.cjs → connect-DLbFBfoV.cjs} +2 -2
  13. package/dist/{connect-D9g-WltE.cjs.map → connect-DLbFBfoV.cjs.map} +1 -1
  14. package/dist/{errors-C8yNfV7w.js → errors-BQJzaUwP.js} +2 -2
  15. package/dist/{errors-C8yNfV7w.js.map → errors-BQJzaUwP.js.map} +1 -1
  16. package/dist/{generate-DhMzVV6l.cjs → generate-BWwjYxN5.cjs} +2 -2
  17. package/dist/{generate-DhMzVV6l.cjs.map → generate-BWwjYxN5.cjs.map} +1 -1
  18. package/dist/{generate-D0Zx0PDk.js → generate-BY_PbRPu.js} +3 -3
  19. package/dist/{generate-D0Zx0PDk.js.map → generate-BY_PbRPu.js.map} +1 -1
  20. package/dist/index.cjs +7 -7
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.js +9 -9
  23. package/dist/{init-Bbz6UeBl.js → init-Dpa1wuah.js} +4 -4
  24. package/dist/{init-Bbz6UeBl.js.map → init-Dpa1wuah.js.map} +1 -1
  25. package/dist/{init-nHruRHSm.cjs → init-yb2ZIQwp.cjs} +2 -2
  26. package/dist/{init-nHruRHSm.cjs.map → init-yb2ZIQwp.cjs.map} +1 -1
  27. package/dist/{login-DFda5soT.js → login-Di6_DU_V.js} +3 -3
  28. package/dist/{login-DFda5soT.js.map → login-Di6_DU_V.js.map} +1 -1
  29. package/dist/{login-BG7t5rN5.cjs → login-LVIZdclC.cjs} +2 -2
  30. package/dist/{login-BG7t5rN5.cjs.map → login-LVIZdclC.cjs.map} +1 -1
  31. package/dist/{logout-B_uyXcH1.cjs → logout-B8L-Jb8P.cjs} +4 -2
  32. package/dist/logout-B8L-Jb8P.cjs.map +1 -0
  33. package/dist/{logout-1AnE6Wgf.js → logout-BOhSROh8.js} +5 -3
  34. package/dist/logout-BOhSROh8.js.map +1 -0
  35. package/dist/{output-C_Gk4p-8.js → output-C5h3LBgQ.js} +3 -3
  36. package/dist/{output-C_Gk4p-8.js.map → output-C5h3LBgQ.js.map} +1 -1
  37. package/dist/{package-Dg6ALxDA.cjs → package-DjS7Xk-S.cjs} +2 -2
  38. package/dist/package-DjS7Xk-S.cjs.map +1 -0
  39. package/dist/package-IY922xjh.js +6 -0
  40. package/dist/package-IY922xjh.js.map +1 -0
  41. package/dist/{rolldown-runtime-C0LytTxp.js → rolldown-runtime-CRm0XQPb.js} +1 -0
  42. package/dist/{run-BGhKiO9F.cjs → run-0k75--OI.cjs} +2 -2
  43. package/dist/{run-BGhKiO9F.cjs.map → run-0k75--OI.cjs.map} +1 -1
  44. package/dist/{run-WTZgnA65.cjs → run-BNQt-kUj.cjs} +2 -2
  45. package/dist/{run-WTZgnA65.cjs.map → run-BNQt-kUj.cjs.map} +1 -1
  46. package/dist/{run-CJmvvmr6.js → run-BaqE5cze.js} +5 -5
  47. package/dist/{run-CJmvvmr6.js.map → run-BaqE5cze.js.map} +1 -1
  48. package/dist/{run-DgWNV5Z5.js → run-BsP5syy1.js} +107 -156
  49. package/dist/{run-DgWNV5Z5.js.map → run-BsP5syy1.js.map} +1 -1
  50. package/dist/{run-cx-6U2Rq.js → run-DQNoMoHW.js} +7 -7
  51. package/dist/{run-cx-6U2Rq.js.map → run-DQNoMoHW.js.map} +1 -1
  52. package/dist/{run-CXYrjM2-.js → run-Drf9rg9j.js} +5 -5
  53. package/dist/{run-CXYrjM2-.js.map → run-Drf9rg9j.js.map} +1 -1
  54. package/dist/{run-BEZhsX-8.js → run-G2lUygYI.js} +3 -3
  55. package/dist/{run-BEZhsX-8.js.map → run-G2lUygYI.js.map} +1 -1
  56. package/dist/{run-CTu2E3vp.cjs → run-GGJ4QLsg.cjs} +2 -2
  57. package/dist/{run-CTu2E3vp.cjs.map → run-GGJ4QLsg.cjs.map} +1 -1
  58. package/dist/{run-yGsAbOqK.cjs → run-_hE0GAWu.cjs} +110 -147
  59. package/dist/{run-yGsAbOqK.cjs.map → run-_hE0GAWu.cjs.map} +1 -1
  60. package/dist/{snapshot-DmmO5Ymq.cjs → snapshot-DndnZx5y.cjs} +2 -2
  61. package/dist/{snapshot-DmmO5Ymq.cjs.map → snapshot-DndnZx5y.cjs.map} +1 -1
  62. package/dist/{snapshot-BBU1-wmn.js → snapshot-ZY24CtRk.js} +6 -6
  63. package/dist/{snapshot-BBU1-wmn.js.map → snapshot-ZY24CtRk.js.map} +1 -1
  64. package/dist/start-BlwmWZDb.js +12 -0
  65. package/dist/start-BlwmWZDb.js.map +1 -0
  66. package/dist/start-Bu5xpzix.cjs +12 -0
  67. package/dist/start-Bu5xpzix.cjs.map +1 -0
  68. package/dist/status-5UqQP9WB.js +17 -0
  69. package/dist/status-5UqQP9WB.js.map +1 -0
  70. package/dist/status-L4I8buia.cjs +17 -0
  71. package/dist/status-L4I8buia.cjs.map +1 -0
  72. package/dist/stop-BQkjAPNH.cjs +11 -0
  73. package/dist/stop-BQkjAPNH.cjs.map +1 -0
  74. package/dist/stop-mqUTbxMO.js +11 -0
  75. package/dist/stop-mqUTbxMO.js.map +1 -0
  76. package/dist/{studio-2iNLigEg.js → studio-BBnIuXst.js} +27 -13
  77. package/dist/studio-BBnIuXst.js.map +1 -0
  78. package/dist/{studio-Dz9XBEp6.cjs → studio-BFy085ae.cjs} +26 -12
  79. package/dist/studio-BFy085ae.cjs.map +1 -0
  80. package/dist/studioWorker.d.ts +1 -0
  81. package/dist/studioWorker.js +62 -0
  82. package/dist/studioWorker.js.map +1 -0
  83. package/dist/{utils-TpILNAy7.js → utils-BWksgOYQ.js} +36 -36
  84. package/dist/utils-BWksgOYQ.js.map +1 -0
  85. package/package.json +7 -7
  86. package/dist/logout-1AnE6Wgf.js.map +0 -1
  87. package/dist/logout-B_uyXcH1.cjs.map +0 -1
  88. package/dist/package-B1pE4gUR.js +0 -6
  89. package/dist/package-B1pE4gUR.js.map +0 -1
  90. package/dist/package-Dg6ALxDA.cjs.map +0 -1
  91. package/dist/status-B88gFiy4.cjs +0 -11
  92. package/dist/status-B88gFiy4.cjs.map +0 -1
  93. package/dist/status-BRdnIBoM.js +0 -11
  94. package/dist/status-BRdnIBoM.js.map +0 -1
  95. package/dist/studio-2iNLigEg.js.map +0 -1
  96. package/dist/studio-Dz9XBEp6.cjs.map +0 -1
  97. package/dist/utils-TpILNAy7.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"run-BGhKiO9F.cjs","names":["styleText","existsSync","logLevelMap","randomUUID","runHook","toError","process","memoryStorage","Diagnostics","formatters","detectTool","FORMATTER_PREFERENCE","linters","LINTER_PREFERENCE","runPostGenerate","createKubb","sendTelemetry","buildTelemetryEvent","version","KUBB_NPM_PACKAGE_URL","UPDATE_CHECK_TIMEOUT_MS","isNewerVersion","Hookable","createSpinner","getConfigs","path","setupReporters","cliReporter","selectReporters","pluralize","getInputKind","fetchUrlBody","logInfo","logError","startWatcher"],"sources":["../src/runners/generate/run.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { existsSync } from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport {\n Hookable,\n type CLIOptions,\n cliReporter,\n type Config,\n createKubb,\n type Diagnostic,\n Diagnostics,\n getInputKind,\n type KubbHooks,\n logLevel as logLevelMap,\n memoryStorage,\n type ProblemDiagnostic,\n type ReporterName,\n} from '@kubb/core'\nimport { version } from '../../../package.json'\nimport { KUBB_NPM_PACKAGE_URL, UPDATE_CHECK_TIMEOUT_MS } from '../../constants.ts'\nimport { buildTelemetryEvent, sendTelemetry } from '../../Telemetry.ts'\nimport setupReporters, { pluralize, selectReporters } from '../../loggers/utils.ts'\nimport { createSpinner, logBanner, logError, logInfo, logIntro, logOutro, logSpacer, logStep, logTip } from '../../loggers/output.ts'\nimport { fetchUrlBody, getConfigs, isNewerVersion, runHook, runPostGenerate, startUrlWatcher, startWatcher } from './utils.ts'\nimport { FORMATTER_PREFERENCE, LINTER_PREFERENCE } from '@internals/utils'\nimport { detectTool, formatters, linters } from '../../tools.ts'\n\ntype GenerateProps = {\n input?: string\n config: Config\n hooks: Hookable<KubbHooks>\n logLevel: number\n /**\n * When `true`, generates in memory instead of writing to disk, and skips formatting, linting,\n * and post-generate commands.\n */\n dryRun?: boolean\n}\n\ntype ToolMap = typeof formatters | typeof linters\n\n/**\n * Static description of one output tool: its command table, the label and messages the pass logs,\n * and how to auto-detect it. Format and lint differ only in these values.\n */\ntype Tool = {\n label: string\n map: ToolMap\n detect: () => Promise<string | null>\n successPrefix: string\n noToolMessage: string\n}\n\ntype RunToolPassOptions = {\n toolValue: string\n tool: Tool\n outputPath: string\n logLevel: number\n hooks: Hookable<KubbHooks>\n onStart: () => Promise<void> | void\n onEnd: () => Promise<void> | void\n}\n\n/**\n * Runs one formatter or linter pass over the output directory. Returns the failure instead of\n * throwing, so the caller can turn it into a coded diagnostic. Failures never render here:\n * the caller emits them through `Diagnostics.emit`, like every other diagnostic.\n */\nasync function runToolPass({ toolValue, tool, outputPath, logLevel, hooks, onStart, onEnd }: RunToolPassOptions): Promise<Error | null> {\n await onStart()\n\n let resolvedTool = toolValue\n if (resolvedTool === 'auto') {\n const detected = await tool.detect()\n if (!detected) {\n await hooks.callHook('kubb:warn', { message: tool.noToolMessage })\n } else {\n resolvedTool = detected\n await hooks.callHook('kubb:info', { message: `Auto-detected ${tool.label}: ${styleText('dim', resolvedTool)}` })\n }\n }\n\n let toolError: Error | null = null\n\n // Nothing to lint or format when the output dir was never written. Skip so the tool\n // (e.g. oxlint with --no-ignore) doesn't fail with \"No files found to lint\".\n if (resolvedTool && resolvedTool !== 'auto' && resolvedTool in tool.map && existsSync(outputPath)) {\n const toolConfig = tool.map[resolvedTool as keyof ToolMap]\n\n const successMessage = [\n `${tool.successPrefix} with ${styleText('dim', resolvedTool)}`,\n logLevel >= logLevelMap.info ? `on ${styleText('dim', outputPath)}` : undefined,\n 'successfully',\n ]\n .filter(Boolean)\n .join(' ')\n\n try {\n const hookId = randomUUID()\n const hookArgs = toolConfig.args(outputPath)\n const commandWithArgs = [toolConfig.command, ...hookArgs].join(' ')\n\n await hooks.callHook('kubb:hook:start', { id: hookId, command: toolConfig.command, args: hookArgs })\n\n const result = await runHook({ id: hookId, command: toolConfig.command, args: hookArgs, commandWithArgs, hooks })\n\n if (result.success) {\n await hooks.callHook('kubb:success', { message: successMessage })\n } else {\n toolError = result.error ?? new Error(toolConfig.errorMessage)\n }\n } catch (caughtError) {\n toolError = toError(caughtError)\n }\n }\n\n await onEnd()\n\n return toolError\n}\n\nasync function generate(options: GenerateProps): Promise<boolean> {\n const { input, hooks, logLevel, dryRun = false } = options\n\n const 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 // The formatter, linter, and post-generate commands run after a successful build. Collect their\n // failures as coded diagnostics so they reach the summary, the json report, and the exit code.\n const processOutput = async ({ config: resolvedConfig, outputPath }: { config: Config; outputPath: string }): Promise<Array<Diagnostic>> => {\n if (dryRun) return []\n\n const outputDiagnostics: Array<Diagnostic> = []\n const reportOutputFailure = async (code: ProblemDiagnostic['code'], label: string, error: Error) => {\n const diagnostic = outputDiagnostic(code, label, error)\n outputDiagnostics.push(diagnostic)\n await Diagnostics.emit(hooks, diagnostic)\n }\n\n // Format and lint are the same pass over the output directory, differing only in the tool\n // table and the hooks they announce themselves with, so run them from one descriptor list.\n const toolPasses = [\n {\n value: resolvedConfig.output.format,\n code: Diagnostics.code.formatFailed,\n tool: {\n label: 'formatter',\n map: formatters,\n detect: () => detectTool(FORMATTER_PREFERENCE),\n successPrefix: 'Formatting',\n noToolMessage: `No formatter found (${FORMATTER_PREFERENCE.join(', ')}). Skipping formatting.`,\n },\n onStart: () => hooks.callHook('kubb:format:start'),\n onEnd: () => hooks.callHook('kubb:format:end'),\n },\n {\n value: resolvedConfig.output.lint,\n code: Diagnostics.code.lintFailed,\n tool: {\n label: 'linter',\n map: linters,\n detect: () => detectTool(LINTER_PREFERENCE),\n successPrefix: 'Linting',\n noToolMessage: `No linter found (${LINTER_PREFERENCE.join(', ')}). Skipping linting.`,\n },\n onStart: () => hooks.callHook('kubb:lint:start'),\n onEnd: () => hooks.callHook('kubb:lint:end'),\n },\n ]\n\n for (const pass of toolPasses) {\n if (!pass.value) continue\n const error = await runToolPass({\n toolValue: pass.value,\n tool: pass.tool,\n onStart: pass.onStart,\n onEnd: pass.onEnd,\n outputPath,\n logLevel,\n hooks,\n })\n if (error) await reportOutputFailure(pass.code, pass.tool.label, error)\n }\n\n if (resolvedConfig.output.postGenerate?.length) {\n await hooks.callHook('kubb:hooks:start')\n const hookResults = await runPostGenerate({ commands: resolvedConfig.output.postGenerate, hooks })\n for (const hookResult of hookResults) {\n if (hookResult.success) continue\n await reportOutputFailure(Diagnostics.code.postGenerateFailed, 'Post-generate command', hookResult.error ?? new Error('Post-generate command failed'))\n }\n await hooks.callHook('kubb:hooks:end')\n }\n\n return outputDiagnostics\n }\n\n const kubb = createKubb(config, { hooks })\n const result = await kubb.generate({ processOutput })\n\n if (dryRun) {\n await hooks.callHook('kubb:info', { message: 'Dry run: no files were written', info: `${result.files.length} file(s) would be generated` })\n }\n\n const telemetryPlugins = Array.from(kubb.driver.plugins.values(), (p) => ({ name: p.name, options: p.options as Record<string, unknown> }))\n await sendTelemetry(\n buildTelemetryEvent({\n command: 'generate',\n kubbVersion: version,\n plugins: telemetryPlugins,\n hrStart,\n filesCreated: result.files.length,\n status: result.success ? 'success' : 'failed',\n }),\n )\n\n return result.success\n}\n\n/**\n * Builds a coded diagnostic for an output-phase failure (formatter, linter, or `done` hook).\n */\nfunction outputDiagnostic(code: ProblemDiagnostic['code'], label: string, caughtError: unknown): ProblemDiagnostic {\n const error = toError(caughtError)\n return {\n code,\n severity: 'error',\n message: `${label} failed: ${error.message}`,\n help: 'Check that the tool is installed and that the command and its config are correct.',\n location: { kind: 'config' },\n cause: error,\n }\n}\n\ntype GenerateCommandOptions = {\n input?: string\n configPath?: string\n logLevel: string\n watch: boolean\n reporters?: Array<ReporterName>\n dryRun?: boolean\n}\n\nasync function checkForUpdate(hooks: Hookable<KubbHooks>): Promise<void> {\n try {\n const res = await fetch(KUBB_NPM_PACKAGE_URL, { signal: AbortSignal.timeout(UPDATE_CHECK_TIMEOUT_MS) })\n const data = (await res.json()) as { version: string }\n if (data.version && isNewerVersion(version, data.version)) {\n await Diagnostics.emit(hooks, Diagnostics.update({ currentVersion: version, latestVersion: data.version }))\n }\n } catch {\n // Ignore network errors\n }\n}\n\n/**\n * Runs the full Kubb generation lifecycle for the given CLI options.\n * Loads configs, sets up the reporters (CLI `--reporter` picks which of `config.reporters` to trigger),\n * checks for a newer version, and calls `generate` for each config entry.\n */\nexport async function run({ input, configPath, logLevel: logLevelKey, watch, reporters: cliReporters, dryRun }: GenerateCommandOptions): Promise<void> {\n const logLevel = logLevelMap[logLevelKey as keyof typeof logLevelMap] ?? logLevelMap.info\n const hooks = new Hookable<KubbHooks>()\n\n // CLI `--reporter` selects which reporters to trigger by name, defaulting to `cli`. The config\n // always carries the available reporters (defineConfig registers the built-ins).\n const requestedNames: Array<ReporterName> = cliReporters?.length ? cliReporters : ['cli']\n\n // The `json` reporter owns stdout, so the command writes nothing of its own around it.\n const quiet = logLevel <= logLevelMap.silent || requestedNames.includes('json')\n\n if (!quiet) {\n logBanner(version)\n logIntro({ title: 'Configuration' })\n }\n\n // Load the config first so `config.reporters` can pick the reporters. A failure here has no\n // reporter installed yet, so fall back to the default `cli` reporter to surface it.\n const configSpinner = createSpinner()\n let configs: Array<Config>\n let resolvedConfigPath: string\n try {\n if (!quiet) configSpinner.start('Loading config')\n\n const loaded = await getConfigs({\n configPath,\n input,\n watch,\n logLevel: logLevelKey as CLIOptions['logLevel'],\n })\n configs = loaded.configs\n resolvedConfigPath = loaded.configPath\n\n if (!quiet) configSpinner.stop(`Loaded ${styleText('dim', path.relative(process.cwd(), resolvedConfigPath))}`)\n } catch (error) {\n if (!quiet) configSpinner.error('Config failed loading')\n\n await setupReporters(hooks, { logLevel, reporters: [cliReporter] })\n await hooks.callHook('kubb:error', { error: toError(error) })\n\n if (!quiet) logOutro(styleText('red', '✗ Configuration failed'))\n process.exit(1)\n }\n\n const reporters = selectReporters(configs[0]?.reporters ?? [], requestedNames)\n await setupReporters(hooks, { logLevel, reporters })\n\n await hooks.callHook('kubb:lifecycle:start', { version })\n\n // Inside the bootstrap group, so an update notice reads as part of the setup rather than as part\n // of the first config's generation.\n await checkForUpdate(hooks)\n\n if (!quiet) logOutro(`${pluralize(configs.length, 'config')} ready`)\n\n try {\n let anyFailed = false\n for (const config of configs) {\n const effectiveInput = input ?? config.input\n const inputKind = typeof effectiveInput === 'string' ? getInputKind(effectiveInput) : undefined\n const watchPath = inputKind === 'file' || inputKind === 'url' ? (effectiveInput as string) : undefined\n if (watchPath && watch) {\n const watchedPaths = [watchPath]\n // Don't removeAll() between builds, that would also drop logger and lifecycle\n // listeners. Plugin listeners are already disposed by safeBuild's dispose()\n // in its finally block, so re-running generate() on the same hooks emitter is safe.\n const build = async (paths: Array<string>) => {\n const succeeded = await generate({ input, config, logLevel, hooks, dryRun })\n logStep(styleText('yellow', `Watching for changes in ${paths.join(' and ')}`))\n if (succeeded) {\n logSpacer()\n logTip()\n }\n }\n\n // For a URL input, capture the document before the build: it becomes the watcher's\n // change-detection baseline, so an edit landing before the first poll still rebuilds.\n // When the server is down the baseline stays undefined and the watcher rebuilds on its\n // first successful poll, so recovery with an unchanged document still generates output.\n const initialBody = inputKind === 'url' ? await fetchUrlBody(watchPath) : undefined\n\n // The watchers ignore their startup state (chokidar's initial events, the baseline\n // above), so run the first build here. A failing first build keeps watching, since\n // the user can fix the input and save.\n try {\n await build(watchedPaths)\n } catch (buildError) {\n await hooks.callHook('kubb:error', { error: toError(buildError) })\n }\n\n if (inputKind === 'url') {\n startUrlWatcher(watchPath, build, { log: { info: logInfo, error: logError }, initialBody })\n } else {\n await startWatcher(watchedPaths, build, { info: logInfo, error: logError })\n }\n } else {\n try {\n const succeeded = await generate({ input, config, logLevel, hooks, dryRun })\n if (!succeeded) anyFailed = true\n } catch (configError) {\n await hooks.callHook('kubb:error', { error: toError(configError) })\n anyFailed = true\n }\n }\n }\n\n await hooks.callHook('kubb:lifecycle:end')\n\n // Watch mode prints a tip after each successful build. Regular generate commands need to\n // print one explicitly after the lifecycle group has closed so it stays outside the group.\n if (!quiet && !watch && !anyFailed) {\n logTip()\n }\n\n if (anyFailed) {\n process.exit(1)\n }\n } catch (error) {\n await hooks.callHook('kubb:error', { error: toError(error) })\n process.exit(1)\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"run-0k75--OI.cjs","names":["styleText","existsSync","logLevelMap","randomUUID","runHook","toError","process","memoryStorage","Diagnostics","formatters","detectTool","FORMATTER_PREFERENCE","linters","LINTER_PREFERENCE","runPostGenerate","createKubb","sendTelemetry","buildTelemetryEvent","version","KUBB_NPM_PACKAGE_URL","UPDATE_CHECK_TIMEOUT_MS","isNewerVersion","Hookable","createSpinner","getConfigs","path","setupReporters","cliReporter","selectReporters","pluralize","getInputKind","fetchUrlBody","logInfo","logError","startWatcher"],"sources":["../src/runners/generate/run.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { existsSync } from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport {\n Hookable,\n type CLIOptions,\n cliReporter,\n type Config,\n createKubb,\n type Diagnostic,\n Diagnostics,\n getInputKind,\n type KubbHooks,\n logLevel as logLevelMap,\n memoryStorage,\n type ProblemDiagnostic,\n type ReporterName,\n} from '@kubb/core'\nimport { version } from '../../../package.json'\nimport { KUBB_NPM_PACKAGE_URL, UPDATE_CHECK_TIMEOUT_MS } from '../../constants.ts'\nimport { buildTelemetryEvent, sendTelemetry } from '../../Telemetry.ts'\nimport setupReporters, { pluralize, selectReporters } from '../../loggers/utils.ts'\nimport { createSpinner, logBanner, logError, logInfo, logIntro, logOutro, logSpacer, logStep, logTip } from '../../loggers/output.ts'\nimport { fetchUrlBody, getConfigs, isNewerVersion, runHook, runPostGenerate, startUrlWatcher, startWatcher } from './utils.ts'\nimport { FORMATTER_PREFERENCE, LINTER_PREFERENCE } from '@internals/utils'\nimport { detectTool, formatters, linters } from '../../tools.ts'\n\ntype GenerateProps = {\n input?: string\n config: Config\n hooks: Hookable<KubbHooks>\n logLevel: number\n /**\n * When `true`, generates in memory instead of writing to disk, and skips formatting, linting,\n * and post-generate commands.\n */\n dryRun?: boolean\n}\n\ntype ToolMap = typeof formatters | typeof linters\n\n/**\n * Static description of one output tool: its command table, the label and messages the pass logs,\n * and how to auto-detect it. Format and lint differ only in these values.\n */\ntype Tool = {\n label: string\n map: ToolMap\n detect: () => Promise<string | null>\n successPrefix: string\n noToolMessage: string\n}\n\ntype RunToolPassOptions = {\n toolValue: string\n tool: Tool\n outputPath: string\n logLevel: number\n hooks: Hookable<KubbHooks>\n onStart: () => Promise<void> | void\n onEnd: () => Promise<void> | void\n}\n\n/**\n * Runs one formatter or linter pass over the output directory. Returns the failure instead of\n * throwing, so the caller can turn it into a coded diagnostic. Failures never render here:\n * the caller emits them through `Diagnostics.emit`, like every other diagnostic.\n */\nasync function runToolPass({ toolValue, tool, outputPath, logLevel, hooks, onStart, onEnd }: RunToolPassOptions): Promise<Error | null> {\n await onStart()\n\n let resolvedTool = toolValue\n if (resolvedTool === 'auto') {\n const detected = await tool.detect()\n if (!detected) {\n await hooks.callHook('kubb:warn', { message: tool.noToolMessage })\n } else {\n resolvedTool = detected\n await hooks.callHook('kubb:info', { message: `Auto-detected ${tool.label}: ${styleText('dim', resolvedTool)}` })\n }\n }\n\n let toolError: Error | null = null\n\n // Nothing to lint or format when the output dir was never written. Skip so the tool\n // (e.g. oxlint with --no-ignore) doesn't fail with \"No files found to lint\".\n if (resolvedTool && resolvedTool !== 'auto' && resolvedTool in tool.map && existsSync(outputPath)) {\n const toolConfig = tool.map[resolvedTool as keyof ToolMap]\n\n const successMessage = [\n `${tool.successPrefix} with ${styleText('dim', resolvedTool)}`,\n logLevel >= logLevelMap.info ? `on ${styleText('dim', outputPath)}` : undefined,\n 'successfully',\n ]\n .filter(Boolean)\n .join(' ')\n\n try {\n const hookId = randomUUID()\n const hookArgs = toolConfig.args(outputPath)\n const commandWithArgs = [toolConfig.command, ...hookArgs].join(' ')\n\n await hooks.callHook('kubb:hook:start', { id: hookId, command: toolConfig.command, args: hookArgs })\n\n const result = await runHook({ id: hookId, command: toolConfig.command, args: hookArgs, commandWithArgs, hooks })\n\n if (result.success) {\n await hooks.callHook('kubb:success', { message: successMessage })\n } else {\n toolError = result.error ?? new Error(toolConfig.errorMessage)\n }\n } catch (caughtError) {\n toolError = toError(caughtError)\n }\n }\n\n await onEnd()\n\n return toolError\n}\n\nasync function generate(options: GenerateProps): Promise<boolean> {\n const { input, hooks, logLevel, dryRun = false } = options\n\n const 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 // The formatter, linter, and post-generate commands run after a successful build. Collect their\n // failures as coded diagnostics so they reach the summary, the json report, and the exit code.\n const processOutput = async ({ config: resolvedConfig, outputPath }: { config: Config; outputPath: string }): Promise<Array<Diagnostic>> => {\n if (dryRun) return []\n\n const outputDiagnostics: Array<Diagnostic> = []\n const reportOutputFailure = async (code: ProblemDiagnostic['code'], label: string, error: Error) => {\n const diagnostic = outputDiagnostic(code, label, error)\n outputDiagnostics.push(diagnostic)\n await Diagnostics.emit(hooks, diagnostic)\n }\n\n // Format and lint are the same pass over the output directory, differing only in the tool\n // table and the hooks they announce themselves with, so run them from one descriptor list.\n const toolPasses = [\n {\n value: resolvedConfig.output.format,\n code: Diagnostics.code.formatFailed,\n tool: {\n label: 'formatter',\n map: formatters,\n detect: () => detectTool(FORMATTER_PREFERENCE),\n successPrefix: 'Formatting',\n noToolMessage: `No formatter found (${FORMATTER_PREFERENCE.join(', ')}). Skipping formatting.`,\n },\n onStart: () => hooks.callHook('kubb:format:start'),\n onEnd: () => hooks.callHook('kubb:format:end'),\n },\n {\n value: resolvedConfig.output.lint,\n code: Diagnostics.code.lintFailed,\n tool: {\n label: 'linter',\n map: linters,\n detect: () => detectTool(LINTER_PREFERENCE),\n successPrefix: 'Linting',\n noToolMessage: `No linter found (${LINTER_PREFERENCE.join(', ')}). Skipping linting.`,\n },\n onStart: () => hooks.callHook('kubb:lint:start'),\n onEnd: () => hooks.callHook('kubb:lint:end'),\n },\n ]\n\n for (const pass of toolPasses) {\n if (!pass.value) continue\n const error = await runToolPass({\n toolValue: pass.value,\n tool: pass.tool,\n onStart: pass.onStart,\n onEnd: pass.onEnd,\n outputPath,\n logLevel,\n hooks,\n })\n if (error) await reportOutputFailure(pass.code, pass.tool.label, error)\n }\n\n if (resolvedConfig.output.postGenerate?.length) {\n await hooks.callHook('kubb:hooks:start')\n const hookResults = await runPostGenerate({ commands: resolvedConfig.output.postGenerate, hooks })\n for (const hookResult of hookResults) {\n if (hookResult.success) continue\n await reportOutputFailure(Diagnostics.code.postGenerateFailed, 'Post-generate command', hookResult.error ?? new Error('Post-generate command failed'))\n }\n await hooks.callHook('kubb:hooks:end')\n }\n\n return outputDiagnostics\n }\n\n const kubb = createKubb(config, { hooks })\n const result = await kubb.generate({ processOutput })\n\n if (dryRun) {\n await hooks.callHook('kubb:info', { message: 'Dry run: no files were written', info: `${result.files.length} file(s) would be generated` })\n }\n\n const telemetryPlugins = Array.from(kubb.driver.plugins.values(), (p) => ({ name: p.name, options: p.options as Record<string, unknown> }))\n await sendTelemetry(\n buildTelemetryEvent({\n command: 'generate',\n kubbVersion: version,\n plugins: telemetryPlugins,\n hrStart,\n filesCreated: result.files.length,\n status: result.success ? 'success' : 'failed',\n }),\n )\n\n return result.success\n}\n\n/**\n * Builds a coded diagnostic for an output-phase failure (formatter, linter, or `done` hook).\n */\nfunction outputDiagnostic(code: ProblemDiagnostic['code'], label: string, caughtError: unknown): ProblemDiagnostic {\n const error = toError(caughtError)\n return {\n code,\n severity: 'error',\n message: `${label} failed: ${error.message}`,\n help: 'Check that the tool is installed and that the command and its config are correct.',\n location: { kind: 'config' },\n cause: error,\n }\n}\n\ntype GenerateCommandOptions = {\n input?: string\n configPath?: string\n logLevel: string\n watch: boolean\n reporters?: Array<ReporterName>\n dryRun?: boolean\n}\n\nasync function checkForUpdate(hooks: Hookable<KubbHooks>): Promise<void> {\n try {\n const res = await fetch(KUBB_NPM_PACKAGE_URL, { signal: AbortSignal.timeout(UPDATE_CHECK_TIMEOUT_MS) })\n const data = (await res.json()) as { version: string }\n if (data.version && isNewerVersion(version, data.version)) {\n await Diagnostics.emit(hooks, Diagnostics.update({ currentVersion: version, latestVersion: data.version }))\n }\n } catch {\n // Ignore network errors\n }\n}\n\n/**\n * Runs the full Kubb generation lifecycle for the given CLI options.\n * Loads configs, sets up the reporters (CLI `--reporter` picks which of `config.reporters` to trigger),\n * checks for a newer version, and calls `generate` for each config entry.\n */\nexport async function run({ input, configPath, logLevel: logLevelKey, watch, reporters: cliReporters, dryRun }: GenerateCommandOptions): Promise<void> {\n const logLevel = logLevelMap[logLevelKey as keyof typeof logLevelMap] ?? logLevelMap.info\n const hooks = new Hookable<KubbHooks>()\n\n // CLI `--reporter` selects which reporters to trigger by name, defaulting to `cli`. The config\n // always carries the available reporters (defineConfig registers the built-ins).\n const requestedNames: Array<ReporterName> = cliReporters?.length ? cliReporters : ['cli']\n\n // The `json` reporter owns stdout, so the command writes nothing of its own around it.\n const quiet = logLevel <= logLevelMap.silent || requestedNames.includes('json')\n\n if (!quiet) {\n logBanner(version)\n logIntro({ title: 'Configuration' })\n }\n\n // Load the config first so `config.reporters` can pick the reporters. A failure here has no\n // reporter installed yet, so fall back to the default `cli` reporter to surface it.\n const configSpinner = createSpinner()\n let configs: Array<Config>\n let resolvedConfigPath: string\n try {\n if (!quiet) configSpinner.start('Loading config')\n\n const loaded = await getConfigs({\n configPath,\n input,\n watch,\n logLevel: logLevelKey as CLIOptions['logLevel'],\n })\n configs = loaded.configs\n resolvedConfigPath = loaded.configPath\n\n if (!quiet) configSpinner.stop(`Loaded ${styleText('dim', path.relative(process.cwd(), resolvedConfigPath))}`)\n } catch (error) {\n if (!quiet) configSpinner.error('Config failed loading')\n\n await setupReporters(hooks, { logLevel, reporters: [cliReporter] })\n await hooks.callHook('kubb:error', { error: toError(error) })\n\n if (!quiet) logOutro(styleText('red', '✗ Configuration failed'))\n process.exit(1)\n }\n\n const reporters = selectReporters(configs[0]?.reporters ?? [], requestedNames)\n await setupReporters(hooks, { logLevel, reporters })\n\n await hooks.callHook('kubb:lifecycle:start', { version })\n\n // Inside the bootstrap group, so an update notice reads as part of the setup rather than as part\n // of the first config's generation.\n await checkForUpdate(hooks)\n\n if (!quiet) logOutro(`${pluralize(configs.length, 'config')} ready`)\n\n try {\n let anyFailed = false\n for (const config of configs) {\n const effectiveInput = input ?? config.input\n const inputKind = typeof effectiveInput === 'string' ? getInputKind(effectiveInput) : undefined\n const watchPath = inputKind === 'file' || inputKind === 'url' ? (effectiveInput as string) : undefined\n if (watchPath && watch) {\n const watchedPaths = [watchPath]\n // Don't removeAll() between builds, that would also drop logger and lifecycle\n // listeners. Plugin listeners are already disposed by safeBuild's dispose()\n // in its finally block, so re-running generate() on the same hooks emitter is safe.\n const build = async (paths: Array<string>) => {\n const succeeded = await generate({ input, config, logLevel, hooks, dryRun })\n logStep(styleText('yellow', `Watching for changes in ${paths.join(' and ')}`))\n if (succeeded) {\n logSpacer()\n logTip()\n }\n }\n\n // For a URL input, capture the document before the build: it becomes the watcher's\n // change-detection baseline, so an edit landing before the first poll still rebuilds.\n // When the server is down the baseline stays undefined and the watcher rebuilds on its\n // first successful poll, so recovery with an unchanged document still generates output.\n const initialBody = inputKind === 'url' ? await fetchUrlBody(watchPath) : undefined\n\n // The watchers ignore their startup state (chokidar's initial events, the baseline\n // above), so run the first build here. A failing first build keeps watching, since\n // the user can fix the input and save.\n try {\n await build(watchedPaths)\n } catch (buildError) {\n await hooks.callHook('kubb:error', { error: toError(buildError) })\n }\n\n if (inputKind === 'url') {\n startUrlWatcher(watchPath, build, { log: { info: logInfo, error: logError }, initialBody })\n } else {\n await startWatcher(watchedPaths, build, { info: logInfo, error: logError })\n }\n } else {\n try {\n const succeeded = await generate({ input, config, logLevel, hooks, dryRun })\n if (!succeeded) anyFailed = true\n } catch (configError) {\n await hooks.callHook('kubb:error', { error: toError(configError) })\n anyFailed = true\n }\n }\n }\n\n await hooks.callHook('kubb:lifecycle:end')\n\n // Watch mode prints a tip after each successful build. Regular generate commands need to\n // print one explicitly after the lifecycle group has closed so it stays outside the group.\n if (!quiet && !watch && !anyFailed) {\n logTip()\n }\n\n if (anyFailed) {\n process.exit(1)\n }\n } catch (error) {\n await hooks.callHook('kubb:error', { error: toError(error) })\n process.exit(1)\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-qbf5tadS.cjs");
2
2
  const require_errors = require("./errors-C-wEou02.cjs");
3
3
  const require_Telemetry = require("./Telemetry-B3kc9gFh.cjs");
4
- const require_package = require("./package-Dg6ALxDA.cjs");
4
+ const require_package = require("./package-DjS7Xk-S.cjs");
5
5
  let node_util = require("node:util");
6
6
  let node_process = require("node:process");
7
7
  node_process = require_rolldown_runtime.__toESM(node_process, 1);
@@ -54,4 +54,4 @@ const runner = async ({ values }) => {
54
54
  //#endregion
55
55
  exports.runner = runner;
56
56
 
57
- //# sourceMappingURL=run-WTZgnA65.cjs.map
57
+ //# sourceMappingURL=run-BNQt-kUj.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-WTZgnA65.cjs","names":["process","sendTelemetry","buildTelemetryEvent","styleText","toError"],"sources":["../src/runners/validate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport type { CommandRunner } from 'gunshi'\nimport { buildTelemetryEvent, sendTelemetry } from '../../Telemetry.ts'\nimport { version } from '../../../package.json'\nimport type { definition } from '../../commands/validate.ts'\n\ntype ValidateOptions = {\n /**\n * Path or URL to the OpenAPI/Swagger file to validate.\n */\n input: string\n /**\n * Current `@kubb/cli` version string, used for the telemetry payload.\n */\n version: string\n}\n\n/**\n * Validates an OpenAPI/Swagger file at `input` using `@kubb/adapter-oas`.\n * Exits the process with code 1 on validation failure or missing dependency.\n */\nexport async function run({ input, version }: ValidateOptions): Promise<void> {\n const hrStart = process.hrtime()\n const report = (status: 'success' | 'failed') => sendTelemetry(buildTelemetryEvent({ command: 'validate', kubbVersion: version, hrStart, status }))\n\n try {\n const { adapterOas } = await import('@kubb/adapter-oas')\n\n const adapter = adapterOas()\n if (!adapter.validate) {\n throw new Error('The loaded adapter does not support validation.')\n }\n\n await adapter.validate(input, { throwOnError: true })\n await report('success')\n\n console.log('✅ Validation success')\n } catch (error) {\n await report('failed')\n if (error instanceof Error && /@kubb\\/adapter-oas/.test(error.message)) {\n console.error(styleText('red', 'The @kubb/adapter-oas package is not installed.'))\n console.error('')\n console.error('Install it with:')\n console.error(styleText('cyan', ' npm install @kubb/adapter-oas'))\n console.error(styleText('cyan', ' # or'))\n console.error(styleText('cyan', ' pnpm install @kubb/adapter-oas'))\n console.error('')\n }\n console.error('❌ Validation failed')\n console.error(toError(error).message)\n\n process.exit(1)\n }\n}\n\n/**\n * Loaded on demand by `index.ts`, so `@kubb/adapter-oas` stays out of the process for every other\n * command.\n */\nexport const runner: CommandRunner<{ args: typeof definition.args; extensions: {} }> = async ({ values }) => {\n await run({ input: values.input, version })\n}\n"],"mappings":";;;;;;;;;;;;AAuBA,eAAsB,IAAI,EAAE,OAAO,WAA2C;CAC5E,MAAM,UAAUA,aAAAA,QAAQ,OAAO;CAC/B,MAAM,UAAU,WAAiCC,kBAAAA,cAAcC,kBAAAA,oBAAoB;EAAE,SAAS;EAAY,aAAa;EAAS;EAAS;CAAO,CAAC,CAAC;CAElJ,IAAI;EACF,MAAM,EAAE,eAAe,MAAM,OAAO;EAEpC,MAAM,UAAU,WAAW;EAC3B,IAAI,CAAC,QAAQ,UACX,MAAM,IAAI,MAAM,iDAAiD;EAGnE,MAAM,QAAQ,SAAS,OAAO,EAAE,cAAc,KAAK,CAAC;EACpD,MAAM,OAAO,SAAS;EAEtB,QAAQ,IAAI,sBAAsB;CACpC,SAAS,OAAO;EACd,MAAM,OAAO,QAAQ;EACrB,IAAI,iBAAiB,SAAS,qBAAqB,KAAK,MAAM,OAAO,GAAG;GACtE,QAAQ,OAAA,GAAMC,UAAAA,UAAAA,CAAU,OAAO,iDAAiD,CAAC;GACjF,QAAQ,MAAM,EAAE;GAChB,QAAQ,MAAM,kBAAkB;GAChC,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,iCAAiC,CAAC;GAClE,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,QAAQ,CAAC;GACzC,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,kCAAkC,CAAC;GACnE,QAAQ,MAAM,EAAE;EAClB;EACA,QAAQ,MAAM,qBAAqB;EACnC,QAAQ,MAAMC,eAAAA,QAAQ,KAAK,CAAC,CAAC,OAAO;EAEpC,aAAA,QAAQ,KAAK,CAAC;CAChB;AACF;;;;;AAMA,MAAa,SAA0E,OAAO,EAAE,aAAa;CAC3G,MAAM,IAAI;EAAE,OAAO,OAAO;EAAO,SAAA,gBAAA;CAAQ,CAAC;AAC5C"}
1
+ {"version":3,"file":"run-BNQt-kUj.cjs","names":["process","sendTelemetry","buildTelemetryEvent","styleText","toError"],"sources":["../src/runners/validate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport type { CommandRunner } from 'gunshi'\nimport { buildTelemetryEvent, sendTelemetry } from '../../Telemetry.ts'\nimport { version } from '../../../package.json'\nimport type { definition } from '../../commands/validate.ts'\n\ntype ValidateOptions = {\n /**\n * Path or URL to the OpenAPI/Swagger file to validate.\n */\n input: string\n /**\n * Current `@kubb/cli` version string, used for the telemetry payload.\n */\n version: string\n}\n\n/**\n * Validates an OpenAPI/Swagger file at `input` using `@kubb/adapter-oas`.\n * Exits the process with code 1 on validation failure or missing dependency.\n */\nexport async function run({ input, version }: ValidateOptions): Promise<void> {\n const hrStart = process.hrtime()\n const report = (status: 'success' | 'failed') => sendTelemetry(buildTelemetryEvent({ command: 'validate', kubbVersion: version, hrStart, status }))\n\n try {\n const { adapterOas } = await import('@kubb/adapter-oas')\n\n const adapter = adapterOas()\n if (!adapter.validate) {\n throw new Error('The loaded adapter does not support validation.')\n }\n\n await adapter.validate(input, { throwOnError: true })\n await report('success')\n\n console.log('✅ Validation success')\n } catch (error) {\n await report('failed')\n if (error instanceof Error && /@kubb\\/adapter-oas/.test(error.message)) {\n console.error(styleText('red', 'The @kubb/adapter-oas package is not installed.'))\n console.error('')\n console.error('Install it with:')\n console.error(styleText('cyan', ' npm install @kubb/adapter-oas'))\n console.error(styleText('cyan', ' # or'))\n console.error(styleText('cyan', ' pnpm install @kubb/adapter-oas'))\n console.error('')\n }\n console.error('❌ Validation failed')\n console.error(toError(error).message)\n\n process.exit(1)\n }\n}\n\n/**\n * Loaded on demand by `index.ts`, so `@kubb/adapter-oas` stays out of the process for every other\n * command.\n */\nexport const runner: CommandRunner<{ args: typeof definition.args; extensions: {} }> = async ({ values }) => {\n await run({ input: values.input, version })\n}\n"],"mappings":";;;;;;;;;;;;AAuBA,eAAsB,IAAI,EAAE,OAAO,WAA2C;CAC5E,MAAM,UAAUA,aAAAA,QAAQ,OAAO;CAC/B,MAAM,UAAU,WAAiCC,kBAAAA,cAAcC,kBAAAA,oBAAoB;EAAE,SAAS;EAAY,aAAa;EAAS;EAAS;CAAO,CAAC,CAAC;CAElJ,IAAI;EACF,MAAM,EAAE,eAAe,MAAM,OAAO;EAEpC,MAAM,UAAU,WAAW;EAC3B,IAAI,CAAC,QAAQ,UACX,MAAM,IAAI,MAAM,iDAAiD;EAGnE,MAAM,QAAQ,SAAS,OAAO,EAAE,cAAc,KAAK,CAAC;EACpD,MAAM,OAAO,SAAS;EAEtB,QAAQ,IAAI,sBAAsB;CACpC,SAAS,OAAO;EACd,MAAM,OAAO,QAAQ;EACrB,IAAI,iBAAiB,SAAS,qBAAqB,KAAK,MAAM,OAAO,GAAG;GACtE,QAAQ,OAAA,GAAMC,UAAAA,UAAAA,CAAU,OAAO,iDAAiD,CAAC;GACjF,QAAQ,MAAM,EAAE;GAChB,QAAQ,MAAM,kBAAkB;GAChC,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,iCAAiC,CAAC;GAClE,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,QAAQ,CAAC;GACzC,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,kCAAkC,CAAC;GACnE,QAAQ,MAAM,EAAE;EAClB;EACA,QAAQ,MAAM,qBAAqB;EACnC,QAAQ,MAAMC,eAAAA,QAAQ,KAAK,CAAC,CAAC,OAAO;EAEpC,aAAA,QAAQ,KAAK,CAAC;CAChB;AACF;;;;;AAMA,MAAa,SAA0E,OAAO,EAAE,aAAa;CAC3G,MAAM,IAAI;EAAE,OAAO,OAAO;EAAO,SAAA,gBAAA;CAAQ,CAAC;AAC5C"}
@@ -1,7 +1,7 @@
1
- import "./rolldown-runtime-C0LytTxp.js";
2
- import { t as toError } from "./errors-C8yNfV7w.js";
3
- import { r as sendTelemetry, t as buildTelemetryEvent } from "./Telemetry-Dw5s6abr.js";
4
- import { t as version } from "./package-B1pE4gUR.js";
1
+ import "./rolldown-runtime-CRm0XQPb.js";
2
+ import { t as toError } from "./errors-BQJzaUwP.js";
3
+ import { r as sendTelemetry, t as buildTelemetryEvent } from "./Telemetry-cHHOzBW8.js";
4
+ import { t as version } from "./package-IY922xjh.js";
5
5
  import { styleText } from "node:util";
6
6
  import process from "node:process";
7
7
  //#region src/runners/validate/run.ts
@@ -53,4 +53,4 @@ const runner = async ({ values }) => {
53
53
  //#endregion
54
54
  export { runner };
55
55
 
56
- //# sourceMappingURL=run-CJmvvmr6.js.map
56
+ //# sourceMappingURL=run-BaqE5cze.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-CJmvvmr6.js","names":[],"sources":["../src/runners/validate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport type { CommandRunner } from 'gunshi'\nimport { buildTelemetryEvent, sendTelemetry } from '../../Telemetry.ts'\nimport { version } from '../../../package.json'\nimport type { definition } from '../../commands/validate.ts'\n\ntype ValidateOptions = {\n /**\n * Path or URL to the OpenAPI/Swagger file to validate.\n */\n input: string\n /**\n * Current `@kubb/cli` version string, used for the telemetry payload.\n */\n version: string\n}\n\n/**\n * Validates an OpenAPI/Swagger file at `input` using `@kubb/adapter-oas`.\n * Exits the process with code 1 on validation failure or missing dependency.\n */\nexport async function run({ input, version }: ValidateOptions): Promise<void> {\n const hrStart = process.hrtime()\n const report = (status: 'success' | 'failed') => sendTelemetry(buildTelemetryEvent({ command: 'validate', kubbVersion: version, hrStart, status }))\n\n try {\n const { adapterOas } = await import('@kubb/adapter-oas')\n\n const adapter = adapterOas()\n if (!adapter.validate) {\n throw new Error('The loaded adapter does not support validation.')\n }\n\n await adapter.validate(input, { throwOnError: true })\n await report('success')\n\n console.log('✅ Validation success')\n } catch (error) {\n await report('failed')\n if (error instanceof Error && /@kubb\\/adapter-oas/.test(error.message)) {\n console.error(styleText('red', 'The @kubb/adapter-oas package is not installed.'))\n console.error('')\n console.error('Install it with:')\n console.error(styleText('cyan', ' npm install @kubb/adapter-oas'))\n console.error(styleText('cyan', ' # or'))\n console.error(styleText('cyan', ' pnpm install @kubb/adapter-oas'))\n console.error('')\n }\n console.error('❌ Validation failed')\n console.error(toError(error).message)\n\n process.exit(1)\n }\n}\n\n/**\n * Loaded on demand by `index.ts`, so `@kubb/adapter-oas` stays out of the process for every other\n * command.\n */\nexport const runner: CommandRunner<{ args: typeof definition.args; extensions: {} }> = async ({ values }) => {\n await run({ input: values.input, version })\n}\n"],"mappings":";;;;;;;;;;;AAuBA,eAAsB,IAAI,EAAE,OAAO,WAA2C;CAC5E,MAAM,UAAU,QAAQ,OAAO;CAC/B,MAAM,UAAU,WAAiC,cAAc,oBAAoB;EAAE,SAAS;EAAY,aAAa;EAAS;EAAS;CAAO,CAAC,CAAC;CAElJ,IAAI;EACF,MAAM,EAAE,eAAe,MAAM,OAAO;EAEpC,MAAM,UAAU,WAAW;EAC3B,IAAI,CAAC,QAAQ,UACX,MAAM,IAAI,MAAM,iDAAiD;EAGnE,MAAM,QAAQ,SAAS,OAAO,EAAE,cAAc,KAAK,CAAC;EACpD,MAAM,OAAO,SAAS;EAEtB,QAAQ,IAAI,sBAAsB;CACpC,SAAS,OAAO;EACd,MAAM,OAAO,QAAQ;EACrB,IAAI,iBAAiB,SAAS,qBAAqB,KAAK,MAAM,OAAO,GAAG;GACtE,QAAQ,MAAM,UAAU,OAAO,iDAAiD,CAAC;GACjF,QAAQ,MAAM,EAAE;GAChB,QAAQ,MAAM,kBAAkB;GAChC,QAAQ,MAAM,UAAU,QAAQ,iCAAiC,CAAC;GAClE,QAAQ,MAAM,UAAU,QAAQ,QAAQ,CAAC;GACzC,QAAQ,MAAM,UAAU,QAAQ,kCAAkC,CAAC;GACnE,QAAQ,MAAM,EAAE;EAClB;EACA,QAAQ,MAAM,qBAAqB;EACnC,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC,OAAO;EAEpC,QAAQ,KAAK,CAAC;CAChB;AACF;;;;;AAMA,MAAa,SAA0E,OAAO,EAAE,aAAa;CAC3G,MAAM,IAAI;EAAE,OAAO,OAAO;EAAO;CAAQ,CAAC;AAC5C"}
1
+ {"version":3,"file":"run-BaqE5cze.js","names":[],"sources":["../src/runners/validate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport type { CommandRunner } from 'gunshi'\nimport { buildTelemetryEvent, sendTelemetry } from '../../Telemetry.ts'\nimport { version } from '../../../package.json'\nimport type { definition } from '../../commands/validate.ts'\n\ntype ValidateOptions = {\n /**\n * Path or URL to the OpenAPI/Swagger file to validate.\n */\n input: string\n /**\n * Current `@kubb/cli` version string, used for the telemetry payload.\n */\n version: string\n}\n\n/**\n * Validates an OpenAPI/Swagger file at `input` using `@kubb/adapter-oas`.\n * Exits the process with code 1 on validation failure or missing dependency.\n */\nexport async function run({ input, version }: ValidateOptions): Promise<void> {\n const hrStart = process.hrtime()\n const report = (status: 'success' | 'failed') => sendTelemetry(buildTelemetryEvent({ command: 'validate', kubbVersion: version, hrStart, status }))\n\n try {\n const { adapterOas } = await import('@kubb/adapter-oas')\n\n const adapter = adapterOas()\n if (!adapter.validate) {\n throw new Error('The loaded adapter does not support validation.')\n }\n\n await adapter.validate(input, { throwOnError: true })\n await report('success')\n\n console.log('✅ Validation success')\n } catch (error) {\n await report('failed')\n if (error instanceof Error && /@kubb\\/adapter-oas/.test(error.message)) {\n console.error(styleText('red', 'The @kubb/adapter-oas package is not installed.'))\n console.error('')\n console.error('Install it with:')\n console.error(styleText('cyan', ' npm install @kubb/adapter-oas'))\n console.error(styleText('cyan', ' # or'))\n console.error(styleText('cyan', ' pnpm install @kubb/adapter-oas'))\n console.error('')\n }\n console.error('❌ Validation failed')\n console.error(toError(error).message)\n\n process.exit(1)\n }\n}\n\n/**\n * Loaded on demand by `index.ts`, so `@kubb/adapter-oas` stays out of the process for every other\n * command.\n */\nexport const runner: CommandRunner<{ args: typeof definition.args; extensions: {} }> = async ({ values }) => {\n await run({ input: values.input, version })\n}\n"],"mappings":";;;;;;;;;;;AAuBA,eAAsB,IAAI,EAAE,OAAO,WAA2C;CAC5E,MAAM,UAAU,QAAQ,OAAO;CAC/B,MAAM,UAAU,WAAiC,cAAc,oBAAoB;EAAE,SAAS;EAAY,aAAa;EAAS;EAAS;CAAO,CAAC,CAAC;CAElJ,IAAI;EACF,MAAM,EAAE,eAAe,MAAM,OAAO;EAEpC,MAAM,UAAU,WAAW;EAC3B,IAAI,CAAC,QAAQ,UACX,MAAM,IAAI,MAAM,iDAAiD;EAGnE,MAAM,QAAQ,SAAS,OAAO,EAAE,cAAc,KAAK,CAAC;EACpD,MAAM,OAAO,SAAS;EAEtB,QAAQ,IAAI,sBAAsB;CACpC,SAAS,OAAO;EACd,MAAM,OAAO,QAAQ;EACrB,IAAI,iBAAiB,SAAS,qBAAqB,KAAK,MAAM,OAAO,GAAG;GACtE,QAAQ,MAAM,UAAU,OAAO,iDAAiD,CAAC;GACjF,QAAQ,MAAM,EAAE;GAChB,QAAQ,MAAM,kBAAkB;GAChC,QAAQ,MAAM,UAAU,QAAQ,iCAAiC,CAAC;GAClE,QAAQ,MAAM,UAAU,QAAQ,QAAQ,CAAC;GACzC,QAAQ,MAAM,UAAU,QAAQ,kCAAkC,CAAC;GACnE,QAAQ,MAAM,EAAE;EAClB;EACA,QAAQ,MAAM,qBAAqB;EACnC,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC,OAAO;EAEpC,QAAQ,KAAK,CAAC;CAChB;AACF;;;;;AAMA,MAAa,SAA0E,OAAO,EAAE,aAAa;CAC3G,MAAM,IAAI;EAAE,OAAO,OAAO;EAAO;CAAQ,CAAC;AAC5C"}
@@ -1,10 +1,10 @@
1
- import "./rolldown-runtime-C0LytTxp.js";
2
- import { t as toError } from "./errors-C8yNfV7w.js";
3
- import { n as isCIEnvironment } from "./agent-3JmkMghp.js";
4
- import { r as sendTelemetry, t as buildTelemetryEvent, u as runtime } from "./Telemetry-Dw5s6abr.js";
5
- import { n as getConfigs, u as setupReporters } from "./utils-TpILNAy7.js";
6
- import { o as logIntro, p as canUseTTY, r as logBlock, s as logOutro, t as createSpinner, u as logTip } from "./output-C_Gk4p-8.js";
7
- import { t as version } from "./package-B1pE4gUR.js";
1
+ import "./rolldown-runtime-CRm0XQPb.js";
2
+ import { t as toError } from "./errors-BQJzaUwP.js";
3
+ import { n as isCIEnvironment } from "./agent-w0Hlq4mG.js";
4
+ import { r as sendTelemetry, t as buildTelemetryEvent, u as runtime } from "./Telemetry-cHHOzBW8.js";
5
+ import { n as getConfigs, u as setupReporters } from "./utils-BWksgOYQ.js";
6
+ import { o as logIntro, p as canUseTTY, r as logBlock, s as logOutro, t as createSpinner, u as logTip } from "./output-C5h3LBgQ.js";
7
+ import { t as version } from "./package-IY922xjh.js";
8
8
  import { t as KUBB_CONFIG_FILENAME } from "./constants-DHRspBTo.js";
9
9
  import { styleText } from "node:util";
10
10
  import { hash } from "node:crypto";
@@ -13,9 +13,9 @@ import process from "node:process";
13
13
  import { execFile } from "node:child_process";
14
14
  import { access, mkdir, readFile, rm, writeFile } from "node:fs/promises";
15
15
  import path from "node:path";
16
- import { cliReporter, logLevel } from "@kubb/core";
17
- import * as prompts from "@clack/prompts";
18
16
  import { PairingCanceledError, createFileStorage, defaultStudioUrl, pairAgent, runConnection, setStorage } from "@kubb/studio";
17
+ import * as prompts from "@clack/prompts";
18
+ import { cliReporter, logLevel } from "@kubb/core";
19
19
  //#region ../../internals/utils/src/openInBrowser.ts
20
20
  /**
21
21
  * Opens a URL or local file in the default browser, unless running in CI.
@@ -291,158 +291,109 @@ function explainRejectedToken(error, reason) {
291
291
  if (reason === "reauthExhausted") return /* @__PURE__ */ new Error(`${error.message} Studio rejected the newly approved token too. Run \`kubb studio login\` and try again.`);
292
292
  return /* @__PURE__ */ new Error(`${error.message} Run \`kubb studio login\` to pair again.`);
293
293
  }
294
- /**
295
- * One `kubb studio` connect run: pairing if needed, connecting, and pairing again whenever Studio
296
- * rejects the token. Reached through `connect()`, which is what the command runs.
297
- */
298
- var StudioConnection = class {
299
- #options;
300
- #configPath;
301
- #shutdown = new AbortController();
302
- #requestShutdown = () => this.#shutdown.abort();
303
- #processEvents = process;
304
- #credentials;
305
- #hinted = false;
306
- #hasReauthenticated = false;
307
- #granted;
308
- constructor(options, configPath) {
309
- this.#options = options;
310
- this.#configPath = configPath;
311
- }
312
- #reportDisconnected() {
313
- if (this.#options.logLevel === "silent") return;
314
- logOutro("Disconnected");
315
- }
316
- /**
317
- * Connects and streams generation events until the process is stopped or Studio rejects the
318
- * token.
319
- *
320
- * One `AbortController` covers the whole run: it cancels an in-flight pairing poll on Ctrl+C and
321
- * ends the wait in `#connectAndWait`. Its signal listeners are armed once here, so a retried
322
- * pairing cannot leave a duplicate behind.
323
- */
324
- async run() {
325
- this.#processEvents.once("SIGINT", this.#requestShutdown);
326
- this.#processEvents.once("SIGTERM", this.#requestShutdown);
327
- try {
328
- this.#credentials = await this.#resolveInitialCredentials();
329
- this.#granted = await resolvePermissions(this.#options, this.#credentials, this.#configPath, !process.env.KUBB_AGENT_TOKEN);
330
- this.#printBanner();
331
- if (await runConnection({
332
- credentials: this.#credentials,
333
- signal: this.#shutdown.signal,
334
- clientOptions: () => this.#clientOptions(),
335
- onTokenRejected: ({ error, live }) => this.#handleRejection(error, live)
336
- }) === "shutdown") this.#reportDisconnected();
337
- } catch (error) {
338
- if (error instanceof PairingCanceledError) return;
339
- throw error;
340
- } finally {
341
- this.#processEvents.off("SIGINT", this.#requestShutdown);
342
- this.#processEvents.off("SIGTERM", this.#requestShutdown);
343
- }
344
- }
345
- async #resolveInitialCredentials() {
346
- const envToken = process.env.KUBB_AGENT_TOKEN;
347
- const stored = envToken ? null : await readCredentials();
348
- const resolved = envToken ? {
349
- studioUrl: this.#options.studioUrl,
294
+ /** Validates the project and resolves pairing and permissions before starting its worker. */
295
+ async function prepareConnection(options, signal) {
296
+ const { configPath } = await loadConfigs(options);
297
+ const envToken = process.env.KUBB_AGENT_TOKEN;
298
+ const stored = envToken ? null : await readCredentials();
299
+ const credentials = await (async () => {
300
+ if (envToken) return {
301
+ studioUrl: options.studioUrl,
350
302
  token: envToken,
351
303
  agentId: "",
352
304
  agentSlug: ""
353
- } : stored?.studioUrl === this.#options.studioUrl ? stored : null;
354
- if (resolved) return resolved;
355
- if (isCIEnvironment()) throw new Error(`Not paired with ${this.#options.studioUrl}. Set KUBB_AGENT_TOKEN, or run \`kubb studio login\` on a machine with a browser.`);
356
- return login(this.#options, { signal: this.#shutdown.signal });
357
- }
358
- #printBanner() {
359
- if (this.#options.logLevel === "silent") return;
360
- const detail = (label, value) => `${styleText("dim", label.padEnd(7))} ${value}`;
361
- logBlock([
362
- detail("Studio", styleText("cyan", this.#options.studioUrl)),
363
- detail("Project", path.basename(process.cwd())),
364
- detail("Config", path.relative(process.cwd(), this.#configPath) || this.#configPath),
365
- "",
366
- styleText("dim", "Permissions"),
367
- ...formatPermissionRows(this.#granted)
368
- ]);
369
- }
370
- /**
371
- * What every connection attempt opens with. Rebuilt per attempt, so a re-pair that changed the
372
- * granted permissions takes effect on the next one.
373
- */
374
- #clientOptions() {
375
- return {
376
- studioUrl: this.#options.studioUrl,
377
- configPath: this.#configPath,
378
- version: this.#options.version,
379
- loadConfig: async () => (await loadConfigs(this.#options)).config,
380
- root: process.cwd(),
381
- permissions: this.#granted,
382
- installLogger: async (hooks) => {
383
- await setupReporters(hooks, {
384
- logLevel: logLevel[this.#options.logLevel ?? "info"],
385
- reporters: [cliReporter]
386
- });
387
- hooks.hook("studio:connected", () => {
388
- if (this.#hinted || this.#options.logLevel === "silent") return;
389
- this.#hinted = true;
390
- logBlock(styleText("dim", "Press Ctrl+C to disconnect"));
391
- });
392
- hooks.hook("studio:ready", () => {
393
- logTip();
394
- });
395
- }
396
305
  };
306
+ if (stored?.studioUrl === options.studioUrl) return stored;
307
+ if (isCIEnvironment()) throw new Error(`Not paired with ${options.studioUrl}. Set KUBB_AGENT_TOKEN, or run \`kubb studio login\` on a machine with a browser.`);
308
+ return login(options, { signal });
309
+ })();
310
+ return {
311
+ configPath,
312
+ credentials,
313
+ permissions: await resolvePermissions(options, credentials, configPath, !envToken)
314
+ };
315
+ }
316
+ /** Runs the same project connection in the foreground or in a background worker. */
317
+ async function connect(options, context = {}) {
318
+ const shutdown = new AbortController();
319
+ const signal = context.signal ?? shutdown.signal;
320
+ const stop = () => shutdown.abort();
321
+ const events = process;
322
+ if (!context.signal) {
323
+ events.once("SIGINT", stop);
324
+ events.once("SIGTERM", stop);
397
325
  }
398
- /**
399
- * Throws when a rejected token cannot be replaced by pairing again: this run already paired once
400
- * and was rejected anyway, or there is no browser to approve a new pairing.
401
- */
402
- #assertCanReauthenticate(error) {
403
- if (this.#hasReauthenticated) throw explainRejectedToken(error, "reauthExhausted");
404
- if (isCIEnvironment() || !canUseTTY()) throw explainRejectedToken(error, "nonInteractive");
405
- }
406
- /**
407
- * Studio rejected the token, either before a session ever opened or once one was already live.
408
- * Keeping a rejected token only produces 401s on every run, so it is forgotten and paired again.
409
- * Returns the credential to reconnect with, or null when the run is over.
410
- */
411
- async #handleRejection(error, live) {
412
- if (process.env.KUBB_AGENT_TOKEN) throw explainRejectedToken(error, "envToken");
413
- if (!live) await clearCredentials();
414
- this.#assertCanReauthenticate(error);
415
- console.log(styleText("yellow", live ? `${error.message} Studio needs you to approve access again.` : `${error.message} Pairing again...`));
416
- if (live) await clearCredentials();
417
- const credentials = await this.#reauthenticate();
418
- if (!credentials && live) this.#reportDisconnected();
419
- return credentials;
420
- }
421
- /**
422
- * Re-pairs and stores the resulting credentials. Returns null when the operator canceled it.
423
- */
424
- async #reauthenticate() {
425
- try {
426
- this.#credentials = await login(this.#options, {
427
- signal: this.#shutdown.signal,
428
- previousCredentials: this.#credentials
429
- });
430
- } catch (loginError) {
431
- if (loginError instanceof PairingCanceledError) return null;
432
- throw loginError;
326
+ let hinted = false;
327
+ let reauthenticated = false;
328
+ try {
329
+ if (!context.prepared) {
330
+ const { getWorkerStatus } = await import("./background-CS7jIBAY.js");
331
+ if ((await getWorkerStatus()).running) throw new Error("This project is running in the background. Run `kubb studio stop` first.");
433
332
  }
434
- this.#hasReauthenticated = true;
435
- this.#granted = await resolvePermissions(this.#options, this.#credentials, this.#configPath, !process.env.KUBB_AGENT_TOKEN);
436
- return this.#credentials;
333
+ const prepared = context.prepared ?? await prepareConnection(options, signal);
334
+ let { credentials, permissions } = prepared;
335
+ const { configPath } = prepared;
336
+ await runConnection({
337
+ credentials,
338
+ signal,
339
+ clientOptions: () => ({
340
+ studioUrl: options.studioUrl,
341
+ configPath,
342
+ version: options.version,
343
+ root: process.cwd(),
344
+ permissions,
345
+ loadConfig: async () => (await loadConfigs(options)).config,
346
+ installLogger: async (hooks) => {
347
+ if (!context.onState) await setupReporters(hooks, {
348
+ logLevel: logLevel[options.logLevel ?? "info"],
349
+ reporters: [cliReporter]
350
+ });
351
+ hooks.hook("studio:connected", () => {
352
+ if (!hinted && !context.onState && options.logLevel !== "silent") logBlock(styleText("dim", "Press Ctrl+C to disconnect"));
353
+ hinted = true;
354
+ });
355
+ hooks.hook("studio:ready", async () => {
356
+ await context.onState?.("connected");
357
+ if (!context.onState) logTip();
358
+ });
359
+ hooks.hook("studio:reconnecting", () => context.onState?.("reconnecting"));
360
+ hooks.hook("studio:error", ({ error }) => {
361
+ if (context.onState) console.error(error.message);
362
+ });
363
+ }
364
+ }),
365
+ onTokenRejected: async ({ error, live }) => {
366
+ await context.onState?.("authentication required");
367
+ if (process.env.KUBB_AGENT_TOKEN) throw explainRejectedToken(error, "envToken");
368
+ if (!live) await clearCredentials();
369
+ if (reauthenticated) throw explainRejectedToken(error, "reauthExhausted");
370
+ if (context.onState || isCIEnvironment() || !canUseTTY()) throw explainRejectedToken(error, "nonInteractive");
371
+ console.log(styleText("yellow", live ? `${error.message} Studio needs you to approve access again.` : `${error.message} Pairing again...`));
372
+ if (live) await clearCredentials();
373
+ try {
374
+ credentials = await login(options, {
375
+ signal,
376
+ previousCredentials: credentials
377
+ });
378
+ } catch (error) {
379
+ if (error instanceof PairingCanceledError) {
380
+ if (live && options.logLevel !== "silent") logOutro("Disconnected");
381
+ return null;
382
+ }
383
+ throw error;
384
+ }
385
+ reauthenticated = true;
386
+ permissions = await resolvePermissions(options, credentials, configPath, !process.env.KUBB_AGENT_TOKEN);
387
+ return credentials;
388
+ }
389
+ });
390
+ if (!context.onState && signal.aborted && options.logLevel !== "silent") logOutro("Disconnected");
391
+ } catch (error) {
392
+ if (!(error instanceof PairingCanceledError)) throw error;
393
+ } finally {
394
+ events.off("SIGINT", stop);
395
+ events.off("SIGTERM", stop);
437
396
  }
438
- };
439
- /**
440
- * Connects this project to Studio and streams generation events until the process is stopped or
441
- * Studio rejects the token.
442
- */
443
- async function connect(options) {
444
- const { configPath } = await loadConfigs(options);
445
- await new StudioConnection(options, configPath).run();
446
397
  }
447
398
  /**
448
399
  * Reports the paired agent and any saved permissions for the current project.
@@ -494,6 +445,6 @@ async function run(options, action, { block = false, json = false } = {}) {
494
445
  }
495
446
  }
496
447
  //#endregion
497
- export { run as a, exists as c, login as i, read as l, createStudioOptions as n, status as o, loadConfigs as r, clearCredentials as s, connect as t };
448
+ export { prepareConnection as a, clearCredentials as c, read as d, login as i, getProjectKubbHome as l, createStudioOptions as n, run as o, loadConfigs as r, status as s, connect as t, exists as u };
498
449
 
499
- //# sourceMappingURL=run-DgWNV5Z5.js.map
450
+ //# sourceMappingURL=run-BsP5syy1.js.map