@kubb/cli 5.5.6 → 5.6.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 (146) hide show
  1. package/dist/{Telemetry-CMXOVUKB.js → Telemetry-RBcAjNxj.js} +18 -43
  2. package/dist/Telemetry-RBcAjNxj.js.map +1 -0
  3. package/dist/{Telemetry-DDHXBdEz.cjs → Telemetry-bGdFBaGt.cjs} +27 -89
  4. package/dist/Telemetry-bGdFBaGt.cjs.map +1 -0
  5. package/dist/agent-BPIqnEl2.js +59 -0
  6. package/dist/agent-BPIqnEl2.js.map +1 -0
  7. package/dist/agent-DElUuYuy.cjs +120 -0
  8. package/dist/agent-DElUuYuy.cjs.map +1 -0
  9. package/dist/{background-DxlRE9O5.js → background-0PMj56FJ.js} +6 -5
  10. package/dist/background-0PMj56FJ.js.map +1 -0
  11. package/dist/background-BqS01QDb.js +2 -0
  12. package/dist/{background-Bbcc2TdN.cjs → background-R0T_7Szu.cjs} +8 -7
  13. package/dist/background-R0T_7Szu.cjs.map +1 -0
  14. package/dist/commands-BAgGrcvc.js +65 -0
  15. package/dist/commands-BAgGrcvc.js.map +1 -0
  16. package/dist/commands-Si-RFAS6.cjs +71 -0
  17. package/dist/commands-Si-RFAS6.cjs.map +1 -0
  18. package/dist/config-8Xl4yZmw.js +146 -0
  19. package/dist/config-8Xl4yZmw.js.map +1 -0
  20. package/dist/config-ByfJSj3q.cjs +164 -0
  21. package/dist/config-ByfJSj3q.cjs.map +1 -0
  22. package/dist/constants-CdxpgX3_.cjs.map +1 -1
  23. package/dist/constants-DHRspBTo.js.map +1 -1
  24. package/dist/{errors-C-wEou02.cjs → errors-CMbMAwyW.cjs} +2 -2
  25. package/dist/{errors-C-wEou02.cjs.map → errors-CMbMAwyW.cjs.map} +1 -1
  26. package/dist/index.cjs +431 -22
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.js +429 -20
  29. package/dist/index.js.map +1 -1
  30. package/dist/output-B6Ondw0g.js +776 -0
  31. package/dist/output-B6Ondw0g.js.map +1 -0
  32. package/dist/output-i3s5c4Xu.cjs +878 -0
  33. package/dist/output-i3s5c4Xu.cjs.map +1 -0
  34. package/dist/run-3I2NPeXG.cjs +31 -0
  35. package/dist/run-3I2NPeXG.cjs.map +1 -0
  36. package/dist/{run-C-jBKNbI.cjs → run-BkLJ5mXn.cjs} +22 -43
  37. package/dist/run-BkLJ5mXn.cjs.map +1 -0
  38. package/dist/run-CZlkqkDc.js +30 -0
  39. package/dist/run-CZlkqkDc.js.map +1 -0
  40. package/dist/run-CmNDNEjR.js +346 -0
  41. package/dist/run-CmNDNEjR.js.map +1 -0
  42. package/dist/{run-BdTwxLCW.js → run-D5AeacqK.js} +9 -23
  43. package/dist/run-D5AeacqK.js.map +1 -0
  44. package/dist/{run-y6LRyWdS.cjs → run-D8Wz_17X.cjs} +41 -60
  45. package/dist/run-D8Wz_17X.cjs.map +1 -0
  46. package/dist/{run-Dn8HVjnM.js → run-DQoKTiGk.js} +23 -44
  47. package/dist/run-DQoKTiGk.js.map +1 -0
  48. package/dist/{run-BDaZPU-1.js → run-Dgph0WYk.js} +25 -49
  49. package/dist/run-Dgph0WYk.js.map +1 -0
  50. package/dist/run-t8nm7zcT.cjs +348 -0
  51. package/dist/run-t8nm7zcT.cjs.map +1 -0
  52. package/dist/{run-CZz_GbE4.cjs → run-yvuot2N9.cjs} +12 -26
  53. package/dist/run-yvuot2N9.cjs.map +1 -0
  54. package/dist/{snapshot-B5mc4gpC.js → snapshot-CkHXR0Nl.js} +5 -5
  55. package/dist/snapshot-CkHXR0Nl.js.map +1 -0
  56. package/dist/{snapshot-DnCxZfmM.cjs → snapshot-D4nKbwkw.cjs} +9 -9
  57. package/dist/snapshot-D4nKbwkw.cjs.map +1 -0
  58. package/dist/studioWorker.js +2 -2
  59. package/package.json +7 -7
  60. package/dist/Telemetry-CMXOVUKB.js.map +0 -1
  61. package/dist/Telemetry-DDHXBdEz.cjs.map +0 -1
  62. package/dist/agent-DiB4CRre.cjs +0 -38
  63. package/dist/agent-DiB4CRre.cjs.map +0 -1
  64. package/dist/agent-yA5vrXJB.js +0 -26
  65. package/dist/agent-yA5vrXJB.js.map +0 -1
  66. package/dist/background-Bbcc2TdN.cjs.map +0 -1
  67. package/dist/background-CFNncNYT.js +0 -2
  68. package/dist/background-DxlRE9O5.js.map +0 -1
  69. package/dist/connect-C9tTngda.js +0 -11
  70. package/dist/connect-C9tTngda.js.map +0 -1
  71. package/dist/connect-CJ7BhOcs.cjs +0 -11
  72. package/dist/connect-CJ7BhOcs.cjs.map +0 -1
  73. package/dist/generate-BUqZ_7GB.cjs +0 -92
  74. package/dist/generate-BUqZ_7GB.cjs.map +0 -1
  75. package/dist/generate-q2m01zRd.js +0 -92
  76. package/dist/generate-q2m01zRd.js.map +0 -1
  77. package/dist/gunshiDryRun-DdKJuVn1.js +0 -2
  78. package/dist/init-Ckpwkfvz.cjs +0 -58
  79. package/dist/init-Ckpwkfvz.cjs.map +0 -1
  80. package/dist/init-DukE9Uw4.js +0 -58
  81. package/dist/init-DukE9Uw4.js.map +0 -1
  82. package/dist/login-Bc19oiFE.cjs +0 -11
  83. package/dist/login-Bc19oiFE.cjs.map +0 -1
  84. package/dist/login-Do3nns0B.js +0 -11
  85. package/dist/login-Do3nns0B.js.map +0 -1
  86. package/dist/logout-BvHFvCeI.cjs +0 -16
  87. package/dist/logout-BvHFvCeI.cjs.map +0 -1
  88. package/dist/logout-COxoIMum.js +0 -16
  89. package/dist/logout-COxoIMum.js.map +0 -1
  90. package/dist/mcp-B-GxGgVr.js +0 -19
  91. package/dist/mcp-B-GxGgVr.js.map +0 -1
  92. package/dist/mcp-B3B-rE7W.cjs +0 -18
  93. package/dist/mcp-B3B-rE7W.cjs.map +0 -1
  94. package/dist/output-CVLosNZq.cjs +0 -411
  95. package/dist/output-CVLosNZq.cjs.map +0 -1
  96. package/dist/output-FDo-db-w.js +0 -321
  97. package/dist/output-FDo-db-w.js.map +0 -1
  98. package/dist/package-Ci2fcoOV.js +0 -6
  99. package/dist/package-Ci2fcoOV.js.map +0 -1
  100. package/dist/package-Do9rJ7D3.cjs +0 -11
  101. package/dist/package-Do9rJ7D3.cjs.map +0 -1
  102. package/dist/rolldown-runtime-qbf5tadS.cjs +0 -38
  103. package/dist/run-BDaZPU-1.js.map +0 -1
  104. package/dist/run-BdTwxLCW.js.map +0 -1
  105. package/dist/run-C-jBKNbI.cjs.map +0 -1
  106. package/dist/run-CAcQlhub.js +0 -295
  107. package/dist/run-CAcQlhub.js.map +0 -1
  108. package/dist/run-CSoFhDyK.cjs +0 -297
  109. package/dist/run-CSoFhDyK.cjs.map +0 -1
  110. package/dist/run-CZz_GbE4.cjs.map +0 -1
  111. package/dist/run-CaEbo-te.js +0 -40
  112. package/dist/run-CaEbo-te.js.map +0 -1
  113. package/dist/run-CihzLZmR.cjs +0 -41
  114. package/dist/run-CihzLZmR.cjs.map +0 -1
  115. package/dist/run-Dn8HVjnM.js.map +0 -1
  116. package/dist/run-y6LRyWdS.cjs.map +0 -1
  117. package/dist/shared-Cl-OLpNh.cjs +0 -81
  118. package/dist/shared-Cl-OLpNh.cjs.map +0 -1
  119. package/dist/shared-DaHA7QFQ.js +0 -58
  120. package/dist/shared-DaHA7QFQ.js.map +0 -1
  121. package/dist/snapshot-B5mc4gpC.js.map +0 -1
  122. package/dist/snapshot-DnCxZfmM.cjs.map +0 -1
  123. package/dist/start-B-GXO8tS.cjs +0 -12
  124. package/dist/start-B-GXO8tS.cjs.map +0 -1
  125. package/dist/start-Dbfx_8zG.js +0 -12
  126. package/dist/start-Dbfx_8zG.js.map +0 -1
  127. package/dist/status-DDajNc8w.js +0 -17
  128. package/dist/status-DDajNc8w.js.map +0 -1
  129. package/dist/status-DusS7DfO.cjs +0 -17
  130. package/dist/status-DusS7DfO.cjs.map +0 -1
  131. package/dist/stop-C5t7Yx0t.js +0 -11
  132. package/dist/stop-C5t7Yx0t.js.map +0 -1
  133. package/dist/stop-zmM3A0Re.cjs +0 -11
  134. package/dist/stop-zmM3A0Re.cjs.map +0 -1
  135. package/dist/studio--IOOl_VB.js +0 -174
  136. package/dist/studio--IOOl_VB.js.map +0 -1
  137. package/dist/studio-CJ2XhtRd.cjs +0 -174
  138. package/dist/studio-CJ2XhtRd.cjs.map +0 -1
  139. package/dist/utils-C3HZOWL_.js +0 -1107
  140. package/dist/utils-C3HZOWL_.js.map +0 -1
  141. package/dist/utils-ClRbJfxu.cjs +0 -1210
  142. package/dist/utils-ClRbJfxu.cjs.map +0 -1
  143. package/dist/validate-BcB0tFQ6.cjs +0 -19
  144. package/dist/validate-BcB0tFQ6.cjs.map +0 -1
  145. package/dist/validate-QpkCbIFJ.js +0 -20
  146. package/dist/validate-QpkCbIFJ.js.map +0 -1
@@ -0,0 +1,346 @@
1
+ import "./rolldown-runtime-CRm0XQPb.js";
2
+ import { t as toError } from "./errors-BQJzaUwP.js";
3
+ import { n as trackRun, r as version } from "./Telemetry-RBcAjNxj.js";
4
+ import { n as selectReporters, r as setupReporters, t as getConfigs } from "./config-8Xl4yZmw.js";
5
+ import { _ as pluralize, a as logInfo, c as logSpacer, i as logError, l as logStep, n as logBanner, o as logIntro, s as logOutro, t as createSpinner, u as logTip } from "./output-B6Ondw0g.js";
6
+ import { styleText } from "node:util";
7
+ import process from "node:process";
8
+ import path from "node:path";
9
+ import { Diagnostics, Hookable, cliReporter, createKubb, fileReporter, getInputKind, htmlReporter, jsonReporter, logLevel, memoryStorage } from "@kubb/core";
10
+ import { isGreaterThan, isValid, truncate } from "verkit";
11
+ //#region src/runners/generate/utils.ts
12
+ /** Glob pattern for paths the file watcher ignores. */
13
+ const WATCHER_IGNORED_PATHS = "**/{.git,node_modules}/**";
14
+ /** Quiet window in milliseconds that collapses a burst of watcher events (an editor save emits several) into one rebuild. */
15
+ const WATCHER_DEBOUNCE_MS = 100;
16
+ /** Interval in milliseconds between polls of a remote `input` URL in watch mode, which emits no filesystem events. */
17
+ const URL_WATCHER_INTERVAL_MS = 2e3;
18
+ /** Upper bound in milliseconds for one URL watcher request, headers and body read, so a hung server never stalls polling. */
19
+ const URL_WATCHER_TIMEOUT_MS = 1e4;
20
+ /**
21
+ * Returns `true` when `latest` is a newer semver version than `current`. Compares each numeric
22
+ * part, so `5.10.0` beats `5.9.0` where a plain string comparison would not. Prerelease
23
+ * suffixes are ignored, and a malformed version never reports an update.
24
+ *
25
+ * @example Double-digit minor
26
+ * `isNewerVersion('5.9.0', '5.10.0') // true`
27
+ *
28
+ * @example String comparison would get this wrong the other way
29
+ * `isNewerVersion('5.10.0', '5.9.0') // false`
30
+ */
31
+ function isNewerVersion(current, latest) {
32
+ if (!isValid(current) || !isValid(latest)) return false;
33
+ return isGreaterThan(truncate(latest, "patch"), truncate(current, "patch"));
34
+ }
35
+ /**
36
+ * Wraps `run` so invocations never overlap: a trigger that lands while a run is in flight
37
+ * marks it dirty and runs once more after it finishes, no matter how many triggers arrived.
38
+ * Useful for event-driven reruns (a file watcher, a queue drain) where bursts should
39
+ * coalesce into a single trailing run.
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * const rebuild = createSerialRunner({
44
+ * run: () => build(),
45
+ * onError: (error) => log.error(error.message),
46
+ * })
47
+ * watcher.on('change', () => void rebuild())
48
+ * ```
49
+ */
50
+ function createSerialRunner({ run, onError }) {
51
+ let running = false;
52
+ let dirty = false;
53
+ return async () => {
54
+ if (running) {
55
+ dirty = true;
56
+ return;
57
+ }
58
+ running = true;
59
+ do {
60
+ dirty = false;
61
+ try {
62
+ await run();
63
+ } catch (error) {
64
+ onError(toError(error));
65
+ }
66
+ } while (dirty);
67
+ running = false;
68
+ };
69
+ }
70
+ /**
71
+ * Starts a file watcher on the given paths and calls `cb` on any change.
72
+ * Ignores `.git` and `node_modules` directories. Event bursts (an editor save emits several)
73
+ * are debounced into one build, and builds never overlap: changes during a build queue exactly
74
+ * one rebuild. Resolves to a function that stops watching.
75
+ */
76
+ async function startWatcher(path, cb, log = {
77
+ info: console.log,
78
+ error: console.log
79
+ }) {
80
+ const { watch } = await import("chokidar");
81
+ const watcher = watch(path, {
82
+ ignorePermissionErrors: true,
83
+ ignored: WATCHER_IGNORED_PATHS,
84
+ ignoreInitial: true
85
+ });
86
+ process.once("SIGINT", () => {
87
+ watcher.close();
88
+ });
89
+ process.once("SIGTERM", () => {
90
+ watcher.close();
91
+ });
92
+ const runBuild = createSerialRunner({
93
+ run: () => cb(path),
94
+ onError: () => log.error(styleText("red", "Watcher failed"))
95
+ });
96
+ let debounceTimer = null;
97
+ watcher.on("all", (type, file) => {
98
+ log.info(styleText("yellow", styleText("bold", `Change detected: ${type} ${file}`)));
99
+ if (debounceTimer) clearTimeout(debounceTimer);
100
+ debounceTimer = setTimeout(() => {
101
+ debounceTimer = null;
102
+ runBuild();
103
+ }, WATCHER_DEBOUNCE_MS);
104
+ });
105
+ return async () => {
106
+ if (debounceTimer) clearTimeout(debounceTimer);
107
+ await watcher.close();
108
+ };
109
+ }
110
+ /**
111
+ * Fetches the body of a remote spec URL, `undefined` when the server does not answer with a
112
+ * readable 2xx body before `signal` aborts. The caller seeds `startUrlWatcher` with the result, so
113
+ * the watcher compares polls against the content the initial build ran on.
114
+ */
115
+ async function fetchUrlBody(url, signal = AbortSignal.timeout(URL_WATCHER_TIMEOUT_MS)) {
116
+ try {
117
+ const response = await fetch(url, { signal });
118
+ if (!response.ok) return void 0;
119
+ return await response.text();
120
+ } catch {
121
+ return;
122
+ }
123
+ }
124
+ /**
125
+ * Polls a remote spec URL and calls `cb` whenever the response body changes. A remote document
126
+ * emits no filesystem events, so this is the URL counterpart of `startWatcher`.
127
+ *
128
+ * `initialBody` seeds the change detection, so an edit landing between the initial build and the
129
+ * first poll still rebuilds. An unreachable server (the API restarting between saves) is reported
130
+ * once per outage and polling continues; after it recovers, a rebuild happens only when the body
131
+ * actually differs from the last one seen, so a plain restart with an unchanged spec stays quiet.
132
+ * Each request is aborted after `timeoutMs`, so a hung response delays at most one poll.
133
+ *
134
+ * Returns a function that stops polling and aborts the in-flight request, so callers (and tests)
135
+ * can shut the watcher down without signaling the process.
136
+ */
137
+ function startUrlWatcher(url, cb, options = {}) {
138
+ const { log = {
139
+ info: console.log,
140
+ error: console.log
141
+ }, intervalMs = URL_WATCHER_INTERVAL_MS, timeoutMs = URL_WATCHER_TIMEOUT_MS, initialBody } = options;
142
+ let lastBody = initialBody;
143
+ let offline = false;
144
+ let timer = null;
145
+ let controller = null;
146
+ let stopped = false;
147
+ const stop = () => {
148
+ stopped = true;
149
+ if (timer) clearTimeout(timer);
150
+ controller?.abort();
151
+ };
152
+ process.once("SIGINT", stop);
153
+ process.once("SIGTERM", stop);
154
+ const runBuild = createSerialRunner({
155
+ run: () => cb([url]),
156
+ onError: () => log.error(styleText("red", "Watcher failed"))
157
+ });
158
+ const schedule = () => {
159
+ if (!stopped) timer = setTimeout(() => void poll(), intervalMs);
160
+ };
161
+ const poll = async () => {
162
+ controller = new AbortController();
163
+ const body = await fetchUrlBody(url, AbortSignal.any([controller.signal, AbortSignal.timeout(timeoutMs)]));
164
+ if (body === void 0) {
165
+ if (!offline && !stopped) {
166
+ offline = true;
167
+ log.error(styleText("red", `Cannot reach ${url}, polling until it responds again`));
168
+ }
169
+ schedule();
170
+ return;
171
+ }
172
+ if (offline) {
173
+ offline = false;
174
+ log.info(styleText("yellow", `${url} is reachable again`));
175
+ }
176
+ const changed = lastBody !== void 0 && body !== lastBody;
177
+ if (changed) log.info(styleText("yellow", styleText("bold", `Change detected: ${url}`)));
178
+ if (changed || lastBody === void 0) runBuild();
179
+ lastBody = body;
180
+ schedule();
181
+ };
182
+ poll();
183
+ return stop;
184
+ }
185
+ //#endregion
186
+ //#region src/runners/generate/run.ts
187
+ /** NPM registry endpoint used to check for @kubb/cli updates. */
188
+ const KUBB_NPM_PACKAGE_URL = "https://registry.npmjs.org/@kubb/cli/latest";
189
+ /** Upper bound in milliseconds for the npm update check, so a slow registry never stalls a run. */
190
+ const UPDATE_CHECK_TIMEOUT_MS = 3e3;
191
+ async function generate(options) {
192
+ const { input, hooks, dryRun = false } = options;
193
+ const report = trackRun({
194
+ command: "generate",
195
+ hrStart: process.hrtime()
196
+ });
197
+ const config = {
198
+ ...options.config,
199
+ input: input ?? options.config.input,
200
+ storage: dryRun ? memoryStorage() : options.config.storage,
201
+ output: dryRun ? {
202
+ ...options.config.output,
203
+ format: false,
204
+ lint: false,
205
+ postGenerate: []
206
+ } : options.config.output
207
+ };
208
+ const kubb = createKubb(config, { hooks });
209
+ const result = await kubb.generate();
210
+ if (dryRun) await hooks.callHook("kubb:info", {
211
+ message: "Dry run: no files were written",
212
+ info: `${result.files.length} file(s) would be generated`
213
+ });
214
+ await report({
215
+ plugins: Array.from(kubb.driver.plugins.values(), (p) => ({
216
+ name: p.name,
217
+ options: p.options
218
+ })),
219
+ filesCreated: result.files.length,
220
+ status: result.success ? "success" : "failed"
221
+ });
222
+ return result.success;
223
+ }
224
+ async function checkForUpdate(hooks) {
225
+ try {
226
+ const data = await (await fetch(KUBB_NPM_PACKAGE_URL, { signal: AbortSignal.timeout(UPDATE_CHECK_TIMEOUT_MS) })).json();
227
+ if (data.version && isNewerVersion(version, data.version)) await Diagnostics.emit(hooks, Diagnostics.update({
228
+ currentVersion: version,
229
+ latestVersion: data.version
230
+ }));
231
+ } catch {}
232
+ }
233
+ /**
234
+ * Runs the full Kubb generation lifecycle for the given CLI options.
235
+ * Loads configs, sets up the reporters (CLI `--reporter` picks which of `config.reporters` to trigger),
236
+ * checks for a newer version, and calls `generate` for each config entry.
237
+ */
238
+ async function run({ input, configPath, logLevel: logLevelKey, watch, reporters: cliReporters, dryRun }) {
239
+ const logLevel$1 = logLevel[logLevelKey] ?? logLevel.info;
240
+ const hooks = new Hookable();
241
+ const requestedNames = cliReporters?.length ? cliReporters : ["cli"];
242
+ const quiet = logLevel$1 <= logLevel.silent || requestedNames.includes("json");
243
+ if (!quiet) {
244
+ logBanner(version);
245
+ logIntro({ title: "Configuration" });
246
+ }
247
+ const configSpinner = createSpinner();
248
+ let configs;
249
+ let resolvedConfigPath;
250
+ try {
251
+ if (!quiet) configSpinner.start("Loading config");
252
+ const loaded = await getConfigs({
253
+ configPath,
254
+ input,
255
+ watch,
256
+ logLevel: logLevelKey
257
+ });
258
+ configs = loaded.configs;
259
+ resolvedConfigPath = loaded.configPath;
260
+ if (!quiet) configSpinner.stop(`Loaded ${styleText("dim", path.relative(process.cwd(), resolvedConfigPath))}`);
261
+ } catch (error) {
262
+ if (!quiet) configSpinner.error("Config failed loading");
263
+ setupReporters(hooks, {
264
+ logLevel: logLevel$1,
265
+ reporters: [cliReporter]
266
+ });
267
+ await hooks.callHook("kubb:error", { error: toError(error) });
268
+ if (!quiet) logOutro(styleText("red", "✗ Configuration failed"));
269
+ process.exit(1);
270
+ }
271
+ const available = configs[0]?.reporters?.length ? configs[0].reporters : [
272
+ cliReporter,
273
+ jsonReporter,
274
+ fileReporter,
275
+ htmlReporter
276
+ ];
277
+ const reporters = selectReporters(available, requestedNames);
278
+ setupReporters(hooks, {
279
+ logLevel: logLevel$1,
280
+ reporters
281
+ });
282
+ await hooks.callHook("kubb:lifecycle:start", { version });
283
+ await checkForUpdate(hooks);
284
+ if (!quiet) logOutro(`${pluralize(configs.length, "config")} ready`);
285
+ try {
286
+ let anyFailed = false;
287
+ for (const config of configs) {
288
+ const effectiveInput = input ?? config.input;
289
+ const inputKind = typeof effectiveInput === "string" ? getInputKind(effectiveInput) : void 0;
290
+ const watchPath = inputKind === "file" || inputKind === "url" ? effectiveInput : void 0;
291
+ if (watchPath && watch) {
292
+ const watchedPaths = [watchPath];
293
+ const build = async (paths) => {
294
+ const succeeded = await generate({
295
+ input,
296
+ config,
297
+ hooks,
298
+ dryRun
299
+ });
300
+ logStep(styleText("yellow", `Watching for changes in ${paths.join(" and ")}`));
301
+ if (succeeded) {
302
+ logSpacer();
303
+ logTip();
304
+ }
305
+ };
306
+ const initialBody = inputKind === "url" ? await fetchUrlBody(watchPath) : void 0;
307
+ try {
308
+ await build(watchedPaths);
309
+ } catch (buildError) {
310
+ await hooks.callHook("kubb:error", { error: toError(buildError) });
311
+ }
312
+ if (inputKind === "url") startUrlWatcher(watchPath, build, {
313
+ log: {
314
+ info: logInfo,
315
+ error: logError
316
+ },
317
+ initialBody
318
+ });
319
+ else await startWatcher(watchedPaths, build, {
320
+ info: logInfo,
321
+ error: logError
322
+ });
323
+ } else try {
324
+ if (!await generate({
325
+ input,
326
+ config,
327
+ hooks,
328
+ dryRun
329
+ })) anyFailed = true;
330
+ } catch (configError) {
331
+ await hooks.callHook("kubb:error", { error: toError(configError) });
332
+ anyFailed = true;
333
+ }
334
+ }
335
+ await hooks.callHook("kubb:lifecycle:end");
336
+ if (!quiet && !watch && !anyFailed) logTip();
337
+ if (anyFailed) process.exit(1);
338
+ } catch (error) {
339
+ await hooks.callHook("kubb:error", { error: toError(error) });
340
+ process.exit(1);
341
+ }
342
+ }
343
+ //#endregion
344
+ export { run };
345
+
346
+ //# sourceMappingURL=run-CmNDNEjR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-CmNDNEjR.js","names":["logLevel","logLevelMap"],"sources":["../src/runners/generate/utils.ts","../src/runners/generate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport { isGreaterThan, isValid, truncate } from 'verkit'\n\n/** Glob pattern for paths the file watcher ignores. */\nconst WATCHER_IGNORED_PATHS = '**/{.git,node_modules}/**' as const\n\n/** Quiet window in milliseconds that collapses a burst of watcher events (an editor save emits several) into one rebuild. */\nconst WATCHER_DEBOUNCE_MS = 100\n\n/** Interval in milliseconds between polls of a remote `input` URL in watch mode, which emits no filesystem events. */\nconst URL_WATCHER_INTERVAL_MS = 2_000\n\n/** Upper bound in milliseconds for one URL watcher request, headers and body read, so a hung server never stalls polling. */\nconst URL_WATCHER_TIMEOUT_MS = 10_000\n\n/**\n * Returns `true` when `latest` is a newer semver version than `current`. Compares each numeric\n * part, so `5.10.0` beats `5.9.0` where a plain string comparison would not. Prerelease\n * suffixes are ignored, and a malformed version never reports an update.\n *\n * @example Double-digit minor\n * `isNewerVersion('5.9.0', '5.10.0') // true`\n *\n * @example String comparison would get this wrong the other way\n * `isNewerVersion('5.10.0', '5.9.0') // false`\n */\nexport function isNewerVersion(current: string, latest: string): boolean {\n if (!isValid(current) || !isValid(latest)) return false\n\n return isGreaterThan(truncate(latest, 'patch') as string, truncate(current, 'patch') as string)\n}\n\ntype SerialRunnerOptions = {\n /**\n * The async work to serialize.\n */\n run(): Promise<void>\n /**\n * Receives errors thrown by `run`, so a failure never rejects the returned trigger.\n */\n onError(error: Error): void\n}\n\n/**\n * Wraps `run` so invocations never overlap: a trigger that lands while a run is in flight\n * marks it dirty and runs once more after it finishes, no matter how many triggers arrived.\n * Useful for event-driven reruns (a file watcher, a queue drain) where bursts should\n * coalesce into a single trailing run.\n *\n * @example\n * ```ts\n * const rebuild = createSerialRunner({\n * run: () => build(),\n * onError: (error) => log.error(error.message),\n * })\n * watcher.on('change', () => void rebuild())\n * ```\n */\nexport function createSerialRunner({ run, onError }: SerialRunnerOptions): () => Promise<void> {\n let running = false\n let dirty = false\n\n return async (): Promise<void> => {\n if (running) {\n dirty = true\n return\n }\n running = true\n do {\n dirty = false\n try {\n await run()\n } catch (error) {\n onError(toError(error))\n }\n } while (dirty)\n running = false\n }\n}\n\ntype WatcherLog = {\n info: (message: string) => void\n error: (message: string) => void\n}\n\n/**\n * Starts a file watcher on the given paths and calls `cb` on any change.\n * Ignores `.git` and `node_modules` directories. Event bursts (an editor save emits several)\n * are debounced into one build, and builds never overlap: changes during a build queue exactly\n * one rebuild. Resolves to a function that stops watching.\n */\nexport async function startWatcher(\n path: Array<string>,\n cb: (path: Array<string>) => Promise<void>,\n log: WatcherLog = { info: console.log, error: console.log },\n): Promise<() => Promise<void>> {\n const { watch } = await import('chokidar')\n // `ignoreInitial` skips the `add` events chokidar fires for existing files at startup, which\n // would otherwise rebuild right after the initial run.\n const watcher = watch(path, { ignorePermissionErrors: true, ignored: WATCHER_IGNORED_PATHS, ignoreInitial: true })\n\n process.once('SIGINT', () => {\n watcher.close()\n })\n process.once('SIGTERM', () => {\n watcher.close()\n })\n\n // Bursts never overlap builds on the shared hooks emitter: a change during a build\n // queues exactly one rerun.\n const runBuild = createSerialRunner({\n run: () => cb(path),\n onError: () => log.error(styleText('red', 'Watcher failed')),\n })\n let debounceTimer: ReturnType<typeof setTimeout> | null = null\n\n watcher.on('all', (type, file) => {\n log.info(styleText('yellow', styleText('bold', `Change detected: ${type} ${file}`)))\n if (debounceTimer) clearTimeout(debounceTimer)\n debounceTimer = setTimeout(() => {\n debounceTimer = null\n void runBuild()\n }, WATCHER_DEBOUNCE_MS)\n })\n\n return async () => {\n if (debounceTimer) clearTimeout(debounceTimer)\n await watcher.close()\n }\n}\n\n/**\n * Fetches the body of a remote spec URL, `undefined` when the server does not answer with a\n * readable 2xx body before `signal` aborts. The caller seeds `startUrlWatcher` with the result, so\n * the watcher compares polls against the content the initial build ran on.\n */\nexport async function fetchUrlBody(url: string, signal: AbortSignal = AbortSignal.timeout(URL_WATCHER_TIMEOUT_MS)): Promise<string | undefined> {\n try {\n const response = await fetch(url, { signal })\n if (!response.ok) return undefined\n return await response.text()\n } catch {\n return undefined\n }\n}\n\ntype UrlWatcherOptions = {\n /**\n * Sink for watcher messages, `console.log` by default.\n */\n log?: WatcherLog\n /**\n * Time in milliseconds between polls.\n */\n intervalMs?: number\n /**\n * Upper bound in milliseconds for one poll request, covering headers and body read.\n */\n timeoutMs?: number\n /**\n * Body the initial build ran against, the baseline for change detection. When omitted (the\n * server was unreachable at startup), the first successful poll rebuilds so the output catches\n * up as soon as the server responds.\n */\n initialBody?: string\n}\n\n/**\n * Polls a remote spec URL and calls `cb` whenever the response body changes. A remote document\n * emits no filesystem events, so this is the URL counterpart of `startWatcher`.\n *\n * `initialBody` seeds the change detection, so an edit landing between the initial build and the\n * first poll still rebuilds. An unreachable server (the API restarting between saves) is reported\n * once per outage and polling continues; after it recovers, a rebuild happens only when the body\n * actually differs from the last one seen, so a plain restart with an unchanged spec stays quiet.\n * Each request is aborted after `timeoutMs`, so a hung response delays at most one poll.\n *\n * Returns a function that stops polling and aborts the in-flight request, so callers (and tests)\n * can shut the watcher down without signaling the process.\n */\nexport function startUrlWatcher(url: string, cb: (path: Array<string>) => Promise<void>, options: UrlWatcherOptions = {}): () => void {\n const { log = { info: console.log, error: console.log }, intervalMs = URL_WATCHER_INTERVAL_MS, timeoutMs = URL_WATCHER_TIMEOUT_MS, initialBody } = options\n\n let lastBody = initialBody\n let offline = false\n let timer: ReturnType<typeof setTimeout> | null = null\n let controller: AbortController | null = null\n let stopped = false\n\n const stop = () => {\n stopped = true\n if (timer) clearTimeout(timer)\n controller?.abort()\n }\n process.once('SIGINT', stop)\n process.once('SIGTERM', stop)\n\n // Builds never overlap on the shared hooks emitter: a change during a build queues exactly\n // one rerun.\n const runBuild = createSerialRunner({\n run: () => cb([url]),\n onError: () => log.error(styleText('red', 'Watcher failed')),\n })\n\n const schedule = () => {\n if (!stopped) {\n timer = setTimeout(() => void poll(), intervalMs)\n }\n }\n\n const poll = async (): Promise<void> => {\n controller = new AbortController()\n // The signal also aborts the body read, so a response that stalls mid-stream still times out.\n const body = await fetchUrlBody(url, AbortSignal.any([controller.signal, AbortSignal.timeout(timeoutMs)]))\n\n if (body === undefined) {\n // `lastBody` survives the outage so recovery rebuilds only on real content changes.\n if (!offline && !stopped) {\n offline = true\n log.error(styleText('red', `Cannot reach ${url}, polling until it responds again`))\n }\n schedule()\n return\n }\n\n if (offline) {\n offline = false\n log.info(styleText('yellow', `${url} is reachable again`))\n }\n const changed = lastBody !== undefined && body !== lastBody\n if (changed) {\n log.info(styleText('yellow', styleText('bold', `Change detected: ${url}`)))\n }\n if (changed || lastBody === undefined) {\n void runBuild()\n }\n lastBody = body\n schedule()\n }\n\n void poll()\n\n return stop\n}\n","import path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport { formatters, linters, toError } from '@internals/utils'\nimport {\n Hookable,\n type CLIOptions,\n cliReporter,\n type Config,\n createKubb,\n Diagnostics,\n fileReporter,\n getInputKind,\n htmlReporter,\n jsonReporter,\n type KubbHooks,\n logLevel as logLevelMap,\n memoryStorage,\n type ReporterName,\n} from '@kubb/core'\nimport { version } from '../../../package.json'\nimport { trackRun } from '../../Telemetry.ts'\nimport { pluralize } from '../../loggers/createLogger.ts'\nimport setupReporters, { selectReporters } from '../../loggers/reporters.ts'\nimport { createSpinner, logBanner, logError, logInfo, logIntro, logOutro, logSpacer, logStep, logTip } from '../../loggers/output.ts'\nimport { getConfigs } from '../../config.ts'\nimport { fetchUrlBody, isNewerVersion, startUrlWatcher, startWatcher } from './utils.ts'\n\n/** NPM registry endpoint used to check for @kubb/cli updates. */\nconst KUBB_NPM_PACKAGE_URL = 'https://registry.npmjs.org/@kubb/cli/latest' as const\n\n/** Upper bound in milliseconds for the npm update check, so a slow registry never stalls a run. */\nconst UPDATE_CHECK_TIMEOUT_MS = 3_000\n\n/** The formatter names from `Config['output'].format`, without `'auto'` (detection, not a tool) and `false` (skip). */\ntype FormatterName = Exclude<NonNullable<Config['output']['format']>, 'auto' | false>\ntype LinterName = Exclude<NonNullable<Config['output']['lint']>, 'auto' | false>\n\n// Pinned here, not in `@internals/utils` (which must not import `@kubb/core`): a tool added to the union without a descriptor fails to compile.\nformatters satisfies Record<FormatterName, unknown>\nlinters satisfies Record<LinterName, unknown>\n\ntype GenerateProps = {\n input?: string\n config: Config\n hooks: Hookable<KubbHooks>\n /**\n * When `true`, generates in memory instead of writing to disk, and skips formatting, linting,\n * and post-generate commands.\n */\n dryRun?: boolean\n}\n\nasync function generate(options: GenerateProps): Promise<boolean> {\n const { input, hooks, dryRun = false } = options\n\n const report = trackRun({ command: 'generate', hrStart: process.hrtime() })\n\n const config: Config = {\n ...options.config,\n input: input ?? options.config.input,\n // Dry-run never touches disk, regardless of the config's own storage driver.\n storage: dryRun ? memoryStorage() : options.config.storage,\n // Also keeps core's `hasOutputPasses` false, so dry-run skips the output manifest write too.\n output: dryRun ? { ...options.config.output, format: false, lint: false, postGenerate: [] } : options.config.output,\n }\n\n // Core formats, lints and runs `output.postGenerate` after an error-free build, and reports\n // their failures as coded diagnostics that reach the summary, the json report and the exit code.\n const kubb = createKubb(config, { hooks })\n const result = await kubb.generate()\n\n if (dryRun) {\n await hooks.callHook('kubb:info', { message: 'Dry run: no files were written', info: `${result.files.length} file(s) would be generated` })\n }\n\n await report({\n plugins: Array.from(kubb.driver.plugins.values(), (p) => ({ name: p.name, options: p.options as Record<string, unknown> })),\n filesCreated: result.files.length,\n status: result.success ? 'success' : 'failed',\n })\n\n return result.success\n}\n\ntype GenerateCommandOptions = {\n input?: string\n configPath?: string\n logLevel: string\n watch: boolean\n reporters?: Array<ReporterName>\n dryRun?: boolean\n}\n\nasync function checkForUpdate(hooks: Hookable<KubbHooks>): Promise<void> {\n try {\n const res = await fetch(KUBB_NPM_PACKAGE_URL, { signal: AbortSignal.timeout(UPDATE_CHECK_TIMEOUT_MS) })\n const data = (await res.json()) as { version: string }\n if (data.version && isNewerVersion(version, data.version)) {\n await Diagnostics.emit(hooks, Diagnostics.update({ currentVersion: version, latestVersion: data.version }))\n }\n } catch {\n // Ignore network errors\n }\n}\n\n/**\n * Runs the full Kubb generation lifecycle for the given CLI options.\n * Loads configs, sets up the reporters (CLI `--reporter` picks which of `config.reporters` to trigger),\n * checks for a newer version, and calls `generate` for each config entry.\n */\nexport async function run({ input, configPath, logLevel: logLevelKey, watch, reporters: cliReporters, dryRun }: GenerateCommandOptions): Promise<void> {\n const logLevel = logLevelMap[logLevelKey as keyof typeof logLevelMap] ?? logLevelMap.info\n const hooks = new Hookable<KubbHooks>()\n\n // CLI `--reporter` selects which reporters to trigger by name, defaulting to `cli`. `defineConfig`\n // registers the built-in reporters on the config; a config exported without it falls back to them below.\n const requestedNames: Array<ReporterName> = cliReporters?.length ? cliReporters : ['cli']\n\n // The `json` reporter owns stdout, so the command writes nothing of its own around it.\n const quiet = logLevel <= logLevelMap.silent || requestedNames.includes('json')\n\n if (!quiet) {\n logBanner(version)\n logIntro({ title: 'Configuration' })\n }\n\n // Load the config first so `config.reporters` can pick the reporters. A failure here has no\n // reporter installed yet, so fall back to the default `cli` reporter to surface it.\n const configSpinner = createSpinner()\n let configs: Array<Config>\n let resolvedConfigPath: string\n try {\n if (!quiet) configSpinner.start('Loading config')\n\n const loaded = await getConfigs({\n configPath,\n input,\n watch,\n logLevel: logLevelKey as CLIOptions['logLevel'],\n })\n configs = loaded.configs\n resolvedConfigPath = loaded.configPath\n\n if (!quiet) configSpinner.stop(`Loaded ${styleText('dim', path.relative(process.cwd(), resolvedConfigPath))}`)\n } catch (error) {\n if (!quiet) configSpinner.error('Config failed loading')\n\n setupReporters(hooks, { logLevel, reporters: [cliReporter] })\n await hooks.callHook('kubb:error', { error: toError(error) })\n\n if (!quiet) logOutro(styleText('red', '✗ Configuration failed'))\n process.exit(1)\n }\n\n // Without a reporter nothing is printed, not even an error, so a config written without\n // `defineConfig` gets the same built-ins it would have registered.\n const available = configs[0]?.reporters?.length ? configs[0].reporters : [cliReporter, jsonReporter, fileReporter, htmlReporter]\n const reporters = selectReporters(available, requestedNames)\n setupReporters(hooks, { logLevel, reporters })\n\n await hooks.callHook('kubb:lifecycle:start', { version })\n\n // Inside the bootstrap group, so an update notice reads as part of the setup rather than as part\n // of the first config's generation.\n await checkForUpdate(hooks)\n\n if (!quiet) logOutro(`${pluralize(configs.length, 'config')} ready`)\n\n try {\n let anyFailed = false\n for (const config of configs) {\n const effectiveInput = input ?? config.input\n const inputKind = typeof effectiveInput === 'string' ? getInputKind(effectiveInput) : undefined\n const watchPath = inputKind === 'file' || inputKind === 'url' ? (effectiveInput as string) : undefined\n if (watchPath && watch) {\n const watchedPaths = [watchPath]\n // Don't removeAll() between builds, that would also drop logger and lifecycle\n // listeners. Plugin listeners are already disposed by safeBuild's dispose()\n // in its finally block, so re-running generate() on the same hooks emitter is safe.\n const build = async (paths: Array<string>) => {\n const succeeded = await generate({ input, config, hooks, dryRun })\n logStep(styleText('yellow', `Watching for changes in ${paths.join(' and ')}`))\n if (succeeded) {\n logSpacer()\n logTip()\n }\n }\n\n // For a URL input, capture the document before the build: it becomes the watcher's\n // change-detection baseline, so an edit landing before the first poll still rebuilds.\n // When the server is down the baseline stays undefined and the watcher rebuilds on its\n // first successful poll, so recovery with an unchanged document still generates output.\n const initialBody = inputKind === 'url' ? await fetchUrlBody(watchPath) : undefined\n\n // The watchers ignore their startup state, so run the first build here; a failing one keeps watching so the user can fix the input.\n try {\n await build(watchedPaths)\n } catch (buildError) {\n await hooks.callHook('kubb:error', { error: toError(buildError) })\n }\n\n if (inputKind === 'url') {\n startUrlWatcher(watchPath, build, { log: { info: logInfo, error: logError }, initialBody })\n } else {\n await startWatcher(watchedPaths, build, { info: logInfo, error: logError })\n }\n } else {\n try {\n const succeeded = await generate({ input, config, hooks, dryRun })\n if (!succeeded) anyFailed = true\n } catch (configError) {\n await hooks.callHook('kubb:error', { error: toError(configError) })\n anyFailed = true\n }\n }\n }\n\n await hooks.callHook('kubb:lifecycle:end')\n\n // Watch mode prints a tip after each successful build. Regular generate commands need to\n // print one explicitly after the lifecycle group has closed so it stays outside the group.\n if (!quiet && !watch && !anyFailed) {\n logTip()\n }\n\n if (anyFailed) {\n process.exit(1)\n }\n } catch (error) {\n await hooks.callHook('kubb:error', { error: toError(error) })\n process.exit(1)\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,6 @@
1
1
  import "./rolldown-runtime-CRm0XQPb.js";
2
2
  import { t as toError } from "./errors-BQJzaUwP.js";
3
- import { r as sendTelemetry, t as buildTelemetryEvent } from "./Telemetry-CMXOVUKB.js";
4
- import { t as version } from "./package-Ci2fcoOV.js";
3
+ import { n as trackRun } from "./Telemetry-RBcAjNxj.js";
5
4
  import { styleText } from "node:util";
6
5
  import process from "node:process";
7
6
  //#region src/runners/validate/run.ts
@@ -9,23 +8,20 @@ import process from "node:process";
9
8
  * Validates an OpenAPI/Swagger file at `input` using `@kubb/adapter-oas`.
10
9
  * Exits the process with code 1 on validation failure or missing dependency.
11
10
  */
12
- async function run({ input, version }) {
13
- const hrStart = process.hrtime();
14
- const report = (status) => sendTelemetry(buildTelemetryEvent({
11
+ async function run({ input }) {
12
+ const report = trackRun({
15
13
  command: "validate",
16
- kubbVersion: version,
17
- hrStart,
18
- status
19
- }));
14
+ hrStart: process.hrtime()
15
+ });
20
16
  try {
21
17
  const { adapterOas } = await import("@kubb/adapter-oas");
22
18
  const adapter = adapterOas();
23
19
  if (!adapter.validate) throw new Error("The loaded adapter does not support validation.");
24
20
  await adapter.validate(input, { throwOnError: true });
25
- await report("success");
21
+ await report({ status: "success" });
26
22
  console.log("✅ Validation success");
27
23
  } catch (error) {
28
- await report("failed");
24
+ await report({ status: "failed" });
29
25
  if (error instanceof Error && /@kubb\/adapter-oas/.test(error.message)) {
30
26
  console.error(styleText("red", "The @kubb/adapter-oas package is not installed."));
31
27
  console.error("");
@@ -40,17 +36,7 @@ async function run({ input, version }) {
40
36
  process.exit(1);
41
37
  }
42
38
  }
43
- /**
44
- * Loaded on demand by `index.ts`, so `@kubb/adapter-oas` stays out of the process for every other
45
- * command.
46
- */
47
- const runner = async ({ values }) => {
48
- await run({
49
- input: values.input,
50
- version
51
- });
52
- };
53
39
  //#endregion
54
- export { runner };
40
+ export { run };
55
41
 
56
- //# sourceMappingURL=run-BdTwxLCW.js.map
42
+ //# sourceMappingURL=run-D5AeacqK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-D5AeacqK.js","names":[],"sources":["../src/runners/validate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport { trackRun } from '../../Telemetry.ts'\n\ntype ValidateOptions = {\n /**\n * Path or URL to the OpenAPI/Swagger file to validate.\n */\n input: string\n}\n\n/**\n * Validates an OpenAPI/Swagger file at `input` using `@kubb/adapter-oas`.\n * Exits the process with code 1 on validation failure or missing dependency.\n */\nexport async function run({ input }: ValidateOptions): Promise<void> {\n const report = trackRun({ command: 'validate', hrStart: process.hrtime() })\n\n try {\n const { adapterOas } = await import('@kubb/adapter-oas')\n\n const adapter = adapterOas()\n if (!adapter.validate) {\n throw new Error('The loaded adapter does not support validation.')\n }\n\n await adapter.validate(input, { throwOnError: true })\n await report({ status: 'success' })\n\n console.log('✅ Validation success')\n } catch (error) {\n await report({ status: 'failed' })\n if (error instanceof Error && /@kubb\\/adapter-oas/.test(error.message)) {\n console.error(styleText('red', 'The @kubb/adapter-oas package is not installed.'))\n console.error('')\n console.error('Install it with:')\n console.error(styleText('cyan', ' npm install @kubb/adapter-oas'))\n console.error(styleText('cyan', ' # or'))\n console.error(styleText('cyan', ' pnpm install @kubb/adapter-oas'))\n console.error('')\n }\n console.error('❌ Validation failed')\n console.error(toError(error).message)\n\n process.exit(1)\n }\n}\n"],"mappings":";;;;;;;;;;AAgBA,eAAsB,IAAI,EAAE,SAAyC;CACnE,MAAM,SAAS,SAAS;EAAE,SAAS;EAAY,SAAS,QAAQ,OAAO;CAAE,CAAC;CAE1E,IAAI;EACF,MAAM,EAAE,eAAe,MAAM,OAAO;EAEpC,MAAM,UAAU,WAAW;EAC3B,IAAI,CAAC,QAAQ,UACX,MAAM,IAAI,MAAM,iDAAiD;EAGnE,MAAM,QAAQ,SAAS,OAAO,EAAE,cAAc,KAAK,CAAC;EACpD,MAAM,OAAO,EAAE,QAAQ,UAAU,CAAC;EAElC,QAAQ,IAAI,sBAAsB;CACpC,SAAS,OAAO;EACd,MAAM,OAAO,EAAE,QAAQ,SAAS,CAAC;EACjC,IAAI,iBAAiB,SAAS,qBAAqB,KAAK,MAAM,OAAO,GAAG;GACtE,QAAQ,MAAM,UAAU,OAAO,iDAAiD,CAAC;GACjF,QAAQ,MAAM,EAAE;GAChB,QAAQ,MAAM,kBAAkB;GAChC,QAAQ,MAAM,UAAU,QAAQ,iCAAiC,CAAC;GAClE,QAAQ,MAAM,UAAU,QAAQ,QAAQ,CAAC;GACzC,QAAQ,MAAM,UAAU,QAAQ,kCAAkC,CAAC;GACnE,QAAQ,MAAM,EAAE;EAClB;EACA,QAAQ,MAAM,qBAAqB;EACnC,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC,OAAO;EAEpC,QAAQ,KAAK,CAAC;CAChB;AACF"}
@@ -1,37 +1,39 @@
1
- const require_rolldown_runtime = require("./rolldown-runtime-qbf5tadS.cjs");
2
- const require_errors = require("./errors-C-wEou02.cjs");
3
- const require_agent = require("./agent-DiB4CRre.cjs");
4
- const require_Telemetry = require("./Telemetry-DDHXBdEz.cjs");
5
- const require_utils = require("./utils-ClRbJfxu.cjs");
6
- const require_output = require("./output-CVLosNZq.cjs");
7
- const require_package = require("./package-Do9rJ7D3.cjs");
1
+ const require_agent = require("./agent-DElUuYuy.cjs");
2
+ const require_errors = require("./errors-CMbMAwyW.cjs");
3
+ const require_Telemetry = require("./Telemetry-bGdFBaGt.cjs");
4
+ const require_output = require("./output-i3s5c4Xu.cjs");
5
+ const require_config = require("./config-ByfJSj3q.cjs");
8
6
  const require_constants = require("./constants-CdxpgX3_.cjs");
9
7
  let node_util = require("node:util");
10
8
  let node_crypto = require("node:crypto");
11
9
  let node_os = require("node:os");
12
10
  let node_process = require("node:process");
13
- node_process = require_rolldown_runtime.__toESM(node_process, 1);
14
- let node_child_process = require("node:child_process");
11
+ node_process = require_agent.__toESM(node_process, 1);
12
+ let tinyexec = require("tinyexec");
15
13
  let node_fs_promises = require("node:fs/promises");
16
14
  let node_path = require("node:path");
17
- node_path = require_rolldown_runtime.__toESM(node_path, 1);
15
+ node_path = require_agent.__toESM(node_path, 1);
18
16
  let _kubb_core = require("@kubb/core");
19
17
  let _clack_prompts = require("@clack/prompts");
20
- _clack_prompts = require_rolldown_runtime.__toESM(_clack_prompts, 1);
18
+ _clack_prompts = require_agent.__toESM(_clack_prompts, 1);
21
19
  let _kubb_studio = require("@kubb/studio");
22
20
  //#region ../../internals/utils/src/openInBrowser.ts
21
+ const ignore = () => {};
23
22
  /**
24
23
  * Opens a URL or local file in the default browser, unless running in CI.
25
24
  */
26
25
  function openInBrowser(target) {
27
26
  if (require_agent.isCIEnvironment()) return;
28
- if (node_process.default.platform === "win32") (0, node_child_process.execFile)("cmd", [
29
- "/c",
30
- "start",
31
- "",
32
- target
33
- ], () => {});
34
- else (0, node_child_process.execFile)(node_process.default.platform === "darwin" ? "open" : "xdg-open", [target], () => {});
27
+ if (node_process.default.platform === "win32") {
28
+ (0, tinyexec.x)("cmd", [
29
+ "/c",
30
+ "start",
31
+ "",
32
+ target
33
+ ]).then(ignore, ignore);
34
+ return;
35
+ }
36
+ (0, tinyexec.x)(node_process.default.platform === "darwin" ? "open" : "xdg-open", [target]).then(ignore, ignore);
35
37
  }
36
38
  //#endregion
37
39
  //#region ../../internals/utils/src/fs.ts
@@ -140,7 +142,7 @@ async function clearCredentials() {
140
142
  //#region src/runners/studio/run.ts
141
143
  function createStudioOptions(values) {
142
144
  return {
143
- version: require_package.version,
145
+ version: require_Telemetry.version,
144
146
  configPath: values.config,
145
147
  studioUrl: values.url ?? _kubb_studio.defaultStudioUrl,
146
148
  permission: {
@@ -274,7 +276,7 @@ async function resolvePermissions(options, credentials, configPath = require_con
274
276
  * Returns the first config.
275
277
  */
276
278
  async function loadConfigs(options) {
277
- const { configPath, configs } = await require_utils.getConfigs({
279
+ const { configPath, configs } = await require_config.getConfigs({
278
280
  configPath: options.configPath,
279
281
  logLevel: options.logLevel
280
282
  });
@@ -330,7 +332,7 @@ async function connect(options, context = {}) {
330
332
  let reauthenticated = false;
331
333
  try {
332
334
  if (!context.prepared) {
333
- const { getWorkerStatus } = await Promise.resolve().then(() => require("./background-Bbcc2TdN.cjs"));
335
+ const { getWorkerStatus } = await Promise.resolve().then(() => require("./background-R0T_7Szu.cjs"));
334
336
  if ((await getWorkerStatus()).running) throw new Error("This project is running in the background. Run `kubb studio stop` first.");
335
337
  }
336
338
  const prepared = context.prepared ?? await prepareConnection(options, signal);
@@ -347,10 +349,10 @@ async function connect(options, context = {}) {
347
349
  permissions,
348
350
  loadConfig: async () => (await loadConfigs(options)).config,
349
351
  installLogger: async (hooks) => {
350
- await require_utils.setupReporters(hooks, {
352
+ require_config.setupReporters(hooks, {
351
353
  logLevel: _kubb_core.logLevel[options.logLevel ?? "info"],
352
354
  reporters: [_kubb_core.cliReporter],
353
- ...context.onState ? { logger: require_utils.plainLogger } : {}
355
+ ...context.onState ? { logger: require_output.plainLogger } : {}
354
356
  });
355
357
  hooks.hook("studio:connected", () => {
356
358
  if (!hinted && !context.onState && options.logLevel !== "silent") require_output.logBlock((0, node_util.styleText)("dim", "Press Ctrl+C to disconnect"));
@@ -397,50 +399,23 @@ async function connect(options, context = {}) {
397
399
  }
398
400
  }
399
401
  /**
400
- * Reports the paired agent and any saved permissions for the current project.
401
- */
402
- async function status(options) {
403
- const credentials = await readCredentials();
404
- if (!credentials) {
405
- console.log("Not paired. Run `kubb studio login`.");
406
- return;
407
- }
408
- console.log(`Paired with ${credentials.studioUrl} as ${(0, node_util.styleText)("cyan", credentials.agentSlug || credentials.agentId)}`);
409
- if (credentials.studioUrl !== options.studioUrl) console.log((0, node_util.styleText)("yellow", `Connecting to ${options.studioUrl} needs pairing again.`));
410
- const remembered = credentials.projects?.[node_process.default.cwd()];
411
- if (!remembered) {
412
- console.log((0, node_util.styleText)("dim", "No saved permissions for this project. Run `kubb studio` to connect and choose."));
413
- return;
414
- }
415
- console.log((0, node_util.styleText)("dim", "Saved permissions"));
416
- for (const row of formatPermissionRows({
417
- allowRead: remembered.allowRead === true,
418
- allowWrite: remembered.allowWrite === true,
419
- allowConfigEdit: remembered.allowConfigEdit === true,
420
- allowExec: remembered.allowExec === true
421
- })) console.log(row);
422
- }
423
- /**
424
402
  * Runs a Studio command with shared setup and telemetry reporting.
425
403
  */
426
404
  async function run(options, action, { block = false, json = false } = {}) {
427
405
  (0, _kubb_studio.setStorage)((0, _kubb_studio.createFileStorage)(getProjectKubbHome()));
428
- const hrStart = node_process.default.hrtime();
429
- const report = (status) => require_Telemetry.sendTelemetry(require_Telemetry.buildTelemetryEvent({
406
+ const report = require_Telemetry.trackRun({
430
407
  command: "studio",
431
- kubbVersion: options.version,
432
- hrStart,
433
- status
434
- }));
408
+ hrStart: node_process.default.hrtime()
409
+ });
435
410
  try {
436
411
  if (options.logLevel !== "silent" && !json) require_output.logIntro({
437
412
  warning: (0, node_util.styleText)("yellow", "This feature is still under development, use with caution"),
438
413
  block
439
414
  });
440
415
  await action();
441
- await report("success");
416
+ await report({ status: "success" });
442
417
  } catch (error) {
443
- await report("failed");
418
+ await report({ status: "failed" });
444
419
  console.error(require_errors.toError(error).message);
445
420
  node_process.default.exitCode = 1;
446
421
  }
@@ -470,6 +445,12 @@ Object.defineProperty(exports, "exists", {
470
445
  return exists;
471
446
  }
472
447
  });
448
+ Object.defineProperty(exports, "formatPermissionRows", {
449
+ enumerable: true,
450
+ get: function() {
451
+ return formatPermissionRows;
452
+ }
453
+ });
473
454
  Object.defineProperty(exports, "getProjectKubbHome", {
474
455
  enumerable: true,
475
456
  get: function() {
@@ -500,17 +481,17 @@ Object.defineProperty(exports, "read", {
500
481
  return read;
501
482
  }
502
483
  });
503
- Object.defineProperty(exports, "run", {
484
+ Object.defineProperty(exports, "readCredentials", {
504
485
  enumerable: true,
505
486
  get: function() {
506
- return run;
487
+ return readCredentials;
507
488
  }
508
489
  });
509
- Object.defineProperty(exports, "status", {
490
+ Object.defineProperty(exports, "run", {
510
491
  enumerable: true,
511
492
  get: function() {
512
- return status;
493
+ return run;
513
494
  }
514
495
  });
515
496
 
516
- //# sourceMappingURL=run-y6LRyWdS.cjs.map
497
+ //# sourceMappingURL=run-D8Wz_17X.cjs.map