@kubb/cli 5.11.4 → 5.11.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{Telemetry-Be1nltUh.cjs → Telemetry-Be3hIy6_.cjs} +2 -42
- package/dist/Telemetry-Be3hIy6_.cjs.map +1 -0
- package/dist/{Telemetry-CwaVQsvD.js → Telemetry-CfJAUDnh.js} +3 -31
- package/dist/Telemetry-CfJAUDnh.js.map +1 -0
- package/dist/{background-CQPyCSn0.js → background-BBpH2jmk.js} +7 -5
- package/dist/background-BBpH2jmk.js.map +1 -0
- package/dist/{background-mKdZ5HRx.cjs → background-BW-e9FCX.cjs} +5 -4
- package/dist/background-BW-e9FCX.cjs.map +1 -0
- package/dist/{background-aTbwrgui.js → background-DS2zOde-.js} +1 -1
- package/dist/config-Bh00Hwpw.js +132 -0
- package/dist/config-Bh00Hwpw.js.map +1 -0
- package/dist/config-D63Gum4F.cjs +169 -0
- package/dist/config-D63Gum4F.cjs.map +1 -0
- package/dist/config-iVdOcpro.js +1 -0
- package/dist/credentials-CZK6zPLv.js.map +1 -1
- package/dist/credentials-DDaKqtJn.cjs.map +1 -1
- package/dist/errors-Cl69p_vI.cjs +43 -0
- package/dist/errors-Cl69p_vI.cjs.map +1 -0
- package/dist/errors-DmC83ALX.js +32 -0
- package/dist/errors-DmC83ALX.js.map +1 -0
- package/dist/index.cjs +872 -307
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +863 -298
- package/dist/index.js.map +1 -1
- package/dist/registry-BlKLO4ft.cjs +272 -0
- package/dist/registry-BlKLO4ft.cjs.map +1 -0
- package/dist/registry-CgQYxUju.js +200 -0
- package/dist/registry-CgQYxUju.js.map +1 -0
- package/dist/reporters-Dl8lrJZG.js +817 -0
- package/dist/reporters-Dl8lrJZG.js.map +1 -0
- package/dist/reporters-TkCgd4dS.cjs +829 -0
- package/dist/reporters-TkCgd4dS.cjs.map +1 -0
- package/dist/{run-YHth5Afz.js → run-BJn0RSW2.js} +170 -76
- package/dist/run-BJn0RSW2.js.map +1 -0
- package/dist/{run-BWRmQxtE.cjs → run-BszyZwY3.cjs} +176 -82
- package/dist/run-BszyZwY3.cjs.map +1 -0
- package/dist/{run-Bczs5vbI.cjs → run-BtVKUjdK.cjs} +4 -3
- package/dist/{run-Bczs5vbI.cjs.map → run-BtVKUjdK.cjs.map} +1 -1
- package/dist/run-CFf0yxyY.cjs +94 -0
- package/dist/run-CFf0yxyY.cjs.map +1 -0
- package/dist/run-D_dD7xHp.js +93 -0
- package/dist/run-D_dD7xHp.js.map +1 -0
- package/dist/run-DsJJCzQD.js +1 -0
- package/dist/{run-B6VxJ_VM.js → run-KuzAqsjg.js} +3 -2
- package/dist/{run-B6VxJ_VM.js.map → run-KuzAqsjg.js.map} +1 -1
- package/dist/run-TrjCNL8e.cjs +227 -0
- package/dist/run-TrjCNL8e.cjs.map +1 -0
- package/dist/run-wkN1irUo.js +224 -0
- package/dist/run-wkN1irUo.js.map +1 -0
- package/dist/{snapshot-Cilp10vE.js → snapshot-CdGwHH15.js} +49 -62
- package/dist/snapshot-CdGwHH15.js.map +1 -0
- package/dist/{snapshot-D_rXnnMH.cjs → snapshot-u4L8mh4Y.cjs} +51 -64
- package/dist/snapshot-u4L8mh4Y.cjs.map +1 -0
- package/dist/status-DHPeR3bq.js +77 -0
- package/dist/status-DHPeR3bq.js.map +1 -0
- package/dist/status-dpSvxxtN.cjs +78 -0
- package/dist/status-dpSvxxtN.cjs.map +1 -0
- package/dist/studioWorker.js +2 -2
- package/dist/summary-6-rotl2L.cjs +46 -0
- package/dist/summary-6-rotl2L.cjs.map +1 -0
- package/dist/summary-DkSLti6f.js +41 -0
- package/dist/summary-DkSLti6f.js.map +1 -0
- package/dist/text-CMP4M19Z.js +239 -0
- package/dist/text-CMP4M19Z.js.map +1 -0
- package/dist/text-CknhKMvM.cjs +341 -0
- package/dist/text-CknhKMvM.cjs.map +1 -0
- package/dist/utils-CnjEJIdZ.js +612 -0
- package/dist/utils-CnjEJIdZ.js.map +1 -0
- package/dist/utils-DpKrXR2t.cjs +727 -0
- package/dist/utils-DpKrXR2t.cjs.map +1 -0
- package/package.json +7 -7
- package/dist/Telemetry-Be1nltUh.cjs.map +0 -1
- package/dist/Telemetry-CwaVQsvD.js.map +0 -1
- package/dist/background-CQPyCSn0.js.map +0 -1
- package/dist/background-mKdZ5HRx.cjs.map +0 -1
- package/dist/config-B56ZuVhi.js +0 -95
- package/dist/config-B56ZuVhi.js.map +0 -1
- package/dist/config-Cs4N79Fm.cjs +0 -113
- package/dist/config-Cs4N79Fm.cjs.map +0 -1
- package/dist/output-HgzJqkSF.cjs +0 -1076
- package/dist/output-HgzJqkSF.cjs.map +0 -1
- package/dist/output-PhkPtNP7.js +0 -937
- package/dist/output-PhkPtNP7.js.map +0 -1
- package/dist/registry-DYUhC7rH.js +0 -115
- package/dist/registry-DYUhC7rH.js.map +0 -1
- package/dist/registry-tk-v78fd.cjs +0 -157
- package/dist/registry-tk-v78fd.cjs.map +0 -1
- package/dist/run-AfjIBtiL.js +0 -39
- package/dist/run-AfjIBtiL.js.map +0 -1
- package/dist/run-BWRmQxtE.cjs.map +0 -1
- package/dist/run-B_Gr9TJ4.cjs +0 -345
- package/dist/run-B_Gr9TJ4.cjs.map +0 -1
- package/dist/run-CwrI0wRy.js +0 -1
- package/dist/run-DDoJGjWT.cjs +0 -40
- package/dist/run-DDoJGjWT.cjs.map +0 -1
- package/dist/run-SYKj8-Q5.js +0 -343
- package/dist/run-SYKj8-Q5.js.map +0 -1
- package/dist/run-YHth5Afz.js.map +0 -1
- package/dist/snapshot-Cilp10vE.js.map +0 -1
- package/dist/snapshot-D_rXnnMH.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-BJn0RSW2.js","names":["logLevelMap"],"sources":["../../../internals/utils/src/copyToClipboard.ts","../../../internals/utils/src/openInBrowser.ts","../src/runners/studio/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { x } from 'tinyexec'\nimport { isCIEnvironment } from './isCIEnvironment.ts'\n\nconst COMMANDS: Partial<Record<NodeJS.Platform, [string, ...Array<string>]>> = {\n darwin: ['pbcopy'],\n win32: ['clip.exe'],\n linux: ['xclip', '-selection', 'clipboard'],\n}\n\n/**\n * Copies text to the system clipboard with the platform's own tool. Resolves `false` in CI, on a\n * platform without a known tool, or when the tool is missing or fails.\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n // Wayland sessions have no X selection for xclip to serve, so they use `wl-copy`.\n const command = process.platform === 'linux' && process.env.WAYLAND_DISPLAY ? (['wl-copy'] as const) : COMMANDS[process.platform]\n if (!command || isCIEnvironment()) return false\n\n const [name, ...args] = command\n // stdout and stderr are ignored: xclip and wl-copy stay alive to serve the selection and would hold open pipes until the timeout.\n const run = x(name, args, { timeout: 2_000, nodeOptions: { stdio: ['pipe', 'ignore', 'ignore'] } })\n // A missing tool closes stdin before the write lands; the rejection below reports it.\n run.process?.stdin?.once('error', () => {})\n run.process?.stdin?.end(text)\n\n return run.then(\n ({ exitCode }) => exitCode === 0,\n () => false,\n )\n}\n","import process from 'node:process'\nimport { x } from 'tinyexec'\nimport { isCIEnvironment } from './isCIEnvironment.ts'\n\nconst ignore = () => {}\n\n/**\n * Opens a URL or local file in the default browser, unless running in CI.\n */\nexport function openInBrowser(target: string): void {\n if (isCIEnvironment()) return\n\n if (process.platform === 'win32') {\n x('cmd', ['/c', 'start', '', target]).then(ignore, ignore)\n return\n }\n x(process.platform === 'darwin' ? 'open' : 'xdg-open', [target]).then(ignore, ignore)\n}\n","import { hostname } from 'node:os'\nimport { toPermissionFlag } from '../../ui/text.ts'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport * as prompts from '@clack/prompts'\nimport { KUBB_CONFIG_FILENAME } from '@internals/shared'\nimport { copyToClipboard, isCIEnvironment, openInBrowser, toError } from '@internals/utils'\nimport type { CLIOptions, Config } from '@kubb/core'\nimport { cliReporter, Diagnostics, Hookable, type KubbHooks, logLevel as logLevelMap } from '@kubb/core'\nimport { connectAgent, defaultStudioUrl, InvalidAgentTokenError, pairAgent, PairingCanceledError } from '@kubb/studio'\nimport { AgentPermission } from '@kubb/studio/protocol'\nimport { trackRun } from '../../Telemetry.ts'\nimport { plainWriter } from '../../loggers/plainWriter.ts'\nimport setupReporters from '../../loggers/reporters.ts'\nimport { logIntro, logOutro, logTip } from '../../ui/intro.ts'\nimport { logBlock, logStep } from '../../ui/log.ts'\nimport { createSpinner } from '../../ui/spinner.ts'\nimport { canUseTTY, isRichOutput } from '../../utils/env.ts'\nimport { getConfigs } from '../../config.ts'\nimport { clearCredentials, type Credentials, getCredentialsPath, getMachineId, readCredentials, writeCredentials } from './credentials.ts'\nimport { version } from '../../../package.json'\n\nexport type StudioOptions = {\n /**\n * Current `@kubb/cli` version, reported to Studio and used for the telemetry payload.\n */\n version: string\n configPath?: string\n /**\n * Base URL of the Studio instance, for a self-hosted deployment. Resolved before it reaches here,\n * since stored credentials are bound to it.\n */\n studioUrl: string\n /**\n * What Studio may do in this project. Each flag grants outright; the rest are asked once per\n * project through {@link resolvePermissions}.\n */\n permission: Record<AgentPermission, boolean>\n /**\n * Whether to open the approval page in a browser during pairing.\n */\n autoOpen: boolean\n logLevel?: CLIOptions['logLevel']\n}\n\nexport type SnapshotOptions = Pick<StudioOptions, 'configPath' | 'studioUrl' | 'logLevel'> & {\n /**\n * Organization CI API key. Falls back to `KUBB_TOKEN`.\n */\n token?: string\n /**\n * Stable identity for the CI agent. Falls back to CI auto-detection.\n */\n id?: string\n /** Identity of another CI agent to also compare with. Falls back to CI auto-detection. */\n baseId?: string\n /**\n * Package name for the generated tarball. Falls back to the nearest package.json.\n */\n name?: string\n /**\n * Package version for the generated tarball. Falls back to the nearest package.json.\n */\n packageVersion?: string\n /**\n * Print the result as one JSON object instead of a summary.\n */\n json?: boolean\n}\n\n/** The flags a `kubb studio` subcommand parsed; each one is optional since a subcommand declares only the flags it uses. */\nexport type StudioValues = {\n config?: string\n url?: string\n allowRead?: boolean\n allowReadAst?: boolean\n allowWrite?: boolean\n allowConfigEdit?: boolean\n allowExec?: boolean\n open?: boolean\n logLevel?: CLIOptions['logLevel']\n}\n\ntype LoginOptions = {\n /**\n * Aborting this cancels an in-flight pairing request or poll and rejects with\n * {@link PairingCanceledError}. Wired to `kubb studio`'s shutdown signal, so Ctrl+C during\n * pairing cancels it instead of leaving the poll running.\n */\n signal?: AbortSignal\n /**\n * Credentials from before this login. When the fresh pairing resolves to the same agent on the\n * same Studio, its saved project permissions carry forward instead of being asked again.\n * Left out for an explicitly requested `kubb studio login`, which always starts clean.\n */\n previousCredentials?: Credentials | null\n}\n\n/**\n * Pairs this machine with Studio and stores the resulting token.\n *\n * The CLI holds a code and the browser approves it, rather than the user copying a token out of\n * the UI. The token comes back over the CLI's own HTTPS POST, so it never lands in a URL, a\n * server log, or a `Referer` header.\n */\nexport async function login({ studioUrl, autoOpen }: StudioOptions, { signal, previousCredentials }: LoginOptions = {}): Promise<Credentials> {\n const spinner = createSpinner()\n // A retry notice stays on screen a while before the countdown takes the line back.\n let retryUntil = 0\n // The spinner only starts once a code is shown.\n let waiting = false\n let countdown: NodeJS.Timeout | undefined\n\n try {\n const { token, agent } = await pairAgent({\n studioUrl,\n type: 'cli',\n name: path.basename(process.cwd()),\n hostname: hostname(),\n machineId: await getMachineId(),\n signal,\n onCode: (session) => {\n logStep(\n [\n 'Pair this machine',\n `${styleText('dim', 'Open')} ${styleText('cyan', session.verification_uri)}`,\n `${styleText('dim', 'Code')} ${styleText('bold', session.user_code)}`,\n ].join('\\n'),\n )\n\n if (autoOpen) {\n openInBrowser(session.verification_uri_complete)\n }\n\n // Same fallback as the poll in `@kubb/studio`, so the countdown ends when polling does.\n const deadline = Date.now() + (session.expires_in > 0 ? session.expires_in : 600) * 1000\n let copied = false\n const waitingText = () =>\n `Waiting for approval ${styleText('dim', `expires in ${formatCountdown(deadline - Date.now())}${copied ? ' · code copied' : ''} · ctrl+c to cancel`)}`\n clearInterval(countdown)\n spinner.start(waitingText())\n waiting = true\n // Plain output prints every message, so only an animated spinner ticks.\n if (isRichOutput()) countdown = setInterval(() => Date.now() > retryUntil && spinner.message(waitingText()), 1000)\n // Not awaited: the code shows at once, and the spinner picks up the copy when it lands.\n void copyToClipboard(session.user_code).then((done) => {\n copied = done\n })\n },\n onRetry: (error) => {\n retryUntil = Date.now() + 5000\n spinner.message(`Could not reach Kubb Studio, retrying: ${error.message}`)\n },\n })\n clearInterval(countdown)\n spinner.stop(`Paired as ${agent.name}${agent.organizationSlug ? ` · org ${agent.organizationSlug}` : ''}`)\n\n const keepsIdentity = previousCredentials?.studioUrl === studioUrl && previousCredentials.agentId === agent.id\n const credentials: Credentials = {\n studioUrl,\n token,\n agentId: agent.id,\n agentSlug: agent.slug,\n ...(agent.organizationSlug ? { organizationSlug: agent.organizationSlug } : {}),\n ...(keepsIdentity && previousCredentials?.projects ? { projects: previousCredentials.projects } : {}),\n }\n await writeCredentials(credentials)\n\n console.log(`Credentials stored in ${getCredentialsPath()}`)\n\n return credentials\n } catch (error) {\n clearInterval(countdown)\n if (waiting) {\n spinner.stop(error instanceof PairingCanceledError ? 'Pairing canceled' : 'Pairing failed')\n }\n throw error\n }\n}\n\n/** Time left on a pairing code as `m:ss`, never below `0:00`. */\nexport function formatCountdown(ms: number): string {\n const seconds = Math.max(0, Math.ceil(ms / 1000))\n\n return `${Math.floor(seconds / 60)}:${String(seconds % 60).padStart(2, '0')}`\n}\n\n/**\n * What each permission is asked as, in the order the list shows them.\n */\nconst PERMISSIONS: ReadonlyArray<{\n key: AgentPermission\n /**\n * Short label for status output and the connect summary.\n */\n label: string\n title: (configPath: string) => string\n hint: string\n}> = [\n { key: AgentPermission.READ, label: 'read source', title: () => 'Read generated files', hint: 'show code in the browser' },\n { key: AgentPermission.READ_AST, label: 'read spec', title: () => 'Read the parsed spec', hint: 'browse schemas and operations' },\n { key: AgentPermission.WRITE, label: 'write files', title: () => 'Write files to disk', hint: 'generate from the browser' },\n { key: AgentPermission.CONFIG_EDIT, label: 'edit config', title: (configPath) => `Change ${configPath}`, hint: 'edit plugin options' },\n { key: AgentPermission.EXEC, label: 'run tools', title: () => 'Run the formatter, linter, and postGenerate', hint: 'after each generation' },\n]\n\n/**\n * Two permissions per row, each marked granted or not, with the flags that grant the missing ones\n * after the last row. For `kubb studio status`.\n */\nexport function formatPermissionRows(granted: Partial<Record<AgentPermission, boolean>>): Array<string> {\n const width = Math.max(...PERMISSIONS.map(({ label }) => label.length))\n const cells = PERMISSIONS.map(({ key, label }) => `${granted[key] ? styleText('green', '✓') : styleText('red', '✖')} ${label.padEnd(width)}`)\n const rows = Array.from({ length: Math.ceil(cells.length / 2) }, (_, index) => cells.slice(index * 2, index * 2 + 2).join(' '))\n const flags = PERMISSIONS.filter(({ key }) => !granted[key])\n .map(({ key }) => toPermissionFlag(key))\n .join(' ')\n\n return flags ? [...rows.slice(0, -1), `${rows.at(-1)} ${styleText('dim', flags)}`] : rows\n}\n\n/**\n * Resolves Studio permissions for the current project.\n * Flags win, saved answers are reused, and the rest are asked in one list whose answers are stored\n * in `~/.kubb/credentials.json`.\n */\nexport async function resolvePermissions(\n options: StudioOptions,\n credentials: Credentials,\n configPath: string = KUBB_CONFIG_FILENAME,\n): Promise<Record<AgentPermission, boolean>> {\n const project = process.cwd()\n const remembered = credentials.projects?.[project]\n const granted = Object.fromEntries(PERMISSIONS.map(({ key }) => [key, options.permission[key] || remembered?.[key] === true])) as Record<\n AgentPermission,\n boolean\n >\n const pending = PERMISSIONS.filter(({ key }) => !options.permission[key] && typeof remembered?.[key] !== 'boolean')\n\n if (!pending.length || isCIEnvironment() || !canUseTTY()) return granted\n\n prompts.updateSettings({ withGuide: true })\n const selected = await prompts.multiselect({\n message: 'What may Kubb Studio do in this project?',\n options: pending.map(({ key, title, hint }) => ({ value: key, label: title(configPath), hint })),\n required: false,\n })\n // A canceled list grants nothing and saves nothing, so the next run asks again.\n if (prompts.isCancel(selected)) return granted\n\n const answers = Object.fromEntries(pending.map(({ key }) => [key, selected.includes(key)]))\n await writeCredentials({\n ...credentials,\n projects: { ...credentials.projects, [project]: { ...remembered, ...answers } },\n })\n\n return { ...granted, ...answers }\n}\n\n/**\n * Loads the project's Kubb config the same way `kubb generate` does, one entry per `defineConfig(...)` entry.\n */\nexport async function loadConfigs(options: Pick<StudioOptions, 'configPath' | 'logLevel'>): Promise<{ configPath: string; configs: Array<Config> }> {\n const { configPath, configs } = await getConfigs({ configPath: options.configPath, logLevel: options.logLevel })\n\n if (!configs.length) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'Config not defined, create a kubb.config.ts or pass it with --config',\n })\n }\n\n // `getConfigs` resolves this to an absolute path. Relativized here, once, so the permission\n // prompt and the path Studio receives over the wire both show the project-relative form instead\n // of leaking the local filesystem layout.\n return { configPath: path.relative(process.cwd(), configPath) || configPath, configs }\n}\n\nexport type PreparedConnection = {\n configPath: string\n credentials: Credentials\n permissions: StudioOptions['permission']\n}\n\n/** Validates the project and resolves pairing and permissions before starting its worker. */\nexport async function prepareConnection(options: StudioOptions, signal?: AbortSignal): Promise<PreparedConnection> {\n const { configPath } = await loadConfigs(options)\n const stored = await readCredentials()\n const credentials = await (async () => {\n if (stored?.studioUrl === options.studioUrl) return stored\n if (isCIEnvironment()) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `Not paired with ${options.studioUrl}. In CI, run \\`kubb studio snapshot\\` instead, or run \\`kubb studio login\\` on a machine with a browser.`,\n })\n }\n return login(options, { signal })\n })()\n const permissions = await resolvePermissions(options, credentials, configPath)\n return { configPath, credentials, permissions }\n}\n\nexport type WorkerState = 'starting' | 'connected' | 'reconnecting' | 'authentication required' | 'stopped'\n\n/** Runs the same project connection in the foreground or in a background worker. */\nexport async function connect(\n options: StudioOptions,\n context: {\n prepared?: PreparedConnection\n signal?: AbortSignal\n onState?: (state: WorkerState) => void | Promise<void>\n } = {},\n): Promise<void> {\n const shutdown = new AbortController()\n const signal = context.signal ?? shutdown.signal\n const stop = () => shutdown.abort()\n const events = process as unknown as NodeJS.EventEmitter\n if (!context.signal) {\n events.once('SIGINT', stop)\n events.once('SIGTERM', stop)\n }\n let unwatch: (() => void) | undefined\n try {\n if (!context.prepared) {\n const { getWorkerStatus } = await import('./background.ts')\n const worker = await getWorkerStatus()\n if (worker.running)\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'This project is running in the background. Run `kubb studio stop` first.',\n })\n }\n const prepared = context.prepared ?? (await prepareConnection(options, signal))\n let { credentials, permissions } = prepared\n const { configPath } = prepared\n let hinted = false\n // Set by a fresh pairing until it connects, so a token rejected right after approval fails the run instead of looping.\n let pairedAgain = false\n\n // The background worker writes to a log file, so it gets the plain logger rather than the\n // animated one. The logger also covers the `studio:*` events and each generation run.\n const hooks = new Hookable<KubbHooks>()\n setupReporters(hooks, {\n logLevel: logLevelMap[options.logLevel ?? 'info'],\n reporters: [cliReporter],\n ...(context.onState ? { writer: plainWriter } : {}),\n })\n // `b` hands the session to the background worker; only a foreground run in a terminal listens.\n const listens = !context.onState && process.stdin.isTTY === true && canUseTTY()\n let background = false\n hooks.hook('studio:connected', async () => {\n pairedAgain = false\n await context.onState?.('connected')\n if (listens && !unwatch) {\n unwatch = watchKeys({\n onBackground: () => {\n background = true\n stop()\n },\n onStop: stop,\n })\n }\n if (hinted || context.onState || options.logLevel === 'silent') return\n hinted = true\n logBlock([\n `${styleText('dim', 'Project')} ${path.basename(process.cwd())} ${styleText(\n 'dim',\n PERMISSIONS.filter(({ key }) => permissions[key])\n .map(({ label }) => label)\n .join(' · ') || 'no permissions',\n )}`,\n styleText('dim', listens ? 'Press b to keep running in the background, Ctrl+C to disconnect' : 'Press Ctrl+C to disconnect'),\n ])\n logTip()\n })\n hooks.hook('studio:reconnecting', () => context.onState?.('reconnecting'))\n\n for (;;) {\n try {\n await connectAgent({\n token: credentials.token,\n studioUrl: options.studioUrl,\n configPath,\n version: options.version,\n root: process.cwd(),\n permissions,\n loadConfigs: async () => (await loadConfigs(options)).configs,\n hooks,\n signal,\n })\n break\n } catch (error) {\n if (!(error instanceof InvalidAgentTokenError)) throw error\n await context.onState?.('authentication required')\n await clearCredentials()\n if (pairedAgain) throw new Error(`${error.message} Studio rejected the newly approved token too. Run \\`kubb studio login\\` and try again.`)\n if (context.onState || isCIEnvironment() || !canUseTTY()) throw new Error(`${error.message} Run \\`kubb studio login\\` to pair again.`)\n\n // The pairing prompts need stdin back.\n unwatch?.()\n unwatch = undefined\n console.log(styleText('yellow', `${error.message} Pairing again...`))\n credentials = await login(options, { signal, previousCredentials: credentials })\n pairedAgain = true\n permissions = await resolvePermissions(options, credentials, configPath)\n }\n }\n // Stops the \"Ready for jobs\" spinner, which would otherwise keep drawing under the closing line.\n await hooks.callHook('kubb:lifecycle:end')\n unwatch?.()\n if (background) {\n const { startWorker } = await import('./background.ts')\n await startWorker(options)\n if (options.logLevel !== 'silent') logOutro('Running in the background · kubb studio stop')\n return\n }\n if (!context.onState && signal.aborted && options.logLevel !== 'silent') logOutro('Disconnected')\n } catch (error) {\n if (!(error instanceof PairingCanceledError)) throw error\n } finally {\n unwatch?.()\n events.off('SIGINT', stop)\n events.off('SIGTERM', stop)\n }\n}\n\n/**\n * Listens for single keys on a TTY stdin. Raw mode turns Ctrl+C into a key instead of SIGINT, so it\n * is handled here too. Returns the function that restores the terminal, safe to call twice.\n */\nexport function watchKeys({ onBackground, onStop }: { onBackground: () => void; onStop: () => void }): () => void {\n const stdin = process.stdin\n const onData = (data: Buffer) => {\n const key = data.toString()\n if (key === 'b' || key === 'B') onBackground()\n if (key === '\\u0003') onStop()\n }\n // A clack spinner reads stdin too and exits the process on Ctrl+C, before the session can close\n // its socket, so its Ctrl+C alias is lifted while these keys are read.\n const cancelAlias = prompts.settings.aliases.get('\\u0003')\n prompts.settings.aliases.delete('\\u0003')\n stdin.setRawMode(true)\n stdin.on('data', onData)\n stdin.resume()\n let restored = false\n\n return () => {\n if (restored) return\n restored = true\n if (cancelAlias) prompts.settings.aliases.set('\\u0003', cancelAlias)\n stdin.off('data', onData)\n stdin.setRawMode(false)\n stdin.pause()\n }\n}\n\n/**\n * Runs a Studio command from its parsed flags: builds the {@link StudioOptions}, prints the intro,\n * and reports the run to telemetry. A failure is printed and sets the exit code instead of throwing.\n */\nexport async function runStudio(\n values: StudioValues,\n action: (options: StudioOptions) => Promise<unknown>,\n { block = false, json = false }: { block?: boolean; json?: boolean } = {},\n): Promise<void> {\n const options: StudioOptions = {\n version,\n configPath: values.config,\n studioUrl: values.url ?? defaultStudioUrl,\n permission: Object.fromEntries(Object.values(AgentPermission).map((key) => [key, values[key] ?? false])) as Record<AgentPermission, boolean>,\n autoOpen: values.open ?? true,\n logLevel: values.logLevel,\n }\n const report = trackRun({ command: 'studio', hrStart: process.hrtime() })\n\n try {\n if (options.logLevel !== 'silent' && !json) {\n logIntro({\n warning: styleText('yellow', 'This feature is still under development, use with caution'),\n block,\n })\n }\n\n await action(options)\n\n await report({ status: 'success' })\n } catch (error) {\n await report({ status: 'failed' })\n console.error(toError(error).message)\n process.exitCode = 1\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const require_rolldown_runtime = require("./rolldown-runtime-CPE0t6oh.cjs");
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
2
|
+
const require_errors = require("./errors-Cl69p_vI.cjs");
|
|
3
|
+
const require_Telemetry = require("./Telemetry-Be3hIy6_.cjs");
|
|
4
|
+
const require_utils = require("./utils-DpKrXR2t.cjs");
|
|
5
|
+
const require_text = require("./text-CknhKMvM.cjs");
|
|
6
|
+
const require_config = require("./config-D63Gum4F.cjs");
|
|
7
|
+
const require_reporters = require("./reporters-TkCgd4dS.cjs");
|
|
5
8
|
const require_credentials = require("./credentials-DDaKqtJn.cjs");
|
|
6
9
|
let node_util = require("node:util");
|
|
7
10
|
let node_os = require("node:os");
|
|
@@ -10,11 +13,42 @@ node_process = require_rolldown_runtime.__toESM(node_process, 1);
|
|
|
10
13
|
let tinyexec = require("tinyexec");
|
|
11
14
|
let node_path = require("node:path");
|
|
12
15
|
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
13
|
-
let _kubb_core = require("@kubb/core");
|
|
14
16
|
let _clack_prompts = require("@clack/prompts");
|
|
15
17
|
_clack_prompts = require_rolldown_runtime.__toESM(_clack_prompts, 1);
|
|
18
|
+
let _kubb_core = require("@kubb/core");
|
|
16
19
|
let _kubb_studio = require("@kubb/studio");
|
|
17
20
|
let _kubb_studio_protocol = require("@kubb/studio/protocol");
|
|
21
|
+
//#region ../../internals/utils/src/copyToClipboard.ts
|
|
22
|
+
const COMMANDS = {
|
|
23
|
+
darwin: ["pbcopy"],
|
|
24
|
+
win32: ["clip.exe"],
|
|
25
|
+
linux: [
|
|
26
|
+
"xclip",
|
|
27
|
+
"-selection",
|
|
28
|
+
"clipboard"
|
|
29
|
+
]
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Copies text to the system clipboard with the platform's own tool. Resolves `false` in CI, on a
|
|
33
|
+
* platform without a known tool, or when the tool is missing or fails.
|
|
34
|
+
*/
|
|
35
|
+
async function copyToClipboard(text) {
|
|
36
|
+
const command = node_process.default.platform === "linux" && node_process.default.env.WAYLAND_DISPLAY ? ["wl-copy"] : COMMANDS[node_process.default.platform];
|
|
37
|
+
if (!command || require_Telemetry.isCIEnvironment()) return false;
|
|
38
|
+
const [name, ...args] = command;
|
|
39
|
+
const run = (0, tinyexec.x)(name, args, {
|
|
40
|
+
timeout: 2e3,
|
|
41
|
+
nodeOptions: { stdio: [
|
|
42
|
+
"pipe",
|
|
43
|
+
"ignore",
|
|
44
|
+
"ignore"
|
|
45
|
+
] }
|
|
46
|
+
});
|
|
47
|
+
run.process?.stdin?.once("error", () => {});
|
|
48
|
+
run.process?.stdin?.end(text);
|
|
49
|
+
return run.then(({ exitCode }) => exitCode === 0, () => false);
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
18
52
|
//#region ../../internals/utils/src/openInBrowser.ts
|
|
19
53
|
const ignore = () => {};
|
|
20
54
|
/**
|
|
@@ -43,8 +77,10 @@ function openInBrowser(target) {
|
|
|
43
77
|
* server log, or a `Referer` header.
|
|
44
78
|
*/
|
|
45
79
|
async function login({ studioUrl, autoOpen }, { signal, previousCredentials } = {}) {
|
|
46
|
-
const spinner =
|
|
80
|
+
const spinner = require_utils.createSpinner();
|
|
81
|
+
let retryUntil = 0;
|
|
47
82
|
let waiting = false;
|
|
83
|
+
let countdown;
|
|
48
84
|
try {
|
|
49
85
|
const { token, agent } = await (0, _kubb_studio.pairAgent)({
|
|
50
86
|
studioUrl,
|
|
@@ -54,99 +90,123 @@ async function login({ studioUrl, autoOpen }, { signal, previousCredentials } =
|
|
|
54
90
|
machineId: await require_credentials.getMachineId(),
|
|
55
91
|
signal,
|
|
56
92
|
onCode: (session) => {
|
|
57
|
-
|
|
93
|
+
require_text.logStep([
|
|
94
|
+
"Pair this machine",
|
|
95
|
+
`${(0, node_util.styleText)("dim", "Open")} ${(0, node_util.styleText)("cyan", session.verification_uri)}`,
|
|
96
|
+
`${(0, node_util.styleText)("dim", "Code")} ${(0, node_util.styleText)("bold", session.user_code)}`
|
|
97
|
+
].join("\n"));
|
|
58
98
|
if (autoOpen) openInBrowser(session.verification_uri_complete);
|
|
59
|
-
|
|
99
|
+
const deadline = Date.now() + (session.expires_in > 0 ? session.expires_in : 600) * 1e3;
|
|
100
|
+
let copied = false;
|
|
101
|
+
const waitingText = () => `Waiting for approval ${(0, node_util.styleText)("dim", `expires in ${formatCountdown(deadline - Date.now())}${copied ? " · code copied" : ""} · ctrl+c to cancel`)}`;
|
|
102
|
+
clearInterval(countdown);
|
|
103
|
+
spinner.start(waitingText());
|
|
60
104
|
waiting = true;
|
|
105
|
+
if (require_text.isRichOutput()) countdown = setInterval(() => Date.now() > retryUntil && spinner.message(waitingText()), 1e3);
|
|
106
|
+
copyToClipboard(session.user_code).then((done) => {
|
|
107
|
+
copied = done;
|
|
108
|
+
});
|
|
61
109
|
},
|
|
62
|
-
onRetry: (error) =>
|
|
110
|
+
onRetry: (error) => {
|
|
111
|
+
retryUntil = Date.now() + 5e3;
|
|
112
|
+
spinner.message(`Could not reach Kubb Studio, retrying: ${error.message}`);
|
|
113
|
+
}
|
|
63
114
|
});
|
|
64
|
-
|
|
115
|
+
clearInterval(countdown);
|
|
116
|
+
spinner.stop(`Paired as ${agent.name}${agent.organizationSlug ? ` · org ${agent.organizationSlug}` : ""}`);
|
|
65
117
|
const keepsIdentity = previousCredentials?.studioUrl === studioUrl && previousCredentials.agentId === agent.id;
|
|
66
118
|
const credentials = {
|
|
67
119
|
studioUrl,
|
|
68
120
|
token,
|
|
69
121
|
agentId: agent.id,
|
|
70
122
|
agentSlug: agent.slug,
|
|
123
|
+
...agent.organizationSlug ? { organizationSlug: agent.organizationSlug } : {},
|
|
71
124
|
...keepsIdentity && previousCredentials?.projects ? { projects: previousCredentials.projects } : {}
|
|
72
125
|
};
|
|
73
126
|
await require_credentials.writeCredentials(credentials);
|
|
74
127
|
console.log(`Credentials stored in ${require_credentials.getCredentialsPath()}`);
|
|
75
128
|
return credentials;
|
|
76
129
|
} catch (error) {
|
|
130
|
+
clearInterval(countdown);
|
|
77
131
|
if (waiting) spinner.stop(error instanceof _kubb_studio.PairingCanceledError ? "Pairing canceled" : "Pairing failed");
|
|
78
132
|
throw error;
|
|
79
133
|
}
|
|
80
134
|
}
|
|
135
|
+
/** Time left on a pairing code as `m:ss`, never below `0:00`. */
|
|
136
|
+
function formatCountdown(ms) {
|
|
137
|
+
const seconds = Math.max(0, Math.ceil(ms / 1e3));
|
|
138
|
+
return `${Math.floor(seconds / 60)}:${String(seconds % 60).padStart(2, "0")}`;
|
|
139
|
+
}
|
|
81
140
|
/**
|
|
82
|
-
* What each permission is asked as, in the order the
|
|
141
|
+
* What each permission is asked as, in the order the list shows them.
|
|
83
142
|
*/
|
|
84
143
|
const PERMISSIONS = [
|
|
85
144
|
{
|
|
86
145
|
key: _kubb_studio_protocol.AgentPermission.READ,
|
|
87
|
-
label: "read
|
|
88
|
-
|
|
146
|
+
label: "read source",
|
|
147
|
+
title: () => "Read generated files",
|
|
148
|
+
hint: "show code in the browser"
|
|
89
149
|
},
|
|
90
150
|
{
|
|
91
151
|
key: _kubb_studio_protocol.AgentPermission.READ_AST,
|
|
92
|
-
label: "read
|
|
93
|
-
|
|
152
|
+
label: "read spec",
|
|
153
|
+
title: () => "Read the parsed spec",
|
|
154
|
+
hint: "browse schemas and operations"
|
|
94
155
|
},
|
|
95
156
|
{
|
|
96
157
|
key: _kubb_studio_protocol.AgentPermission.WRITE,
|
|
97
|
-
label: "write
|
|
98
|
-
|
|
158
|
+
label: "write files",
|
|
159
|
+
title: () => "Write files to disk",
|
|
160
|
+
hint: "generate from the browser"
|
|
99
161
|
},
|
|
100
162
|
{
|
|
101
163
|
key: _kubb_studio_protocol.AgentPermission.CONFIG_EDIT,
|
|
102
|
-
label: "edit
|
|
103
|
-
|
|
164
|
+
label: "edit config",
|
|
165
|
+
title: (configPath) => `Change ${configPath}`,
|
|
166
|
+
hint: "edit plugin options"
|
|
104
167
|
},
|
|
105
168
|
{
|
|
106
169
|
key: _kubb_studio_protocol.AgentPermission.EXEC,
|
|
107
|
-
label: "run
|
|
108
|
-
|
|
170
|
+
label: "run tools",
|
|
171
|
+
title: () => "Run the formatter, linter, and postGenerate",
|
|
172
|
+
hint: "after each generation"
|
|
109
173
|
}
|
|
110
174
|
];
|
|
111
175
|
/**
|
|
112
|
-
*
|
|
113
|
-
*
|
|
176
|
+
* Two permissions per row, each marked granted or not, with the flags that grant the missing ones
|
|
177
|
+
* after the last row. For `kubb studio status`.
|
|
114
178
|
*/
|
|
115
179
|
function formatPermissionRows(granted) {
|
|
116
|
-
|
|
180
|
+
const width = Math.max(...PERMISSIONS.map(({ label }) => label.length));
|
|
181
|
+
const cells = PERMISSIONS.map(({ key, label }) => `${granted[key] ? (0, node_util.styleText)("green", "✓") : (0, node_util.styleText)("red", "✖")} ${label.padEnd(width)}`);
|
|
182
|
+
const rows = Array.from({ length: Math.ceil(cells.length / 2) }, (_, index) => cells.slice(index * 2, index * 2 + 2).join(" "));
|
|
183
|
+
const flags = PERMISSIONS.filter(({ key }) => !granted[key]).map(({ key }) => require_text.toPermissionFlag(key)).join(" ");
|
|
184
|
+
return flags ? [...rows.slice(0, -1), `${rows.at(-1)} ${(0, node_util.styleText)("dim", flags)}`] : rows;
|
|
117
185
|
}
|
|
118
186
|
/**
|
|
119
187
|
* Resolves Studio permissions for the current project.
|
|
120
|
-
* Flags win, saved answers are reused, and
|
|
188
|
+
* Flags win, saved answers are reused, and the rest are asked in one list whose answers are stored
|
|
189
|
+
* in `~/.kubb/credentials.json`.
|
|
121
190
|
*/
|
|
122
|
-
async function resolvePermissions(options, credentials, configPath =
|
|
191
|
+
async function resolvePermissions(options, credentials, configPath = require_config.KUBB_CONFIG_FILENAME) {
|
|
123
192
|
const project = node_process.default.cwd();
|
|
124
193
|
const remembered = credentials.projects?.[project];
|
|
125
|
-
const granted = {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
allowWrite: false,
|
|
129
|
-
allowConfigEdit: false,
|
|
130
|
-
allowExec: false
|
|
131
|
-
};
|
|
132
|
-
const answers = {};
|
|
194
|
+
const granted = Object.fromEntries(PERMISSIONS.map(({ key }) => [key, options.permission[key] || remembered?.[key] === true]));
|
|
195
|
+
const pending = PERMISSIONS.filter(({ key }) => !options.permission[key] && typeof remembered?.[key] !== "boolean");
|
|
196
|
+
if (!pending.length || require_Telemetry.isCIEnvironment() || !require_text.canUseTTY()) return granted;
|
|
133
197
|
_clack_prompts.updateSettings({ withGuide: true });
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}) === true;
|
|
147
|
-
answers[key] = granted[key];
|
|
148
|
-
}
|
|
149
|
-
if (Object.keys(answers).length) await require_credentials.writeCredentials({
|
|
198
|
+
const selected = await _clack_prompts.multiselect({
|
|
199
|
+
message: "What may Kubb Studio do in this project?",
|
|
200
|
+
options: pending.map(({ key, title, hint }) => ({
|
|
201
|
+
value: key,
|
|
202
|
+
label: title(configPath),
|
|
203
|
+
hint
|
|
204
|
+
})),
|
|
205
|
+
required: false
|
|
206
|
+
});
|
|
207
|
+
if (_clack_prompts.isCancel(selected)) return granted;
|
|
208
|
+
const answers = Object.fromEntries(pending.map(({ key }) => [key, selected.includes(key)]));
|
|
209
|
+
await require_credentials.writeCredentials({
|
|
150
210
|
...credentials,
|
|
151
211
|
projects: {
|
|
152
212
|
...credentials.projects,
|
|
@@ -156,36 +216,29 @@ async function resolvePermissions(options, credentials, configPath = require_out
|
|
|
156
216
|
}
|
|
157
217
|
}
|
|
158
218
|
});
|
|
159
|
-
return
|
|
219
|
+
return {
|
|
220
|
+
...granted,
|
|
221
|
+
...answers
|
|
222
|
+
};
|
|
160
223
|
}
|
|
161
224
|
/**
|
|
162
|
-
* Loads the project's Kubb config the same way `kubb generate` does.
|
|
163
|
-
* Returns the first config.
|
|
225
|
+
* Loads the project's Kubb config the same way `kubb generate` does, one entry per `defineConfig(...)` entry.
|
|
164
226
|
*/
|
|
165
227
|
async function loadConfigs(options) {
|
|
166
228
|
const { configPath, configs } = await require_config.getConfigs({
|
|
167
229
|
configPath: options.configPath,
|
|
168
230
|
logLevel: options.logLevel
|
|
169
231
|
});
|
|
170
|
-
|
|
171
|
-
if (!config) throw new _kubb_core.Diagnostics.Error({
|
|
232
|
+
if (!configs.length) throw new _kubb_core.Diagnostics.Error({
|
|
172
233
|
code: _kubb_core.Diagnostics.code.unknown,
|
|
173
234
|
severity: "error",
|
|
174
235
|
message: "Config not defined, create a kubb.config.ts or pass it with --config"
|
|
175
236
|
});
|
|
176
237
|
return {
|
|
177
238
|
configPath: node_path.default.relative(node_process.default.cwd(), configPath) || configPath,
|
|
178
|
-
|
|
239
|
+
configs
|
|
179
240
|
};
|
|
180
241
|
}
|
|
181
|
-
/**
|
|
182
|
-
* Explains a rejected token to the operator. Builds the error and nothing else, so each caller
|
|
183
|
-
* decides what happens to the credentials.
|
|
184
|
-
*/
|
|
185
|
-
function explainRejectedToken(error, reason) {
|
|
186
|
-
if (reason === "reauthExhausted") return /* @__PURE__ */ new Error(`${error.message} Studio rejected the newly approved token too. Run \`kubb studio login\` and try again.`);
|
|
187
|
-
return /* @__PURE__ */ new Error(`${error.message} Run \`kubb studio login\` to pair again.`);
|
|
188
|
-
}
|
|
189
242
|
/** Validates the project and resolves pairing and permissions before starting its worker. */
|
|
190
243
|
async function prepareConnection(options, signal) {
|
|
191
244
|
const { configPath } = await loadConfigs(options);
|
|
@@ -215,9 +268,10 @@ async function connect(options, context = {}) {
|
|
|
215
268
|
events.once("SIGINT", stop);
|
|
216
269
|
events.once("SIGTERM", stop);
|
|
217
270
|
}
|
|
271
|
+
let unwatch;
|
|
218
272
|
try {
|
|
219
273
|
if (!context.prepared) {
|
|
220
|
-
const { getWorkerStatus } = await Promise.resolve().then(() => require("./background-
|
|
274
|
+
const { getWorkerStatus } = await Promise.resolve().then(() => require("./background-BW-e9FCX.cjs"));
|
|
221
275
|
if ((await getWorkerStatus()).running) throw new _kubb_core.Diagnostics.Error({
|
|
222
276
|
code: _kubb_core.Diagnostics.code.unknown,
|
|
223
277
|
severity: "error",
|
|
@@ -230,18 +284,27 @@ async function connect(options, context = {}) {
|
|
|
230
284
|
let hinted = false;
|
|
231
285
|
let pairedAgain = false;
|
|
232
286
|
const hooks = new _kubb_core.Hookable();
|
|
233
|
-
|
|
287
|
+
require_reporters.setupReporters(hooks, {
|
|
234
288
|
logLevel: _kubb_core.logLevel[options.logLevel ?? "info"],
|
|
235
289
|
reporters: [_kubb_core.cliReporter],
|
|
236
|
-
...context.onState ? {
|
|
290
|
+
...context.onState ? { writer: require_text.plainWriter } : {}
|
|
237
291
|
});
|
|
292
|
+
const listens = !context.onState && node_process.default.stdin.isTTY === true && require_text.canUseTTY();
|
|
293
|
+
let background = false;
|
|
238
294
|
hooks.hook("studio:connected", async () => {
|
|
239
295
|
pairedAgain = false;
|
|
240
296
|
await context.onState?.("connected");
|
|
297
|
+
if (listens && !unwatch) unwatch = watchKeys({
|
|
298
|
+
onBackground: () => {
|
|
299
|
+
background = true;
|
|
300
|
+
stop();
|
|
301
|
+
},
|
|
302
|
+
onStop: stop
|
|
303
|
+
});
|
|
241
304
|
if (hinted || context.onState || options.logLevel === "silent") return;
|
|
242
305
|
hinted = true;
|
|
243
|
-
|
|
244
|
-
|
|
306
|
+
require_text.logBlock([`${(0, node_util.styleText)("dim", "Project")} ${node_path.default.basename(node_process.default.cwd())} ${(0, node_util.styleText)("dim", PERMISSIONS.filter(({ key }) => permissions[key]).map(({ label }) => label).join(" · ") || "no permissions")}`, (0, node_util.styleText)("dim", listens ? "Press b to keep running in the background, Ctrl+C to disconnect" : "Press Ctrl+C to disconnect")]);
|
|
307
|
+
require_text.logTip();
|
|
245
308
|
});
|
|
246
309
|
hooks.hook("studio:reconnecting", () => context.onState?.("reconnecting"));
|
|
247
310
|
for (;;) try {
|
|
@@ -252,7 +315,7 @@ async function connect(options, context = {}) {
|
|
|
252
315
|
version: options.version,
|
|
253
316
|
root: node_process.default.cwd(),
|
|
254
317
|
permissions,
|
|
255
|
-
|
|
318
|
+
loadConfigs: async () => (await loadConfigs(options)).configs,
|
|
256
319
|
hooks,
|
|
257
320
|
signal
|
|
258
321
|
});
|
|
@@ -261,8 +324,10 @@ async function connect(options, context = {}) {
|
|
|
261
324
|
if (!(error instanceof _kubb_studio.InvalidAgentTokenError)) throw error;
|
|
262
325
|
await context.onState?.("authentication required");
|
|
263
326
|
await require_credentials.clearCredentials();
|
|
264
|
-
if (pairedAgain) throw
|
|
265
|
-
if (context.onState || require_Telemetry.isCIEnvironment() || !
|
|
327
|
+
if (pairedAgain) throw new Error(`${error.message} Studio rejected the newly approved token too. Run \`kubb studio login\` and try again.`);
|
|
328
|
+
if (context.onState || require_Telemetry.isCIEnvironment() || !require_text.canUseTTY()) throw new Error(`${error.message} Run \`kubb studio login\` to pair again.`);
|
|
329
|
+
unwatch?.();
|
|
330
|
+
unwatch = void 0;
|
|
266
331
|
console.log((0, node_util.styleText)("yellow", `${error.message} Pairing again...`));
|
|
267
332
|
credentials = await login(options, {
|
|
268
333
|
signal,
|
|
@@ -271,15 +336,50 @@ async function connect(options, context = {}) {
|
|
|
271
336
|
pairedAgain = true;
|
|
272
337
|
permissions = await resolvePermissions(options, credentials, configPath);
|
|
273
338
|
}
|
|
274
|
-
|
|
339
|
+
await hooks.callHook("kubb:lifecycle:end");
|
|
340
|
+
unwatch?.();
|
|
341
|
+
if (background) {
|
|
342
|
+
const { startWorker } = await Promise.resolve().then(() => require("./background-BW-e9FCX.cjs"));
|
|
343
|
+
await startWorker(options);
|
|
344
|
+
if (options.logLevel !== "silent") require_text.logOutro("Running in the background · kubb studio stop");
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
if (!context.onState && signal.aborted && options.logLevel !== "silent") require_text.logOutro("Disconnected");
|
|
275
348
|
} catch (error) {
|
|
276
349
|
if (!(error instanceof _kubb_studio.PairingCanceledError)) throw error;
|
|
277
350
|
} finally {
|
|
351
|
+
unwatch?.();
|
|
278
352
|
events.off("SIGINT", stop);
|
|
279
353
|
events.off("SIGTERM", stop);
|
|
280
354
|
}
|
|
281
355
|
}
|
|
282
356
|
/**
|
|
357
|
+
* Listens for single keys on a TTY stdin. Raw mode turns Ctrl+C into a key instead of SIGINT, so it
|
|
358
|
+
* is handled here too. Returns the function that restores the terminal, safe to call twice.
|
|
359
|
+
*/
|
|
360
|
+
function watchKeys({ onBackground, onStop }) {
|
|
361
|
+
const stdin = node_process.default.stdin;
|
|
362
|
+
const onData = (data) => {
|
|
363
|
+
const key = data.toString();
|
|
364
|
+
if (key === "b" || key === "B") onBackground();
|
|
365
|
+
if (key === "") onStop();
|
|
366
|
+
};
|
|
367
|
+
const cancelAlias = _clack_prompts.settings.aliases.get("");
|
|
368
|
+
_clack_prompts.settings.aliases.delete("");
|
|
369
|
+
stdin.setRawMode(true);
|
|
370
|
+
stdin.on("data", onData);
|
|
371
|
+
stdin.resume();
|
|
372
|
+
let restored = false;
|
|
373
|
+
return () => {
|
|
374
|
+
if (restored) return;
|
|
375
|
+
restored = true;
|
|
376
|
+
if (cancelAlias) _clack_prompts.settings.aliases.set("", cancelAlias);
|
|
377
|
+
stdin.off("data", onData);
|
|
378
|
+
stdin.setRawMode(false);
|
|
379
|
+
stdin.pause();
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
283
383
|
* Runs a Studio command from its parsed flags: builds the {@link StudioOptions}, prints the intro,
|
|
284
384
|
* and reports the run to telemetry. A failure is printed and sets the exit code instead of throwing.
|
|
285
385
|
*/
|
|
@@ -288,13 +388,7 @@ async function runStudio(values, action, { block = false, json = false } = {}) {
|
|
|
288
388
|
version: require_Telemetry.version,
|
|
289
389
|
configPath: values.config,
|
|
290
390
|
studioUrl: values.url ?? _kubb_studio.defaultStudioUrl,
|
|
291
|
-
permission:
|
|
292
|
-
allowRead: values.allowRead ?? false,
|
|
293
|
-
allowReadAst: values.allowReadAst ?? false,
|
|
294
|
-
allowWrite: values.allowWrite ?? false,
|
|
295
|
-
allowConfigEdit: values.allowConfigEdit ?? false,
|
|
296
|
-
allowExec: values.allowExec ?? false
|
|
297
|
-
},
|
|
391
|
+
permission: Object.fromEntries(Object.values(_kubb_studio_protocol.AgentPermission).map((key) => [key, values[key] ?? false])),
|
|
298
392
|
autoOpen: values.open ?? true,
|
|
299
393
|
logLevel: values.logLevel
|
|
300
394
|
};
|
|
@@ -303,7 +397,7 @@ async function runStudio(values, action, { block = false, json = false } = {}) {
|
|
|
303
397
|
hrStart: node_process.default.hrtime()
|
|
304
398
|
});
|
|
305
399
|
try {
|
|
306
|
-
if (options.logLevel !== "silent" && !json)
|
|
400
|
+
if (options.logLevel !== "silent" && !json) require_text.logIntro({
|
|
307
401
|
warning: (0, node_util.styleText)("yellow", "This feature is still under development, use with caution"),
|
|
308
402
|
block
|
|
309
403
|
});
|
|
@@ -311,7 +405,7 @@ async function runStudio(values, action, { block = false, json = false } = {}) {
|
|
|
311
405
|
await report({ status: "success" });
|
|
312
406
|
} catch (error) {
|
|
313
407
|
await report({ status: "failed" });
|
|
314
|
-
console.error(
|
|
408
|
+
console.error(require_errors.toError(error).message);
|
|
315
409
|
node_process.default.exitCode = 1;
|
|
316
410
|
}
|
|
317
411
|
}
|
|
@@ -323,4 +417,4 @@ exports.login = login;
|
|
|
323
417
|
exports.prepareConnection = prepareConnection;
|
|
324
418
|
exports.runStudio = runStudio;
|
|
325
419
|
|
|
326
|
-
//# sourceMappingURL=run-
|
|
420
|
+
//# sourceMappingURL=run-BszyZwY3.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-BszyZwY3.cjs","names":["process","isCIEnvironment","x","isCIEnvironment","process","createSpinner","pairAgent","path","process","hostname","getMachineId","styleText","isRichOutput","writeCredentials","getCredentialsPath","PairingCanceledError","AgentPermission","toPermissionFlag","KUBB_CONFIG_FILENAME","isCIEnvironment","canUseTTY","prompts","getConfigs","Diagnostics","readCredentials","Hookable","logLevelMap","cliReporter","plainWriter","connectAgent","InvalidAgentTokenError","clearCredentials","defaultStudioUrl","trackRun","toError"],"sources":["../../../internals/utils/src/copyToClipboard.ts","../../../internals/utils/src/openInBrowser.ts","../src/runners/studio/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { x } from 'tinyexec'\nimport { isCIEnvironment } from './isCIEnvironment.ts'\n\nconst COMMANDS: Partial<Record<NodeJS.Platform, [string, ...Array<string>]>> = {\n darwin: ['pbcopy'],\n win32: ['clip.exe'],\n linux: ['xclip', '-selection', 'clipboard'],\n}\n\n/**\n * Copies text to the system clipboard with the platform's own tool. Resolves `false` in CI, on a\n * platform without a known tool, or when the tool is missing or fails.\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n // Wayland sessions have no X selection for xclip to serve, so they use `wl-copy`.\n const command = process.platform === 'linux' && process.env.WAYLAND_DISPLAY ? (['wl-copy'] as const) : COMMANDS[process.platform]\n if (!command || isCIEnvironment()) return false\n\n const [name, ...args] = command\n // stdout and stderr are ignored: xclip and wl-copy stay alive to serve the selection and would hold open pipes until the timeout.\n const run = x(name, args, { timeout: 2_000, nodeOptions: { stdio: ['pipe', 'ignore', 'ignore'] } })\n // A missing tool closes stdin before the write lands; the rejection below reports it.\n run.process?.stdin?.once('error', () => {})\n run.process?.stdin?.end(text)\n\n return run.then(\n ({ exitCode }) => exitCode === 0,\n () => false,\n )\n}\n","import process from 'node:process'\nimport { x } from 'tinyexec'\nimport { isCIEnvironment } from './isCIEnvironment.ts'\n\nconst ignore = () => {}\n\n/**\n * Opens a URL or local file in the default browser, unless running in CI.\n */\nexport function openInBrowser(target: string): void {\n if (isCIEnvironment()) return\n\n if (process.platform === 'win32') {\n x('cmd', ['/c', 'start', '', target]).then(ignore, ignore)\n return\n }\n x(process.platform === 'darwin' ? 'open' : 'xdg-open', [target]).then(ignore, ignore)\n}\n","import { hostname } from 'node:os'\nimport { toPermissionFlag } from '../../ui/text.ts'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport * as prompts from '@clack/prompts'\nimport { KUBB_CONFIG_FILENAME } from '@internals/shared'\nimport { copyToClipboard, isCIEnvironment, openInBrowser, toError } from '@internals/utils'\nimport type { CLIOptions, Config } from '@kubb/core'\nimport { cliReporter, Diagnostics, Hookable, type KubbHooks, logLevel as logLevelMap } from '@kubb/core'\nimport { connectAgent, defaultStudioUrl, InvalidAgentTokenError, pairAgent, PairingCanceledError } from '@kubb/studio'\nimport { AgentPermission } from '@kubb/studio/protocol'\nimport { trackRun } from '../../Telemetry.ts'\nimport { plainWriter } from '../../loggers/plainWriter.ts'\nimport setupReporters from '../../loggers/reporters.ts'\nimport { logIntro, logOutro, logTip } from '../../ui/intro.ts'\nimport { logBlock, logStep } from '../../ui/log.ts'\nimport { createSpinner } from '../../ui/spinner.ts'\nimport { canUseTTY, isRichOutput } from '../../utils/env.ts'\nimport { getConfigs } from '../../config.ts'\nimport { clearCredentials, type Credentials, getCredentialsPath, getMachineId, readCredentials, writeCredentials } from './credentials.ts'\nimport { version } from '../../../package.json'\n\nexport type StudioOptions = {\n /**\n * Current `@kubb/cli` version, reported to Studio and used for the telemetry payload.\n */\n version: string\n configPath?: string\n /**\n * Base URL of the Studio instance, for a self-hosted deployment. Resolved before it reaches here,\n * since stored credentials are bound to it.\n */\n studioUrl: string\n /**\n * What Studio may do in this project. Each flag grants outright; the rest are asked once per\n * project through {@link resolvePermissions}.\n */\n permission: Record<AgentPermission, boolean>\n /**\n * Whether to open the approval page in a browser during pairing.\n */\n autoOpen: boolean\n logLevel?: CLIOptions['logLevel']\n}\n\nexport type SnapshotOptions = Pick<StudioOptions, 'configPath' | 'studioUrl' | 'logLevel'> & {\n /**\n * Organization CI API key. Falls back to `KUBB_TOKEN`.\n */\n token?: string\n /**\n * Stable identity for the CI agent. Falls back to CI auto-detection.\n */\n id?: string\n /** Identity of another CI agent to also compare with. Falls back to CI auto-detection. */\n baseId?: string\n /**\n * Package name for the generated tarball. Falls back to the nearest package.json.\n */\n name?: string\n /**\n * Package version for the generated tarball. Falls back to the nearest package.json.\n */\n packageVersion?: string\n /**\n * Print the result as one JSON object instead of a summary.\n */\n json?: boolean\n}\n\n/** The flags a `kubb studio` subcommand parsed; each one is optional since a subcommand declares only the flags it uses. */\nexport type StudioValues = {\n config?: string\n url?: string\n allowRead?: boolean\n allowReadAst?: boolean\n allowWrite?: boolean\n allowConfigEdit?: boolean\n allowExec?: boolean\n open?: boolean\n logLevel?: CLIOptions['logLevel']\n}\n\ntype LoginOptions = {\n /**\n * Aborting this cancels an in-flight pairing request or poll and rejects with\n * {@link PairingCanceledError}. Wired to `kubb studio`'s shutdown signal, so Ctrl+C during\n * pairing cancels it instead of leaving the poll running.\n */\n signal?: AbortSignal\n /**\n * Credentials from before this login. When the fresh pairing resolves to the same agent on the\n * same Studio, its saved project permissions carry forward instead of being asked again.\n * Left out for an explicitly requested `kubb studio login`, which always starts clean.\n */\n previousCredentials?: Credentials | null\n}\n\n/**\n * Pairs this machine with Studio and stores the resulting token.\n *\n * The CLI holds a code and the browser approves it, rather than the user copying a token out of\n * the UI. The token comes back over the CLI's own HTTPS POST, so it never lands in a URL, a\n * server log, or a `Referer` header.\n */\nexport async function login({ studioUrl, autoOpen }: StudioOptions, { signal, previousCredentials }: LoginOptions = {}): Promise<Credentials> {\n const spinner = createSpinner()\n // A retry notice stays on screen a while before the countdown takes the line back.\n let retryUntil = 0\n // The spinner only starts once a code is shown.\n let waiting = false\n let countdown: NodeJS.Timeout | undefined\n\n try {\n const { token, agent } = await pairAgent({\n studioUrl,\n type: 'cli',\n name: path.basename(process.cwd()),\n hostname: hostname(),\n machineId: await getMachineId(),\n signal,\n onCode: (session) => {\n logStep(\n [\n 'Pair this machine',\n `${styleText('dim', 'Open')} ${styleText('cyan', session.verification_uri)}`,\n `${styleText('dim', 'Code')} ${styleText('bold', session.user_code)}`,\n ].join('\\n'),\n )\n\n if (autoOpen) {\n openInBrowser(session.verification_uri_complete)\n }\n\n // Same fallback as the poll in `@kubb/studio`, so the countdown ends when polling does.\n const deadline = Date.now() + (session.expires_in > 0 ? session.expires_in : 600) * 1000\n let copied = false\n const waitingText = () =>\n `Waiting for approval ${styleText('dim', `expires in ${formatCountdown(deadline - Date.now())}${copied ? ' · code copied' : ''} · ctrl+c to cancel`)}`\n clearInterval(countdown)\n spinner.start(waitingText())\n waiting = true\n // Plain output prints every message, so only an animated spinner ticks.\n if (isRichOutput()) countdown = setInterval(() => Date.now() > retryUntil && spinner.message(waitingText()), 1000)\n // Not awaited: the code shows at once, and the spinner picks up the copy when it lands.\n void copyToClipboard(session.user_code).then((done) => {\n copied = done\n })\n },\n onRetry: (error) => {\n retryUntil = Date.now() + 5000\n spinner.message(`Could not reach Kubb Studio, retrying: ${error.message}`)\n },\n })\n clearInterval(countdown)\n spinner.stop(`Paired as ${agent.name}${agent.organizationSlug ? ` · org ${agent.organizationSlug}` : ''}`)\n\n const keepsIdentity = previousCredentials?.studioUrl === studioUrl && previousCredentials.agentId === agent.id\n const credentials: Credentials = {\n studioUrl,\n token,\n agentId: agent.id,\n agentSlug: agent.slug,\n ...(agent.organizationSlug ? { organizationSlug: agent.organizationSlug } : {}),\n ...(keepsIdentity && previousCredentials?.projects ? { projects: previousCredentials.projects } : {}),\n }\n await writeCredentials(credentials)\n\n console.log(`Credentials stored in ${getCredentialsPath()}`)\n\n return credentials\n } catch (error) {\n clearInterval(countdown)\n if (waiting) {\n spinner.stop(error instanceof PairingCanceledError ? 'Pairing canceled' : 'Pairing failed')\n }\n throw error\n }\n}\n\n/** Time left on a pairing code as `m:ss`, never below `0:00`. */\nexport function formatCountdown(ms: number): string {\n const seconds = Math.max(0, Math.ceil(ms / 1000))\n\n return `${Math.floor(seconds / 60)}:${String(seconds % 60).padStart(2, '0')}`\n}\n\n/**\n * What each permission is asked as, in the order the list shows them.\n */\nconst PERMISSIONS: ReadonlyArray<{\n key: AgentPermission\n /**\n * Short label for status output and the connect summary.\n */\n label: string\n title: (configPath: string) => string\n hint: string\n}> = [\n { key: AgentPermission.READ, label: 'read source', title: () => 'Read generated files', hint: 'show code in the browser' },\n { key: AgentPermission.READ_AST, label: 'read spec', title: () => 'Read the parsed spec', hint: 'browse schemas and operations' },\n { key: AgentPermission.WRITE, label: 'write files', title: () => 'Write files to disk', hint: 'generate from the browser' },\n { key: AgentPermission.CONFIG_EDIT, label: 'edit config', title: (configPath) => `Change ${configPath}`, hint: 'edit plugin options' },\n { key: AgentPermission.EXEC, label: 'run tools', title: () => 'Run the formatter, linter, and postGenerate', hint: 'after each generation' },\n]\n\n/**\n * Two permissions per row, each marked granted or not, with the flags that grant the missing ones\n * after the last row. For `kubb studio status`.\n */\nexport function formatPermissionRows(granted: Partial<Record<AgentPermission, boolean>>): Array<string> {\n const width = Math.max(...PERMISSIONS.map(({ label }) => label.length))\n const cells = PERMISSIONS.map(({ key, label }) => `${granted[key] ? styleText('green', '✓') : styleText('red', '✖')} ${label.padEnd(width)}`)\n const rows = Array.from({ length: Math.ceil(cells.length / 2) }, (_, index) => cells.slice(index * 2, index * 2 + 2).join(' '))\n const flags = PERMISSIONS.filter(({ key }) => !granted[key])\n .map(({ key }) => toPermissionFlag(key))\n .join(' ')\n\n return flags ? [...rows.slice(0, -1), `${rows.at(-1)} ${styleText('dim', flags)}`] : rows\n}\n\n/**\n * Resolves Studio permissions for the current project.\n * Flags win, saved answers are reused, and the rest are asked in one list whose answers are stored\n * in `~/.kubb/credentials.json`.\n */\nexport async function resolvePermissions(\n options: StudioOptions,\n credentials: Credentials,\n configPath: string = KUBB_CONFIG_FILENAME,\n): Promise<Record<AgentPermission, boolean>> {\n const project = process.cwd()\n const remembered = credentials.projects?.[project]\n const granted = Object.fromEntries(PERMISSIONS.map(({ key }) => [key, options.permission[key] || remembered?.[key] === true])) as Record<\n AgentPermission,\n boolean\n >\n const pending = PERMISSIONS.filter(({ key }) => !options.permission[key] && typeof remembered?.[key] !== 'boolean')\n\n if (!pending.length || isCIEnvironment() || !canUseTTY()) return granted\n\n prompts.updateSettings({ withGuide: true })\n const selected = await prompts.multiselect({\n message: 'What may Kubb Studio do in this project?',\n options: pending.map(({ key, title, hint }) => ({ value: key, label: title(configPath), hint })),\n required: false,\n })\n // A canceled list grants nothing and saves nothing, so the next run asks again.\n if (prompts.isCancel(selected)) return granted\n\n const answers = Object.fromEntries(pending.map(({ key }) => [key, selected.includes(key)]))\n await writeCredentials({\n ...credentials,\n projects: { ...credentials.projects, [project]: { ...remembered, ...answers } },\n })\n\n return { ...granted, ...answers }\n}\n\n/**\n * Loads the project's Kubb config the same way `kubb generate` does, one entry per `defineConfig(...)` entry.\n */\nexport async function loadConfigs(options: Pick<StudioOptions, 'configPath' | 'logLevel'>): Promise<{ configPath: string; configs: Array<Config> }> {\n const { configPath, configs } = await getConfigs({ configPath: options.configPath, logLevel: options.logLevel })\n\n if (!configs.length) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'Config not defined, create a kubb.config.ts or pass it with --config',\n })\n }\n\n // `getConfigs` resolves this to an absolute path. Relativized here, once, so the permission\n // prompt and the path Studio receives over the wire both show the project-relative form instead\n // of leaking the local filesystem layout.\n return { configPath: path.relative(process.cwd(), configPath) || configPath, configs }\n}\n\nexport type PreparedConnection = {\n configPath: string\n credentials: Credentials\n permissions: StudioOptions['permission']\n}\n\n/** Validates the project and resolves pairing and permissions before starting its worker. */\nexport async function prepareConnection(options: StudioOptions, signal?: AbortSignal): Promise<PreparedConnection> {\n const { configPath } = await loadConfigs(options)\n const stored = await readCredentials()\n const credentials = await (async () => {\n if (stored?.studioUrl === options.studioUrl) return stored\n if (isCIEnvironment()) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `Not paired with ${options.studioUrl}. In CI, run \\`kubb studio snapshot\\` instead, or run \\`kubb studio login\\` on a machine with a browser.`,\n })\n }\n return login(options, { signal })\n })()\n const permissions = await resolvePermissions(options, credentials, configPath)\n return { configPath, credentials, permissions }\n}\n\nexport type WorkerState = 'starting' | 'connected' | 'reconnecting' | 'authentication required' | 'stopped'\n\n/** Runs the same project connection in the foreground or in a background worker. */\nexport async function connect(\n options: StudioOptions,\n context: {\n prepared?: PreparedConnection\n signal?: AbortSignal\n onState?: (state: WorkerState) => void | Promise<void>\n } = {},\n): Promise<void> {\n const shutdown = new AbortController()\n const signal = context.signal ?? shutdown.signal\n const stop = () => shutdown.abort()\n const events = process as unknown as NodeJS.EventEmitter\n if (!context.signal) {\n events.once('SIGINT', stop)\n events.once('SIGTERM', stop)\n }\n let unwatch: (() => void) | undefined\n try {\n if (!context.prepared) {\n const { getWorkerStatus } = await import('./background.ts')\n const worker = await getWorkerStatus()\n if (worker.running)\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'This project is running in the background. Run `kubb studio stop` first.',\n })\n }\n const prepared = context.prepared ?? (await prepareConnection(options, signal))\n let { credentials, permissions } = prepared\n const { configPath } = prepared\n let hinted = false\n // Set by a fresh pairing until it connects, so a token rejected right after approval fails the run instead of looping.\n let pairedAgain = false\n\n // The background worker writes to a log file, so it gets the plain logger rather than the\n // animated one. The logger also covers the `studio:*` events and each generation run.\n const hooks = new Hookable<KubbHooks>()\n setupReporters(hooks, {\n logLevel: logLevelMap[options.logLevel ?? 'info'],\n reporters: [cliReporter],\n ...(context.onState ? { writer: plainWriter } : {}),\n })\n // `b` hands the session to the background worker; only a foreground run in a terminal listens.\n const listens = !context.onState && process.stdin.isTTY === true && canUseTTY()\n let background = false\n hooks.hook('studio:connected', async () => {\n pairedAgain = false\n await context.onState?.('connected')\n if (listens && !unwatch) {\n unwatch = watchKeys({\n onBackground: () => {\n background = true\n stop()\n },\n onStop: stop,\n })\n }\n if (hinted || context.onState || options.logLevel === 'silent') return\n hinted = true\n logBlock([\n `${styleText('dim', 'Project')} ${path.basename(process.cwd())} ${styleText(\n 'dim',\n PERMISSIONS.filter(({ key }) => permissions[key])\n .map(({ label }) => label)\n .join(' · ') || 'no permissions',\n )}`,\n styleText('dim', listens ? 'Press b to keep running in the background, Ctrl+C to disconnect' : 'Press Ctrl+C to disconnect'),\n ])\n logTip()\n })\n hooks.hook('studio:reconnecting', () => context.onState?.('reconnecting'))\n\n for (;;) {\n try {\n await connectAgent({\n token: credentials.token,\n studioUrl: options.studioUrl,\n configPath,\n version: options.version,\n root: process.cwd(),\n permissions,\n loadConfigs: async () => (await loadConfigs(options)).configs,\n hooks,\n signal,\n })\n break\n } catch (error) {\n if (!(error instanceof InvalidAgentTokenError)) throw error\n await context.onState?.('authentication required')\n await clearCredentials()\n if (pairedAgain) throw new Error(`${error.message} Studio rejected the newly approved token too. Run \\`kubb studio login\\` and try again.`)\n if (context.onState || isCIEnvironment() || !canUseTTY()) throw new Error(`${error.message} Run \\`kubb studio login\\` to pair again.`)\n\n // The pairing prompts need stdin back.\n unwatch?.()\n unwatch = undefined\n console.log(styleText('yellow', `${error.message} Pairing again...`))\n credentials = await login(options, { signal, previousCredentials: credentials })\n pairedAgain = true\n permissions = await resolvePermissions(options, credentials, configPath)\n }\n }\n // Stops the \"Ready for jobs\" spinner, which would otherwise keep drawing under the closing line.\n await hooks.callHook('kubb:lifecycle:end')\n unwatch?.()\n if (background) {\n const { startWorker } = await import('./background.ts')\n await startWorker(options)\n if (options.logLevel !== 'silent') logOutro('Running in the background · kubb studio stop')\n return\n }\n if (!context.onState && signal.aborted && options.logLevel !== 'silent') logOutro('Disconnected')\n } catch (error) {\n if (!(error instanceof PairingCanceledError)) throw error\n } finally {\n unwatch?.()\n events.off('SIGINT', stop)\n events.off('SIGTERM', stop)\n }\n}\n\n/**\n * Listens for single keys on a TTY stdin. Raw mode turns Ctrl+C into a key instead of SIGINT, so it\n * is handled here too. Returns the function that restores the terminal, safe to call twice.\n */\nexport function watchKeys({ onBackground, onStop }: { onBackground: () => void; onStop: () => void }): () => void {\n const stdin = process.stdin\n const onData = (data: Buffer) => {\n const key = data.toString()\n if (key === 'b' || key === 'B') onBackground()\n if (key === '\\u0003') onStop()\n }\n // A clack spinner reads stdin too and exits the process on Ctrl+C, before the session can close\n // its socket, so its Ctrl+C alias is lifted while these keys are read.\n const cancelAlias = prompts.settings.aliases.get('\\u0003')\n prompts.settings.aliases.delete('\\u0003')\n stdin.setRawMode(true)\n stdin.on('data', onData)\n stdin.resume()\n let restored = false\n\n return () => {\n if (restored) return\n restored = true\n if (cancelAlias) prompts.settings.aliases.set('\\u0003', cancelAlias)\n stdin.off('data', onData)\n stdin.setRawMode(false)\n stdin.pause()\n }\n}\n\n/**\n * Runs a Studio command from its parsed flags: builds the {@link StudioOptions}, prints the intro,\n * and reports the run to telemetry. A failure is printed and sets the exit code instead of throwing.\n */\nexport async function runStudio(\n values: StudioValues,\n action: (options: StudioOptions) => Promise<unknown>,\n { block = false, json = false }: { block?: boolean; json?: boolean } = {},\n): Promise<void> {\n const options: StudioOptions = {\n version,\n configPath: values.config,\n studioUrl: values.url ?? defaultStudioUrl,\n permission: Object.fromEntries(Object.values(AgentPermission).map((key) => [key, values[key] ?? false])) as Record<AgentPermission, boolean>,\n autoOpen: values.open ?? true,\n logLevel: values.logLevel,\n }\n const report = trackRun({ command: 'studio', hrStart: process.hrtime() })\n\n try {\n if (options.logLevel !== 'silent' && !json) {\n logIntro({\n warning: styleText('yellow', 'This feature is still under development, use with caution'),\n block,\n })\n }\n\n await action(options)\n\n await report({ status: 'success' })\n } catch (error) {\n await report({ status: 'failed' })\n console.error(toError(error).message)\n process.exitCode = 1\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const require_rolldown_runtime = require("./rolldown-runtime-CPE0t6oh.cjs");
|
|
2
|
-
const
|
|
2
|
+
const require_errors = require("./errors-Cl69p_vI.cjs");
|
|
3
|
+
const require_Telemetry = require("./Telemetry-Be3hIy6_.cjs");
|
|
3
4
|
let node_util = require("node:util");
|
|
4
5
|
let node_process = require("node:process");
|
|
5
6
|
node_process = require_rolldown_runtime.__toESM(node_process, 1);
|
|
@@ -22,11 +23,11 @@ async function run() {
|
|
|
22
23
|
}), { once: true });
|
|
23
24
|
} catch (error) {
|
|
24
25
|
await report({ status: "failed" });
|
|
25
|
-
console.error(
|
|
26
|
+
console.error(require_errors.toError(error).message);
|
|
26
27
|
node_process.default.exitCode = 1;
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
//#endregion
|
|
30
31
|
exports.run = run;
|
|
31
32
|
|
|
32
|
-
//# sourceMappingURL=run-
|
|
33
|
+
//# sourceMappingURL=run-BtVKUjdK.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-
|
|
1
|
+
{"version":3,"file":"run-BtVKUjdK.cjs","names":["trackRun","process","styleText","toError"],"sources":["../src/runners/mcp/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport type * as McpModule from '@kubb/mcp'\nimport { trackRun } from '../../Telemetry.ts'\n\n/**\n * Starts the `@kubb/mcp` server over stdio and reports the outcome to telemetry.\n */\nexport async function run(): Promise<void> {\n const { run: startMcpServer } = (await import('@kubb/mcp')) as typeof McpModule\n\n const report = trackRun({ command: 'mcp', hrStart: process.hrtime() })\n\n try {\n // The MCP stdio transport owns stdout: anything else written there corrupts the JSON-RPC stream.\n console.error(styleText('cyan', '⏳ Starting MCP server...'))\n console.warn(styleText('yellow', 'This feature is still under development, use with caution'))\n const server = startMcpServer()\n // Report once the client introduces itself, so the event names the client (e.g. `claude-code`, `cursor-vscode`).\n server.on('initialize', ({ clientInfo }) => void report({ status: 'success', mcpClient: clientInfo.name }), { once: true })\n } catch (error) {\n await report({ status: 'failed' })\n console.error(toError(error).message)\n process.exitCode = 1\n }\n}\n"],"mappings":";;;;;;;;;;AASA,eAAsB,MAAqB;CACzC,MAAM,EAAE,KAAK,mBAAoB,MAAM,OAAO;CAE9C,MAAM,SAASA,kBAAAA,SAAS;EAAE,SAAS;EAAO,SAASC,aAAAA,QAAQ,OAAO;CAAE,CAAC;CAErE,IAAI;EAEF,QAAQ,OAAA,GAAMC,UAAAA,UAAAA,CAAU,QAAQ,0BAA0B,CAAC;EAC3D,QAAQ,MAAA,GAAKA,UAAAA,UAAAA,CAAU,UAAU,2DAA2D,CAAC;EAG7F,eAAK,CAAC,CAAC,GAAG,eAAe,EAAE,iBAAiB,KAAK,OAAO;GAAE,QAAQ;GAAW,WAAW,WAAW;EAAK,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC;CAC5H,SAAS,OAAO;EACd,MAAM,OAAO,EAAE,QAAQ,SAAS,CAAC;EACjC,QAAQ,MAAMC,eAAAA,QAAQ,KAAK,CAAC,CAAC,OAAO;EACpC,aAAA,QAAA,WAAmB;CACrB;AACF"}
|