@kubb/cli 5.14.6 → 5.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/bin/kubb.js +2 -1
  2. package/dist/{Telemetry-B5V_ufmv.cjs → Telemetry-B52pKz9i.cjs} +14 -118
  3. package/dist/Telemetry-B52pKz9i.cjs.map +1 -0
  4. package/dist/{Telemetry-DrnGartf.js → Telemetry-C7Qwy2s7.js} +12 -86
  5. package/dist/Telemetry-C7Qwy2s7.js.map +1 -0
  6. package/dist/{background-DlK0by5c.js → background-BJCuXYuB.js} +5 -6
  7. package/dist/{background-DlK0by5c.js.map → background-BJCuXYuB.js.map} +1 -1
  8. package/dist/{background-CdPT1eaq.cjs → background-CK2gQtTU.cjs} +5 -6
  9. package/dist/{background-CdPT1eaq.cjs.map → background-CK2gQtTU.cjs.map} +1 -1
  10. package/dist/{background-C6XHpEo7.js → background-D4mZCg-4.js} +1 -1
  11. package/dist/banner-BdTTDFkG.js +140 -0
  12. package/dist/banner-BdTTDFkG.js.map +1 -0
  13. package/dist/banner-wJFk-L-c.cjs +163 -0
  14. package/dist/banner-wJFk-L-c.cjs.map +1 -0
  15. package/dist/config-BL3HnFhb.js +1 -0
  16. package/dist/config-BWj9jBVj.cjs +62 -0
  17. package/dist/config-BWj9jBVj.cjs.map +1 -0
  18. package/dist/{config-CNqgDSu3.js → config-CQTxXvIG.js} +6 -52
  19. package/dist/config-CQTxXvIG.js.map +1 -0
  20. package/dist/{config-BG_Nr2CZ.cjs → config-CRrmj88c.cjs} +15 -62
  21. package/dist/config-CRrmj88c.cjs.map +1 -0
  22. package/dist/config-Uk3rbZfb.js +49 -0
  23. package/dist/config-Uk3rbZfb.js.map +1 -0
  24. package/dist/configFile-C0DIXNMD.js +993 -0
  25. package/dist/configFile-C0DIXNMD.js.map +1 -0
  26. package/dist/configFile-CoEpHdXG.cjs +1028 -0
  27. package/dist/configFile-CoEpHdXG.cjs.map +1 -0
  28. package/dist/{credentials-C8tjAhTo.js → credentials-B77iJx9H.js} +1 -1
  29. package/dist/{credentials-DDaKqtJn.cjs → credentials-DEsGwcGD.cjs} +3 -4
  30. package/dist/{credentials-DDaKqtJn.cjs.map → credentials-DEsGwcGD.cjs.map} +1 -1
  31. package/dist/{credentials-CZK6zPLv.js → credentials-osgjujE_.js} +3 -4
  32. package/dist/{credentials-CZK6zPLv.js.map → credentials-osgjujE_.js.map} +1 -1
  33. package/dist/env-C3xHRMez.js +1 -0
  34. package/dist/env-eu3XyKqJ.cjs +55 -0
  35. package/dist/env-eu3XyKqJ.cjs.map +1 -0
  36. package/dist/env-rv-VgSGN.js +34 -0
  37. package/dist/env-rv-VgSGN.js.map +1 -0
  38. package/dist/{errors-Cl69p_vI.cjs → errors-BponpdjN.cjs} +3 -4
  39. package/dist/{errors-Cl69p_vI.cjs.map → errors-BponpdjN.cjs.map} +1 -1
  40. package/dist/{errors-DmC83ALX.js → errors-wzqmMpMo.js} +3 -4
  41. package/dist/{errors-DmC83ALX.js.map → errors-wzqmMpMo.js.map} +1 -1
  42. package/dist/index.cjs +37 -2719
  43. package/dist/index.cjs.map +1 -1
  44. package/dist/index.d.cts +0 -2
  45. package/dist/index.d.ts +0 -2
  46. package/dist/index.js +35 -2713
  47. package/dist/index.js.map +1 -1
  48. package/dist/installWithSpinner-DpnpxHq5.js +49 -0
  49. package/dist/installWithSpinner-DpnpxHq5.js.map +1 -0
  50. package/dist/installWithSpinner-ONGfIVUJ.cjs +56 -0
  51. package/dist/installWithSpinner-ONGfIVUJ.cjs.map +1 -0
  52. package/dist/{text-CL6N6yPS.js → intro-9PB8sE8z.js} +8 -52
  53. package/dist/intro-9PB8sE8z.js.map +1 -0
  54. package/dist/{text-DrsG1EDN.cjs → intro-YPaf1Imr.cjs} +12 -80
  55. package/dist/intro-YPaf1Imr.cjs.map +1 -0
  56. package/dist/isCIEnvironment-D6xtAAZ2.js +14 -0
  57. package/dist/isCIEnvironment-D6xtAAZ2.js.map +1 -0
  58. package/dist/isCIEnvironment-DiVOMI5Q.cjs +20 -0
  59. package/dist/isCIEnvironment-DiVOMI5Q.cjs.map +1 -0
  60. package/dist/mascot--q1xjKw1.js +63 -0
  61. package/dist/mascot--q1xjKw1.js.map +1 -0
  62. package/dist/mascot-JSA0j3Q_.cjs +80 -0
  63. package/dist/mascot-JSA0j3Q_.cjs.map +1 -0
  64. package/dist/mcp-CcseJJwh.cjs +20 -0
  65. package/dist/mcp-CcseJJwh.cjs.map +1 -0
  66. package/dist/mcp-DUTsS8tR.js +21 -0
  67. package/dist/mcp-DUTsS8tR.js.map +1 -0
  68. package/dist/package-B1hUUjio.cjs +10 -0
  69. package/dist/package-B1hUUjio.cjs.map +1 -0
  70. package/dist/package-MYPMnnTX.js +5 -0
  71. package/dist/package-MYPMnnTX.js.map +1 -0
  72. package/dist/{registry-DOGpflct.js → registry-B3eYk4LN.js} +7 -67
  73. package/dist/registry-B3eYk4LN.js.map +1 -0
  74. package/dist/{registry-BzBp6aZI.cjs → registry-YE1pFWL-.cjs} +4 -82
  75. package/dist/registry-YE1pFWL-.cjs.map +1 -0
  76. package/dist/{reporters-GzXlc4CK.cjs → reporters-2cgjvXwR.cjs} +32 -40
  77. package/dist/{reporters-GzXlc4CK.cjs.map → reporters-2cgjvXwR.cjs.map} +1 -1
  78. package/dist/{reporters-mYHIUZSx.js → reporters-BM430HdQ.js} +19 -27
  79. package/dist/{reporters-mYHIUZSx.js.map → reporters-BM430HdQ.js.map} +1 -1
  80. package/dist/{rolldown-runtime-CPE0t6oh.cjs → rolldown-runtime-C3-Zg-KD.cjs} +1 -2
  81. package/dist/{rolldown-runtime-CRm0XQPb.js → rolldown-runtime-xo6NMXYd.js} +1 -2
  82. package/dist/run-1H9TGT8v.js +77 -0
  83. package/dist/run-1H9TGT8v.js.map +1 -0
  84. package/dist/run-BYP_t9dR.cjs +324 -0
  85. package/dist/run-BYP_t9dR.cjs.map +1 -0
  86. package/dist/run-Bq6gcfkS.js +1 -0
  87. package/dist/run-BrM7-NSV.js +181 -0
  88. package/dist/run-BrM7-NSV.js.map +1 -0
  89. package/dist/run-BsrNfFIl.js +228 -0
  90. package/dist/run-BsrNfFIl.js.map +1 -0
  91. package/dist/{run-l8IiOR_c.js → run-CLiHI99L.js} +9 -9
  92. package/dist/{run-l8IiOR_c.js.map → run-CLiHI99L.js.map} +1 -1
  93. package/dist/{run-C8Prej7s.cjs → run-CQORv7Gq.cjs} +44 -37
  94. package/dist/run-CQORv7Gq.cjs.map +1 -0
  95. package/dist/{run-EJtgdIin.js → run-CXVhxFfC.js} +31 -23
  96. package/dist/run-CXVhxFfC.js.map +1 -0
  97. package/dist/run-CrM4jsix.cjs +80 -0
  98. package/dist/run-CrM4jsix.cjs.map +1 -0
  99. package/dist/run-CvFakE3B.cjs +185 -0
  100. package/dist/run-CvFakE3B.cjs.map +1 -0
  101. package/dist/{run-DC_xH5H3.cjs → run-CyzKy-0p.cjs} +49 -41
  102. package/dist/run-CyzKy-0p.cjs.map +1 -0
  103. package/dist/run-D-nn9-Wq.js +319 -0
  104. package/dist/run-D-nn9-Wq.js.map +1 -0
  105. package/dist/run-DBnSbwtU.cjs +389 -0
  106. package/dist/run-DBnSbwtU.cjs.map +1 -0
  107. package/dist/{run-j1g5si5R.js → run-DTqMrPS9.js} +5 -6
  108. package/dist/{run-j1g5si5R.js.map → run-DTqMrPS9.js.map} +1 -1
  109. package/dist/{run-9fs2T2Je.js → run-DUwX6Icx.js} +26 -20
  110. package/dist/run-DUwX6Icx.js.map +1 -0
  111. package/dist/run-FEiyv6_U.js +385 -0
  112. package/dist/run-FEiyv6_U.js.map +1 -0
  113. package/dist/run-LY_UAYyM.cjs +233 -0
  114. package/dist/run-LY_UAYyM.cjs.map +1 -0
  115. package/dist/{run-sjzj0ir-.cjs → run-dMTJfs4_.cjs} +10 -10
  116. package/dist/{run-sjzj0ir-.cjs.map → run-dMTJfs4_.cjs.map} +1 -1
  117. package/dist/{run-CypFtkVE.cjs → run-uPA5s3rI.cjs} +5 -6
  118. package/dist/{run-CypFtkVE.cjs.map → run-uPA5s3rI.cjs.map} +1 -1
  119. package/dist/shared-C0EtrdUm.cjs +123 -0
  120. package/dist/shared-C0EtrdUm.cjs.map +1 -0
  121. package/dist/shared-Ct9stKpp.js +94 -0
  122. package/dist/shared-Ct9stKpp.js.map +1 -0
  123. package/dist/{snapshot-laSRD0z1.cjs → snapshot-CPF9zyZj.cjs} +13 -14
  124. package/dist/{snapshot-laSRD0z1.cjs.map → snapshot-CPF9zyZj.cjs.map} +1 -1
  125. package/dist/{snapshot-BJWnL6hE.js → snapshot-CiV08NJr.js} +10 -11
  126. package/dist/{snapshot-BJWnL6hE.js.map → snapshot-CiV08NJr.js.map} +1 -1
  127. package/dist/spinner-BZaln7O8.js +160 -0
  128. package/dist/spinner-BZaln7O8.js.map +1 -0
  129. package/dist/spinner-CfB0sIPy.cjs +208 -0
  130. package/dist/spinner-CfB0sIPy.cjs.map +1 -0
  131. package/dist/{status-DFEdbBPu.cjs → status-C066YA-4.cjs} +7 -8
  132. package/dist/{status-DFEdbBPu.cjs.map → status-C066YA-4.cjs.map} +1 -1
  133. package/dist/{status-BjmXLRm2.js → status-Dj8tivag.js} +6 -7
  134. package/dist/{status-BjmXLRm2.js.map → status-Dj8tivag.js.map} +1 -1
  135. package/dist/studio-B4XsXgKj.js +215 -0
  136. package/dist/studio-B4XsXgKj.js.map +1 -0
  137. package/dist/studio-D9_-mKee.cjs +218 -0
  138. package/dist/studio-D9_-mKee.cjs.map +1 -0
  139. package/dist/studioWorker.js +4 -5
  140. package/dist/{summary-DDnI70tn.js → summary-CbmQKA8l.js} +5 -6
  141. package/dist/{summary-DDnI70tn.js.map → summary-CbmQKA8l.js.map} +1 -1
  142. package/dist/{summary-1DCwzWEU.cjs → summary-Clvl5Hxs.cjs} +7 -8
  143. package/dist/{summary-1DCwzWEU.cjs.map → summary-Clvl5Hxs.cjs.map} +1 -1
  144. package/dist/table-BlRe9YTZ.cjs +15 -0
  145. package/dist/table-BlRe9YTZ.cjs.map +1 -0
  146. package/dist/table-CR7iZJGo.js +10 -0
  147. package/dist/table-CR7iZJGo.js.map +1 -0
  148. package/dist/text-BmiI4s6N.js +13 -0
  149. package/dist/text-BmiI4s6N.js.map +1 -0
  150. package/dist/text-Ep3AulAS.cjs +24 -0
  151. package/dist/text-Ep3AulAS.cjs.map +1 -0
  152. package/dist/time-3BKoci3G.cjs +82 -0
  153. package/dist/time-3BKoci3G.cjs.map +1 -0
  154. package/dist/time-C-wU7VhC.js +65 -0
  155. package/dist/time-C-wU7VhC.js.map +1 -0
  156. package/dist/utils-BdibacYq.js +244 -0
  157. package/dist/utils-BdibacYq.js.map +1 -0
  158. package/dist/utils-CO89mxRU.cjs +290 -0
  159. package/dist/utils-CO89mxRU.cjs.map +1 -0
  160. package/dist/utils-CbJ6hS_t.js +222 -0
  161. package/dist/utils-CbJ6hS_t.js.map +1 -0
  162. package/dist/utils-CcARPB45.cjs +286 -0
  163. package/dist/utils-CcARPB45.cjs.map +1 -0
  164. package/dist/validate-B3tLWYJU.cjs +27 -0
  165. package/dist/validate-B3tLWYJU.cjs.map +1 -0
  166. package/dist/validate-C5fyNF4v.js +28 -0
  167. package/dist/validate-C5fyNF4v.js.map +1 -0
  168. package/package.json +7 -7
  169. package/dist/Telemetry-B5V_ufmv.cjs.map +0 -1
  170. package/dist/Telemetry-DrnGartf.js.map +0 -1
  171. package/dist/config-BG_Nr2CZ.cjs.map +0 -1
  172. package/dist/config-CNqgDSu3.js.map +0 -1
  173. package/dist/config-DWDpFSn1.js +0 -1
  174. package/dist/registry-BzBp6aZI.cjs.map +0 -1
  175. package/dist/registry-DOGpflct.js.map +0 -1
  176. package/dist/run-9fs2T2Je.js.map +0 -1
  177. package/dist/run-C8Prej7s.cjs.map +0 -1
  178. package/dist/run-CXVme-aS.js +0 -1
  179. package/dist/run-DC_xH5H3.cjs.map +0 -1
  180. package/dist/run-EJtgdIin.js.map +0 -1
  181. package/dist/text-CL6N6yPS.js.map +0 -1
  182. package/dist/text-DrsG1EDN.cjs.map +0 -1
  183. package/dist/utils-C3vTpUje.cjs +0 -645
  184. package/dist/utils-C3vTpUje.cjs.map +0 -1
  185. package/dist/utils-CIc8YFtr.js +0 -536
  186. package/dist/utils-CIc8YFtr.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-DUwX6Icx.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 allowInstall?: boolean\n allowUpdate?: boolean\n allowRemove?: boolean\n allowSaveInput?: 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.INSTALL, label: 'add plugins', title: () => 'Install extensions from the registry', hint: 'kubb add from the browser' },\n { key: AgentPermission.UPDATE, label: 'update plugins', title: () => 'Update installed extensions', hint: 'kubb update from the browser' },\n { key: AgentPermission.REMOVE, label: 'remove plugins', title: () => 'Remove extensions', hint: 'kubb remove from the browser' },\n {\n key: AgentPermission.SAVE_INPUT,\n label: 'save input',\n title: (configPath) => `Save the spec from Studio as the input in ${configPath}`,\n hint: 'keep a pasted spec, URL, or git file',\n },\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 { edit = false }: { edit?: boolean } = {},\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 // `edit` asks again for every permission no flag grants, with the saved ones checked.\n const pending = PERMISSIONS.filter(({ key }) => !options.permission[key] && (edit || 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 ...(edit ? { initialValues: pending.filter(({ key }) => remembered?.[key] === true).map(({ key }) => key) } : {}),\n required: false,\n })\n // A canceled list grants nothing and saves nothing, so the next run asks again.\n if (prompts.isCancel(selected)) {\n if (edit) throw new Error('Canceled. Permissions are unchanged.')\n return granted\n }\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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"}
@@ -0,0 +1,385 @@
1
+ import "./rolldown-runtime-xo6NMXYd.js";
2
+ import { a as ConfigEditOperation, t as editConfig } from "./configFile-C0DIXNMD.js";
3
+ import { n as getElapsedMs, t as formatMs } from "./time-C-wU7VhC.js";
4
+ import { r as exists, s as write, t as createSpinner } from "./spinner-BZaln7O8.js";
5
+ import { t as version } from "./package-MYPMnnTX.js";
6
+ import { l as logStep, n as logIntro, o as logBlock, r as logOutro, s as logError, t as isInteractiveRun, u as logWarn } from "./intro-9PB8sE8z.js";
7
+ import { n as dryRunId } from "./shared-Ct9stKpp.js";
8
+ import { t as pluralize } from "./text-BmiI4s6N.js";
9
+ import { a as KUBB_CONFIG_FILENAME, o as KUBB_PACKAGE_NAME, s as initDefaults } from "./config-CQTxXvIG.js";
10
+ import { t as getConfigs } from "./config-Uk3rbZfb.js";
11
+ import { a as installSpec, i as incompatibility, r as fetchRegistryIndex, s as registryUrl } from "./registry-B3eYk4LN.js";
12
+ import { a as generateScript, c as missingPluginDependencies, i as findSpecFiles, l as parsePluginsFlag, n as detectPackageManager, o as initPackageJson, r as findPlugin, s as installPackages, t as addGenerateScript, u as readSpecInfo } from "./utils-CbJ6hS_t.js";
13
+ import { t as installWithSpinner } from "./installWithSpinner-DpnpxHq5.js";
14
+ import { styleText } from "node:util";
15
+ import { defineWithTypes } from "gunshi";
16
+ import process from "node:process";
17
+ import path from "node:path";
18
+ import * as clack from "@clack/prompts";
19
+ import { Diagnostics, createKubb } from "@kubb/core";
20
+ // ../../internals/shared/src/init.ts
21
+ /** The `kubb.config.ts` `kubb init` writes before `kubb add` puts each plugin in. */
22
+ function generateConfigFile({ inputPath, outputPath }) {
23
+ return `import { defineConfig } from 'kubb/config'
24
+
25
+ export default defineConfig({
26
+ input: '${inputPath}',
27
+ output: {
28
+ path: '${outputPath}',
29
+ clean: true,
30
+ },
31
+ plugins: [],
32
+ })
33
+ `;
34
+ }
35
+ // src/runners/init/run.ts
36
+ function cancelAndExit(message = "Operation canceled.") {
37
+ clack.cancel(message);
38
+ process.exit(0);
39
+ }
40
+ function unwrap(value) {
41
+ if (clack.isCancel(value)) cancelAndExit();
42
+ return value;
43
+ }
44
+ /** The full `kubb.config.ts` for `choices`, with each plugin added the way `kubb add` adds it. */
45
+ function buildConfig({ inputPath, outputPath, plugins }) {
46
+ const { source, outcomes } = editConfig({
47
+ source: generateConfigFile({
48
+ inputPath,
49
+ outputPath
50
+ }),
51
+ edits: plugins.map((entry) => ({
52
+ operation: ConfigEditOperation.ADD_PLUGIN,
53
+ plugin: entry.artifact.package
54
+ })),
55
+ extensions: new Map(plugins.map(({ artifact, manifest }) => [artifact.package, {
56
+ package: artifact.package,
57
+ version: artifact.version,
58
+ manifest
59
+ }]))
60
+ });
61
+ const failed = outcomes.find((outcome) => !outcome.applied);
62
+ if (failed && failed.edit.operation === ConfigEditOperation.ADD_PLUGIN) throw new Diagnostics.Error({
63
+ code: Diagnostics.code.unknown,
64
+ severity: "error",
65
+ message: `Could not add ${failed.edit.plugin} to ${KUBB_CONFIG_FILENAME}: ${failed.reason}`,
66
+ help: `Run kubb init without that plugin, then add it with kubb add.`
67
+ });
68
+ return source;
69
+ }
70
+ /** Generates from the config at `configPath` without reporters, and returns how many files it wrote. */
71
+ async function firstRun(configPath) {
72
+ const { configs } = await getConfigs({ configPath });
73
+ let files = 0;
74
+ for (const config of configs) {
75
+ const result = await createKubb(config).generate();
76
+ if (!result.success) throw new Error(result.diagnostics.flatMap((diagnostic) => diagnostic.severity === "error" ? [diagnostic.message] : []).join("\n"));
77
+ files += result.files.length;
78
+ }
79
+ return files;
80
+ }
81
+ /** The command that runs `kubb generate`: the `generate` script when it runs Kubb, otherwise `npx kubb generate`. */
82
+ function generateCommand({ packageManager, script, watch }) {
83
+ if (script !== "kubb generate") return `npx kubb generate${watch ? " --watch" : ""}`;
84
+ const run = [
85
+ packageManager.name,
86
+ ...packageManager.runCommand,
87
+ "generate"
88
+ ].join(" ");
89
+ if (!watch) return run;
90
+ return packageManager.name === "npm" ? `${run} -- --watch` : `${run} --watch`;
91
+ }
92
+ /**
93
+ * Runs the Kubb setup wizard: detects the package manager and specs, asks for the spec, plugins, and
94
+ * output folder, shows the config for review, then installs, writes `kubb.config.ts`, adds a
95
+ * `generate` script, and runs the first generation.
96
+ * Pass `yes: true` to skip all prompts and print one line per step.
97
+ */
98
+ async function run({ yes, input: inputFlag, output: outputFlag, plugins: pluginsFlag, dryRun }) {
99
+ const cwd = process.cwd();
100
+ /** Runs `task` behind a spinner, or prints one line when it is done in `--yes` mode. */
101
+ async function step({ start, task, done, failed }) {
102
+ const spinner = createSpinner();
103
+ if (!yes) spinner.start(start);
104
+ try {
105
+ const result = await task();
106
+ if (yes) console.log(`${styleText("green", "✓")} ${done(result)}`);
107
+ else spinner.stop(done(result));
108
+ return result;
109
+ } catch (error) {
110
+ if (!yes) spinner.error(failed);
111
+ throw error;
112
+ }
113
+ }
114
+ if (!yes) logIntro({ title: isInteractiveRun({
115
+ yes,
116
+ dryRun: dryRun.enabled
117
+ }) ? void 0 : "Set up Kubb" });
118
+ try {
119
+ const registry = fetchRegistryIndex({ registry: registryUrl() }).then((entries) => entries.filter((entry) => entry.kind === "plugin" && !incompatibility(entry.manifest)));
120
+ registry.catch(() => {});
121
+ if (!await exists(path.join(cwd, "package.json"))) {
122
+ if (!yes) {
123
+ if (!unwrap(await clack.confirm({
124
+ message: "No package.json found. Would you like to create one?",
125
+ initialValue: true
126
+ }))) cancelAndExit();
127
+ }
128
+ const packageManager = detectPackageManager(cwd);
129
+ await step({
130
+ start: `Initializing package.json with ${packageManager.name}`,
131
+ task: () => initPackageJson(cwd, packageManager),
132
+ done: () => `Created package.json with ${packageManager.name}`,
133
+ failed: "Could not create package.json"
134
+ });
135
+ }
136
+ const packageManager = detectPackageManager(cwd);
137
+ const specs = await findSpecFiles(cwd);
138
+ if (!yes) {
139
+ logStep(`Package manager ${packageManager.name}`);
140
+ if (specs[0]) {
141
+ const { version: specVersion, operations } = await readSpecInfo(path.join(cwd, specs[0]));
142
+ const details = [
143
+ specs[0].slice(2),
144
+ specVersion ? `${specVersion.startsWith("2") ? "Swagger" : "OpenAPI"} ${specVersion}` : void 0,
145
+ operations === void 0 ? void 0 : pluralize(operations, "operation"),
146
+ specs.length > 1 ? `+${specs.length - 1} more` : void 0
147
+ ];
148
+ logStep(`Found ${details.filter(Boolean).join(" · ")}`);
149
+ }
150
+ }
151
+ const plugins = pluginsFlag || yes ? await registry : void 0;
152
+ const defaultPlugins = (entries) => initDefaults.plugins.flatMap((id) => findPlugin({
153
+ plugins: entries,
154
+ id
155
+ }) ?? []);
156
+ const flagPlugins = pluginsFlag && plugins ? parsePluginsFlag({
157
+ plugins,
158
+ value: pluginsFlag
159
+ }) : void 0;
160
+ let choices = {
161
+ inputPath: inputFlag ?? specs[0] ?? initDefaults.inputPath,
162
+ outputPath: outputFlag ?? initDefaults.outputPath,
163
+ plugins: flagPlugins ?? (plugins ? defaultPlugins(plugins) : [])
164
+ };
165
+ if (yes && !choices.plugins.length) throw new Error("The registry has no default plugin. Pass --plugins to choose one.");
166
+ async function askInput(current) {
167
+ const choice = specs.length ? unwrap(await clack.select({
168
+ message: "Which spec should Kubb read?",
169
+ options: [
170
+ ...specs.map((spec) => ({
171
+ value: spec,
172
+ label: spec,
173
+ hint: "found in this repo"
174
+ })),
175
+ {
176
+ value: "url",
177
+ label: "A URL"
178
+ },
179
+ {
180
+ value: "file",
181
+ label: "Another file"
182
+ }
183
+ ],
184
+ initialValue: specs.includes(current) ? current : /^https?:\/\//.test(current) ? "url" : "file"
185
+ })) : /^https?:\/\//.test(current) ? "url" : "file";
186
+ if (specs.includes(choice)) return choice;
187
+ const isUrl = choice === "url";
188
+ const initial = isUrl === /^https?:\/\//.test(current) && !specs.includes(current) ? current : void 0;
189
+ return unwrap(await clack.text({
190
+ message: isUrl ? "Spec URL" : "Spec path",
191
+ placeholder: isUrl ? "https://example.com/openapi.yaml" : initDefaults.inputPath,
192
+ initialValue: initial,
193
+ defaultValue: isUrl ? void 0 : initDefaults.inputPath,
194
+ validate: (value) => {
195
+ if (isUrl && !/^https?:\/\//.test(value ?? "")) return "Enter an http(s) URL";
196
+ }
197
+ }));
198
+ }
199
+ async function askPlugins(previous) {
200
+ const plugins = await registry;
201
+ const current = previous.length ? previous : defaultPlugins(plugins);
202
+ const width = Math.max(...plugins.map((entry) => entry.manifest.displayName.length));
203
+ const nameWidth = Math.max(...plugins.map((entry) => entry.manifest.name.length));
204
+ const values = unwrap(await clack.multiselect({
205
+ message: "What should Kubb generate?",
206
+ options: plugins.map(({ id, manifest }) => ({
207
+ value: id,
208
+ label: `${manifest.displayName.padEnd(width)} ${styleText("dim", manifest.name.padEnd(nameWidth))}`.trimEnd()
209
+ })),
210
+ initialValues: current.map((entry) => entry.id),
211
+ required: true
212
+ }));
213
+ return plugins.filter((entry) => values.includes(entry.id));
214
+ }
215
+ const answered = yes || Boolean(inputFlag && outputFlag && pluginsFlag);
216
+ if (!answered) {
217
+ let firstPass = true;
218
+ while (true) {
219
+ choices = {
220
+ inputPath: firstPass && inputFlag ? inputFlag : await askInput(choices.inputPath),
221
+ plugins: firstPass && flagPlugins ? flagPlugins : await askPlugins(choices.plugins),
222
+ outputPath: firstPass && outputFlag ? outputFlag : unwrap(await clack.text({
223
+ message: "Output folder",
224
+ placeholder: choices.outputPath,
225
+ defaultValue: choices.outputPath
226
+ }))
227
+ };
228
+ firstPass = false;
229
+ const missing = missingPluginDependencies(choices.plugins.map((entry) => entry.manifest));
230
+ if (missing.length) {
231
+ logWarn(`${missing.join("\n")}\nAdd the missing plugins.`);
232
+ continue;
233
+ }
234
+ const config = buildConfig(choices);
235
+ const packages = [KUBB_PACKAGE_NAME, ...choices.plugins.map((entry) => entry.artifact.package)];
236
+ logStep(`Review ${KUBB_CONFIG_FILENAME}`);
237
+ logBlock([
238
+ ...config.trimEnd().split("\n"),
239
+ "",
240
+ `${styleText("dim", "Installs")} ${packages.join(" ")} with ${packageManager.name}`
241
+ ]);
242
+ const configExists = await exists(path.join(cwd, KUBB_CONFIG_FILENAME));
243
+ if (unwrap(await clack.select({
244
+ message: configExists ? `kubb.config.ts exists. Overwrite it?` : "Create it?",
245
+ options: [{
246
+ value: true,
247
+ label: "Yes"
248
+ }, {
249
+ value: false,
250
+ label: "Change a choice"
251
+ }]
252
+ }))) break;
253
+ }
254
+ }
255
+ const missing = missingPluginDependencies(choices.plugins.map((entry) => entry.manifest));
256
+ if (missing.length) throw new Diagnostics.Error({
257
+ code: Diagnostics.code.missingDependency,
258
+ severity: "error",
259
+ message: `${missing.join("\n")}\nAdd the missing plugins and run kubb init again.`
260
+ });
261
+ const configPath = path.join(cwd, KUBB_CONFIG_FILENAME);
262
+ if (answered && !yes && await exists(configPath)) {
263
+ if (!unwrap(await clack.confirm({
264
+ message: `kubb.config.ts exists. Overwrite it?`,
265
+ initialValue: false
266
+ }))) cancelAndExit("Keeping existing configuration.");
267
+ }
268
+ const packagesToInstall = [`${KUBB_PACKAGE_NAME}@${version}`, ...choices.plugins.map((entry) => installSpec(entry.artifact))];
269
+ const packageNames = [KUBB_PACKAGE_NAME, ...choices.plugins.map((entry) => entry.artifact.package)];
270
+ const dry = { message: `install ${packagesToInstall.length} packages with ${packageManager.name}` };
271
+ if (yes) await step({
272
+ start: "",
273
+ task: async () => void await dryRun.run(() => installPackages(packagesToInstall, packageManager, cwd), dry),
274
+ done: () => `Installed ${packageNames.join(" ")} with ${packageManager.name}`,
275
+ failed: "Installation failed"
276
+ });
277
+ else await installWithSpinner({
278
+ packages: packagesToInstall,
279
+ names: `${packagesToInstall.length} packages`,
280
+ packageManager,
281
+ cwd,
282
+ install: async (packages, packageManager, cwd, onLine) => void await dryRun.run(() => installPackages(packages, packageManager, cwd, onLine), dry)
283
+ });
284
+ await step({
285
+ start: `Writing ${KUBB_CONFIG_FILENAME}`,
286
+ task: async () => dryRun.run(async () => void await write(configPath, buildConfig(choices)), { message: `write ${KUBB_CONFIG_FILENAME}` }),
287
+ done: () => `Wrote ${KUBB_CONFIG_FILENAME}`,
288
+ failed: `Could not write ${KUBB_CONFIG_FILENAME}`
289
+ });
290
+ const scriptAdded = await dryRun.run(() => addGenerateScript(cwd), {
291
+ message: "add a generate script to package.json",
292
+ resolve: async () => await generateScript(cwd) === void 0
293
+ });
294
+ if (scriptAdded && !yes) logStep("Added \"generate\": \"kubb generate\" to package.json");
295
+ const script = scriptAdded ? "kubb generate" : await generateScript(cwd);
296
+ const runStart = process.hrtime();
297
+ try {
298
+ await dryRun.run(() => step({
299
+ start: "Running the first generation",
300
+ task: () => firstRun(configPath),
301
+ done: (files) => yes ? `Generated ${pluralize(files, "file")} in ${choices.outputPath}` : `First run ${pluralize(files, "file")} in ${choices.outputPath} · ${formatMs(getElapsedMs(runStart))}`,
302
+ failed: "First run failed"
303
+ }), {
304
+ message: "run the first generation",
305
+ resolve: () => 0
306
+ });
307
+ } catch (error) {
308
+ logError(error instanceof Error ? error.message : String(error));
309
+ const message = `Kubb is set up, but the first run failed. Fix the error, then run ${generateCommand({
310
+ packageManager,
311
+ script,
312
+ watch: false
313
+ })}.`;
314
+ if (yes) console.log(message);
315
+ else logOutro(styleText("yellow", message));
316
+ process.exitCode = 1;
317
+ return;
318
+ }
319
+ if (yes) {
320
+ console.log(`Kubb is set up. Run ${generateCommand({
321
+ packageManager,
322
+ script,
323
+ watch: false
324
+ })} after changing the spec.`);
325
+ return;
326
+ }
327
+ logOutro(`${styleText("green", "✓ Kubb is set up")}\n ${styleText("dim", "Next")} ${generateCommand({
328
+ packageManager,
329
+ script,
330
+ watch: true
331
+ })}`);
332
+ } catch (error) {
333
+ logError(styleText("red", "An error occurred during initialization"));
334
+ if (error instanceof Error) logError(error.message);
335
+ process.exit(1);
336
+ }
337
+ }
338
+ const command = defineWithTypes()({
339
+ name: "init",
340
+ description: "Set up a config, install plugins, and run the first generation.",
341
+ examples: [
342
+ "kubb init",
343
+ "kubb init --yes",
344
+ "kubb init --input ./openapi.yaml --output ./src/gen --plugins plugin-ts,plugin-zod",
345
+ "kubb init --yes --input ./openapi.yaml --plugins ts,zod --output src/api",
346
+ "kubb init --plugins plugin-ts,plugin-axios,plugin-react-query",
347
+ "kubb init --yes --dry-run"
348
+ ].join("\n"),
349
+ toKebab: true,
350
+ args: {
351
+ yes: {
352
+ type: "boolean",
353
+ description: "Skip prompts and use the detected spec, the default plugin, and the default output folder",
354
+ short: "y",
355
+ default: false
356
+ },
357
+ input: {
358
+ type: "string",
359
+ description: "Path to the OpenAPI specification",
360
+ short: "i",
361
+ metavar: "path"
362
+ },
363
+ output: {
364
+ type: "string",
365
+ description: "Output directory for generated files",
366
+ short: "o",
367
+ metavar: "path"
368
+ },
369
+ plugins: {
370
+ type: "string",
371
+ description: "Comma-separated Kubb registry ids of the plugins to add, the same ids `kubb add` takes (plugin-ts, plugin-zod, acme/plugin-x), or short names (ts, zod)",
372
+ metavar: "plugin-ts,plugin-zod,..."
373
+ }
374
+ },
375
+ run: ({ values, extensions }) => run({
376
+ yes: values.yes,
377
+ input: values.input,
378
+ output: values.output,
379
+ plugins: values.plugins,
380
+ dryRun: extensions[dryRunId]
381
+ })
382
+ });
383
+ export { command, run };
384
+
385
+ //# sourceMappingURL=run-FEiyv6_U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-FEiyv6_U.js","names":[],"sources":["../../../internals/shared/src/init.ts","../src/runners/init/run.ts"],"sourcesContent":["/** The `kubb.config.ts` `kubb init` writes before `kubb add` puts each plugin in. */\nexport function generateConfigFile({ inputPath, outputPath }: { inputPath: string; outputPath: string }): string {\n return `import { defineConfig } from 'kubb/config'\n\nexport default defineConfig({\n input: '${inputPath}',\n output: {\n path: '${outputPath}',\n clean: true,\n },\n plugins: [],\n})\n`\n}\n","import path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport * as clack from '@clack/prompts'\nimport type { DryRunExtension } from '@gunshi/plugin-dryrun'\nimport { defineWithTypes } from 'gunshi'\nimport { ConfigEditOperation, editConfig, generateConfigFile, initDefaults, KUBB_CONFIG_FILENAME, KUBB_PACKAGE_NAME } from '@internals/shared'\nimport { exists, formatMs, getElapsedMs, write } from '@internals/utils'\nimport { createKubb, Diagnostics, type RegistryEntry } from '@kubb/core'\nimport { dryRunId, type DryRunExtensions } from '../../commands/shared.ts'\nimport { getConfigs } from '../../config.ts'\nimport { pluralize } from '../../ui/text.ts'\nimport { isInteractiveRun, logIntro, logOutro } from '../../ui/intro.ts'\nimport { logBlock, logError, logStep, logWarn } from '../../ui/log.ts'\nimport { createSpinner } from '../../ui/spinner.ts'\nimport { fetchRegistryIndex, incompatibility, installSpec, registryUrl } from '../../utils/registry.ts'\nimport { installWithSpinner } from '../installWithSpinner.ts'\nimport {\n addGenerateScript,\n detectPackageManager,\n findPlugin,\n findSpecFiles,\n generateScript,\n initPackageJson,\n installPackages,\n missingPluginDependencies,\n type PackageManagerInfo,\n parsePluginsFlag,\n readSpecInfo,\n} from './utils.ts'\nimport { version } from '../../../package.json'\n\nfunction cancelAndExit(message = 'Operation canceled.'): never {\n clack.cancel(message)\n process.exit(0)\n}\n\nfunction unwrap<T>(value: T): Exclude<T, symbol> {\n if (clack.isCancel(value)) cancelAndExit()\n return value as Exclude<T, symbol>\n}\n\ntype InitOptions = {\n /**\n * When `true`, skips all interactive prompts and uses the detected or default values.\n */\n yes: boolean\n /**\n * Input path flag value from `--input`. When provided, skips the input prompt.\n */\n input?: string\n /**\n * Output directory flag value from `--output`. When provided, skips the output prompt.\n */\n output?: string\n /**\n * Comma-separated plugin list from `--plugins`, e.g. `'plugin-ts,zod'`. When provided, skips the plugin selection prompt.\n */\n plugins?: string\n /**\n * Dry-run extension from `@gunshi/plugin-dryrun`. When enabled, package installation, file\n * writes, and the first run are skipped.\n */\n dryRun: DryRunExtension\n}\n\ntype Choices = {\n inputPath: string\n outputPath: string\n plugins: Array<RegistryEntry>\n}\n\n/** The full `kubb.config.ts` for `choices`, with each plugin added the way `kubb add` adds it. */\nfunction buildConfig({ inputPath, outputPath, plugins }: Choices): string {\n const { source, outcomes } = editConfig({\n source: generateConfigFile({ inputPath, outputPath }),\n edits: plugins.map((entry) => ({ operation: ConfigEditOperation.ADD_PLUGIN, plugin: entry.artifact.package })),\n extensions: new Map(plugins.map(({ artifact, manifest }) => [artifact.package, { package: artifact.package, version: artifact.version, manifest }])),\n })\n const failed = outcomes.find((outcome) => !outcome.applied)\n if (failed && failed.edit.operation === ConfigEditOperation.ADD_PLUGIN)\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `Could not add ${failed.edit.plugin} to ${KUBB_CONFIG_FILENAME}: ${failed.reason}`,\n help: `Run kubb init without that plugin, then add it with kubb add.`,\n })\n return source\n}\n\n/** Generates from the config at `configPath` without reporters, and returns how many files it wrote. */\nasync function firstRun(configPath: string): Promise<number> {\n const { configs } = await getConfigs({ configPath })\n let files = 0\n for (const config of configs) {\n const result = await createKubb(config).generate()\n if (!result.success) throw new Error(result.diagnostics.flatMap((diagnostic) => (diagnostic.severity === 'error' ? [diagnostic.message] : [])).join('\\n'))\n files += result.files.length\n }\n return files\n}\n\n/** The command that runs `kubb generate`: the `generate` script when it runs Kubb, otherwise `npx kubb generate`. */\nfunction generateCommand({ packageManager, script, watch }: { packageManager: PackageManagerInfo; script: string | undefined; watch: boolean }): string {\n if (script !== 'kubb generate') return `npx kubb generate${watch ? ' --watch' : ''}`\n const run = [packageManager.name, ...packageManager.runCommand, 'generate'].join(' ')\n if (!watch) return run\n return packageManager.name === 'npm' ? `${run} -- --watch` : `${run} --watch`\n}\n\n/**\n * Runs the Kubb setup wizard: detects the package manager and specs, asks for the spec, plugins, and\n * output folder, shows the config for review, then installs, writes `kubb.config.ts`, adds a\n * `generate` script, and runs the first generation.\n * Pass `yes: true` to skip all prompts and print one line per step.\n */\nexport async function run({ yes, input: inputFlag, output: outputFlag, plugins: pluginsFlag, dryRun }: InitOptions): Promise<void> {\n const cwd = process.cwd()\n\n /** Runs `task` behind a spinner, or prints one line when it is done in `--yes` mode. */\n async function step<T>({ start, task, done, failed }: { start: string; task: () => Promise<T>; done: (result: T) => string; failed: string }): Promise<T> {\n const spinner = createSpinner()\n if (!yes) spinner.start(start)\n try {\n const result = await task()\n if (yes) console.log(`${styleText('green', '✓')} ${done(result)}`)\n else spinner.stop(done(result))\n return result\n } catch (error) {\n if (!yes) spinner.error(failed)\n throw error\n }\n }\n\n if (!yes) logIntro({ title: isInteractiveRun({ yes, dryRun: dryRun.enabled }) ? undefined : 'Set up Kubb' })\n\n try {\n // Start the registry fetch now but await it only at the plugin step, so the first prompt never waits on the network\n const registry = fetchRegistryIndex({ registry: registryUrl() }).then((entries) =>\n entries.filter((entry) => entry.kind === 'plugin' && !incompatibility(entry.manifest)),\n )\n registry.catch(() => {})\n\n if (!(await exists(path.join(cwd, 'package.json')))) {\n if (!yes) {\n const shouldInit = unwrap(await clack.confirm({ message: 'No package.json found. Would you like to create one?', initialValue: true }))\n if (!shouldInit) cancelAndExit()\n }\n\n const packageManager = detectPackageManager(cwd)\n await step({\n start: `Initializing package.json with ${packageManager.name}`,\n task: () => initPackageJson(cwd, packageManager),\n done: () => `Created package.json with ${packageManager.name}`,\n failed: 'Could not create package.json',\n })\n }\n\n const packageManager = detectPackageManager(cwd)\n const specs = await findSpecFiles(cwd)\n\n if (!yes) {\n logStep(`Package manager ${packageManager.name}`)\n if (specs[0]) {\n const { version: specVersion, operations } = await readSpecInfo(path.join(cwd, specs[0]))\n const details = [\n specs[0].slice(2),\n specVersion ? `${specVersion.startsWith('2') ? 'Swagger' : 'OpenAPI'} ${specVersion}` : undefined,\n operations === undefined ? undefined : pluralize(operations, 'operation'),\n specs.length > 1 ? `+${specs.length - 1} more` : undefined,\n ]\n logStep(`Found ${details.filter(Boolean).join(' · ')}`)\n }\n }\n\n // `--plugins` and `--yes` need the registry before any prompt; the interactive path reads it at the plugin step\n const plugins = pluginsFlag || yes ? await registry : undefined\n const defaultPlugins = (entries: Array<RegistryEntry>) => initDefaults.plugins.flatMap((id) => findPlugin({ plugins: entries, id }) ?? [])\n\n const flagPlugins = pluginsFlag && plugins ? parsePluginsFlag({ plugins, value: pluginsFlag }) : undefined\n\n let choices: Choices = {\n inputPath: inputFlag ?? specs[0] ?? initDefaults.inputPath,\n outputPath: outputFlag ?? initDefaults.outputPath,\n plugins: flagPlugins ?? (plugins ? defaultPlugins(plugins) : []),\n }\n if (yes && !choices.plugins.length) {\n throw new Error('The registry has no default plugin. Pass --plugins to choose one.')\n }\n\n async function askInput(current: string): Promise<string> {\n const choice = specs.length\n ? unwrap(\n await clack.select({\n message: 'Which spec should Kubb read?',\n options: [\n ...specs.map((spec) => ({ value: spec, label: spec, hint: 'found in this repo' })),\n { value: 'url', label: 'A URL' },\n { value: 'file', label: 'Another file' },\n ],\n initialValue: specs.includes(current) ? current : /^https?:\\/\\//.test(current) ? 'url' : 'file',\n }),\n )\n : /^https?:\\/\\//.test(current)\n ? 'url'\n : 'file'\n if (specs.includes(choice)) return choice\n const isUrl = choice === 'url'\n const initial = isUrl === /^https?:\\/\\//.test(current) && !specs.includes(current) ? current : undefined\n return unwrap(\n await clack.text({\n message: isUrl ? 'Spec URL' : 'Spec path',\n placeholder: isUrl ? 'https://example.com/openapi.yaml' : initDefaults.inputPath,\n initialValue: initial,\n defaultValue: isUrl ? undefined : initDefaults.inputPath,\n validate: (value) => {\n if (isUrl && !/^https?:\\/\\//.test(value ?? '')) return 'Enter an http(s) URL'\n },\n }),\n )\n }\n\n async function askPlugins(previous: Array<RegistryEntry>): Promise<Array<RegistryEntry>> {\n const plugins = await registry\n const current = previous.length ? previous : defaultPlugins(plugins)\n const width = Math.max(...plugins.map((entry) => entry.manifest.displayName.length))\n const nameWidth = Math.max(...plugins.map((entry) => entry.manifest.name.length))\n const values = unwrap(\n await clack.multiselect({\n message: 'What should Kubb generate?',\n options: plugins.map(({ id, manifest }) => ({\n value: id,\n label: `${manifest.displayName.padEnd(width)} ${styleText('dim', manifest.name.padEnd(nameWidth))}`.trimEnd(),\n })),\n initialValues: current.map((entry) => entry.id),\n required: true,\n }),\n )\n return plugins.filter((entry) => values.includes(entry.id))\n }\n\n // Flags for all three choices leave nothing to ask or review, as before the review step existed\n const answered = yes || Boolean(inputFlag && outputFlag && pluginsFlag)\n if (!answered) {\n let firstPass = true\n while (true) {\n // The first pass skips the questions a flag answered; \"Change a choice\" asks them all again.\n choices = {\n inputPath: firstPass && inputFlag ? inputFlag : await askInput(choices.inputPath),\n plugins: firstPass && flagPlugins ? flagPlugins : await askPlugins(choices.plugins),\n outputPath:\n firstPass && outputFlag\n ? outputFlag\n : unwrap(await clack.text({ message: 'Output folder', placeholder: choices.outputPath, defaultValue: choices.outputPath })),\n }\n firstPass = false\n const missing = missingPluginDependencies(choices.plugins.map((entry) => entry.manifest))\n if (missing.length) {\n logWarn(`${missing.join('\\n')}\\nAdd the missing plugins.`)\n continue\n }\n const config = buildConfig(choices)\n const packages = [KUBB_PACKAGE_NAME, ...choices.plugins.map((entry) => entry.artifact.package)]\n logStep(`Review ${KUBB_CONFIG_FILENAME}`)\n logBlock([...config.trimEnd().split('\\n'), '', `${styleText('dim', 'Installs')} ${packages.join(' ')} with ${packageManager.name}`])\n const configExists = await exists(path.join(cwd, KUBB_CONFIG_FILENAME))\n const confirmed = unwrap(\n await clack.select({\n message: configExists ? `${KUBB_CONFIG_FILENAME} exists. Overwrite it?` : 'Create it?',\n options: [\n { value: true, label: 'Yes' },\n { value: false, label: 'Change a choice' },\n ],\n }),\n )\n if (confirmed) break\n }\n }\n\n // Check the selection against the plugins' manifests before installing anything\n const missing = missingPluginDependencies(choices.plugins.map((entry) => entry.manifest))\n if (missing.length) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.missingDependency,\n severity: 'error',\n message: `${missing.join('\\n')}\\nAdd the missing plugins and run kubb init again.`,\n })\n }\n\n const configPath = path.join(cwd, KUBB_CONFIG_FILENAME)\n if (answered && !yes && (await exists(configPath))) {\n const overwrite = unwrap(await clack.confirm({ message: `${KUBB_CONFIG_FILENAME} exists. Overwrite it?`, initialValue: false }))\n if (!overwrite) cancelAndExit('Keeping existing configuration.')\n }\n\n // Install `kubb` at the running CLI's version and each plugin at the version the registry pins\n const packagesToInstall = [`${KUBB_PACKAGE_NAME}@${version}`, ...choices.plugins.map((entry) => installSpec(entry.artifact))]\n const packageNames = [KUBB_PACKAGE_NAME, ...choices.plugins.map((entry) => entry.artifact.package)]\n const dry = { message: `install ${packagesToInstall.length} packages with ${packageManager.name}` }\n if (yes) {\n await step({\n start: '',\n task: async () => void (await dryRun.run(() => installPackages(packagesToInstall, packageManager, cwd), dry)),\n done: () => `Installed ${packageNames.join(' ')} with ${packageManager.name}`,\n failed: 'Installation failed',\n })\n } else {\n await installWithSpinner({\n packages: packagesToInstall,\n names: `${packagesToInstall.length} packages`,\n packageManager,\n cwd,\n install: async (packages, packageManager, cwd, onLine) => void (await dryRun.run(() => installPackages(packages, packageManager, cwd, onLine), dry)),\n })\n }\n\n await step({\n start: `Writing ${KUBB_CONFIG_FILENAME}`,\n task: async () => dryRun.run(async () => void (await write(configPath, buildConfig(choices))), { message: `write ${KUBB_CONFIG_FILENAME}` }),\n done: () => `Wrote ${KUBB_CONFIG_FILENAME}`,\n failed: `Could not write ${KUBB_CONFIG_FILENAME}`,\n })\n\n const scriptAdded = await dryRun.run(() => addGenerateScript(cwd), {\n message: 'add a generate script to package.json',\n resolve: async () => (await generateScript(cwd)) === undefined,\n })\n if (scriptAdded && !yes) logStep('Added \"generate\": \"kubb generate\" to package.json')\n\n const script = scriptAdded ? 'kubb generate' : await generateScript(cwd)\n const runStart = process.hrtime()\n try {\n await dryRun.run(\n () =>\n step({\n start: 'Running the first generation',\n task: () => firstRun(configPath),\n done: (files) =>\n yes\n ? `Generated ${pluralize(files, 'file')} in ${choices.outputPath}`\n : `First run ${pluralize(files, 'file')} in ${choices.outputPath} · ${formatMs(getElapsedMs(runStart))}`,\n failed: 'First run failed',\n }),\n { message: 'run the first generation', resolve: () => 0 },\n )\n } catch (error) {\n logError(error instanceof Error ? error.message : String(error))\n const message = `Kubb is set up, but the first run failed. Fix the error, then run ${generateCommand({ packageManager, script, watch: false })}.`\n if (yes) console.log(message)\n else logOutro(styleText('yellow', message))\n process.exitCode = 1\n return\n }\n\n if (yes) {\n console.log(`Kubb is set up. Run ${generateCommand({ packageManager, script, watch: false })} after changing the spec.`)\n return\n }\n logOutro(`${styleText('green', '✓ Kubb is set up')}\\n ${styleText('dim', 'Next')} ${generateCommand({ packageManager, script, watch: true })}`)\n } catch (error) {\n logError(styleText('red', 'An error occurred during initialization'))\n if (error instanceof Error) {\n logError(error.message)\n }\n process.exit(1)\n }\n}\n\nexport const command = defineWithTypes<{ extensions: DryRunExtensions }>()({\n name: 'init',\n description: 'Set up a config, install plugins, and run the first generation.',\n examples: [\n 'kubb init',\n 'kubb init --yes',\n 'kubb init --input ./openapi.yaml --output ./src/gen --plugins plugin-ts,plugin-zod',\n 'kubb init --yes --input ./openapi.yaml --plugins ts,zod --output src/api',\n 'kubb init --plugins plugin-ts,plugin-axios,plugin-react-query',\n 'kubb init --yes --dry-run',\n ].join('\\n'),\n toKebab: true,\n args: {\n yes: {\n type: 'boolean',\n description: 'Skip prompts and use the detected spec, the default plugin, and the default output folder',\n short: 'y',\n default: false,\n },\n input: {\n type: 'string',\n description: 'Path to the OpenAPI specification',\n short: 'i',\n metavar: 'path',\n },\n output: {\n type: 'string',\n description: 'Output directory for generated files',\n short: 'o',\n metavar: 'path',\n },\n plugins: {\n type: 'string',\n description:\n 'Comma-separated Kubb registry ids of the plugins to add, the same ids `kubb add` takes (plugin-ts, plugin-zod, acme/plugin-x), or short names (ts, zod)',\n metavar: 'plugin-ts,plugin-zod,...',\n },\n },\n run: ({ values, extensions }) => run({ yes: values.yes, input: values.input, output: values.output, plugins: values.plugins, dryRun: extensions[dryRunId] }),\n})\n"],"mappings":"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"}