@kubb/cli 5.9.2 → 5.9.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 (58) hide show
  1. package/dist/{Telemetry-B_C4MVJd.cjs → Telemetry-C9gmBTr0.cjs} +2 -2
  2. package/dist/{Telemetry-B_C4MVJd.cjs.map → Telemetry-C9gmBTr0.cjs.map} +1 -1
  3. package/dist/{Telemetry-DER8LIO5.js → Telemetry-CSc7OVsv.js} +2 -2
  4. package/dist/{Telemetry-DER8LIO5.js.map → Telemetry-CSc7OVsv.js.map} +1 -1
  5. package/dist/background-1AFVK_yN.js +1 -0
  6. package/dist/{background-Bh4FDWa3.cjs → background-BcRoKru0.cjs} +2 -2
  7. package/dist/{background-Bh4FDWa3.cjs.map → background-BcRoKru0.cjs.map} +1 -1
  8. package/dist/{background-B0YbkZ0s.js → background-CCex47-d.js} +2 -2
  9. package/dist/{background-B0YbkZ0s.js.map → background-CCex47-d.js.map} +1 -1
  10. package/dist/{commands-hXDwA0zn.cjs → commands-BuY0nrlU.cjs} +3 -3
  11. package/dist/{commands-hXDwA0zn.cjs.map → commands-BuY0nrlU.cjs.map} +1 -1
  12. package/dist/{commands-BegVe5Mt.js → commands-atq2z0Bo.js} +3 -3
  13. package/dist/{commands-BegVe5Mt.js.map → commands-atq2z0Bo.js.map} +1 -1
  14. package/dist/index.cjs +19 -18
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.js +19 -18
  17. package/dist/index.js.map +1 -1
  18. package/dist/{run-KLPSFEv-.js → run-B1jaQu6Q.js} +2 -2
  19. package/dist/{run-KLPSFEv-.js.map → run-B1jaQu6Q.js.map} +1 -1
  20. package/dist/{run-Ct6kzKpg.cjs → run-BGTUbY2h.cjs} +24 -3
  21. package/dist/run-BGTUbY2h.cjs.map +1 -0
  22. package/dist/{run-CJHsZZB8.js → run-BPQzGEIs.js} +2 -2
  23. package/dist/{run-CJHsZZB8.js.map → run-BPQzGEIs.js.map} +1 -1
  24. package/dist/{run-BQQhNg8I.js → run-BRUwQ5Y7.js} +3 -3
  25. package/dist/{run-BQQhNg8I.js.map → run-BRUwQ5Y7.js.map} +1 -1
  26. package/dist/{run-89YfZJuo.cjs → run-Bhs7mJ1f.cjs} +23 -11
  27. package/dist/run-Bhs7mJ1f.cjs.map +1 -0
  28. package/dist/run-CH48n-MJ.js +1 -0
  29. package/dist/{run-D8EJ2hKI.cjs → run-CIvFRMLt.cjs} +2 -2
  30. package/dist/{run-D8EJ2hKI.cjs.map → run-CIvFRMLt.cjs.map} +1 -1
  31. package/dist/{run-e8gMz1M_.cjs → run-Co732JNO.cjs} +2 -2
  32. package/dist/{run-e8gMz1M_.cjs.map → run-Co732JNO.cjs.map} +1 -1
  33. package/dist/{run-fg0ycsS_.cjs → run-DFos0eOY.cjs} +2 -2
  34. package/dist/{run-fg0ycsS_.cjs.map → run-DFos0eOY.cjs.map} +1 -1
  35. package/dist/{run-Ca_OX3WZ.js → run-DfEoWJuy.js} +25 -4
  36. package/dist/run-DfEoWJuy.js.map +1 -0
  37. package/dist/{run-DL2wLwBZ.cjs → run-Dm9OZUkQ.cjs} +2 -2
  38. package/dist/{run-DL2wLwBZ.cjs.map → run-Dm9OZUkQ.cjs.map} +1 -1
  39. package/dist/{run-BCswmM8Q.js → run-DunTcXOS.js} +2 -2
  40. package/dist/{run-BCswmM8Q.js.map → run-DunTcXOS.js.map} +1 -1
  41. package/dist/{run-C8dyBAPb.cjs → run-DxGkjzRm.cjs} +3 -3
  42. package/dist/{run-C8dyBAPb.cjs.map → run-DxGkjzRm.cjs.map} +1 -1
  43. package/dist/{run-Dej-hm91.js → run-DxxYCqEo.js} +23 -11
  44. package/dist/run-DxxYCqEo.js.map +1 -0
  45. package/dist/{run-BcMMYk7G.js → run-QPsBYkq_.js} +2 -2
  46. package/dist/{run-BcMMYk7G.js.map → run-QPsBYkq_.js.map} +1 -1
  47. package/dist/{snapshot-C0WaZZiF.js → snapshot-CkpJr-gr.js} +3 -3
  48. package/dist/{snapshot-C0WaZZiF.js.map → snapshot-CkpJr-gr.js.map} +1 -1
  49. package/dist/{snapshot-B45A4RfA.cjs → snapshot-DUJU70H_.cjs} +3 -3
  50. package/dist/{snapshot-B45A4RfA.cjs.map → snapshot-DUJU70H_.cjs.map} +1 -1
  51. package/dist/studioWorker.js +2 -2
  52. package/package.json +7 -7
  53. package/dist/background-DSKoOwcG.js +0 -1
  54. package/dist/run-89YfZJuo.cjs.map +0 -1
  55. package/dist/run-8HrdMihy.js +0 -1
  56. package/dist/run-Ca_OX3WZ.js.map +0 -1
  57. package/dist/run-Ct6kzKpg.cjs.map +0 -1
  58. package/dist/run-Dej-hm91.js.map +0 -1
@@ -35,7 +35,7 @@ function detect() {
35
35
  }
36
36
  //#endregion
37
37
  //#region package.json
38
- var version = "5.9.2";
38
+ var version = "5.9.3";
39
39
  //#endregion
40
40
  //#region src/Telemetry.ts
41
41
  /** OpenTelemetry ingestion endpoint for anonymous usage telemetry. */
@@ -228,4 +228,4 @@ Object.defineProperty(exports, "version", {
228
228
  }
229
229
  });
230
230
 
231
- //# sourceMappingURL=Telemetry-B_C4MVJd.cjs.map
231
+ //# sourceMappingURL=Telemetry-C9gmBTr0.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Telemetry-B_C4MVJd.cjs","names":["process","getElapsedMs","os","isCIEnvironment","getAgentName","randomBytes"],"sources":["../../../internals/utils/src/runtime.ts","../package.json","../src/Telemetry.ts"],"sourcesContent":["// Bun polyfills `process.versions.node`, so detection keys off the globals instead.\nconst isBun = typeof Bun !== 'undefined'\nconst isDeno = 'Deno' in globalThis\n\n/**\n * The JavaScript runtime executing the current process: its name, version and whether it is Bun.\n *\n * @example\n * ```ts\n * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise\n * ```\n */\nexport const runtime = { isBun, ...detect() } as const\n\nfunction detect(): { name: 'bun' | 'deno' | 'node'; version: string } {\n if (isBun) return { name: 'bun', version: process.versions.bun ?? '' }\n if (isDeno) return { name: 'deno', version: (globalThis as { Deno?: { version?: { deno?: string } } }).Deno?.version?.deno ?? '' }\n return { name: 'node', version: process.versions?.node ?? '' }\n}\n","","import { randomBytes } from 'node:crypto'\nimport os from 'node:os'\nimport process from 'node:process'\nimport { getElapsedMs, isCIEnvironment, runtime } from '@internals/utils'\nimport { getAgentName } from './agent.ts'\nimport { version } from '../package.json'\n\n/** OpenTelemetry ingestion endpoint for anonymous usage telemetry. */\nconst OTLP_ENDPOINT = 'https://otlp.kubb.dev' as const\n\ntype TelemetryCommand = 'generate' | 'mcp' | 'studio' | 'validate'\n\ntype OtlpValue =\n | { stringValue: string }\n | { boolValue: boolean }\n | { intValue: number }\n | { arrayValue: { values: Array<OtlpValue> } }\n | { kvlistValue: { values: Array<OtlpKeyValue> } }\n\ntype OtlpKeyValue = {\n key: string\n value: OtlpValue\n}\n\ntype OtlpSpan = {\n traceId: string\n spanId: string\n name: string\n kind: 1\n startTimeUnixNano: string\n endTimeUnixNano: string\n attributes: Array<OtlpKeyValue>\n status: { code: 1 | 2 }\n}\n\ntype OtlpExportTraceServiceRequest = {\n resourceSpans: Array<{\n resource: { attributes: Array<OtlpKeyValue> }\n scopeSpans: Array<{\n scope: { name: string; version: string }\n spans: Array<OtlpSpan>\n }>\n }>\n}\n\n/**\n * Anonymous plugin name and options snapshot sent with each telemetry event.\n */\nexport type TelemetryPlugin = {\n /**\n * Plugin name as registered in the Kubb config, e.g. `'@kubb/plugin-ts'`.\n */\n name: string\n /**\n * Anonymized snapshot of the plugin options. Values are included but cannot be traced back to a user.\n */\n options: Record<string, unknown>\n}\n\n/**\n * Anonymous snapshot of a single Kubb run, built by {@link buildTelemetryEvent} and sent by {@link sendTelemetry}.\n */\ntype TelemetryEvent = {\n command: string\n kubbVersion: string\n /**\n * Major version of Node that executed the run, e.g. `'22'`.\n */\n nodeVersion: string\n /**\n * Name of the JavaScript runtime that executed the run, `'bun'`, `'deno'`, or `'node'`.\n */\n runtime: string\n /**\n * Major version of the active runtime, e.g. `'1'` under Bun or `'22'` under Node.\n */\n runtimeVersion: string\n platform: string\n ci: boolean\n /**\n * Name of the detected AI coding agent (e.g. `'claude'`, `'cursor'`), when the CLI is invoked\n * by one. `undefined` when run by a human or an unrecognized caller.\n */\n agent?: string\n plugins: Array<TelemetryPlugin>\n duration: number\n filesCreated: number\n status: 'success' | 'failed'\n}\n\n/**\n * Returns `true` when telemetry is disabled via `DO_NOT_TRACK` or `KUBB_DISABLE_TELEMETRY`.\n */\nexport function isDisabled(): boolean {\n return ['DO_NOT_TRACK', 'KUBB_DISABLE_TELEMETRY'].some((name) => ['1', 'true'].includes(process.env[name] ?? ''))\n}\n\n/**\n * Build an anonymous telemetry payload from a completed generation run.\n */\nexport function buildTelemetryEvent(options: {\n command: TelemetryCommand\n kubbVersion: string\n plugins?: Array<TelemetryPlugin>\n hrStart: [number, number]\n filesCreated?: number\n status: 'success' | 'failed'\n}): TelemetryEvent {\n const duration = Math.round(getElapsedMs(options.hrStart))\n\n return {\n command: options.command,\n kubbVersion: options.kubbVersion,\n nodeVersion: process.versions.node.split('.')[0] as string,\n runtime: runtime.name,\n runtimeVersion: runtime.version.split('.')[0] as string,\n platform: os.platform(),\n ci: isCIEnvironment(),\n agent: getAgentName(),\n plugins: options.plugins ?? [],\n duration,\n filesCreated: options.filesCreated ?? 0,\n status: options.status,\n }\n}\n\ntype TrackRunOptions = {\n command: TelemetryCommand\n /** `process.hrtime()` snapshot taken when the command started. */\n hrStart: [number, number]\n}\n\ntype RunResult = Pick<TelemetryEvent, 'status'> & Partial<Pick<TelemetryEvent, 'plugins' | 'filesCreated'>>\n\n/** Tracks one command run for the running CLI version; returns the reporter the command calls once it knows how it ended. */\nexport function trackRun({ command, hrStart }: TrackRunOptions): (result: RunResult) => Promise<void> {\n return (result) => sendTelemetry(buildTelemetryEvent({ command, kubbVersion: version, hrStart, ...result }))\n}\n\n/**\n * Convert a {@link TelemetryEvent} into an OTLP-compatible JSON trace payload.\n *\n * @see https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/\n */\nexport function buildOtlpPayload(event: TelemetryEvent): OtlpExportTraceServiceRequest {\n const traceId = randomBytes(16).toString('hex')\n const spanId = randomBytes(8).toString('hex')\n const endTimeNs = BigInt(Date.now()) * 1_000_000n\n const startTimeNs = endTimeNs - BigInt(event.duration) * 1_000_000n\n const pluginNames = [...new Set(event.plugins.map((plugin) => plugin.name))].sort()\n\n const attributes: Array<OtlpKeyValue> = [\n { key: 'kubb.command', value: { stringValue: event.command } },\n { key: 'kubb.version', value: { stringValue: event.kubbVersion } },\n { key: 'kubb.node_version', value: { stringValue: event.nodeVersion } },\n { key: 'kubb.runtime', value: { stringValue: event.runtime } },\n { key: 'kubb.runtime_version', value: { stringValue: event.runtimeVersion } },\n { key: 'kubb.platform', value: { stringValue: event.platform } },\n { key: 'kubb.ci', value: { boolValue: event.ci } },\n ...(event.agent ? [{ key: 'kubb.agent', value: { stringValue: event.agent } }] : []),\n { key: 'kubb.files_created', value: { intValue: event.filesCreated } },\n { key: 'kubb.status', value: { stringValue: event.status } },\n {\n key: 'kubb.plugins',\n value: { arrayValue: { values: pluginNames.map((name) => ({ stringValue: name })) } },\n },\n ...pluginNames.map((name) => ({ key: `kubb.plugin.${name}`, value: { boolValue: true } })),\n {\n key: 'kubb.plugin_options',\n value: {\n arrayValue: {\n values: event.plugins.map((p) => ({\n kvlistValue: {\n values: [\n { key: 'name', value: { stringValue: p.name } },\n {\n key: 'options',\n value: {\n stringValue: JSON.stringify({\n ...p.options,\n usedEnumNames: undefined,\n }),\n },\n },\n ],\n },\n })),\n },\n },\n },\n ]\n\n return {\n resourceSpans: [\n {\n resource: {\n attributes: [\n { key: 'service.name', value: { stringValue: 'kubb' } },\n {\n key: 'service.version',\n value: { stringValue: event.kubbVersion },\n },\n { key: 'telemetry.sdk.language', value: { stringValue: 'nodejs' } },\n ],\n },\n scopeSpans: [\n {\n scope: { name: 'kubb-core', version: event.kubbVersion },\n spans: [\n {\n traceId,\n spanId,\n name: event.command,\n kind: 1,\n startTimeUnixNano: String(startTimeNs),\n endTimeUnixNano: String(endTimeNs),\n attributes,\n status: {\n code: event.status === 'success' ? 1 : 2,\n },\n },\n ],\n },\n ],\n },\n ],\n }\n}\n\n/**\n * Send an anonymous telemetry event to the Kubb OTLP endpoint. Respects `DO_NOT_TRACK` and\n * `KUBB_DISABLE_TELEMETRY`, and fails silently so telemetry never interrupts a run. No file\n * paths, OpenAPI specs, or secrets are sent.\n */\nexport async function sendTelemetry(event: TelemetryEvent): Promise<void> {\n if (isDisabled()) {\n return\n }\n\n try {\n await fetch(`${OTLP_ENDPOINT}/v1/traces`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Kubb-Telemetry-Version': '1',\n 'Kubb-Telemetry-Source': 'kubb-cli',\n },\n body: JSON.stringify(buildOtlpPayload(event)),\n signal: AbortSignal.timeout(5_000),\n })\n } catch (_e) {\n // Fail silently, telemetry must never break the run\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Telemetry-C9gmBTr0.cjs","names":["process","getElapsedMs","os","isCIEnvironment","getAgentName","randomBytes"],"sources":["../../../internals/utils/src/runtime.ts","../package.json","../src/Telemetry.ts"],"sourcesContent":["// Bun polyfills `process.versions.node`, so detection keys off the globals instead.\nconst isBun = typeof Bun !== 'undefined'\nconst isDeno = 'Deno' in globalThis\n\n/**\n * The JavaScript runtime executing the current process: its name, version and whether it is Bun.\n *\n * @example\n * ```ts\n * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise\n * ```\n */\nexport const runtime = { isBun, ...detect() } as const\n\nfunction detect(): { name: 'bun' | 'deno' | 'node'; version: string } {\n if (isBun) return { name: 'bun', version: process.versions.bun ?? '' }\n if (isDeno) return { name: 'deno', version: (globalThis as { Deno?: { version?: { deno?: string } } }).Deno?.version?.deno ?? '' }\n return { name: 'node', version: process.versions?.node ?? '' }\n}\n","","import { randomBytes } from 'node:crypto'\nimport os from 'node:os'\nimport process from 'node:process'\nimport { getElapsedMs, isCIEnvironment, runtime } from '@internals/utils'\nimport { getAgentName } from './agent.ts'\nimport { version } from '../package.json'\n\n/** OpenTelemetry ingestion endpoint for anonymous usage telemetry. */\nconst OTLP_ENDPOINT = 'https://otlp.kubb.dev' as const\n\ntype TelemetryCommand = 'generate' | 'mcp' | 'studio' | 'validate'\n\ntype OtlpValue =\n | { stringValue: string }\n | { boolValue: boolean }\n | { intValue: number }\n | { arrayValue: { values: Array<OtlpValue> } }\n | { kvlistValue: { values: Array<OtlpKeyValue> } }\n\ntype OtlpKeyValue = {\n key: string\n value: OtlpValue\n}\n\ntype OtlpSpan = {\n traceId: string\n spanId: string\n name: string\n kind: 1\n startTimeUnixNano: string\n endTimeUnixNano: string\n attributes: Array<OtlpKeyValue>\n status: { code: 1 | 2 }\n}\n\ntype OtlpExportTraceServiceRequest = {\n resourceSpans: Array<{\n resource: { attributes: Array<OtlpKeyValue> }\n scopeSpans: Array<{\n scope: { name: string; version: string }\n spans: Array<OtlpSpan>\n }>\n }>\n}\n\n/**\n * Anonymous plugin name and options snapshot sent with each telemetry event.\n */\nexport type TelemetryPlugin = {\n /**\n * Plugin name as registered in the Kubb config, e.g. `'@kubb/plugin-ts'`.\n */\n name: string\n /**\n * Anonymized snapshot of the plugin options. Values are included but cannot be traced back to a user.\n */\n options: Record<string, unknown>\n}\n\n/**\n * Anonymous snapshot of a single Kubb run, built by {@link buildTelemetryEvent} and sent by {@link sendTelemetry}.\n */\ntype TelemetryEvent = {\n command: string\n kubbVersion: string\n /**\n * Major version of Node that executed the run, e.g. `'22'`.\n */\n nodeVersion: string\n /**\n * Name of the JavaScript runtime that executed the run, `'bun'`, `'deno'`, or `'node'`.\n */\n runtime: string\n /**\n * Major version of the active runtime, e.g. `'1'` under Bun or `'22'` under Node.\n */\n runtimeVersion: string\n platform: string\n ci: boolean\n /**\n * Name of the detected AI coding agent (e.g. `'claude'`, `'cursor'`), when the CLI is invoked\n * by one. `undefined` when run by a human or an unrecognized caller.\n */\n agent?: string\n plugins: Array<TelemetryPlugin>\n duration: number\n filesCreated: number\n status: 'success' | 'failed'\n}\n\n/**\n * Returns `true` when telemetry is disabled via `DO_NOT_TRACK` or `KUBB_DISABLE_TELEMETRY`.\n */\nexport function isDisabled(): boolean {\n return ['DO_NOT_TRACK', 'KUBB_DISABLE_TELEMETRY'].some((name) => ['1', 'true'].includes(process.env[name] ?? ''))\n}\n\n/**\n * Build an anonymous telemetry payload from a completed generation run.\n */\nexport function buildTelemetryEvent(options: {\n command: TelemetryCommand\n kubbVersion: string\n plugins?: Array<TelemetryPlugin>\n hrStart: [number, number]\n filesCreated?: number\n status: 'success' | 'failed'\n}): TelemetryEvent {\n const duration = Math.round(getElapsedMs(options.hrStart))\n\n return {\n command: options.command,\n kubbVersion: options.kubbVersion,\n nodeVersion: process.versions.node.split('.')[0] as string,\n runtime: runtime.name,\n runtimeVersion: runtime.version.split('.')[0] as string,\n platform: os.platform(),\n ci: isCIEnvironment(),\n agent: getAgentName(),\n plugins: options.plugins ?? [],\n duration,\n filesCreated: options.filesCreated ?? 0,\n status: options.status,\n }\n}\n\ntype TrackRunOptions = {\n command: TelemetryCommand\n /** `process.hrtime()` snapshot taken when the command started. */\n hrStart: [number, number]\n}\n\ntype RunResult = Pick<TelemetryEvent, 'status'> & Partial<Pick<TelemetryEvent, 'plugins' | 'filesCreated'>>\n\n/** Tracks one command run for the running CLI version; returns the reporter the command calls once it knows how it ended. */\nexport function trackRun({ command, hrStart }: TrackRunOptions): (result: RunResult) => Promise<void> {\n return (result) => sendTelemetry(buildTelemetryEvent({ command, kubbVersion: version, hrStart, ...result }))\n}\n\n/**\n * Convert a {@link TelemetryEvent} into an OTLP-compatible JSON trace payload.\n *\n * @see https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/\n */\nexport function buildOtlpPayload(event: TelemetryEvent): OtlpExportTraceServiceRequest {\n const traceId = randomBytes(16).toString('hex')\n const spanId = randomBytes(8).toString('hex')\n const endTimeNs = BigInt(Date.now()) * 1_000_000n\n const startTimeNs = endTimeNs - BigInt(event.duration) * 1_000_000n\n const pluginNames = [...new Set(event.plugins.map((plugin) => plugin.name))].sort()\n\n const attributes: Array<OtlpKeyValue> = [\n { key: 'kubb.command', value: { stringValue: event.command } },\n { key: 'kubb.version', value: { stringValue: event.kubbVersion } },\n { key: 'kubb.node_version', value: { stringValue: event.nodeVersion } },\n { key: 'kubb.runtime', value: { stringValue: event.runtime } },\n { key: 'kubb.runtime_version', value: { stringValue: event.runtimeVersion } },\n { key: 'kubb.platform', value: { stringValue: event.platform } },\n { key: 'kubb.ci', value: { boolValue: event.ci } },\n ...(event.agent ? [{ key: 'kubb.agent', value: { stringValue: event.agent } }] : []),\n { key: 'kubb.files_created', value: { intValue: event.filesCreated } },\n { key: 'kubb.status', value: { stringValue: event.status } },\n {\n key: 'kubb.plugins',\n value: { arrayValue: { values: pluginNames.map((name) => ({ stringValue: name })) } },\n },\n ...pluginNames.map((name) => ({ key: `kubb.plugin.${name}`, value: { boolValue: true } })),\n {\n key: 'kubb.plugin_options',\n value: {\n arrayValue: {\n values: event.plugins.map((p) => ({\n kvlistValue: {\n values: [\n { key: 'name', value: { stringValue: p.name } },\n {\n key: 'options',\n value: {\n stringValue: JSON.stringify({\n ...p.options,\n usedEnumNames: undefined,\n }),\n },\n },\n ],\n },\n })),\n },\n },\n },\n ]\n\n return {\n resourceSpans: [\n {\n resource: {\n attributes: [\n { key: 'service.name', value: { stringValue: 'kubb' } },\n {\n key: 'service.version',\n value: { stringValue: event.kubbVersion },\n },\n { key: 'telemetry.sdk.language', value: { stringValue: 'nodejs' } },\n ],\n },\n scopeSpans: [\n {\n scope: { name: 'kubb-core', version: event.kubbVersion },\n spans: [\n {\n traceId,\n spanId,\n name: event.command,\n kind: 1,\n startTimeUnixNano: String(startTimeNs),\n endTimeUnixNano: String(endTimeNs),\n attributes,\n status: {\n code: event.status === 'success' ? 1 : 2,\n },\n },\n ],\n },\n ],\n },\n ],\n }\n}\n\n/**\n * Send an anonymous telemetry event to the Kubb OTLP endpoint. Respects `DO_NOT_TRACK` and\n * `KUBB_DISABLE_TELEMETRY`, and fails silently so telemetry never interrupts a run. No file\n * paths, OpenAPI specs, or secrets are sent.\n */\nexport async function sendTelemetry(event: TelemetryEvent): Promise<void> {\n if (isDisabled()) {\n return\n }\n\n try {\n await fetch(`${OTLP_ENDPOINT}/v1/traces`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Kubb-Telemetry-Version': '1',\n 'Kubb-Telemetry-Source': 'kubb-cli',\n },\n body: JSON.stringify(buildOtlpPayload(event)),\n signal: AbortSignal.timeout(5_000),\n })\n } catch (_e) {\n // Fail silently, telemetry must never break the run\n }\n}\n"],"mappings":"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"}
@@ -34,7 +34,7 @@ function detect() {
34
34
  }
35
35
  //#endregion
36
36
  //#region package.json
37
- var version = "5.9.2";
37
+ var version = "5.9.3";
38
38
  //#endregion
39
39
  //#region src/Telemetry.ts
40
40
  /** OpenTelemetry ingestion endpoint for anonymous usage telemetry. */
@@ -204,4 +204,4 @@ async function sendTelemetry(event) {
204
204
  //#endregion
205
205
  export { runtime as i, trackRun as n, version as r, isDisabled as t };
206
206
 
207
- //# sourceMappingURL=Telemetry-DER8LIO5.js.map
207
+ //# sourceMappingURL=Telemetry-CSc7OVsv.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Telemetry-DER8LIO5.js","names":["process"],"sources":["../../../internals/utils/src/runtime.ts","../package.json","../src/Telemetry.ts"],"sourcesContent":["// Bun polyfills `process.versions.node`, so detection keys off the globals instead.\nconst isBun = typeof Bun !== 'undefined'\nconst isDeno = 'Deno' in globalThis\n\n/**\n * The JavaScript runtime executing the current process: its name, version and whether it is Bun.\n *\n * @example\n * ```ts\n * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise\n * ```\n */\nexport const runtime = { isBun, ...detect() } as const\n\nfunction detect(): { name: 'bun' | 'deno' | 'node'; version: string } {\n if (isBun) return { name: 'bun', version: process.versions.bun ?? '' }\n if (isDeno) return { name: 'deno', version: (globalThis as { Deno?: { version?: { deno?: string } } }).Deno?.version?.deno ?? '' }\n return { name: 'node', version: process.versions?.node ?? '' }\n}\n","","import { randomBytes } from 'node:crypto'\nimport os from 'node:os'\nimport process from 'node:process'\nimport { getElapsedMs, isCIEnvironment, runtime } from '@internals/utils'\nimport { getAgentName } from './agent.ts'\nimport { version } from '../package.json'\n\n/** OpenTelemetry ingestion endpoint for anonymous usage telemetry. */\nconst OTLP_ENDPOINT = 'https://otlp.kubb.dev' as const\n\ntype TelemetryCommand = 'generate' | 'mcp' | 'studio' | 'validate'\n\ntype OtlpValue =\n | { stringValue: string }\n | { boolValue: boolean }\n | { intValue: number }\n | { arrayValue: { values: Array<OtlpValue> } }\n | { kvlistValue: { values: Array<OtlpKeyValue> } }\n\ntype OtlpKeyValue = {\n key: string\n value: OtlpValue\n}\n\ntype OtlpSpan = {\n traceId: string\n spanId: string\n name: string\n kind: 1\n startTimeUnixNano: string\n endTimeUnixNano: string\n attributes: Array<OtlpKeyValue>\n status: { code: 1 | 2 }\n}\n\ntype OtlpExportTraceServiceRequest = {\n resourceSpans: Array<{\n resource: { attributes: Array<OtlpKeyValue> }\n scopeSpans: Array<{\n scope: { name: string; version: string }\n spans: Array<OtlpSpan>\n }>\n }>\n}\n\n/**\n * Anonymous plugin name and options snapshot sent with each telemetry event.\n */\nexport type TelemetryPlugin = {\n /**\n * Plugin name as registered in the Kubb config, e.g. `'@kubb/plugin-ts'`.\n */\n name: string\n /**\n * Anonymized snapshot of the plugin options. Values are included but cannot be traced back to a user.\n */\n options: Record<string, unknown>\n}\n\n/**\n * Anonymous snapshot of a single Kubb run, built by {@link buildTelemetryEvent} and sent by {@link sendTelemetry}.\n */\ntype TelemetryEvent = {\n command: string\n kubbVersion: string\n /**\n * Major version of Node that executed the run, e.g. `'22'`.\n */\n nodeVersion: string\n /**\n * Name of the JavaScript runtime that executed the run, `'bun'`, `'deno'`, or `'node'`.\n */\n runtime: string\n /**\n * Major version of the active runtime, e.g. `'1'` under Bun or `'22'` under Node.\n */\n runtimeVersion: string\n platform: string\n ci: boolean\n /**\n * Name of the detected AI coding agent (e.g. `'claude'`, `'cursor'`), when the CLI is invoked\n * by one. `undefined` when run by a human or an unrecognized caller.\n */\n agent?: string\n plugins: Array<TelemetryPlugin>\n duration: number\n filesCreated: number\n status: 'success' | 'failed'\n}\n\n/**\n * Returns `true` when telemetry is disabled via `DO_NOT_TRACK` or `KUBB_DISABLE_TELEMETRY`.\n */\nexport function isDisabled(): boolean {\n return ['DO_NOT_TRACK', 'KUBB_DISABLE_TELEMETRY'].some((name) => ['1', 'true'].includes(process.env[name] ?? ''))\n}\n\n/**\n * Build an anonymous telemetry payload from a completed generation run.\n */\nexport function buildTelemetryEvent(options: {\n command: TelemetryCommand\n kubbVersion: string\n plugins?: Array<TelemetryPlugin>\n hrStart: [number, number]\n filesCreated?: number\n status: 'success' | 'failed'\n}): TelemetryEvent {\n const duration = Math.round(getElapsedMs(options.hrStart))\n\n return {\n command: options.command,\n kubbVersion: options.kubbVersion,\n nodeVersion: process.versions.node.split('.')[0] as string,\n runtime: runtime.name,\n runtimeVersion: runtime.version.split('.')[0] as string,\n platform: os.platform(),\n ci: isCIEnvironment(),\n agent: getAgentName(),\n plugins: options.plugins ?? [],\n duration,\n filesCreated: options.filesCreated ?? 0,\n status: options.status,\n }\n}\n\ntype TrackRunOptions = {\n command: TelemetryCommand\n /** `process.hrtime()` snapshot taken when the command started. */\n hrStart: [number, number]\n}\n\ntype RunResult = Pick<TelemetryEvent, 'status'> & Partial<Pick<TelemetryEvent, 'plugins' | 'filesCreated'>>\n\n/** Tracks one command run for the running CLI version; returns the reporter the command calls once it knows how it ended. */\nexport function trackRun({ command, hrStart }: TrackRunOptions): (result: RunResult) => Promise<void> {\n return (result) => sendTelemetry(buildTelemetryEvent({ command, kubbVersion: version, hrStart, ...result }))\n}\n\n/**\n * Convert a {@link TelemetryEvent} into an OTLP-compatible JSON trace payload.\n *\n * @see https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/\n */\nexport function buildOtlpPayload(event: TelemetryEvent): OtlpExportTraceServiceRequest {\n const traceId = randomBytes(16).toString('hex')\n const spanId = randomBytes(8).toString('hex')\n const endTimeNs = BigInt(Date.now()) * 1_000_000n\n const startTimeNs = endTimeNs - BigInt(event.duration) * 1_000_000n\n const pluginNames = [...new Set(event.plugins.map((plugin) => plugin.name))].sort()\n\n const attributes: Array<OtlpKeyValue> = [\n { key: 'kubb.command', value: { stringValue: event.command } },\n { key: 'kubb.version', value: { stringValue: event.kubbVersion } },\n { key: 'kubb.node_version', value: { stringValue: event.nodeVersion } },\n { key: 'kubb.runtime', value: { stringValue: event.runtime } },\n { key: 'kubb.runtime_version', value: { stringValue: event.runtimeVersion } },\n { key: 'kubb.platform', value: { stringValue: event.platform } },\n { key: 'kubb.ci', value: { boolValue: event.ci } },\n ...(event.agent ? [{ key: 'kubb.agent', value: { stringValue: event.agent } }] : []),\n { key: 'kubb.files_created', value: { intValue: event.filesCreated } },\n { key: 'kubb.status', value: { stringValue: event.status } },\n {\n key: 'kubb.plugins',\n value: { arrayValue: { values: pluginNames.map((name) => ({ stringValue: name })) } },\n },\n ...pluginNames.map((name) => ({ key: `kubb.plugin.${name}`, value: { boolValue: true } })),\n {\n key: 'kubb.plugin_options',\n value: {\n arrayValue: {\n values: event.plugins.map((p) => ({\n kvlistValue: {\n values: [\n { key: 'name', value: { stringValue: p.name } },\n {\n key: 'options',\n value: {\n stringValue: JSON.stringify({\n ...p.options,\n usedEnumNames: undefined,\n }),\n },\n },\n ],\n },\n })),\n },\n },\n },\n ]\n\n return {\n resourceSpans: [\n {\n resource: {\n attributes: [\n { key: 'service.name', value: { stringValue: 'kubb' } },\n {\n key: 'service.version',\n value: { stringValue: event.kubbVersion },\n },\n { key: 'telemetry.sdk.language', value: { stringValue: 'nodejs' } },\n ],\n },\n scopeSpans: [\n {\n scope: { name: 'kubb-core', version: event.kubbVersion },\n spans: [\n {\n traceId,\n spanId,\n name: event.command,\n kind: 1,\n startTimeUnixNano: String(startTimeNs),\n endTimeUnixNano: String(endTimeNs),\n attributes,\n status: {\n code: event.status === 'success' ? 1 : 2,\n },\n },\n ],\n },\n ],\n },\n ],\n }\n}\n\n/**\n * Send an anonymous telemetry event to the Kubb OTLP endpoint. Respects `DO_NOT_TRACK` and\n * `KUBB_DISABLE_TELEMETRY`, and fails silently so telemetry never interrupts a run. No file\n * paths, OpenAPI specs, or secrets are sent.\n */\nexport async function sendTelemetry(event: TelemetryEvent): Promise<void> {\n if (isDisabled()) {\n return\n }\n\n try {\n await fetch(`${OTLP_ENDPOINT}/v1/traces`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Kubb-Telemetry-Version': '1',\n 'Kubb-Telemetry-Source': 'kubb-cli',\n },\n body: JSON.stringify(buildOtlpPayload(event)),\n signal: AbortSignal.timeout(5_000),\n })\n } catch (_e) {\n // Fail silently, telemetry must never break the run\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Telemetry-CSc7OVsv.js","names":["process"],"sources":["../../../internals/utils/src/runtime.ts","../package.json","../src/Telemetry.ts"],"sourcesContent":["// Bun polyfills `process.versions.node`, so detection keys off the globals instead.\nconst isBun = typeof Bun !== 'undefined'\nconst isDeno = 'Deno' in globalThis\n\n/**\n * The JavaScript runtime executing the current process: its name, version and whether it is Bun.\n *\n * @example\n * ```ts\n * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise\n * ```\n */\nexport const runtime = { isBun, ...detect() } as const\n\nfunction detect(): { name: 'bun' | 'deno' | 'node'; version: string } {\n if (isBun) return { name: 'bun', version: process.versions.bun ?? '' }\n if (isDeno) return { name: 'deno', version: (globalThis as { Deno?: { version?: { deno?: string } } }).Deno?.version?.deno ?? '' }\n return { name: 'node', version: process.versions?.node ?? '' }\n}\n","","import { randomBytes } from 'node:crypto'\nimport os from 'node:os'\nimport process from 'node:process'\nimport { getElapsedMs, isCIEnvironment, runtime } from '@internals/utils'\nimport { getAgentName } from './agent.ts'\nimport { version } from '../package.json'\n\n/** OpenTelemetry ingestion endpoint for anonymous usage telemetry. */\nconst OTLP_ENDPOINT = 'https://otlp.kubb.dev' as const\n\ntype TelemetryCommand = 'generate' | 'mcp' | 'studio' | 'validate'\n\ntype OtlpValue =\n | { stringValue: string }\n | { boolValue: boolean }\n | { intValue: number }\n | { arrayValue: { values: Array<OtlpValue> } }\n | { kvlistValue: { values: Array<OtlpKeyValue> } }\n\ntype OtlpKeyValue = {\n key: string\n value: OtlpValue\n}\n\ntype OtlpSpan = {\n traceId: string\n spanId: string\n name: string\n kind: 1\n startTimeUnixNano: string\n endTimeUnixNano: string\n attributes: Array<OtlpKeyValue>\n status: { code: 1 | 2 }\n}\n\ntype OtlpExportTraceServiceRequest = {\n resourceSpans: Array<{\n resource: { attributes: Array<OtlpKeyValue> }\n scopeSpans: Array<{\n scope: { name: string; version: string }\n spans: Array<OtlpSpan>\n }>\n }>\n}\n\n/**\n * Anonymous plugin name and options snapshot sent with each telemetry event.\n */\nexport type TelemetryPlugin = {\n /**\n * Plugin name as registered in the Kubb config, e.g. `'@kubb/plugin-ts'`.\n */\n name: string\n /**\n * Anonymized snapshot of the plugin options. Values are included but cannot be traced back to a user.\n */\n options: Record<string, unknown>\n}\n\n/**\n * Anonymous snapshot of a single Kubb run, built by {@link buildTelemetryEvent} and sent by {@link sendTelemetry}.\n */\ntype TelemetryEvent = {\n command: string\n kubbVersion: string\n /**\n * Major version of Node that executed the run, e.g. `'22'`.\n */\n nodeVersion: string\n /**\n * Name of the JavaScript runtime that executed the run, `'bun'`, `'deno'`, or `'node'`.\n */\n runtime: string\n /**\n * Major version of the active runtime, e.g. `'1'` under Bun or `'22'` under Node.\n */\n runtimeVersion: string\n platform: string\n ci: boolean\n /**\n * Name of the detected AI coding agent (e.g. `'claude'`, `'cursor'`), when the CLI is invoked\n * by one. `undefined` when run by a human or an unrecognized caller.\n */\n agent?: string\n plugins: Array<TelemetryPlugin>\n duration: number\n filesCreated: number\n status: 'success' | 'failed'\n}\n\n/**\n * Returns `true` when telemetry is disabled via `DO_NOT_TRACK` or `KUBB_DISABLE_TELEMETRY`.\n */\nexport function isDisabled(): boolean {\n return ['DO_NOT_TRACK', 'KUBB_DISABLE_TELEMETRY'].some((name) => ['1', 'true'].includes(process.env[name] ?? ''))\n}\n\n/**\n * Build an anonymous telemetry payload from a completed generation run.\n */\nexport function buildTelemetryEvent(options: {\n command: TelemetryCommand\n kubbVersion: string\n plugins?: Array<TelemetryPlugin>\n hrStart: [number, number]\n filesCreated?: number\n status: 'success' | 'failed'\n}): TelemetryEvent {\n const duration = Math.round(getElapsedMs(options.hrStart))\n\n return {\n command: options.command,\n kubbVersion: options.kubbVersion,\n nodeVersion: process.versions.node.split('.')[0] as string,\n runtime: runtime.name,\n runtimeVersion: runtime.version.split('.')[0] as string,\n platform: os.platform(),\n ci: isCIEnvironment(),\n agent: getAgentName(),\n plugins: options.plugins ?? [],\n duration,\n filesCreated: options.filesCreated ?? 0,\n status: options.status,\n }\n}\n\ntype TrackRunOptions = {\n command: TelemetryCommand\n /** `process.hrtime()` snapshot taken when the command started. */\n hrStart: [number, number]\n}\n\ntype RunResult = Pick<TelemetryEvent, 'status'> & Partial<Pick<TelemetryEvent, 'plugins' | 'filesCreated'>>\n\n/** Tracks one command run for the running CLI version; returns the reporter the command calls once it knows how it ended. */\nexport function trackRun({ command, hrStart }: TrackRunOptions): (result: RunResult) => Promise<void> {\n return (result) => sendTelemetry(buildTelemetryEvent({ command, kubbVersion: version, hrStart, ...result }))\n}\n\n/**\n * Convert a {@link TelemetryEvent} into an OTLP-compatible JSON trace payload.\n *\n * @see https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/\n */\nexport function buildOtlpPayload(event: TelemetryEvent): OtlpExportTraceServiceRequest {\n const traceId = randomBytes(16).toString('hex')\n const spanId = randomBytes(8).toString('hex')\n const endTimeNs = BigInt(Date.now()) * 1_000_000n\n const startTimeNs = endTimeNs - BigInt(event.duration) * 1_000_000n\n const pluginNames = [...new Set(event.plugins.map((plugin) => plugin.name))].sort()\n\n const attributes: Array<OtlpKeyValue> = [\n { key: 'kubb.command', value: { stringValue: event.command } },\n { key: 'kubb.version', value: { stringValue: event.kubbVersion } },\n { key: 'kubb.node_version', value: { stringValue: event.nodeVersion } },\n { key: 'kubb.runtime', value: { stringValue: event.runtime } },\n { key: 'kubb.runtime_version', value: { stringValue: event.runtimeVersion } },\n { key: 'kubb.platform', value: { stringValue: event.platform } },\n { key: 'kubb.ci', value: { boolValue: event.ci } },\n ...(event.agent ? [{ key: 'kubb.agent', value: { stringValue: event.agent } }] : []),\n { key: 'kubb.files_created', value: { intValue: event.filesCreated } },\n { key: 'kubb.status', value: { stringValue: event.status } },\n {\n key: 'kubb.plugins',\n value: { arrayValue: { values: pluginNames.map((name) => ({ stringValue: name })) } },\n },\n ...pluginNames.map((name) => ({ key: `kubb.plugin.${name}`, value: { boolValue: true } })),\n {\n key: 'kubb.plugin_options',\n value: {\n arrayValue: {\n values: event.plugins.map((p) => ({\n kvlistValue: {\n values: [\n { key: 'name', value: { stringValue: p.name } },\n {\n key: 'options',\n value: {\n stringValue: JSON.stringify({\n ...p.options,\n usedEnumNames: undefined,\n }),\n },\n },\n ],\n },\n })),\n },\n },\n },\n ]\n\n return {\n resourceSpans: [\n {\n resource: {\n attributes: [\n { key: 'service.name', value: { stringValue: 'kubb' } },\n {\n key: 'service.version',\n value: { stringValue: event.kubbVersion },\n },\n { key: 'telemetry.sdk.language', value: { stringValue: 'nodejs' } },\n ],\n },\n scopeSpans: [\n {\n scope: { name: 'kubb-core', version: event.kubbVersion },\n spans: [\n {\n traceId,\n spanId,\n name: event.command,\n kind: 1,\n startTimeUnixNano: String(startTimeNs),\n endTimeUnixNano: String(endTimeNs),\n attributes,\n status: {\n code: event.status === 'success' ? 1 : 2,\n },\n },\n ],\n },\n ],\n },\n ],\n }\n}\n\n/**\n * Send an anonymous telemetry event to the Kubb OTLP endpoint. Respects `DO_NOT_TRACK` and\n * `KUBB_DISABLE_TELEMETRY`, and fails silently so telemetry never interrupts a run. No file\n * paths, OpenAPI specs, or secrets are sent.\n */\nexport async function sendTelemetry(event: TelemetryEvent): Promise<void> {\n if (isDisabled()) {\n return\n }\n\n try {\n await fetch(`${OTLP_ENDPOINT}/v1/traces`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Kubb-Telemetry-Version': '1',\n 'Kubb-Telemetry-Source': 'kubb-cli',\n },\n body: JSON.stringify(buildOtlpPayload(event)),\n signal: AbortSignal.timeout(5_000),\n })\n } catch (_e) {\n // Fail silently, telemetry must never break the run\n }\n}\n"],"mappings":";;;;;;AACA,MAAM,QAAQ,OAAO,QAAQ;AAC7B,MAAM,SAAS,UAAU;;;;;;;;;AAUzB,MAAa,UAAU;CAAE;CAAO,GAAG,OAAO;AAAE;AAE5C,SAAS,SAA6D;CACpE,IAAI,OAAO,OAAO;EAAE,MAAM;EAAO,SAAS,QAAQ,SAAS,OAAO;CAAG;CACrE,IAAI,QAAQ,OAAO;EAAE,MAAM;EAAQ,SAAU,WAA0D,MAAM,SAAS,QAAQ;CAAG;CACjI,OAAO;EAAE,MAAM;EAAQ,SAAS,QAAQ,UAAU,QAAQ;CAAG;AAC/D;;;;;;;AEVA,MAAM,gBAAgB;;;;AAqFtB,SAAgB,aAAsB;CACpC,OAAO,CAAC,gBAAgB,wBAAwB,CAAC,CAAC,MAAM,SAAS,CAAC,KAAK,MAAM,CAAC,CAAC,SAASA,UAAQ,IAAI,SAAS,EAAE,CAAC;AAClH;;;;AAKA,SAAgB,oBAAoB,SAOjB;CACjB,MAAM,WAAW,KAAK,MAAM,aAAa,QAAQ,OAAO,CAAC;CAEzD,OAAO;EACL,SAAS,QAAQ;EACjB,aAAa,QAAQ;EACrB,aAAaA,UAAQ,SAAS,KAAK,MAAM,GAAG,CAAC,CAAC;EAC9C,SAAS,QAAQ;EACjB,gBAAgB,QAAQ,QAAQ,MAAM,GAAG,CAAC,CAAC;EAC3C,UAAU,GAAG,SAAS;EACtB,IAAI,gBAAgB;EACpB,OAAO,aAAa;EACpB,SAAS,QAAQ,WAAW,CAAC;EAC7B;EACA,cAAc,QAAQ,gBAAgB;EACtC,QAAQ,QAAQ;CAClB;AACF;;AAWA,SAAgB,SAAS,EAAE,SAAS,WAAkE;CACpG,QAAQ,WAAW,cAAc,oBAAoB;EAAE;EAAS,aAAa;EAAS;EAAS,GAAG;CAAO,CAAC,CAAC;AAC7G;;;;;;AAOA,SAAgB,iBAAiB,OAAsD;CACrF,MAAM,UAAU,YAAY,EAAE,CAAC,CAAC,SAAS,KAAK;CAC9C,MAAM,SAAS,YAAY,CAAC,CAAC,CAAC,SAAS,KAAK;CAC5C,MAAM,YAAY,OAAO,KAAK,IAAI,CAAC,IAAI;CACvC,MAAM,cAAc,YAAY,OAAO,MAAM,QAAQ,IAAI;CACzD,MAAM,cAAc,CAAC,GAAG,IAAI,IAAI,MAAM,QAAQ,KAAK,WAAW,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK;CAElF,MAAM,aAAkC;EACtC;GAAE,KAAK;GAAgB,OAAO,EAAE,aAAa,MAAM,QAAQ;EAAE;EAC7D;GAAE,KAAK;GAAgB,OAAO,EAAE,aAAa,MAAM,YAAY;EAAE;EACjE;GAAE,KAAK;GAAqB,OAAO,EAAE,aAAa,MAAM,YAAY;EAAE;EACtE;GAAE,KAAK;GAAgB,OAAO,EAAE,aAAa,MAAM,QAAQ;EAAE;EAC7D;GAAE,KAAK;GAAwB,OAAO,EAAE,aAAa,MAAM,eAAe;EAAE;EAC5E;GAAE,KAAK;GAAiB,OAAO,EAAE,aAAa,MAAM,SAAS;EAAE;EAC/D;GAAE,KAAK;GAAW,OAAO,EAAE,WAAW,MAAM,GAAG;EAAE;EACjD,GAAI,MAAM,QAAQ,CAAC;GAAE,KAAK;GAAc,OAAO,EAAE,aAAa,MAAM,MAAM;EAAE,CAAC,IAAI,CAAC;EAClF;GAAE,KAAK;GAAsB,OAAO,EAAE,UAAU,MAAM,aAAa;EAAE;EACrE;GAAE,KAAK;GAAe,OAAO,EAAE,aAAa,MAAM,OAAO;EAAE;EAC3D;GACE,KAAK;GACL,OAAO,EAAE,YAAY,EAAE,QAAQ,YAAY,KAAK,UAAU,EAAE,aAAa,KAAK,EAAE,EAAE,EAAE;EACtF;EACA,GAAG,YAAY,KAAK,UAAU;GAAE,KAAK,eAAe;GAAQ,OAAO,EAAE,WAAW,KAAK;EAAE,EAAE;EACzF;GACE,KAAK;GACL,OAAO,EACL,YAAY,EACV,QAAQ,MAAM,QAAQ,KAAK,OAAO,EAChC,aAAa,EACX,QAAQ,CACN;IAAE,KAAK;IAAQ,OAAO,EAAE,aAAa,EAAE,KAAK;GAAE,GAC9C;IACE,KAAK;IACL,OAAO,EACL,aAAa,KAAK,UAAU;KAC1B,GAAG,EAAE;KACL,eAAe,KAAA;IACjB,CAAC,EACH;GACF,CACF,EACF,EACF,EAAE,EACJ,EACF;EACF;CACF;CAEA,OAAO,EACL,eAAe,CACb;EACE,UAAU,EACR,YAAY;GACV;IAAE,KAAK;IAAgB,OAAO,EAAE,aAAa,OAAO;GAAE;GACtD;IACE,KAAK;IACL,OAAO,EAAE,aAAa,MAAM,YAAY;GAC1C;GACA;IAAE,KAAK;IAA0B,OAAO,EAAE,aAAa,SAAS;GAAE;EACpE,EACF;EACA,YAAY,CACV;GACE,OAAO;IAAE,MAAM;IAAa,SAAS,MAAM;GAAY;GACvD,OAAO,CACL;IACE;IACA;IACA,MAAM,MAAM;IACZ,MAAM;IACN,mBAAmB,OAAO,WAAW;IACrC,iBAAiB,OAAO,SAAS;IACjC;IACA,QAAQ,EACN,MAAM,MAAM,WAAW,YAAY,IAAI,EACzC;GACF,CACF;EACF,CACF;CACF,CACF,EACF;AACF;;;;;;AAOA,eAAsB,cAAc,OAAsC;CACxE,IAAI,WAAW,GACb;CAGF,IAAI;EACF,MAAM,MAAM,GAAG,cAAc,aAAa;GACxC,QAAQ;GACR,SAAS;IACP,gBAAgB;IAChB,0BAA0B;IAC1B,yBAAyB;GAC3B;GACA,MAAM,KAAK,UAAU,iBAAiB,KAAK,CAAC;GAC5C,QAAQ,YAAY,QAAQ,GAAK;EACnC,CAAC;CACH,SAAS,IAAI,CAEb;AACF"}
@@ -0,0 +1 @@
1
+ export { n as getWorkerStatus } from "./background-CCex47-d.js";
@@ -1,5 +1,5 @@
1
1
  const require_agent = require("./agent-DElUuYuy.cjs");
2
- const require_run = require("./run-C8dyBAPb.cjs");
2
+ const require_run = require("./run-DxGkjzRm.cjs");
3
3
  require("node:crypto");
4
4
  let tinyexec = require("tinyexec");
5
5
  let node_fs_promises = require("node:fs/promises");
@@ -169,4 +169,4 @@ exports.getWorkerStatus = getWorkerStatus;
169
169
  exports.startWorker = startWorker;
170
170
  exports.stopWorker = stopWorker;
171
171
 
172
- //# sourceMappingURL=background-Bh4FDWa3.cjs.map
172
+ //# sourceMappingURL=background-BcRoKru0.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"background-Bh4FDWa3.cjs","names":["path","getProjectKubbHome","readFile","connectSocket","delay","prepareConnection","createRequire","x"],"sources":["../src/runners/studio/background.ts"],"sourcesContent":["import { hash, randomBytes } from 'node:crypto'\nimport { readFile, rename, writeFile } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport { connect as connectSocket, createServer } from 'node:net'\nimport path from 'node:path'\nimport { setTimeout as delay } from 'node:timers/promises'\nimport { x } from 'tinyexec'\nimport { getProjectKubbHome } from './credentials.ts'\nimport { prepareConnection, type PreparedConnection, type StudioOptions, type WorkerState } from './run.ts'\n\nexport type WorkerRecord = { id: string; pid: number; port: number; state: WorkerState }\nconst states: Array<WorkerState> = ['starting', 'connected', 'reconnecting', 'authentication required', 'stopped']\nexport const getWorkerLogPath = () => path.join(getProjectKubbHome(), 'worker.log')\nconst statePath = () => path.join(getProjectKubbHome(), 'worker.json')\n\nasync function readWorker(): Promise<WorkerRecord | null> {\n try {\n const value: unknown = JSON.parse(await readFile(statePath(), 'utf8'))\n if (!value || typeof value !== 'object') return null\n const record = value as Partial<WorkerRecord>\n return typeof record.id === 'string' &&\n /^[a-f0-9]{32}$/.test(record.id) &&\n Number.isInteger(record.pid) &&\n (record.pid ?? 0) > 1 &&\n Number.isInteger(record.port) &&\n (record.port ?? 0) > 0 &&\n (record.port ?? 0) <= 65535 &&\n states.includes(record.state as WorkerState)\n ? (record as WorkerRecord)\n : null\n } catch {\n return null\n }\n}\n\nfunction isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch (error) {\n return (error as NodeJS.ErrnoException).code === 'EPERM'\n }\n}\n\n/** Authenticated loopback IPC; a stored PID never authorizes sending a process signal. */\nfunction requestWorker(record: WorkerRecord, command: 'status' | 'stop'): Promise<WorkerRecord> {\n return new Promise((resolve, reject) => {\n const socket = connectSocket({ host: '127.0.0.1', port: record.port })\n let received = ''\n socket.setTimeout(2_000, () => socket.destroy(new Error('Worker control timed out')))\n socket.once('error', reject)\n socket.once('connect', () => socket.write(JSON.stringify({ id: record.id, command }) + '\\n'))\n socket.on('data', (chunk: Buffer) => {\n received += chunk.toString()\n if (received.length > 4096) socket.destroy(new Error('Invalid worker response'))\n })\n socket.once('end', () => {\n try {\n const response = JSON.parse(received) as WorkerRecord\n if (response.id !== record.id || response.pid !== record.pid || !states.includes(response.state)) throw new Error('Worker identity changed')\n resolve(response)\n } catch (error) {\n reject(error)\n }\n })\n })\n}\n\nexport async function getWorkerStatus(): Promise<{ running: boolean; state: WorkerState; pid?: number }> {\n const record = await readWorker()\n if (!record) return { running: false, state: 'stopped' }\n try {\n const response = await requestWorker(record, 'status')\n return { running: true, state: response.state, pid: response.pid }\n } catch {\n return { running: false, state: record.state === 'authentication required' ? record.state : 'stopped' }\n }\n}\n\nexport async function stopWorker(): Promise<void> {\n const record = await readWorker()\n if (!record) return\n try {\n await requestWorker(record, 'stop')\n } catch (error) {\n if (\n (error as NodeJS.ErrnoException).code !== 'ECONNREFUSED' &&\n isAlive(record.pid) &&\n record.state !== 'stopped' &&\n record.state !== 'authentication required'\n ) {\n throw new Error('Cannot verify the background worker. No process was signaled.')\n }\n return\n }\n const deadline = Date.now() + 15_000\n while (Date.now() < deadline) {\n try {\n await requestWorker(record, 'status')\n } catch {\n return\n }\n await delay(100)\n }\n throw new Error('The worker has not finished shutting down. Check worker.log and try again.')\n}\n\n/** The listening port is the project lock, so stale state never needs a PID-based takeover. */\nexport async function serveWorker(shutdown: AbortController) {\n const record: WorkerRecord = { id: randomBytes(16).toString('hex'), pid: process.pid, port: 0, state: 'starting' }\n const server = createServer((socket) => {\n let input = ''\n socket.setTimeout(2_000, () => socket.destroy())\n socket.on('error', () => {})\n socket.on('data', (chunk: Buffer) => {\n input += chunk.toString()\n if (input.length > 4096) {\n socket.destroy()\n return\n }\n if (!input.includes('\\n')) return\n try {\n const request = JSON.parse(input) as { id?: unknown; command?: unknown }\n if (request.id !== record.id || !['status', 'stop'].includes(String(request.command))) {\n socket.destroy()\n return\n }\n socket.end(JSON.stringify(record))\n if (request.command === 'stop') shutdown.abort()\n } catch {\n socket.destroy()\n }\n })\n })\n // Hash the project directory to choose its loopback port; fail on collisions.\n const port = 20_000 + (Number.parseInt(hash('sha256', getProjectKubbHome()).slice(0, 8), 16) % 30_000)\n try {\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, '127.0.0.1', resolve)\n })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EADDRINUSE') throw error\n // Let a simultaneous starter finish writing its record before checking ownership.\n await delay(100)\n const existing = await readWorker()\n if (existing?.port === port) {\n try {\n return { existing: await requestWorker(existing, 'status') }\n } catch {\n /* Refuse an unverified listener. */\n }\n }\n throw new Error('The project control port is occupied or another worker is starting. Try again after stopping that listener.')\n }\n record.port = port\n let saving = Promise.resolve()\n const save = () => {\n const value = JSON.stringify(record)\n saving = saving.then(async () => {\n const temporary = `${statePath()}.${record.id}`\n await writeFile(temporary, value, { mode: 0o600 })\n await rename(temporary, statePath())\n })\n return saving\n }\n try {\n await save()\n } catch (error) {\n server.close()\n throw error\n }\n return {\n async state(state: WorkerState) {\n record.state = state\n await save()\n },\n async close() {\n try {\n if (record.state !== 'authentication required') {\n record.state = 'stopped'\n await save()\n }\n } finally {\n await new Promise<void>((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())))\n }\n },\n }\n}\n\nexport type WorkerLaunch = { options: StudioOptions; prepared: PreparedConnection }\n\nexport async function startWorker(options: StudioOptions): Promise<void> {\n const current = await getWorkerStatus()\n if (current.running) {\n console.log(`Already running (${current.state}, PID ${current.pid}).`)\n return\n }\n const prepared = await prepareConnection(options)\n const entry = path.join(path.dirname(createRequire(import.meta.url).resolve('@kubb/cli/package.json')), 'dist', 'studioWorker.js')\n const child = x(process.execPath, [...process.execArgv, entry], {\n nodeOptions: { cwd: process.cwd(), detached: true, stdio: ['ignore', 'ignore', 'ignore', 'ipc'] },\n }).process\n if (!child) throw new Error('Background worker failed to start')\n try {\n const started = new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => done(new Error('Background worker startup timed out')), 20_000)\n const done = (error?: Error) => {\n clearTimeout(timer)\n child.removeListener('error', failed)\n child.removeListener('exit', exited)\n child.removeListener('message', ready)\n if (error) reject(error)\n else resolve()\n }\n const failed = (error: Error) => done(error)\n const exited = () => done(new Error(`Background worker exited during startup. Check ${getWorkerLogPath()}`))\n child.once('error', failed)\n child.once('exit', exited)\n const ready = (message: unknown) => {\n if (!message || typeof message !== 'object' || !('started' in message) || message.started !== true)\n return done(new Error('Invalid worker startup response'))\n done()\n }\n child.once('message', ready)\n child.send({ options: { ...options, autoOpen: false }, prepared } satisfies WorkerLaunch, (error) => {\n if (error) done(error)\n })\n })\n await started\n if (child.connected) child.disconnect()\n child.unref()\n const status = await getWorkerStatus()\n console.log(`Background worker ${status.state} (PID ${status.pid ?? child.pid}). Logs: ${getWorkerLogPath()}`)\n } catch (error) {\n // This is the child we just spawned, not a PID recovered from disk.\n child.kill('SIGTERM')\n throw error\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"background-BcRoKru0.cjs","names":["path","getProjectKubbHome","readFile","connectSocket","delay","prepareConnection","createRequire","x"],"sources":["../src/runners/studio/background.ts"],"sourcesContent":["import { hash, randomBytes } from 'node:crypto'\nimport { readFile, rename, writeFile } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport { connect as connectSocket, createServer } from 'node:net'\nimport path from 'node:path'\nimport { setTimeout as delay } from 'node:timers/promises'\nimport { x } from 'tinyexec'\nimport { getProjectKubbHome } from './credentials.ts'\nimport { prepareConnection, type PreparedConnection, type StudioOptions, type WorkerState } from './run.ts'\n\nexport type WorkerRecord = { id: string; pid: number; port: number; state: WorkerState }\nconst states: Array<WorkerState> = ['starting', 'connected', 'reconnecting', 'authentication required', 'stopped']\nexport const getWorkerLogPath = () => path.join(getProjectKubbHome(), 'worker.log')\nconst statePath = () => path.join(getProjectKubbHome(), 'worker.json')\n\nasync function readWorker(): Promise<WorkerRecord | null> {\n try {\n const value: unknown = JSON.parse(await readFile(statePath(), 'utf8'))\n if (!value || typeof value !== 'object') return null\n const record = value as Partial<WorkerRecord>\n return typeof record.id === 'string' &&\n /^[a-f0-9]{32}$/.test(record.id) &&\n Number.isInteger(record.pid) &&\n (record.pid ?? 0) > 1 &&\n Number.isInteger(record.port) &&\n (record.port ?? 0) > 0 &&\n (record.port ?? 0) <= 65535 &&\n states.includes(record.state as WorkerState)\n ? (record as WorkerRecord)\n : null\n } catch {\n return null\n }\n}\n\nfunction isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch (error) {\n return (error as NodeJS.ErrnoException).code === 'EPERM'\n }\n}\n\n/** Authenticated loopback IPC; a stored PID never authorizes sending a process signal. */\nfunction requestWorker(record: WorkerRecord, command: 'status' | 'stop'): Promise<WorkerRecord> {\n return new Promise((resolve, reject) => {\n const socket = connectSocket({ host: '127.0.0.1', port: record.port })\n let received = ''\n socket.setTimeout(2_000, () => socket.destroy(new Error('Worker control timed out')))\n socket.once('error', reject)\n socket.once('connect', () => socket.write(JSON.stringify({ id: record.id, command }) + '\\n'))\n socket.on('data', (chunk: Buffer) => {\n received += chunk.toString()\n if (received.length > 4096) socket.destroy(new Error('Invalid worker response'))\n })\n socket.once('end', () => {\n try {\n const response = JSON.parse(received) as WorkerRecord\n if (response.id !== record.id || response.pid !== record.pid || !states.includes(response.state)) throw new Error('Worker identity changed')\n resolve(response)\n } catch (error) {\n reject(error)\n }\n })\n })\n}\n\nexport async function getWorkerStatus(): Promise<{ running: boolean; state: WorkerState; pid?: number }> {\n const record = await readWorker()\n if (!record) return { running: false, state: 'stopped' }\n try {\n const response = await requestWorker(record, 'status')\n return { running: true, state: response.state, pid: response.pid }\n } catch {\n return { running: false, state: record.state === 'authentication required' ? record.state : 'stopped' }\n }\n}\n\nexport async function stopWorker(): Promise<void> {\n const record = await readWorker()\n if (!record) return\n try {\n await requestWorker(record, 'stop')\n } catch (error) {\n if (\n (error as NodeJS.ErrnoException).code !== 'ECONNREFUSED' &&\n isAlive(record.pid) &&\n record.state !== 'stopped' &&\n record.state !== 'authentication required'\n ) {\n throw new Error('Cannot verify the background worker. No process was signaled.')\n }\n return\n }\n const deadline = Date.now() + 15_000\n while (Date.now() < deadline) {\n try {\n await requestWorker(record, 'status')\n } catch {\n return\n }\n await delay(100)\n }\n throw new Error('The worker has not finished shutting down. Check worker.log and try again.')\n}\n\n/** The listening port is the project lock, so stale state never needs a PID-based takeover. */\nexport async function serveWorker(shutdown: AbortController) {\n const record: WorkerRecord = { id: randomBytes(16).toString('hex'), pid: process.pid, port: 0, state: 'starting' }\n const server = createServer((socket) => {\n let input = ''\n socket.setTimeout(2_000, () => socket.destroy())\n socket.on('error', () => {})\n socket.on('data', (chunk: Buffer) => {\n input += chunk.toString()\n if (input.length > 4096) {\n socket.destroy()\n return\n }\n if (!input.includes('\\n')) return\n try {\n const request = JSON.parse(input) as { id?: unknown; command?: unknown }\n if (request.id !== record.id || !['status', 'stop'].includes(String(request.command))) {\n socket.destroy()\n return\n }\n socket.end(JSON.stringify(record))\n if (request.command === 'stop') shutdown.abort()\n } catch {\n socket.destroy()\n }\n })\n })\n // Hash the project directory to choose its loopback port; fail on collisions.\n const port = 20_000 + (Number.parseInt(hash('sha256', getProjectKubbHome()).slice(0, 8), 16) % 30_000)\n try {\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, '127.0.0.1', resolve)\n })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EADDRINUSE') throw error\n // Let a simultaneous starter finish writing its record before checking ownership.\n await delay(100)\n const existing = await readWorker()\n if (existing?.port === port) {\n try {\n return { existing: await requestWorker(existing, 'status') }\n } catch {\n /* Refuse an unverified listener. */\n }\n }\n throw new Error('The project control port is occupied or another worker is starting. Try again after stopping that listener.')\n }\n record.port = port\n let saving = Promise.resolve()\n const save = () => {\n const value = JSON.stringify(record)\n saving = saving.then(async () => {\n const temporary = `${statePath()}.${record.id}`\n await writeFile(temporary, value, { mode: 0o600 })\n await rename(temporary, statePath())\n })\n return saving\n }\n try {\n await save()\n } catch (error) {\n server.close()\n throw error\n }\n return {\n async state(state: WorkerState) {\n record.state = state\n await save()\n },\n async close() {\n try {\n if (record.state !== 'authentication required') {\n record.state = 'stopped'\n await save()\n }\n } finally {\n await new Promise<void>((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())))\n }\n },\n }\n}\n\nexport type WorkerLaunch = { options: StudioOptions; prepared: PreparedConnection }\n\nexport async function startWorker(options: StudioOptions): Promise<void> {\n const current = await getWorkerStatus()\n if (current.running) {\n console.log(`Already running (${current.state}, PID ${current.pid}).`)\n return\n }\n const prepared = await prepareConnection(options)\n const entry = path.join(path.dirname(createRequire(import.meta.url).resolve('@kubb/cli/package.json')), 'dist', 'studioWorker.js')\n const child = x(process.execPath, [...process.execArgv, entry], {\n nodeOptions: { cwd: process.cwd(), detached: true, stdio: ['ignore', 'ignore', 'ignore', 'ipc'] },\n }).process\n if (!child) throw new Error('Background worker failed to start')\n try {\n const started = new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => done(new Error('Background worker startup timed out')), 20_000)\n const done = (error?: Error) => {\n clearTimeout(timer)\n child.removeListener('error', failed)\n child.removeListener('exit', exited)\n child.removeListener('message', ready)\n if (error) reject(error)\n else resolve()\n }\n const failed = (error: Error) => done(error)\n const exited = () => done(new Error(`Background worker exited during startup. Check ${getWorkerLogPath()}`))\n child.once('error', failed)\n child.once('exit', exited)\n const ready = (message: unknown) => {\n if (!message || typeof message !== 'object' || !('started' in message) || message.started !== true)\n return done(new Error('Invalid worker startup response'))\n done()\n }\n child.once('message', ready)\n child.send({ options: { ...options, autoOpen: false }, prepared } satisfies WorkerLaunch, (error) => {\n if (error) done(error)\n })\n })\n await started\n if (child.connected) child.disconnect()\n child.unref()\n const status = await getWorkerStatus()\n console.log(`Background worker ${status.state} (PID ${status.pid ?? child.pid}). Logs: ${getWorkerLogPath()}`)\n } catch (error) {\n // This is the child we just spawned, not a PID recovered from disk.\n child.kill('SIGTERM')\n throw error\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { l as getProjectKubbHome, o as prepareConnection } from "./run-BQQhNg8I.js";
2
+ import { l as getProjectKubbHome, o as prepareConnection } from "./run-BRUwQ5Y7.js";
3
3
  import { createRequire } from "node:module";
4
4
  import { hash, randomBytes } from "node:crypto";
5
5
  import { x } from "tinyexec";
@@ -246,4 +246,4 @@ async function startWorker(options) {
246
246
  //#endregion
247
247
  export { stopWorker as a, startWorker as i, getWorkerStatus as n, serveWorker as r, getWorkerLogPath as t };
248
248
 
249
- //# sourceMappingURL=background-B0YbkZ0s.js.map
249
+ //# sourceMappingURL=background-CCex47-d.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"background-B0YbkZ0s.js","names":["connectSocket","delay"],"sources":["../src/runners/studio/background.ts"],"sourcesContent":["import { hash, randomBytes } from 'node:crypto'\nimport { readFile, rename, writeFile } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport { connect as connectSocket, createServer } from 'node:net'\nimport path from 'node:path'\nimport { setTimeout as delay } from 'node:timers/promises'\nimport { x } from 'tinyexec'\nimport { getProjectKubbHome } from './credentials.ts'\nimport { prepareConnection, type PreparedConnection, type StudioOptions, type WorkerState } from './run.ts'\n\nexport type WorkerRecord = { id: string; pid: number; port: number; state: WorkerState }\nconst states: Array<WorkerState> = ['starting', 'connected', 'reconnecting', 'authentication required', 'stopped']\nexport const getWorkerLogPath = () => path.join(getProjectKubbHome(), 'worker.log')\nconst statePath = () => path.join(getProjectKubbHome(), 'worker.json')\n\nasync function readWorker(): Promise<WorkerRecord | null> {\n try {\n const value: unknown = JSON.parse(await readFile(statePath(), 'utf8'))\n if (!value || typeof value !== 'object') return null\n const record = value as Partial<WorkerRecord>\n return typeof record.id === 'string' &&\n /^[a-f0-9]{32}$/.test(record.id) &&\n Number.isInteger(record.pid) &&\n (record.pid ?? 0) > 1 &&\n Number.isInteger(record.port) &&\n (record.port ?? 0) > 0 &&\n (record.port ?? 0) <= 65535 &&\n states.includes(record.state as WorkerState)\n ? (record as WorkerRecord)\n : null\n } catch {\n return null\n }\n}\n\nfunction isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch (error) {\n return (error as NodeJS.ErrnoException).code === 'EPERM'\n }\n}\n\n/** Authenticated loopback IPC; a stored PID never authorizes sending a process signal. */\nfunction requestWorker(record: WorkerRecord, command: 'status' | 'stop'): Promise<WorkerRecord> {\n return new Promise((resolve, reject) => {\n const socket = connectSocket({ host: '127.0.0.1', port: record.port })\n let received = ''\n socket.setTimeout(2_000, () => socket.destroy(new Error('Worker control timed out')))\n socket.once('error', reject)\n socket.once('connect', () => socket.write(JSON.stringify({ id: record.id, command }) + '\\n'))\n socket.on('data', (chunk: Buffer) => {\n received += chunk.toString()\n if (received.length > 4096) socket.destroy(new Error('Invalid worker response'))\n })\n socket.once('end', () => {\n try {\n const response = JSON.parse(received) as WorkerRecord\n if (response.id !== record.id || response.pid !== record.pid || !states.includes(response.state)) throw new Error('Worker identity changed')\n resolve(response)\n } catch (error) {\n reject(error)\n }\n })\n })\n}\n\nexport async function getWorkerStatus(): Promise<{ running: boolean; state: WorkerState; pid?: number }> {\n const record = await readWorker()\n if (!record) return { running: false, state: 'stopped' }\n try {\n const response = await requestWorker(record, 'status')\n return { running: true, state: response.state, pid: response.pid }\n } catch {\n return { running: false, state: record.state === 'authentication required' ? record.state : 'stopped' }\n }\n}\n\nexport async function stopWorker(): Promise<void> {\n const record = await readWorker()\n if (!record) return\n try {\n await requestWorker(record, 'stop')\n } catch (error) {\n if (\n (error as NodeJS.ErrnoException).code !== 'ECONNREFUSED' &&\n isAlive(record.pid) &&\n record.state !== 'stopped' &&\n record.state !== 'authentication required'\n ) {\n throw new Error('Cannot verify the background worker. No process was signaled.')\n }\n return\n }\n const deadline = Date.now() + 15_000\n while (Date.now() < deadline) {\n try {\n await requestWorker(record, 'status')\n } catch {\n return\n }\n await delay(100)\n }\n throw new Error('The worker has not finished shutting down. Check worker.log and try again.')\n}\n\n/** The listening port is the project lock, so stale state never needs a PID-based takeover. */\nexport async function serveWorker(shutdown: AbortController) {\n const record: WorkerRecord = { id: randomBytes(16).toString('hex'), pid: process.pid, port: 0, state: 'starting' }\n const server = createServer((socket) => {\n let input = ''\n socket.setTimeout(2_000, () => socket.destroy())\n socket.on('error', () => {})\n socket.on('data', (chunk: Buffer) => {\n input += chunk.toString()\n if (input.length > 4096) {\n socket.destroy()\n return\n }\n if (!input.includes('\\n')) return\n try {\n const request = JSON.parse(input) as { id?: unknown; command?: unknown }\n if (request.id !== record.id || !['status', 'stop'].includes(String(request.command))) {\n socket.destroy()\n return\n }\n socket.end(JSON.stringify(record))\n if (request.command === 'stop') shutdown.abort()\n } catch {\n socket.destroy()\n }\n })\n })\n // Hash the project directory to choose its loopback port; fail on collisions.\n const port = 20_000 + (Number.parseInt(hash('sha256', getProjectKubbHome()).slice(0, 8), 16) % 30_000)\n try {\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, '127.0.0.1', resolve)\n })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EADDRINUSE') throw error\n // Let a simultaneous starter finish writing its record before checking ownership.\n await delay(100)\n const existing = await readWorker()\n if (existing?.port === port) {\n try {\n return { existing: await requestWorker(existing, 'status') }\n } catch {\n /* Refuse an unverified listener. */\n }\n }\n throw new Error('The project control port is occupied or another worker is starting. Try again after stopping that listener.')\n }\n record.port = port\n let saving = Promise.resolve()\n const save = () => {\n const value = JSON.stringify(record)\n saving = saving.then(async () => {\n const temporary = `${statePath()}.${record.id}`\n await writeFile(temporary, value, { mode: 0o600 })\n await rename(temporary, statePath())\n })\n return saving\n }\n try {\n await save()\n } catch (error) {\n server.close()\n throw error\n }\n return {\n async state(state: WorkerState) {\n record.state = state\n await save()\n },\n async close() {\n try {\n if (record.state !== 'authentication required') {\n record.state = 'stopped'\n await save()\n }\n } finally {\n await new Promise<void>((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())))\n }\n },\n }\n}\n\nexport type WorkerLaunch = { options: StudioOptions; prepared: PreparedConnection }\n\nexport async function startWorker(options: StudioOptions): Promise<void> {\n const current = await getWorkerStatus()\n if (current.running) {\n console.log(`Already running (${current.state}, PID ${current.pid}).`)\n return\n }\n const prepared = await prepareConnection(options)\n const entry = path.join(path.dirname(createRequire(import.meta.url).resolve('@kubb/cli/package.json')), 'dist', 'studioWorker.js')\n const child = x(process.execPath, [...process.execArgv, entry], {\n nodeOptions: { cwd: process.cwd(), detached: true, stdio: ['ignore', 'ignore', 'ignore', 'ipc'] },\n }).process\n if (!child) throw new Error('Background worker failed to start')\n try {\n const started = new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => done(new Error('Background worker startup timed out')), 20_000)\n const done = (error?: Error) => {\n clearTimeout(timer)\n child.removeListener('error', failed)\n child.removeListener('exit', exited)\n child.removeListener('message', ready)\n if (error) reject(error)\n else resolve()\n }\n const failed = (error: Error) => done(error)\n const exited = () => done(new Error(`Background worker exited during startup. Check ${getWorkerLogPath()}`))\n child.once('error', failed)\n child.once('exit', exited)\n const ready = (message: unknown) => {\n if (!message || typeof message !== 'object' || !('started' in message) || message.started !== true)\n return done(new Error('Invalid worker startup response'))\n done()\n }\n child.once('message', ready)\n child.send({ options: { ...options, autoOpen: false }, prepared } satisfies WorkerLaunch, (error) => {\n if (error) done(error)\n })\n })\n await started\n if (child.connected) child.disconnect()\n child.unref()\n const status = await getWorkerStatus()\n console.log(`Background worker ${status.state} (PID ${status.pid ?? child.pid}). Logs: ${getWorkerLogPath()}`)\n } catch (error) {\n // This is the child we just spawned, not a PID recovered from disk.\n child.kill('SIGTERM')\n throw error\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"background-CCex47-d.js","names":["connectSocket","delay"],"sources":["../src/runners/studio/background.ts"],"sourcesContent":["import { hash, randomBytes } from 'node:crypto'\nimport { readFile, rename, writeFile } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport { connect as connectSocket, createServer } from 'node:net'\nimport path from 'node:path'\nimport { setTimeout as delay } from 'node:timers/promises'\nimport { x } from 'tinyexec'\nimport { getProjectKubbHome } from './credentials.ts'\nimport { prepareConnection, type PreparedConnection, type StudioOptions, type WorkerState } from './run.ts'\n\nexport type WorkerRecord = { id: string; pid: number; port: number; state: WorkerState }\nconst states: Array<WorkerState> = ['starting', 'connected', 'reconnecting', 'authentication required', 'stopped']\nexport const getWorkerLogPath = () => path.join(getProjectKubbHome(), 'worker.log')\nconst statePath = () => path.join(getProjectKubbHome(), 'worker.json')\n\nasync function readWorker(): Promise<WorkerRecord | null> {\n try {\n const value: unknown = JSON.parse(await readFile(statePath(), 'utf8'))\n if (!value || typeof value !== 'object') return null\n const record = value as Partial<WorkerRecord>\n return typeof record.id === 'string' &&\n /^[a-f0-9]{32}$/.test(record.id) &&\n Number.isInteger(record.pid) &&\n (record.pid ?? 0) > 1 &&\n Number.isInteger(record.port) &&\n (record.port ?? 0) > 0 &&\n (record.port ?? 0) <= 65535 &&\n states.includes(record.state as WorkerState)\n ? (record as WorkerRecord)\n : null\n } catch {\n return null\n }\n}\n\nfunction isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch (error) {\n return (error as NodeJS.ErrnoException).code === 'EPERM'\n }\n}\n\n/** Authenticated loopback IPC; a stored PID never authorizes sending a process signal. */\nfunction requestWorker(record: WorkerRecord, command: 'status' | 'stop'): Promise<WorkerRecord> {\n return new Promise((resolve, reject) => {\n const socket = connectSocket({ host: '127.0.0.1', port: record.port })\n let received = ''\n socket.setTimeout(2_000, () => socket.destroy(new Error('Worker control timed out')))\n socket.once('error', reject)\n socket.once('connect', () => socket.write(JSON.stringify({ id: record.id, command }) + '\\n'))\n socket.on('data', (chunk: Buffer) => {\n received += chunk.toString()\n if (received.length > 4096) socket.destroy(new Error('Invalid worker response'))\n })\n socket.once('end', () => {\n try {\n const response = JSON.parse(received) as WorkerRecord\n if (response.id !== record.id || response.pid !== record.pid || !states.includes(response.state)) throw new Error('Worker identity changed')\n resolve(response)\n } catch (error) {\n reject(error)\n }\n })\n })\n}\n\nexport async function getWorkerStatus(): Promise<{ running: boolean; state: WorkerState; pid?: number }> {\n const record = await readWorker()\n if (!record) return { running: false, state: 'stopped' }\n try {\n const response = await requestWorker(record, 'status')\n return { running: true, state: response.state, pid: response.pid }\n } catch {\n return { running: false, state: record.state === 'authentication required' ? record.state : 'stopped' }\n }\n}\n\nexport async function stopWorker(): Promise<void> {\n const record = await readWorker()\n if (!record) return\n try {\n await requestWorker(record, 'stop')\n } catch (error) {\n if (\n (error as NodeJS.ErrnoException).code !== 'ECONNREFUSED' &&\n isAlive(record.pid) &&\n record.state !== 'stopped' &&\n record.state !== 'authentication required'\n ) {\n throw new Error('Cannot verify the background worker. No process was signaled.')\n }\n return\n }\n const deadline = Date.now() + 15_000\n while (Date.now() < deadline) {\n try {\n await requestWorker(record, 'status')\n } catch {\n return\n }\n await delay(100)\n }\n throw new Error('The worker has not finished shutting down. Check worker.log and try again.')\n}\n\n/** The listening port is the project lock, so stale state never needs a PID-based takeover. */\nexport async function serveWorker(shutdown: AbortController) {\n const record: WorkerRecord = { id: randomBytes(16).toString('hex'), pid: process.pid, port: 0, state: 'starting' }\n const server = createServer((socket) => {\n let input = ''\n socket.setTimeout(2_000, () => socket.destroy())\n socket.on('error', () => {})\n socket.on('data', (chunk: Buffer) => {\n input += chunk.toString()\n if (input.length > 4096) {\n socket.destroy()\n return\n }\n if (!input.includes('\\n')) return\n try {\n const request = JSON.parse(input) as { id?: unknown; command?: unknown }\n if (request.id !== record.id || !['status', 'stop'].includes(String(request.command))) {\n socket.destroy()\n return\n }\n socket.end(JSON.stringify(record))\n if (request.command === 'stop') shutdown.abort()\n } catch {\n socket.destroy()\n }\n })\n })\n // Hash the project directory to choose its loopback port; fail on collisions.\n const port = 20_000 + (Number.parseInt(hash('sha256', getProjectKubbHome()).slice(0, 8), 16) % 30_000)\n try {\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, '127.0.0.1', resolve)\n })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EADDRINUSE') throw error\n // Let a simultaneous starter finish writing its record before checking ownership.\n await delay(100)\n const existing = await readWorker()\n if (existing?.port === port) {\n try {\n return { existing: await requestWorker(existing, 'status') }\n } catch {\n /* Refuse an unverified listener. */\n }\n }\n throw new Error('The project control port is occupied or another worker is starting. Try again after stopping that listener.')\n }\n record.port = port\n let saving = Promise.resolve()\n const save = () => {\n const value = JSON.stringify(record)\n saving = saving.then(async () => {\n const temporary = `${statePath()}.${record.id}`\n await writeFile(temporary, value, { mode: 0o600 })\n await rename(temporary, statePath())\n })\n return saving\n }\n try {\n await save()\n } catch (error) {\n server.close()\n throw error\n }\n return {\n async state(state: WorkerState) {\n record.state = state\n await save()\n },\n async close() {\n try {\n if (record.state !== 'authentication required') {\n record.state = 'stopped'\n await save()\n }\n } finally {\n await new Promise<void>((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())))\n }\n },\n }\n}\n\nexport type WorkerLaunch = { options: StudioOptions; prepared: PreparedConnection }\n\nexport async function startWorker(options: StudioOptions): Promise<void> {\n const current = await getWorkerStatus()\n if (current.running) {\n console.log(`Already running (${current.state}, PID ${current.pid}).`)\n return\n }\n const prepared = await prepareConnection(options)\n const entry = path.join(path.dirname(createRequire(import.meta.url).resolve('@kubb/cli/package.json')), 'dist', 'studioWorker.js')\n const child = x(process.execPath, [...process.execArgv, entry], {\n nodeOptions: { cwd: process.cwd(), detached: true, stdio: ['ignore', 'ignore', 'ignore', 'ipc'] },\n }).process\n if (!child) throw new Error('Background worker failed to start')\n try {\n const started = new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => done(new Error('Background worker startup timed out')), 20_000)\n const done = (error?: Error) => {\n clearTimeout(timer)\n child.removeListener('error', failed)\n child.removeListener('exit', exited)\n child.removeListener('message', ready)\n if (error) reject(error)\n else resolve()\n }\n const failed = (error: Error) => done(error)\n const exited = () => done(new Error(`Background worker exited during startup. Check ${getWorkerLogPath()}`))\n child.once('error', failed)\n child.once('exit', exited)\n const ready = (message: unknown) => {\n if (!message || typeof message !== 'object' || !('started' in message) || message.started !== true)\n return done(new Error('Invalid worker startup response'))\n done()\n }\n child.once('message', ready)\n child.send({ options: { ...options, autoOpen: false }, prepared } satisfies WorkerLaunch, (error) => {\n if (error) done(error)\n })\n })\n await started\n if (child.connected) child.disconnect()\n child.unref()\n const status = await getWorkerStatus()\n console.log(`Background worker ${status.state} (PID ${status.pid ?? child.pid}). Logs: ${getWorkerLogPath()}`)\n } catch (error) {\n // This is the child we just spawned, not a PID recovered from disk.\n child.kill('SIGTERM')\n throw error\n }\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAM,SAA6B;CAAC;CAAY;CAAa;CAAgB;CAA2B;AAAS;AACjH,MAAa,yBAAyB,KAAK,KAAK,mBAAmB,GAAG,YAAY;AAClF,MAAM,kBAAkB,KAAK,KAAK,mBAAmB,GAAG,aAAa;AAErE,eAAe,aAA2C;CACxD,IAAI;EACF,MAAM,QAAiB,KAAK,MAAM,MAAM,SAAS,UAAU,GAAG,MAAM,CAAC;EACrE,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU,OAAO;EAChD,MAAM,SAAS;EACf,OAAO,OAAO,OAAO,OAAO,YAC1B,iBAAiB,KAAK,OAAO,EAAE,KAC/B,OAAO,UAAU,OAAO,GAAG,MAC1B,OAAO,OAAO,KAAK,KACpB,OAAO,UAAU,OAAO,IAAI,MAC3B,OAAO,QAAQ,KAAK,MACpB,OAAO,QAAQ,MAAM,SACtB,OAAO,SAAS,OAAO,KAAoB,IACxC,SACD;CACN,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,QAAQ,KAAsB;CACrC,IAAI;EACF,QAAQ,KAAK,KAAK,CAAC;EACnB,OAAO;CACT,SAAS,OAAO;EACd,OAAQ,MAAgC,SAAS;CACnD;AACF;;AAGA,SAAS,cAAc,QAAsB,SAAmD;CAC9F,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,SAASA,QAAc;GAAE,MAAM;GAAa,MAAM,OAAO;EAAK,CAAC;EACrE,IAAI,WAAW;EACf,OAAO,WAAW,WAAa,OAAO,wBAAQ,IAAI,MAAM,0BAA0B,CAAC,CAAC;EACpF,OAAO,KAAK,SAAS,MAAM;EAC3B,OAAO,KAAK,iBAAiB,OAAO,MAAM,KAAK,UAAU;GAAE,IAAI,OAAO;GAAI;EAAQ,CAAC,IAAI,IAAI,CAAC;EAC5F,OAAO,GAAG,SAAS,UAAkB;GACnC,YAAY,MAAM,SAAS;GAC3B,IAAI,SAAS,SAAS,MAAM,OAAO,wBAAQ,IAAI,MAAM,yBAAyB,CAAC;EACjF,CAAC;EACD,OAAO,KAAK,aAAa;GACvB,IAAI;IACF,MAAM,WAAW,KAAK,MAAM,QAAQ;IACpC,IAAI,SAAS,OAAO,OAAO,MAAM,SAAS,QAAQ,OAAO,OAAO,CAAC,OAAO,SAAS,SAAS,KAAK,GAAG,MAAM,IAAI,MAAM,yBAAyB;IAC3I,QAAQ,QAAQ;GAClB,SAAS,OAAO;IACd,OAAO,KAAK;GACd;EACF,CAAC;CACH,CAAC;AACH;AAEA,eAAsB,kBAAmF;CACvG,MAAM,SAAS,MAAM,WAAW;CAChC,IAAI,CAAC,QAAQ,OAAO;EAAE,SAAS;EAAO,OAAO;CAAU;CACvD,IAAI;EACF,MAAM,WAAW,MAAM,cAAc,QAAQ,QAAQ;EACrD,OAAO;GAAE,SAAS;GAAM,OAAO,SAAS;GAAO,KAAK,SAAS;EAAI;CACnE,QAAQ;EACN,OAAO;GAAE,SAAS;GAAO,OAAO,OAAO,UAAU,4BAA4B,OAAO,QAAQ;EAAU;CACxG;AACF;AAEA,eAAsB,aAA4B;CAChD,MAAM,SAAS,MAAM,WAAW;CAChC,IAAI,CAAC,QAAQ;CACb,IAAI;EACF,MAAM,cAAc,QAAQ,MAAM;CACpC,SAAS,OAAO;EACd,IACG,MAAgC,SAAS,kBAC1C,QAAQ,OAAO,GAAG,KAClB,OAAO,UAAU,aACjB,OAAO,UAAU,2BAEjB,MAAM,IAAI,MAAM,+DAA+D;EAEjF;CACF;CACA,MAAM,WAAW,KAAK,IAAI,IAAI;CAC9B,OAAO,KAAK,IAAI,IAAI,UAAU;EAC5B,IAAI;GACF,MAAM,cAAc,QAAQ,QAAQ;EACtC,QAAQ;GACN;EACF;EACA,MAAMC,aAAM,GAAG;CACjB;CACA,MAAM,IAAI,MAAM,4EAA4E;AAC9F;;AAGA,eAAsB,YAAY,UAA2B;CAC3D,MAAM,SAAuB;EAAE,IAAI,YAAY,EAAE,CAAC,CAAC,SAAS,KAAK;EAAG,KAAK,QAAQ;EAAK,MAAM;EAAG,OAAO;CAAW;CACjH,MAAM,SAAS,cAAc,WAAW;EACtC,IAAI,QAAQ;EACZ,OAAO,WAAW,WAAa,OAAO,QAAQ,CAAC;EAC/C,OAAO,GAAG,eAAe,CAAC,CAAC;EAC3B,OAAO,GAAG,SAAS,UAAkB;GACnC,SAAS,MAAM,SAAS;GACxB,IAAI,MAAM,SAAS,MAAM;IACvB,OAAO,QAAQ;IACf;GACF;GACA,IAAI,CAAC,MAAM,SAAS,IAAI,GAAG;GAC3B,IAAI;IACF,MAAM,UAAU,KAAK,MAAM,KAAK;IAChC,IAAI,QAAQ,OAAO,OAAO,MAAM,CAAC,CAAC,UAAU,MAAM,CAAC,CAAC,SAAS,OAAO,QAAQ,OAAO,CAAC,GAAG;KACrF,OAAO,QAAQ;KACf;IACF;IACA,OAAO,IAAI,KAAK,UAAU,MAAM,CAAC;IACjC,IAAI,QAAQ,YAAY,QAAQ,SAAS,MAAM;GACjD,QAAQ;IACN,OAAO,QAAQ;GACjB;EACF,CAAC;CACH,CAAC;CAED,MAAM,OAAO,MAAU,OAAO,SAAS,KAAK,UAAU,mBAAmB,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,EAAE,IAAI;CAC/F,IAAI;EACF,MAAM,IAAI,SAAe,SAAS,WAAW;GAC3C,OAAO,KAAK,SAAS,MAAM;GAC3B,OAAO,OAAO,MAAM,aAAa,OAAO;EAC1C,CAAC;CACH,SAAS,OAAO;EACd,IAAK,MAAgC,SAAS,cAAc,MAAM;EAElE,MAAMA,aAAM,GAAG;EACf,MAAM,WAAW,MAAM,WAAW;EAClC,IAAI,UAAU,SAAS,MACrB,IAAI;GACF,OAAO,EAAE,UAAU,MAAM,cAAc,UAAU,QAAQ,EAAE;EAC7D,QAAQ,CAER;EAEF,MAAM,IAAI,MAAM,6GAA6G;CAC/H;CACA,OAAO,OAAO;CACd,IAAI,SAAS,QAAQ,QAAQ;CAC7B,MAAM,aAAa;EACjB,MAAM,QAAQ,KAAK,UAAU,MAAM;EACnC,SAAS,OAAO,KAAK,YAAY;GAC/B,MAAM,YAAY,GAAG,UAAU,EAAE,GAAG,OAAO;GAC3C,MAAM,UAAU,WAAW,OAAO,EAAE,MAAM,IAAM,CAAC;GACjD,MAAM,OAAO,WAAW,UAAU,CAAC;EACrC,CAAC;EACD,OAAO;CACT;CACA,IAAI;EACF,MAAM,KAAK;CACb,SAAS,OAAO;EACd,OAAO,MAAM;EACb,MAAM;CACR;CACA,OAAO;EACL,MAAM,MAAM,OAAoB;GAC9B,OAAO,QAAQ;GACf,MAAM,KAAK;EACb;EACA,MAAM,QAAQ;GACZ,IAAI;IACF,IAAI,OAAO,UAAU,2BAA2B;KAC9C,OAAO,QAAQ;KACf,MAAM,KAAK;IACb;GACF,UAAU;IACR,MAAM,IAAI,SAAe,SAAS,WAAW,OAAO,OAAO,UAAW,QAAQ,OAAO,KAAK,IAAI,QAAQ,CAAE,CAAC;GAC3G;EACF;CACF;AACF;AAIA,eAAsB,YAAY,SAAuC;CACvE,MAAM,UAAU,MAAM,gBAAgB;CACtC,IAAI,QAAQ,SAAS;EACnB,QAAQ,IAAI,oBAAoB,QAAQ,MAAM,QAAQ,QAAQ,IAAI,GAAG;EACrE;CACF;CACA,MAAM,WAAW,MAAM,kBAAkB,OAAO;CAChD,MAAM,QAAQ,KAAK,KAAK,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC,CAAC,QAAQ,wBAAwB,CAAC,GAAG,QAAQ,iBAAiB;CACjI,MAAM,QAAQ,EAAE,QAAQ,UAAU,CAAC,GAAG,QAAQ,UAAU,KAAK,GAAG,EAC9D,aAAa;EAAE,KAAK,QAAQ,IAAI;EAAG,UAAU;EAAM,OAAO;GAAC;GAAU;GAAU;GAAU;EAAK;CAAE,EAClG,CAAC,CAAC,CAAC;CACH,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,mCAAmC;CAC/D,IAAI;EAyBF,MAAM,IAxBc,SAAe,SAAS,WAAW;GACrD,MAAM,QAAQ,iBAAiB,qBAAK,IAAI,MAAM,qCAAqC,CAAC,GAAG,GAAM;GAC7F,MAAM,QAAQ,UAAkB;IAC9B,aAAa,KAAK;IAClB,MAAM,eAAe,SAAS,MAAM;IACpC,MAAM,eAAe,QAAQ,MAAM;IACnC,MAAM,eAAe,WAAW,KAAK;IACrC,IAAI,OAAO,OAAO,KAAK;SAClB,QAAQ;GACf;GACA,MAAM,UAAU,UAAiB,KAAK,KAAK;GAC3C,MAAM,eAAe,qBAAK,IAAI,MAAM,kDAAkD,iBAAiB,GAAG,CAAC;GAC3G,MAAM,KAAK,SAAS,MAAM;GAC1B,MAAM,KAAK,QAAQ,MAAM;GACzB,MAAM,SAAS,YAAqB;IAClC,IAAI,CAAC,WAAW,OAAO,YAAY,YAAY,EAAE,aAAa,YAAY,QAAQ,YAAY,MAC5F,OAAO,qBAAK,IAAI,MAAM,iCAAiC,CAAC;IAC1D,KAAK;GACP;GACA,MAAM,KAAK,WAAW,KAAK;GAC3B,MAAM,KAAK;IAAE,SAAS;KAAE,GAAG;KAAS,UAAU;IAAM;IAAG;GAAS,IAA2B,UAAU;IACnG,IAAI,OAAO,KAAK,KAAK;GACvB,CAAC;EACH,CACY;EACZ,IAAI,MAAM,WAAW,MAAM,WAAW;EACtC,MAAM,MAAM;EACZ,MAAM,SAAS,MAAM,gBAAgB;EACrC,QAAQ,IAAI,qBAAqB,OAAO,MAAM,QAAQ,OAAO,OAAO,MAAM,IAAI,WAAW,iBAAiB,GAAG;CAC/G,SAAS,OAAO;EAEd,MAAM,KAAK,SAAS;EACpB,MAAM;CACR;AACF"}
@@ -1,6 +1,6 @@
1
1
  const require_agent = require("./agent-DElUuYuy.cjs");
2
- const require_run = require("./run-C8dyBAPb.cjs");
3
- const require_background = require("./background-Bh4FDWa3.cjs");
2
+ const require_run = require("./run-DxGkjzRm.cjs");
3
+ const require_background = require("./background-BcRoKru0.cjs");
4
4
  let node_util = require("node:util");
5
5
  let node_process = require("node:process");
6
6
  node_process = require_agent.__toESM(node_process, 1);
@@ -84,4 +84,4 @@ exports.startRunner = startRunner;
84
84
  exports.statusRunner = statusRunner;
85
85
  exports.stopRunner = stopRunner;
86
86
 
87
- //# sourceMappingURL=commands-hXDwA0zn.cjs.map
87
+ //# sourceMappingURL=commands-BuY0nrlU.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands-hXDwA0zn.cjs","names":["readCredentials","styleText","process","formatPermissionRows","createStudioOptions","run","connect","login","stopWorker","clearCredentials","startWorker","getWorkerStatus","getWorkerLogPath"],"sources":["../src/runners/studio/commands.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport type { CommandRunner } from 'gunshi'\nimport type { command as connectCommand } from '../../commands/studio/connect.ts'\nimport type { command as logoutCommand } from '../../commands/studio/logout.ts'\nimport type { command as statusCommand } from '../../commands/studio/status.ts'\nimport { getWorkerLogPath, getWorkerStatus, startWorker, stopWorker } from './background.ts'\nimport { clearCredentials, readCredentials } from './credentials.ts'\nimport { connect, createStudioOptions, formatPermissionRows, login, run, type StudioOptions } from './run.ts'\n\ntype Runner<T extends { args: object }> = CommandRunner<{ args: T['args']; extensions: {} }>\n\n/** Reports the paired agent and any saved permissions for the current project. */\nasync function status(options: StudioOptions): Promise<void> {\n const credentials = await readCredentials()\n\n if (!credentials) {\n console.log('Not paired. Run `kubb studio login`.')\n\n return\n }\n\n console.log(`Paired with ${credentials.studioUrl} as ${styleText('cyan', credentials.agentSlug || credentials.agentId)}`)\n\n if (credentials.studioUrl !== options.studioUrl) {\n console.log(styleText('yellow', `Connecting to ${options.studioUrl} needs pairing again.`))\n }\n\n const remembered = credentials.projects?.[process.cwd()]\n\n if (!remembered) {\n console.log(styleText('dim', 'No saved permissions for this project. Run `kubb studio` to connect and choose.'))\n\n return\n }\n\n console.log(styleText('dim', 'Saved permissions'))\n\n for (const row of formatPermissionRows({\n allowRead: remembered.allowRead === true,\n allowWrite: remembered.allowWrite === true,\n allowConfigEdit: remembered.allowConfigEdit === true,\n allowExec: remembered.allowExec === true,\n })) {\n console.log(row)\n }\n}\n\nexport const connectRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => connect(options), block: true })\n}\n\nexport const loginRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => login(options) })\n}\n\nexport const logoutRunner: Runner<typeof logoutCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({\n options,\n action: async () => {\n await stopWorker()\n await clearCredentials()\n console.log('Signed out of Kubb Studio.')\n },\n })\n}\n\nexport const startRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => startWorker(options) })\n}\n\nexport const statusRunner: Runner<typeof statusCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({\n options,\n action: async () => {\n const worker = await getWorkerStatus()\n console.log(`Background connection: ${worker.state}${worker.running ? ` (PID ${worker.pid})` : ''}`)\n console.log(`Logs: ${getWorkerLogPath()}`)\n await status(options)\n },\n })\n}\n\nexport async function stopRunner(): Promise<void> {\n await stopWorker()\n console.log('Background connection stopped.')\n}\n"],"mappings":";;;;;;;;AAaA,eAAe,OAAO,SAAuC;CAC3D,MAAM,cAAc,MAAMA,YAAAA,gBAAgB;CAE1C,IAAI,CAAC,aAAa;EAChB,QAAQ,IAAI,sCAAsC;EAElD;CACF;CAEA,QAAQ,IAAI,eAAe,YAAY,UAAU,OAAA,GAAMC,UAAAA,UAAAA,CAAU,QAAQ,YAAY,aAAa,YAAY,OAAO,GAAG;CAExH,IAAI,YAAY,cAAc,QAAQ,WACpC,QAAQ,KAAA,GAAIA,UAAAA,UAAAA,CAAU,UAAU,iBAAiB,QAAQ,UAAU,sBAAsB,CAAC;CAG5F,MAAM,aAAa,YAAY,WAAWC,aAAAA,QAAQ,IAAI;CAEtD,IAAI,CAAC,YAAY;EACf,QAAQ,KAAA,GAAID,UAAAA,UAAAA,CAAU,OAAO,iFAAiF,CAAC;EAE/G;CACF;CAEA,QAAQ,KAAA,GAAIA,UAAAA,UAAAA,CAAU,OAAO,mBAAmB,CAAC;CAEjD,KAAK,MAAM,OAAOE,YAAAA,qBAAqB;EACrC,WAAW,WAAW,cAAc;EACpC,YAAY,WAAW,eAAe;EACtC,iBAAiB,WAAW,oBAAoB;EAChD,WAAW,WAAW,cAAc;CACtC,CAAC,GACC,QAAQ,IAAI,GAAG;AAEnB;AAEA,MAAa,gBAA+C,OAAO,EAAE,aAAa;CAChF,MAAM,UAAUC,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EAAE;EAAS,cAAcC,YAAAA,QAAQ,OAAO;EAAG,OAAO;CAAK,CAAC;AACpE;AAEA,MAAa,cAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAUF,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EAAE;EAAS,cAAcE,YAAAA,MAAM,OAAO;CAAE,CAAC;AACrD;AAEA,MAAa,eAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAUH,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EACR;EACA,QAAQ,YAAY;GAClB,MAAMG,mBAAAA,WAAW;GACjB,MAAMC,YAAAA,iBAAiB;GACvB,QAAQ,IAAI,4BAA4B;EAC1C;CACF,CAAC;AACH;AAEA,MAAa,cAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAUL,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EAAE;EAAS,cAAcK,mBAAAA,YAAY,OAAO;CAAE,CAAC;AAC3D;AAEA,MAAa,eAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAUN,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EACR;EACA,QAAQ,YAAY;GAClB,MAAM,SAAS,MAAMM,mBAAAA,gBAAgB;GACrC,QAAQ,IAAI,0BAA0B,OAAO,QAAQ,OAAO,UAAU,SAAS,OAAO,IAAI,KAAK,IAAI;GACnG,QAAQ,IAAI,SAASC,mBAAAA,iBAAiB,GAAG;GACzC,MAAM,OAAO,OAAO;EACtB;CACF,CAAC;AACH;AAEA,eAAsB,aAA4B;CAChD,MAAMJ,mBAAAA,WAAW;CACjB,QAAQ,IAAI,gCAAgC;AAC9C"}
1
+ {"version":3,"file":"commands-BuY0nrlU.cjs","names":["readCredentials","styleText","process","formatPermissionRows","createStudioOptions","run","connect","login","stopWorker","clearCredentials","startWorker","getWorkerStatus","getWorkerLogPath"],"sources":["../src/runners/studio/commands.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport type { CommandRunner } from 'gunshi'\nimport type { command as connectCommand } from '../../commands/studio/connect.ts'\nimport type { command as logoutCommand } from '../../commands/studio/logout.ts'\nimport type { command as statusCommand } from '../../commands/studio/status.ts'\nimport { getWorkerLogPath, getWorkerStatus, startWorker, stopWorker } from './background.ts'\nimport { clearCredentials, readCredentials } from './credentials.ts'\nimport { connect, createStudioOptions, formatPermissionRows, login, run, type StudioOptions } from './run.ts'\n\ntype Runner<T extends { args: object }> = CommandRunner<{ args: T['args']; extensions: {} }>\n\n/** Reports the paired agent and any saved permissions for the current project. */\nasync function status(options: StudioOptions): Promise<void> {\n const credentials = await readCredentials()\n\n if (!credentials) {\n console.log('Not paired. Run `kubb studio login`.')\n\n return\n }\n\n console.log(`Paired with ${credentials.studioUrl} as ${styleText('cyan', credentials.agentSlug || credentials.agentId)}`)\n\n if (credentials.studioUrl !== options.studioUrl) {\n console.log(styleText('yellow', `Connecting to ${options.studioUrl} needs pairing again.`))\n }\n\n const remembered = credentials.projects?.[process.cwd()]\n\n if (!remembered) {\n console.log(styleText('dim', 'No saved permissions for this project. Run `kubb studio` to connect and choose.'))\n\n return\n }\n\n console.log(styleText('dim', 'Saved permissions'))\n\n for (const row of formatPermissionRows({\n allowRead: remembered.allowRead === true,\n allowWrite: remembered.allowWrite === true,\n allowConfigEdit: remembered.allowConfigEdit === true,\n allowExec: remembered.allowExec === true,\n })) {\n console.log(row)\n }\n}\n\nexport const connectRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => connect(options), block: true })\n}\n\nexport const loginRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => login(options) })\n}\n\nexport const logoutRunner: Runner<typeof logoutCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({\n options,\n action: async () => {\n await stopWorker()\n await clearCredentials()\n console.log('Signed out of Kubb Studio.')\n },\n })\n}\n\nexport const startRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => startWorker(options) })\n}\n\nexport const statusRunner: Runner<typeof statusCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({\n options,\n action: async () => {\n const worker = await getWorkerStatus()\n console.log(`Background connection: ${worker.state}${worker.running ? ` (PID ${worker.pid})` : ''}`)\n console.log(`Logs: ${getWorkerLogPath()}`)\n await status(options)\n },\n })\n}\n\nexport async function stopRunner(): Promise<void> {\n await stopWorker()\n console.log('Background connection stopped.')\n}\n"],"mappings":";;;;;;;;AAaA,eAAe,OAAO,SAAuC;CAC3D,MAAM,cAAc,MAAMA,YAAAA,gBAAgB;CAE1C,IAAI,CAAC,aAAa;EAChB,QAAQ,IAAI,sCAAsC;EAElD;CACF;CAEA,QAAQ,IAAI,eAAe,YAAY,UAAU,OAAA,GAAMC,UAAAA,UAAAA,CAAU,QAAQ,YAAY,aAAa,YAAY,OAAO,GAAG;CAExH,IAAI,YAAY,cAAc,QAAQ,WACpC,QAAQ,KAAA,GAAIA,UAAAA,UAAAA,CAAU,UAAU,iBAAiB,QAAQ,UAAU,sBAAsB,CAAC;CAG5F,MAAM,aAAa,YAAY,WAAWC,aAAAA,QAAQ,IAAI;CAEtD,IAAI,CAAC,YAAY;EACf,QAAQ,KAAA,GAAID,UAAAA,UAAAA,CAAU,OAAO,iFAAiF,CAAC;EAE/G;CACF;CAEA,QAAQ,KAAA,GAAIA,UAAAA,UAAAA,CAAU,OAAO,mBAAmB,CAAC;CAEjD,KAAK,MAAM,OAAOE,YAAAA,qBAAqB;EACrC,WAAW,WAAW,cAAc;EACpC,YAAY,WAAW,eAAe;EACtC,iBAAiB,WAAW,oBAAoB;EAChD,WAAW,WAAW,cAAc;CACtC,CAAC,GACC,QAAQ,IAAI,GAAG;AAEnB;AAEA,MAAa,gBAA+C,OAAO,EAAE,aAAa;CAChF,MAAM,UAAUC,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EAAE;EAAS,cAAcC,YAAAA,QAAQ,OAAO;EAAG,OAAO;CAAK,CAAC;AACpE;AAEA,MAAa,cAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAUF,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EAAE;EAAS,cAAcE,YAAAA,MAAM,OAAO;CAAE,CAAC;AACrD;AAEA,MAAa,eAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAUH,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EACR;EACA,QAAQ,YAAY;GAClB,MAAMG,mBAAAA,WAAW;GACjB,MAAMC,YAAAA,iBAAiB;GACvB,QAAQ,IAAI,4BAA4B;EAC1C;CACF,CAAC;AACH;AAEA,MAAa,cAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAUL,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EAAE;EAAS,cAAcK,mBAAAA,YAAY,OAAO;CAAE,CAAC;AAC3D;AAEA,MAAa,eAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAUN,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EACR;EACA,QAAQ,YAAY;GAClB,MAAM,SAAS,MAAMM,mBAAAA,gBAAgB;GACrC,QAAQ,IAAI,0BAA0B,OAAO,QAAQ,OAAO,UAAU,SAAS,OAAO,IAAI,KAAK,IAAI;GACnG,QAAQ,IAAI,SAASC,mBAAAA,iBAAiB,GAAG;GACzC,MAAM,OAAO,OAAO;EACtB;CACF,CAAC;AACH;AAEA,eAAsB,aAA4B;CAChD,MAAMJ,mBAAAA,WAAW;CACjB,QAAQ,IAAI,gCAAgC;AAC9C"}
@@ -1,6 +1,6 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { a as login, c as clearCredentials, n as createStudioOptions, r as formatPermissionRows, s as run, t as connect, u as readCredentials } from "./run-BQQhNg8I.js";
3
- import { a as stopWorker, i as startWorker, n as getWorkerStatus, t as getWorkerLogPath } from "./background-B0YbkZ0s.js";
2
+ import { a as login, c as clearCredentials, n as createStudioOptions, r as formatPermissionRows, s as run, t as connect, u as readCredentials } from "./run-BRUwQ5Y7.js";
3
+ import { a as stopWorker, i as startWorker, n as getWorkerStatus, t as getWorkerLogPath } from "./background-CCex47-d.js";
4
4
  import { styleText } from "node:util";
5
5
  import process from "node:process";
6
6
  //#region src/runners/studio/commands.ts
@@ -78,4 +78,4 @@ async function stopRunner() {
78
78
  //#endregion
79
79
  export { connectRunner, loginRunner, logoutRunner, startRunner, statusRunner, stopRunner };
80
80
 
81
- //# sourceMappingURL=commands-BegVe5Mt.js.map
81
+ //# sourceMappingURL=commands-atq2z0Bo.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands-BegVe5Mt.js","names":[],"sources":["../src/runners/studio/commands.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport type { CommandRunner } from 'gunshi'\nimport type { command as connectCommand } from '../../commands/studio/connect.ts'\nimport type { command as logoutCommand } from '../../commands/studio/logout.ts'\nimport type { command as statusCommand } from '../../commands/studio/status.ts'\nimport { getWorkerLogPath, getWorkerStatus, startWorker, stopWorker } from './background.ts'\nimport { clearCredentials, readCredentials } from './credentials.ts'\nimport { connect, createStudioOptions, formatPermissionRows, login, run, type StudioOptions } from './run.ts'\n\ntype Runner<T extends { args: object }> = CommandRunner<{ args: T['args']; extensions: {} }>\n\n/** Reports the paired agent and any saved permissions for the current project. */\nasync function status(options: StudioOptions): Promise<void> {\n const credentials = await readCredentials()\n\n if (!credentials) {\n console.log('Not paired. Run `kubb studio login`.')\n\n return\n }\n\n console.log(`Paired with ${credentials.studioUrl} as ${styleText('cyan', credentials.agentSlug || credentials.agentId)}`)\n\n if (credentials.studioUrl !== options.studioUrl) {\n console.log(styleText('yellow', `Connecting to ${options.studioUrl} needs pairing again.`))\n }\n\n const remembered = credentials.projects?.[process.cwd()]\n\n if (!remembered) {\n console.log(styleText('dim', 'No saved permissions for this project. Run `kubb studio` to connect and choose.'))\n\n return\n }\n\n console.log(styleText('dim', 'Saved permissions'))\n\n for (const row of formatPermissionRows({\n allowRead: remembered.allowRead === true,\n allowWrite: remembered.allowWrite === true,\n allowConfigEdit: remembered.allowConfigEdit === true,\n allowExec: remembered.allowExec === true,\n })) {\n console.log(row)\n }\n}\n\nexport const connectRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => connect(options), block: true })\n}\n\nexport const loginRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => login(options) })\n}\n\nexport const logoutRunner: Runner<typeof logoutCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({\n options,\n action: async () => {\n await stopWorker()\n await clearCredentials()\n console.log('Signed out of Kubb Studio.')\n },\n })\n}\n\nexport const startRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => startWorker(options) })\n}\n\nexport const statusRunner: Runner<typeof statusCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({\n options,\n action: async () => {\n const worker = await getWorkerStatus()\n console.log(`Background connection: ${worker.state}${worker.running ? ` (PID ${worker.pid})` : ''}`)\n console.log(`Logs: ${getWorkerLogPath()}`)\n await status(options)\n },\n })\n}\n\nexport async function stopRunner(): Promise<void> {\n await stopWorker()\n console.log('Background connection stopped.')\n}\n"],"mappings":";;;;;;;AAaA,eAAe,OAAO,SAAuC;CAC3D,MAAM,cAAc,MAAM,gBAAgB;CAE1C,IAAI,CAAC,aAAa;EAChB,QAAQ,IAAI,sCAAsC;EAElD;CACF;CAEA,QAAQ,IAAI,eAAe,YAAY,UAAU,MAAM,UAAU,QAAQ,YAAY,aAAa,YAAY,OAAO,GAAG;CAExH,IAAI,YAAY,cAAc,QAAQ,WACpC,QAAQ,IAAI,UAAU,UAAU,iBAAiB,QAAQ,UAAU,sBAAsB,CAAC;CAG5F,MAAM,aAAa,YAAY,WAAW,QAAQ,IAAI;CAEtD,IAAI,CAAC,YAAY;EACf,QAAQ,IAAI,UAAU,OAAO,iFAAiF,CAAC;EAE/G;CACF;CAEA,QAAQ,IAAI,UAAU,OAAO,mBAAmB,CAAC;CAEjD,KAAK,MAAM,OAAO,qBAAqB;EACrC,WAAW,WAAW,cAAc;EACpC,YAAY,WAAW,eAAe;EACtC,iBAAiB,WAAW,oBAAoB;EAChD,WAAW,WAAW,cAAc;CACtC,CAAC,GACC,QAAQ,IAAI,GAAG;AAEnB;AAEA,MAAa,gBAA+C,OAAO,EAAE,aAAa;CAChF,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EAAE;EAAS,cAAc,QAAQ,OAAO;EAAG,OAAO;CAAK,CAAC;AACpE;AAEA,MAAa,cAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EAAE;EAAS,cAAc,MAAM,OAAO;CAAE,CAAC;AACrD;AAEA,MAAa,eAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EACR;EACA,QAAQ,YAAY;GAClB,MAAM,WAAW;GACjB,MAAM,iBAAiB;GACvB,QAAQ,IAAI,4BAA4B;EAC1C;CACF,CAAC;AACH;AAEA,MAAa,cAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EAAE;EAAS,cAAc,YAAY,OAAO;CAAE,CAAC;AAC3D;AAEA,MAAa,eAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EACR;EACA,QAAQ,YAAY;GAClB,MAAM,SAAS,MAAM,gBAAgB;GACrC,QAAQ,IAAI,0BAA0B,OAAO,QAAQ,OAAO,UAAU,SAAS,OAAO,IAAI,KAAK,IAAI;GACnG,QAAQ,IAAI,SAAS,iBAAiB,GAAG;GACzC,MAAM,OAAO,OAAO;EACtB;CACF,CAAC;AACH;AAEA,eAAsB,aAA4B;CAChD,MAAM,WAAW;CACjB,QAAQ,IAAI,gCAAgC;AAC9C"}
1
+ {"version":3,"file":"commands-atq2z0Bo.js","names":[],"sources":["../src/runners/studio/commands.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport type { CommandRunner } from 'gunshi'\nimport type { command as connectCommand } from '../../commands/studio/connect.ts'\nimport type { command as logoutCommand } from '../../commands/studio/logout.ts'\nimport type { command as statusCommand } from '../../commands/studio/status.ts'\nimport { getWorkerLogPath, getWorkerStatus, startWorker, stopWorker } from './background.ts'\nimport { clearCredentials, readCredentials } from './credentials.ts'\nimport { connect, createStudioOptions, formatPermissionRows, login, run, type StudioOptions } from './run.ts'\n\ntype Runner<T extends { args: object }> = CommandRunner<{ args: T['args']; extensions: {} }>\n\n/** Reports the paired agent and any saved permissions for the current project. */\nasync function status(options: StudioOptions): Promise<void> {\n const credentials = await readCredentials()\n\n if (!credentials) {\n console.log('Not paired. Run `kubb studio login`.')\n\n return\n }\n\n console.log(`Paired with ${credentials.studioUrl} as ${styleText('cyan', credentials.agentSlug || credentials.agentId)}`)\n\n if (credentials.studioUrl !== options.studioUrl) {\n console.log(styleText('yellow', `Connecting to ${options.studioUrl} needs pairing again.`))\n }\n\n const remembered = credentials.projects?.[process.cwd()]\n\n if (!remembered) {\n console.log(styleText('dim', 'No saved permissions for this project. Run `kubb studio` to connect and choose.'))\n\n return\n }\n\n console.log(styleText('dim', 'Saved permissions'))\n\n for (const row of formatPermissionRows({\n allowRead: remembered.allowRead === true,\n allowWrite: remembered.allowWrite === true,\n allowConfigEdit: remembered.allowConfigEdit === true,\n allowExec: remembered.allowExec === true,\n })) {\n console.log(row)\n }\n}\n\nexport const connectRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => connect(options), block: true })\n}\n\nexport const loginRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => login(options) })\n}\n\nexport const logoutRunner: Runner<typeof logoutCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({\n options,\n action: async () => {\n await stopWorker()\n await clearCredentials()\n console.log('Signed out of Kubb Studio.')\n },\n })\n}\n\nexport const startRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => startWorker(options) })\n}\n\nexport const statusRunner: Runner<typeof statusCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({\n options,\n action: async () => {\n const worker = await getWorkerStatus()\n console.log(`Background connection: ${worker.state}${worker.running ? ` (PID ${worker.pid})` : ''}`)\n console.log(`Logs: ${getWorkerLogPath()}`)\n await status(options)\n },\n })\n}\n\nexport async function stopRunner(): Promise<void> {\n await stopWorker()\n console.log('Background connection stopped.')\n}\n"],"mappings":";;;;;;;AAaA,eAAe,OAAO,SAAuC;CAC3D,MAAM,cAAc,MAAM,gBAAgB;CAE1C,IAAI,CAAC,aAAa;EAChB,QAAQ,IAAI,sCAAsC;EAElD;CACF;CAEA,QAAQ,IAAI,eAAe,YAAY,UAAU,MAAM,UAAU,QAAQ,YAAY,aAAa,YAAY,OAAO,GAAG;CAExH,IAAI,YAAY,cAAc,QAAQ,WACpC,QAAQ,IAAI,UAAU,UAAU,iBAAiB,QAAQ,UAAU,sBAAsB,CAAC;CAG5F,MAAM,aAAa,YAAY,WAAW,QAAQ,IAAI;CAEtD,IAAI,CAAC,YAAY;EACf,QAAQ,IAAI,UAAU,OAAO,iFAAiF,CAAC;EAE/G;CACF;CAEA,QAAQ,IAAI,UAAU,OAAO,mBAAmB,CAAC;CAEjD,KAAK,MAAM,OAAO,qBAAqB;EACrC,WAAW,WAAW,cAAc;EACpC,YAAY,WAAW,eAAe;EACtC,iBAAiB,WAAW,oBAAoB;EAChD,WAAW,WAAW,cAAc;CACtC,CAAC,GACC,QAAQ,IAAI,GAAG;AAEnB;AAEA,MAAa,gBAA+C,OAAO,EAAE,aAAa;CAChF,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EAAE;EAAS,cAAc,QAAQ,OAAO;EAAG,OAAO;CAAK,CAAC;AACpE;AAEA,MAAa,cAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EAAE;EAAS,cAAc,MAAM,OAAO;CAAE,CAAC;AACrD;AAEA,MAAa,eAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EACR;EACA,QAAQ,YAAY;GAClB,MAAM,WAAW;GACjB,MAAM,iBAAiB;GACvB,QAAQ,IAAI,4BAA4B;EAC1C;CACF,CAAC;AACH;AAEA,MAAa,cAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EAAE;EAAS,cAAc,YAAY,OAAO;CAAE,CAAC;AAC3D;AAEA,MAAa,eAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EACR;EACA,QAAQ,YAAY;GAClB,MAAM,SAAS,MAAM,gBAAgB;GACrC,QAAQ,IAAI,0BAA0B,OAAO,QAAQ,OAAO,UAAU,SAAS,OAAO,IAAI,KAAK,IAAI;GACnG,QAAQ,IAAI,SAAS,iBAAiB,GAAG;GACzC,MAAM,OAAO,OAAO;EACtB;CACF,CAAC;AACH;AAEA,eAAsB,aAA4B;CAChD,MAAM,WAAW;CACjB,QAAQ,IAAI,gCAAgC;AAC9C"}
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_agent = require("./agent-DElUuYuy.cjs");
3
- const require_Telemetry = require("./Telemetry-B_C4MVJd.cjs");
3
+ const require_Telemetry = require("./Telemetry-C9gmBTr0.cjs");
4
4
  let node_util = require("node:util");
5
5
  let _gunshi_plugin_dryrun = require("@gunshi/plugin-dryrun");
6
6
  _gunshi_plugin_dryrun = require_agent.__toESM(_gunshi_plugin_dryrun, 1);
@@ -69,8 +69,9 @@ const studioPermissionArgs = {
69
69
  //#region src/commands/add.ts
70
70
  const command$13 = (0, gunshi.define)({
71
71
  name: "add",
72
- description: "Install a plugin, adapter, or parser from the Kubb registry at its reviewed version. A plugin is added to kubb.config.ts, an adapter or parser prints the code to add. Reads KUBB_REGISTRY to use another registry.",
72
+ description: "Install a plugin, adapter, or parser from the Kubb registry at its reviewed version. Without an id, pick one from the registry. A plugin is added to kubb.config.ts, an adapter or parser prints the code to add. Reads KUBB_REGISTRY to use another registry.",
73
73
  examples: [
74
+ "kubb add",
74
75
  "kubb add plugin-zod",
75
76
  "kubb add kubb-labs/plugin-react-query",
76
77
  "kubb add acme/plugin-x --yes",
@@ -80,8 +81,8 @@ const command$13 = (0, gunshi.define)({
80
81
  args: {
81
82
  id: {
82
83
  type: "positional",
83
- description: "Registry id: owner/slug, or a slug for an official extension",
84
- required: true
84
+ description: "Registry id: owner/slug, or a slug for an official extension. Asked for when omitted",
85
+ required: false
85
86
  },
86
87
  ...configArg,
87
88
  ...yesArg,
@@ -93,7 +94,7 @@ const command$13 = (0, gunshi.define)({
93
94
  }
94
95
  },
95
96
  async run({ values }) {
96
- const { run } = await Promise.resolve().then(() => require("./run-Ct6kzKpg.cjs"));
97
+ const { run } = await Promise.resolve().then(() => require("./run-BGTUbY2h.cjs"));
97
98
  await run({
98
99
  id: values.id,
99
100
  configPath: values.config,
@@ -176,7 +177,7 @@ const command$12 = (0, gunshi.defineWithTypes)()({
176
177
  async run(ctx) {
177
178
  const { values } = ctx;
178
179
  const logLevel = resolveLogLevel(values);
179
- const { run } = await Promise.resolve().then(() => require("./run-fg0ycsS_.cjs"));
180
+ const { run } = await Promise.resolve().then(() => require("./run-DFos0eOY.cjs"));
180
181
  await run({
181
182
  input: values.input,
182
183
  configPath: values.config,
@@ -227,7 +228,7 @@ const command$11 = (0, gunshi.defineWithTypes)()({
227
228
  },
228
229
  async run(ctx) {
229
230
  const { values } = ctx;
230
- const { run } = await Promise.resolve().then(() => require("./run-DL2wLwBZ.cjs"));
231
+ const { run } = await Promise.resolve().then(() => require("./run-Dm9OZUkQ.cjs"));
231
232
  await run({
232
233
  yes: values.yes,
233
234
  version: require_Telemetry.version,
@@ -262,7 +263,7 @@ const command$9 = (0, gunshi.define)({
262
263
  ].join("\n"),
263
264
  rendering: { header: null },
264
265
  async run() {
265
- const { run } = await Promise.resolve().then(() => require("./run-D8EJ2hKI.cjs"));
266
+ const { run } = await Promise.resolve().then(() => require("./run-CIvFRMLt.cjs"));
266
267
  await run();
267
268
  }
268
269
  });
@@ -291,7 +292,7 @@ const command$8 = (0, gunshi.define)({
291
292
  ...logLevelArg
292
293
  },
293
294
  async run(ctx) {
294
- const { connectRunner } = await Promise.resolve().then(() => require("./commands-hXDwA0zn.cjs"));
295
+ const { connectRunner } = await Promise.resolve().then(() => require("./commands-BuY0nrlU.cjs"));
295
296
  await connectRunner(ctx);
296
297
  }
297
298
  });
@@ -304,7 +305,7 @@ const command$7 = (0, gunshi.define)({
304
305
  toKebab: true,
305
306
  args: command$8.args,
306
307
  async run(ctx) {
307
- const { loginRunner } = await Promise.resolve().then(() => require("./commands-hXDwA0zn.cjs"));
308
+ const { loginRunner } = await Promise.resolve().then(() => require("./commands-BuY0nrlU.cjs"));
308
309
  await loginRunner(ctx);
309
310
  }
310
311
  });
@@ -322,7 +323,7 @@ const command$6 = (0, gunshi.define)({
322
323
  ...logLevelArg
323
324
  },
324
325
  async run(ctx) {
325
- const { logoutRunner } = await Promise.resolve().then(() => require("./commands-hXDwA0zn.cjs"));
326
+ const { logoutRunner } = await Promise.resolve().then(() => require("./commands-BuY0nrlU.cjs"));
326
327
  await logoutRunner(ctx);
327
328
  }
328
329
  });
@@ -362,7 +363,7 @@ const command$5 = (0, gunshi.define)({
362
363
  ...logLevelArg
363
364
  },
364
365
  async run(ctx) {
365
- const { runner } = await Promise.resolve().then(() => require("./snapshot-B45A4RfA.cjs"));
366
+ const { runner } = await Promise.resolve().then(() => require("./snapshot-DUJU70H_.cjs"));
366
367
  await runner(ctx);
367
368
  }
368
369
  });
@@ -374,7 +375,7 @@ const command$4 = (0, gunshi.define)({
374
375
  toKebab: true,
375
376
  args: command$8.args,
376
377
  async run(ctx) {
377
- const { startRunner } = await Promise.resolve().then(() => require("./commands-hXDwA0zn.cjs"));
378
+ const { startRunner } = await Promise.resolve().then(() => require("./commands-BuY0nrlU.cjs"));
378
379
  await startRunner(ctx);
379
380
  }
380
381
  });
@@ -382,7 +383,7 @@ const stopCommand = (0, gunshi.define)({
382
383
  name: "stop",
383
384
  description: "Stop this project's background connection and keep its pairing.",
384
385
  async run() {
385
- const { stopRunner } = await Promise.resolve().then(() => require("./commands-hXDwA0zn.cjs"));
386
+ const { stopRunner } = await Promise.resolve().then(() => require("./commands-BuY0nrlU.cjs"));
386
387
  await stopRunner();
387
388
  }
388
389
  });
@@ -400,7 +401,7 @@ const command$3 = (0, gunshi.define)({
400
401
  ...logLevelArg
401
402
  },
402
403
  async run(ctx) {
403
- const { statusRunner } = await Promise.resolve().then(() => require("./commands-hXDwA0zn.cjs"));
404
+ const { statusRunner } = await Promise.resolve().then(() => require("./commands-BuY0nrlU.cjs"));
404
405
  await statusRunner(ctx);
405
406
  }
406
407
  });
@@ -420,7 +421,7 @@ const command$2 = (0, gunshi.define)({
420
421
  toKebab: true,
421
422
  args: command$8.args,
422
423
  async run(ctx) {
423
- const { connectRunner } = await Promise.resolve().then(() => require("./commands-hXDwA0zn.cjs"));
424
+ const { connectRunner } = await Promise.resolve().then(() => require("./commands-BuY0nrlU.cjs"));
424
425
  await connectRunner(ctx);
425
426
  },
426
427
  subCommands: {
@@ -470,7 +471,7 @@ const command$1 = (0, gunshi.define)({
470
471
  ...yesArg
471
472
  },
472
473
  async run({ values }) {
473
- const { run } = await Promise.resolve().then(() => require("./run-89YfZJuo.cjs"));
474
+ const { run } = await Promise.resolve().then(() => require("./run-Bhs7mJ1f.cjs"));
474
475
  await run({
475
476
  ids: values.ids ?? [],
476
477
  check: values.check,
@@ -491,7 +492,7 @@ const command = (0, gunshi.define)({
491
492
  required: true
492
493
  } },
493
494
  async run({ values }) {
494
- const { run } = await Promise.resolve().then(() => require("./run-e8gMz1M_.cjs"));
495
+ const { run } = await Promise.resolve().then(() => require("./run-Co732JNO.cjs"));
495
496
  await run({ input: values.input });
496
497
  }
497
498
  });