@kubb/cli 5.8.1 → 5.8.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 (38) hide show
  1. package/dist/{Telemetry-C3raFshE.js → Telemetry-BOCR2q1g.js} +2 -2
  2. package/dist/{Telemetry-C3raFshE.js.map → Telemetry-BOCR2q1g.js.map} +1 -1
  3. package/dist/{Telemetry-DVdoZ5i3.cjs → Telemetry-D1M0d8PT.cjs} +2 -2
  4. package/dist/{Telemetry-DVdoZ5i3.cjs.map → Telemetry-D1M0d8PT.cjs.map} +1 -1
  5. package/dist/{background-BXczDhV0.cjs → background-1fPYMKIh.cjs} +2 -2
  6. package/dist/{background-BXczDhV0.cjs.map → background-1fPYMKIh.cjs.map} +1 -1
  7. package/dist/background-BreCsKLJ.js +1 -0
  8. package/dist/{background-KPjyLyLs.js → background-lBbQYvN7.js} +2 -2
  9. package/dist/{background-KPjyLyLs.js.map → background-lBbQYvN7.js.map} +1 -1
  10. package/dist/{commands-DAb8WcSg.js → commands-DCwzlFGA.js} +3 -3
  11. package/dist/{commands-DAb8WcSg.js.map → commands-DCwzlFGA.js.map} +1 -1
  12. package/dist/{commands-Dves_8Dw.cjs → commands-VS9f9all.cjs} +3 -3
  13. package/dist/{commands-Dves_8Dw.cjs.map → commands-VS9f9all.cjs.map} +1 -1
  14. package/dist/index.cjs +12 -12
  15. package/dist/index.js +12 -12
  16. package/dist/{run-CYlBM95X.cjs → run-BF_nhSiJ.cjs} +2 -2
  17. package/dist/{run-CYlBM95X.cjs.map → run-BF_nhSiJ.cjs.map} +1 -1
  18. package/dist/{run-DnnQQi1q.cjs → run-BKkuOyne.cjs} +2 -2
  19. package/dist/{run-DnnQQi1q.cjs.map → run-BKkuOyne.cjs.map} +1 -1
  20. package/dist/{run-CZ26dcKd.cjs → run-C31KZ8zp.cjs} +2 -2
  21. package/dist/{run-CZ26dcKd.cjs.map → run-C31KZ8zp.cjs.map} +1 -1
  22. package/dist/{run-DkuGqsyU.js → run-CNiUPnC7.js} +2 -2
  23. package/dist/{run-DkuGqsyU.js.map → run-CNiUPnC7.js.map} +1 -1
  24. package/dist/{run-FH6VbxNn.js → run-CkIxVyjD.js} +2 -2
  25. package/dist/{run-FH6VbxNn.js.map → run-CkIxVyjD.js.map} +1 -1
  26. package/dist/{run-Bl8Evvbv.js → run-DjINtbfD.js} +2 -2
  27. package/dist/{run-Bl8Evvbv.js.map → run-DjINtbfD.js.map} +1 -1
  28. package/dist/{run-33URIiPM.cjs → run-DrUd6OfI.cjs} +3 -3
  29. package/dist/{run-33URIiPM.cjs.map → run-DrUd6OfI.cjs.map} +1 -1
  30. package/dist/{run-BMHEBZbR.js → run-mIZ7hJVc.js} +3 -3
  31. package/dist/{run-BMHEBZbR.js.map → run-mIZ7hJVc.js.map} +1 -1
  32. package/dist/{snapshot-RIdF2azE.cjs → snapshot-CQcQ5L6B.cjs} +3 -3
  33. package/dist/{snapshot-RIdF2azE.cjs.map → snapshot-CQcQ5L6B.cjs.map} +1 -1
  34. package/dist/{snapshot-CVc0EW6M.js → snapshot-DgsBHsOb.js} +3 -3
  35. package/dist/{snapshot-CVc0EW6M.js.map → snapshot-DgsBHsOb.js.map} +1 -1
  36. package/dist/studioWorker.js +2 -2
  37. package/package.json +7 -7
  38. package/dist/background-DHfGpbjE.js +0 -1
@@ -74,7 +74,7 @@ var Runtime = class {
74
74
  const runtime = new Runtime();
75
75
  //#endregion
76
76
  //#region package.json
77
- var version = "5.8.1";
77
+ var version = "5.8.3";
78
78
  //#endregion
79
79
  //#region src/Telemetry.ts
80
80
  /** OpenTelemetry ingestion endpoint for anonymous usage telemetry. */
@@ -244,4 +244,4 @@ async function sendTelemetry(event) {
244
244
  //#endregion
245
245
  export { runtime as i, trackRun as n, version as r, isDisabled as t };
246
246
 
247
- //# sourceMappingURL=Telemetry-C3raFshE.js.map
247
+ //# sourceMappingURL=Telemetry-BOCR2q1g.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Telemetry-C3raFshE.js","names":["process"],"sources":["../../../internals/utils/src/runtime.ts","../package.json","../src/Telemetry.ts"],"sourcesContent":["/**\n * Name of the JavaScript runtime executing the current process.\n */\ntype RuntimeName = 'bun' | 'deno' | 'node'\n\n/**\n * Detects the JavaScript runtime executing the current process and exposes its name and version.\n *\n * Prefer the shared {@link runtime} instance over constructing your own.\n */\nclass Runtime {\n /**\n * `true` when the current process is running under Bun.\n *\n * Detection keys off the global `Bun` object rather than `process.versions`,\n * because Bun polyfills `process.versions.node` for Node compatibility and would\n * otherwise look like Node.\n *\n * @example\n * ```ts\n * if (runtime.isBun) {\n * await Bun.write(path, data)\n * }\n * ```\n */\n get isBun(): boolean {\n return typeof Bun !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Deno.\n */\n get isDeno(): boolean {\n return typeof (globalThis as { Deno?: unknown }).Deno !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Node.\n *\n * Bun and Deno are excluded first so a polyfilled `process` does not register as Node.\n */\n get isNode(): boolean {\n return !this.isBun && !this.isDeno && typeof process !== 'undefined' && process.versions?.node != null\n }\n\n /**\n * Name of the runtime executing the current process.\n *\n * @example\n * ```ts\n * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise\n * ```\n */\n get name(): RuntimeName {\n if (this.isBun) return 'bun'\n if (this.isDeno) return 'deno'\n\n return 'node'\n }\n\n /**\n * Version of the active runtime, or an empty string when it cannot be read.\n *\n * @example\n * ```ts\n * runtime.version // '1.3.11' under Bun, '22.22.2' under Node\n * ```\n */\n get version(): string {\n if (this.isBun) return process.versions.bun ?? ''\n if (this.isDeno) return (globalThis as { Deno?: { version?: { deno?: string } } }).Deno?.version?.deno ?? ''\n\n return process.versions?.node ?? ''\n }\n}\n\n/**\n * Shared {@link Runtime} instance describing the JavaScript runtime executing the current process.\n */\nexport const runtime = new Runtime()\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-BOCR2q1g.js","names":["process"],"sources":["../../../internals/utils/src/runtime.ts","../package.json","../src/Telemetry.ts"],"sourcesContent":["/**\n * Name of the JavaScript runtime executing the current process.\n */\ntype RuntimeName = 'bun' | 'deno' | 'node'\n\n/**\n * Detects the JavaScript runtime executing the current process and exposes its name and version.\n *\n * Prefer the shared {@link runtime} instance over constructing your own.\n */\nclass Runtime {\n /**\n * `true` when the current process is running under Bun.\n *\n * Detection keys off the global `Bun` object rather than `process.versions`,\n * because Bun polyfills `process.versions.node` for Node compatibility and would\n * otherwise look like Node.\n *\n * @example\n * ```ts\n * if (runtime.isBun) {\n * await Bun.write(path, data)\n * }\n * ```\n */\n get isBun(): boolean {\n return typeof Bun !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Deno.\n */\n get isDeno(): boolean {\n return typeof (globalThis as { Deno?: unknown }).Deno !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Node.\n *\n * Bun and Deno are excluded first so a polyfilled `process` does not register as Node.\n */\n get isNode(): boolean {\n return !this.isBun && !this.isDeno && typeof process !== 'undefined' && process.versions?.node != null\n }\n\n /**\n * Name of the runtime executing the current process.\n *\n * @example\n * ```ts\n * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise\n * ```\n */\n get name(): RuntimeName {\n if (this.isBun) return 'bun'\n if (this.isDeno) return 'deno'\n\n return 'node'\n }\n\n /**\n * Version of the active runtime, or an empty string when it cannot be read.\n *\n * @example\n * ```ts\n * runtime.version // '1.3.11' under Bun, '22.22.2' under Node\n * ```\n */\n get version(): string {\n if (this.isBun) return process.versions.bun ?? ''\n if (this.isDeno) return (globalThis as { Deno?: { version?: { deno?: string } } }).Deno?.version?.deno ?? ''\n\n return process.versions?.node ?? ''\n }\n}\n\n/**\n * Shared {@link Runtime} instance describing the JavaScript runtime executing the current process.\n */\nexport const runtime = new Runtime()\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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"}
@@ -75,7 +75,7 @@ var Runtime = class {
75
75
  const runtime = new Runtime();
76
76
  //#endregion
77
77
  //#region package.json
78
- var version = "5.8.1";
78
+ var version = "5.8.3";
79
79
  //#endregion
80
80
  //#region src/Telemetry.ts
81
81
  /** OpenTelemetry ingestion endpoint for anonymous usage telemetry. */
@@ -268,4 +268,4 @@ Object.defineProperty(exports, "version", {
268
268
  }
269
269
  });
270
270
 
271
- //# sourceMappingURL=Telemetry-DVdoZ5i3.cjs.map
271
+ //# sourceMappingURL=Telemetry-D1M0d8PT.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Telemetry-DVdoZ5i3.cjs","names":["process","getElapsedMs","os","isCIEnvironment","getAgentName","randomBytes"],"sources":["../../../internals/utils/src/runtime.ts","../package.json","../src/Telemetry.ts"],"sourcesContent":["/**\n * Name of the JavaScript runtime executing the current process.\n */\ntype RuntimeName = 'bun' | 'deno' | 'node'\n\n/**\n * Detects the JavaScript runtime executing the current process and exposes its name and version.\n *\n * Prefer the shared {@link runtime} instance over constructing your own.\n */\nclass Runtime {\n /**\n * `true` when the current process is running under Bun.\n *\n * Detection keys off the global `Bun` object rather than `process.versions`,\n * because Bun polyfills `process.versions.node` for Node compatibility and would\n * otherwise look like Node.\n *\n * @example\n * ```ts\n * if (runtime.isBun) {\n * await Bun.write(path, data)\n * }\n * ```\n */\n get isBun(): boolean {\n return typeof Bun !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Deno.\n */\n get isDeno(): boolean {\n return typeof (globalThis as { Deno?: unknown }).Deno !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Node.\n *\n * Bun and Deno are excluded first so a polyfilled `process` does not register as Node.\n */\n get isNode(): boolean {\n return !this.isBun && !this.isDeno && typeof process !== 'undefined' && process.versions?.node != null\n }\n\n /**\n * Name of the runtime executing the current process.\n *\n * @example\n * ```ts\n * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise\n * ```\n */\n get name(): RuntimeName {\n if (this.isBun) return 'bun'\n if (this.isDeno) return 'deno'\n\n return 'node'\n }\n\n /**\n * Version of the active runtime, or an empty string when it cannot be read.\n *\n * @example\n * ```ts\n * runtime.version // '1.3.11' under Bun, '22.22.2' under Node\n * ```\n */\n get version(): string {\n if (this.isBun) return process.versions.bun ?? ''\n if (this.isDeno) return (globalThis as { Deno?: { version?: { deno?: string } } }).Deno?.version?.deno ?? ''\n\n return process.versions?.node ?? ''\n }\n}\n\n/**\n * Shared {@link Runtime} instance describing the JavaScript runtime executing the current process.\n */\nexport const runtime = new Runtime()\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":";;;;;;;;;;;;AAUA,IAAM,UAAN,MAAc;;;;;;;;;;;;;;;CAeZ,IAAI,QAAiB;EACnB,OAAO,OAAO,QAAQ;CACxB;;;;CAKA,IAAI,SAAkB;EACpB,OAAO,OAAQ,WAAkC,SAAS;CAC5D;;;;;;CAOA,IAAI,SAAkB;EACpB,OAAO,CAAC,KAAK,SAAS,CAAC,KAAK,UAAU,OAAO,YAAY,eAAe,QAAQ,UAAU,QAAQ;CACpG;;;;;;;;;CAUA,IAAI,OAAoB;EACtB,IAAI,KAAK,OAAO,OAAO;EACvB,IAAI,KAAK,QAAQ,OAAO;EAExB,OAAO;CACT;;;;;;;;;CAUA,IAAI,UAAkB;EACpB,IAAI,KAAK,OAAO,OAAO,QAAQ,SAAS,OAAO;EAC/C,IAAI,KAAK,QAAQ,OAAQ,WAA0D,MAAM,SAAS,QAAQ;EAE1G,OAAO,QAAQ,UAAU,QAAQ;CACnC;AACF;;;;AAKA,MAAa,UAAU,IAAI,QAAQ;;;;;;;AEvEnC,MAAM,gBAAgB;;;;AAqFtB,SAAgB,aAAsB;CACpC,OAAO,CAAC,gBAAgB,wBAAwB,CAAC,CAAC,MAAM,SAAS,CAAC,KAAK,MAAM,CAAC,CAAC,SAASA,aAAAA,QAAQ,IAAI,SAAS,EAAE,CAAC;AAClH;;;;AAKA,SAAgB,oBAAoB,SAOjB;CACjB,MAAM,WAAW,KAAK,MAAMC,cAAAA,aAAa,QAAQ,OAAO,CAAC;CAEzD,OAAO;EACL,SAAS,QAAQ;EACjB,aAAa,QAAQ;EACrB,aAAaD,aAAAA,QAAQ,SAAS,KAAK,MAAM,GAAG,CAAC,CAAC;EAC9C,SAAS,QAAQ;EACjB,gBAAgB,QAAQ,QAAQ,MAAM,GAAG,CAAC,CAAC;EAC3C,UAAUE,QAAAA,QAAG,SAAS;EACtB,IAAIC,cAAAA,gBAAgB;EACpB,OAAOC,cAAAA,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,WAAA,GAAUC,YAAAA,YAAAA,CAAY,EAAE,CAAC,CAAC,SAAS,KAAK;CAC9C,MAAM,UAAA,GAASA,YAAAA,YAAAA,CAAY,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"}
1
+ {"version":3,"file":"Telemetry-D1M0d8PT.cjs","names":["process","getElapsedMs","os","isCIEnvironment","getAgentName","randomBytes"],"sources":["../../../internals/utils/src/runtime.ts","../package.json","../src/Telemetry.ts"],"sourcesContent":["/**\n * Name of the JavaScript runtime executing the current process.\n */\ntype RuntimeName = 'bun' | 'deno' | 'node'\n\n/**\n * Detects the JavaScript runtime executing the current process and exposes its name and version.\n *\n * Prefer the shared {@link runtime} instance over constructing your own.\n */\nclass Runtime {\n /**\n * `true` when the current process is running under Bun.\n *\n * Detection keys off the global `Bun` object rather than `process.versions`,\n * because Bun polyfills `process.versions.node` for Node compatibility and would\n * otherwise look like Node.\n *\n * @example\n * ```ts\n * if (runtime.isBun) {\n * await Bun.write(path, data)\n * }\n * ```\n */\n get isBun(): boolean {\n return typeof Bun !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Deno.\n */\n get isDeno(): boolean {\n return typeof (globalThis as { Deno?: unknown }).Deno !== 'undefined'\n }\n\n /**\n * `true` when the current process is running under Node.\n *\n * Bun and Deno are excluded first so a polyfilled `process` does not register as Node.\n */\n get isNode(): boolean {\n return !this.isBun && !this.isDeno && typeof process !== 'undefined' && process.versions?.node != null\n }\n\n /**\n * Name of the runtime executing the current process.\n *\n * @example\n * ```ts\n * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise\n * ```\n */\n get name(): RuntimeName {\n if (this.isBun) return 'bun'\n if (this.isDeno) return 'deno'\n\n return 'node'\n }\n\n /**\n * Version of the active runtime, or an empty string when it cannot be read.\n *\n * @example\n * ```ts\n * runtime.version // '1.3.11' under Bun, '22.22.2' under Node\n * ```\n */\n get version(): string {\n if (this.isBun) return process.versions.bun ?? ''\n if (this.isDeno) return (globalThis as { Deno?: { version?: { deno?: string } } }).Deno?.version?.deno ?? ''\n\n return process.versions?.node ?? ''\n }\n}\n\n/**\n * Shared {@link Runtime} instance describing the JavaScript runtime executing the current process.\n */\nexport const runtime = new Runtime()\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,5 +1,5 @@
1
1
  const require_agent = require("./agent-DElUuYuy.cjs");
2
- const require_run = require("./run-33URIiPM.cjs");
2
+ const require_run = require("./run-DrUd6OfI.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-BXczDhV0.cjs.map
172
+ //# sourceMappingURL=background-1fPYMKIh.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"background-BXczDhV0.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-1fPYMKIh.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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"}
@@ -0,0 +1 @@
1
+ export { n as getWorkerStatus } from "./background-lBbQYvN7.js";
@@ -1,5 +1,5 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { l as getProjectKubbHome, o as prepareConnection } from "./run-BMHEBZbR.js";
2
+ import { l as getProjectKubbHome, o as prepareConnection } from "./run-mIZ7hJVc.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-KPjyLyLs.js.map
249
+ //# sourceMappingURL=background-lBbQYvN7.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"background-KPjyLyLs.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-lBbQYvN7.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,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-BMHEBZbR.js";
3
- import { a as stopWorker, i as startWorker, n as getWorkerStatus, t as getWorkerLogPath } from "./background-KPjyLyLs.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-mIZ7hJVc.js";
3
+ import { a as stopWorker, i as startWorker, n as getWorkerStatus, t as getWorkerLogPath } from "./background-lBbQYvN7.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-DAb8WcSg.js.map
81
+ //# sourceMappingURL=commands-DCwzlFGA.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands-DAb8WcSg.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-DCwzlFGA.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,6 +1,6 @@
1
1
  const require_agent = require("./agent-DElUuYuy.cjs");
2
- const require_run = require("./run-33URIiPM.cjs");
3
- const require_background = require("./background-BXczDhV0.cjs");
2
+ const require_run = require("./run-DrUd6OfI.cjs");
3
+ const require_background = require("./background-1fPYMKIh.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-Dves_8Dw.cjs.map
87
+ //# sourceMappingURL=commands-VS9f9all.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands-Dves_8Dw.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-VS9f9all.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"}
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-DVdoZ5i3.cjs");
3
+ const require_Telemetry = require("./Telemetry-D1M0d8PT.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);
@@ -176,7 +176,7 @@ const command$12 = (0, gunshi.defineWithTypes)()({
176
176
  async run(ctx) {
177
177
  const { values } = ctx;
178
178
  const logLevel = resolveLogLevel(values);
179
- const { run } = await Promise.resolve().then(() => require("./run-DnnQQi1q.cjs"));
179
+ const { run } = await Promise.resolve().then(() => require("./run-BKkuOyne.cjs"));
180
180
  await run({
181
181
  input: values.input,
182
182
  configPath: values.config,
@@ -261,7 +261,7 @@ const command$9 = (0, gunshi.define)({
261
261
  "# { \"mcpServers\": { \"kubb\": { \"command\": \"npx\", \"args\": [\"kubb\", \"mcp\"] } } }"
262
262
  ].join("\n"),
263
263
  async run() {
264
- const { run } = await Promise.resolve().then(() => require("./run-CZ26dcKd.cjs"));
264
+ const { run } = await Promise.resolve().then(() => require("./run-C31KZ8zp.cjs"));
265
265
  await run();
266
266
  }
267
267
  });
@@ -290,7 +290,7 @@ const command$8 = (0, gunshi.define)({
290
290
  ...logLevelArg
291
291
  },
292
292
  async run(ctx) {
293
- const { connectRunner } = await Promise.resolve().then(() => require("./commands-Dves_8Dw.cjs"));
293
+ const { connectRunner } = await Promise.resolve().then(() => require("./commands-VS9f9all.cjs"));
294
294
  await connectRunner(ctx);
295
295
  }
296
296
  });
@@ -303,7 +303,7 @@ const command$7 = (0, gunshi.define)({
303
303
  toKebab: true,
304
304
  args: command$8.args,
305
305
  async run(ctx) {
306
- const { loginRunner } = await Promise.resolve().then(() => require("./commands-Dves_8Dw.cjs"));
306
+ const { loginRunner } = await Promise.resolve().then(() => require("./commands-VS9f9all.cjs"));
307
307
  await loginRunner(ctx);
308
308
  }
309
309
  });
@@ -321,7 +321,7 @@ const command$6 = (0, gunshi.define)({
321
321
  ...logLevelArg
322
322
  },
323
323
  async run(ctx) {
324
- const { logoutRunner } = await Promise.resolve().then(() => require("./commands-Dves_8Dw.cjs"));
324
+ const { logoutRunner } = await Promise.resolve().then(() => require("./commands-VS9f9all.cjs"));
325
325
  await logoutRunner(ctx);
326
326
  }
327
327
  });
@@ -361,7 +361,7 @@ const command$5 = (0, gunshi.define)({
361
361
  ...logLevelArg
362
362
  },
363
363
  async run(ctx) {
364
- const { runner } = await Promise.resolve().then(() => require("./snapshot-RIdF2azE.cjs"));
364
+ const { runner } = await Promise.resolve().then(() => require("./snapshot-CQcQ5L6B.cjs"));
365
365
  await runner(ctx);
366
366
  }
367
367
  });
@@ -373,7 +373,7 @@ const command$4 = (0, gunshi.define)({
373
373
  toKebab: true,
374
374
  args: command$8.args,
375
375
  async run(ctx) {
376
- const { startRunner } = await Promise.resolve().then(() => require("./commands-Dves_8Dw.cjs"));
376
+ const { startRunner } = await Promise.resolve().then(() => require("./commands-VS9f9all.cjs"));
377
377
  await startRunner(ctx);
378
378
  }
379
379
  });
@@ -381,7 +381,7 @@ const stopCommand = (0, gunshi.define)({
381
381
  name: "stop",
382
382
  description: "Stop this project's background connection and keep its pairing.",
383
383
  async run() {
384
- const { stopRunner } = await Promise.resolve().then(() => require("./commands-Dves_8Dw.cjs"));
384
+ const { stopRunner } = await Promise.resolve().then(() => require("./commands-VS9f9all.cjs"));
385
385
  await stopRunner();
386
386
  }
387
387
  });
@@ -399,7 +399,7 @@ const command$3 = (0, gunshi.define)({
399
399
  ...logLevelArg
400
400
  },
401
401
  async run(ctx) {
402
- const { statusRunner } = await Promise.resolve().then(() => require("./commands-Dves_8Dw.cjs"));
402
+ const { statusRunner } = await Promise.resolve().then(() => require("./commands-VS9f9all.cjs"));
403
403
  await statusRunner(ctx);
404
404
  }
405
405
  });
@@ -419,7 +419,7 @@ const command$2 = (0, gunshi.define)({
419
419
  toKebab: true,
420
420
  args: command$8.args,
421
421
  async run(ctx) {
422
- const { connectRunner } = await Promise.resolve().then(() => require("./commands-Dves_8Dw.cjs"));
422
+ const { connectRunner } = await Promise.resolve().then(() => require("./commands-VS9f9all.cjs"));
423
423
  await connectRunner(ctx);
424
424
  },
425
425
  subCommands: {
@@ -490,7 +490,7 @@ const command = (0, gunshi.define)({
490
490
  required: true
491
491
  } },
492
492
  async run({ values }) {
493
- const { run } = await Promise.resolve().then(() => require("./run-CYlBM95X.cjs"));
493
+ const { run } = await Promise.resolve().then(() => require("./run-BF_nhSiJ.cjs"));
494
494
  await run({ input: values.input });
495
495
  }
496
496
  });