@kubb/cli 5.9.0 → 5.9.2

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 (98) hide show
  1. package/bin/kubb.js +1 -1
  2. package/dist/{Telemetry-D1jiXfo2.cjs → Telemetry-B_C4MVJd.cjs} +26 -66
  3. package/dist/Telemetry-B_C4MVJd.cjs.map +1 -0
  4. package/dist/{Telemetry-BivZAaw9.js → Telemetry-DER8LIO5.js} +26 -66
  5. package/dist/Telemetry-DER8LIO5.js.map +1 -0
  6. package/dist/{background-uIIElWXl.js → background-B0YbkZ0s.js} +2 -2
  7. package/dist/{background-uIIElWXl.js.map → background-B0YbkZ0s.js.map} +1 -1
  8. package/dist/{background-Cd2TGkLg.cjs → background-Bh4FDWa3.cjs} +2 -2
  9. package/dist/{background-Cd2TGkLg.cjs.map → background-Bh4FDWa3.cjs.map} +1 -1
  10. package/dist/background-DSKoOwcG.js +1 -0
  11. package/dist/{commands-BlNFxWKB.js → commands-BegVe5Mt.js} +3 -3
  12. package/dist/{commands-BlNFxWKB.js.map → commands-BegVe5Mt.js.map} +1 -1
  13. package/dist/{commands-ID-cYLXW.cjs → commands-hXDwA0zn.cjs} +3 -3
  14. package/dist/{commands-ID-cYLXW.cjs.map → commands-hXDwA0zn.cjs.map} +1 -1
  15. package/dist/{config-DAdYwK_D.js → config-B6UIKcl1.js} +13 -16
  16. package/dist/config-B6UIKcl1.js.map +1 -0
  17. package/dist/{config-CRBZcWwg.cjs → config-Bo9ro7vg.cjs} +13 -16
  18. package/dist/config-Bo9ro7vg.cjs.map +1 -0
  19. package/dist/constants-Cii4HX64.js +12 -0
  20. package/dist/constants-Cii4HX64.js.map +1 -0
  21. package/dist/constants-Df449N47.cjs +29 -0
  22. package/dist/constants-Df449N47.cjs.map +1 -0
  23. package/dist/index.cjs +19 -28
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.js +19 -28
  26. package/dist/index.js.map +1 -1
  27. package/dist/{output-CWupdozw.cjs → output-BnK0scpX.cjs} +10 -15
  28. package/dist/output-BnK0scpX.cjs.map +1 -0
  29. package/dist/{output-B9Yw7vL0.js → output-qFt4vV7K.js} +10 -15
  30. package/dist/output-qFt4vV7K.js.map +1 -0
  31. package/dist/{reporters-C5HAypFq.cjs → reporters-B4rZOlo8.cjs} +2 -2
  32. package/dist/{reporters-C5HAypFq.cjs.map → reporters-B4rZOlo8.cjs.map} +1 -1
  33. package/dist/{reporters-CNZQUlXY.js → reporters-H21Jvrff.js} +2 -2
  34. package/dist/{reporters-CNZQUlXY.js.map → reporters-H21Jvrff.js.map} +1 -1
  35. package/dist/{run-VAkf24Cw.cjs → run-89YfZJuo.cjs} +3 -3
  36. package/dist/{run-VAkf24Cw.cjs.map → run-89YfZJuo.cjs.map} +1 -1
  37. package/dist/run-8HrdMihy.js +1 -0
  38. package/dist/{run-DnXUzX34.js → run-BCswmM8Q.js} +3 -5
  39. package/dist/run-BCswmM8Q.js.map +1 -0
  40. package/dist/{run-BF2Wq1Io.js → run-BQQhNg8I.js} +7 -7
  41. package/dist/{run-BF2Wq1Io.js.map → run-BQQhNg8I.js.map} +1 -1
  42. package/dist/{run-Ey756UCd.js → run-BYff_byB.js} +2 -2
  43. package/dist/{run-Ey756UCd.js.map → run-BYff_byB.js.map} +1 -1
  44. package/dist/{run-mx0KM8y5.js → run-BcMMYk7G.js} +10 -22
  45. package/dist/run-BcMMYk7G.js.map +1 -0
  46. package/dist/{run-DSeEZTnT.cjs → run-C8dyBAPb.cjs} +7 -7
  47. package/dist/{run-DSeEZTnT.cjs.map → run-C8dyBAPb.cjs.map} +1 -1
  48. package/dist/{run-USNnlQcA.js → run-CJHsZZB8.js} +41 -49
  49. package/dist/run-CJHsZZB8.js.map +1 -0
  50. package/dist/{run-yb2R1vt0.js → run-Ca_OX3WZ.js} +6 -7
  51. package/dist/run-Ca_OX3WZ.js.map +1 -0
  52. package/dist/{run-C5P5_H0R.cjs → run-Ct6kzKpg.cjs} +6 -6
  53. package/dist/run-Ct6kzKpg.cjs.map +1 -0
  54. package/dist/{run-D4cZ-1zg.cjs → run-D8EJ2hKI.cjs} +2 -2
  55. package/dist/{run-D4cZ-1zg.cjs.map → run-D8EJ2hKI.cjs.map} +1 -1
  56. package/dist/{run-E11sqsk0.cjs → run-DL2wLwBZ.cjs} +41 -49
  57. package/dist/run-DL2wLwBZ.cjs.map +1 -0
  58. package/dist/{run-DRR30f0e.js → run-Dej-hm91.js} +3 -3
  59. package/dist/{run-DRR30f0e.js.map → run-Dej-hm91.js.map} +1 -1
  60. package/dist/{run-CnBJroZW.cjs → run-DpAMfkm5.cjs} +2 -2
  61. package/dist/{run-CnBJroZW.cjs.map → run-DpAMfkm5.cjs.map} +1 -1
  62. package/dist/{run-ajUuT3vK.js → run-KLPSFEv-.js} +2 -2
  63. package/dist/{run-ajUuT3vK.js.map → run-KLPSFEv-.js.map} +1 -1
  64. package/dist/{run-DfkvTomI.cjs → run-e8gMz1M_.cjs} +3 -5
  65. package/dist/run-e8gMz1M_.cjs.map +1 -0
  66. package/dist/{run-CNXBX4kr.cjs → run-fg0ycsS_.cjs} +10 -22
  67. package/dist/run-fg0ycsS_.cjs.map +1 -0
  68. package/dist/{snapshot-D5OaRDf9.cjs → snapshot-B45A4RfA.cjs} +5 -5
  69. package/dist/{snapshot-D5OaRDf9.cjs.map → snapshot-B45A4RfA.cjs.map} +1 -1
  70. package/dist/{snapshot-CHKxNlYg.js → snapshot-C0WaZZiF.js} +5 -5
  71. package/dist/{snapshot-CHKxNlYg.js.map → snapshot-C0WaZZiF.js.map} +1 -1
  72. package/dist/studioWorker.js +2 -2
  73. package/dist/{utils-Dhx5PMpD.js → utils-BHW8kA8P.js} +11 -8
  74. package/dist/utils-BHW8kA8P.js.map +1 -0
  75. package/dist/{utils-ZcCFqERz.cjs → utils-BzQ46pgd.cjs} +16 -13
  76. package/dist/utils-BzQ46pgd.cjs.map +1 -0
  77. package/package.json +7 -7
  78. package/dist/Telemetry-BivZAaw9.js.map +0 -1
  79. package/dist/Telemetry-D1jiXfo2.cjs.map +0 -1
  80. package/dist/background-D0UaV1ZP.js +0 -1
  81. package/dist/config-CRBZcWwg.cjs.map +0 -1
  82. package/dist/config-DAdYwK_D.js.map +0 -1
  83. package/dist/constants-CdxpgX3_.cjs +0 -115
  84. package/dist/constants-CdxpgX3_.cjs.map +0 -1
  85. package/dist/constants-DHRspBTo.js +0 -92
  86. package/dist/constants-DHRspBTo.js.map +0 -1
  87. package/dist/output-B9Yw7vL0.js.map +0 -1
  88. package/dist/output-CWupdozw.cjs.map +0 -1
  89. package/dist/run-C5P5_H0R.cjs.map +0 -1
  90. package/dist/run-CNXBX4kr.cjs.map +0 -1
  91. package/dist/run-DfkvTomI.cjs.map +0 -1
  92. package/dist/run-DnXUzX34.js.map +0 -1
  93. package/dist/run-E11sqsk0.cjs.map +0 -1
  94. package/dist/run-USNnlQcA.js.map +0 -1
  95. package/dist/run-mx0KM8y5.js.map +0 -1
  96. package/dist/run-yb2R1vt0.js.map +0 -1
  97. package/dist/utils-Dhx5PMpD.js.map +0 -1
  98. package/dist/utils-ZcCFqERz.cjs.map +0 -1
package/bin/kubb.js CHANGED
@@ -5,7 +5,7 @@ process.title = 'Kubb'
5
5
 
6
6
  try {
7
7
  const { run } = await import('../dist/index.js')
8
- await run(process.argv)
8
+ await run(process.argv.slice(2))
9
9
  } catch (err) {
10
10
  console.error(err)
11
11
  process.exit(1)
@@ -5,77 +5,37 @@ node_os = require_agent.__toESM(node_os, 1);
5
5
  let node_process = require("node:process");
6
6
  node_process = require_agent.__toESM(node_process, 1);
7
7
  //#region ../../internals/utils/src/runtime.ts
8
+ const isBun = typeof Bun !== "undefined";
9
+ const isDeno = "Deno" in globalThis;
8
10
  /**
9
- * Detects the JavaScript runtime executing the current process and exposes its name and version.
11
+ * The JavaScript runtime executing the current process: its name, version and whether it is Bun.
10
12
  *
11
- * Prefer the shared {@link runtime} instance over constructing your own.
13
+ * @example
14
+ * ```ts
15
+ * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise
16
+ * ```
12
17
  */
13
- var Runtime = class {
14
- /**
15
- * `true` when the current process is running under Bun.
16
- *
17
- * Detection keys off the global `Bun` object rather than `process.versions`,
18
- * because Bun polyfills `process.versions.node` for Node compatibility and would
19
- * otherwise look like Node.
20
- *
21
- * @example
22
- * ```ts
23
- * if (runtime.isBun) {
24
- * await Bun.write(path, data)
25
- * }
26
- * ```
27
- */
28
- get isBun() {
29
- return typeof Bun !== "undefined";
30
- }
31
- /**
32
- * `true` when the current process is running under Deno.
33
- */
34
- get isDeno() {
35
- return typeof globalThis.Deno !== "undefined";
36
- }
37
- /**
38
- * `true` when the current process is running under Node.
39
- *
40
- * Bun and Deno are excluded first so a polyfilled `process` does not register as Node.
41
- */
42
- get isNode() {
43
- return !this.isBun && !this.isDeno && typeof process !== "undefined" && process.versions?.node != null;
44
- }
45
- /**
46
- * Name of the runtime executing the current process.
47
- *
48
- * @example
49
- * ```ts
50
- * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise
51
- * ```
52
- */
53
- get name() {
54
- if (this.isBun) return "bun";
55
- if (this.isDeno) return "deno";
56
- return "node";
57
- }
58
- /**
59
- * Version of the active runtime, or an empty string when it cannot be read.
60
- *
61
- * @example
62
- * ```ts
63
- * runtime.version // '1.3.11' under Bun, '22.22.2' under Node
64
- * ```
65
- */
66
- get version() {
67
- if (this.isBun) return process.versions.bun ?? "";
68
- if (this.isDeno) return globalThis.Deno?.version?.deno ?? "";
69
- return process.versions?.node ?? "";
70
- }
18
+ const runtime = {
19
+ isBun,
20
+ ...detect()
71
21
  };
72
- /**
73
- * Shared {@link Runtime} instance describing the JavaScript runtime executing the current process.
74
- */
75
- const runtime = new Runtime();
22
+ function detect() {
23
+ if (isBun) return {
24
+ name: "bun",
25
+ version: process.versions.bun ?? ""
26
+ };
27
+ if (isDeno) return {
28
+ name: "deno",
29
+ version: globalThis.Deno?.version?.deno ?? ""
30
+ };
31
+ return {
32
+ name: "node",
33
+ version: process.versions?.node ?? ""
34
+ };
35
+ }
76
36
  //#endregion
77
37
  //#region package.json
78
- var version = "5.9.0";
38
+ var version = "5.9.2";
79
39
  //#endregion
80
40
  //#region src/Telemetry.ts
81
41
  /** OpenTelemetry ingestion endpoint for anonymous usage telemetry. */
@@ -268,4 +228,4 @@ Object.defineProperty(exports, "version", {
268
228
  }
269
229
  });
270
230
 
271
- //# sourceMappingURL=Telemetry-D1jiXfo2.cjs.map
231
+ //# sourceMappingURL=Telemetry-B_C4MVJd.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Telemetry-B_C4MVJd.cjs","names":["process","getElapsedMs","os","isCIEnvironment","getAgentName","randomBytes"],"sources":["../../../internals/utils/src/runtime.ts","../package.json","../src/Telemetry.ts"],"sourcesContent":["// Bun polyfills `process.versions.node`, so detection keys off the globals instead.\nconst isBun = typeof Bun !== 'undefined'\nconst isDeno = 'Deno' in globalThis\n\n/**\n * The JavaScript runtime executing the current process: its name, version and whether it is Bun.\n *\n * @example\n * ```ts\n * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise\n * ```\n */\nexport const runtime = { isBun, ...detect() } as const\n\nfunction detect(): { name: 'bun' | 'deno' | 'node'; version: string } {\n if (isBun) return { name: 'bun', version: process.versions.bun ?? '' }\n if (isDeno) return { name: 'deno', version: (globalThis as { Deno?: { version?: { deno?: string } } }).Deno?.version?.deno ?? '' }\n return { name: 'node', version: process.versions?.node ?? '' }\n}\n","","import { randomBytes } from 'node:crypto'\nimport os from 'node:os'\nimport process from 'node:process'\nimport { getElapsedMs, isCIEnvironment, runtime } from '@internals/utils'\nimport { getAgentName } from './agent.ts'\nimport { version } from '../package.json'\n\n/** OpenTelemetry ingestion endpoint for anonymous usage telemetry. */\nconst OTLP_ENDPOINT = 'https://otlp.kubb.dev' as const\n\ntype TelemetryCommand = 'generate' | 'mcp' | 'studio' | 'validate'\n\ntype OtlpValue =\n | { stringValue: string }\n | { boolValue: boolean }\n | { intValue: number }\n | { arrayValue: { values: Array<OtlpValue> } }\n | { kvlistValue: { values: Array<OtlpKeyValue> } }\n\ntype OtlpKeyValue = {\n key: string\n value: OtlpValue\n}\n\ntype OtlpSpan = {\n traceId: string\n spanId: string\n name: string\n kind: 1\n startTimeUnixNano: string\n endTimeUnixNano: string\n attributes: Array<OtlpKeyValue>\n status: { code: 1 | 2 }\n}\n\ntype OtlpExportTraceServiceRequest = {\n resourceSpans: Array<{\n resource: { attributes: Array<OtlpKeyValue> }\n scopeSpans: Array<{\n scope: { name: string; version: string }\n spans: Array<OtlpSpan>\n }>\n }>\n}\n\n/**\n * Anonymous plugin name and options snapshot sent with each telemetry event.\n */\nexport type TelemetryPlugin = {\n /**\n * Plugin name as registered in the Kubb config, e.g. `'@kubb/plugin-ts'`.\n */\n name: string\n /**\n * Anonymized snapshot of the plugin options. Values are included but cannot be traced back to a user.\n */\n options: Record<string, unknown>\n}\n\n/**\n * Anonymous snapshot of a single Kubb run, built by {@link buildTelemetryEvent} and sent by {@link sendTelemetry}.\n */\ntype TelemetryEvent = {\n command: string\n kubbVersion: string\n /**\n * Major version of Node that executed the run, e.g. `'22'`.\n */\n nodeVersion: string\n /**\n * Name of the JavaScript runtime that executed the run, `'bun'`, `'deno'`, or `'node'`.\n */\n runtime: string\n /**\n * Major version of the active runtime, e.g. `'1'` under Bun or `'22'` under Node.\n */\n runtimeVersion: string\n platform: string\n ci: boolean\n /**\n * Name of the detected AI coding agent (e.g. `'claude'`, `'cursor'`), when the CLI is invoked\n * by one. `undefined` when run by a human or an unrecognized caller.\n */\n agent?: string\n plugins: Array<TelemetryPlugin>\n duration: number\n filesCreated: number\n status: 'success' | 'failed'\n}\n\n/**\n * Returns `true` when telemetry is disabled via `DO_NOT_TRACK` or `KUBB_DISABLE_TELEMETRY`.\n */\nexport function isDisabled(): boolean {\n return ['DO_NOT_TRACK', 'KUBB_DISABLE_TELEMETRY'].some((name) => ['1', 'true'].includes(process.env[name] ?? ''))\n}\n\n/**\n * Build an anonymous telemetry payload from a completed generation run.\n */\nexport function buildTelemetryEvent(options: {\n command: TelemetryCommand\n kubbVersion: string\n plugins?: Array<TelemetryPlugin>\n hrStart: [number, number]\n filesCreated?: number\n status: 'success' | 'failed'\n}): TelemetryEvent {\n const duration = Math.round(getElapsedMs(options.hrStart))\n\n return {\n command: options.command,\n kubbVersion: options.kubbVersion,\n nodeVersion: process.versions.node.split('.')[0] as string,\n runtime: runtime.name,\n runtimeVersion: runtime.version.split('.')[0] as string,\n platform: os.platform(),\n ci: isCIEnvironment(),\n agent: getAgentName(),\n plugins: options.plugins ?? [],\n duration,\n filesCreated: options.filesCreated ?? 0,\n status: options.status,\n }\n}\n\ntype TrackRunOptions = {\n command: TelemetryCommand\n /** `process.hrtime()` snapshot taken when the command started. */\n hrStart: [number, number]\n}\n\ntype RunResult = Pick<TelemetryEvent, 'status'> & Partial<Pick<TelemetryEvent, 'plugins' | 'filesCreated'>>\n\n/** Tracks one command run for the running CLI version; returns the reporter the command calls once it knows how it ended. */\nexport function trackRun({ command, hrStart }: TrackRunOptions): (result: RunResult) => Promise<void> {\n return (result) => sendTelemetry(buildTelemetryEvent({ command, kubbVersion: version, hrStart, ...result }))\n}\n\n/**\n * Convert a {@link TelemetryEvent} into an OTLP-compatible JSON trace payload.\n *\n * @see https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/\n */\nexport function buildOtlpPayload(event: TelemetryEvent): OtlpExportTraceServiceRequest {\n const traceId = randomBytes(16).toString('hex')\n const spanId = randomBytes(8).toString('hex')\n const endTimeNs = BigInt(Date.now()) * 1_000_000n\n const startTimeNs = endTimeNs - BigInt(event.duration) * 1_000_000n\n const pluginNames = [...new Set(event.plugins.map((plugin) => plugin.name))].sort()\n\n const attributes: Array<OtlpKeyValue> = [\n { key: 'kubb.command', value: { stringValue: event.command } },\n { key: 'kubb.version', value: { stringValue: event.kubbVersion } },\n { key: 'kubb.node_version', value: { stringValue: event.nodeVersion } },\n { key: 'kubb.runtime', value: { stringValue: event.runtime } },\n { key: 'kubb.runtime_version', value: { stringValue: event.runtimeVersion } },\n { key: 'kubb.platform', value: { stringValue: event.platform } },\n { key: 'kubb.ci', value: { boolValue: event.ci } },\n ...(event.agent ? [{ key: 'kubb.agent', value: { stringValue: event.agent } }] : []),\n { key: 'kubb.files_created', value: { intValue: event.filesCreated } },\n { key: 'kubb.status', value: { stringValue: event.status } },\n {\n key: 'kubb.plugins',\n value: { arrayValue: { values: pluginNames.map((name) => ({ stringValue: name })) } },\n },\n ...pluginNames.map((name) => ({ key: `kubb.plugin.${name}`, value: { boolValue: true } })),\n {\n key: 'kubb.plugin_options',\n value: {\n arrayValue: {\n values: event.plugins.map((p) => ({\n kvlistValue: {\n values: [\n { key: 'name', value: { stringValue: p.name } },\n {\n key: 'options',\n value: {\n stringValue: JSON.stringify({\n ...p.options,\n usedEnumNames: undefined,\n }),\n },\n },\n ],\n },\n })),\n },\n },\n },\n ]\n\n return {\n resourceSpans: [\n {\n resource: {\n attributes: [\n { key: 'service.name', value: { stringValue: 'kubb' } },\n {\n key: 'service.version',\n value: { stringValue: event.kubbVersion },\n },\n { key: 'telemetry.sdk.language', value: { stringValue: 'nodejs' } },\n ],\n },\n scopeSpans: [\n {\n scope: { name: 'kubb-core', version: event.kubbVersion },\n spans: [\n {\n traceId,\n spanId,\n name: event.command,\n kind: 1,\n startTimeUnixNano: String(startTimeNs),\n endTimeUnixNano: String(endTimeNs),\n attributes,\n status: {\n code: event.status === 'success' ? 1 : 2,\n },\n },\n ],\n },\n ],\n },\n ],\n }\n}\n\n/**\n * Send an anonymous telemetry event to the Kubb OTLP endpoint. Respects `DO_NOT_TRACK` and\n * `KUBB_DISABLE_TELEMETRY`, and fails silently so telemetry never interrupts a run. No file\n * paths, OpenAPI specs, or secrets are sent.\n */\nexport async function sendTelemetry(event: TelemetryEvent): Promise<void> {\n if (isDisabled()) {\n return\n }\n\n try {\n await fetch(`${OTLP_ENDPOINT}/v1/traces`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Kubb-Telemetry-Version': '1',\n 'Kubb-Telemetry-Source': 'kubb-cli',\n },\n body: JSON.stringify(buildOtlpPayload(event)),\n signal: AbortSignal.timeout(5_000),\n })\n } catch (_e) {\n // Fail silently, telemetry must never break the run\n }\n}\n"],"mappings":"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"}
@@ -4,77 +4,37 @@ import { randomBytes } from "node:crypto";
4
4
  import os from "node:os";
5
5
  import process$1 from "node:process";
6
6
  //#region ../../internals/utils/src/runtime.ts
7
+ const isBun = typeof Bun !== "undefined";
8
+ const isDeno = "Deno" in globalThis;
7
9
  /**
8
- * Detects the JavaScript runtime executing the current process and exposes its name and version.
10
+ * The JavaScript runtime executing the current process: its name, version and whether it is Bun.
9
11
  *
10
- * Prefer the shared {@link runtime} instance over constructing your own.
12
+ * @example
13
+ * ```ts
14
+ * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise
15
+ * ```
11
16
  */
12
- var Runtime = class {
13
- /**
14
- * `true` when the current process is running under Bun.
15
- *
16
- * Detection keys off the global `Bun` object rather than `process.versions`,
17
- * because Bun polyfills `process.versions.node` for Node compatibility and would
18
- * otherwise look like Node.
19
- *
20
- * @example
21
- * ```ts
22
- * if (runtime.isBun) {
23
- * await Bun.write(path, data)
24
- * }
25
- * ```
26
- */
27
- get isBun() {
28
- return typeof Bun !== "undefined";
29
- }
30
- /**
31
- * `true` when the current process is running under Deno.
32
- */
33
- get isDeno() {
34
- return typeof globalThis.Deno !== "undefined";
35
- }
36
- /**
37
- * `true` when the current process is running under Node.
38
- *
39
- * Bun and Deno are excluded first so a polyfilled `process` does not register as Node.
40
- */
41
- get isNode() {
42
- return !this.isBun && !this.isDeno && typeof process !== "undefined" && process.versions?.node != null;
43
- }
44
- /**
45
- * Name of the runtime executing the current process.
46
- *
47
- * @example
48
- * ```ts
49
- * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise
50
- * ```
51
- */
52
- get name() {
53
- if (this.isBun) return "bun";
54
- if (this.isDeno) return "deno";
55
- return "node";
56
- }
57
- /**
58
- * Version of the active runtime, or an empty string when it cannot be read.
59
- *
60
- * @example
61
- * ```ts
62
- * runtime.version // '1.3.11' under Bun, '22.22.2' under Node
63
- * ```
64
- */
65
- get version() {
66
- if (this.isBun) return process.versions.bun ?? "";
67
- if (this.isDeno) return globalThis.Deno?.version?.deno ?? "";
68
- return process.versions?.node ?? "";
69
- }
17
+ const runtime = {
18
+ isBun,
19
+ ...detect()
70
20
  };
71
- /**
72
- * Shared {@link Runtime} instance describing the JavaScript runtime executing the current process.
73
- */
74
- const runtime = new Runtime();
21
+ function detect() {
22
+ if (isBun) return {
23
+ name: "bun",
24
+ version: process.versions.bun ?? ""
25
+ };
26
+ if (isDeno) return {
27
+ name: "deno",
28
+ version: globalThis.Deno?.version?.deno ?? ""
29
+ };
30
+ return {
31
+ name: "node",
32
+ version: process.versions?.node ?? ""
33
+ };
34
+ }
75
35
  //#endregion
76
36
  //#region package.json
77
- var version = "5.9.0";
37
+ var version = "5.9.2";
78
38
  //#endregion
79
39
  //#region src/Telemetry.ts
80
40
  /** OpenTelemetry ingestion endpoint for anonymous usage telemetry. */
@@ -244,4 +204,4 @@ async function sendTelemetry(event) {
244
204
  //#endregion
245
205
  export { runtime as i, trackRun as n, version as r, isDisabled as t };
246
206
 
247
- //# sourceMappingURL=Telemetry-BivZAaw9.js.map
207
+ //# sourceMappingURL=Telemetry-DER8LIO5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Telemetry-DER8LIO5.js","names":["process"],"sources":["../../../internals/utils/src/runtime.ts","../package.json","../src/Telemetry.ts"],"sourcesContent":["// Bun polyfills `process.versions.node`, so detection keys off the globals instead.\nconst isBun = typeof Bun !== 'undefined'\nconst isDeno = 'Deno' in globalThis\n\n/**\n * The JavaScript runtime executing the current process: its name, version and whether it is Bun.\n *\n * @example\n * ```ts\n * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise\n * ```\n */\nexport const runtime = { isBun, ...detect() } as const\n\nfunction detect(): { name: 'bun' | 'deno' | 'node'; version: string } {\n if (isBun) return { name: 'bun', version: process.versions.bun ?? '' }\n if (isDeno) return { name: 'deno', version: (globalThis as { Deno?: { version?: { deno?: string } } }).Deno?.version?.deno ?? '' }\n return { name: 'node', version: process.versions?.node ?? '' }\n}\n","","import { randomBytes } from 'node:crypto'\nimport os from 'node:os'\nimport process from 'node:process'\nimport { getElapsedMs, isCIEnvironment, runtime } from '@internals/utils'\nimport { getAgentName } from './agent.ts'\nimport { version } from '../package.json'\n\n/** OpenTelemetry ingestion endpoint for anonymous usage telemetry. */\nconst OTLP_ENDPOINT = 'https://otlp.kubb.dev' as const\n\ntype TelemetryCommand = 'generate' | 'mcp' | 'studio' | 'validate'\n\ntype OtlpValue =\n | { stringValue: string }\n | { boolValue: boolean }\n | { intValue: number }\n | { arrayValue: { values: Array<OtlpValue> } }\n | { kvlistValue: { values: Array<OtlpKeyValue> } }\n\ntype OtlpKeyValue = {\n key: string\n value: OtlpValue\n}\n\ntype OtlpSpan = {\n traceId: string\n spanId: string\n name: string\n kind: 1\n startTimeUnixNano: string\n endTimeUnixNano: string\n attributes: Array<OtlpKeyValue>\n status: { code: 1 | 2 }\n}\n\ntype OtlpExportTraceServiceRequest = {\n resourceSpans: Array<{\n resource: { attributes: Array<OtlpKeyValue> }\n scopeSpans: Array<{\n scope: { name: string; version: string }\n spans: Array<OtlpSpan>\n }>\n }>\n}\n\n/**\n * Anonymous plugin name and options snapshot sent with each telemetry event.\n */\nexport type TelemetryPlugin = {\n /**\n * Plugin name as registered in the Kubb config, e.g. `'@kubb/plugin-ts'`.\n */\n name: string\n /**\n * Anonymized snapshot of the plugin options. Values are included but cannot be traced back to a user.\n */\n options: Record<string, unknown>\n}\n\n/**\n * Anonymous snapshot of a single Kubb run, built by {@link buildTelemetryEvent} and sent by {@link sendTelemetry}.\n */\ntype TelemetryEvent = {\n command: string\n kubbVersion: string\n /**\n * Major version of Node that executed the run, e.g. `'22'`.\n */\n nodeVersion: string\n /**\n * Name of the JavaScript runtime that executed the run, `'bun'`, `'deno'`, or `'node'`.\n */\n runtime: string\n /**\n * Major version of the active runtime, e.g. `'1'` under Bun or `'22'` under Node.\n */\n runtimeVersion: string\n platform: string\n ci: boolean\n /**\n * Name of the detected AI coding agent (e.g. `'claude'`, `'cursor'`), when the CLI is invoked\n * by one. `undefined` when run by a human or an unrecognized caller.\n */\n agent?: string\n plugins: Array<TelemetryPlugin>\n duration: number\n filesCreated: number\n status: 'success' | 'failed'\n}\n\n/**\n * Returns `true` when telemetry is disabled via `DO_NOT_TRACK` or `KUBB_DISABLE_TELEMETRY`.\n */\nexport function isDisabled(): boolean {\n return ['DO_NOT_TRACK', 'KUBB_DISABLE_TELEMETRY'].some((name) => ['1', 'true'].includes(process.env[name] ?? ''))\n}\n\n/**\n * Build an anonymous telemetry payload from a completed generation run.\n */\nexport function buildTelemetryEvent(options: {\n command: TelemetryCommand\n kubbVersion: string\n plugins?: Array<TelemetryPlugin>\n hrStart: [number, number]\n filesCreated?: number\n status: 'success' | 'failed'\n}): TelemetryEvent {\n const duration = Math.round(getElapsedMs(options.hrStart))\n\n return {\n command: options.command,\n kubbVersion: options.kubbVersion,\n nodeVersion: process.versions.node.split('.')[0] as string,\n runtime: runtime.name,\n runtimeVersion: runtime.version.split('.')[0] as string,\n platform: os.platform(),\n ci: isCIEnvironment(),\n agent: getAgentName(),\n plugins: options.plugins ?? [],\n duration,\n filesCreated: options.filesCreated ?? 0,\n status: options.status,\n }\n}\n\ntype TrackRunOptions = {\n command: TelemetryCommand\n /** `process.hrtime()` snapshot taken when the command started. */\n hrStart: [number, number]\n}\n\ntype RunResult = Pick<TelemetryEvent, 'status'> & Partial<Pick<TelemetryEvent, 'plugins' | 'filesCreated'>>\n\n/** Tracks one command run for the running CLI version; returns the reporter the command calls once it knows how it ended. */\nexport function trackRun({ command, hrStart }: TrackRunOptions): (result: RunResult) => Promise<void> {\n return (result) => sendTelemetry(buildTelemetryEvent({ command, kubbVersion: version, hrStart, ...result }))\n}\n\n/**\n * Convert a {@link TelemetryEvent} into an OTLP-compatible JSON trace payload.\n *\n * @see https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/\n */\nexport function buildOtlpPayload(event: TelemetryEvent): OtlpExportTraceServiceRequest {\n const traceId = randomBytes(16).toString('hex')\n const spanId = randomBytes(8).toString('hex')\n const endTimeNs = BigInt(Date.now()) * 1_000_000n\n const startTimeNs = endTimeNs - BigInt(event.duration) * 1_000_000n\n const pluginNames = [...new Set(event.plugins.map((plugin) => plugin.name))].sort()\n\n const attributes: Array<OtlpKeyValue> = [\n { key: 'kubb.command', value: { stringValue: event.command } },\n { key: 'kubb.version', value: { stringValue: event.kubbVersion } },\n { key: 'kubb.node_version', value: { stringValue: event.nodeVersion } },\n { key: 'kubb.runtime', value: { stringValue: event.runtime } },\n { key: 'kubb.runtime_version', value: { stringValue: event.runtimeVersion } },\n { key: 'kubb.platform', value: { stringValue: event.platform } },\n { key: 'kubb.ci', value: { boolValue: event.ci } },\n ...(event.agent ? [{ key: 'kubb.agent', value: { stringValue: event.agent } }] : []),\n { key: 'kubb.files_created', value: { intValue: event.filesCreated } },\n { key: 'kubb.status', value: { stringValue: event.status } },\n {\n key: 'kubb.plugins',\n value: { arrayValue: { values: pluginNames.map((name) => ({ stringValue: name })) } },\n },\n ...pluginNames.map((name) => ({ key: `kubb.plugin.${name}`, value: { boolValue: true } })),\n {\n key: 'kubb.plugin_options',\n value: {\n arrayValue: {\n values: event.plugins.map((p) => ({\n kvlistValue: {\n values: [\n { key: 'name', value: { stringValue: p.name } },\n {\n key: 'options',\n value: {\n stringValue: JSON.stringify({\n ...p.options,\n usedEnumNames: undefined,\n }),\n },\n },\n ],\n },\n })),\n },\n },\n },\n ]\n\n return {\n resourceSpans: [\n {\n resource: {\n attributes: [\n { key: 'service.name', value: { stringValue: 'kubb' } },\n {\n key: 'service.version',\n value: { stringValue: event.kubbVersion },\n },\n { key: 'telemetry.sdk.language', value: { stringValue: 'nodejs' } },\n ],\n },\n scopeSpans: [\n {\n scope: { name: 'kubb-core', version: event.kubbVersion },\n spans: [\n {\n traceId,\n spanId,\n name: event.command,\n kind: 1,\n startTimeUnixNano: String(startTimeNs),\n endTimeUnixNano: String(endTimeNs),\n attributes,\n status: {\n code: event.status === 'success' ? 1 : 2,\n },\n },\n ],\n },\n ],\n },\n ],\n }\n}\n\n/**\n * Send an anonymous telemetry event to the Kubb OTLP endpoint. Respects `DO_NOT_TRACK` and\n * `KUBB_DISABLE_TELEMETRY`, and fails silently so telemetry never interrupts a run. No file\n * paths, OpenAPI specs, or secrets are sent.\n */\nexport async function sendTelemetry(event: TelemetryEvent): Promise<void> {\n if (isDisabled()) {\n return\n }\n\n try {\n await fetch(`${OTLP_ENDPOINT}/v1/traces`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Kubb-Telemetry-Version': '1',\n 'Kubb-Telemetry-Source': 'kubb-cli',\n },\n body: JSON.stringify(buildOtlpPayload(event)),\n signal: AbortSignal.timeout(5_000),\n })\n } catch (_e) {\n // Fail silently, telemetry must never break the run\n }\n}\n"],"mappings":";;;;;;AACA,MAAM,QAAQ,OAAO,QAAQ;AAC7B,MAAM,SAAS,UAAU;;;;;;;;;AAUzB,MAAa,UAAU;CAAE;CAAO,GAAG,OAAO;AAAE;AAE5C,SAAS,SAA6D;CACpE,IAAI,OAAO,OAAO;EAAE,MAAM;EAAO,SAAS,QAAQ,SAAS,OAAO;CAAG;CACrE,IAAI,QAAQ,OAAO;EAAE,MAAM;EAAQ,SAAU,WAA0D,MAAM,SAAS,QAAQ;CAAG;CACjI,OAAO;EAAE,MAAM;EAAQ,SAAS,QAAQ,UAAU,QAAQ;CAAG;AAC/D;;;;;;;AEVA,MAAM,gBAAgB;;;;AAqFtB,SAAgB,aAAsB;CACpC,OAAO,CAAC,gBAAgB,wBAAwB,CAAC,CAAC,MAAM,SAAS,CAAC,KAAK,MAAM,CAAC,CAAC,SAASA,UAAQ,IAAI,SAAS,EAAE,CAAC;AAClH;;;;AAKA,SAAgB,oBAAoB,SAOjB;CACjB,MAAM,WAAW,KAAK,MAAM,aAAa,QAAQ,OAAO,CAAC;CAEzD,OAAO;EACL,SAAS,QAAQ;EACjB,aAAa,QAAQ;EACrB,aAAaA,UAAQ,SAAS,KAAK,MAAM,GAAG,CAAC,CAAC;EAC9C,SAAS,QAAQ;EACjB,gBAAgB,QAAQ,QAAQ,MAAM,GAAG,CAAC,CAAC;EAC3C,UAAU,GAAG,SAAS;EACtB,IAAI,gBAAgB;EACpB,OAAO,aAAa;EACpB,SAAS,QAAQ,WAAW,CAAC;EAC7B;EACA,cAAc,QAAQ,gBAAgB;EACtC,QAAQ,QAAQ;CAClB;AACF;;AAWA,SAAgB,SAAS,EAAE,SAAS,WAAkE;CACpG,QAAQ,WAAW,cAAc,oBAAoB;EAAE;EAAS,aAAa;EAAS;EAAS,GAAG;CAAO,CAAC,CAAC;AAC7G;;;;;;AAOA,SAAgB,iBAAiB,OAAsD;CACrF,MAAM,UAAU,YAAY,EAAE,CAAC,CAAC,SAAS,KAAK;CAC9C,MAAM,SAAS,YAAY,CAAC,CAAC,CAAC,SAAS,KAAK;CAC5C,MAAM,YAAY,OAAO,KAAK,IAAI,CAAC,IAAI;CACvC,MAAM,cAAc,YAAY,OAAO,MAAM,QAAQ,IAAI;CACzD,MAAM,cAAc,CAAC,GAAG,IAAI,IAAI,MAAM,QAAQ,KAAK,WAAW,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK;CAElF,MAAM,aAAkC;EACtC;GAAE,KAAK;GAAgB,OAAO,EAAE,aAAa,MAAM,QAAQ;EAAE;EAC7D;GAAE,KAAK;GAAgB,OAAO,EAAE,aAAa,MAAM,YAAY;EAAE;EACjE;GAAE,KAAK;GAAqB,OAAO,EAAE,aAAa,MAAM,YAAY;EAAE;EACtE;GAAE,KAAK;GAAgB,OAAO,EAAE,aAAa,MAAM,QAAQ;EAAE;EAC7D;GAAE,KAAK;GAAwB,OAAO,EAAE,aAAa,MAAM,eAAe;EAAE;EAC5E;GAAE,KAAK;GAAiB,OAAO,EAAE,aAAa,MAAM,SAAS;EAAE;EAC/D;GAAE,KAAK;GAAW,OAAO,EAAE,WAAW,MAAM,GAAG;EAAE;EACjD,GAAI,MAAM,QAAQ,CAAC;GAAE,KAAK;GAAc,OAAO,EAAE,aAAa,MAAM,MAAM;EAAE,CAAC,IAAI,CAAC;EAClF;GAAE,KAAK;GAAsB,OAAO,EAAE,UAAU,MAAM,aAAa;EAAE;EACrE;GAAE,KAAK;GAAe,OAAO,EAAE,aAAa,MAAM,OAAO;EAAE;EAC3D;GACE,KAAK;GACL,OAAO,EAAE,YAAY,EAAE,QAAQ,YAAY,KAAK,UAAU,EAAE,aAAa,KAAK,EAAE,EAAE,EAAE;EACtF;EACA,GAAG,YAAY,KAAK,UAAU;GAAE,KAAK,eAAe;GAAQ,OAAO,EAAE,WAAW,KAAK;EAAE,EAAE;EACzF;GACE,KAAK;GACL,OAAO,EACL,YAAY,EACV,QAAQ,MAAM,QAAQ,KAAK,OAAO,EAChC,aAAa,EACX,QAAQ,CACN;IAAE,KAAK;IAAQ,OAAO,EAAE,aAAa,EAAE,KAAK;GAAE,GAC9C;IACE,KAAK;IACL,OAAO,EACL,aAAa,KAAK,UAAU;KAC1B,GAAG,EAAE;KACL,eAAe,KAAA;IACjB,CAAC,EACH;GACF,CACF,EACF,EACF,EAAE,EACJ,EACF;EACF;CACF;CAEA,OAAO,EACL,eAAe,CACb;EACE,UAAU,EACR,YAAY;GACV;IAAE,KAAK;IAAgB,OAAO,EAAE,aAAa,OAAO;GAAE;GACtD;IACE,KAAK;IACL,OAAO,EAAE,aAAa,MAAM,YAAY;GAC1C;GACA;IAAE,KAAK;IAA0B,OAAO,EAAE,aAAa,SAAS;GAAE;EACpE,EACF;EACA,YAAY,CACV;GACE,OAAO;IAAE,MAAM;IAAa,SAAS,MAAM;GAAY;GACvD,OAAO,CACL;IACE;IACA;IACA,MAAM,MAAM;IACZ,MAAM;IACN,mBAAmB,OAAO,WAAW;IACrC,iBAAiB,OAAO,SAAS;IACjC;IACA,QAAQ,EACN,MAAM,MAAM,WAAW,YAAY,IAAI,EACzC;GACF,CACF;EACF,CACF;CACF,CACF,EACF;AACF;;;;;;AAOA,eAAsB,cAAc,OAAsC;CACxE,IAAI,WAAW,GACb;CAGF,IAAI;EACF,MAAM,MAAM,GAAG,cAAc,aAAa;GACxC,QAAQ;GACR,SAAS;IACP,gBAAgB;IAChB,0BAA0B;IAC1B,yBAAyB;GAC3B;GACA,MAAM,KAAK,UAAU,iBAAiB,KAAK,CAAC;GAC5C,QAAQ,YAAY,QAAQ,GAAK;EACnC,CAAC;CACH,SAAS,IAAI,CAEb;AACF"}
@@ -1,5 +1,5 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
- import { l as getProjectKubbHome, o as prepareConnection } from "./run-BF2Wq1Io.js";
2
+ import { l as getProjectKubbHome, o as prepareConnection } from "./run-BQQhNg8I.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-uIIElWXl.js.map
249
+ //# sourceMappingURL=background-B0YbkZ0s.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"background-uIIElWXl.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-B0YbkZ0s.js","names":["connectSocket","delay"],"sources":["../src/runners/studio/background.ts"],"sourcesContent":["import { hash, randomBytes } from 'node:crypto'\nimport { readFile, rename, writeFile } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport { connect as connectSocket, createServer } from 'node:net'\nimport path from 'node:path'\nimport { setTimeout as delay } from 'node:timers/promises'\nimport { x } from 'tinyexec'\nimport { getProjectKubbHome } from './credentials.ts'\nimport { prepareConnection, type PreparedConnection, type StudioOptions, type WorkerState } from './run.ts'\n\nexport type WorkerRecord = { id: string; pid: number; port: number; state: WorkerState }\nconst states: Array<WorkerState> = ['starting', 'connected', 'reconnecting', 'authentication required', 'stopped']\nexport const getWorkerLogPath = () => path.join(getProjectKubbHome(), 'worker.log')\nconst statePath = () => path.join(getProjectKubbHome(), 'worker.json')\n\nasync function readWorker(): Promise<WorkerRecord | null> {\n try {\n const value: unknown = JSON.parse(await readFile(statePath(), 'utf8'))\n if (!value || typeof value !== 'object') return null\n const record = value as Partial<WorkerRecord>\n return typeof record.id === 'string' &&\n /^[a-f0-9]{32}$/.test(record.id) &&\n Number.isInteger(record.pid) &&\n (record.pid ?? 0) > 1 &&\n Number.isInteger(record.port) &&\n (record.port ?? 0) > 0 &&\n (record.port ?? 0) <= 65535 &&\n states.includes(record.state as WorkerState)\n ? (record as WorkerRecord)\n : null\n } catch {\n return null\n }\n}\n\nfunction isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch (error) {\n return (error as NodeJS.ErrnoException).code === 'EPERM'\n }\n}\n\n/** Authenticated loopback IPC; a stored PID never authorizes sending a process signal. */\nfunction requestWorker(record: WorkerRecord, command: 'status' | 'stop'): Promise<WorkerRecord> {\n return new Promise((resolve, reject) => {\n const socket = connectSocket({ host: '127.0.0.1', port: record.port })\n let received = ''\n socket.setTimeout(2_000, () => socket.destroy(new Error('Worker control timed out')))\n socket.once('error', reject)\n socket.once('connect', () => socket.write(JSON.stringify({ id: record.id, command }) + '\\n'))\n socket.on('data', (chunk: Buffer) => {\n received += chunk.toString()\n if (received.length > 4096) socket.destroy(new Error('Invalid worker response'))\n })\n socket.once('end', () => {\n try {\n const response = JSON.parse(received) as WorkerRecord\n if (response.id !== record.id || response.pid !== record.pid || !states.includes(response.state)) throw new Error('Worker identity changed')\n resolve(response)\n } catch (error) {\n reject(error)\n }\n })\n })\n}\n\nexport async function getWorkerStatus(): Promise<{ running: boolean; state: WorkerState; pid?: number }> {\n const record = await readWorker()\n if (!record) return { running: false, state: 'stopped' }\n try {\n const response = await requestWorker(record, 'status')\n return { running: true, state: response.state, pid: response.pid }\n } catch {\n return { running: false, state: record.state === 'authentication required' ? record.state : 'stopped' }\n }\n}\n\nexport async function stopWorker(): Promise<void> {\n const record = await readWorker()\n if (!record) return\n try {\n await requestWorker(record, 'stop')\n } catch (error) {\n if (\n (error as NodeJS.ErrnoException).code !== 'ECONNREFUSED' &&\n isAlive(record.pid) &&\n record.state !== 'stopped' &&\n record.state !== 'authentication required'\n ) {\n throw new Error('Cannot verify the background worker. No process was signaled.')\n }\n return\n }\n const deadline = Date.now() + 15_000\n while (Date.now() < deadline) {\n try {\n await requestWorker(record, 'status')\n } catch {\n return\n }\n await delay(100)\n }\n throw new Error('The worker has not finished shutting down. Check worker.log and try again.')\n}\n\n/** The listening port is the project lock, so stale state never needs a PID-based takeover. */\nexport async function serveWorker(shutdown: AbortController) {\n const record: WorkerRecord = { id: randomBytes(16).toString('hex'), pid: process.pid, port: 0, state: 'starting' }\n const server = createServer((socket) => {\n let input = ''\n socket.setTimeout(2_000, () => socket.destroy())\n socket.on('error', () => {})\n socket.on('data', (chunk: Buffer) => {\n input += chunk.toString()\n if (input.length > 4096) {\n socket.destroy()\n return\n }\n if (!input.includes('\\n')) return\n try {\n const request = JSON.parse(input) as { id?: unknown; command?: unknown }\n if (request.id !== record.id || !['status', 'stop'].includes(String(request.command))) {\n socket.destroy()\n return\n }\n socket.end(JSON.stringify(record))\n if (request.command === 'stop') shutdown.abort()\n } catch {\n socket.destroy()\n }\n })\n })\n // Hash the project directory to choose its loopback port; fail on collisions.\n const port = 20_000 + (Number.parseInt(hash('sha256', getProjectKubbHome()).slice(0, 8), 16) % 30_000)\n try {\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, '127.0.0.1', resolve)\n })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EADDRINUSE') throw error\n // Let a simultaneous starter finish writing its record before checking ownership.\n await delay(100)\n const existing = await readWorker()\n if (existing?.port === port) {\n try {\n return { existing: await requestWorker(existing, 'status') }\n } catch {\n /* Refuse an unverified listener. */\n }\n }\n throw new Error('The project control port is occupied or another worker is starting. Try again after stopping that listener.')\n }\n record.port = port\n let saving = Promise.resolve()\n const save = () => {\n const value = JSON.stringify(record)\n saving = saving.then(async () => {\n const temporary = `${statePath()}.${record.id}`\n await writeFile(temporary, value, { mode: 0o600 })\n await rename(temporary, statePath())\n })\n return saving\n }\n try {\n await save()\n } catch (error) {\n server.close()\n throw error\n }\n return {\n async state(state: WorkerState) {\n record.state = state\n await save()\n },\n async close() {\n try {\n if (record.state !== 'authentication required') {\n record.state = 'stopped'\n await save()\n }\n } finally {\n await new Promise<void>((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())))\n }\n },\n }\n}\n\nexport type WorkerLaunch = { options: StudioOptions; prepared: PreparedConnection }\n\nexport async function startWorker(options: StudioOptions): Promise<void> {\n const current = await getWorkerStatus()\n if (current.running) {\n console.log(`Already running (${current.state}, PID ${current.pid}).`)\n return\n }\n const prepared = await prepareConnection(options)\n const entry = path.join(path.dirname(createRequire(import.meta.url).resolve('@kubb/cli/package.json')), 'dist', 'studioWorker.js')\n const child = x(process.execPath, [...process.execArgv, entry], {\n nodeOptions: { cwd: process.cwd(), detached: true, stdio: ['ignore', 'ignore', 'ignore', 'ipc'] },\n }).process\n if (!child) throw new Error('Background worker failed to start')\n try {\n const started = new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => done(new Error('Background worker startup timed out')), 20_000)\n const done = (error?: Error) => {\n clearTimeout(timer)\n child.removeListener('error', failed)\n child.removeListener('exit', exited)\n child.removeListener('message', ready)\n if (error) reject(error)\n else resolve()\n }\n const failed = (error: Error) => done(error)\n const exited = () => done(new Error(`Background worker exited during startup. Check ${getWorkerLogPath()}`))\n child.once('error', failed)\n child.once('exit', exited)\n const ready = (message: unknown) => {\n if (!message || typeof message !== 'object' || !('started' in message) || message.started !== true)\n return done(new Error('Invalid worker startup response'))\n done()\n }\n child.once('message', ready)\n child.send({ options: { ...options, autoOpen: false }, prepared } satisfies WorkerLaunch, (error) => {\n if (error) done(error)\n })\n })\n await started\n if (child.connected) child.disconnect()\n child.unref()\n const status = await getWorkerStatus()\n console.log(`Background worker ${status.state} (PID ${status.pid ?? child.pid}). Logs: ${getWorkerLogPath()}`)\n } catch (error) {\n // This is the child we just spawned, not a PID recovered from disk.\n child.kill('SIGTERM')\n throw error\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  const require_agent = require("./agent-DElUuYuy.cjs");
2
- const require_run = require("./run-DSeEZTnT.cjs");
2
+ const require_run = require("./run-C8dyBAPb.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-Cd2TGkLg.cjs.map
172
+ //# sourceMappingURL=background-Bh4FDWa3.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"background-Cd2TGkLg.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-Bh4FDWa3.cjs","names":["path","getProjectKubbHome","readFile","connectSocket","delay","prepareConnection","createRequire","x"],"sources":["../src/runners/studio/background.ts"],"sourcesContent":["import { hash, randomBytes } from 'node:crypto'\nimport { readFile, rename, writeFile } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport { connect as connectSocket, createServer } from 'node:net'\nimport path from 'node:path'\nimport { setTimeout as delay } from 'node:timers/promises'\nimport { x } from 'tinyexec'\nimport { getProjectKubbHome } from './credentials.ts'\nimport { prepareConnection, type PreparedConnection, type StudioOptions, type WorkerState } from './run.ts'\n\nexport type WorkerRecord = { id: string; pid: number; port: number; state: WorkerState }\nconst states: Array<WorkerState> = ['starting', 'connected', 'reconnecting', 'authentication required', 'stopped']\nexport const getWorkerLogPath = () => path.join(getProjectKubbHome(), 'worker.log')\nconst statePath = () => path.join(getProjectKubbHome(), 'worker.json')\n\nasync function readWorker(): Promise<WorkerRecord | null> {\n try {\n const value: unknown = JSON.parse(await readFile(statePath(), 'utf8'))\n if (!value || typeof value !== 'object') return null\n const record = value as Partial<WorkerRecord>\n return typeof record.id === 'string' &&\n /^[a-f0-9]{32}$/.test(record.id) &&\n Number.isInteger(record.pid) &&\n (record.pid ?? 0) > 1 &&\n Number.isInteger(record.port) &&\n (record.port ?? 0) > 0 &&\n (record.port ?? 0) <= 65535 &&\n states.includes(record.state as WorkerState)\n ? (record as WorkerRecord)\n : null\n } catch {\n return null\n }\n}\n\nfunction isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch (error) {\n return (error as NodeJS.ErrnoException).code === 'EPERM'\n }\n}\n\n/** Authenticated loopback IPC; a stored PID never authorizes sending a process signal. */\nfunction requestWorker(record: WorkerRecord, command: 'status' | 'stop'): Promise<WorkerRecord> {\n return new Promise((resolve, reject) => {\n const socket = connectSocket({ host: '127.0.0.1', port: record.port })\n let received = ''\n socket.setTimeout(2_000, () => socket.destroy(new Error('Worker control timed out')))\n socket.once('error', reject)\n socket.once('connect', () => socket.write(JSON.stringify({ id: record.id, command }) + '\\n'))\n socket.on('data', (chunk: Buffer) => {\n received += chunk.toString()\n if (received.length > 4096) socket.destroy(new Error('Invalid worker response'))\n })\n socket.once('end', () => {\n try {\n const response = JSON.parse(received) as WorkerRecord\n if (response.id !== record.id || response.pid !== record.pid || !states.includes(response.state)) throw new Error('Worker identity changed')\n resolve(response)\n } catch (error) {\n reject(error)\n }\n })\n })\n}\n\nexport async function getWorkerStatus(): Promise<{ running: boolean; state: WorkerState; pid?: number }> {\n const record = await readWorker()\n if (!record) return { running: false, state: 'stopped' }\n try {\n const response = await requestWorker(record, 'status')\n return { running: true, state: response.state, pid: response.pid }\n } catch {\n return { running: false, state: record.state === 'authentication required' ? record.state : 'stopped' }\n }\n}\n\nexport async function stopWorker(): Promise<void> {\n const record = await readWorker()\n if (!record) return\n try {\n await requestWorker(record, 'stop')\n } catch (error) {\n if (\n (error as NodeJS.ErrnoException).code !== 'ECONNREFUSED' &&\n isAlive(record.pid) &&\n record.state !== 'stopped' &&\n record.state !== 'authentication required'\n ) {\n throw new Error('Cannot verify the background worker. No process was signaled.')\n }\n return\n }\n const deadline = Date.now() + 15_000\n while (Date.now() < deadline) {\n try {\n await requestWorker(record, 'status')\n } catch {\n return\n }\n await delay(100)\n }\n throw new Error('The worker has not finished shutting down. Check worker.log and try again.')\n}\n\n/** The listening port is the project lock, so stale state never needs a PID-based takeover. */\nexport async function serveWorker(shutdown: AbortController) {\n const record: WorkerRecord = { id: randomBytes(16).toString('hex'), pid: process.pid, port: 0, state: 'starting' }\n const server = createServer((socket) => {\n let input = ''\n socket.setTimeout(2_000, () => socket.destroy())\n socket.on('error', () => {})\n socket.on('data', (chunk: Buffer) => {\n input += chunk.toString()\n if (input.length > 4096) {\n socket.destroy()\n return\n }\n if (!input.includes('\\n')) return\n try {\n const request = JSON.parse(input) as { id?: unknown; command?: unknown }\n if (request.id !== record.id || !['status', 'stop'].includes(String(request.command))) {\n socket.destroy()\n return\n }\n socket.end(JSON.stringify(record))\n if (request.command === 'stop') shutdown.abort()\n } catch {\n socket.destroy()\n }\n })\n })\n // Hash the project directory to choose its loopback port; fail on collisions.\n const port = 20_000 + (Number.parseInt(hash('sha256', getProjectKubbHome()).slice(0, 8), 16) % 30_000)\n try {\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, '127.0.0.1', resolve)\n })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EADDRINUSE') throw error\n // Let a simultaneous starter finish writing its record before checking ownership.\n await delay(100)\n const existing = await readWorker()\n if (existing?.port === port) {\n try {\n return { existing: await requestWorker(existing, 'status') }\n } catch {\n /* Refuse an unverified listener. */\n }\n }\n throw new Error('The project control port is occupied or another worker is starting. Try again after stopping that listener.')\n }\n record.port = port\n let saving = Promise.resolve()\n const save = () => {\n const value = JSON.stringify(record)\n saving = saving.then(async () => {\n const temporary = `${statePath()}.${record.id}`\n await writeFile(temporary, value, { mode: 0o600 })\n await rename(temporary, statePath())\n })\n return saving\n }\n try {\n await save()\n } catch (error) {\n server.close()\n throw error\n }\n return {\n async state(state: WorkerState) {\n record.state = state\n await save()\n },\n async close() {\n try {\n if (record.state !== 'authentication required') {\n record.state = 'stopped'\n await save()\n }\n } finally {\n await new Promise<void>((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())))\n }\n },\n }\n}\n\nexport type WorkerLaunch = { options: StudioOptions; prepared: PreparedConnection }\n\nexport async function startWorker(options: StudioOptions): Promise<void> {\n const current = await getWorkerStatus()\n if (current.running) {\n console.log(`Already running (${current.state}, PID ${current.pid}).`)\n return\n }\n const prepared = await prepareConnection(options)\n const entry = path.join(path.dirname(createRequire(import.meta.url).resolve('@kubb/cli/package.json')), 'dist', 'studioWorker.js')\n const child = x(process.execPath, [...process.execArgv, entry], {\n nodeOptions: { cwd: process.cwd(), detached: true, stdio: ['ignore', 'ignore', 'ignore', 'ipc'] },\n }).process\n if (!child) throw new Error('Background worker failed to start')\n try {\n const started = new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => done(new Error('Background worker startup timed out')), 20_000)\n const done = (error?: Error) => {\n clearTimeout(timer)\n child.removeListener('error', failed)\n child.removeListener('exit', exited)\n child.removeListener('message', ready)\n if (error) reject(error)\n else resolve()\n }\n const failed = (error: Error) => done(error)\n const exited = () => done(new Error(`Background worker exited during startup. Check ${getWorkerLogPath()}`))\n child.once('error', failed)\n child.once('exit', exited)\n const ready = (message: unknown) => {\n if (!message || typeof message !== 'object' || !('started' in message) || message.started !== true)\n return done(new Error('Invalid worker startup response'))\n done()\n }\n child.once('message', ready)\n child.send({ options: { ...options, autoOpen: false }, prepared } satisfies WorkerLaunch, (error) => {\n if (error) done(error)\n })\n })\n await started\n if (child.connected) child.disconnect()\n child.unref()\n const status = await getWorkerStatus()\n console.log(`Background worker ${status.state} (PID ${status.pid ?? child.pid}). Logs: ${getWorkerLogPath()}`)\n } catch (error) {\n // This is the child we just spawned, not a PID recovered from disk.\n child.kill('SIGTERM')\n throw error\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { n as getWorkerStatus } from "./background-B0YbkZ0s.js";
@@ -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-BF2Wq1Io.js";
3
- import { a as stopWorker, i as startWorker, n as getWorkerStatus, t as getWorkerLogPath } from "./background-uIIElWXl.js";
2
+ import { a as login, c as clearCredentials, n as createStudioOptions, r as formatPermissionRows, s as run, t as connect, u as readCredentials } from "./run-BQQhNg8I.js";
3
+ import { a as stopWorker, i as startWorker, n as getWorkerStatus, t as getWorkerLogPath } from "./background-B0YbkZ0s.js";
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-BlNFxWKB.js.map
81
+ //# sourceMappingURL=commands-BegVe5Mt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands-BlNFxWKB.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-BegVe5Mt.js","names":[],"sources":["../src/runners/studio/commands.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport type { CommandRunner } from 'gunshi'\nimport type { command as connectCommand } from '../../commands/studio/connect.ts'\nimport type { command as logoutCommand } from '../../commands/studio/logout.ts'\nimport type { command as statusCommand } from '../../commands/studio/status.ts'\nimport { getWorkerLogPath, getWorkerStatus, startWorker, stopWorker } from './background.ts'\nimport { clearCredentials, readCredentials } from './credentials.ts'\nimport { connect, createStudioOptions, formatPermissionRows, login, run, type StudioOptions } from './run.ts'\n\ntype Runner<T extends { args: object }> = CommandRunner<{ args: T['args']; extensions: {} }>\n\n/** Reports the paired agent and any saved permissions for the current project. */\nasync function status(options: StudioOptions): Promise<void> {\n const credentials = await readCredentials()\n\n if (!credentials) {\n console.log('Not paired. Run `kubb studio login`.')\n\n return\n }\n\n console.log(`Paired with ${credentials.studioUrl} as ${styleText('cyan', credentials.agentSlug || credentials.agentId)}`)\n\n if (credentials.studioUrl !== options.studioUrl) {\n console.log(styleText('yellow', `Connecting to ${options.studioUrl} needs pairing again.`))\n }\n\n const remembered = credentials.projects?.[process.cwd()]\n\n if (!remembered) {\n console.log(styleText('dim', 'No saved permissions for this project. Run `kubb studio` to connect and choose.'))\n\n return\n }\n\n console.log(styleText('dim', 'Saved permissions'))\n\n for (const row of formatPermissionRows({\n allowRead: remembered.allowRead === true,\n allowWrite: remembered.allowWrite === true,\n allowConfigEdit: remembered.allowConfigEdit === true,\n allowExec: remembered.allowExec === true,\n })) {\n console.log(row)\n }\n}\n\nexport const connectRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => connect(options), block: true })\n}\n\nexport const loginRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => login(options) })\n}\n\nexport const logoutRunner: Runner<typeof logoutCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({\n options,\n action: async () => {\n await stopWorker()\n await clearCredentials()\n console.log('Signed out of Kubb Studio.')\n },\n })\n}\n\nexport const startRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => startWorker(options) })\n}\n\nexport const statusRunner: Runner<typeof statusCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({\n options,\n action: async () => {\n const worker = await getWorkerStatus()\n console.log(`Background connection: ${worker.state}${worker.running ? ` (PID ${worker.pid})` : ''}`)\n console.log(`Logs: ${getWorkerLogPath()}`)\n await status(options)\n },\n })\n}\n\nexport async function stopRunner(): Promise<void> {\n await stopWorker()\n console.log('Background connection stopped.')\n}\n"],"mappings":";;;;;;;AAaA,eAAe,OAAO,SAAuC;CAC3D,MAAM,cAAc,MAAM,gBAAgB;CAE1C,IAAI,CAAC,aAAa;EAChB,QAAQ,IAAI,sCAAsC;EAElD;CACF;CAEA,QAAQ,IAAI,eAAe,YAAY,UAAU,MAAM,UAAU,QAAQ,YAAY,aAAa,YAAY,OAAO,GAAG;CAExH,IAAI,YAAY,cAAc,QAAQ,WACpC,QAAQ,IAAI,UAAU,UAAU,iBAAiB,QAAQ,UAAU,sBAAsB,CAAC;CAG5F,MAAM,aAAa,YAAY,WAAW,QAAQ,IAAI;CAEtD,IAAI,CAAC,YAAY;EACf,QAAQ,IAAI,UAAU,OAAO,iFAAiF,CAAC;EAE/G;CACF;CAEA,QAAQ,IAAI,UAAU,OAAO,mBAAmB,CAAC;CAEjD,KAAK,MAAM,OAAO,qBAAqB;EACrC,WAAW,WAAW,cAAc;EACpC,YAAY,WAAW,eAAe;EACtC,iBAAiB,WAAW,oBAAoB;EAChD,WAAW,WAAW,cAAc;CACtC,CAAC,GACC,QAAQ,IAAI,GAAG;AAEnB;AAEA,MAAa,gBAA+C,OAAO,EAAE,aAAa;CAChF,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EAAE;EAAS,cAAc,QAAQ,OAAO;EAAG,OAAO;CAAK,CAAC;AACpE;AAEA,MAAa,cAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EAAE;EAAS,cAAc,MAAM,OAAO;CAAE,CAAC;AACrD;AAEA,MAAa,eAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EACR;EACA,QAAQ,YAAY;GAClB,MAAM,WAAW;GACjB,MAAM,iBAAiB;GACvB,QAAQ,IAAI,4BAA4B;EAC1C;CACF,CAAC;AACH;AAEA,MAAa,cAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EAAE;EAAS,cAAc,YAAY,OAAO;CAAE,CAAC;AAC3D;AAEA,MAAa,eAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAU,oBAAoB,MAAM;CAC1C,MAAM,IAAI;EACR;EACA,QAAQ,YAAY;GAClB,MAAM,SAAS,MAAM,gBAAgB;GACrC,QAAQ,IAAI,0BAA0B,OAAO,QAAQ,OAAO,UAAU,SAAS,OAAO,IAAI,KAAK,IAAI;GACnG,QAAQ,IAAI,SAAS,iBAAiB,GAAG;GACzC,MAAM,OAAO,OAAO;EACtB;CACF,CAAC;AACH;AAEA,eAAsB,aAA4B;CAChD,MAAM,WAAW;CACjB,QAAQ,IAAI,gCAAgC;AAC9C"}
@@ -1,6 +1,6 @@
1
1
  const require_agent = require("./agent-DElUuYuy.cjs");
2
- const require_run = require("./run-DSeEZTnT.cjs");
3
- const require_background = require("./background-Cd2TGkLg.cjs");
2
+ const require_run = require("./run-C8dyBAPb.cjs");
3
+ const require_background = require("./background-Bh4FDWa3.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-ID-cYLXW.cjs.map
87
+ //# sourceMappingURL=commands-hXDwA0zn.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands-ID-cYLXW.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-hXDwA0zn.cjs","names":["readCredentials","styleText","process","formatPermissionRows","createStudioOptions","run","connect","login","stopWorker","clearCredentials","startWorker","getWorkerStatus","getWorkerLogPath"],"sources":["../src/runners/studio/commands.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport type { CommandRunner } from 'gunshi'\nimport type { command as connectCommand } from '../../commands/studio/connect.ts'\nimport type { command as logoutCommand } from '../../commands/studio/logout.ts'\nimport type { command as statusCommand } from '../../commands/studio/status.ts'\nimport { getWorkerLogPath, getWorkerStatus, startWorker, stopWorker } from './background.ts'\nimport { clearCredentials, readCredentials } from './credentials.ts'\nimport { connect, createStudioOptions, formatPermissionRows, login, run, type StudioOptions } from './run.ts'\n\ntype Runner<T extends { args: object }> = CommandRunner<{ args: T['args']; extensions: {} }>\n\n/** Reports the paired agent and any saved permissions for the current project. */\nasync function status(options: StudioOptions): Promise<void> {\n const credentials = await readCredentials()\n\n if (!credentials) {\n console.log('Not paired. Run `kubb studio login`.')\n\n return\n }\n\n console.log(`Paired with ${credentials.studioUrl} as ${styleText('cyan', credentials.agentSlug || credentials.agentId)}`)\n\n if (credentials.studioUrl !== options.studioUrl) {\n console.log(styleText('yellow', `Connecting to ${options.studioUrl} needs pairing again.`))\n }\n\n const remembered = credentials.projects?.[process.cwd()]\n\n if (!remembered) {\n console.log(styleText('dim', 'No saved permissions for this project. Run `kubb studio` to connect and choose.'))\n\n return\n }\n\n console.log(styleText('dim', 'Saved permissions'))\n\n for (const row of formatPermissionRows({\n allowRead: remembered.allowRead === true,\n allowWrite: remembered.allowWrite === true,\n allowConfigEdit: remembered.allowConfigEdit === true,\n allowExec: remembered.allowExec === true,\n })) {\n console.log(row)\n }\n}\n\nexport const connectRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => connect(options), block: true })\n}\n\nexport const loginRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => login(options) })\n}\n\nexport const logoutRunner: Runner<typeof logoutCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({\n options,\n action: async () => {\n await stopWorker()\n await clearCredentials()\n console.log('Signed out of Kubb Studio.')\n },\n })\n}\n\nexport const startRunner: Runner<typeof connectCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({ options, action: () => startWorker(options) })\n}\n\nexport const statusRunner: Runner<typeof statusCommand> = async ({ values }) => {\n const options = createStudioOptions(values)\n await run({\n options,\n action: async () => {\n const worker = await getWorkerStatus()\n console.log(`Background connection: ${worker.state}${worker.running ? ` (PID ${worker.pid})` : ''}`)\n console.log(`Logs: ${getWorkerLogPath()}`)\n await status(options)\n },\n })\n}\n\nexport async function stopRunner(): Promise<void> {\n await stopWorker()\n console.log('Background connection stopped.')\n}\n"],"mappings":";;;;;;;;AAaA,eAAe,OAAO,SAAuC;CAC3D,MAAM,cAAc,MAAMA,YAAAA,gBAAgB;CAE1C,IAAI,CAAC,aAAa;EAChB,QAAQ,IAAI,sCAAsC;EAElD;CACF;CAEA,QAAQ,IAAI,eAAe,YAAY,UAAU,OAAA,GAAMC,UAAAA,UAAAA,CAAU,QAAQ,YAAY,aAAa,YAAY,OAAO,GAAG;CAExH,IAAI,YAAY,cAAc,QAAQ,WACpC,QAAQ,KAAA,GAAIA,UAAAA,UAAAA,CAAU,UAAU,iBAAiB,QAAQ,UAAU,sBAAsB,CAAC;CAG5F,MAAM,aAAa,YAAY,WAAWC,aAAAA,QAAQ,IAAI;CAEtD,IAAI,CAAC,YAAY;EACf,QAAQ,KAAA,GAAID,UAAAA,UAAAA,CAAU,OAAO,iFAAiF,CAAC;EAE/G;CACF;CAEA,QAAQ,KAAA,GAAIA,UAAAA,UAAAA,CAAU,OAAO,mBAAmB,CAAC;CAEjD,KAAK,MAAM,OAAOE,YAAAA,qBAAqB;EACrC,WAAW,WAAW,cAAc;EACpC,YAAY,WAAW,eAAe;EACtC,iBAAiB,WAAW,oBAAoB;EAChD,WAAW,WAAW,cAAc;CACtC,CAAC,GACC,QAAQ,IAAI,GAAG;AAEnB;AAEA,MAAa,gBAA+C,OAAO,EAAE,aAAa;CAChF,MAAM,UAAUC,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EAAE;EAAS,cAAcC,YAAAA,QAAQ,OAAO;EAAG,OAAO;CAAK,CAAC;AACpE;AAEA,MAAa,cAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAUF,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EAAE;EAAS,cAAcE,YAAAA,MAAM,OAAO;CAAE,CAAC;AACrD;AAEA,MAAa,eAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAUH,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EACR;EACA,QAAQ,YAAY;GAClB,MAAMG,mBAAAA,WAAW;GACjB,MAAMC,YAAAA,iBAAiB;GACvB,QAAQ,IAAI,4BAA4B;EAC1C;CACF,CAAC;AACH;AAEA,MAAa,cAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAUL,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EAAE;EAAS,cAAcK,mBAAAA,YAAY,OAAO;CAAE,CAAC;AAC3D;AAEA,MAAa,eAA6C,OAAO,EAAE,aAAa;CAC9E,MAAM,UAAUN,YAAAA,oBAAoB,MAAM;CAC1C,MAAMC,YAAAA,IAAI;EACR;EACA,QAAQ,YAAY;GAClB,MAAM,SAAS,MAAMM,mBAAAA,gBAAgB;GACrC,QAAQ,IAAI,0BAA0B,OAAO,QAAQ,OAAO,UAAU,SAAS,OAAO,IAAI,KAAK,IAAI;GACnG,QAAQ,IAAI,SAASC,mBAAAA,iBAAiB,GAAG;GACzC,MAAM,OAAO,OAAO;EACtB;CACF,CAAC;AACH;AAEA,eAAsB,aAA4B;CAChD,MAAMJ,mBAAAA,WAAW;CACjB,QAAQ,IAAI,gCAAgC;AAC9C"}
@@ -22,33 +22,30 @@ const JITI_OPTIONS = {
22
22
  * lets go of a file, so `moduleCache: false` alone would keep returning the first version of it.
23
23
  */
24
24
  const JAVASCRIPT_EXTENSION = /\.[cm]?jsx?$/;
25
+ const jiti = createJiti(import.meta.url, JITI_OPTIONS);
25
26
  /**
26
- * Creates a jiti-based loader for Kubb's TypeScript and JavaScript config modules.
27
+ * Loads a Kubb TypeScript or JavaScript config module via jiti.
27
28
  *
28
29
  * jiti transpiles TypeScript and the `@kubb/renderer-jsx` JSX runtime on the fly. Every load
29
30
  * re-evaluates the file, so a config edited on disk is picked up by the next load.
30
31
  *
31
32
  * @example
32
33
  * ```ts
33
- * const config = await createModuleLoader().load('/abs/kubb.config.ts', { default: true })
34
+ * const config = await loadModule('/abs/kubb.config.ts', { default: true })
34
35
  * ```
35
36
  */
36
- function createModuleLoader() {
37
- const jiti = createJiti(import.meta.url, JITI_OPTIONS);
38
- return { async load(filePath, options) {
39
- if (!JAVASCRIPT_EXTENSION.test(filePath)) return options?.default ? jiti.import(filePath, { default: true }) : jiti.import(filePath);
40
- const mod = await jiti.evalModule(await readFile(filePath, "utf8"), {
41
- filename: filePath,
42
- async: true,
43
- forceTranspile: true
44
- });
45
- return options?.default ? mod?.default ?? mod : mod;
46
- } };
37
+ async function loadModule(filePath, options) {
38
+ if (!JAVASCRIPT_EXTENSION.test(filePath)) return options?.default ? jiti.import(filePath, { default: true }) : jiti.import(filePath);
39
+ const mod = await jiti.evalModule(await readFile(filePath, "utf8"), {
40
+ filename: filePath,
41
+ async: true,
42
+ forceTranspile: true
43
+ });
44
+ return options?.default ? mod?.default ?? mod : mod;
47
45
  }
48
46
  //#endregion
49
47
  //#region src/config.ts
50
- const loader = createModuleLoader();
51
- const tsLoader = (configFile) => loader.load(configFile, { default: true });
48
+ const tsLoader = (configFile) => loadModule(configFile, { default: true });
52
49
  const MODULE_NAME = "kubb";
53
50
  const SEARCH_FILES = [
54
51
  "",
@@ -117,4 +114,4 @@ async function getConfigs({ configPath, input, watch, logLevel }) {
117
114
  //#endregion
118
115
  export { getConfigs as n, findConfigFile as t };
119
116
 
120
- //# sourceMappingURL=config-DAdYwK_D.js.map
117
+ //# sourceMappingURL=config-B6UIKcl1.js.map