@kubb/cli 5.14.6 → 5.15.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 (186) hide show
  1. package/bin/kubb.js +2 -1
  2. package/dist/{Telemetry-DrnGartf.js → Telemetry-B3edcFoB.js} +12 -86
  3. package/dist/Telemetry-B3edcFoB.js.map +1 -0
  4. package/dist/{Telemetry-B5V_ufmv.cjs → Telemetry-COWGqYmh.cjs} +14 -118
  5. package/dist/Telemetry-COWGqYmh.cjs.map +1 -0
  6. package/dist/{background-CdPT1eaq.cjs → background-B24lIehn.cjs} +5 -6
  7. package/dist/{background-CdPT1eaq.cjs.map → background-B24lIehn.cjs.map} +1 -1
  8. package/dist/{background-C6XHpEo7.js → background-D-7OGjvg.js} +1 -1
  9. package/dist/{background-DlK0by5c.js → background-_dKcGjM7.js} +5 -6
  10. package/dist/{background-DlK0by5c.js.map → background-_dKcGjM7.js.map} +1 -1
  11. package/dist/banner-BdTTDFkG.js +140 -0
  12. package/dist/banner-BdTTDFkG.js.map +1 -0
  13. package/dist/banner-wJFk-L-c.cjs +163 -0
  14. package/dist/banner-wJFk-L-c.cjs.map +1 -0
  15. package/dist/config-BL3HnFhb.js +1 -0
  16. package/dist/config-BWj9jBVj.cjs +62 -0
  17. package/dist/config-BWj9jBVj.cjs.map +1 -0
  18. package/dist/{config-CNqgDSu3.js → config-CQTxXvIG.js} +6 -52
  19. package/dist/config-CQTxXvIG.js.map +1 -0
  20. package/dist/{config-BG_Nr2CZ.cjs → config-CRrmj88c.cjs} +15 -62
  21. package/dist/config-CRrmj88c.cjs.map +1 -0
  22. package/dist/config-Uk3rbZfb.js +49 -0
  23. package/dist/config-Uk3rbZfb.js.map +1 -0
  24. package/dist/configFile-C0DIXNMD.js +993 -0
  25. package/dist/configFile-C0DIXNMD.js.map +1 -0
  26. package/dist/configFile-CoEpHdXG.cjs +1028 -0
  27. package/dist/configFile-CoEpHdXG.cjs.map +1 -0
  28. package/dist/{credentials-C8tjAhTo.js → credentials-B77iJx9H.js} +1 -1
  29. package/dist/{credentials-DDaKqtJn.cjs → credentials-DEsGwcGD.cjs} +3 -4
  30. package/dist/{credentials-DDaKqtJn.cjs.map → credentials-DEsGwcGD.cjs.map} +1 -1
  31. package/dist/{credentials-CZK6zPLv.js → credentials-osgjujE_.js} +3 -4
  32. package/dist/{credentials-CZK6zPLv.js.map → credentials-osgjujE_.js.map} +1 -1
  33. package/dist/env-C3xHRMez.js +1 -0
  34. package/dist/env-eu3XyKqJ.cjs +55 -0
  35. package/dist/env-eu3XyKqJ.cjs.map +1 -0
  36. package/dist/env-rv-VgSGN.js +34 -0
  37. package/dist/env-rv-VgSGN.js.map +1 -0
  38. package/dist/{errors-Cl69p_vI.cjs → errors-BponpdjN.cjs} +3 -4
  39. package/dist/{errors-Cl69p_vI.cjs.map → errors-BponpdjN.cjs.map} +1 -1
  40. package/dist/{errors-DmC83ALX.js → errors-wzqmMpMo.js} +3 -4
  41. package/dist/{errors-DmC83ALX.js.map → errors-wzqmMpMo.js.map} +1 -1
  42. package/dist/index.cjs +37 -2719
  43. package/dist/index.cjs.map +1 -1
  44. package/dist/index.d.cts +0 -2
  45. package/dist/index.d.ts +0 -2
  46. package/dist/index.js +35 -2713
  47. package/dist/index.js.map +1 -1
  48. package/dist/installWithSpinner-DpnpxHq5.js +49 -0
  49. package/dist/installWithSpinner-DpnpxHq5.js.map +1 -0
  50. package/dist/installWithSpinner-ONGfIVUJ.cjs +56 -0
  51. package/dist/installWithSpinner-ONGfIVUJ.cjs.map +1 -0
  52. package/dist/{text-CL6N6yPS.js → intro-9PB8sE8z.js} +8 -52
  53. package/dist/intro-9PB8sE8z.js.map +1 -0
  54. package/dist/{text-DrsG1EDN.cjs → intro-YPaf1Imr.cjs} +12 -80
  55. package/dist/intro-YPaf1Imr.cjs.map +1 -0
  56. package/dist/isCIEnvironment-D6xtAAZ2.js +14 -0
  57. package/dist/isCIEnvironment-D6xtAAZ2.js.map +1 -0
  58. package/dist/isCIEnvironment-DiVOMI5Q.cjs +20 -0
  59. package/dist/isCIEnvironment-DiVOMI5Q.cjs.map +1 -0
  60. package/dist/mascot--q1xjKw1.js +63 -0
  61. package/dist/mascot--q1xjKw1.js.map +1 -0
  62. package/dist/mascot-JSA0j3Q_.cjs +80 -0
  63. package/dist/mascot-JSA0j3Q_.cjs.map +1 -0
  64. package/dist/mcp-CYPOFKnP.cjs +20 -0
  65. package/dist/mcp-CYPOFKnP.cjs.map +1 -0
  66. package/dist/mcp-CxeZR5vb.js +21 -0
  67. package/dist/mcp-CxeZR5vb.js.map +1 -0
  68. package/dist/package-D3Yss9Bb.js +5 -0
  69. package/dist/package-D3Yss9Bb.js.map +1 -0
  70. package/dist/package-aX0q9SZr.cjs +10 -0
  71. package/dist/package-aX0q9SZr.cjs.map +1 -0
  72. package/dist/{registry-DOGpflct.js → registry-B3eYk4LN.js} +7 -67
  73. package/dist/registry-B3eYk4LN.js.map +1 -0
  74. package/dist/{registry-BzBp6aZI.cjs → registry-YE1pFWL-.cjs} +4 -82
  75. package/dist/registry-YE1pFWL-.cjs.map +1 -0
  76. package/dist/{reporters-GzXlc4CK.cjs → reporters-2cgjvXwR.cjs} +32 -40
  77. package/dist/{reporters-GzXlc4CK.cjs.map → reporters-2cgjvXwR.cjs.map} +1 -1
  78. package/dist/{reporters-mYHIUZSx.js → reporters-BM430HdQ.js} +19 -27
  79. package/dist/{reporters-mYHIUZSx.js.map → reporters-BM430HdQ.js.map} +1 -1
  80. package/dist/{rolldown-runtime-CPE0t6oh.cjs → rolldown-runtime-C3-Zg-KD.cjs} +1 -2
  81. package/dist/{rolldown-runtime-CRm0XQPb.js → rolldown-runtime-xo6NMXYd.js} +1 -2
  82. package/dist/run-1H9TGT8v.js +77 -0
  83. package/dist/run-1H9TGT8v.js.map +1 -0
  84. package/dist/run-B4zvF9WY.cjs +233 -0
  85. package/dist/run-B4zvF9WY.cjs.map +1 -0
  86. package/dist/run-BYP_t9dR.cjs +324 -0
  87. package/dist/run-BYP_t9dR.cjs.map +1 -0
  88. package/dist/{run-C8Prej7s.cjs → run-Bb19PlwV.cjs} +44 -37
  89. package/dist/run-Bb19PlwV.cjs.map +1 -0
  90. package/dist/{run-DC_xH5H3.cjs → run-BoO7H8RA.cjs} +49 -41
  91. package/dist/run-BoO7H8RA.cjs.map +1 -0
  92. package/dist/run-BrM7-NSV.js +181 -0
  93. package/dist/run-BrM7-NSV.js.map +1 -0
  94. package/dist/{run-l8IiOR_c.js → run-C0KI-NE3.js} +9 -9
  95. package/dist/{run-l8IiOR_c.js.map → run-C0KI-NE3.js.map} +1 -1
  96. package/dist/run-CCLPt4hr.js +1 -0
  97. package/dist/run-CCsdLz3X.js +385 -0
  98. package/dist/run-CCsdLz3X.js.map +1 -0
  99. package/dist/{run-EJtgdIin.js → run-CbX6tpqB.js} +31 -23
  100. package/dist/run-CbX6tpqB.js.map +1 -0
  101. package/dist/run-CrM4jsix.cjs +80 -0
  102. package/dist/run-CrM4jsix.cjs.map +1 -0
  103. package/dist/run-CvFakE3B.cjs +185 -0
  104. package/dist/run-CvFakE3B.cjs.map +1 -0
  105. package/dist/run-D-nn9-Wq.js +319 -0
  106. package/dist/run-D-nn9-Wq.js.map +1 -0
  107. package/dist/{run-CypFtkVE.cjs → run-D5Z6nfzK.cjs} +5 -6
  108. package/dist/{run-CypFtkVE.cjs.map → run-D5Z6nfzK.cjs.map} +1 -1
  109. package/dist/{run-sjzj0ir-.cjs → run-DCqmf5W1.cjs} +10 -10
  110. package/dist/{run-sjzj0ir-.cjs.map → run-DCqmf5W1.cjs.map} +1 -1
  111. package/dist/{run-j1g5si5R.js → run-DFXhBS64.js} +5 -6
  112. package/dist/{run-j1g5si5R.js.map → run-DFXhBS64.js.map} +1 -1
  113. package/dist/run-DgGZOC_x.cjs +389 -0
  114. package/dist/run-DgGZOC_x.cjs.map +1 -0
  115. package/dist/{run-9fs2T2Je.js → run-KqdudiWQ.js} +26 -20
  116. package/dist/run-KqdudiWQ.js.map +1 -0
  117. package/dist/run-RN_31Q4u.js +228 -0
  118. package/dist/run-RN_31Q4u.js.map +1 -0
  119. package/dist/shared-C0EtrdUm.cjs +123 -0
  120. package/dist/shared-C0EtrdUm.cjs.map +1 -0
  121. package/dist/shared-Ct9stKpp.js +94 -0
  122. package/dist/shared-Ct9stKpp.js.map +1 -0
  123. package/dist/{snapshot-laSRD0z1.cjs → snapshot-D7Ytw8S0.cjs} +13 -14
  124. package/dist/{snapshot-laSRD0z1.cjs.map → snapshot-D7Ytw8S0.cjs.map} +1 -1
  125. package/dist/{snapshot-BJWnL6hE.js → snapshot-n7dJGCWv.js} +10 -11
  126. package/dist/{snapshot-BJWnL6hE.js.map → snapshot-n7dJGCWv.js.map} +1 -1
  127. package/dist/spinner-BZaln7O8.js +160 -0
  128. package/dist/spinner-BZaln7O8.js.map +1 -0
  129. package/dist/spinner-CfB0sIPy.cjs +208 -0
  130. package/dist/spinner-CfB0sIPy.cjs.map +1 -0
  131. package/dist/{status-DFEdbBPu.cjs → status-Bc0_4T41.cjs} +7 -8
  132. package/dist/{status-DFEdbBPu.cjs.map → status-Bc0_4T41.cjs.map} +1 -1
  133. package/dist/{status-BjmXLRm2.js → status-DxSkp1cH.js} +6 -7
  134. package/dist/{status-BjmXLRm2.js.map → status-DxSkp1cH.js.map} +1 -1
  135. package/dist/studio-BpYwgFb0.cjs +218 -0
  136. package/dist/studio-BpYwgFb0.cjs.map +1 -0
  137. package/dist/studio-mw6HaPkr.js +215 -0
  138. package/dist/studio-mw6HaPkr.js.map +1 -0
  139. package/dist/studioWorker.js +4 -5
  140. package/dist/{summary-DDnI70tn.js → summary-CbmQKA8l.js} +5 -6
  141. package/dist/{summary-DDnI70tn.js.map → summary-CbmQKA8l.js.map} +1 -1
  142. package/dist/{summary-1DCwzWEU.cjs → summary-Clvl5Hxs.cjs} +7 -8
  143. package/dist/{summary-1DCwzWEU.cjs.map → summary-Clvl5Hxs.cjs.map} +1 -1
  144. package/dist/table-BlRe9YTZ.cjs +15 -0
  145. package/dist/table-BlRe9YTZ.cjs.map +1 -0
  146. package/dist/table-CR7iZJGo.js +10 -0
  147. package/dist/table-CR7iZJGo.js.map +1 -0
  148. package/dist/text-BmiI4s6N.js +13 -0
  149. package/dist/text-BmiI4s6N.js.map +1 -0
  150. package/dist/text-Ep3AulAS.cjs +24 -0
  151. package/dist/text-Ep3AulAS.cjs.map +1 -0
  152. package/dist/time-3BKoci3G.cjs +82 -0
  153. package/dist/time-3BKoci3G.cjs.map +1 -0
  154. package/dist/time-C-wU7VhC.js +65 -0
  155. package/dist/time-C-wU7VhC.js.map +1 -0
  156. package/dist/utils-BdibacYq.js +244 -0
  157. package/dist/utils-BdibacYq.js.map +1 -0
  158. package/dist/utils-CO89mxRU.cjs +290 -0
  159. package/dist/utils-CO89mxRU.cjs.map +1 -0
  160. package/dist/utils-CbJ6hS_t.js +222 -0
  161. package/dist/utils-CbJ6hS_t.js.map +1 -0
  162. package/dist/utils-CcARPB45.cjs +286 -0
  163. package/dist/utils-CcARPB45.cjs.map +1 -0
  164. package/dist/validate-8ZcWXfMt.js +28 -0
  165. package/dist/validate-8ZcWXfMt.js.map +1 -0
  166. package/dist/validate-CMSeDpGT.cjs +27 -0
  167. package/dist/validate-CMSeDpGT.cjs.map +1 -0
  168. package/package.json +7 -7
  169. package/dist/Telemetry-B5V_ufmv.cjs.map +0 -1
  170. package/dist/Telemetry-DrnGartf.js.map +0 -1
  171. package/dist/config-BG_Nr2CZ.cjs.map +0 -1
  172. package/dist/config-CNqgDSu3.js.map +0 -1
  173. package/dist/config-DWDpFSn1.js +0 -1
  174. package/dist/registry-BzBp6aZI.cjs.map +0 -1
  175. package/dist/registry-DOGpflct.js.map +0 -1
  176. package/dist/run-9fs2T2Je.js.map +0 -1
  177. package/dist/run-C8Prej7s.cjs.map +0 -1
  178. package/dist/run-CXVme-aS.js +0 -1
  179. package/dist/run-DC_xH5H3.cjs.map +0 -1
  180. package/dist/run-EJtgdIin.js.map +0 -1
  181. package/dist/text-CL6N6yPS.js.map +0 -1
  182. package/dist/text-DrsG1EDN.cjs.map +0 -1
  183. package/dist/utils-C3vTpUje.cjs +0 -645
  184. package/dist/utils-C3vTpUje.cjs.map +0 -1
  185. package/dist/utils-CIc8YFtr.js +0 -536
  186. package/dist/utils-CIc8YFtr.js.map +0 -1
@@ -0,0 +1,286 @@
1
+ const require_rolldown_runtime = require("./rolldown-runtime-C3-Zg-KD.cjs");
2
+ const require_spinner = require("./spinner-CfB0sIPy.cjs");
3
+ let node_util = require("node:util");
4
+ let node_process = require("node:process");
5
+ node_process = require_rolldown_runtime.__toESM(node_process, 1);
6
+ let node_fs_promises = require("node:fs/promises");
7
+ let node_path = require("node:path");
8
+ // ../../internals/utils/src/promise.ts
9
+ /**
10
+ * Runs `run` over every item with at most `limit` in flight. Workers share one iterator, so each
11
+ * takes the next item the moment it frees up instead of waiting for a batch to drain.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * await inParallel({ items: files, limit: 50, run: (file) => storage.writeItem(file.path, file.source) })
16
+ * ```
17
+ */
18
+ async function inParallel({ items, limit, run }) {
19
+ const queue = items.entries();
20
+ const worker = async () => {
21
+ for (const [index, item] of queue) await run(item, index);
22
+ };
23
+ await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => worker()));
24
+ }
25
+ // src/runners/generate/utils.ts
26
+ /** Glob pattern for paths the file watcher ignores. */
27
+ const WATCHER_IGNORED_PATHS = "**/{.git,node_modules}/**";
28
+ /**
29
+ * Quiet window in milliseconds that collapses a burst of watcher events (an editor save emits several) into one rebuild.
30
+ * It outlasts chokidar's 100 ms atomic-save window, which holds back the event of a write-then-rename save.
31
+ */
32
+ const WATCHER_DEBOUNCE_MS = 250;
33
+ /** `14:02:11 petStore.yaml changed`, the line a watcher prints when its input changes. */
34
+ function formatChange({ target, removed = false, now = /* @__PURE__ */ new Date() }) {
35
+ return `${(0, node_util.styleText)("dim", now.toTimeString().slice(0, 8))} ${(0, node_util.styleText)("bold", target)} ${removed ? "removed" : "changed"}`;
36
+ }
37
+ /**
38
+ * Starts a file watcher on the given paths and calls `cb` on any change.
39
+ * Ignores `.git` and `node_modules` directories. Event bursts (an editor save emits several)
40
+ * are debounced into one call. `cb` must never reject: its result is not awaited, so the caller
41
+ * serializes and reports its own builds. Resolves to a function that stops watching.
42
+ */
43
+ async function startWatcher(path, cb, log = {
44
+ info: console.log,
45
+ error: console.log
46
+ }) {
47
+ const { watch } = await import("chokidar");
48
+ const watcher = watch(path, {
49
+ ignorePermissionErrors: true,
50
+ ignored: WATCHER_IGNORED_PATHS,
51
+ ignoreInitial: true
52
+ });
53
+ for (const signal of ["SIGINT", "SIGTERM"]) node_process.default.once(signal, () => void watcher.close());
54
+ let debounceTimer = null;
55
+ watcher.on("all", (type, file) => {
56
+ log.info(formatChange({
57
+ target: (0, node_path.relative)(node_process.default.cwd(), file),
58
+ removed: type === "unlink"
59
+ }));
60
+ if (debounceTimer) clearTimeout(debounceTimer);
61
+ debounceTimer = setTimeout(() => {
62
+ debounceTimer = null;
63
+ cb(path);
64
+ }, WATCHER_DEBOUNCE_MS);
65
+ });
66
+ return async () => {
67
+ if (debounceTimer) clearTimeout(debounceTimer);
68
+ await watcher.close();
69
+ };
70
+ }
71
+ function createSnapshot() {
72
+ return {
73
+ schemas: /* @__PURE__ */ new Set(),
74
+ operations: /* @__PURE__ */ new Set()
75
+ };
76
+ }
77
+ /**
78
+ * Collects a {@link BuildSnapshot} from the hooks while a build runs. `take` hands back the finished
79
+ * build's snapshot and starts the next one.
80
+ */
81
+ function trackBuild(hooks) {
82
+ let current = createSnapshot();
83
+ hooks.hook("kubb:generate:schema", (node) => {
84
+ if (node.name) current.schemas.add(node.name);
85
+ });
86
+ hooks.hook("kubb:generate:operation", (node) => {
87
+ current.operations.add(node.operationId);
88
+ });
89
+ return { take() {
90
+ const snapshot = current;
91
+ current = createSnapshot();
92
+ return snapshot;
93
+ } };
94
+ }
95
+ function diffNames(previous, next) {
96
+ return {
97
+ added: [...next].filter((name) => !previous.has(name)).length,
98
+ removed: [...previous].filter((name) => !next.has(name)).length
99
+ };
100
+ }
101
+ /**
102
+ * Compares two {@link BuildSnapshot}s by name.
103
+ */
104
+ function diffBuilds(previous, next) {
105
+ return {
106
+ schemas: diffNames(previous.schemas, next.schemas),
107
+ operations: diffNames(previous.operations, next.operations)
108
+ };
109
+ }
110
+ /**
111
+ * Compares file contents or fingerprints by path.
112
+ */
113
+ function diffFiles(previous, next) {
114
+ const files = [];
115
+ let unchanged = 0;
116
+ for (const [path, fingerprint] of next) {
117
+ const before = previous.get(path);
118
+ if (before === fingerprint) unchanged++;
119
+ else files.push({
120
+ status: before === void 0 ? "A" : "M",
121
+ path
122
+ });
123
+ }
124
+ for (const path of previous.keys()) if (!next.has(path)) files.push({
125
+ status: "D",
126
+ path
127
+ });
128
+ return {
129
+ files,
130
+ unchanged
131
+ };
132
+ }
133
+ function countLineChanges(before, after) {
134
+ const remaining = /* @__PURE__ */ new Map();
135
+ for (const line of before ? before.split("\n") : []) remaining.set(line, (remaining.get(line) ?? 0) + 1);
136
+ let added = 0;
137
+ for (const line of after ? after.split("\n") : []) {
138
+ const count = remaining.get(line) ?? 0;
139
+ if (count > 0) remaining.set(line, count - 1);
140
+ else added++;
141
+ }
142
+ const removed = [...remaining.values()].reduce((sum, count) => sum + count, 0);
143
+ return {
144
+ added,
145
+ removed
146
+ };
147
+ }
148
+ /**
149
+ * Reads the output before generation, so cleaning the directory cannot erase the diff baseline.
150
+ * A missing directory or an unreadable file is skipped.
151
+ */
152
+ async function readOutputFiles(outputPath) {
153
+ const entries = await (0, node_fs_promises.readdir)(outputPath, {
154
+ recursive: true,
155
+ withFileTypes: true
156
+ }).catch(() => []);
157
+ const files = /* @__PURE__ */ new Map();
158
+ await inParallel({
159
+ items: entries.filter((entry) => entry.isFile()).map((entry) => (0, node_path.join)(entry.parentPath, entry.name)),
160
+ limit: 50,
161
+ run: async (filePath) => {
162
+ const source = await require_spinner.read(filePath).catch(() => null);
163
+ if (source !== null) files.set(filePath, source);
164
+ }
165
+ });
166
+ return files;
167
+ }
168
+ /**
169
+ * Compares generated output with the files captured before generation. The manifest recognizes
170
+ * output rewritten by a formatter, and `clean` includes files the run would delete.
171
+ */
172
+ async function diffOutput({ storage, paths, clean, manifest, previousFiles }) {
173
+ const generated = new Set(paths);
174
+ const changes = [];
175
+ let unchanged = 0;
176
+ await inParallel({
177
+ items: paths,
178
+ limit: 50,
179
+ run: async (filePath, index) => {
180
+ const next = await storage.readItem(filePath);
181
+ if (next === null) return;
182
+ const previous = previousFiles.get(filePath) ?? null;
183
+ if (previous !== null && (require_spinner.matchesStored({
184
+ stored: previous,
185
+ source: next
186
+ }) || manifest?.isUpToDate({
187
+ key: filePath,
188
+ source: next,
189
+ disk: previous
190
+ }))) {
191
+ unchanged++;
192
+ return;
193
+ }
194
+ changes[index] = {
195
+ status: previous === null ? "A" : "M",
196
+ path: filePath,
197
+ ...countLineChanges(previous?.trim() ?? "", previous === null ? next.trimEnd() : next.trim())
198
+ };
199
+ }
200
+ });
201
+ const files = changes.filter((file) => file !== void 0);
202
+ if (clean) {
203
+ for (const [filePath, source] of previousFiles) if (!generated.has(filePath)) files.push({
204
+ status: "D",
205
+ path: filePath,
206
+ ...countLineChanges(source.trimEnd(), "")
207
+ });
208
+ }
209
+ return {
210
+ files,
211
+ unchanged
212
+ };
213
+ }
214
+ /**
215
+ * Reads `r` (rebuild) and `q` (quit) from an interactive stdin in raw mode, and keeps ctrl+c
216
+ * working. Returns `undefined` when stdin is not a TTY. Otherwise returns `arm`, which turns raw
217
+ * mode back on: a spinner restores the terminal when it stops, so call it after each build. Raw mode
218
+ * is restored on exit.
219
+ */
220
+ function listenForKeys({ rebuild, quit, input = node_process.default.stdin }) {
221
+ if (!input.isTTY) return void 0;
222
+ const arm = () => {
223
+ input.setRawMode(true);
224
+ input.resume();
225
+ };
226
+ input.setEncoding("utf8");
227
+ input.on("data", (data) => {
228
+ const key = data.trim();
229
+ if (key === "r") {
230
+ rebuild();
231
+ return;
232
+ }
233
+ if (key === "q" || data === "") {
234
+ input.setRawMode(false);
235
+ input.pause();
236
+ quit(key === "q" ? 0 : 130);
237
+ }
238
+ });
239
+ node_process.default.once("exit", () => input.setRawMode(false));
240
+ arm();
241
+ return arm;
242
+ }
243
+ Object.defineProperty(exports, "diffBuilds", {
244
+ enumerable: true,
245
+ get: function() {
246
+ return diffBuilds;
247
+ }
248
+ });
249
+ Object.defineProperty(exports, "diffFiles", {
250
+ enumerable: true,
251
+ get: function() {
252
+ return diffFiles;
253
+ }
254
+ });
255
+ Object.defineProperty(exports, "diffOutput", {
256
+ enumerable: true,
257
+ get: function() {
258
+ return diffOutput;
259
+ }
260
+ });
261
+ Object.defineProperty(exports, "listenForKeys", {
262
+ enumerable: true,
263
+ get: function() {
264
+ return listenForKeys;
265
+ }
266
+ });
267
+ Object.defineProperty(exports, "readOutputFiles", {
268
+ enumerable: true,
269
+ get: function() {
270
+ return readOutputFiles;
271
+ }
272
+ });
273
+ Object.defineProperty(exports, "startWatcher", {
274
+ enumerable: true,
275
+ get: function() {
276
+ return startWatcher;
277
+ }
278
+ });
279
+ Object.defineProperty(exports, "trackBuild", {
280
+ enumerable: true,
281
+ get: function() {
282
+ return trackBuild;
283
+ }
284
+ });
285
+
286
+ //# sourceMappingURL=utils-CcARPB45.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-CcARPB45.cjs","names":["styleText","relative","process","readdir","join","read","matchesStored"],"sources":["../../../internals/utils/src/promise.ts","../src/runners/generate/utils.ts"],"sourcesContent":["/** A value that may already be resolved or still pending.\n *\n * @example\n * ```ts\n * function load(id: string): PossiblePromise<string> {\n * return cache.get(id) ?? fetchRemote(id)\n * }\n * ```\n */\nexport type PossiblePromise<T> = Promise<T> | T\n\ntype Store<TKey, TValue> = {\n has(key: TKey): boolean\n get(key: TKey): TValue | undefined\n set(key: TKey, value: TValue): unknown\n}\n\n/**\n * Wraps `factory` with a keyed cache backed by the provided store.\n *\n * Pass a `WeakMap` for object keys (results are GC-eligible when the key is\n * collected) or a `Map` for primitive keys. For multi-argument functions,\n * nest two `memoize` calls — the outer keyed by the first argument, the\n * inner (created once per outer miss) keyed by the second.\n *\n * Because the cache is owned by the caller, it can be shared, inspected, or\n * cleared independently of the memoized function.\n *\n * @example Single WeakMap key\n * ```ts\n * const cache = new WeakMap<SchemaNode, Set<string>>()\n * const getRefs = memoize(cache, (node) => collectRefs(node))\n * ```\n *\n * @example Single Map key (primitive)\n * ```ts\n * const cache = new Map<string, Resolver>()\n * const getResolver = memoize(cache, (name) => buildResolver(name))\n * ```\n *\n * @example Two-level (object + primitive)\n * ```ts\n * const outer = new WeakMap<Params[], Map<string, Params[]>>()\n * const fn = memoize(outer, (params) => memoize(new Map(), (key) => transform(params, key)))\n * fn(params)('camelcase')\n * ```\n */\nexport function memoize<TKey, TValue>(store: Store<TKey, TValue>, factory: (key: TKey) => TValue): (key: TKey) => TValue {\n return (key: TKey): TValue => {\n if (store.has(key)) return store.get(key)!\n const value = factory(key)\n store.set(key, value)\n return value\n }\n}\n\ntype ParallelOptions<TItem> = {\n /**\n * Items to work through, handed out in order.\n */\n items: ReadonlyArray<TItem>\n /**\n * How many items may be in flight at once.\n */\n limit: number\n /**\n * Runs once per item, with the item's position so a caller can report progress.\n */\n run(item: TItem, index: number): Promise<void>\n}\n\n/**\n * Runs `run` over every item with at most `limit` in flight. Workers share one iterator, so each\n * takes the next item the moment it frees up instead of waiting for a batch to drain.\n *\n * @example\n * ```ts\n * await inParallel({ items: files, limit: 50, run: (file) => storage.writeItem(file.path, file.source) })\n * ```\n */\nexport async function inParallel<TItem>({ items, limit, run }: ParallelOptions<TItem>): Promise<void> {\n const queue = items.entries()\n\n const worker = async (): Promise<void> => {\n for (const [index, item] of queue) await run(item, index)\n }\n\n await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => worker()))\n}\n","import { readdir } from 'node:fs/promises'\nimport { join, relative } from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport { inParallel, matchesStored, read } from '@internals/utils'\nimport type { Hookable, KubbHooks, OutputManifest, Storage } from '@kubb/core'\n\n/** Glob pattern for paths the file watcher ignores. */\nconst WATCHER_IGNORED_PATHS = '**/{.git,node_modules}/**' as const\n\n/**\n * Quiet window in milliseconds that collapses a burst of watcher events (an editor save emits several) into one rebuild.\n * It outlasts chokidar's 100 ms atomic-save window, which holds back the event of a write-then-rename save.\n */\nconst WATCHER_DEBOUNCE_MS = 250\n\n/** `14:02:11 petStore.yaml changed`, the line a watcher prints when its input changes. */\nexport function formatChange({ target, removed = false, now = new Date() }: { target: string; removed?: boolean; now?: Date }): string {\n return `${styleText('dim', now.toTimeString().slice(0, 8))} ${styleText('bold', target)} ${removed ? 'removed' : 'changed'}`\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 call. `cb` must never reject: its result is not awaited, so the caller\n * serializes and reports its own builds. 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 for (const signal of ['SIGINT', 'SIGTERM'] as const) {\n process.once(signal, () => void watcher.close())\n }\n\n let debounceTimer: ReturnType<typeof setTimeout> | null = null\n\n watcher.on('all', (type, file) => {\n log.info(formatChange({ target: relative(process.cwd(), file), removed: type === 'unlink' }))\n if (debounceTimer) clearTimeout(debounceTimer)\n debounceTimer = setTimeout(() => {\n debounceTimer = null\n void cb(path)\n }, WATCHER_DEBOUNCE_MS)\n })\n\n return async () => {\n if (debounceTimer) clearTimeout(debounceTimer)\n await watcher.close()\n }\n}\n\n/**\n * What one build produced: the schema and operation names the plugins generated.\n */\nexport type BuildSnapshot = {\n schemas: Set<string>\n operations: Set<string>\n}\n\nfunction createSnapshot(): BuildSnapshot {\n return { schemas: new Set(), operations: new Set() }\n}\n\n/**\n * Collects a {@link BuildSnapshot} from the hooks while a build runs. `take` hands back the finished\n * build's snapshot and starts the next one.\n */\nexport function trackBuild(hooks: Hookable<KubbHooks>): { take(): BuildSnapshot } {\n let current = createSnapshot()\n\n hooks.hook('kubb:generate:schema', (node) => {\n if (node.name) current.schemas.add(node.name)\n })\n hooks.hook('kubb:generate:operation', (node) => {\n current.operations.add(node.operationId)\n })\n\n return {\n take() {\n const snapshot = current\n current = createSnapshot()\n return snapshot\n },\n }\n}\n\ntype NameChange = { added: number; removed: number }\n\n/**\n * How a rebuild differs from the build before it: the spec's added and removed schemas and operations.\n */\nexport type BuildDiff = {\n schemas: NameChange\n operations: NameChange\n}\n\nfunction diffNames(previous: Set<string>, next: Set<string>): NameChange {\n return { added: [...next].filter((name) => !previous.has(name)).length, removed: [...previous].filter((name) => !next.has(name)).length }\n}\n\n/**\n * Compares two {@link BuildSnapshot}s by name.\n */\nexport function diffBuilds(previous: BuildSnapshot, next: BuildSnapshot): BuildDiff {\n return {\n schemas: diffNames(previous.schemas, next.schemas),\n operations: diffNames(previous.operations, next.operations),\n }\n}\n\n/**\n * Compares file contents or fingerprints by path.\n */\nexport function diffFiles(previous: ReadonlyMap<string, string>, next: ReadonlyMap<string, string>): { files: Array<FileChange>; unchanged: number } {\n const files: Array<FileChange> = []\n let unchanged = 0\n for (const [path, fingerprint] of next) {\n const before = previous.get(path)\n if (before === fingerprint) unchanged++\n else files.push({ status: before === undefined ? 'A' : 'M', path })\n }\n for (const path of previous.keys()) {\n if (!next.has(path)) files.push({ status: 'D', path })\n }\n\n return { files, unchanged }\n}\n\n/** A changed file with how many lines it gains and loses, counted as a multiset, which is cheap and close enough for a plan. */\nexport type FileChange = { status: 'A' | 'M' | 'D'; path: string; added?: number; removed?: number }\n\nfunction countLineChanges(before: string, after: string): { added: number; removed: number } {\n const remaining = new Map<string, number>()\n for (const line of before ? before.split('\\n') : []) remaining.set(line, (remaining.get(line) ?? 0) + 1)\n let added = 0\n for (const line of after ? after.split('\\n') : []) {\n const count = remaining.get(line) ?? 0\n if (count > 0) remaining.set(line, count - 1)\n else added++\n }\n const removed = [...remaining.values()].reduce((sum, count) => sum + count, 0)\n return { added, removed }\n}\n\n/**\n * Reads the output before generation, so cleaning the directory cannot erase the diff baseline.\n * A missing directory or an unreadable file is skipped.\n */\nexport async function readOutputFiles(outputPath: string): Promise<Map<string, string>> {\n const entries = await readdir(outputPath, { recursive: true, withFileTypes: true }).catch(() => [])\n const files = new Map<string, string>()\n await inParallel({\n items: entries.filter((entry) => entry.isFile()).map((entry) => join(entry.parentPath, entry.name)),\n limit: 50,\n run: async (filePath) => {\n const source = await read(filePath).catch(() => null)\n if (source !== null) files.set(filePath, source)\n },\n })\n return files\n}\n\n/**\n * Compares generated output with the files captured before generation. The manifest recognizes\n * output rewritten by a formatter, and `clean` includes files the run would delete.\n */\nexport async function diffOutput({\n storage,\n paths,\n clean,\n manifest,\n previousFiles,\n}: {\n storage: Storage\n paths: ReadonlyArray<string>\n clean: boolean\n manifest?: Pick<OutputManifest, 'isUpToDate'>\n /**\n * The output captured before a real run, including files removed by cleaning.\n */\n previousFiles: ReadonlyMap<string, string>\n}): Promise<{ files: Array<FileChange>; unchanged: number }> {\n const generated = new Set(paths)\n const changes: Array<FileChange | undefined> = []\n let unchanged = 0\n await inParallel({\n items: paths,\n limit: 50,\n run: async (filePath, index) => {\n const next = await storage.readItem(filePath)\n if (next === null) return\n const previous = previousFiles.get(filePath) ?? null\n if (previous !== null && (matchesStored({ stored: previous, source: next }) || manifest?.isUpToDate({ key: filePath, source: next, disk: previous }))) {\n unchanged++\n return\n }\n changes[index] = {\n status: previous === null ? 'A' : 'M',\n path: filePath,\n ...countLineChanges(previous?.trim() ?? '', previous === null ? next.trimEnd() : next.trim()),\n }\n },\n })\n const files = changes.filter((file) => file !== undefined)\n if (clean) {\n for (const [filePath, source] of previousFiles) {\n if (!generated.has(filePath)) files.push({ status: 'D', path: filePath, ...countLineChanges(source.trimEnd(), '') })\n }\n }\n\n return { files, unchanged }\n}\n\ntype KeyInput = Pick<NodeJS.ReadStream, 'isTTY' | 'setRawMode' | 'resume' | 'pause' | 'setEncoding' | 'on'>\n\ntype KeyOptions = {\n rebuild: () => void\n /**\n * Ends the process with this exit code: `0` for `q`, `130` for ctrl+c, which raw mode turns into a key.\n */\n quit: (code: number) => void\n input?: KeyInput\n}\n\n/**\n * Reads `r` (rebuild) and `q` (quit) from an interactive stdin in raw mode, and keeps ctrl+c\n * working. Returns `undefined` when stdin is not a TTY. Otherwise returns `arm`, which turns raw\n * mode back on: a spinner restores the terminal when it stops, so call it after each build. Raw mode\n * is restored on exit.\n */\nexport function listenForKeys({ rebuild, quit, input = process.stdin }: KeyOptions): (() => void) | undefined {\n if (!input.isTTY) return undefined\n\n const arm = () => {\n input.setRawMode(true)\n input.resume()\n }\n input.setEncoding('utf8')\n input.on('data', (data: string) => {\n const key = data.trim()\n if (key === 'r') {\n rebuild()\n return\n }\n if (key === 'q' || data === '\\u0003') {\n input.setRawMode(false)\n input.pause()\n quit(key === 'q' ? 0 : 130)\n }\n })\n process.once('exit', () => input.setRawMode(false))\n arm()\n\n return arm\n}\n"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import "./rolldown-runtime-xo6NMXYd.js";
2
+ import { t as configArg } from "./shared-Ct9stKpp.js";
3
+ import { define } from "gunshi";
4
+ // src/commands/validate.ts
5
+ /** The runner is imported when the command runs, so listing `kubb --help` never loads `@kubb/adapter-oas`. */
6
+ const command = define({
7
+ name: "validate",
8
+ description: "Check a specification with the configured adapter before generating.",
9
+ examples: ["kubb validate ./openapi.yaml", "kubb validate https://petstore3.swagger.io/api/v3/openapi.json"].join("\n"),
10
+ args: {
11
+ ...configArg,
12
+ input: {
13
+ type: "positional",
14
+ description: "Path or URL to the specification to validate",
15
+ required: true
16
+ }
17
+ },
18
+ async run({ values }) {
19
+ const { run } = await import("./run-C0KI-NE3.js");
20
+ await run({
21
+ input: values.input,
22
+ configPath: values.config
23
+ });
24
+ }
25
+ });
26
+ export { command };
27
+
28
+ //# sourceMappingURL=validate-8ZcWXfMt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-8ZcWXfMt.js","names":[],"sources":["../src/commands/validate.ts"],"sourcesContent":["import { define } from 'gunshi'\nimport { configArg } from './shared.ts'\n\n/** The runner is imported when the command runs, so listing `kubb --help` never loads `@kubb/adapter-oas`. */\nexport const command = define({\n name: 'validate',\n description: 'Check a specification with the configured adapter before generating.',\n examples: ['kubb validate ./openapi.yaml', 'kubb validate https://petstore3.swagger.io/api/v3/openapi.json'].join('\\n'),\n args: {\n ...configArg,\n input: {\n type: 'positional',\n description: 'Path or URL to the specification to validate',\n required: true,\n },\n },\n async run({ values }) {\n const { run } = await import('../runners/validate/run.ts')\n await run({ input: values.input, configPath: values.config })\n },\n})\n"],"mappings":";;;;;AAIA,MAAa,UAAU,OAAO;CAC5B,MAAM;CACN,aAAa;CACb,UAAU,CAAC,gCAAgC,gEAAgE,CAAC,CAAC,KAAK,IAAI;CACtH,MAAM;EACJ,GAAG;EACH,OAAO;GACL,MAAM;GACN,aAAa;GACb,UAAU;EACZ;CACF;CACA,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,QAAQ,MAAM,OAAO;EAC7B,MAAM,IAAI;GAAE,OAAO,OAAO;GAAO,YAAY,OAAO;EAAO,CAAC;CAC9D;AACF,CAAC"}
@@ -0,0 +1,27 @@
1
+ require("./rolldown-runtime-C3-Zg-KD.cjs");
2
+ const require_shared = require("./shared-C0EtrdUm.cjs");
3
+ // src/commands/validate.ts
4
+ /** The runner is imported when the command runs, so listing `kubb --help` never loads `@kubb/adapter-oas`. */
5
+ const command = (0, require("gunshi").define)({
6
+ name: "validate",
7
+ description: "Check a specification with the configured adapter before generating.",
8
+ examples: ["kubb validate ./openapi.yaml", "kubb validate https://petstore3.swagger.io/api/v3/openapi.json"].join("\n"),
9
+ args: {
10
+ ...require_shared.configArg,
11
+ input: {
12
+ type: "positional",
13
+ description: "Path or URL to the specification to validate",
14
+ required: true
15
+ }
16
+ },
17
+ async run({ values }) {
18
+ const { run } = await Promise.resolve().then(() => require("./run-DCqmf5W1.cjs"));
19
+ await run({
20
+ input: values.input,
21
+ configPath: values.config
22
+ });
23
+ }
24
+ });
25
+ exports.command = command;
26
+
27
+ //# sourceMappingURL=validate-CMSeDpGT.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-CMSeDpGT.cjs","names":["define","configArg"],"sources":["../src/commands/validate.ts"],"sourcesContent":["import { define } from 'gunshi'\nimport { configArg } from './shared.ts'\n\n/** The runner is imported when the command runs, so listing `kubb --help` never loads `@kubb/adapter-oas`. */\nexport const command = define({\n name: 'validate',\n description: 'Check a specification with the configured adapter before generating.',\n examples: ['kubb validate ./openapi.yaml', 'kubb validate https://petstore3.swagger.io/api/v3/openapi.json'].join('\\n'),\n args: {\n ...configArg,\n input: {\n type: 'positional',\n description: 'Path or URL to the specification to validate',\n required: true,\n },\n },\n async run({ values }) {\n const { run } = await import('../runners/validate/run.ts')\n await run({ input: values.input, configPath: values.config })\n },\n})\n"],"mappings":";;;;AAIA,MAAa,WAAA,G,gBAAUA,CAAAA,CAAAA,OAAAA,CAAO;CAC5B,MAAM;CACN,aAAa;CACb,UAAU,CAAC,gCAAgC,gEAAgE,CAAC,CAAC,KAAK,IAAI;CACtH,MAAM;EACJ,GAAGC,eAAAA;EACH,OAAO;GACL,MAAM;GACN,aAAa;GACb,UAAU;EACZ;CACF;CACA,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,QAAQ,MAAA,QAAA,QAAA,CAAA,CAAA,WAAA,QAAM,oBAAA,CAAA;EACtB,MAAM,IAAI;GAAE,OAAO,OAAO;GAAO,YAAY,OAAO;EAAO,CAAC;CAC9D;AACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/cli",
3
- "version": "5.14.6",
3
+ "version": "5.15.0",
4
4
  "description": "Official CLI for Kubb. Run kubb generate, kubb init, kubb validate, kubb studio, and kubb mcp to manage the full code generation lifecycle.",
5
5
  "keywords": [
6
6
  "cli",
@@ -68,7 +68,7 @@
68
68
  "dependencies": {
69
69
  "@clack/prompts": "^1.8.1",
70
70
  "@gunshi/plugin-dryrun": "^0.37.3",
71
- "@kubb/core": "5.14.6",
71
+ "@kubb/core": "5.15.0",
72
72
  "chokidar": "^6.0.0",
73
73
  "gunshi": "^0.37.3",
74
74
  "jiti": "^2.7.0",
@@ -79,13 +79,13 @@
79
79
  "devDependencies": {
80
80
  "@internals/shared": "0.0.1",
81
81
  "@internals/utils": "0.0.1",
82
- "@kubb/adapter-oas": "5.14.6",
83
- "@kubb/studio": "5.14.6"
82
+ "@kubb/adapter-oas": "5.15.0",
83
+ "@kubb/studio": "5.15.0"
84
84
  },
85
85
  "peerDependencies": {
86
- "@kubb/adapter-oas": "5.14.6",
87
- "@kubb/mcp": "5.14.6",
88
- "@kubb/studio": "5.14.6"
86
+ "@kubb/adapter-oas": "5.15.0",
87
+ "@kubb/mcp": "5.15.0",
88
+ "@kubb/studio": "5.15.0"
89
89
  },
90
90
  "peerDependenciesMeta": {
91
91
  "@kubb/adapter-oas": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"Telemetry-B5V_ufmv.cjs","names":["process","process","randomBytes","getAgentProfile","os"],"sources":["../../../internals/utils/src/isCIEnvironment.ts","../../../internals/utils/src/runtime.ts","../../../internals/utils/src/time.ts","../package.json","../src/Telemetry.ts"],"sourcesContent":["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 +0,0 @@
1
- {"version":3,"file":"Telemetry-DrnGartf.js","names":["process","process"],"sources":["../../../internals/utils/src/isCIEnvironment.ts","../../../internals/utils/src/runtime.ts","../../../internals/utils/src/time.ts","../package.json","../src/Telemetry.ts"],"sourcesContent":["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 +0,0 @@
1
- {"version":3,"file":"config-BG_Nr2CZ.cjs","names":["jiti","createJiti","readFile","join","process","resolve","dirname","existsSync","basename","resolve","Diagnostics","process","toError"],"sources":["../../../internals/shared/src/constants.ts","../../../internals/shared/src/loader.ts","../../../internals/shared/src/config.ts","../src/config.ts"],"sourcesContent":["export const KUBB_CONFIG_FILENAME = 'kubb.config.ts' as const\n\n/** File extensions a Kubb config file may use. */\nexport const CONFIG_EXTENSIONS = ['.ts', '.mts', '.cts', '.js', '.mjs', '.cjs'] as const\n\nexport const KUBB_PACKAGE_NAME = 'kubb' as const\n\n/**\n * Extensions `kubb` ships at its own version, so they count as installed without being a direct\n * dependency. `constants.test.ts` checks it against the `kubb` package's dependencies.\n */\nexport const BUNDLED_PACKAGES: ReadonlyArray<string> = ['@kubb/adapter-oas', '@kubb/parser-ts', '@kubb/parser-md', '@kubb/plugin-barrel']\n\nexport const initDefaults = {\n inputPath: './openapi.yaml',\n outputPath: './src/gen',\n plugins: ['plugin-ts'],\n} as const\n","import { readFile } from 'node:fs/promises'\nimport { createJiti } from 'jiti'\n\n/**\n * jiti options for loading Kubb config modules: the automatic JSX runtime pointed at\n * `@kubb/renderer-jsx`, and `moduleCache` off so a re-load re-evaluates the file.\n */\nconst JITI_OPTIONS = {\n jsx: { runtime: 'automatic', importSource: '@kubb/renderer-jsx' },\n moduleCache: false,\n} satisfies Parameters<typeof createJiti>[1]\n\n/**\n * Plain JavaScript files. jiti hands these to Node's native `import()`, whose module cache never\n * lets go of a file, so `moduleCache: false` alone would keep returning the first version of it.\n */\nconst JAVASCRIPT_EXTENSION = /\\.[cm]?jsx?$/\n\n/**\n * Per-call options for {@link loadModule}.\n */\ntype LoadModuleOptions = {\n /**\n * Return the module's default export instead of the full namespace.\n */\n default?: boolean\n}\n\nconst jiti = createJiti(import.meta.url, JITI_OPTIONS)\n\n/**\n * Loads a Kubb TypeScript or JavaScript config module via jiti.\n *\n * jiti transpiles TypeScript and the `@kubb/renderer-jsx` JSX runtime on the fly. Every load\n * re-evaluates the file, so a config edited on disk is picked up by the next load.\n *\n * @example\n * ```ts\n * const config = await loadModule('/abs/kubb.config.ts', { default: true })\n * ```\n */\nexport async function loadModule<T = unknown>(filePath: string, options?: LoadModuleOptions): Promise<T> {\n if (!JAVASCRIPT_EXTENSION.test(filePath)) {\n return (options?.default ? jiti.import(filePath, { default: true }) : jiti.import(filePath)) as Promise<T>\n }\n\n // Transpiled through jiti instead, so every load re-evaluates the file as it is on disk now.\n // A TypeScript file it imports reloads too. A plain JavaScript file it imports still goes\n // through Node's `import()` and stays cached until the process restarts.\n const mod = (await jiti.evalModule(await readFile(filePath, 'utf8'), { filename: filePath, async: true, forceTranspile: true })) as\n | { default?: unknown }\n | undefined\n return (options?.default ? (mod?.default ?? mod) : mod) as T\n}\n","import { existsSync } from 'node:fs'\nimport { basename, dirname, join, resolve } from 'node:path'\nimport process from 'node:process'\nimport { CONFIG_EXTENSIONS } from './constants.ts'\nimport { loadModule } from './loader.ts'\n\n// A config in one of these folders belongs to the folder above it.\nconst CONFIG_FOLDERS = ['.config', 'configs']\nconst SEARCH_FILES = ['', ...CONFIG_FOLDERS.map((folder) => `${folder}/`)].flatMap((prefix) => [`${prefix}.kubbrc`, `${prefix}kubb.config`])\n\n/**\n * Every config file path the Kubb CLI checks in `dir`, in the order it checks them.\n */\nexport function configFileCandidates(dir: string): Array<string> {\n return SEARCH_FILES.flatMap((file) => CONFIG_EXTENSIONS.map((extension) => join(dir, `${file}${extension}`)))\n}\n\n/**\n * The first Kubb config file in `cwd` or the nearest parent folder that has one: `.kubbrc` before\n * `kubb.config`, the folder itself before its `.config/` and `configs/`, and {@link CONFIG_EXTENSIONS} in order.\n */\nexport function findConfigFile(cwd: string = process.cwd()): string | undefined {\n for (let dir = resolve(cwd); ; dir = dirname(dir)) {\n const found = configFileCandidates(dir).find((file) => existsSync(file))\n if (found || dirname(dir) === dir) return found\n }\n}\n\n/**\n * Loads a Kubb config module, calls it with `cli` when it exports a function, and returns its\n * configs as a list, so a single config and a `defineConfig([...])` array read the same. Each\n * `root` resolves from the folder the config belongs to: the file's folder, or the folder above\n * `.config/` and `configs/`. A missing `root` becomes that folder, so the CLI, the bundler, and\n * an editor read the same paths wherever they run.\n */\nexport async function loadConfigFile<T extends { root?: string }>({ file, cli }: { file: string; cli: unknown }): Promise<Array<T>> {\n const loaded = await loadModule<unknown>(file, { default: true })\n const resolved = (await (typeof loaded === 'function' ? loaded(cli) : loaded)) as T | Array<T>\n const dir = CONFIG_FOLDERS.includes(basename(dirname(file))) ? dirname(dirname(file)) : dirname(file)\n return (Array.isArray(resolved) ? resolved : [resolved]).map((config) => ({ ...config, root: resolve(dir, config.root ?? '.') }))\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, cli: { 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":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-CNqgDSu3.js","names":[],"sources":["../../../internals/shared/src/constants.ts","../../../internals/shared/src/loader.ts","../../../internals/shared/src/config.ts","../src/config.ts"],"sourcesContent":["export const KUBB_CONFIG_FILENAME = 'kubb.config.ts' as const\n\n/** File extensions a Kubb config file may use. */\nexport const CONFIG_EXTENSIONS = ['.ts', '.mts', '.cts', '.js', '.mjs', '.cjs'] as const\n\nexport const KUBB_PACKAGE_NAME = 'kubb' as const\n\n/**\n * Extensions `kubb` ships at its own version, so they count as installed without being a direct\n * dependency. `constants.test.ts` checks it against the `kubb` package's dependencies.\n */\nexport const BUNDLED_PACKAGES: ReadonlyArray<string> = ['@kubb/adapter-oas', '@kubb/parser-ts', '@kubb/parser-md', '@kubb/plugin-barrel']\n\nexport const initDefaults = {\n inputPath: './openapi.yaml',\n outputPath: './src/gen',\n plugins: ['plugin-ts'],\n} as const\n","import { readFile } from 'node:fs/promises'\nimport { createJiti } from 'jiti'\n\n/**\n * jiti options for loading Kubb config modules: the automatic JSX runtime pointed at\n * `@kubb/renderer-jsx`, and `moduleCache` off so a re-load re-evaluates the file.\n */\nconst JITI_OPTIONS = {\n jsx: { runtime: 'automatic', importSource: '@kubb/renderer-jsx' },\n moduleCache: false,\n} satisfies Parameters<typeof createJiti>[1]\n\n/**\n * Plain JavaScript files. jiti hands these to Node's native `import()`, whose module cache never\n * lets go of a file, so `moduleCache: false` alone would keep returning the first version of it.\n */\nconst JAVASCRIPT_EXTENSION = /\\.[cm]?jsx?$/\n\n/**\n * Per-call options for {@link loadModule}.\n */\ntype LoadModuleOptions = {\n /**\n * Return the module's default export instead of the full namespace.\n */\n default?: boolean\n}\n\nconst jiti = createJiti(import.meta.url, JITI_OPTIONS)\n\n/**\n * Loads a Kubb TypeScript or JavaScript config module via jiti.\n *\n * jiti transpiles TypeScript and the `@kubb/renderer-jsx` JSX runtime on the fly. Every load\n * re-evaluates the file, so a config edited on disk is picked up by the next load.\n *\n * @example\n * ```ts\n * const config = await loadModule('/abs/kubb.config.ts', { default: true })\n * ```\n */\nexport async function loadModule<T = unknown>(filePath: string, options?: LoadModuleOptions): Promise<T> {\n if (!JAVASCRIPT_EXTENSION.test(filePath)) {\n return (options?.default ? jiti.import(filePath, { default: true }) : jiti.import(filePath)) as Promise<T>\n }\n\n // Transpiled through jiti instead, so every load re-evaluates the file as it is on disk now.\n // A TypeScript file it imports reloads too. A plain JavaScript file it imports still goes\n // through Node's `import()` and stays cached until the process restarts.\n const mod = (await jiti.evalModule(await readFile(filePath, 'utf8'), { filename: filePath, async: true, forceTranspile: true })) as\n | { default?: unknown }\n | undefined\n return (options?.default ? (mod?.default ?? mod) : mod) as T\n}\n","import { existsSync } from 'node:fs'\nimport { basename, dirname, join, resolve } from 'node:path'\nimport process from 'node:process'\nimport { CONFIG_EXTENSIONS } from './constants.ts'\nimport { loadModule } from './loader.ts'\n\n// A config in one of these folders belongs to the folder above it.\nconst CONFIG_FOLDERS = ['.config', 'configs']\nconst SEARCH_FILES = ['', ...CONFIG_FOLDERS.map((folder) => `${folder}/`)].flatMap((prefix) => [`${prefix}.kubbrc`, `${prefix}kubb.config`])\n\n/**\n * Every config file path the Kubb CLI checks in `dir`, in the order it checks them.\n */\nexport function configFileCandidates(dir: string): Array<string> {\n return SEARCH_FILES.flatMap((file) => CONFIG_EXTENSIONS.map((extension) => join(dir, `${file}${extension}`)))\n}\n\n/**\n * The first Kubb config file in `cwd` or the nearest parent folder that has one: `.kubbrc` before\n * `kubb.config`, the folder itself before its `.config/` and `configs/`, and {@link CONFIG_EXTENSIONS} in order.\n */\nexport function findConfigFile(cwd: string = process.cwd()): string | undefined {\n for (let dir = resolve(cwd); ; dir = dirname(dir)) {\n const found = configFileCandidates(dir).find((file) => existsSync(file))\n if (found || dirname(dir) === dir) return found\n }\n}\n\n/**\n * Loads a Kubb config module, calls it with `cli` when it exports a function, and returns its\n * configs as a list, so a single config and a `defineConfig([...])` array read the same. Each\n * `root` resolves from the folder the config belongs to: the file's folder, or the folder above\n * `.config/` and `configs/`. A missing `root` becomes that folder, so the CLI, the bundler, and\n * an editor read the same paths wherever they run.\n */\nexport async function loadConfigFile<T extends { root?: string }>({ file, cli }: { file: string; cli: unknown }): Promise<Array<T>> {\n const loaded = await loadModule<unknown>(file, { default: true })\n const resolved = (await (typeof loaded === 'function' ? loaded(cli) : loaded)) as T | Array<T>\n const dir = CONFIG_FOLDERS.includes(basename(dirname(file))) ? dirname(dirname(file)) : dirname(file)\n return (Array.isArray(resolved) ? resolved : [resolved]).map((config) => ({ ...config, root: resolve(dir, config.root ?? '.') }))\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, cli: { 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":"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"}
@@ -1 +0,0 @@
1
- export { t as getConfigs } from "./config-CNqgDSu3.js";
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry-BzBp6aZI.cjs","names":["getIntro","isRichOutput","stripVTControlCharacters","isInteractiveRun","wakeUp","sleep","process","Diagnostics","getErrorMessage","toError","isRegistryEntry","isValid","isLessThan","difference"],"sources":["../src/ui/mascot.ts","../src/utils/registry.ts"],"sourcesContent":["import { setTimeout as sleep } from 'node:timers/promises'\nimport { stripVTControlCharacters } from 'node:util'\nimport { isRichOutput } from '../utils/env.ts'\nimport { type Expression, getIntro, wakeUp } from '../loggers/banner.ts'\nimport { isInteractiveRun } from './intro.ts'\n\nfunction bannerIntro(version: string, expression: Expression, command: string): string {\n return getIntro({ title: 'Turn your API spec into type-safe code', description: `kubb ${command}`, version, expression })\n}\n\n/** Whether the mascot can be drawn: a rich, 256-color terminal wide enough that no line wraps and throws off a redraw. */\nfunction canDrawMascot(version: string, command: string): boolean {\n if (!isRichOutput() || !process.stdout.hasColors(256)) return false\n\n return stripVTControlCharacters(bannerIntro(version, 'open', command))\n .split('\\n')\n .every((line) => line.length <= process.stdout.columns)\n}\n\n/**\n * Whether a command opens with the mascot. Only the long-running ones do: `generate`, a Studio\n * session or pairing, and `add` or `update` while they ask questions. Quick commands print only\n * their result.\n */\nexport function wantsMascot({ commandPath, values }: { commandPath: ReadonlyArray<string>; values: Record<string, unknown> }): boolean {\n const [command, subCommand] = commandPath\n if (values.help || values.version) return false\n if (command === 'studio') return subCommand === undefined || subCommand === 'connect' || subCommand === 'login'\n if (command === 'add' || command === 'update' || command === 'init') return isInteractiveRun({ yes: values.yes, dryRun: values.dryRun ?? values['dry-run'] })\n\n return command === undefined || command === 'generate'\n}\n\n/**\n * The still Kubb mascot with the version and the running command, such as `studio connect`, or a\n * single version line where the terminal cannot draw it. Commands print it as their header; it\n * draws at once, with no wake-up frames.\n */\nexport function getBanner(version: string, command: string): string {\n return canDrawMascot(version, command) ? `\\n${bannerIntro(version, 'open', command)}` : `Kubb CLI v${version}`\n}\n\n/**\n * Opens `kubb generate` with the mascot playing its wake-up frames in place, which takes under a\n * second and overlaps the config load. Elsewhere the still {@link getBanner} is the header.\n */\nexport async function logBanner(version: string): Promise<void> {\n if (!canDrawMascot(version, 'generate')) {\n console.log(getBanner(version, 'generate'))\n\n return\n }\n\n console.log('')\n for (const [index, [expression, ms]] of wakeUp.entries()) {\n const frame = bannerIntro(version, expression, 'generate')\n if (index > 0) process.stdout.moveCursor(0, -frame.split('\\n').length)\n console.log(frame)\n await sleep(ms)\n }\n}\n","import process from 'node:process'\nimport { getErrorMessage, toError } from '@internals/utils'\nimport { checkCompatibility, Diagnostics, type ExtensionManifest, isRegistryEntry, type RegistryArtifact, type RegistryEntry } from '@kubb/core'\nimport { difference, isLessThan, isValid } from 'verkit'\n\nconst DEFAULT_REGISTRY = 'https://kubb.dev/registry'\n\nconst SLUG = '[a-z0-9]+(?:-[a-z0-9]+)*'\nconst ID = new RegExp(`^${SLUG}(\\\\/${SLUG})?$`)\n\n/** The registry base URL: `KUBB_REGISTRY`, or kubb.dev. */\nexport function registryUrl(): string {\n const url = process.env.KUBB_REGISTRY || DEFAULT_REGISTRY\n if (!/^https?:\\/\\//.test(url))\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `KUBB_REGISTRY must be an http(s) URL, got \"${url}\".`,\n help: 'Set `KUBB_REGISTRY` to an http(s) URL, or unset it to use https://kubb.dev/registry.',\n })\n return url.replace(/\\/+$/, '')\n}\n\n/**\n * Turns `owner/slug`, or a bare `slug` meaning `kubb-labs/<slug>`, into a registry id.\n *\n * @throws when the id has another shape, so it never reaches a URL unchecked.\n */\nexport function toRegistryId(input: string): string {\n if (!ID.test(input))\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `\"${input}\" is not a registry id. Use owner/slug, such as kubb-labs/plugin-zod, or a slug, such as plugin-zod.`,\n })\n return input.includes('/') ? input : `kubb-labs/${input}`\n}\n\n/** The shortest id `kubb add` and `kubb update` accept: the slug for an official extension, else `owner/slug`. */\nexport function toShortId(id: string): string {\n return id.startsWith('kubb-labs/') ? id.slice('kubb-labs/'.length) : id\n}\n\n/**\n * GETs `url` as JSON. A non-2xx answer or a body that is not JSON returns no `body`.\n * A network error throws with the URL.\n */\nasync function fetchJSON(url: string): Promise<{ status: number; body?: unknown }> {\n let response: Response\n try {\n response = await globalThis.fetch(url, { headers: { accept: 'application/json' } })\n } catch (cause) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.inputUnreachable,\n severity: 'error',\n message: `Could not read ${url}: ${getErrorMessage(cause)}`,\n help: 'Check your network connection and that the registry is reachable.',\n cause: toError(cause),\n })\n }\n if (!response.ok) return { status: response.status }\n return { status: response.status, body: await response.json().catch(() => undefined) }\n}\n\n/** Fetches the registry index, leaving out entries that fail validation. */\nexport async function fetchRegistryIndex({ registry }: { registry: string }): Promise<Array<RegistryEntry>> {\n const { status, body } = await fetchJSON(`${registry}/index.json`)\n const index = body as { version?: unknown; extensions?: unknown } | null | undefined\n if (status !== 200 || index?.version !== 1 || !Array.isArray(index.extensions)) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.inputRequestFailed,\n severity: 'error',\n message: `The registry at ${registry} sent an invalid index (HTTP ${status}).`,\n help: 'Try again later, or check that `KUBB_REGISTRY` points at a Kubb registry.',\n })\n }\n return index.extensions.filter(isRegistryEntry)\n}\n\n/** What the package manager installs: `<package>@<version>`, or a GitHub release's commit, so the install cannot move with the tag. */\nexport function installSpec(artifact: RegistryArtifact): string {\n return artifact.kind === 'github' ? `github:${artifact.owner}/${artifact.repo}#${artifact.commit}` : `${artifact.package}@${artifact.version}`\n}\n\n/** Why the running Kubb or Node.js version cannot use this extension, or `undefined` when it can. */\nexport function incompatibility(manifest: ExtensionManifest): string | undefined {\n try {\n checkCompatibility({ name: manifest.name, compatibility: manifest.compatibility })\n return undefined\n } catch (error) {\n return getErrorMessage(error)\n }\n}\n\n/**\n * Whether `latest` is newer than `installed`. An unknown installed version counts as outdated, and an\n * invalid `latest` never does.\n */\nexport function isOutdated({ installed, latest }: { installed: string | undefined; latest: string }): boolean {\n if (!isValid(latest)) return false\n return !installed || !isValid(installed) || isLessThan(installed, latest)\n}\n\n/** `major`, `minor`, or `patch` from `installed` to `latest`, or `undefined` when either is unknown or invalid. */\nexport function bumpOf({ installed, latest }: { installed: string | undefined; latest: string }): 'major' | 'minor' | 'patch' | undefined {\n if (!installed || !isValid(installed) || !isValid(latest)) return undefined\n const kind = difference(installed, latest)\n if (!kind) return undefined\n if (kind.endsWith('major')) return 'major'\n return kind.endsWith('minor') ? 'minor' : 'patch'\n}\n\nfunction editDistance(a: string, b: string): number {\n const row = Array.from({ length: b.length + 1 }, (_, index) => index)\n for (let i = 1; i <= a.length; i++) {\n let previous = row[0]!\n row[0] = i\n for (let j = 1; j <= b.length; j++) {\n const current = row[j]!\n row[j] = Math.min(row[j]! + 1, row[j - 1]! + 1, previous + (a[i - 1] === b[j - 1] ? 0 : 1))\n previous = current\n }\n }\n return row[b.length]!\n}\n\n/** Words every extension shares, so they never make two ids look alike. */\nconst COMMON_TOKENS = new Set(['kubb', 'plugin', 'adapter', 'parser'])\n\n/**\n * The ids closest to a mistyped `input`, best first, at most three: those within a few edits of it,\n * or sharing a word such as `zod` in any order. Compares slugs, so the owner may be left out.\n */\nexport function closestIds({ input, ids }: { input: string; ids: Array<string> }): Array<string> {\n const slug = (id: string) => id.slice(id.indexOf('/') + 1)\n const tokens = new Set(\n slug(input)\n .split('-')\n .filter((token) => !COMMON_TOKENS.has(token)),\n )\n return ids\n .map((id) => ({\n id,\n distance: editDistance(slug(input), slug(id)),\n shared: slug(id)\n .split('-')\n .some((token) => tokens.has(token)),\n }))\n .filter(({ distance, shared }) => shared || distance <= Math.max(2, Math.floor(slug(input).length / 4)))\n .sort((a, b) => Number(b.shared) - Number(a.shared) || a.distance - b.distance)\n .slice(0, 3)\n .map(({ id }) => id)\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry-DOGpflct.js","names":["sleep","process"],"sources":["../src/ui/mascot.ts","../src/utils/registry.ts"],"sourcesContent":["import { setTimeout as sleep } from 'node:timers/promises'\nimport { stripVTControlCharacters } from 'node:util'\nimport { isRichOutput } from '../utils/env.ts'\nimport { type Expression, getIntro, wakeUp } from '../loggers/banner.ts'\nimport { isInteractiveRun } from './intro.ts'\n\nfunction bannerIntro(version: string, expression: Expression, command: string): string {\n return getIntro({ title: 'Turn your API spec into type-safe code', description: `kubb ${command}`, version, expression })\n}\n\n/** Whether the mascot can be drawn: a rich, 256-color terminal wide enough that no line wraps and throws off a redraw. */\nfunction canDrawMascot(version: string, command: string): boolean {\n if (!isRichOutput() || !process.stdout.hasColors(256)) return false\n\n return stripVTControlCharacters(bannerIntro(version, 'open', command))\n .split('\\n')\n .every((line) => line.length <= process.stdout.columns)\n}\n\n/**\n * Whether a command opens with the mascot. Only the long-running ones do: `generate`, a Studio\n * session or pairing, and `add` or `update` while they ask questions. Quick commands print only\n * their result.\n */\nexport function wantsMascot({ commandPath, values }: { commandPath: ReadonlyArray<string>; values: Record<string, unknown> }): boolean {\n const [command, subCommand] = commandPath\n if (values.help || values.version) return false\n if (command === 'studio') return subCommand === undefined || subCommand === 'connect' || subCommand === 'login'\n if (command === 'add' || command === 'update' || command === 'init') return isInteractiveRun({ yes: values.yes, dryRun: values.dryRun ?? values['dry-run'] })\n\n return command === undefined || command === 'generate'\n}\n\n/**\n * The still Kubb mascot with the version and the running command, such as `studio connect`, or a\n * single version line where the terminal cannot draw it. Commands print it as their header; it\n * draws at once, with no wake-up frames.\n */\nexport function getBanner(version: string, command: string): string {\n return canDrawMascot(version, command) ? `\\n${bannerIntro(version, 'open', command)}` : `Kubb CLI v${version}`\n}\n\n/**\n * Opens `kubb generate` with the mascot playing its wake-up frames in place, which takes under a\n * second and overlaps the config load. Elsewhere the still {@link getBanner} is the header.\n */\nexport async function logBanner(version: string): Promise<void> {\n if (!canDrawMascot(version, 'generate')) {\n console.log(getBanner(version, 'generate'))\n\n return\n }\n\n console.log('')\n for (const [index, [expression, ms]] of wakeUp.entries()) {\n const frame = bannerIntro(version, expression, 'generate')\n if (index > 0) process.stdout.moveCursor(0, -frame.split('\\n').length)\n console.log(frame)\n await sleep(ms)\n }\n}\n","import process from 'node:process'\nimport { getErrorMessage, toError } from '@internals/utils'\nimport { checkCompatibility, Diagnostics, type ExtensionManifest, isRegistryEntry, type RegistryArtifact, type RegistryEntry } from '@kubb/core'\nimport { difference, isLessThan, isValid } from 'verkit'\n\nconst DEFAULT_REGISTRY = 'https://kubb.dev/registry'\n\nconst SLUG = '[a-z0-9]+(?:-[a-z0-9]+)*'\nconst ID = new RegExp(`^${SLUG}(\\\\/${SLUG})?$`)\n\n/** The registry base URL: `KUBB_REGISTRY`, or kubb.dev. */\nexport function registryUrl(): string {\n const url = process.env.KUBB_REGISTRY || DEFAULT_REGISTRY\n if (!/^https?:\\/\\//.test(url))\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `KUBB_REGISTRY must be an http(s) URL, got \"${url}\".`,\n help: 'Set `KUBB_REGISTRY` to an http(s) URL, or unset it to use https://kubb.dev/registry.',\n })\n return url.replace(/\\/+$/, '')\n}\n\n/**\n * Turns `owner/slug`, or a bare `slug` meaning `kubb-labs/<slug>`, into a registry id.\n *\n * @throws when the id has another shape, so it never reaches a URL unchecked.\n */\nexport function toRegistryId(input: string): string {\n if (!ID.test(input))\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `\"${input}\" is not a registry id. Use owner/slug, such as kubb-labs/plugin-zod, or a slug, such as plugin-zod.`,\n })\n return input.includes('/') ? input : `kubb-labs/${input}`\n}\n\n/** The shortest id `kubb add` and `kubb update` accept: the slug for an official extension, else `owner/slug`. */\nexport function toShortId(id: string): string {\n return id.startsWith('kubb-labs/') ? id.slice('kubb-labs/'.length) : id\n}\n\n/**\n * GETs `url` as JSON. A non-2xx answer or a body that is not JSON returns no `body`.\n * A network error throws with the URL.\n */\nasync function fetchJSON(url: string): Promise<{ status: number; body?: unknown }> {\n let response: Response\n try {\n response = await globalThis.fetch(url, { headers: { accept: 'application/json' } })\n } catch (cause) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.inputUnreachable,\n severity: 'error',\n message: `Could not read ${url}: ${getErrorMessage(cause)}`,\n help: 'Check your network connection and that the registry is reachable.',\n cause: toError(cause),\n })\n }\n if (!response.ok) return { status: response.status }\n return { status: response.status, body: await response.json().catch(() => undefined) }\n}\n\n/** Fetches the registry index, leaving out entries that fail validation. */\nexport async function fetchRegistryIndex({ registry }: { registry: string }): Promise<Array<RegistryEntry>> {\n const { status, body } = await fetchJSON(`${registry}/index.json`)\n const index = body as { version?: unknown; extensions?: unknown } | null | undefined\n if (status !== 200 || index?.version !== 1 || !Array.isArray(index.extensions)) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.inputRequestFailed,\n severity: 'error',\n message: `The registry at ${registry} sent an invalid index (HTTP ${status}).`,\n help: 'Try again later, or check that `KUBB_REGISTRY` points at a Kubb registry.',\n })\n }\n return index.extensions.filter(isRegistryEntry)\n}\n\n/** What the package manager installs: `<package>@<version>`, or a GitHub release's commit, so the install cannot move with the tag. */\nexport function installSpec(artifact: RegistryArtifact): string {\n return artifact.kind === 'github' ? `github:${artifact.owner}/${artifact.repo}#${artifact.commit}` : `${artifact.package}@${artifact.version}`\n}\n\n/** Why the running Kubb or Node.js version cannot use this extension, or `undefined` when it can. */\nexport function incompatibility(manifest: ExtensionManifest): string | undefined {\n try {\n checkCompatibility({ name: manifest.name, compatibility: manifest.compatibility })\n return undefined\n } catch (error) {\n return getErrorMessage(error)\n }\n}\n\n/**\n * Whether `latest` is newer than `installed`. An unknown installed version counts as outdated, and an\n * invalid `latest` never does.\n */\nexport function isOutdated({ installed, latest }: { installed: string | undefined; latest: string }): boolean {\n if (!isValid(latest)) return false\n return !installed || !isValid(installed) || isLessThan(installed, latest)\n}\n\n/** `major`, `minor`, or `patch` from `installed` to `latest`, or `undefined` when either is unknown or invalid. */\nexport function bumpOf({ installed, latest }: { installed: string | undefined; latest: string }): 'major' | 'minor' | 'patch' | undefined {\n if (!installed || !isValid(installed) || !isValid(latest)) return undefined\n const kind = difference(installed, latest)\n if (!kind) return undefined\n if (kind.endsWith('major')) return 'major'\n return kind.endsWith('minor') ? 'minor' : 'patch'\n}\n\nfunction editDistance(a: string, b: string): number {\n const row = Array.from({ length: b.length + 1 }, (_, index) => index)\n for (let i = 1; i <= a.length; i++) {\n let previous = row[0]!\n row[0] = i\n for (let j = 1; j <= b.length; j++) {\n const current = row[j]!\n row[j] = Math.min(row[j]! + 1, row[j - 1]! + 1, previous + (a[i - 1] === b[j - 1] ? 0 : 1))\n previous = current\n }\n }\n return row[b.length]!\n}\n\n/** Words every extension shares, so they never make two ids look alike. */\nconst COMMON_TOKENS = new Set(['kubb', 'plugin', 'adapter', 'parser'])\n\n/**\n * The ids closest to a mistyped `input`, best first, at most three: those within a few edits of it,\n * or sharing a word such as `zod` in any order. Compares slugs, so the owner may be left out.\n */\nexport function closestIds({ input, ids }: { input: string; ids: Array<string> }): Array<string> {\n const slug = (id: string) => id.slice(id.indexOf('/') + 1)\n const tokens = new Set(\n slug(input)\n .split('-')\n .filter((token) => !COMMON_TOKENS.has(token)),\n )\n return ids\n .map((id) => ({\n id,\n distance: editDistance(slug(input), slug(id)),\n shared: slug(id)\n .split('-')\n .some((token) => tokens.has(token)),\n }))\n .filter(({ distance, shared }) => shared || distance <= Math.max(2, Math.floor(slug(input).length / 4)))\n .sort((a, b) => Number(b.shared) - Number(a.shared) || a.distance - b.distance)\n .slice(0, 3)\n .map(({ id }) => id)\n}\n"],"mappings":";;;;;;;;;;AAMA,SAAS,YAAY,SAAiB,YAAwB,SAAyB;CACrF,OAAO,SAAS;EAAE,OAAO;EAA0C,aAAa,QAAQ;EAAW;EAAS;CAAW,CAAC;AAC1H;;AAGA,SAAS,cAAc,SAAiB,SAA0B;CAChE,IAAI,CAAC,aAAa,KAAK,CAAC,QAAQ,OAAO,UAAU,GAAG,GAAG,OAAO;CAE9D,OAAO,yBAAyB,YAAY,SAAS,QAAQ,OAAO,CAAC,CAAC,CACnE,MAAM,IAAI,CAAC,CACX,OAAO,SAAS,KAAK,UAAU,QAAQ,OAAO,OAAO;AAC1D;;;;;;AAOA,SAAgB,YAAY,EAAE,aAAa,UAA4F;CACrI,MAAM,CAAC,SAAS,cAAc;CAC9B,IAAI,OAAO,QAAQ,OAAO,SAAS,OAAO;CAC1C,IAAI,YAAY,UAAU,OAAO,eAAe,KAAA,KAAa,eAAe,aAAa,eAAe;CACxG,IAAI,YAAY,SAAS,YAAY,YAAY,YAAY,QAAQ,OAAO,iBAAiB;EAAE,KAAK,OAAO;EAAK,QAAQ,OAAO,UAAU,OAAO;CAAW,CAAC;CAE5J,OAAO,YAAY,KAAA,KAAa,YAAY;AAC9C;;;;;;AAOA,SAAgB,UAAU,SAAiB,SAAyB;CAClE,OAAO,cAAc,SAAS,OAAO,IAAI,KAAK,YAAY,SAAS,QAAQ,OAAO,MAAM,aAAa;AACvG;;;;;AAMA,eAAsB,UAAU,SAAgC;CAC9D,IAAI,CAAC,cAAc,SAAS,UAAU,GAAG;EACvC,QAAQ,IAAI,UAAU,SAAS,UAAU,CAAC;EAE1C;CACF;CAEA,QAAQ,IAAI,EAAE;CACd,KAAK,MAAM,CAAC,OAAO,CAAC,YAAY,QAAQ,OAAO,QAAQ,GAAG;EACxD,MAAM,QAAQ,YAAY,SAAS,YAAY,UAAU;EACzD,IAAI,QAAQ,GAAG,QAAQ,OAAO,WAAW,GAAG,CAAC,MAAM,MAAM,IAAI,CAAC,CAAC,MAAM;EACrE,QAAQ,IAAI,KAAK;EACjB,MAAMA,WAAM,EAAE;CAChB;AACF;;;ACvDA,MAAM,mBAAmB;AAEzB,MAAM,OAAO;AACb,MAAM,KAAK,IAAI,OAAO,IAAI,KAAK,MAAM,KAAK,IAAI;;AAG9C,SAAgB,cAAsB;CACpC,MAAM,MAAMC,UAAQ,IAAI,iBAAiB;CACzC,IAAI,CAAC,eAAe,KAAK,GAAG,GAC1B,MAAM,IAAI,YAAY,MAAM;EAC1B,MAAM,YAAY,KAAK;EACvB,UAAU;EACV,SAAS,8CAA8C,IAAI;EAC3D,MAAM;CACR,CAAC;CACH,OAAO,IAAI,QAAQ,QAAQ,EAAE;AAC/B;;;;;;AAOA,SAAgB,aAAa,OAAuB;CAClD,IAAI,CAAC,GAAG,KAAK,KAAK,GAChB,MAAM,IAAI,YAAY,MAAM;EAC1B,MAAM,YAAY,KAAK;EACvB,UAAU;EACV,SAAS,IAAI,MAAM;CACrB,CAAC;CACH,OAAO,MAAM,SAAS,GAAG,IAAI,QAAQ,aAAa;AACpD;;AAGA,SAAgB,UAAU,IAAoB;CAC5C,OAAO,GAAG,WAAW,YAAY,IAAI,GAAG,MAAM,EAAmB,IAAI;AACvE;;;;;AAMA,eAAe,UAAU,KAA0D;CACjF,IAAI;CACJ,IAAI;EACF,WAAW,MAAM,WAAW,MAAM,KAAK,EAAE,SAAS,EAAE,QAAQ,mBAAmB,EAAE,CAAC;CACpF,SAAS,OAAO;EACd,MAAM,IAAI,YAAY,MAAM;GAC1B,MAAM,YAAY,KAAK;GACvB,UAAU;GACV,SAAS,kBAAkB,IAAI,IAAI,gBAAgB,KAAK;GACxD,MAAM;GACN,OAAO,QAAQ,KAAK;EACtB,CAAC;CACH;CACA,IAAI,CAAC,SAAS,IAAI,OAAO,EAAE,QAAQ,SAAS,OAAO;CACnD,OAAO;EAAE,QAAQ,SAAS;EAAQ,MAAM,MAAM,SAAS,KAAK,CAAC,CAAC,YAAY,KAAA,CAAS;CAAE;AACvF;;AAGA,eAAsB,mBAAmB,EAAE,YAAiE;CAC1G,MAAM,EAAE,QAAQ,SAAS,MAAM,UAAU,GAAG,SAAS,YAAY;CACjE,MAAM,QAAQ;CACd,IAAI,WAAW,OAAO,OAAO,YAAY,KAAK,CAAC,MAAM,QAAQ,MAAM,UAAU,GAC3E,MAAM,IAAI,YAAY,MAAM;EAC1B,MAAM,YAAY,KAAK;EACvB,UAAU;EACV,SAAS,mBAAmB,SAAS,+BAA+B,OAAO;EAC3E,MAAM;CACR,CAAC;CAEH,OAAO,MAAM,WAAW,OAAO,eAAe;AAChD;;AAGA,SAAgB,YAAY,UAAoC;CAC9D,OAAO,SAAS,SAAS,WAAW,UAAU,SAAS,MAAM,GAAG,SAAS,KAAK,GAAG,SAAS,WAAW,GAAG,SAAS,QAAQ,GAAG,SAAS;AACvI;;AAGA,SAAgB,gBAAgB,UAAiD;CAC/E,IAAI;EACF,mBAAmB;GAAE,MAAM,SAAS;GAAM,eAAe,SAAS;EAAc,CAAC;EACjF;CACF,SAAS,OAAO;EACd,OAAO,gBAAgB,KAAK;CAC9B;AACF;;;;;AAMA,SAAgB,WAAW,EAAE,WAAW,UAAsE;CAC5G,IAAI,CAAC,QAAQ,MAAM,GAAG,OAAO;CAC7B,OAAO,CAAC,aAAa,CAAC,QAAQ,SAAS,KAAK,WAAW,WAAW,MAAM;AAC1E;;AAGA,SAAgB,OAAO,EAAE,WAAW,UAAsG;CACxI,IAAI,CAAC,aAAa,CAAC,QAAQ,SAAS,KAAK,CAAC,QAAQ,MAAM,GAAG,OAAO,KAAA;CAClE,MAAM,OAAO,WAAW,WAAW,MAAM;CACzC,IAAI,CAAC,MAAM,OAAO,KAAA;CAClB,IAAI,KAAK,SAAS,OAAO,GAAG,OAAO;CACnC,OAAO,KAAK,SAAS,OAAO,IAAI,UAAU;AAC5C;AAEA,SAAS,aAAa,GAAW,GAAmB;CAClD,MAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,GAAG,UAAU,KAAK;CACpE,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;EAClC,IAAI,WAAW,IAAI;EACnB,IAAI,KAAK;EACT,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;GAClC,MAAM,UAAU,IAAI;GACpB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAM,GAAG,IAAI,IAAI,KAAM,GAAG,YAAY,EAAE,IAAI,OAAO,EAAE,IAAI,KAAK,IAAI,EAAE;GAC1F,WAAW;EACb;CACF;CACA,OAAO,IAAI,EAAE;AACf;;AAGA,MAAM,gCAAgB,IAAI,IAAI;CAAC;CAAQ;CAAU;CAAW;AAAQ,CAAC;;;;;AAMrE,SAAgB,WAAW,EAAE,OAAO,OAA6D;CAC/F,MAAM,QAAQ,OAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;CACzD,MAAM,SAAS,IAAI,IACjB,KAAK,KAAK,CAAC,CACR,MAAM,GAAG,CAAC,CACV,QAAQ,UAAU,CAAC,cAAc,IAAI,KAAK,CAAC,CAChD;CACA,OAAO,IACJ,KAAK,QAAQ;EACZ;EACA,UAAU,aAAa,KAAK,KAAK,GAAG,KAAK,EAAE,CAAC;EAC5C,QAAQ,KAAK,EAAE,CAAC,CACb,MAAM,GAAG,CAAC,CACV,MAAM,UAAU,OAAO,IAAI,KAAK,CAAC;CACtC,EAAE,CAAC,CACF,QAAQ,EAAE,UAAU,aAAa,UAAU,YAAY,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CACvG,MAAM,GAAG,MAAM,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,KAAK,EAAE,WAAW,EAAE,QAAQ,CAAC,CAC9E,MAAM,GAAG,CAAC,CAAC,CACX,KAAK,EAAE,SAAS,EAAE;AACvB"}