@kubb/cli 5.10.1 → 5.10.3

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 (90) hide show
  1. package/dist/{Telemetry-BfdvvZus.cjs → Telemetry-BV4GonCV.cjs} +2 -2
  2. package/dist/Telemetry-BV4GonCV.cjs.map +1 -0
  3. package/dist/Telemetry-CH2kkxWK.cjs +322 -0
  4. package/dist/Telemetry-CH2kkxWK.cjs.map +1 -0
  5. package/dist/{Telemetry-Bf6lUdai.js → Telemetry-Cz9QCzRo.js} +2 -2
  6. package/dist/Telemetry-Cz9QCzRo.js.map +1 -0
  7. package/dist/{background-D5K6ecEo.js → background-DFME5huR.js} +30 -7
  8. package/dist/background-DFME5huR.js.map +1 -0
  9. package/dist/{background-obsD4Gj2.cjs → background-DVZB1n4j.cjs} +25 -6
  10. package/dist/background-DVZB1n4j.cjs.map +1 -0
  11. package/dist/background-WaKtfQWr.cjs +192 -0
  12. package/dist/background-WaKtfQWr.cjs.map +1 -0
  13. package/dist/{background-C8doa9-4.js → background-_A5NwvYH.js} +1 -1
  14. package/dist/{config-CcqzzfB7.cjs → config-DKAqX5sW.cjs} +18 -4
  15. package/dist/config-DKAqX5sW.cjs.map +1 -0
  16. package/dist/{config-IMZ26zcb.js → config-DV_7s1m-.js} +19 -5
  17. package/dist/config-DV_7s1m-.js.map +1 -0
  18. package/dist/config-OL_izsmp.cjs +113 -0
  19. package/dist/config-OL_izsmp.cjs.map +1 -0
  20. package/dist/credentials-xOkTTDWj.cjs +113 -0
  21. package/dist/credentials-xOkTTDWj.cjs.map +1 -0
  22. package/dist/index.cjs +65 -24
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +8 -0
  25. package/dist/index.d.ts +0 -1
  26. package/dist/index.js +65 -24
  27. package/dist/index.js.map +1 -1
  28. package/dist/output-C5g7AtWH.cjs +1008 -0
  29. package/dist/output-C5g7AtWH.cjs.map +1 -0
  30. package/dist/{output-mwVt_Vj9.js → output-D_gc1nrM.js} +99 -44
  31. package/dist/output-D_gc1nrM.js.map +1 -0
  32. package/dist/{output-DLrxGtuN.cjs → output-nieBFDgM.cjs} +104 -43
  33. package/dist/output-nieBFDgM.cjs.map +1 -0
  34. package/dist/{registry-x-_nbYR6.cjs → registry-C8E_G7Xc.cjs} +49 -15
  35. package/dist/registry-C8E_G7Xc.cjs.map +1 -0
  36. package/dist/registry-CIpW2zQc.cjs +157 -0
  37. package/dist/registry-CIpW2zQc.cjs.map +1 -0
  38. package/dist/{registry-ChqX2AFQ.js → registry-De1vVn1d.js} +50 -16
  39. package/dist/registry-De1vVn1d.js.map +1 -0
  40. package/dist/rolldown-runtime-C0BPl7ul.cjs +43 -0
  41. package/dist/run-BbhrOuK6.cjs +40 -0
  42. package/dist/{run-1MJA0P5x.cjs.map → run-BbhrOuK6.cjs.map} +1 -1
  43. package/dist/{run-DHiVlG37.cjs → run-BnLba1gt.cjs} +27 -14
  44. package/dist/run-BnLba1gt.cjs.map +1 -0
  45. package/dist/{run-D4vOhfbJ.js → run-Bp47k1W1.js} +2 -2
  46. package/dist/{run-D4vOhfbJ.js.map → run-Bp47k1W1.js.map} +1 -1
  47. package/dist/run-BpdJ6X75.cjs +32 -0
  48. package/dist/{run-B13e9GQz.cjs.map → run-BpdJ6X75.cjs.map} +1 -1
  49. package/dist/{run-Cm0sJO0h.js → run-CCMlmk-z.js} +1 -1
  50. package/dist/{run-DTz7gAk1.js → run-CPYD1Lp0.js} +27 -14
  51. package/dist/run-CPYD1Lp0.js.map +1 -0
  52. package/dist/run-CSOEGpWZ.cjs +326 -0
  53. package/dist/run-CSOEGpWZ.cjs.map +1 -0
  54. package/dist/{run-B13e9GQz.cjs → run-CvE8ZdKG.cjs} +2 -2
  55. package/dist/run-CvE8ZdKG.cjs.map +1 -0
  56. package/dist/{run-Cu3pmezx.js → run-DaFK-Uy2.js} +2 -2
  57. package/dist/{run-Cu3pmezx.js.map → run-DaFK-Uy2.js.map} +1 -1
  58. package/dist/{run-BAlcXyYw.js → run-Ij84bqza.js} +22 -16
  59. package/dist/run-Ij84bqza.js.map +1 -0
  60. package/dist/{run-1MJA0P5x.cjs → run-MFjzBB_M.cjs} +2 -2
  61. package/dist/run-MFjzBB_M.cjs.map +1 -0
  62. package/dist/run-hgSZImuK.cjs +345 -0
  63. package/dist/run-hgSZImuK.cjs.map +1 -0
  64. package/dist/{run-CUyhuGlK.cjs → run-hyi91b22.cjs} +22 -16
  65. package/dist/run-hyi91b22.cjs.map +1 -0
  66. package/dist/{snapshot-DCG-Jf1A.js → snapshot-B6w3BLum.js} +22 -9
  67. package/dist/snapshot-B6w3BLum.js.map +1 -0
  68. package/dist/snapshot-DP9Pcnsg.cjs +264 -0
  69. package/dist/snapshot-DP9Pcnsg.cjs.map +1 -0
  70. package/dist/{snapshot-C5cthCuU.cjs → snapshot-D_F4XkYQ.cjs} +22 -9
  71. package/dist/snapshot-D_F4XkYQ.cjs.map +1 -0
  72. package/dist/studioWorker.js +2 -2
  73. package/package.json +15 -10
  74. package/dist/Telemetry-Bf6lUdai.js.map +0 -1
  75. package/dist/Telemetry-BfdvvZus.cjs.map +0 -1
  76. package/dist/background-D5K6ecEo.js.map +0 -1
  77. package/dist/background-obsD4Gj2.cjs.map +0 -1
  78. package/dist/config-CcqzzfB7.cjs.map +0 -1
  79. package/dist/config-IMZ26zcb.js.map +0 -1
  80. package/dist/output-DLrxGtuN.cjs.map +0 -1
  81. package/dist/output-mwVt_Vj9.js.map +0 -1
  82. package/dist/registry-ChqX2AFQ.js.map +0 -1
  83. package/dist/registry-x-_nbYR6.cjs.map +0 -1
  84. package/dist/run-BAlcXyYw.js.map +0 -1
  85. package/dist/run-CUyhuGlK.cjs.map +0 -1
  86. package/dist/run-DHiVlG37.cjs.map +0 -1
  87. package/dist/run-DTz7gAk1.js.map +0 -1
  88. package/dist/snapshot-C5cthCuU.cjs.map +0 -1
  89. package/dist/snapshot-DCG-Jf1A.js.map +0 -1
  90. package/dist/studioWorker.d.ts +0 -1
@@ -1 +1 @@
1
- export { t as connect, n as formatPermissionRows, i as login, s as runStudio } from "./run-DTz7gAk1.js";
1
+ export { t as connect, n as formatPermissionRows, i as login, s as runStudio } from "./run-CPYD1Lp0.js";
@@ -1,16 +1,17 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { l as toError, n as trackRun, r as version, s as isCIEnvironment } from "./Telemetry-Bf6lUdai.js";
3
- import { b as KUBB_CONFIG_FILENAME, g as canUseTTY, o as logIntro, p as plainLogger, r as logBlock, s as logOutro, t as createSpinner, u as logTip } from "./output-mwVt_Vj9.js";
2
+ import { l as toError, n as trackRun, r as version, s as isCIEnvironment } from "./Telemetry-Cz9QCzRo.js";
3
+ import { g as canUseTTY, o as logIntro, p as plainLogger, r as logBlock, s as logOutro, t as createSpinner, u as logTip, x as KUBB_CONFIG_FILENAME } from "./output-D_gc1nrM.js";
4
4
  import { a as readCredentials, n as getCredentialsPath, o as writeCredentials, r as getMachineId, t as clearCredentials } from "./credentials-CZK6zPLv.js";
5
- import { r as setupReporters, t as getConfigs } from "./config-IMZ26zcb.js";
5
+ import { r as setupReporters, t as getConfigs } from "./config-DV_7s1m-.js";
6
6
  import { styleText } from "node:util";
7
7
  import { hostname } from "node:os";
8
8
  import process from "node:process";
9
9
  import { x } from "tinyexec";
10
10
  import path from "node:path";
11
+ import { Diagnostics, Hookable, cliReporter, logLevel } from "@kubb/core";
11
12
  import * as prompts from "@clack/prompts";
12
- import { Hookable, cliReporter, logLevel } from "@kubb/core";
13
13
  import { InvalidAgentTokenError, PairingCanceledError, connectAgent, defaultStudioUrl, pairAgent } from "@kubb/studio";
14
+ import { AgentPermission } from "@kubb/studio/protocol";
14
15
  //#region ../../internals/utils/src/openInBrowser.ts
15
16
  const ignore = () => {};
16
17
  /**
@@ -79,27 +80,27 @@ async function login({ studioUrl, autoOpen }, { signal, previousCredentials } =
79
80
  */
80
81
  const PERMISSIONS = [
81
82
  {
82
- key: "allowRead",
83
+ key: AgentPermission.READ,
83
84
  label: "read generated files",
84
85
  question: () => "Let Kubb Studio read the files a generation produced?"
85
86
  },
86
87
  {
87
- key: "allowReadAst",
88
+ key: AgentPermission.READ_AST,
88
89
  label: "read parsed spec",
89
90
  question: () => "Let Kubb Studio read the parsed spec (the Kubb AST)?"
90
91
  },
91
92
  {
92
- key: "allowWrite",
93
+ key: AgentPermission.WRITE,
93
94
  label: "write generated files",
94
95
  question: (project) => `Let Kubb Studio write generated files into ${project}?`
95
96
  },
96
97
  {
97
- key: "allowConfigEdit",
98
+ key: AgentPermission.CONFIG_EDIT,
98
99
  label: "edit kubb.config.ts",
99
100
  question: (_project, configPath) => `Let Kubb Studio change plugin options in ${configPath}?`
100
101
  },
101
102
  {
102
- key: "allowExec",
103
+ key: AgentPermission.EXEC,
103
104
  label: "run formatter, linter, postGenerate",
104
105
  question: () => "Let Kubb Studio run the formatter, the linter, and output.postGenerate?"
105
106
  }
@@ -164,7 +165,11 @@ async function loadConfigs(options) {
164
165
  logLevel: options.logLevel
165
166
  });
166
167
  const [config] = configs;
167
- if (!config) throw new Error("Config not defined, create a kubb.config.ts or pass it with --config");
168
+ if (!config) throw new Diagnostics.Error({
169
+ code: Diagnostics.code.unknown,
170
+ severity: "error",
171
+ message: "Config not defined, create a kubb.config.ts or pass it with --config"
172
+ });
168
173
  return {
169
174
  configPath: path.relative(process.cwd(), configPath) || configPath,
170
175
  config
@@ -184,7 +189,11 @@ async function prepareConnection(options, signal) {
184
189
  const stored = await readCredentials();
185
190
  const credentials = await (async () => {
186
191
  if (stored?.studioUrl === options.studioUrl) return stored;
187
- if (isCIEnvironment()) throw new Error(`Not paired with ${options.studioUrl}. In CI, run \`kubb studio snapshot\` instead, or run \`kubb studio login\` on a machine with a browser.`);
192
+ if (isCIEnvironment()) throw new Diagnostics.Error({
193
+ code: Diagnostics.code.unknown,
194
+ severity: "error",
195
+ message: `Not paired with ${options.studioUrl}. In CI, run \`kubb studio snapshot\` instead, or run \`kubb studio login\` on a machine with a browser.`
196
+ });
188
197
  return login(options, { signal });
189
198
  })();
190
199
  return {
@@ -205,8 +214,12 @@ async function connect(options, context = {}) {
205
214
  }
206
215
  try {
207
216
  if (!context.prepared) {
208
- const { getWorkerStatus } = await import("./background-C8doa9-4.js");
209
- if ((await getWorkerStatus()).running) throw new Error("This project is running in the background. Run `kubb studio stop` first.");
217
+ const { getWorkerStatus } = await import("./background-_A5NwvYH.js");
218
+ if ((await getWorkerStatus()).running) throw new Diagnostics.Error({
219
+ code: Diagnostics.code.unknown,
220
+ severity: "error",
221
+ message: "This project is running in the background. Run `kubb studio stop` first."
222
+ });
210
223
  }
211
224
  const prepared = context.prepared ?? await prepareConnection(options, signal);
212
225
  let { credentials, permissions } = prepared;
@@ -302,4 +315,4 @@ async function runStudio(values, action, { block = false, json = false } = {}) {
302
315
  //#endregion
303
316
  export { prepareConnection as a, login as i, formatPermissionRows as n, resolvePermissions as o, loadConfigs as r, runStudio as s, connect as t };
304
317
 
305
- //# sourceMappingURL=run-DTz7gAk1.js.map
318
+ //# sourceMappingURL=run-CPYD1Lp0.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-CPYD1Lp0.js","names":["logLevelMap"],"sources":["../../../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 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 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 { 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 { plainLogger } from '../../loggers/plainLogger.ts'\nimport setupReporters from '../../loggers/reporters.ts'\nimport { createSpinner, logBlock, logIntro, logOutro, logTip } from '../../loggers/output.ts'\nimport { canUseTTY } 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 // The spinner only starts once a code is shown.\n let waiting = false\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 console.log(`\\nOpen ${styleText('cyan', session.verification_uri)} and approve the code ${styleText('bold', session.user_code)}`)\n\n if (autoOpen) {\n openInBrowser(session.verification_uri_complete)\n }\n\n spinner.start('Waiting for approval')\n waiting = true\n },\n onRetry: (error) => spinner.message(`Could not reach Kubb Studio, retrying: ${error.message}`),\n })\n spinner.stop(`Paired as ${agent.name}`)\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 ...(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 if (waiting) {\n spinner.stop(error instanceof PairingCanceledError ? 'Pairing canceled' : 'Pairing failed')\n }\n throw error\n }\n}\n\n/**\n * What each permission is asked as, in the order the questions appear.\n */\nconst PERMISSIONS: ReadonlyArray<{\n key: AgentPermission\n /**\n * Short label for status output and the connect summary.\n */\n label: string\n question: (project: string, configPath: string) => string\n}> = [\n {\n key: AgentPermission.READ,\n label: 'read generated files',\n question: () => 'Let Kubb Studio read the files a generation produced?',\n },\n { key: AgentPermission.READ_AST, label: 'read parsed spec', question: () => 'Let Kubb Studio read the parsed spec (the Kubb AST)?' },\n { key: AgentPermission.WRITE, label: 'write generated files', question: (project) => `Let Kubb Studio write generated files into ${project}?` },\n {\n key: AgentPermission.CONFIG_EDIT,\n label: 'edit kubb.config.ts',\n question: (_project, configPath) => `Let Kubb Studio change plugin options in ${configPath}?`,\n },\n {\n key: AgentPermission.EXEC,\n label: 'run formatter, linter, postGenerate',\n question: () => 'Let Kubb Studio run the formatter, the linter, and output.postGenerate?',\n },\n]\n\n/**\n * One row per permission, for the connect banner and `kubb studio status`. A list rather than a\n * joined line: four labels this long read as one run-on sentence side by side.\n */\nexport function formatPermissionRows(granted: Record<AgentPermission, boolean>): Array<string> {\n return PERMISSIONS.map(({ key, label }) => `${granted[key] ? styleText('green', '✔') : styleText('red', '✘')} ${label}`)\n}\n\n/**\n * Resolves Studio permissions for the current project.\n * Flags win, saved answers are reused, and new answers are stored 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: Record<AgentPermission, boolean> = { allowRead: false, allowReadAst: false, allowWrite: false, allowConfigEdit: false, allowExec: false }\n const answers: Partial<Record<AgentPermission, boolean>> = {}\n prompts.updateSettings({ withGuide: true })\n\n for (const { key, question } of PERMISSIONS) {\n if (options.permission[key] || typeof remembered?.[key] === 'boolean') {\n granted[key] = options.permission[key] || remembered?.[key] === true\n continue\n }\n\n if (isCIEnvironment() || !canUseTTY()) {\n granted[key] = false\n continue\n }\n\n granted[key] = (await prompts.confirm({ message: question(project, configPath), initialValue: false })) === true\n answers[key] = granted[key]\n }\n if (Object.keys(answers).length) {\n await writeCredentials({\n ...credentials,\n projects: { ...credentials.projects, [project]: { ...remembered, ...answers } },\n })\n }\n\n return granted\n}\n\n/**\n * Loads the project's Kubb config the same way `kubb generate` does.\n * Returns the first config.\n */\nexport async function loadConfigs(options: Pick<StudioOptions, 'configPath' | 'logLevel'>): Promise<{ configPath: string; config: Config }> {\n const { configPath, configs } = await getConfigs({ configPath: options.configPath, logLevel: options.logLevel })\n const [config] = configs\n\n if (!config) {\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, config }\n}\n\n/**\n * Why a rejected token could not be recovered automatically: no browser is available to re-pair\n * with, or the token this run already re-paired for was rejected again.\n */\ntype RejectedTokenReason = 'nonInteractive' | 'reauthExhausted'\n\n/**\n * Explains a rejected token to the operator. Builds the error and nothing else, so each caller\n * decides what happens to the credentials.\n */\nfunction explainRejectedToken(error: InvalidAgentTokenError, reason: RejectedTokenReason): Error {\n if (reason === 'reauthExhausted') {\n return new Error(`${error.message} Studio rejected the newly approved token too. Run \\`kubb studio login\\` and try again.`)\n }\n\n return new Error(`${error.message} Run \\`kubb studio login\\` to pair again.`)\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 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 ? { logger: plainLogger } : {}),\n })\n hooks.hook('studio:connected', async () => {\n pairedAgain = false\n await context.onState?.('connected')\n if (hinted || context.onState || options.logLevel === 'silent') return\n hinted = true\n logBlock(styleText('dim', 'Press Ctrl+C to disconnect'))\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 loadConfig: async () => (await loadConfigs(options)).config,\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 explainRejectedToken(error, 'reauthExhausted')\n if (context.onState || isCIEnvironment() || !canUseTTY()) throw explainRejectedToken(error, 'nonInteractive')\n\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 if (!context.onState && signal.aborted && options.logLevel !== 'silent') logOutro('Disconnected')\n } catch (error) {\n if (!(error instanceof PairingCanceledError)) throw error\n } finally {\n events.off('SIGINT', stop)\n events.off('SIGTERM', stop)\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: {\n allowRead: values.allowRead ?? false,\n allowReadAst: values.allowReadAst ?? false,\n allowWrite: values.allowWrite ?? false,\n allowConfigEdit: values.allowConfigEdit ?? false,\n allowExec: values.allowExec ?? false,\n },\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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"}
@@ -0,0 +1,326 @@
1
+ const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
2
+ const require_Telemetry = require("./Telemetry-CH2kkxWK.cjs");
3
+ const require_output = require("./output-C5g7AtWH.cjs");
4
+ const require_config = require("./config-OL_izsmp.cjs");
5
+ const require_credentials = require("./credentials-xOkTTDWj.cjs");
6
+ let node_util = require("node:util");
7
+ let node_os = require("node:os");
8
+ let node_process = require("node:process");
9
+ node_process = require_rolldown_runtime.__toESM(node_process, 1);
10
+ let tinyexec = require("tinyexec");
11
+ let node_path = require("node:path");
12
+ node_path = require_rolldown_runtime.__toESM(node_path, 1);
13
+ let _kubb_core = require("@kubb/core");
14
+ let _clack_prompts = require("@clack/prompts");
15
+ _clack_prompts = require_rolldown_runtime.__toESM(_clack_prompts, 1);
16
+ let _kubb_studio = require("@kubb/studio");
17
+ let _kubb_studio_protocol = require("@kubb/studio/protocol");
18
+ //#region ../../internals/utils/src/openInBrowser.ts
19
+ const ignore = () => {};
20
+ /**
21
+ * Opens a URL or local file in the default browser, unless running in CI.
22
+ */
23
+ function openInBrowser(target) {
24
+ if (require_Telemetry.isCIEnvironment()) return;
25
+ if (node_process.default.platform === "win32") {
26
+ (0, tinyexec.x)("cmd", [
27
+ "/c",
28
+ "start",
29
+ "",
30
+ target
31
+ ]).then(ignore, ignore);
32
+ return;
33
+ }
34
+ (0, tinyexec.x)(node_process.default.platform === "darwin" ? "open" : "xdg-open", [target]).then(ignore, ignore);
35
+ }
36
+ //#endregion
37
+ //#region src/runners/studio/run.ts
38
+ /**
39
+ * Pairs this machine with Studio and stores the resulting token.
40
+ *
41
+ * The CLI holds a code and the browser approves it, rather than the user copying a token out of
42
+ * the UI. The token comes back over the CLI's own HTTPS POST, so it never lands in a URL, a
43
+ * server log, or a `Referer` header.
44
+ */
45
+ async function login({ studioUrl, autoOpen }, { signal, previousCredentials } = {}) {
46
+ const spinner = require_output.createSpinner();
47
+ let waiting = false;
48
+ try {
49
+ const { token, agent } = await (0, _kubb_studio.pairAgent)({
50
+ studioUrl,
51
+ type: "cli",
52
+ name: node_path.default.basename(node_process.default.cwd()),
53
+ hostname: (0, node_os.hostname)(),
54
+ machineId: await require_credentials.getMachineId(),
55
+ signal,
56
+ onCode: (session) => {
57
+ console.log(`\nOpen ${(0, node_util.styleText)("cyan", session.verification_uri)} and approve the code ${(0, node_util.styleText)("bold", session.user_code)}`);
58
+ if (autoOpen) openInBrowser(session.verification_uri_complete);
59
+ spinner.start("Waiting for approval");
60
+ waiting = true;
61
+ },
62
+ onRetry: (error) => spinner.message(`Could not reach Kubb Studio, retrying: ${error.message}`)
63
+ });
64
+ spinner.stop(`Paired as ${agent.name}`);
65
+ const keepsIdentity = previousCredentials?.studioUrl === studioUrl && previousCredentials.agentId === agent.id;
66
+ const credentials = {
67
+ studioUrl,
68
+ token,
69
+ agentId: agent.id,
70
+ agentSlug: agent.slug,
71
+ ...keepsIdentity && previousCredentials?.projects ? { projects: previousCredentials.projects } : {}
72
+ };
73
+ await require_credentials.writeCredentials(credentials);
74
+ console.log(`Credentials stored in ${require_credentials.getCredentialsPath()}`);
75
+ return credentials;
76
+ } catch (error) {
77
+ if (waiting) spinner.stop(error instanceof _kubb_studio.PairingCanceledError ? "Pairing canceled" : "Pairing failed");
78
+ throw error;
79
+ }
80
+ }
81
+ /**
82
+ * What each permission is asked as, in the order the questions appear.
83
+ */
84
+ const PERMISSIONS = [
85
+ {
86
+ key: _kubb_studio_protocol.AgentPermission.READ,
87
+ label: "read generated files",
88
+ question: () => "Let Kubb Studio read the files a generation produced?"
89
+ },
90
+ {
91
+ key: _kubb_studio_protocol.AgentPermission.READ_AST,
92
+ label: "read parsed spec",
93
+ question: () => "Let Kubb Studio read the parsed spec (the Kubb AST)?"
94
+ },
95
+ {
96
+ key: _kubb_studio_protocol.AgentPermission.WRITE,
97
+ label: "write generated files",
98
+ question: (project) => `Let Kubb Studio write generated files into ${project}?`
99
+ },
100
+ {
101
+ key: _kubb_studio_protocol.AgentPermission.CONFIG_EDIT,
102
+ label: "edit kubb.config.ts",
103
+ question: (_project, configPath) => `Let Kubb Studio change plugin options in ${configPath}?`
104
+ },
105
+ {
106
+ key: _kubb_studio_protocol.AgentPermission.EXEC,
107
+ label: "run formatter, linter, postGenerate",
108
+ question: () => "Let Kubb Studio run the formatter, the linter, and output.postGenerate?"
109
+ }
110
+ ];
111
+ /**
112
+ * One row per permission, for the connect banner and `kubb studio status`. A list rather than a
113
+ * joined line: four labels this long read as one run-on sentence side by side.
114
+ */
115
+ function formatPermissionRows(granted) {
116
+ return PERMISSIONS.map(({ key, label }) => `${granted[key] ? (0, node_util.styleText)("green", "✔") : (0, node_util.styleText)("red", "✘")} ${label}`);
117
+ }
118
+ /**
119
+ * Resolves Studio permissions for the current project.
120
+ * Flags win, saved answers are reused, and new answers are stored in `~/.kubb/credentials.json`.
121
+ */
122
+ async function resolvePermissions(options, credentials, configPath = require_output.KUBB_CONFIG_FILENAME) {
123
+ const project = node_process.default.cwd();
124
+ const remembered = credentials.projects?.[project];
125
+ const granted = {
126
+ allowRead: false,
127
+ allowReadAst: false,
128
+ allowWrite: false,
129
+ allowConfigEdit: false,
130
+ allowExec: false
131
+ };
132
+ const answers = {};
133
+ _clack_prompts.updateSettings({ withGuide: true });
134
+ for (const { key, question } of PERMISSIONS) {
135
+ if (options.permission[key] || typeof remembered?.[key] === "boolean") {
136
+ granted[key] = options.permission[key] || remembered?.[key] === true;
137
+ continue;
138
+ }
139
+ if (require_Telemetry.isCIEnvironment() || !require_output.canUseTTY()) {
140
+ granted[key] = false;
141
+ continue;
142
+ }
143
+ granted[key] = await _clack_prompts.confirm({
144
+ message: question(project, configPath),
145
+ initialValue: false
146
+ }) === true;
147
+ answers[key] = granted[key];
148
+ }
149
+ if (Object.keys(answers).length) await require_credentials.writeCredentials({
150
+ ...credentials,
151
+ projects: {
152
+ ...credentials.projects,
153
+ [project]: {
154
+ ...remembered,
155
+ ...answers
156
+ }
157
+ }
158
+ });
159
+ return granted;
160
+ }
161
+ /**
162
+ * Loads the project's Kubb config the same way `kubb generate` does.
163
+ * Returns the first config.
164
+ */
165
+ async function loadConfigs(options) {
166
+ const { configPath, configs } = await require_config.getConfigs({
167
+ configPath: options.configPath,
168
+ logLevel: options.logLevel
169
+ });
170
+ const [config] = configs;
171
+ if (!config) throw new _kubb_core.Diagnostics.Error({
172
+ code: _kubb_core.Diagnostics.code.unknown,
173
+ severity: "error",
174
+ message: "Config not defined, create a kubb.config.ts or pass it with --config"
175
+ });
176
+ return {
177
+ configPath: node_path.default.relative(node_process.default.cwd(), configPath) || configPath,
178
+ config
179
+ };
180
+ }
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
+ /** Validates the project and resolves pairing and permissions before starting its worker. */
190
+ async function prepareConnection(options, signal) {
191
+ const { configPath } = await loadConfigs(options);
192
+ const stored = await require_credentials.readCredentials();
193
+ const credentials = await (async () => {
194
+ if (stored?.studioUrl === options.studioUrl) return stored;
195
+ if (require_Telemetry.isCIEnvironment()) throw new _kubb_core.Diagnostics.Error({
196
+ code: _kubb_core.Diagnostics.code.unknown,
197
+ severity: "error",
198
+ message: `Not paired with ${options.studioUrl}. In CI, run \`kubb studio snapshot\` instead, or run \`kubb studio login\` on a machine with a browser.`
199
+ });
200
+ return login(options, { signal });
201
+ })();
202
+ return {
203
+ configPath,
204
+ credentials,
205
+ permissions: await resolvePermissions(options, credentials, configPath)
206
+ };
207
+ }
208
+ /** Runs the same project connection in the foreground or in a background worker. */
209
+ async function connect(options, context = {}) {
210
+ const shutdown = new AbortController();
211
+ const signal = context.signal ?? shutdown.signal;
212
+ const stop = () => shutdown.abort();
213
+ const events = node_process.default;
214
+ if (!context.signal) {
215
+ events.once("SIGINT", stop);
216
+ events.once("SIGTERM", stop);
217
+ }
218
+ try {
219
+ if (!context.prepared) {
220
+ const { getWorkerStatus } = await Promise.resolve().then(() => require("./background-WaKtfQWr.cjs"));
221
+ if ((await getWorkerStatus()).running) throw new _kubb_core.Diagnostics.Error({
222
+ code: _kubb_core.Diagnostics.code.unknown,
223
+ severity: "error",
224
+ message: "This project is running in the background. Run `kubb studio stop` first."
225
+ });
226
+ }
227
+ const prepared = context.prepared ?? await prepareConnection(options, signal);
228
+ let { credentials, permissions } = prepared;
229
+ const { configPath } = prepared;
230
+ let hinted = false;
231
+ let pairedAgain = false;
232
+ const hooks = new _kubb_core.Hookable();
233
+ require_config.setupReporters(hooks, {
234
+ logLevel: _kubb_core.logLevel[options.logLevel ?? "info"],
235
+ reporters: [_kubb_core.cliReporter],
236
+ ...context.onState ? { logger: require_output.plainLogger } : {}
237
+ });
238
+ hooks.hook("studio:connected", async () => {
239
+ pairedAgain = false;
240
+ await context.onState?.("connected");
241
+ if (hinted || context.onState || options.logLevel === "silent") return;
242
+ hinted = true;
243
+ require_output.logBlock((0, node_util.styleText)("dim", "Press Ctrl+C to disconnect"));
244
+ require_output.logTip();
245
+ });
246
+ hooks.hook("studio:reconnecting", () => context.onState?.("reconnecting"));
247
+ for (;;) try {
248
+ await (0, _kubb_studio.connectAgent)({
249
+ token: credentials.token,
250
+ studioUrl: options.studioUrl,
251
+ configPath,
252
+ version: options.version,
253
+ root: node_process.default.cwd(),
254
+ permissions,
255
+ loadConfig: async () => (await loadConfigs(options)).config,
256
+ hooks,
257
+ signal
258
+ });
259
+ break;
260
+ } catch (error) {
261
+ if (!(error instanceof _kubb_studio.InvalidAgentTokenError)) throw error;
262
+ await context.onState?.("authentication required");
263
+ await require_credentials.clearCredentials();
264
+ if (pairedAgain) throw explainRejectedToken(error, "reauthExhausted");
265
+ if (context.onState || require_Telemetry.isCIEnvironment() || !require_output.canUseTTY()) throw explainRejectedToken(error, "nonInteractive");
266
+ console.log((0, node_util.styleText)("yellow", `${error.message} Pairing again...`));
267
+ credentials = await login(options, {
268
+ signal,
269
+ previousCredentials: credentials
270
+ });
271
+ pairedAgain = true;
272
+ permissions = await resolvePermissions(options, credentials, configPath);
273
+ }
274
+ if (!context.onState && signal.aborted && options.logLevel !== "silent") require_output.logOutro("Disconnected");
275
+ } catch (error) {
276
+ if (!(error instanceof _kubb_studio.PairingCanceledError)) throw error;
277
+ } finally {
278
+ events.off("SIGINT", stop);
279
+ events.off("SIGTERM", stop);
280
+ }
281
+ }
282
+ /**
283
+ * Runs a Studio command from its parsed flags: builds the {@link StudioOptions}, prints the intro,
284
+ * and reports the run to telemetry. A failure is printed and sets the exit code instead of throwing.
285
+ */
286
+ async function runStudio(values, action, { block = false, json = false } = {}) {
287
+ const options = {
288
+ version: require_Telemetry.version,
289
+ configPath: values.config,
290
+ 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
+ },
298
+ autoOpen: values.open ?? true,
299
+ logLevel: values.logLevel
300
+ };
301
+ const report = require_Telemetry.trackRun({
302
+ command: "studio",
303
+ hrStart: node_process.default.hrtime()
304
+ });
305
+ try {
306
+ if (options.logLevel !== "silent" && !json) require_output.logIntro({
307
+ warning: (0, node_util.styleText)("yellow", "This feature is still under development, use with caution"),
308
+ block
309
+ });
310
+ await action(options);
311
+ await report({ status: "success" });
312
+ } catch (error) {
313
+ await report({ status: "failed" });
314
+ console.error(require_Telemetry.toError(error).message);
315
+ node_process.default.exitCode = 1;
316
+ }
317
+ }
318
+ //#endregion
319
+ exports.connect = connect;
320
+ exports.formatPermissionRows = formatPermissionRows;
321
+ exports.loadConfigs = loadConfigs;
322
+ exports.login = login;
323
+ exports.prepareConnection = prepareConnection;
324
+ exports.runStudio = runStudio;
325
+
326
+ //# sourceMappingURL=run-CSOEGpWZ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-CSOEGpWZ.cjs","names":["isCIEnvironment","process","createSpinner","pairAgent","path","process","hostname","getMachineId","styleText","writeCredentials","getCredentialsPath","PairingCanceledError","AgentPermission","KUBB_CONFIG_FILENAME","isCIEnvironment","canUseTTY","prompts","getConfigs","Diagnostics","readCredentials","Hookable","logLevelMap","cliReporter","plainLogger","connectAgent","InvalidAgentTokenError","clearCredentials","defaultStudioUrl","trackRun","toError"],"sources":["../../../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 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 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 { 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 { plainLogger } from '../../loggers/plainLogger.ts'\nimport setupReporters from '../../loggers/reporters.ts'\nimport { createSpinner, logBlock, logIntro, logOutro, logTip } from '../../loggers/output.ts'\nimport { canUseTTY } 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 // The spinner only starts once a code is shown.\n let waiting = false\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 console.log(`\\nOpen ${styleText('cyan', session.verification_uri)} and approve the code ${styleText('bold', session.user_code)}`)\n\n if (autoOpen) {\n openInBrowser(session.verification_uri_complete)\n }\n\n spinner.start('Waiting for approval')\n waiting = true\n },\n onRetry: (error) => spinner.message(`Could not reach Kubb Studio, retrying: ${error.message}`),\n })\n spinner.stop(`Paired as ${agent.name}`)\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 ...(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 if (waiting) {\n spinner.stop(error instanceof PairingCanceledError ? 'Pairing canceled' : 'Pairing failed')\n }\n throw error\n }\n}\n\n/**\n * What each permission is asked as, in the order the questions appear.\n */\nconst PERMISSIONS: ReadonlyArray<{\n key: AgentPermission\n /**\n * Short label for status output and the connect summary.\n */\n label: string\n question: (project: string, configPath: string) => string\n}> = [\n {\n key: AgentPermission.READ,\n label: 'read generated files',\n question: () => 'Let Kubb Studio read the files a generation produced?',\n },\n { key: AgentPermission.READ_AST, label: 'read parsed spec', question: () => 'Let Kubb Studio read the parsed spec (the Kubb AST)?' },\n { key: AgentPermission.WRITE, label: 'write generated files', question: (project) => `Let Kubb Studio write generated files into ${project}?` },\n {\n key: AgentPermission.CONFIG_EDIT,\n label: 'edit kubb.config.ts',\n question: (_project, configPath) => `Let Kubb Studio change plugin options in ${configPath}?`,\n },\n {\n key: AgentPermission.EXEC,\n label: 'run formatter, linter, postGenerate',\n question: () => 'Let Kubb Studio run the formatter, the linter, and output.postGenerate?',\n },\n]\n\n/**\n * One row per permission, for the connect banner and `kubb studio status`. A list rather than a\n * joined line: four labels this long read as one run-on sentence side by side.\n */\nexport function formatPermissionRows(granted: Record<AgentPermission, boolean>): Array<string> {\n return PERMISSIONS.map(({ key, label }) => `${granted[key] ? styleText('green', '✔') : styleText('red', '✘')} ${label}`)\n}\n\n/**\n * Resolves Studio permissions for the current project.\n * Flags win, saved answers are reused, and new answers are stored 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: Record<AgentPermission, boolean> = { allowRead: false, allowReadAst: false, allowWrite: false, allowConfigEdit: false, allowExec: false }\n const answers: Partial<Record<AgentPermission, boolean>> = {}\n prompts.updateSettings({ withGuide: true })\n\n for (const { key, question } of PERMISSIONS) {\n if (options.permission[key] || typeof remembered?.[key] === 'boolean') {\n granted[key] = options.permission[key] || remembered?.[key] === true\n continue\n }\n\n if (isCIEnvironment() || !canUseTTY()) {\n granted[key] = false\n continue\n }\n\n granted[key] = (await prompts.confirm({ message: question(project, configPath), initialValue: false })) === true\n answers[key] = granted[key]\n }\n if (Object.keys(answers).length) {\n await writeCredentials({\n ...credentials,\n projects: { ...credentials.projects, [project]: { ...remembered, ...answers } },\n })\n }\n\n return granted\n}\n\n/**\n * Loads the project's Kubb config the same way `kubb generate` does.\n * Returns the first config.\n */\nexport async function loadConfigs(options: Pick<StudioOptions, 'configPath' | 'logLevel'>): Promise<{ configPath: string; config: Config }> {\n const { configPath, configs } = await getConfigs({ configPath: options.configPath, logLevel: options.logLevel })\n const [config] = configs\n\n if (!config) {\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, config }\n}\n\n/**\n * Why a rejected token could not be recovered automatically: no browser is available to re-pair\n * with, or the token this run already re-paired for was rejected again.\n */\ntype RejectedTokenReason = 'nonInteractive' | 'reauthExhausted'\n\n/**\n * Explains a rejected token to the operator. Builds the error and nothing else, so each caller\n * decides what happens to the credentials.\n */\nfunction explainRejectedToken(error: InvalidAgentTokenError, reason: RejectedTokenReason): Error {\n if (reason === 'reauthExhausted') {\n return new Error(`${error.message} Studio rejected the newly approved token too. Run \\`kubb studio login\\` and try again.`)\n }\n\n return new Error(`${error.message} Run \\`kubb studio login\\` to pair again.`)\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 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 ? { logger: plainLogger } : {}),\n })\n hooks.hook('studio:connected', async () => {\n pairedAgain = false\n await context.onState?.('connected')\n if (hinted || context.onState || options.logLevel === 'silent') return\n hinted = true\n logBlock(styleText('dim', 'Press Ctrl+C to disconnect'))\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 loadConfig: async () => (await loadConfigs(options)).config,\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 explainRejectedToken(error, 'reauthExhausted')\n if (context.onState || isCIEnvironment() || !canUseTTY()) throw explainRejectedToken(error, 'nonInteractive')\n\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 if (!context.onState && signal.aborted && options.logLevel !== 'silent') logOutro('Disconnected')\n } catch (error) {\n if (!(error instanceof PairingCanceledError)) throw error\n } finally {\n events.off('SIGINT', stop)\n events.off('SIGTERM', stop)\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: {\n allowRead: values.allowRead ?? false,\n allowReadAst: values.allowReadAst ?? false,\n allowWrite: values.allowWrite ?? false,\n allowConfigEdit: values.allowConfigEdit ?? false,\n allowExec: values.allowExec ?? false,\n },\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,5 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-CPE0t6oh.cjs");
2
- const require_Telemetry = require("./Telemetry-BfdvvZus.cjs");
2
+ const require_Telemetry = require("./Telemetry-BV4GonCV.cjs");
3
3
  let node_util = require("node:util");
4
4
  let node_process = require("node:process");
5
5
  node_process = require_rolldown_runtime.__toESM(node_process, 1);
@@ -29,4 +29,4 @@ async function run() {
29
29
  //#endregion
30
30
  exports.run = run;
31
31
 
32
- //# sourceMappingURL=run-B13e9GQz.cjs.map
32
+ //# sourceMappingURL=run-CvE8ZdKG.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-CvE8ZdKG.cjs","names":["trackRun","process","styleText","toError"],"sources":["../src/runners/mcp/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport type * as McpModule from '@kubb/mcp'\nimport { trackRun } from '../../Telemetry.ts'\n\n/**\n * Starts the `@kubb/mcp` server over stdio and reports the outcome to telemetry.\n */\nexport async function run(): Promise<void> {\n const { run: startMcpServer } = (await import('@kubb/mcp')) as typeof McpModule\n\n const report = trackRun({ command: 'mcp', hrStart: process.hrtime() })\n\n try {\n // The MCP stdio transport owns stdout: anything else written there corrupts the JSON-RPC stream.\n console.error(styleText('cyan', '⏳ Starting MCP server...'))\n console.warn(styleText('yellow', 'This feature is still under development, use with caution'))\n const server = startMcpServer()\n // Report once the client introduces itself, so the event names the client (e.g. `claude-code`, `cursor-vscode`).\n server.on('initialize', ({ clientInfo }) => void report({ status: 'success', mcpClient: clientInfo.name }), { once: true })\n } catch (error) {\n await report({ status: 'failed' })\n console.error(toError(error).message)\n process.exitCode = 1\n }\n}\n"],"mappings":";;;;;;;;;AASA,eAAsB,MAAqB;CACzC,MAAM,EAAE,KAAK,mBAAoB,MAAM,OAAO;CAE9C,MAAM,SAASA,kBAAAA,SAAS;EAAE,SAAS;EAAO,SAASC,aAAAA,QAAQ,OAAO;CAAE,CAAC;CAErE,IAAI;EAEF,QAAQ,OAAA,GAAMC,UAAAA,UAAAA,CAAU,QAAQ,0BAA0B,CAAC;EAC3D,QAAQ,MAAA,GAAKA,UAAAA,UAAAA,CAAU,UAAU,2DAA2D,CAAC;EAG7F,eAAK,CAAC,CAAC,GAAG,eAAe,EAAE,iBAAiB,KAAK,OAAO;GAAE,QAAQ;GAAW,WAAW,WAAW;EAAK,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC;CAC5H,SAAS,OAAO;EACd,MAAM,OAAO,EAAE,QAAQ,SAAS,CAAC;EACjC,QAAQ,MAAMC,kBAAAA,QAAQ,KAAK,CAAC,CAAC,OAAO;EACpC,aAAA,QAAA,WAAmB;CACrB;AACF"}
@@ -1,5 +1,5 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { l as toError, n as trackRun } from "./Telemetry-Bf6lUdai.js";
2
+ import { l as toError, n as trackRun } from "./Telemetry-Cz9QCzRo.js";
3
3
  import { styleText } from "node:util";
4
4
  import process from "node:process";
5
5
  //#region src/runners/mcp/run.ts
@@ -28,4 +28,4 @@ async function run() {
28
28
  //#endregion
29
29
  export { run };
30
30
 
31
- //# sourceMappingURL=run-Cu3pmezx.js.map
31
+ //# sourceMappingURL=run-DaFK-Uy2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-Cu3pmezx.js","names":[],"sources":["../src/runners/mcp/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport type * as McpModule from '@kubb/mcp'\nimport { trackRun } from '../../Telemetry.ts'\n\n/**\n * Starts the `@kubb/mcp` server over stdio and reports the outcome to telemetry.\n */\nexport async function run(): Promise<void> {\n const { run: startMcpServer } = (await import('@kubb/mcp')) as typeof McpModule\n\n const report = trackRun({ command: 'mcp', hrStart: process.hrtime() })\n\n try {\n // The MCP stdio transport owns stdout: anything else written there corrupts the JSON-RPC stream.\n console.error(styleText('cyan', '⏳ Starting MCP server...'))\n console.warn(styleText('yellow', 'This feature is still under development, use with caution'))\n const server = startMcpServer()\n // Report once the client introduces itself, so the event names the client (e.g. `claude-code`, `cursor-vscode`).\n server.on('initialize', ({ clientInfo }) => void report({ status: 'success', mcpClient: clientInfo.name }), { once: true })\n } catch (error) {\n await report({ status: 'failed' })\n console.error(toError(error).message)\n process.exitCode = 1\n }\n}\n"],"mappings":";;;;;;;;AASA,eAAsB,MAAqB;CACzC,MAAM,EAAE,KAAK,mBAAoB,MAAM,OAAO;CAE9C,MAAM,SAAS,SAAS;EAAE,SAAS;EAAO,SAAS,QAAQ,OAAO;CAAE,CAAC;CAErE,IAAI;EAEF,QAAQ,MAAM,UAAU,QAAQ,0BAA0B,CAAC;EAC3D,QAAQ,KAAK,UAAU,UAAU,2DAA2D,CAAC;EAG7F,eAAK,CAAC,CAAC,GAAG,eAAe,EAAE,iBAAiB,KAAK,OAAO;GAAE,QAAQ;GAAW,WAAW,WAAW;EAAK,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC;CAC5H,SAAS,OAAO;EACd,MAAM,OAAO,EAAE,QAAQ,SAAS,CAAC;EACjC,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC,OAAO;EACpC,QAAQ,WAAW;CACrB;AACF"}
1
+ {"version":3,"file":"run-DaFK-Uy2.js","names":[],"sources":["../src/runners/mcp/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport type * as McpModule from '@kubb/mcp'\nimport { trackRun } from '../../Telemetry.ts'\n\n/**\n * Starts the `@kubb/mcp` server over stdio and reports the outcome to telemetry.\n */\nexport async function run(): Promise<void> {\n const { run: startMcpServer } = (await import('@kubb/mcp')) as typeof McpModule\n\n const report = trackRun({ command: 'mcp', hrStart: process.hrtime() })\n\n try {\n // The MCP stdio transport owns stdout: anything else written there corrupts the JSON-RPC stream.\n console.error(styleText('cyan', '⏳ Starting MCP server...'))\n console.warn(styleText('yellow', 'This feature is still under development, use with caution'))\n const server = startMcpServer()\n // Report once the client introduces itself, so the event names the client (e.g. `claude-code`, `cursor-vscode`).\n server.on('initialize', ({ clientInfo }) => void report({ status: 'success', mcpClient: clientInfo.name }), { once: true })\n } catch (error) {\n await report({ status: 'failed' })\n console.error(toError(error).message)\n process.exitCode = 1\n }\n}\n"],"mappings":";;;;;;;;AASA,eAAsB,MAAqB;CACzC,MAAM,EAAE,KAAK,mBAAoB,MAAM,OAAO;CAE9C,MAAM,SAAS,SAAS;EAAE,SAAS;EAAO,SAAS,QAAQ,OAAO;CAAE,CAAC;CAErE,IAAI;EAEF,QAAQ,MAAM,UAAU,QAAQ,0BAA0B,CAAC;EAC3D,QAAQ,KAAK,UAAU,UAAU,2DAA2D,CAAC;EAG7F,eAAK,CAAC,CAAC,GAAG,eAAe,EAAE,iBAAiB,KAAK,OAAO;GAAE,QAAQ;GAAW,WAAW,WAAW;EAAK,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC;CAC5H,SAAS,OAAO;EACd,MAAM,OAAO,EAAE,QAAQ,SAAS,CAAC;EACjC,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC,OAAO;EACpC,QAAQ,WAAW;CACrB;AACF"}