@kubb/cli 5.10.3 → 5.11.0

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 (69) hide show
  1. package/dist/{Telemetry-Cz9QCzRo.js → Telemetry-D54bKqiZ.js} +2 -2
  2. package/dist/{Telemetry-Cz9QCzRo.js.map → Telemetry-D54bKqiZ.js.map} +1 -1
  3. package/dist/{Telemetry-BV4GonCV.cjs → Telemetry-emCunBZD.cjs} +2 -2
  4. package/dist/{Telemetry-BV4GonCV.cjs.map → Telemetry-emCunBZD.cjs.map} +1 -1
  5. package/dist/{background-DFME5huR.js → background-CazP2t3p.js} +2 -2
  6. package/dist/{background-DFME5huR.js.map → background-CazP2t3p.js.map} +1 -1
  7. package/dist/{background-DVZB1n4j.cjs → background-D1q5qKbD.cjs} +2 -2
  8. package/dist/{background-DVZB1n4j.cjs.map → background-D1q5qKbD.cjs.map} +1 -1
  9. package/dist/{background-_A5NwvYH.js → background-D_Ffper-.js} +1 -1
  10. package/dist/{config-DV_7s1m-.js → config-AxC9X28n.js} +3 -3
  11. package/dist/{config-DV_7s1m-.js.map → config-AxC9X28n.js.map} +1 -1
  12. package/dist/{config-DKAqX5sW.cjs → config-ChrJbiHE.cjs} +3 -3
  13. package/dist/{config-OL_izsmp.cjs.map → config-ChrJbiHE.cjs.map} +1 -1
  14. package/dist/index.cjs +15 -15
  15. package/dist/index.js +15 -15
  16. package/dist/{output-D_gc1nrM.js → output-Bh9zt0Bs.js} +2 -2
  17. package/dist/{output-D_gc1nrM.js.map → output-Bh9zt0Bs.js.map} +1 -1
  18. package/dist/{output-nieBFDgM.cjs → output-DTljL9Ws.cjs} +2 -2
  19. package/dist/{output-nieBFDgM.cjs.map → output-DTljL9Ws.cjs.map} +1 -1
  20. package/dist/{registry-C8E_G7Xc.cjs → registry-BXY6IkwJ.cjs} +2 -2
  21. package/dist/{registry-C8E_G7Xc.cjs.map → registry-BXY6IkwJ.cjs.map} +1 -1
  22. package/dist/{registry-De1vVn1d.js → registry-pGRX9C6u.js} +2 -2
  23. package/dist/{registry-De1vVn1d.js.map → registry-pGRX9C6u.js.map} +1 -1
  24. package/dist/{run-hyi91b22.cjs → run-5-nCbBHG.cjs} +5 -5
  25. package/dist/{run-hgSZImuK.cjs.map → run-5-nCbBHG.cjs.map} +1 -1
  26. package/dist/{run-CCMlmk-z.js → run-BEnJOcry.js} +1 -1
  27. package/dist/{run-CvE8ZdKG.cjs → run-CF08-tw4.cjs} +2 -2
  28. package/dist/{run-BpdJ6X75.cjs.map → run-CF08-tw4.cjs.map} +1 -1
  29. package/dist/{run-DaFK-Uy2.js → run-CFp3FPGw.js} +2 -2
  30. package/dist/{run-DaFK-Uy2.js.map → run-CFp3FPGw.js.map} +1 -1
  31. package/dist/{run-CPYD1Lp0.js → run-CXDiBAu2.js} +5 -5
  32. package/dist/{run-CPYD1Lp0.js.map → run-CXDiBAu2.js.map} +1 -1
  33. package/dist/{run-Bp47k1W1.js → run-CgjQy13a.js} +2 -2
  34. package/dist/{run-Bp47k1W1.js.map → run-CgjQy13a.js.map} +1 -1
  35. package/dist/{run-Ij84bqza.js → run-CkyawufO.js} +5 -5
  36. package/dist/{run-Ij84bqza.js.map → run-CkyawufO.js.map} +1 -1
  37. package/dist/{run-MFjzBB_M.cjs → run-DAobECOj.cjs} +2 -2
  38. package/dist/{run-BbhrOuK6.cjs.map → run-DAobECOj.cjs.map} +1 -1
  39. package/dist/{run-BnLba1gt.cjs → run-DTulgo15.cjs} +5 -5
  40. package/dist/{run-BnLba1gt.cjs.map → run-DTulgo15.cjs.map} +1 -1
  41. package/dist/{snapshot-B6w3BLum.js → snapshot-9yYp872a.js} +5 -5
  42. package/dist/{snapshot-B6w3BLum.js.map → snapshot-9yYp872a.js.map} +1 -1
  43. package/dist/{snapshot-D_F4XkYQ.cjs → snapshot-CWfVxcnq.cjs} +5 -5
  44. package/dist/{snapshot-D_F4XkYQ.cjs.map → snapshot-CWfVxcnq.cjs.map} +1 -1
  45. package/dist/studioWorker.js +2 -2
  46. package/package.json +8 -8
  47. package/dist/Telemetry-CH2kkxWK.cjs +0 -322
  48. package/dist/Telemetry-CH2kkxWK.cjs.map +0 -1
  49. package/dist/background-WaKtfQWr.cjs +0 -192
  50. package/dist/background-WaKtfQWr.cjs.map +0 -1
  51. package/dist/config-DKAqX5sW.cjs.map +0 -1
  52. package/dist/config-OL_izsmp.cjs +0 -113
  53. package/dist/credentials-xOkTTDWj.cjs +0 -113
  54. package/dist/credentials-xOkTTDWj.cjs.map +0 -1
  55. package/dist/output-C5g7AtWH.cjs +0 -1008
  56. package/dist/output-C5g7AtWH.cjs.map +0 -1
  57. package/dist/registry-CIpW2zQc.cjs +0 -157
  58. package/dist/registry-CIpW2zQc.cjs.map +0 -1
  59. package/dist/rolldown-runtime-C0BPl7ul.cjs +0 -43
  60. package/dist/run-BbhrOuK6.cjs +0 -40
  61. package/dist/run-BpdJ6X75.cjs +0 -32
  62. package/dist/run-CSOEGpWZ.cjs +0 -326
  63. package/dist/run-CSOEGpWZ.cjs.map +0 -1
  64. package/dist/run-CvE8ZdKG.cjs.map +0 -1
  65. package/dist/run-MFjzBB_M.cjs.map +0 -1
  66. package/dist/run-hgSZImuK.cjs +0 -345
  67. package/dist/run-hyi91b22.cjs.map +0 -1
  68. package/dist/snapshot-DP9Pcnsg.cjs +0 -264
  69. package/dist/snapshot-DP9Pcnsg.cjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"Telemetry-CH2kkxWK.cjs","names":["process","process","randomBytes","getAgentProfile","os"],"sources":["../../../internals/utils/src/errors.ts","../../../internals/utils/src/isCIEnvironment.ts","../../../internals/utils/src/runtime.ts","../../../internals/utils/src/time.ts","../package.json","../src/Telemetry.ts"],"sourcesContent":["/**\n * Coerces an unknown thrown value to an `Error` instance.\n * Returns the value as-is when it is already an `Error`; otherwise wraps it with `String(value)`.\n *\n * @example\n * ```ts\n * try { ... } catch(err) {\n * throw new Error('Build failed', { cause: toError(err) })\n * }\n * ```\n */\nexport function toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value))\n}\n\n/**\n * Extracts a human-readable message from any thrown value.\n *\n * @example\n * ```ts\n * getErrorMessage(new Error('oops')) // 'oops'\n * getErrorMessage('plain string') // 'plain string'\n * ```\n */\nexport function getErrorMessage(value: unknown): string {\n return value instanceof Error ? value.message : String(value)\n}\n\n/**\n * Returns `error` followed by every error in its `cause` chain, outermost first. Stops at a\n * non-`Error` cause or a cycle.\n *\n * @example\n * ```ts\n * getErrorChain(new Error('Config failed loading', { cause: new Error('boom') })).map((error) => error.message)\n * // ['Config failed loading', 'boom']\n * ```\n */\nexport function getErrorChain(error: unknown): Array<Error> {\n const chain: Array<Error> = []\n for (let current = error; current instanceof Error && !chain.includes(current); current = current.cause) {\n chain.push(current)\n }\n return chain\n}\n","import process from 'node:process'\n\n/**\n * Returns `true` when a known CI provider has set its environment variable.\n * `CI=false` and `CI=0` count as not CI, so a user can opt out locally.\n */\nexport function isCIEnvironment(): boolean {\n const ci = process.env.CI\n return !!(\n (ci && ci !== 'false' && ci !== '0') ||\n process.env.GITHUB_ACTIONS ||\n process.env.GITLAB_CI ||\n process.env.BITBUCKET_BUILD_NUMBER ||\n process.env.JENKINS_URL ||\n process.env.CIRCLECI ||\n process.env.TRAVIS ||\n process.env.TEAMCITY_VERSION ||\n process.env.BUILDKITE ||\n process.env.TF_BUILD\n )\n}\n","// 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","/**\n * Calculates elapsed time in milliseconds from a high-resolution `process.hrtime` start time.\n * Rounds to 2 decimal places for sub-millisecond precision without noise.\n *\n * @example\n * ```ts\n * const start = process.hrtime()\n * doWork()\n * getElapsedMs(start) // 42.35\n * ```\n */\nexport function getElapsedMs(hrStart: [number, number]): number {\n const [seconds, nanoseconds] = process.hrtime(hrStart)\n const ms = seconds * 1000 + nanoseconds / 1e6\n return Math.round(ms * 100) / 100\n}\n\n/**\n * Converts a millisecond duration into a human-readable string (`ms`, `s`, or `m s`).\n *\n * @example\n * ```ts\n * formatMs(250) // '250ms'\n * formatMs(1500) // '1.50s'\n * formatMs(90000) // '1m 30.0s'\n * ```\n */\nexport function formatMs(ms: number): string {\n if (ms >= 60000) {\n const mins = Math.floor(ms / 60000)\n const secs = ((ms % 60000) / 1000).toFixed(1)\n return `${mins}m ${secs}s`\n }\n\n if (ms >= 1000) {\n return `${(ms / 1000).toFixed(2)}s`\n }\n return `${Math.round(ms)}ms`\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 { getAgentProfile } from 'gunshi/agent'\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\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/** How a command run ended, as the command reports it to the function {@link trackRun} returned. */\ntype RunResult = {\n status: 'success' | 'failed'\n plugins?: Array<TelemetryPlugin>\n filesCreated?: number\n /**\n * Name the MCP client sends in its `initialize` request, e.g. `'claude-code'`. Only set for `kubb mcp`.\n */\n mcpClient?: string\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/** 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 }: { command: TelemetryCommand; hrStart: [number, number] }): (result: RunResult) => Promise<void> {\n return (result) => sendTelemetry(buildOtlpPayload({ command, duration: Math.round(getElapsedMs(hrStart)), ...result }))\n}\n\n/**\n * The OTLP trace payload for one run: a span named after the command whose attributes are the\n * anonymous run facts. The attribute keys are the contract with otlp.kubb.dev.\n *\n * @see https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/\n */\nexport function buildOtlpPayload({\n command,\n duration,\n status,\n plugins = [],\n filesCreated = 0,\n mcpClient,\n}: RunResult & { command: TelemetryCommand; duration: number }) {\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(duration) * 1_000_000n\n const pluginNames = [...new Set(plugins.map((plugin) => plugin.name))].sort()\n const agent = getAgentProfile()\n\n const attributes = [\n { key: 'kubb.command', value: { stringValue: command } },\n { key: 'kubb.version', value: { stringValue: version } },\n { key: 'kubb.node_version', value: { stringValue: process.versions.node.split('.')[0] as string } },\n { key: 'kubb.runtime', value: { stringValue: runtime.name } },\n { key: 'kubb.runtime_version', value: { stringValue: runtime.version.split('.')[0] as string } },\n { key: 'kubb.platform', value: { stringValue: os.platform() } },\n { key: 'kubb.ci', value: { boolValue: isCIEnvironment() } },\n // A terminal on stdin means a person typed the command; agents, scripts, and CI pipe it.\n { key: 'kubb.tty', value: { boolValue: process.stdin.isTTY === true } },\n ...(agent.isAgent && agent.name ? [{ key: 'kubb.agent', value: { stringValue: agent.name } }] : []),\n // The client picks this name, so cap its length before it leaves the machine.\n ...(mcpClient ? [{ key: 'kubb.mcp_client', value: { stringValue: mcpClient.slice(0, 64) } }] : []),\n { key: 'kubb.files_created', value: { intValue: filesCreated } },\n { key: 'kubb.status', value: { stringValue: 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: 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 { key: 'service.version', value: { stringValue: version } },\n { key: 'telemetry.sdk.language', value: { stringValue: 'nodejs' } },\n ],\n },\n scopeSpans: [\n {\n scope: { name: 'kubb-core', version },\n spans: [\n {\n traceId,\n spanId,\n name: command,\n kind: 1,\n startTimeUnixNano: String(startTimeNs),\n endTimeUnixNano: String(endTimeNs),\n attributes,\n status: {\n code: status === 'success' ? 1 : 2,\n },\n },\n ],\n },\n ],\n },\n ],\n }\n}\n\n/**\n * Send an OTLP payload to the Kubb 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(payload: ReturnType<typeof buildOtlpPayload>): 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(payload),\n signal: AbortSignal.timeout(5_000),\n })\n } catch (_e) {\n // Fail silently, telemetry must never break the run\n }\n}\n"],"mappings":"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"}
@@ -1,192 +0,0 @@
1
- const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
2
- const require_credentials = require("./credentials-xOkTTDWj.cjs");
3
- const require_run = require("./run-CSOEGpWZ.cjs");
4
- require("node:crypto");
5
- let tinyexec = require("tinyexec");
6
- let node_fs_promises = require("node:fs/promises");
7
- let node_path = require("node:path");
8
- node_path = require_rolldown_runtime.__toESM(node_path, 1);
9
- let _kubb_core = require("@kubb/core");
10
- let node_module = require("node:module");
11
- let node_net = require("node:net");
12
- let node_timers_promises = require("node:timers/promises");
13
- //#region src/runners/studio/background.ts
14
- const states = [
15
- "starting",
16
- "connected",
17
- "reconnecting",
18
- "authentication required",
19
- "stopped"
20
- ];
21
- const getWorkerLogPath = () => node_path.default.join(require_credentials.getProjectKubbHome(), "worker.log");
22
- const statePath = () => node_path.default.join(require_credentials.getProjectKubbHome(), "worker.json");
23
- async function readWorker() {
24
- try {
25
- const value = JSON.parse(await (0, node_fs_promises.readFile)(statePath(), "utf8"));
26
- if (!value || typeof value !== "object") return null;
27
- const record = value;
28
- return typeof record.id === "string" && /^[a-f0-9]{32}$/.test(record.id) && Number.isInteger(record.pid) && (record.pid ?? 0) > 1 && Number.isInteger(record.port) && (record.port ?? 0) > 0 && (record.port ?? 0) <= 65535 && states.includes(record.state) ? record : null;
29
- } catch {
30
- return null;
31
- }
32
- }
33
- function isAlive(pid) {
34
- try {
35
- process.kill(pid, 0);
36
- return true;
37
- } catch (error) {
38
- return error.code === "EPERM";
39
- }
40
- }
41
- /** Authenticated loopback IPC; a stored PID never authorizes sending a process signal. */
42
- function requestWorker(record, command) {
43
- return new Promise((resolve, reject) => {
44
- const socket = (0, node_net.connect)({
45
- host: "127.0.0.1",
46
- port: record.port
47
- });
48
- let received = "";
49
- socket.setTimeout(2e3, () => socket.destroy(/* @__PURE__ */ new Error("Worker control timed out")));
50
- socket.once("error", reject);
51
- socket.once("connect", () => socket.write(JSON.stringify({
52
- id: record.id,
53
- command
54
- }) + "\n"));
55
- socket.on("data", (chunk) => {
56
- received += chunk.toString();
57
- if (received.length > 4096) socket.destroy(/* @__PURE__ */ new Error("Invalid worker response"));
58
- });
59
- socket.once("end", () => {
60
- try {
61
- const response = JSON.parse(received);
62
- if (response.id !== record.id || response.pid !== record.pid || !states.includes(response.state)) throw new _kubb_core.Diagnostics.Error({
63
- code: _kubb_core.Diagnostics.code.internalError,
64
- severity: "error",
65
- message: "Worker identity changed"
66
- });
67
- resolve(response);
68
- } catch (error) {
69
- reject(error);
70
- }
71
- });
72
- });
73
- }
74
- async function getWorkerStatus() {
75
- const record = await readWorker();
76
- if (!record) return {
77
- running: false,
78
- state: "stopped"
79
- };
80
- try {
81
- const response = await requestWorker(record, "status");
82
- return {
83
- running: true,
84
- state: response.state,
85
- pid: response.pid
86
- };
87
- } catch {
88
- return {
89
- running: false,
90
- state: record.state === "authentication required" ? record.state : "stopped"
91
- };
92
- }
93
- }
94
- async function stopWorker() {
95
- const record = await readWorker();
96
- if (!record) return;
97
- try {
98
- await requestWorker(record, "stop");
99
- } catch (error) {
100
- if (error.code !== "ECONNREFUSED" && isAlive(record.pid) && record.state !== "stopped" && record.state !== "authentication required") throw new _kubb_core.Diagnostics.Error({
101
- code: _kubb_core.Diagnostics.code.unknown,
102
- severity: "error",
103
- message: "Cannot verify the background worker. No process was signaled.",
104
- help: "Check `worker.log`, then stop the process by hand if it is still running."
105
- });
106
- return;
107
- }
108
- const deadline = Date.now() + 15e3;
109
- while (Date.now() < deadline) {
110
- try {
111
- await requestWorker(record, "status");
112
- } catch {
113
- return;
114
- }
115
- await (0, node_timers_promises.setTimeout)(100);
116
- }
117
- throw new _kubb_core.Diagnostics.Error({
118
- code: _kubb_core.Diagnostics.code.unknown,
119
- severity: "error",
120
- message: "The worker has not finished shutting down. Check worker.log and try again."
121
- });
122
- }
123
- async function startWorker(options) {
124
- const current = await getWorkerStatus();
125
- if (current.running) {
126
- console.log(`Already running (${current.state}, PID ${current.pid}).`);
127
- return;
128
- }
129
- const prepared = await require_run.prepareConnection(options);
130
- const entry = node_path.default.join(node_path.default.dirname((0, node_module.createRequire)(require("url").pathToFileURL(__filename).href).resolve("@kubb/cli/package.json")), "dist", "studioWorker.js");
131
- const child = (0, tinyexec.x)(process.execPath, [...process.execArgv, entry], { nodeOptions: {
132
- cwd: process.cwd(),
133
- detached: true,
134
- stdio: [
135
- "ignore",
136
- "ignore",
137
- "ignore",
138
- "ipc"
139
- ]
140
- } }).process;
141
- if (!child) throw new _kubb_core.Diagnostics.Error({
142
- code: _kubb_core.Diagnostics.code.unknown,
143
- severity: "error",
144
- message: "Background worker failed to start",
145
- help: "Run `kubb studio` in the foreground to see why it fails."
146
- });
147
- try {
148
- await new Promise((resolve, reject) => {
149
- const timer = setTimeout(() => done(/* @__PURE__ */ new Error("Background worker startup timed out")), 2e4);
150
- const done = (error) => {
151
- clearTimeout(timer);
152
- child.removeListener("error", failed);
153
- child.removeListener("exit", exited);
154
- child.removeListener("message", ready);
155
- if (error) reject(error);
156
- else resolve();
157
- };
158
- const failed = (error) => done(error);
159
- const exited = () => done(/* @__PURE__ */ new Error(`Background worker exited during startup. Check ${getWorkerLogPath()}`));
160
- child.once("error", failed);
161
- child.once("exit", exited);
162
- const ready = (message) => {
163
- if (!message || typeof message !== "object" || !("started" in message) || message.started !== true) return done(/* @__PURE__ */ new Error("Invalid worker startup response"));
164
- done();
165
- };
166
- child.once("message", ready);
167
- child.send({
168
- options: {
169
- ...options,
170
- autoOpen: false
171
- },
172
- prepared
173
- }, (error) => {
174
- if (error) done(error);
175
- });
176
- });
177
- if (child.connected) child.disconnect();
178
- child.unref();
179
- const status = await getWorkerStatus();
180
- console.log(`Background worker ${status.state} (PID ${status.pid ?? child.pid}). Logs: ${getWorkerLogPath()}`);
181
- } catch (error) {
182
- child.kill("SIGTERM");
183
- throw error;
184
- }
185
- }
186
- //#endregion
187
- exports.getWorkerLogPath = getWorkerLogPath;
188
- exports.getWorkerStatus = getWorkerStatus;
189
- exports.startWorker = startWorker;
190
- exports.stopWorker = stopWorker;
191
-
192
- //# sourceMappingURL=background-WaKtfQWr.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"background-WaKtfQWr.cjs","names":["path","getProjectKubbHome","readFile","connectSocket","Diagnostics","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 { Diagnostics } from '@kubb/core'\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))\n throw new Diagnostics.Error({ code: Diagnostics.code.internalError, severity: 'error', message: '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 Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'Cannot verify the background worker. No process was signaled.',\n help: 'Check `worker.log`, then stop the process by hand if it is still running.',\n })\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 Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'The worker has not finished shutting down. Check worker.log and try again.',\n })\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 Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'The project control port is occupied or another worker is starting. Try again after stopping that listener.',\n })\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)\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'Background worker failed to start',\n help: 'Run `kubb studio` in the foreground to see why it fails.',\n })\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 +0,0 @@
1
- {"version":3,"file":"config-DKAqX5sW.cjs","names":["process","isRichOutput","clackLogger","plainLogger","createCliReporter","resolve","findConfigFile","Diagnostics","CONFIG_EXTENSIONS","process","loadConfigFile","toError"],"sources":["../src/loggers/reporters.ts","../src/config.ts"],"sourcesContent":["import process from 'node:process'\nimport type { Config, Hookable, KubbHooks, Reporter, ReporterContext, ReporterPluginFiles } from '@kubb/core'\nimport { createCliReporter } from '@kubb/core'\nimport { isRichOutput } from '../utils/env.ts'\nimport type { Logger, LoggerOptions } from './defineLogger.ts'\nimport { clackLogger } from './clackLogger.ts'\nimport { plainLogger } from './plainLogger.ts'\n\n/** Bridges a {@link Reporter} onto the hook emitter: calls `report` with each config's {@link GenerationResult} on `kubb:generation:end`. */\nfunction installReporter(context: Hookable<KubbHooks>, reporter: Reporter, ctx: ReporterContext): void {\n const pluginFiles = reporter.needsPluginFiles ? new Map<Config, Map<string, Set<string>>>() : undefined\n\n if (pluginFiles) {\n context.hook('kubb:plugin:end', ({ config, plugin, files }) => {\n const filesByPlugin = pluginFiles.get(config) ?? new Map<string, Set<string>>()\n const seen = new Set([...filesByPlugin.values()].flatMap((paths) => [...paths]))\n const added = files.filter((file) => !seen.has(file.path)).map((file) => file.path)\n\n if (added.length) filesByPlugin.set(plugin.name, new Set([...(filesByPlugin.get(plugin.name) ?? []), ...added]))\n\n pluginFiles.set(config, filesByPlugin)\n })\n }\n\n context.hook('kubb:generation:end', async ({ config, diagnostics = [], filesCreated = 0, status = 'success', hrStart = process.hrtime() }) => {\n const files = pluginFiles?.get(config)\n const grouped: ReporterPluginFiles | undefined = files && [...files].map(([plugin, paths]) => ({ plugin, files: [...paths] }))\n\n await reporter.report({ config, diagnostics, filesCreated, status, hrStart, pluginFiles: grouped }, ctx)\n\n pluginFiles?.delete(config)\n })\n\n if (reporter.drain) {\n context.hook('kubb:lifecycle:end', () => reporter.drain?.(ctx))\n }\n}\n\n/** Installs the live logger and wires the selected reporters. `cli` renders its summary through the logger, and is skipped when `json` owns stdout. */\nfunction setupReporters(\n context: Hookable<KubbHooks>,\n {\n logLevel,\n reporters,\n logger: forcedLogger,\n }: LoggerOptions & {\n reporters: ReadonlyArray<Reporter>\n /** Overrides the terminal-based pick, e.g. the plain logger for `kubb studio snapshot`. */\n logger?: Logger\n },\n): void {\n const hasJson = reporters.some((reporter) => reporter.name === 'json')\n const ctx: ReporterContext = { logLevel }\n\n for (const reporter of reporters) {\n if (reporter.name !== 'cli') {\n installReporter(context, reporter, ctx)\n continue\n }\n\n if (hasJson) {\n continue\n }\n\n const logger = forcedLogger ?? (isRichOutput() ? clackLogger : plainLogger)\n const handle = logger(context, { logLevel })\n\n // The summary belongs inside the group the logger opened for this config, so the logger writes it.\n installReporter(context, createCliReporter({ render: handle?.renderSummary }), ctx)\n }\n}\n\nexport default setupReporters\n\n/** Picks the reporters whose `name` is in `names`, in the given order (the CLI maps `--reporter` to this); duplicates and unknown names are skipped. */\nexport function selectReporters(reporters: ReadonlyArray<Reporter>, names: ReadonlyArray<string>): Array<Reporter> {\n return [...new Set(names)].flatMap((name) => reporters.find((reporter) => reporter.name === name) ?? [])\n}\n","import { resolve } from 'node:path'\nimport process from 'node:process'\nimport { CONFIG_EXTENSIONS, findConfigFile, loadConfigFile } from '@internals/shared'\nimport { type CLIOptions, type Config, Diagnostics } from '@kubb/core'\nimport { toError } from '@internals/utils'\n\ntype GetConfigsOptions = {\n /** Explicit path to the Kubb config file. When omitted, the loader searches up from `process.cwd()`. */\n configPath?: string\n /** OpenAPI input path or URL that overrides `config.input` for this run. */\n input?: string\n /** Watch flag forwarded to the user's `defineConfig` function. */\n watch?: boolean\n /** Log level forwarded to the user's `defineConfig` function. */\n logLevel?: CLIOptions['logLevel']\n}\n\ntype GetConfigsResult = {\n /** Absolute path to the resolved config file. */\n configPath: string\n /** Resolved and normalized Kubb configs, each guaranteed to have a `plugins` array. */\n configs: Array<Config>\n}\n\n/** Discovers the Kubb config and resolves it into normalized configs, each guaranteed to have a `plugins` array. */\nexport async function getConfigs({ configPath, input, watch, logLevel }: GetConfigsOptions): Promise<GetConfigsResult> {\n const file = configPath ? resolve(configPath) : findConfigFile()\n if (!file) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `No Kubb config found. Looked for kubb.config.* and .kubbrc.* (${CONFIG_EXTENSIONS.join(', ')}) in ${process.cwd()}, its .config/ and configs/ folders, and each parent folder.`,\n help: 'Run `kubb init` to create one, or pass a path with `--config`.',\n location: { kind: 'config' },\n })\n }\n\n let configs: Array<Config>\n try {\n configs = await loadConfigFile<Config>(file, { config: configPath, input, watch, logLevel } satisfies CLIOptions)\n } catch (error) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `Config failed loading: ${file}`,\n help: 'Fix the error the config file throws, shown under `caused by:`.',\n location: { kind: 'config' },\n cause: toError(error),\n })\n }\n\n return { configPath: file, configs: configs.map((item) => ({ ...item, plugins: item.plugins ?? [] })) }\n}\n"],"mappings":";;;;;;;;;AASA,SAAS,gBAAgB,SAA8B,UAAoB,KAA4B;CACrG,MAAM,cAAc,SAAS,mCAAmB,IAAI,IAAsC,IAAI,KAAA;CAE9F,IAAI,aACF,QAAQ,KAAK,oBAAoB,EAAE,QAAQ,QAAQ,YAAY;EAC7D,MAAM,gBAAgB,YAAY,IAAI,MAAM,qBAAK,IAAI,IAAyB;EAC9E,MAAM,OAAO,IAAI,IAAI,CAAC,GAAG,cAAc,OAAO,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,KAAK,CAAC,CAAC;EAC/E,MAAM,QAAQ,MAAM,QAAQ,SAAS,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,KAAK,IAAI;EAElF,IAAI,MAAM,QAAQ,cAAc,IAAI,OAAO,sBAAM,IAAI,IAAI,CAAC,GAAI,cAAc,IAAI,OAAO,IAAI,KAAK,CAAC,GAAI,GAAG,KAAK,CAAC,CAAC;EAE/G,YAAY,IAAI,QAAQ,aAAa;CACvC,CAAC;CAGH,QAAQ,KAAK,uBAAuB,OAAO,EAAE,QAAQ,cAAc,CAAC,GAAG,eAAe,GAAG,SAAS,WAAW,UAAUA,aAAAA,QAAQ,OAAO,QAAQ;EAC5I,MAAM,QAAQ,aAAa,IAAI,MAAM;EACrC,MAAM,UAA2C,SAAS,CAAC,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,QAAQ,YAAY;GAAE;GAAQ,OAAO,CAAC,GAAG,KAAK;EAAE,EAAE;EAE7H,MAAM,SAAS,OAAO;GAAE;GAAQ;GAAa;GAAc;GAAQ;GAAS,aAAa;EAAQ,GAAG,GAAG;EAEvG,aAAa,OAAO,MAAM;CAC5B,CAAC;CAED,IAAI,SAAS,OACX,QAAQ,KAAK,4BAA4B,SAAS,QAAQ,GAAG,CAAC;AAElE;;AAGA,SAAS,eACP,SACA,EACE,UACA,WACA,QAAQ,gBAMJ;CACN,MAAM,UAAU,UAAU,MAAM,aAAa,SAAS,SAAS,MAAM;CACrE,MAAM,MAAuB,EAAE,SAAS;CAExC,KAAK,MAAM,YAAY,WAAW;EAChC,IAAI,SAAS,SAAS,OAAO;GAC3B,gBAAgB,SAAS,UAAU,GAAG;GACtC;EACF;EAEA,IAAI,SACF;EAIF,MAAM,UADS,iBAAiBC,eAAAA,aAAa,IAAIC,eAAAA,cAAcC,eAAAA,aAAAA,CACzC,SAAS,EAAE,SAAS,CAAC;EAG3C,gBAAgB,UAAA,GAASC,WAAAA,kBAAAA,CAAkB,EAAE,QAAQ,QAAQ,cAAc,CAAC,GAAG,GAAG;CACpF;AACF;;AAKA,SAAgB,gBAAgB,WAAoC,OAA+C;CACjH,OAAO,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,SAAS,SAAS,UAAU,MAAM,aAAa,SAAS,SAAS,IAAI,KAAK,CAAC,CAAC;AACzG;;;;ACpDA,eAAsB,WAAW,EAAE,YAAY,OAAO,OAAO,YAA0D;CACrH,MAAM,OAAO,cAAA,GAAaC,UAAAA,QAAAA,CAAQ,UAAU,IAAIC,eAAAA,eAAe;CAC/D,IAAI,CAAC,MACH,MAAM,IAAIC,WAAAA,YAAY,MAAM;EAC1B,MAAMA,WAAAA,YAAY,KAAK;EACvB,UAAU;EACV,SAAS,iEAAiEC,eAAAA,kBAAkB,KAAK,IAAI,EAAE,OAAOC,aAAAA,QAAQ,IAAI,EAAE;EAC5H,MAAM;EACN,UAAU,EAAE,MAAM,SAAS;CAC7B,CAAC;CAGH,IAAI;CACJ,IAAI;EACF,UAAU,MAAMC,eAAAA,eAAuB,MAAM;GAAE,QAAQ;GAAY;GAAO;GAAO;EAAS,CAAsB;CAClH,SAAS,OAAO;EACd,MAAM,IAAIH,WAAAA,YAAY,MAAM;GAC1B,MAAMA,WAAAA,YAAY,KAAK;GACvB,UAAU;GACV,SAAS,0BAA0B;GACnC,MAAM;GACN,UAAU,EAAE,MAAM,SAAS;GAC3B,OAAOI,kBAAAA,QAAQ,KAAK;EACtB,CAAC;CACH;CAEA,OAAO;EAAE,YAAY;EAAM,SAAS,QAAQ,KAAK,UAAU;GAAE,GAAG;GAAM,SAAS,KAAK,WAAW,CAAC;EAAE,EAAE;CAAE;AACxG"}
@@ -1,113 +0,0 @@
1
- const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
2
- const require_Telemetry = require("./Telemetry-CH2kkxWK.cjs");
3
- const require_output = require("./output-C5g7AtWH.cjs");
4
- let node_process = require("node:process");
5
- node_process = require_rolldown_runtime.__toESM(node_process, 1);
6
- let node_path = require("node:path");
7
- let _kubb_core = require("@kubb/core");
8
- //#region src/loggers/reporters.ts
9
- /** Bridges a {@link Reporter} onto the hook emitter: calls `report` with each config's {@link GenerationResult} on `kubb:generation:end`. */
10
- function installReporter(context, reporter, ctx) {
11
- const pluginFiles = reporter.needsPluginFiles ? /* @__PURE__ */ new Map() : void 0;
12
- if (pluginFiles) context.hook("kubb:plugin:end", ({ config, plugin, files }) => {
13
- const filesByPlugin = pluginFiles.get(config) ?? /* @__PURE__ */ new Map();
14
- const seen = new Set([...filesByPlugin.values()].flatMap((paths) => [...paths]));
15
- const added = files.filter((file) => !seen.has(file.path)).map((file) => file.path);
16
- if (added.length) filesByPlugin.set(plugin.name, /* @__PURE__ */ new Set([...filesByPlugin.get(plugin.name) ?? [], ...added]));
17
- pluginFiles.set(config, filesByPlugin);
18
- });
19
- context.hook("kubb:generation:end", async ({ config, diagnostics = [], filesCreated = 0, status = "success", hrStart = node_process.default.hrtime() }) => {
20
- const files = pluginFiles?.get(config);
21
- const grouped = files && [...files].map(([plugin, paths]) => ({
22
- plugin,
23
- files: [...paths]
24
- }));
25
- await reporter.report({
26
- config,
27
- diagnostics,
28
- filesCreated,
29
- status,
30
- hrStart,
31
- pluginFiles: grouped
32
- }, ctx);
33
- pluginFiles?.delete(config);
34
- });
35
- if (reporter.drain) context.hook("kubb:lifecycle:end", () => reporter.drain?.(ctx));
36
- }
37
- /** Installs the live logger and wires the selected reporters. `cli` renders its summary through the logger, and is skipped when `json` owns stdout. */
38
- function setupReporters(context, { logLevel, reporters, logger: forcedLogger }) {
39
- const hasJson = reporters.some((reporter) => reporter.name === "json");
40
- const ctx = { logLevel };
41
- for (const reporter of reporters) {
42
- if (reporter.name !== "cli") {
43
- installReporter(context, reporter, ctx);
44
- continue;
45
- }
46
- if (hasJson) continue;
47
- const handle = (forcedLogger ?? (require_output.isRichOutput() ? require_output.clackLogger : require_output.plainLogger))(context, { logLevel });
48
- installReporter(context, (0, _kubb_core.createCliReporter)({ render: handle?.renderSummary }), ctx);
49
- }
50
- }
51
- /** Picks the reporters whose `name` is in `names`, in the given order (the CLI maps `--reporter` to this); duplicates and unknown names are skipped. */
52
- function selectReporters(reporters, names) {
53
- return [...new Set(names)].flatMap((name) => reporters.find((reporter) => reporter.name === name) ?? []);
54
- }
55
- //#endregion
56
- //#region src/config.ts
57
- /** Discovers the Kubb config and resolves it into normalized configs, each guaranteed to have a `plugins` array. */
58
- async function getConfigs({ configPath, input, watch, logLevel }) {
59
- const file = configPath ? (0, node_path.resolve)(configPath) : require_output.findConfigFile();
60
- if (!file) throw new _kubb_core.Diagnostics.Error({
61
- code: _kubb_core.Diagnostics.code.unknown,
62
- severity: "error",
63
- message: `No Kubb config found. Looked for kubb.config.* and .kubbrc.* (${require_output.CONFIG_EXTENSIONS.join(", ")}) in ${node_process.default.cwd()}, its .config/ and configs/ folders, and each parent folder.`,
64
- help: "Run `kubb init` to create one, or pass a path with `--config`.",
65
- location: { kind: "config" }
66
- });
67
- let configs;
68
- try {
69
- configs = await require_output.loadConfigFile(file, {
70
- config: configPath,
71
- input,
72
- watch,
73
- logLevel
74
- });
75
- } catch (error) {
76
- throw new _kubb_core.Diagnostics.Error({
77
- code: _kubb_core.Diagnostics.code.unknown,
78
- severity: "error",
79
- message: `Config failed loading: ${file}`,
80
- help: "Fix the error the config file throws, shown under `caused by:`.",
81
- location: { kind: "config" },
82
- cause: require_Telemetry.toError(error)
83
- });
84
- }
85
- return {
86
- configPath: file,
87
- configs: configs.map((item) => ({
88
- ...item,
89
- plugins: item.plugins ?? []
90
- }))
91
- };
92
- }
93
- //#endregion
94
- Object.defineProperty(exports, "getConfigs", {
95
- enumerable: true,
96
- get: function() {
97
- return getConfigs;
98
- }
99
- });
100
- Object.defineProperty(exports, "selectReporters", {
101
- enumerable: true,
102
- get: function() {
103
- return selectReporters;
104
- }
105
- });
106
- Object.defineProperty(exports, "setupReporters", {
107
- enumerable: true,
108
- get: function() {
109
- return setupReporters;
110
- }
111
- });
112
-
113
- //# sourceMappingURL=config-OL_izsmp.cjs.map
@@ -1,113 +0,0 @@
1
- const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
2
- let node_crypto = require("node:crypto");
3
- let node_process = require("node:process");
4
- node_process = require_rolldown_runtime.__toESM(node_process, 1);
5
- let node_path = require("node:path");
6
- node_path = require_rolldown_runtime.__toESM(node_path, 1);
7
- let _kubb_core = require("@kubb/core");
8
- //#region src/runners/studio/credentials.ts
9
- var credentials_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
10
- clearCredentials: () => clearCredentials,
11
- getCredentialsPath: () => getCredentialsPath,
12
- getMachineId: () => getMachineId,
13
- getProjectKubbHome: () => getProjectKubbHome,
14
- readCredentials: () => readCredentials,
15
- writeCredentials: () => writeCredentials
16
- });
17
- const projectBase = (project = node_process.default.cwd()) => node_path.default.join("projects", (0, node_crypto.hash)("sha256", project));
18
- /**
19
- * Root for the credential and machine identity of the current project, inside `KUBB_HOME`.
20
- *
21
- * Studio agents are project connections, so two projects on one machine must not share the same
22
- * persisted token or machine secret.
23
- */
24
- function getProjectKubbHome(project = node_process.default.cwd()) {
25
- return (0, _kubb_core.resolveKubbDir)(projectBase(project));
26
- }
27
- const projectStorage = () => (0, _kubb_core.kubbStorage)({ base: projectBase() });
28
- const CREDENTIALS_FILENAME = "credentials.json";
29
- /**
30
- * Absolute path of the stored credential, so callers can name it in output without rebuilding it.
31
- */
32
- function getCredentialsPath() {
33
- return node_path.default.join(getProjectKubbHome(), CREDENTIALS_FILENAME);
34
- }
35
- /**
36
- * Reads the stored credential, or null when this machine has not paired yet or the file is
37
- * unreadable or corrupt. A bad file is treated as "not paired" so `kubb studio login` can
38
- * overwrite it rather than the CLI dying on it.
39
- */
40
- async function readCredentials() {
41
- const stored = await projectStorage().getItem(CREDENTIALS_FILENAME).catch(() => null);
42
- return typeof stored?.token === "string" && stored.token !== "" ? stored : null;
43
- }
44
- /**
45
- * Writes the credential into the project folder, which only its owner can open.
46
- */
47
- async function writeCredentials(credentials) {
48
- await projectStorage().setItem(CREDENTIALS_FILENAME, credentials);
49
- }
50
- /**
51
- * Forgets the stored credential. Succeeds when there was nothing to forget.
52
- */
53
- async function clearCredentials() {
54
- await projectStorage().removeItem(CREDENTIALS_FILENAME);
55
- }
56
- /**
57
- * Reads this project's machine secret, creating it on first use. Pairing sends its hash, so pairing
58
- * the same project again rotates one agent's token instead of creating a second agent. It lives
59
- * apart from the credential, which {@link clearCredentials} deletes.
60
- */
61
- async function getMachineId() {
62
- const storage = projectStorage();
63
- const stored = await storage.getItem("machine-secret").catch(() => null);
64
- if (typeof stored === "string" && stored.trim()) return stored.trim();
65
- const secret = (0, node_crypto.randomBytes)(32).toString("hex");
66
- await storage.setItem("machine-secret", secret);
67
- return secret;
68
- }
69
- //#endregion
70
- Object.defineProperty(exports, "clearCredentials", {
71
- enumerable: true,
72
- get: function() {
73
- return clearCredentials;
74
- }
75
- });
76
- Object.defineProperty(exports, "credentials_exports", {
77
- enumerable: true,
78
- get: function() {
79
- return credentials_exports;
80
- }
81
- });
82
- Object.defineProperty(exports, "getCredentialsPath", {
83
- enumerable: true,
84
- get: function() {
85
- return getCredentialsPath;
86
- }
87
- });
88
- Object.defineProperty(exports, "getMachineId", {
89
- enumerable: true,
90
- get: function() {
91
- return getMachineId;
92
- }
93
- });
94
- Object.defineProperty(exports, "getProjectKubbHome", {
95
- enumerable: true,
96
- get: function() {
97
- return getProjectKubbHome;
98
- }
99
- });
100
- Object.defineProperty(exports, "readCredentials", {
101
- enumerable: true,
102
- get: function() {
103
- return readCredentials;
104
- }
105
- });
106
- Object.defineProperty(exports, "writeCredentials", {
107
- enumerable: true,
108
- get: function() {
109
- return writeCredentials;
110
- }
111
- });
112
-
113
- //# sourceMappingURL=credentials-xOkTTDWj.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"credentials-xOkTTDWj.cjs","names":["process","path","hash","resolveKubbDir","kubbStorage","randomBytes"],"sources":["../src/runners/studio/credentials.ts"],"sourcesContent":["import { hash, randomBytes } from 'node:crypto'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { kubbStorage, resolveKubbDir } from '@kubb/core'\n\nconst projectBase = (project = process.cwd()) => path.join('projects', hash('sha256', project))\n\n/**\n * Root for the credential and machine identity of the current project, inside `KUBB_HOME`.\n *\n * Studio agents are project connections, so two projects on one machine must not share the same\n * persisted token or machine secret.\n */\nexport function getProjectKubbHome(project = process.cwd()): string {\n return resolveKubbDir(projectBase(project))\n}\n\nconst projectStorage = () => kubbStorage({ base: projectBase() })\n\nconst CREDENTIALS_FILENAME = 'credentials.json'\n\n/**\n * Absolute path of the stored credential, so callers can name it in output without rebuilding it.\n */\nexport function getCredentialsPath(): string {\n return path.join(getProjectKubbHome(), CREDENTIALS_FILENAME)\n}\n\nexport type Credentials = {\n /**\n * The Studio instance this machine paired with. A different `--url` means re-pairing.\n */\n studioUrl: string\n /**\n * Bearer token for this machine. Never logged, never printed.\n */\n token: string\n agentId: string\n agentSlug: string\n /**\n * Permissions the user has already granted, keyed by absolute project path, so the CLI asks\n * once per project instead of on every run.\n */\n projects?: Record<string, { allowRead?: boolean; allowReadAst?: boolean; allowWrite?: boolean; allowConfigEdit?: boolean; allowExec?: boolean }>\n}\n\n/**\n * Reads the stored credential, or null when this machine has not paired yet or the file is\n * unreadable or corrupt. A bad file is treated as \"not paired\" so `kubb studio login` can\n * overwrite it rather than the CLI dying on it.\n */\nexport async function readCredentials(): Promise<Credentials | null> {\n const stored = await projectStorage()\n .getItem<Credentials>(CREDENTIALS_FILENAME)\n .catch(() => null)\n\n return typeof stored?.token === 'string' && stored.token !== '' ? stored : null\n}\n\n/**\n * Writes the credential into the project folder, which only its owner can open.\n */\nexport async function writeCredentials(credentials: Credentials): Promise<void> {\n await projectStorage().setItem(CREDENTIALS_FILENAME, credentials)\n}\n\n/**\n * Forgets the stored credential. Succeeds when there was nothing to forget.\n */\nexport async function clearCredentials(): Promise<void> {\n await projectStorage().removeItem(CREDENTIALS_FILENAME)\n}\n\n/**\n * Reads this project's machine secret, creating it on first use. Pairing sends its hash, so pairing\n * the same project again rotates one agent's token instead of creating a second agent. It lives\n * apart from the credential, which {@link clearCredentials} deletes.\n */\nexport async function getMachineId(): Promise<string> {\n const storage = projectStorage()\n const stored = await storage.getItem('machine-secret').catch(() => null)\n if (typeof stored === 'string' && stored.trim()) return stored.trim()\n\n const secret = randomBytes(32).toString('hex')\n await storage.setItem('machine-secret', secret)\n\n return secret\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAKA,MAAM,eAAe,UAAUA,aAAAA,QAAQ,IAAI,MAAMC,UAAAA,QAAK,KAAK,aAAA,GAAYC,YAAAA,KAAAA,CAAK,UAAU,OAAO,CAAC;;;;;;;AAQ9F,SAAgB,mBAAmB,UAAUF,aAAAA,QAAQ,IAAI,GAAW;CAClE,QAAA,GAAOG,WAAAA,eAAAA,CAAe,YAAY,OAAO,CAAC;AAC5C;AAEA,MAAM,wBAAA,GAAuBC,WAAAA,YAAAA,CAAY,EAAE,MAAM,YAAY,EAAE,CAAC;AAEhE,MAAM,uBAAuB;;;;AAK7B,SAAgB,qBAA6B;CAC3C,OAAOH,UAAAA,QAAK,KAAK,mBAAmB,GAAG,oBAAoB;AAC7D;;;;;;AAyBA,eAAsB,kBAA+C;CACnE,MAAM,SAAS,MAAM,eAAe,CAAC,CAClC,QAAqB,oBAAoB,CAAC,CAC1C,YAAY,IAAI;CAEnB,OAAO,OAAO,QAAQ,UAAU,YAAY,OAAO,UAAU,KAAK,SAAS;AAC7E;;;;AAKA,eAAsB,iBAAiB,aAAyC;CAC9E,MAAM,eAAe,CAAC,CAAC,QAAQ,sBAAsB,WAAW;AAClE;;;;AAKA,eAAsB,mBAAkC;CACtD,MAAM,eAAe,CAAC,CAAC,WAAW,oBAAoB;AACxD;;;;;;AAOA,eAAsB,eAAgC;CACpD,MAAM,UAAU,eAAe;CAC/B,MAAM,SAAS,MAAM,QAAQ,QAAQ,gBAAgB,CAAC,CAAC,YAAY,IAAI;CACvE,IAAI,OAAO,WAAW,YAAY,OAAO,KAAK,GAAG,OAAO,OAAO,KAAK;CAEpE,MAAM,UAAA,GAASI,YAAAA,YAAAA,CAAY,EAAE,CAAC,CAAC,SAAS,KAAK;CAC7C,MAAM,QAAQ,QAAQ,kBAAkB,MAAM;CAE9C,OAAO;AACT"}