@kubb/agent 5.0.0-beta.20 → 5.0.0-beta.22

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.
@@ -4889,7 +4889,7 @@ function* collectLazy(node, options) {
4889
4889
  v = (_g = visitor.response) == null ? void 0 : _g.call(visitor, node, { parent });
4890
4890
  break;
4891
4891
  }
4892
- if (v !== void 0) yield v;
4892
+ if (v != null) yield v;
4893
4893
  for (const child of getChildren(node, recurse)) yield* collectLazy(child, {
4894
4894
  ...options,
4895
4895
  parent: node
@@ -5037,9 +5037,9 @@ function extractStringsFromNodes(nodes) {
5037
5037
  }
5038
5038
  function resolveRefName(node) {
5039
5039
  var _a, _b, _c, _d, _e, _f, _g;
5040
- if (!node || node.type !== "ref") return void 0;
5041
- if (node.ref) return (_d = (_c = (_a = extractRefName(node.ref)) != null ? _a : node.name) != null ? _c : (_b = node.schema) == null ? void 0 : _b.name) != null ? _d : void 0;
5042
- return (_g = (_f = node.name) != null ? _f : (_e = node.schema) == null ? void 0 : _e.name) != null ? _g : void 0;
5040
+ if (!node || node.type !== "ref") return null;
5041
+ if (node.ref) return (_d = (_c = (_a = extractRefName(node.ref)) != null ? _a : node.name) != null ? _c : (_b = node.schema) == null ? void 0 : _b.name) != null ? _d : null;
5042
+ return (_g = (_f = node.name) != null ? _f : (_e = node.schema) == null ? void 0 : _e.name) != null ? _g : null;
5043
5043
  }
5044
5044
  const collectSchemaRefs = memoize$1(/* @__PURE__ */ new WeakMap(), (node) => {
5045
5045
  const refs = /* @__PURE__ */ new Set();
@@ -5148,9 +5148,117 @@ var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !==
5148
5148
  var __accessCheck$1 = (obj, member, msg) => member.has(obj) || __typeError$1("Cannot " + msg);
5149
5149
  var __privateGet$1 = (obj, member, getter) => (__accessCheck$1(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
5150
5150
  var __privateAdd$1 = (obj, member, value) => member.has(obj) ? __typeError$1("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
5151
- var __privateSet = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
5151
+ var __privateSet$1 = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
5152
5152
  var __privateMethod$1 = (obj, member, method) => (__accessCheck$1(obj, member, "access private method"), method);
5153
- var _options, _URLPath_instances, transformParam_fn, eachParam_fn, _a$1, _cache, _filesCache, _FileManager_instances, store_fn, _b, _studio, _middlewareListeners, _eventGeneratorPlugins, _resolvers, _defaultResolvers, _hookListeners, _KubbDriver_instances, normalizePlugin_fn, registerAdapter_fn, registerMiddleware_fn, registerPlugin_fn, trackHookListener_fn, _getDefaultResolver, _c;
5153
+ var _emitter, _AsyncEventEmitter_instances, emitAll_fn, _a$1, _options, _URLPath_instances, transformParam_fn, eachParam_fn, _b, _cache, _sorted, _onUpsert, _FileManager_instances, store_fn, dedupe_fn, _c, _studio, _middlewareListeners, _fileProcessor, _eventGeneratorPlugins, _resolvers, _defaultResolvers, _hookListeners, _KubbDriver_instances, normalizePlugin_fn, registerAdapter_fn, registerMiddleware_fn, registerPlugin_fn, filesPayload_fn, emitPluginEnd_fn, runGenerators_fn, trackHookListener_fn, _getDefaultResolver, _d;
5154
+ var BuildError = class extends Error {
5155
+ constructor(message, options) {
5156
+ super(message, { cause: options.cause });
5157
+ __publicField$1(this, "errors");
5158
+ this.name = "BuildError";
5159
+ this.errors = options.errors;
5160
+ }
5161
+ };
5162
+ function toError(value) {
5163
+ return value instanceof Error ? value : new Error(String(value));
5164
+ }
5165
+ var AsyncEventEmitter = (_a$1 = class {
5166
+ /**
5167
+ * Maximum number of listeners per event before Node emits a memory-leak warning.
5168
+ * @default 10
5169
+ */
5170
+ constructor(maxListener = 10) {
5171
+ __privateAdd$1(this, _AsyncEventEmitter_instances);
5172
+ __privateAdd$1(this, _emitter, new EventEmitter());
5173
+ __privateGet$1(this, _emitter).setMaxListeners(maxListener);
5174
+ }
5175
+ /**
5176
+ * Emits `eventName` and awaits all registered listeners sequentially.
5177
+ * Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
5178
+ *
5179
+ * @example
5180
+ * ```ts
5181
+ * await emitter.emit('build', 'petstore')
5182
+ * ```
5183
+ */
5184
+ emit(eventName, ...eventArgs) {
5185
+ const listeners = __privateGet$1(this, _emitter).listeners(eventName);
5186
+ if (listeners.length === 0) return;
5187
+ return __privateMethod$1(this, _AsyncEventEmitter_instances, emitAll_fn).call(this, eventName, listeners, eventArgs);
5188
+ }
5189
+ /**
5190
+ * Registers a persistent listener for `eventName`.
5191
+ *
5192
+ * @example
5193
+ * ```ts
5194
+ * emitter.on('build', async (name) => { console.log(name) })
5195
+ * ```
5196
+ */
5197
+ on(eventName, handler) {
5198
+ __privateGet$1(this, _emitter).on(eventName, handler);
5199
+ }
5200
+ /**
5201
+ * Registers a one-shot listener that removes itself after the first invocation.
5202
+ *
5203
+ * @example
5204
+ * ```ts
5205
+ * emitter.onOnce('build', async (name) => { console.log(name) })
5206
+ * ```
5207
+ */
5208
+ onOnce(eventName, handler) {
5209
+ const wrapper = (...args) => {
5210
+ this.off(eventName, wrapper);
5211
+ return handler(...args);
5212
+ };
5213
+ this.on(eventName, wrapper);
5214
+ }
5215
+ /**
5216
+ * Removes a previously registered listener.
5217
+ *
5218
+ * @example
5219
+ * ```ts
5220
+ * emitter.off('build', handler)
5221
+ * ```
5222
+ */
5223
+ off(eventName, handler) {
5224
+ __privateGet$1(this, _emitter).off(eventName, handler);
5225
+ }
5226
+ /**
5227
+ * Returns the number of listeners registered for `eventName`.
5228
+ *
5229
+ * @example
5230
+ * ```ts
5231
+ * emitter.on('build', handler)
5232
+ * emitter.listenerCount('build') // 1
5233
+ * ```
5234
+ */
5235
+ listenerCount(eventName) {
5236
+ return __privateGet$1(this, _emitter).listenerCount(eventName);
5237
+ }
5238
+ /**
5239
+ * Removes all listeners from every event channel.
5240
+ *
5241
+ * @example
5242
+ * ```ts
5243
+ * emitter.removeAll()
5244
+ * ```
5245
+ */
5246
+ removeAll() {
5247
+ __privateGet$1(this, _emitter).removeAllListeners();
5248
+ }
5249
+ }, _emitter = new WeakMap(), _AsyncEventEmitter_instances = new WeakSet(), emitAll_fn = async function(eventName, listeners, eventArgs) {
5250
+ for (const listener of listeners) try {
5251
+ await listener(...eventArgs);
5252
+ } catch (err) {
5253
+ let serializedArgs;
5254
+ try {
5255
+ serializedArgs = JSON.stringify(eventArgs);
5256
+ } catch {
5257
+ serializedArgs = String(eventArgs);
5258
+ }
5259
+ throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
5260
+ }
5261
+ }, _a$1);
5154
5262
  function toCamelOrPascal(text, pascal) {
5155
5263
  return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
5156
5264
  if (word.length > 1 && word === word.toUpperCase()) return word;
@@ -5176,6 +5284,16 @@ function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
5176
5284
  }) : camelCase(part));
5177
5285
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
5178
5286
  }
5287
+ function getElapsedMs(hrStart) {
5288
+ const [seconds, nanoseconds] = process.hrtime(hrStart);
5289
+ const ms = seconds * 1e3 + nanoseconds / 1e6;
5290
+ return Math.round(ms * 100) / 100;
5291
+ }
5292
+ function formatMs(ms) {
5293
+ if (ms >= 6e4) return `${Math.floor(ms / 6e4)}m ${(ms % 6e4 / 1e3).toFixed(1)}s`;
5294
+ if (ms >= 1e3) return `${(ms / 1e3).toFixed(2)}s`;
5295
+ return `${Math.round(ms)}ms`;
5296
+ }
5179
5297
  function* chunks(arr, size) {
5180
5298
  for (let i = 0; i < arr.length; i += size) yield arr.slice(i, i + size);
5181
5299
  }
@@ -5201,10 +5319,6 @@ async function forBatches(source, process2, options) {
5201
5319
  if (flush) await flush();
5202
5320
  }
5203
5321
  }
5204
- async function withDrain(work, flush) {
5205
- await work(flush);
5206
- await flush();
5207
- }
5208
5322
  function isPromise(result) {
5209
5323
  return result !== null && result !== void 0 && typeof result["then"] === "function";
5210
5324
  }
@@ -5310,7 +5424,7 @@ function isValidVarName(name) {
5310
5424
  if (!name || reservedWords.has(name)) return false;
5311
5425
  return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
5312
5426
  }
5313
- var URLPath = (_a$1 = class {
5427
+ var URLPath = (_b = class {
5314
5428
  constructor(path2, options = {}) {
5315
5429
  __privateAdd$1(this, _URLPath_instances);
5316
5430
  /**
@@ -5319,7 +5433,7 @@ var URLPath = (_a$1 = class {
5319
5433
  __publicField$1(this, "path");
5320
5434
  __privateAdd$1(this, _options);
5321
5435
  this.path = path2;
5322
- __privateSet(this, _options, options);
5436
+ __privateSet$1(this, _options, options);
5323
5437
  }
5324
5438
  /** Converts the OpenAPI path to Express-style colon syntax, e.g. `/pet/{petId}` → `/pet/:petId`.
5325
5439
  *
@@ -5397,12 +5511,13 @@ var URLPath = (_a$1 = class {
5397
5511
  * @example
5398
5512
  * new URLPath('/pet/{petId}').toTemplateString() // '`/pet/${petId}`'
5399
5513
  */
5400
- toTemplateString({ prefix = "", replacer } = {}) {
5401
- return `\`${prefix}${this.path.split(/\{([^}]+)\}/).map((part, i) => {
5514
+ toTemplateString({ prefix, replacer } = {}) {
5515
+ const result = this.path.split(/\{([^}]+)\}/).map((part, i) => {
5402
5516
  if (i % 2 === 0) return part;
5403
5517
  const param = __privateMethod$1(this, _URLPath_instances, transformParam_fn).call(this, part);
5404
5518
  return `\${${replacer ? replacer(param) : param}}`;
5405
- }).join("")}\``;
5519
+ }).join("");
5520
+ return `\`${prefix != null ? prefix : ""}${result}\``;
5406
5521
  }
5407
5522
  /**
5408
5523
  * Extracts all `{param}` segments from the path and returns them as a key-value map.
@@ -5444,7 +5559,7 @@ eachParam_fn = function(fn) {
5444
5559
  const raw = match[1];
5445
5560
  fn(raw, __privateMethod$1(this, _URLPath_instances, transformParam_fn).call(this, raw));
5446
5561
  }
5447
- }, _a$1);
5562
+ }, _b);
5448
5563
  const DEFAULT_STUDIO_URL = "https://kubb.studio";
5449
5564
  const DEFAULT_BANNER = "simple";
5450
5565
  const DEFAULT_EXTENSION = { ".ts": ".ts" };
@@ -5596,7 +5711,7 @@ function buildDefaultBanner({ title, description, version, config }) {
5596
5711
  function defaultResolveBanner(meta, { output, config }) {
5597
5712
  if (typeof (output == null ? void 0 : output.banner) === "function") return output.banner(meta);
5598
5713
  if (typeof (output == null ? void 0 : output.banner) === "string") return output.banner;
5599
- if (config.output.defaultBanner === false) return;
5714
+ if (config.output.defaultBanner === false) return null;
5600
5715
  return buildDefaultBanner({
5601
5716
  title: meta == null ? void 0 : meta.title,
5602
5717
  version: meta == null ? void 0 : meta.version,
@@ -5606,6 +5721,7 @@ function defaultResolveBanner(meta, { output, config }) {
5606
5721
  function defaultResolveFooter(meta, { output }) {
5607
5722
  if (typeof (output == null ? void 0 : output.footer) === "function") return output.footer(meta);
5608
5723
  if (typeof (output == null ? void 0 : output.footer) === "string") return output.footer;
5724
+ return null;
5609
5725
  }
5610
5726
  function defineResolver(build) {
5611
5727
  let resolver;
@@ -5649,38 +5765,42 @@ function mergeFile(a, b) {
5649
5765
  ...a,
5650
5766
  banner: b.banner,
5651
5767
  footer: b.footer,
5652
- sources: [...a.sources || [], ...b.sources || []],
5653
- imports: [...a.imports || [], ...b.imports || []],
5654
- exports: [...a.exports || [], ...b.exports || []]
5768
+ sources: a.sources.length ? b.sources.length ? [...a.sources, ...b.sources] : a.sources : b.sources,
5769
+ imports: a.imports.length ? b.imports.length ? [...a.imports, ...b.imports] : a.imports : b.imports,
5770
+ exports: a.exports.length ? b.exports.length ? [...a.exports, ...b.exports] : a.exports : b.exports
5655
5771
  };
5656
5772
  }
5657
- function mergeFilesByPath(files) {
5658
- const merged = /* @__PURE__ */ new Map();
5659
- for (const file of files) {
5660
- const existing = merged.get(file.path);
5661
- merged.set(file.path, existing ? mergeFile(existing, file) : file);
5662
- }
5663
- return merged;
5773
+ function isIndexPath(path2) {
5774
+ return path2.endsWith("/index.ts") || path2 === "index.ts";
5664
5775
  }
5665
- var FileManager = (_b = class {
5776
+ function compareFiles(a, b) {
5777
+ const lenDiff = a.path.length - b.path.length;
5778
+ if (lenDiff !== 0) return lenDiff;
5779
+ const aIsIndex = isIndexPath(a.path);
5780
+ const bIsIndex = isIndexPath(b.path);
5781
+ if (aIsIndex && !bIsIndex) return 1;
5782
+ if (!aIsIndex && bIsIndex) return -1;
5783
+ return 0;
5784
+ }
5785
+ var FileManager = (_c = class {
5666
5786
  constructor() {
5667
5787
  __privateAdd$1(this, _FileManager_instances);
5668
5788
  __privateAdd$1(this, _cache, /* @__PURE__ */ new Map());
5669
- __privateAdd$1(this, _filesCache, null);
5789
+ __privateAdd$1(this, _sorted, null);
5790
+ __privateAdd$1(this, _onUpsert, null);
5670
5791
  }
5671
5792
  /**
5672
- * Adds one or more files. Incoming files with the same path are merged
5673
- * (sources/imports/exports concatenated), but existing cache entries are
5674
- * replaced use {@link upsert} when you want to merge into the cache too.
5793
+ * Registers a callback invoked with the resolved {@link FileNode} on every
5794
+ * `add` / `upsert`. Used by the build loop to track newly written files
5795
+ * without keeping its own scan-based diff. Single subscriber by design
5796
+ * setting again replaces the previous callback. Pass `null` to detach.
5675
5797
  */
5798
+ setOnUpsert(callback) {
5799
+ __privateSet$1(this, _onUpsert, callback);
5800
+ }
5676
5801
  add(...files) {
5677
5802
  return __privateMethod$1(this, _FileManager_instances, store_fn).call(this, files, false);
5678
5803
  }
5679
- /**
5680
- * Adds or merges one or more files.
5681
- * If a file with the same path already exists in the cache, its
5682
- * sources/imports/exports are merged into the incoming file.
5683
- */
5684
5804
  upsert(...files) {
5685
5805
  return __privateMethod$1(this, _FileManager_instances, store_fn).call(this, files, true);
5686
5806
  }
@@ -5689,54 +5809,180 @@ var FileManager = (_b = class {
5689
5809
  return (_a2 = __privateGet$1(this, _cache).get(path2)) != null ? _a2 : null;
5690
5810
  }
5691
5811
  deleteByPath(path2) {
5692
- __privateGet$1(this, _cache).delete(path2);
5693
- __privateSet(this, _filesCache, null);
5812
+ if (!__privateGet$1(this, _cache).delete(path2)) return;
5813
+ __privateSet$1(this, _sorted, null);
5694
5814
  }
5695
5815
  clear() {
5696
5816
  __privateGet$1(this, _cache).clear();
5697
- __privateSet(this, _filesCache, null);
5817
+ __privateSet$1(this, _sorted, null);
5698
5818
  }
5699
5819
  /**
5700
- * Releases all stored files. Called by the core after `kubb:build:end` to
5701
- * free the per-plugin FileNode caches for the rest of the process lifetime.
5820
+ * Releases all stored files. Called by the core after `kubb:build:end`.
5702
5821
  */
5703
5822
  dispose() {
5704
5823
  this.clear();
5824
+ __privateSet$1(this, _onUpsert, null);
5705
5825
  }
5706
5826
  [Symbol.dispose]() {
5707
5827
  this.dispose();
5708
5828
  }
5709
5829
  /**
5710
- * All stored files, sorted by path length (shorter paths first).
5830
+ * All stored files in stable sort order (shortest path first, barrel files
5831
+ * last within a length bucket). Returns a cached view — do not mutate.
5711
5832
  */
5712
5833
  get files() {
5713
- if (__privateGet$1(this, _filesCache)) return __privateGet$1(this, _filesCache);
5714
- __privateSet(this, _filesCache, [...__privateGet$1(this, _cache).values()].sort((a, b) => {
5715
- const lenDiff = a.path.length - b.path.length;
5716
- if (lenDiff !== 0) return lenDiff;
5717
- const aIsIndex = a.path.endsWith("/index.ts") || a.path === "index.ts";
5718
- const bIsIndex = b.path.endsWith("/index.ts") || b.path === "index.ts";
5719
- if (aIsIndex && !bIsIndex) return 1;
5720
- if (!aIsIndex && bIsIndex) return -1;
5721
- return 0;
5722
- }));
5723
- return __privateGet$1(this, _filesCache);
5724
- }
5725
- }, _cache = new WeakMap(), _filesCache = new WeakMap(), _FileManager_instances = new WeakSet(), store_fn = function(files, mergeExisting) {
5726
- const resolvedFiles = [];
5727
- for (const file of mergeFilesByPath(files).values()) {
5728
- const existing = mergeExisting ? __privateGet$1(this, _cache).get(file.path) : void 0;
5729
- const resolvedFile = createFile(existing ? mergeFile(existing, file) : file);
5730
- __privateGet$1(this, _cache).set(resolvedFile.path, resolvedFile);
5731
- resolvedFiles.push(resolvedFile);
5732
- }
5733
- __privateSet(this, _filesCache, null);
5734
- return resolvedFiles;
5735
- }, _b);
5834
+ var _a2;
5835
+ return (_a2 = __privateGet$1(this, _sorted)) != null ? _a2 : __privateSet$1(this, _sorted, [...__privateGet$1(this, _cache).values()].sort(compareFiles));
5836
+ }
5837
+ }, _cache = new WeakMap(), _sorted = new WeakMap(), _onUpsert = new WeakMap(), _FileManager_instances = new WeakSet(), store_fn = function(files, mergeExisting) {
5838
+ var _a2;
5839
+ const batch = files.length > 1 ? __privateMethod$1(this, _FileManager_instances, dedupe_fn).call(this, files) : files;
5840
+ const resolved = [];
5841
+ for (const file of batch) {
5842
+ const existing = __privateGet$1(this, _cache).get(file.path);
5843
+ const merged = existing && mergeExisting ? createFile(mergeFile(existing, file)) : createFile(file);
5844
+ __privateGet$1(this, _cache).set(merged.path, merged);
5845
+ resolved.push(merged);
5846
+ (_a2 = __privateGet$1(this, _onUpsert)) == null ? void 0 : _a2.call(this, merged);
5847
+ }
5848
+ if (resolved.length > 0) __privateSet$1(this, _sorted, null);
5849
+ return resolved;
5850
+ }, dedupe_fn = function(files) {
5851
+ const seen = /* @__PURE__ */ new Map();
5852
+ for (const file of files) {
5853
+ const prev = seen.get(file.path);
5854
+ seen.set(file.path, prev ? mergeFile(prev, file) : file);
5855
+ }
5856
+ return [...seen.values()];
5857
+ }, _c);
5858
+ function joinSources(file) {
5859
+ const sources = file.sources;
5860
+ if (sources.length === 0) return "";
5861
+ const parts = [];
5862
+ for (const source of sources) {
5863
+ const s = extractStringsFromNodes(source.nodes);
5864
+ if (s) parts.push(s);
5865
+ }
5866
+ return parts.join("\n\n");
5867
+ }
5868
+ var FileProcessor = class {
5869
+ constructor() {
5870
+ __publicField$1(this, "events", new AsyncEventEmitter());
5871
+ }
5872
+ parse(file, { parsers, extension } = {}) {
5873
+ const parseExtName = (extension == null ? void 0 : extension[file.extname]) || void 0;
5874
+ if (!parsers || !file.extname) return joinSources(file);
5875
+ const parser = parsers.get(file.extname);
5876
+ if (!parser) return joinSources(file);
5877
+ return parser.parse(file, { extname: parseExtName });
5878
+ }
5879
+ *stream(files, options = {}) {
5880
+ const total = files.length;
5881
+ if (total === 0) return;
5882
+ let processed = 0;
5883
+ for (const file of files) {
5884
+ const source = this.parse(file, options);
5885
+ processed++;
5886
+ yield {
5887
+ file,
5888
+ source,
5889
+ processed,
5890
+ total,
5891
+ percentage: processed / total * 100
5892
+ };
5893
+ }
5894
+ }
5895
+ async run(files, options = {}) {
5896
+ await this.events.emit("start", files);
5897
+ for (const { file, source, processed, total, percentage } of this.stream(files, options)) await this.events.emit("update", {
5898
+ file,
5899
+ source,
5900
+ processed,
5901
+ percentage,
5902
+ total
5903
+ });
5904
+ await this.events.emit("end", files);
5905
+ return files;
5906
+ }
5907
+ /**
5908
+ * Clears all registered event listeners.
5909
+ */
5910
+ dispose() {
5911
+ this.events.removeAll();
5912
+ }
5913
+ [Symbol.dispose]() {
5914
+ this.dispose();
5915
+ }
5916
+ };
5917
+ function _usingCtx() {
5918
+ var r = "function" == typeof SuppressedError ? SuppressedError : function(r2, e2) {
5919
+ var n2 = Error();
5920
+ return n2.name = "SuppressedError", n2.error = r2, n2.suppressed = e2, n2;
5921
+ };
5922
+ var e = {};
5923
+ var n = [];
5924
+ function using(r2, e2) {
5925
+ if (null != e2) {
5926
+ if (Object(e2) !== e2) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
5927
+ if (r2) var o = e2[Symbol.asyncDispose || Symbol["for"]("Symbol.asyncDispose")];
5928
+ if (void 0 === o && (o = e2[Symbol.dispose || Symbol["for"]("Symbol.dispose")], r2)) var t = o;
5929
+ if ("function" != typeof o) throw new TypeError("Object is not disposable.");
5930
+ t && (o = function o2() {
5931
+ try {
5932
+ t.call(e2);
5933
+ } catch (r3) {
5934
+ return Promise.reject(r3);
5935
+ }
5936
+ }), n.push({
5937
+ v: e2,
5938
+ d: o,
5939
+ a: r2
5940
+ });
5941
+ } else r2 && n.push({
5942
+ d: e2,
5943
+ a: r2
5944
+ });
5945
+ return e2;
5946
+ }
5947
+ return {
5948
+ e,
5949
+ u: using.bind(null, false),
5950
+ a: using.bind(null, true),
5951
+ d: function d() {
5952
+ var o;
5953
+ var t = this.e;
5954
+ var s = 0;
5955
+ function next() {
5956
+ for (; o = n.pop(); ) try {
5957
+ if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
5958
+ if (o.d) {
5959
+ var r2 = o.d.call(o.v);
5960
+ if (o.a) return s |= 2, Promise.resolve(r2).then(next, err);
5961
+ } else s |= 1;
5962
+ } catch (r3) {
5963
+ return err(r3);
5964
+ }
5965
+ if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
5966
+ if (t !== e) throw t;
5967
+ }
5968
+ function err(n2) {
5969
+ return t = t !== e ? new r(n2, t) : n2, next();
5970
+ }
5971
+ return next();
5972
+ }
5973
+ };
5974
+ }
5736
5975
  function enforceOrder(enforce) {
5737
5976
  return enforce === "pre" ? -1 : enforce === "post" ? 1 : 0;
5738
5977
  }
5739
- var KubbDriver = (_c = class {
5978
+ const OPERATION_FILTER_TYPES = /* @__PURE__ */ new Set([
5979
+ "tag",
5980
+ "operationId",
5981
+ "path",
5982
+ "method",
5983
+ "contentType"
5984
+ ]);
5985
+ var KubbDriver = (_d = class {
5740
5986
  constructor(config, options) {
5741
5987
  __privateAdd$1(this, _KubbDriver_instances);
5742
5988
  __publicField$1(this, "config");
@@ -5745,8 +5991,8 @@ var KubbDriver = (_c = class {
5745
5991
  * The streaming `InputStreamNode` produced by the adapter.
5746
5992
  * Always set after adapter setup — parse-only adapters are wrapped automatically.
5747
5993
  */
5748
- __publicField$1(this, "inputNode");
5749
- __publicField$1(this, "adapter");
5994
+ __publicField$1(this, "inputNode", null);
5995
+ __publicField$1(this, "adapter", null);
5750
5996
  /**
5751
5997
  * Studio session state, kept together so `dispose()` can reset it atomically.
5752
5998
  *
@@ -5757,9 +6003,9 @@ var KubbDriver = (_c = class {
5757
6003
  * per studio session, even when `openInStudio()` is called multiple times.
5758
6004
  */
5759
6005
  __privateAdd$1(this, _studio, {
5760
- source: void 0,
6006
+ source: null,
5761
6007
  isOpen: false,
5762
- inputNode: void 0
6008
+ inputNode: null
5763
6009
  });
5764
6010
  __privateAdd$1(this, _middlewareListeners, []);
5765
6011
  /**
@@ -5768,6 +6014,7 @@ var KubbDriver = (_c = class {
5768
6014
  * add files; this property gives direct read/write access when needed.
5769
6015
  */
5770
6016
  __publicField$1(this, "fileManager", new FileManager());
6017
+ __privateAdd$1(this, _fileProcessor, new FileProcessor());
5771
6018
  __publicField$1(this, "plugins", /* @__PURE__ */ new Map());
5772
6019
  /**
5773
6020
  * Tracks which plugins have generators registered via `addGenerator()` (event-based path).
@@ -5781,9 +6028,10 @@ var KubbDriver = (_c = class {
5781
6028
  name: "default",
5782
6029
  pluginName
5783
6030
  }))));
6031
+ var _a2;
5784
6032
  this.config = config;
5785
6033
  this.options = options;
5786
- this.adapter = config.adapter;
6034
+ this.adapter = (_a2 = config.adapter) != null ? _a2 : null;
5787
6035
  }
5788
6036
  /**
5789
6037
  * Returns `'single'` when `fileOrFolder` has a file extension, `'split'` otherwise.
@@ -5906,24 +6154,165 @@ var KubbDriver = (_c = class {
5906
6154
  return __privateGet$1(this, _eventGeneratorPlugins).has(pluginName);
5907
6155
  }
5908
6156
  /**
5909
- * Unregisters all plugin lifecycle listeners from the shared event emitter.
5910
- * Called at the end of a build to prevent listener leaks across repeated builds.
5911
- *
5912
- * @internal
6157
+ * Runs the full plugin pipeline. Returns timings/failures collected so far even
6158
+ * when an outer hook throws the orchestrator preserves partial state by capturing
6159
+ * the error into `error` instead of propagating.
5913
6160
  */
5914
- dispose() {
5915
- for (const [event, handlers] of __privateGet$1(this, _hookListeners)) for (const handler of handlers) this.hooks.off(event, handler);
5916
- __privateGet$1(this, _hookListeners).clear();
5917
- __privateGet$1(this, _eventGeneratorPlugins).clear();
5918
- __privateGet$1(this, _resolvers).clear();
5919
- __privateGet$1(this, _defaultResolvers).clear();
5920
- this.fileManager.dispose();
5921
- this.inputNode = void 0;
5922
- __privateSet(this, _studio, {
5923
- source: void 0,
5924
- isOpen: false,
5925
- inputNode: void 0
5926
- });
6161
+ async run({ storage }) {
6162
+ var _a2;
6163
+ const hooks = this.hooks;
6164
+ const config = this.config;
6165
+ const failedPlugins = /* @__PURE__ */ new Set();
6166
+ const pluginTimings = /* @__PURE__ */ new Map();
6167
+ const parsersMap = /* @__PURE__ */ new Map();
6168
+ for (const parser of config.parsers) if (parser.extNames) for (const ext of parser.extNames) parsersMap.set(ext, parser);
6169
+ const pendingFiles = /* @__PURE__ */ new Map();
6170
+ this.fileManager.setOnUpsert((file) => {
6171
+ pendingFiles.set(file.path, file);
6172
+ });
6173
+ try {
6174
+ const flushPending = async () => {
6175
+ if (pendingFiles.size === 0) return;
6176
+ const files2 = [...pendingFiles.values()];
6177
+ pendingFiles.clear();
6178
+ await hooks.emit("kubb:debug", {
6179
+ date: /* @__PURE__ */ new Date(),
6180
+ logs: [`Writing ${files2.length} files...`]
6181
+ });
6182
+ await hooks.emit("kubb:files:processing:start", { files: files2 });
6183
+ const items = [...__privateGet$1(this, _fileProcessor).stream(files2, {
6184
+ parsers: parsersMap,
6185
+ extension: config.output.extension
6186
+ })];
6187
+ await hooks.emit("kubb:files:processing:update", { files: items.map(({ file, source, processed, total, percentage }) => ({
6188
+ file,
6189
+ source,
6190
+ processed,
6191
+ total,
6192
+ percentage,
6193
+ config
6194
+ })) });
6195
+ const queue = [];
6196
+ for (const { file, source } of items) if (source) {
6197
+ queue.push(storage.setItem(file.path, source));
6198
+ if (queue.length >= 50) await Promise.all(queue.splice(0));
6199
+ }
6200
+ await Promise.all(queue);
6201
+ await hooks.emit("kubb:files:processing:end", { files: files2 });
6202
+ await hooks.emit("kubb:debug", {
6203
+ date: /* @__PURE__ */ new Date(),
6204
+ logs: [`\u2713 File write process completed for ${files2.length} files`]
6205
+ });
6206
+ };
6207
+ await this.emitSetupHooks();
6208
+ if (this.adapter && this.inputNode) await hooks.emit("kubb:build:start", Object.assign({
6209
+ config,
6210
+ adapter: this.adapter,
6211
+ meta: this.inputNode.meta,
6212
+ getPlugin: this.getPlugin.bind(this)
6213
+ }, __privateMethod$1(this, _KubbDriver_instances, filesPayload_fn).call(this)));
6214
+ const generatorPlugins = [];
6215
+ for (const plugin of this.plugins.values()) {
6216
+ const context = this.getContext(plugin);
6217
+ const hrStart = process.hrtime();
6218
+ try {
6219
+ await hooks.emit("kubb:plugin:start", { plugin });
6220
+ await hooks.emit("kubb:debug", {
6221
+ date: /* @__PURE__ */ new Date(),
6222
+ logs: ["Starting plugin...", ` \u2022 Plugin Name: ${plugin.name}`]
6223
+ });
6224
+ } catch (caughtError) {
6225
+ const error = caughtError;
6226
+ const duration2 = getElapsedMs(hrStart);
6227
+ pluginTimings.set(plugin.name, duration2);
6228
+ await __privateMethod$1(this, _KubbDriver_instances, emitPluginEnd_fn).call(this, {
6229
+ plugin,
6230
+ duration: duration2,
6231
+ success: false,
6232
+ error
6233
+ });
6234
+ failedPlugins.add({
6235
+ plugin,
6236
+ error
6237
+ });
6238
+ continue;
6239
+ }
6240
+ if (((_a2 = plugin.generators) == null ? void 0 : _a2.length) || this.hasEventGenerators(plugin.name)) {
6241
+ generatorPlugins.push({
6242
+ plugin,
6243
+ context,
6244
+ hrStart
6245
+ });
6246
+ continue;
6247
+ }
6248
+ const duration = getElapsedMs(hrStart);
6249
+ pluginTimings.set(plugin.name, duration);
6250
+ await __privateMethod$1(this, _KubbDriver_instances, emitPluginEnd_fn).call(this, {
6251
+ plugin,
6252
+ duration,
6253
+ success: true
6254
+ });
6255
+ await hooks.emit("kubb:debug", {
6256
+ date: /* @__PURE__ */ new Date(),
6257
+ logs: [`\u2713 Plugin started successfully (${formatMs(duration)})`]
6258
+ });
6259
+ }
6260
+ if (generatorPlugins.length > 0) if (this.inputNode) {
6261
+ const { timings, failed } = await __privateMethod$1(this, _KubbDriver_instances, runGenerators_fn).call(this, generatorPlugins, flushPending);
6262
+ await flushPending();
6263
+ for (const [name, duration] of timings) pluginTimings.set(name, duration);
6264
+ for (const entry of failed) failedPlugins.add(entry);
6265
+ } else for (const { plugin, hrStart } of generatorPlugins) {
6266
+ const duration = getElapsedMs(hrStart);
6267
+ pluginTimings.set(plugin.name, duration);
6268
+ await __privateMethod$1(this, _KubbDriver_instances, emitPluginEnd_fn).call(this, {
6269
+ plugin,
6270
+ duration,
6271
+ success: true
6272
+ });
6273
+ }
6274
+ await hooks.emit("kubb:plugins:end", Object.assign({ config }, __privateMethod$1(this, _KubbDriver_instances, filesPayload_fn).call(this)));
6275
+ await flushPending();
6276
+ const files = this.fileManager.files;
6277
+ await hooks.emit("kubb:build:end", {
6278
+ files,
6279
+ config,
6280
+ outputDir: resolve(config.root, config.output.path)
6281
+ });
6282
+ return {
6283
+ failedPlugins,
6284
+ pluginTimings
6285
+ };
6286
+ } catch (caughtError) {
6287
+ return {
6288
+ failedPlugins,
6289
+ pluginTimings,
6290
+ error: caughtError
6291
+ };
6292
+ } finally {
6293
+ this.fileManager.setOnUpsert(null);
6294
+ }
6295
+ }
6296
+ /**
6297
+ * Unregisters all plugin lifecycle listeners from the shared event emitter.
6298
+ * Called at the end of a build to prevent listener leaks across repeated builds.
6299
+ *
6300
+ * @internal
6301
+ */
6302
+ dispose() {
6303
+ for (const [event, handlers] of __privateGet$1(this, _hookListeners)) for (const handler of handlers) this.hooks.off(event, handler);
6304
+ __privateGet$1(this, _hookListeners).clear();
6305
+ __privateGet$1(this, _eventGeneratorPlugins).clear();
6306
+ __privateGet$1(this, _resolvers).clear();
6307
+ __privateGet$1(this, _defaultResolvers).clear();
6308
+ this.fileManager.dispose();
6309
+ __privateGet$1(this, _fileProcessor).dispose();
6310
+ this.inputNode = null;
6311
+ __privateSet$1(this, _studio, {
6312
+ source: null,
6313
+ isOpen: false,
6314
+ inputNode: null
6315
+ });
5927
6316
  for (const [event, handler] of __privateGet$1(this, _middlewareListeners)) this.hooks.off(event, handler);
5928
6317
  }
5929
6318
  [Symbol.dispose]() {
@@ -5955,7 +6344,7 @@ var KubbDriver = (_c = class {
5955
6344
  return resolve(driver.config.root, driver.config.output.path);
5956
6345
  },
5957
6346
  getMode(output) {
5958
- return _c.getMode(resolve(driver.config.root, driver.config.output.path, output.path));
6347
+ return _d.getMode(resolve(driver.config.root, driver.config.output.path, output.path));
5959
6348
  },
5960
6349
  hooks: driver.hooks,
5961
6350
  plugin,
@@ -5995,13 +6384,13 @@ var KubbDriver = (_c = class {
5995
6384
  driver.hooks.emit("kubb:info", { message });
5996
6385
  },
5997
6386
  async openInStudio(options) {
5998
- var _a2, _b2, _c2, _d;
6387
+ var _a2, _b2, _c2, _d2;
5999
6388
  if (!driver.config.devtools || __privateGet$1(driver, _studio).isOpen) return;
6000
6389
  if (typeof driver.config.devtools !== "object") throw new Error("Devtools must be an object");
6001
6390
  if (!driver.adapter || !__privateGet$1(driver, _studio).source) throw new Error("adapter is not defined, make sure you have set the parser in kubb.config.ts");
6002
6391
  __privateGet$1(driver, _studio).isOpen = true;
6003
6392
  const studioUrl = (_b2 = (_a2 = driver.config.devtools) == null ? void 0 : _a2.studioUrl) != null ? _b2 : "https://kubb.studio";
6004
- (_d = (_c2 = __privateGet$1(driver, _studio)).inputNode) != null ? _d : _c2.inputNode = Promise.resolve(driver.adapter.parse(__privateGet$1(driver, _studio).source));
6393
+ (_d2 = (_c2 = __privateGet$1(driver, _studio)).inputNode) != null ? _d2 : _c2.inputNode = Promise.resolve(driver.adapter.parse(__privateGet$1(driver, _studio).source));
6005
6394
  return openInStudio(await __privateGet$1(driver, _studio).inputNode, studioUrl, options);
6006
6395
  }
6007
6396
  };
@@ -6014,7 +6403,7 @@ var KubbDriver = (_c = class {
6014
6403
  if (!plugin) throw new Error(`[kubb] Plugin "${pluginName}" is required but not found. Make sure it is included in your Kubb config.`);
6015
6404
  return plugin;
6016
6405
  }
6017
- }, _studio = new WeakMap(), _middlewareListeners = new WeakMap(), _eventGeneratorPlugins = new WeakMap(), _resolvers = new WeakMap(), _defaultResolvers = new WeakMap(), _hookListeners = new WeakMap(), _KubbDriver_instances = new WeakSet(), /**
6406
+ }, _studio = new WeakMap(), _middlewareListeners = new WeakMap(), _fileProcessor = new WeakMap(), _eventGeneratorPlugins = new WeakMap(), _resolvers = new WeakMap(), _defaultResolvers = new WeakMap(), _hookListeners = new WeakMap(), _KubbDriver_instances = new WeakSet(), /**
6018
6407
  * Creates an `NormalizedPlugin` from a hook-style plugin and registers
6019
6408
  * its lifecycle handlers on the `AsyncEventEmitter`.
6020
6409
  */
@@ -6115,6 +6504,208 @@ registerPlugin_fn = function(plugin) {
6115
6504
  this.hooks.on(event, handler);
6116
6505
  __privateMethod$1(this, _KubbDriver_instances, trackHookListener_fn).call(this, event, handler);
6117
6506
  }
6507
+ }, filesPayload_fn = function() {
6508
+ const driver = this;
6509
+ return {
6510
+ get files() {
6511
+ return driver.fileManager.files;
6512
+ },
6513
+ upsertFile: (...files) => driver.fileManager.upsert(...files)
6514
+ };
6515
+ }, emitPluginEnd_fn = function({ plugin, duration, success, error }) {
6516
+ return this.hooks.emit("kubb:plugin:end", Object.assign({
6517
+ plugin,
6518
+ duration,
6519
+ success,
6520
+ ...error ? { error } : {},
6521
+ config: this.config
6522
+ }, __privateMethod$1(this, _KubbDriver_instances, filesPayload_fn).call(this)));
6523
+ }, runGenerators_fn = async function(entries, flushPending) {
6524
+ var _a2, _b2;
6525
+ const timings = /* @__PURE__ */ new Map();
6526
+ const failed = /* @__PURE__ */ new Set();
6527
+ const driver = this;
6528
+ const { schemas, operations } = this.inputNode;
6529
+ const states = entries.map(({ plugin, context, hrStart }) => {
6530
+ var _a3;
6531
+ const { exclude, include, override } = plugin.options;
6532
+ const hasExclude = Array.isArray(exclude) && exclude.length > 0;
6533
+ const hasInclude = Array.isArray(include) && include.length > 0;
6534
+ const hasOverride = Array.isArray(override) && override.length > 0;
6535
+ return {
6536
+ plugin,
6537
+ generatorContext: {
6538
+ ...context,
6539
+ resolver: this.getResolver(plugin.name)
6540
+ },
6541
+ generators: (_a3 = plugin.generators) != null ? _a3 : [],
6542
+ hrStart,
6543
+ failed: false,
6544
+ error: null,
6545
+ optionsAreStatic: !hasExclude && !hasInclude && !hasOverride,
6546
+ allowedSchemaNames: null
6547
+ };
6548
+ });
6549
+ const emitsSchemaHook = this.hooks.listenerCount("kubb:generate:schema") > 0;
6550
+ const emitsOperationHook = this.hooks.listenerCount("kubb:generate:operation") > 0;
6551
+ const pruningStates = states.filter(({ plugin }) => {
6552
+ var _a3, _b3;
6553
+ const { include } = plugin.options;
6554
+ return ((_a3 = include == null ? void 0 : include.some(({ type }) => OPERATION_FILTER_TYPES.has(type))) != null ? _a3 : false) && !((_b3 = include == null ? void 0 : include.some(({ type }) => type === "schemaName")) != null ? _b3 : false);
6555
+ });
6556
+ if (pruningStates.length > 0) {
6557
+ const allSchemas = [];
6558
+ for await (const schema of schemas) allSchemas.push(schema);
6559
+ const includedOpsByState = new Map(pruningStates.map((s) => [s, []]));
6560
+ for await (const operation of operations) for (const state of pruningStates) {
6561
+ const { exclude, include, override } = state.plugin.options;
6562
+ if (state.generatorContext.resolver.resolveOptions(operation, {
6563
+ options: state.plugin.options,
6564
+ exclude,
6565
+ include,
6566
+ override
6567
+ }) !== null) (_a2 = includedOpsByState.get(state)) == null ? void 0 : _a2.push(operation);
6568
+ }
6569
+ for (const state of pruningStates) {
6570
+ state.allowedSchemaNames = collectUsedSchemaNames((_b2 = includedOpsByState.get(state)) != null ? _b2 : [], allSchemas);
6571
+ includedOpsByState.delete(state);
6572
+ }
6573
+ }
6574
+ const resolveRendererFor = (gen, state) => {
6575
+ var _a3, _b3;
6576
+ return gen.renderer === null ? void 0 : (_b3 = (_a3 = gen.renderer) != null ? _a3 : state.plugin.renderer) != null ? _b3 : state.generatorContext.config.renderer;
6577
+ };
6578
+ const dispatchSchema = async (state, node) => {
6579
+ if (state.failed) return;
6580
+ try {
6581
+ const { plugin, generatorContext, generators } = state;
6582
+ const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
6583
+ if (state.allowedSchemaNames !== null && transformedNode.name && !state.allowedSchemaNames.has(transformedNode.name)) return;
6584
+ const { exclude, include, override } = plugin.options;
6585
+ const options = state.optionsAreStatic ? plugin.options : generatorContext.resolver.resolveOptions(transformedNode, {
6586
+ options: plugin.options,
6587
+ exclude,
6588
+ include,
6589
+ override
6590
+ });
6591
+ if (options === null) return;
6592
+ const ctx = {
6593
+ ...generatorContext,
6594
+ options
6595
+ };
6596
+ for (const gen of generators) {
6597
+ if (!gen.schema) continue;
6598
+ const raw = gen.schema(transformedNode, ctx);
6599
+ const applied = applyHookResult({
6600
+ result: isPromise(raw) ? await raw : raw,
6601
+ driver,
6602
+ rendererFactory: resolveRendererFor(gen, state)
6603
+ });
6604
+ if (isPromise(applied)) await applied;
6605
+ }
6606
+ if (emitsSchemaHook) await this.hooks.emit("kubb:generate:schema", transformedNode, ctx);
6607
+ } catch (caughtError) {
6608
+ state.failed = true;
6609
+ state.error = caughtError;
6610
+ }
6611
+ };
6612
+ const dispatchOperation = async (state, node) => {
6613
+ if (state.failed) return;
6614
+ try {
6615
+ const { plugin, generatorContext, generators } = state;
6616
+ const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
6617
+ const { exclude, include, override } = plugin.options;
6618
+ const options = state.optionsAreStatic ? plugin.options : generatorContext.resolver.resolveOptions(transformedNode, {
6619
+ options: plugin.options,
6620
+ exclude,
6621
+ include,
6622
+ override
6623
+ });
6624
+ if (options === null) return;
6625
+ const ctx = {
6626
+ ...generatorContext,
6627
+ options
6628
+ };
6629
+ for (const gen of generators) {
6630
+ if (!gen.operation) continue;
6631
+ const raw = gen.operation(transformedNode, ctx);
6632
+ const applied = applyHookResult({
6633
+ result: isPromise(raw) ? await raw : raw,
6634
+ driver,
6635
+ rendererFactory: resolveRendererFor(gen, state)
6636
+ });
6637
+ if (isPromise(applied)) await applied;
6638
+ }
6639
+ if (emitsOperationHook) await this.hooks.emit("kubb:generate:operation", transformedNode, ctx);
6640
+ } catch (caughtError) {
6641
+ state.failed = true;
6642
+ state.error = caughtError;
6643
+ }
6644
+ };
6645
+ const needsCollectedOperations = this.hooks.listenerCount("kubb:generate:operations") > 0 || states.some((s) => s.generators.some((g) => !!g.operations));
6646
+ const collectedOperations = needsCollectedOperations ? [] : void 0;
6647
+ await forBatches(schemas, (nodes) => Promise.all(nodes.flatMap((n) => states.map((state) => dispatchSchema(state, n)))), {
6648
+ concurrency: 8,
6649
+ flush: flushPending
6650
+ });
6651
+ await forBatches(operations, (nodes) => {
6652
+ if (needsCollectedOperations) collectedOperations.push(...nodes);
6653
+ return Promise.all(nodes.flatMap((n) => states.map((state) => dispatchOperation(state, n))));
6654
+ }, {
6655
+ concurrency: 8,
6656
+ flush: flushPending
6657
+ });
6658
+ for (const state of states) {
6659
+ if (!state.failed && needsCollectedOperations) try {
6660
+ const { plugin, generatorContext, generators } = state;
6661
+ const ctx = {
6662
+ ...generatorContext,
6663
+ options: plugin.options
6664
+ };
6665
+ const pluginOperations = state.optionsAreStatic ? collectedOperations : collectedOperations.filter((node) => {
6666
+ const transformed = plugin.transformer ? transform(node, plugin.transformer) : node;
6667
+ const { exclude, include, override } = plugin.options;
6668
+ return generatorContext.resolver.resolveOptions(transformed, {
6669
+ options: plugin.options,
6670
+ exclude,
6671
+ include,
6672
+ override
6673
+ }) !== null;
6674
+ });
6675
+ for (const gen of generators) {
6676
+ if (!gen.operations) continue;
6677
+ await applyHookResult({
6678
+ result: await gen.operations(pluginOperations, ctx),
6679
+ driver,
6680
+ rendererFactory: resolveRendererFor(gen, state)
6681
+ });
6682
+ }
6683
+ await this.hooks.emit("kubb:generate:operations", pluginOperations, ctx);
6684
+ } catch (caughtError) {
6685
+ state.failed = true;
6686
+ state.error = caughtError;
6687
+ }
6688
+ const duration = getElapsedMs(state.hrStart);
6689
+ timings.set(state.plugin.name, duration);
6690
+ await __privateMethod$1(this, _KubbDriver_instances, emitPluginEnd_fn).call(this, {
6691
+ plugin: state.plugin,
6692
+ duration,
6693
+ success: !state.failed,
6694
+ error: state.failed && state.error ? state.error : void 0
6695
+ });
6696
+ if (state.failed && state.error) failed.add({
6697
+ plugin: state.plugin,
6698
+ error: state.error
6699
+ });
6700
+ await this.hooks.emit("kubb:debug", {
6701
+ date: /* @__PURE__ */ new Date(),
6702
+ logs: [state.failed ? "\u2717 Plugin start failed" : `\u2713 Plugin started successfully (${formatMs(duration)})`]
6703
+ });
6704
+ }
6705
+ return {
6706
+ timings,
6707
+ failed
6708
+ };
6118
6709
  }, trackHookListener_fn = function(event, handler) {
6119
6710
  let handlers = __privateGet$1(this, _hookListeners).get(event);
6120
6711
  if (!handlers) {
@@ -6122,7 +6713,7 @@ registerPlugin_fn = function(plugin) {
6122
6713
  __privateGet$1(this, _hookListeners).set(event, handlers);
6123
6714
  }
6124
6715
  handlers.add(handler);
6125
- }, _getDefaultResolver = new WeakMap(), _c);
6716
+ }, _getDefaultResolver = new WeakMap(), _d);
6126
6717
  function applyHookResult({ result, driver, rendererFactory }) {
6127
6718
  if (!result) return;
6128
6719
  if (Array.isArray(result)) {
@@ -6131,10 +6722,15 @@ function applyHookResult({ result, driver, rendererFactory }) {
6131
6722
  }
6132
6723
  if (!rendererFactory) return;
6133
6724
  const renderer = rendererFactory();
6134
- if (renderer.stream) {
6135
- for (const file of renderer.stream(result)) driver.fileManager.upsert(file);
6136
- renderer.unmount();
6725
+ if (renderer.stream) try {
6726
+ var _usingCtx$1 = _usingCtx();
6727
+ const r = _usingCtx$1.u(renderer);
6728
+ for (const file of r.stream(result)) driver.fileManager.upsert(file);
6137
6729
  return;
6730
+ } catch (_) {
6731
+ _usingCtx$1.e = _;
6732
+ } finally {
6733
+ _usingCtx$1.d();
6138
6734
  }
6139
6735
  return applyAsyncRender({
6140
6736
  renderer,
@@ -6143,9 +6739,16 @@ function applyHookResult({ result, driver, rendererFactory }) {
6143
6739
  });
6144
6740
  }
6145
6741
  async function applyAsyncRender({ renderer, result, driver }) {
6146
- await renderer.render(result);
6147
- driver.fileManager.upsert(...renderer.files);
6148
- renderer.unmount();
6742
+ try {
6743
+ var _usingCtx3 = _usingCtx();
6744
+ const r = _usingCtx3.u(renderer);
6745
+ await r.render(result);
6746
+ driver.fileManager.upsert(...r.files);
6747
+ } catch (_) {
6748
+ _usingCtx3.e = _;
6749
+ } finally {
6750
+ _usingCtx3.d();
6751
+ }
6149
6752
  }
6150
6753
  function inputToAdapterSource(config) {
6151
6754
  const input = config.input;
@@ -6169,130 +6772,13 @@ var __typeError = (msg) => {
6169
6772
  throw TypeError(msg);
6170
6773
  };
6171
6774
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6172
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
6775
+ var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
6173
6776
  var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
6174
6777
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
6175
6778
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
6779
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
6176
6780
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
6177
- var _emitter, _AsyncEventEmitter_instances, emitAll_fn, _a;
6178
- var BuildError = class extends Error {
6179
- constructor(message, options) {
6180
- super(message, { cause: options.cause });
6181
- __publicField(this, "errors");
6182
- this.name = "BuildError";
6183
- this.errors = options.errors;
6184
- }
6185
- };
6186
- function toError(value) {
6187
- return value instanceof Error ? value : new Error(String(value));
6188
- }
6189
- var AsyncEventEmitter = (_a = class {
6190
- /**
6191
- * Maximum number of listeners per event before Node emits a memory-leak warning.
6192
- * @default 10
6193
- */
6194
- constructor(maxListener = 10) {
6195
- __privateAdd(this, _AsyncEventEmitter_instances);
6196
- __privateAdd(this, _emitter, new EventEmitter());
6197
- __privateGet(this, _emitter).setMaxListeners(maxListener);
6198
- }
6199
- /**
6200
- * Emits `eventName` and awaits all registered listeners sequentially.
6201
- * Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
6202
- *
6203
- * @example
6204
- * ```ts
6205
- * await emitter.emit('build', 'petstore')
6206
- * ```
6207
- */
6208
- emit(eventName, ...eventArgs) {
6209
- const listeners = __privateGet(this, _emitter).listeners(eventName);
6210
- if (listeners.length === 0) return;
6211
- return __privateMethod(this, _AsyncEventEmitter_instances, emitAll_fn).call(this, eventName, listeners, eventArgs);
6212
- }
6213
- /**
6214
- * Registers a persistent listener for `eventName`.
6215
- *
6216
- * @example
6217
- * ```ts
6218
- * emitter.on('build', async (name) => { console.log(name) })
6219
- * ```
6220
- */
6221
- on(eventName, handler) {
6222
- __privateGet(this, _emitter).on(eventName, handler);
6223
- }
6224
- /**
6225
- * Registers a one-shot listener that removes itself after the first invocation.
6226
- *
6227
- * @example
6228
- * ```ts
6229
- * emitter.onOnce('build', async (name) => { console.log(name) })
6230
- * ```
6231
- */
6232
- onOnce(eventName, handler) {
6233
- const wrapper = (...args) => {
6234
- this.off(eventName, wrapper);
6235
- return handler(...args);
6236
- };
6237
- this.on(eventName, wrapper);
6238
- }
6239
- /**
6240
- * Removes a previously registered listener.
6241
- *
6242
- * @example
6243
- * ```ts
6244
- * emitter.off('build', handler)
6245
- * ```
6246
- */
6247
- off(eventName, handler) {
6248
- __privateGet(this, _emitter).off(eventName, handler);
6249
- }
6250
- /**
6251
- * Returns the number of listeners registered for `eventName`.
6252
- *
6253
- * @example
6254
- * ```ts
6255
- * emitter.on('build', handler)
6256
- * emitter.listenerCount('build') // 1
6257
- * ```
6258
- */
6259
- listenerCount(eventName) {
6260
- return __privateGet(this, _emitter).listenerCount(eventName);
6261
- }
6262
- /**
6263
- * Removes all listeners from every event channel.
6264
- *
6265
- * @example
6266
- * ```ts
6267
- * emitter.removeAll()
6268
- * ```
6269
- */
6270
- removeAll() {
6271
- __privateGet(this, _emitter).removeAllListeners();
6272
- }
6273
- }, _emitter = new WeakMap(), _AsyncEventEmitter_instances = new WeakSet(), emitAll_fn = async function(eventName, listeners, eventArgs) {
6274
- for (const listener of listeners) try {
6275
- await listener(...eventArgs);
6276
- } catch (err) {
6277
- let serializedArgs;
6278
- try {
6279
- serializedArgs = JSON.stringify(eventArgs);
6280
- } catch {
6281
- serializedArgs = String(eventArgs);
6282
- }
6283
- throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
6284
- }
6285
- }, _a);
6286
- function getElapsedMs(hrStart) {
6287
- const [seconds, nanoseconds] = process.hrtime(hrStart);
6288
- const ms = seconds * 1e3 + nanoseconds / 1e6;
6289
- return Math.round(ms * 100) / 100;
6290
- }
6291
- function formatMs(ms) {
6292
- if (ms >= 6e4) return `${Math.floor(ms / 6e4)}m ${(ms % 6e4 / 1e3).toFixed(1)}s`;
6293
- if (ms >= 1e3) return `${(ms / 1e3).toFixed(2)}s`;
6294
- return `${Math.round(ms)}ms`;
6295
- }
6781
+ var _userConfig, _config, _driver, _storage, _Kubb_instances, configLogs_fn, _a;
6296
6782
  async function exists(path) {
6297
6783
  if (typeof Bun !== "undefined") return Bun.file(path).exists();
6298
6784
  return access(path).then(() => true, () => false);
@@ -6333,60 +6819,10 @@ async function clean(path) {
6333
6819
  force: true
6334
6820
  });
6335
6821
  }
6336
- var version$1 = "5.0.0-beta.20";
6337
- function createStorage(build2) {
6338
- return (options) => build2(options != null ? options : {});
6822
+ var version$1 = "5.0.0-beta.22";
6823
+ function createStorage(build) {
6824
+ return (options) => build(options != null ? options : {});
6339
6825
  }
6340
- function joinSources(file) {
6341
- const sources = file.sources;
6342
- if (sources.length === 0) return "";
6343
- const parts = [];
6344
- for (const source of sources) {
6345
- const s = extractStringsFromNodes(source.nodes);
6346
- if (s) parts.push(s);
6347
- }
6348
- return parts.join("\n\n");
6349
- }
6350
- var FileProcessor = class {
6351
- constructor() {
6352
- __publicField(this, "events", new AsyncEventEmitter());
6353
- }
6354
- parse(file, { parsers, extension } = {}) {
6355
- const parseExtName = (extension == null ? void 0 : extension[file.extname]) || void 0;
6356
- if (!parsers || !file.extname) return joinSources(file);
6357
- const parser = parsers.get(file.extname);
6358
- if (!parser) return joinSources(file);
6359
- return parser.parse(file, { extname: parseExtName });
6360
- }
6361
- *stream(files, options = {}) {
6362
- const total = files.length;
6363
- if (total === 0) return;
6364
- let processed = 0;
6365
- for (const file of files) {
6366
- const source = this.parse(file, options);
6367
- processed++;
6368
- yield {
6369
- file,
6370
- source,
6371
- processed,
6372
- total,
6373
- percentage: processed / total * 100
6374
- };
6375
- }
6376
- }
6377
- async run(files, options = {}) {
6378
- await this.events.emit("start", files);
6379
- for (const { file, source, processed, total, percentage } of this.stream(files, options)) await this.events.emit("update", {
6380
- file,
6381
- source,
6382
- processed,
6383
- percentage,
6384
- total
6385
- });
6386
- await this.events.emit("end", files);
6387
- return files;
6388
- }
6389
- };
6390
6826
  const fsStorage = createStorage(() => ({
6391
6827
  name: "fs",
6392
6828
  async hasItem(key) {
@@ -6434,64 +6870,6 @@ const fsStorage = createStorage(() => ({
6434
6870
  await clean(resolve(base));
6435
6871
  }
6436
6872
  }));
6437
- function _usingCtx() {
6438
- var r = "function" == typeof SuppressedError ? SuppressedError : function(r2, e2) {
6439
- var n2 = Error();
6440
- return n2.name = "SuppressedError", n2.error = r2, n2.suppressed = e2, n2;
6441
- };
6442
- var e = {};
6443
- var n = [];
6444
- function using(r2, e2) {
6445
- if (null != e2) {
6446
- if (Object(e2) !== e2) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
6447
- if (r2) var o = e2[Symbol.asyncDispose || Symbol["for"]("Symbol.asyncDispose")];
6448
- if (void 0 === o && (o = e2[Symbol.dispose || Symbol["for"]("Symbol.dispose")], r2)) var t = o;
6449
- if ("function" != typeof o) throw new TypeError("Object is not disposable.");
6450
- t && (o = function o2() {
6451
- try {
6452
- t.call(e2);
6453
- } catch (r3) {
6454
- return Promise.reject(r3);
6455
- }
6456
- }), n.push({
6457
- v: e2,
6458
- d: o,
6459
- a: r2
6460
- });
6461
- } else r2 && n.push({
6462
- d: e2,
6463
- a: r2
6464
- });
6465
- return e2;
6466
- }
6467
- return {
6468
- e,
6469
- u: using.bind(null, false),
6470
- a: using.bind(null, true),
6471
- d: function d() {
6472
- var o;
6473
- var t = this.e;
6474
- var s = 0;
6475
- function next() {
6476
- for (; o = n.pop(); ) try {
6477
- if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
6478
- if (o.d) {
6479
- var r2 = o.d.call(o.v);
6480
- if (o.a) return s |= 2, Promise.resolve(r2).then(next, err);
6481
- } else s |= 1;
6482
- } catch (r3) {
6483
- return err(r3);
6484
- }
6485
- if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
6486
- if (t !== e) throw t;
6487
- }
6488
- function err(n2) {
6489
- return t = t !== e ? new r(n2, t) : n2, next();
6490
- }
6491
- return next();
6492
- }
6493
- };
6494
- }
6495
6873
  function createSourcesView(storage) {
6496
6874
  const paths = /* @__PURE__ */ new Set();
6497
6875
  return createStorage(() => ({
@@ -6522,13 +6900,12 @@ function createSourcesView(storage) {
6522
6900
  }
6523
6901
  }))();
6524
6902
  }
6525
- async function setup(userConfig, options = {}) {
6526
- var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
6527
- const hooks = (_a2 = options.hooks) != null ? _a2 : new AsyncEventEmitter();
6528
- const config = {
6903
+ function resolveConfig(userConfig) {
6904
+ var _a2, _b, _c;
6905
+ return {
6529
6906
  ...userConfig,
6530
6907
  root: userConfig.root || process.cwd(),
6531
- parsers: (_b = userConfig.parsers) != null ? _b : [],
6908
+ parsers: (_a2 = userConfig.parsers) != null ? _a2 : [],
6532
6909
  output: {
6533
6910
  format: false,
6534
6911
  lint: false,
@@ -6536,474 +6913,149 @@ async function setup(userConfig, options = {}) {
6536
6913
  defaultBanner: DEFAULT_BANNER,
6537
6914
  ...userConfig.output
6538
6915
  },
6539
- storage: (_c = userConfig.storage) != null ? _c : fsStorage(),
6916
+ storage: (_b = userConfig.storage) != null ? _b : fsStorage(),
6540
6917
  devtools: userConfig.devtools ? {
6541
6918
  studioUrl: DEFAULT_STUDIO_URL,
6542
6919
  ...typeof userConfig.devtools === "boolean" ? {} : userConfig.devtools
6543
6920
  } : void 0,
6544
- plugins: (_d = userConfig.plugins) != null ? _d : []
6921
+ plugins: (_c = userConfig.plugins) != null ? _c : []
6545
6922
  };
6546
- const driver = new KubbDriver(config, { hooks });
6547
- const storage = createSourcesView(config.storage);
6548
- const diagnosticInfo = getDiagnosticInfo();
6549
- await hooks.emit("kubb:debug", {
6550
- date: /* @__PURE__ */ new Date(),
6551
- logs: [
6552
- "Configuration:",
6553
- ` \u2022 Name: ${userConfig.name || "unnamed"}`,
6554
- ` \u2022 Root: ${userConfig.root || process.cwd()}`,
6555
- ` \u2022 Output: ${((_e = userConfig.output) == null ? void 0 : _e.path) || "not specified"}`,
6556
- ` \u2022 Plugins: ${((_f = userConfig.plugins) == null ? void 0 : _f.length) || 0}`,
6557
- "Output Settings:",
6558
- ` \u2022 Storage: ${config.storage.name}`,
6559
- ` \u2022 Formatter: ${((_g = userConfig.output) == null ? void 0 : _g.format) || "none"}`,
6560
- ` \u2022 Linter: ${((_h = userConfig.output) == null ? void 0 : _h.lint) || "none"}`,
6561
- `Running adapter: ${((_i = config.adapter) == null ? void 0 : _i.name) || "none"}`,
6562
- "Environment:",
6563
- Object.entries(diagnosticInfo).map(([key, value]) => ` \u2022 ${key}: ${value}`).join("\n")
6564
- ]
6565
- });
6566
- try {
6567
- if (isInputPath(userConfig) && !new URLPath(userConfig.input.path).isURL) {
6568
- await exists(userConfig.input.path);
6569
- await hooks.emit("kubb:debug", {
6570
- date: /* @__PURE__ */ new Date(),
6571
- logs: [`\u2713 Input file validated: ${userConfig.input.path}`]
6572
- });
6573
- }
6574
- } catch (caughtError) {
6575
- if (isInputPath(userConfig)) {
6576
- const error = caughtError;
6577
- throw new Error(`Cannot read file/URL defined in \`input.path\` or set with \`kubb generate PATH\` in the CLI of your Kubb config ${userConfig.input.path}`, { cause: error });
6578
- }
6579
- }
6580
- if (config.output.clean) {
6581
- await hooks.emit("kubb:debug", {
6582
- date: /* @__PURE__ */ new Date(),
6583
- logs: ["Cleaning output directories", ` \u2022 Output: ${config.output.path}`]
6584
- });
6585
- await config.storage.clear(resolve(config.root, config.output.path));
6586
- }
6587
- await driver.setup();
6923
+ }
6924
+ function getDiagnosticInfo() {
6588
6925
  return {
6589
- config,
6590
- hooks,
6591
- driver,
6592
- storage,
6593
- dispose,
6594
- [Symbol.dispose]: dispose
6926
+ nodeVersion: version$2,
6927
+ KubbVersion: version$1,
6928
+ platform: process.platform,
6929
+ arch: process.arch,
6930
+ cwd: process.cwd()
6595
6931
  };
6596
- function dispose() {
6597
- driver.dispose();
6598
- }
6599
6932
  }
6600
- async function safeBuild(setupResult) {
6601
- var _a2;
6602
- try {
6603
- var _usingCtx$1 = _usingCtx();
6604
- _usingCtx$1.u(setupResult);
6605
- const { driver, hooks, storage } = setupResult;
6606
- const failedPlugins = /* @__PURE__ */ new Set();
6607
- const pluginTimings = /* @__PURE__ */ new Map();
6608
- const config = driver.config;
6609
- const writtenPaths = /* @__PURE__ */ new Set();
6610
- const parsersMap = /* @__PURE__ */ new Map();
6611
- const fileProcessor = new FileProcessor();
6612
- for (const parser of config.parsers) if (parser.extNames) for (const extname of parser.extNames) parsersMap.set(extname, parser);
6613
- async function flushPendingFiles() {
6614
- const files = driver.fileManager.files.filter((f) => !writtenPaths.has(f.path));
6615
- if (files.length === 0) return;
6616
- await hooks.emit("kubb:debug", {
6933
+ function isInputPath(config) {
6934
+ return typeof (config == null ? void 0 : config.input) === "object" && config.input !== null && "path" in config.input;
6935
+ }
6936
+ var Kubb = (_a = class {
6937
+ constructor(userConfig, options = {}) {
6938
+ __privateAdd(this, _Kubb_instances);
6939
+ __publicField(this, "hooks");
6940
+ __privateAdd(this, _userConfig);
6941
+ __privateAdd(this, _config, null);
6942
+ __privateAdd(this, _driver, null);
6943
+ __privateAdd(this, _storage, null);
6944
+ var _a2;
6945
+ __privateSet(this, _userConfig, userConfig);
6946
+ this.hooks = (_a2 = options.hooks) != null ? _a2 : new AsyncEventEmitter();
6947
+ }
6948
+ get storage() {
6949
+ if (!__privateGet(this, _storage)) throw new Error("[kubb] setup() must be called before accessing storage");
6950
+ return __privateGet(this, _storage);
6951
+ }
6952
+ get driver() {
6953
+ if (!__privateGet(this, _driver)) throw new Error("[kubb] setup() must be called before accessing driver");
6954
+ return __privateGet(this, _driver);
6955
+ }
6956
+ get config() {
6957
+ if (!__privateGet(this, _config)) throw new Error("[kubb] setup() must be called before accessing config");
6958
+ return __privateGet(this, _config);
6959
+ }
6960
+ /**
6961
+ * Resolves config and initializes the driver. `build()` calls this automatically.
6962
+ */
6963
+ async setup() {
6964
+ const config = resolveConfig(__privateGet(this, _userConfig));
6965
+ const driver = new KubbDriver(config, { hooks: this.hooks });
6966
+ const storage = createSourcesView(config.storage);
6967
+ await this.hooks.emit("kubb:debug", {
6968
+ date: /* @__PURE__ */ new Date(),
6969
+ logs: __privateMethod(this, _Kubb_instances, configLogs_fn).call(this, config)
6970
+ });
6971
+ if (isInputPath(__privateGet(this, _userConfig)) && !new URLPath(__privateGet(this, _userConfig).input.path).isURL) try {
6972
+ await exists(__privateGet(this, _userConfig).input.path);
6973
+ await this.hooks.emit("kubb:debug", {
6617
6974
  date: /* @__PURE__ */ new Date(),
6618
- logs: [`Writing ${files.length} files...`]
6975
+ logs: [`\u2713 Input file validated: ${__privateGet(this, _userConfig).input.path}`]
6619
6976
  });
6620
- await hooks.emit("kubb:files:processing:start", { files });
6621
- const stream = fileProcessor.stream(files, {
6622
- parsers: parsersMap,
6623
- extension: config.output.extension
6624
- });
6625
- const queue = [];
6626
- for (const { file, source, processed, total, percentage } of stream) {
6627
- writtenPaths.add(file.path);
6628
- queue.push((async () => {
6629
- await hooks.emit("kubb:file:processing:update", {
6630
- file,
6631
- source,
6632
- processed,
6633
- total,
6634
- percentage,
6635
- config
6636
- });
6637
- if (source) await storage.setItem(file.path, source);
6638
- })());
6639
- if (queue.length >= 50) await Promise.all(queue.splice(0));
6640
- }
6641
- await Promise.all(queue);
6642
- await hooks.emit("kubb:files:processing:end", { files });
6643
- await hooks.emit("kubb:debug", {
6977
+ } catch (caughtError) {
6978
+ throw new Error(`Cannot read file/URL defined in \`input.path\` or set with \`kubb generate PATH\` in the CLI of your Kubb config ${__privateGet(this, _userConfig).input.path}`, { cause: caughtError });
6979
+ }
6980
+ if (config.output.clean) {
6981
+ await this.hooks.emit("kubb:debug", {
6644
6982
  date: /* @__PURE__ */ new Date(),
6645
- logs: [`\u2713 File write process completed for ${files.length} files`]
6983
+ logs: ["Cleaning output directories", ` \u2022 Output: ${config.output.path}`]
6646
6984
  });
6985
+ await config.storage.clear(resolve(config.root, config.output.path));
6647
6986
  }
6648
- async function dispatchOperationsToGenerators(generators, collectedOperations, ctx, rendererFor) {
6649
- for (const gen of generators) {
6650
- if (!gen.operations) continue;
6651
- await applyHookResult({
6652
- result: await gen.operations(collectedOperations, ctx),
6653
- driver,
6654
- rendererFactory: rendererFor(gen)
6655
- });
6656
- }
6657
- await driver.hooks.emit("kubb:generate:operations", collectedOperations, ctx);
6658
- }
6659
- async function runPlugins(entries) {
6660
- var _a3, _b;
6661
- const { schemas, operations } = driver.inputNode;
6662
- const operationFilterTypes = /* @__PURE__ */ new Set([
6663
- "tag",
6664
- "operationId",
6665
- "path",
6666
- "method",
6667
- "contentType"
6668
- ]);
6669
- const states = entries.map(({ plugin, context, hrStart }) => {
6670
- var _a4;
6671
- const { exclude, include, override } = plugin.options;
6672
- const hasExclude = Array.isArray(exclude) && exclude.length > 0;
6673
- const hasInclude = Array.isArray(include) && include.length > 0;
6674
- const hasOverride = Array.isArray(override) && override.length > 0;
6675
- return {
6676
- plugin,
6677
- generatorContext: {
6678
- ...context,
6679
- resolver: driver.getResolver(plugin.name)
6680
- },
6681
- generators: (_a4 = plugin.generators) != null ? _a4 : [],
6682
- hrStart,
6683
- failed: false,
6684
- error: void 0,
6685
- optionsAreStatic: !hasExclude && !hasInclude && !hasOverride,
6686
- allowedSchemaNames: void 0
6687
- };
6688
- });
6689
- const pruningStates = states.filter(({ plugin }) => {
6690
- var _a4, _b2;
6691
- const { include } = plugin.options;
6692
- return ((_a4 = include == null ? void 0 : include.some(({ type }) => operationFilterTypes.has(type))) != null ? _a4 : false) && !((_b2 = include == null ? void 0 : include.some(({ type }) => type === "schemaName")) != null ? _b2 : false);
6693
- });
6694
- if (pruningStates.length > 0) {
6695
- const allSchemas = [];
6696
- for await (const schema of schemas) allSchemas.push(schema);
6697
- const includedOpsByState = new Map(pruningStates.map((s) => [s, []]));
6698
- for await (const operation of operations) for (const state of pruningStates) {
6699
- const { exclude, include, override } = state.plugin.options;
6700
- if (state.generatorContext.resolver.resolveOptions(operation, {
6701
- options: state.plugin.options,
6702
- exclude,
6703
- include,
6704
- override
6705
- }) !== null) (_a3 = includedOpsByState.get(state)) == null ? void 0 : _a3.push(operation);
6706
- }
6707
- for (const state of pruningStates) state.allowedSchemaNames = collectUsedSchemaNames((_b = includedOpsByState.get(state)) != null ? _b : [], allSchemas);
6708
- }
6709
- function resolveRendererFor(gen, state) {
6710
- var _a4, _b2;
6711
- return gen.renderer === null ? void 0 : (_b2 = (_a4 = gen.renderer) != null ? _a4 : state.plugin.renderer) != null ? _b2 : state.generatorContext.config.renderer;
6712
- }
6713
- async function dispatchSchema(state, node) {
6714
- if (state.failed) return;
6715
- try {
6716
- const { plugin, generatorContext, generators } = state;
6717
- const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
6718
- if (state.allowedSchemaNames !== void 0 && transformedNode.name && !state.allowedSchemaNames.has(transformedNode.name)) return;
6719
- const { exclude, include, override } = plugin.options;
6720
- const options = state.optionsAreStatic ? plugin.options : generatorContext.resolver.resolveOptions(transformedNode, {
6721
- options: plugin.options,
6722
- exclude,
6723
- include,
6724
- override
6725
- });
6726
- if (options === null) return;
6727
- const ctx = {
6728
- ...generatorContext,
6729
- options
6730
- };
6731
- for (const gen of generators) {
6732
- if (!gen.schema) continue;
6733
- const raw = gen.schema(transformedNode, ctx);
6734
- const applied = applyHookResult({
6735
- result: isPromise(raw) ? await raw : raw,
6736
- driver,
6737
- rendererFactory: resolveRendererFor(gen, state)
6738
- });
6739
- if (isPromise(applied)) await applied;
6740
- }
6741
- await driver.hooks.emit("kubb:generate:schema", transformedNode, ctx);
6742
- } catch (caughtError) {
6743
- state.failed = true;
6744
- state.error = caughtError;
6745
- }
6746
- }
6747
- async function dispatchOperation(state, node) {
6748
- if (state.failed) return;
6749
- try {
6750
- const { plugin, generatorContext, generators } = state;
6751
- const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
6752
- const { exclude, include, override } = plugin.options;
6753
- const options = state.optionsAreStatic ? plugin.options : generatorContext.resolver.resolveOptions(transformedNode, {
6754
- options: plugin.options,
6755
- exclude,
6756
- include,
6757
- override
6758
- });
6759
- if (options === null) return;
6760
- const ctx = {
6761
- ...generatorContext,
6762
- options
6763
- };
6764
- for (const gen of generators) {
6765
- if (!gen.operation) continue;
6766
- const raw = gen.operation(transformedNode, ctx);
6767
- const applied = applyHookResult({
6768
- result: isPromise(raw) ? await raw : raw,
6769
- driver,
6770
- rendererFactory: resolveRendererFor(gen, state)
6771
- });
6772
- if (isPromise(applied)) await applied;
6773
- }
6774
- await driver.hooks.emit("kubb:generate:operation", transformedNode, ctx);
6775
- } catch (caughtError) {
6776
- state.failed = true;
6777
- state.error = caughtError;
6778
- }
6779
- }
6780
- await forBatches(schemas, (nodes) => Promise.all(nodes.flatMap((n) => states.map((state) => dispatchSchema(state, n)))), {
6781
- concurrency: 8,
6782
- flush: flushPendingFiles
6783
- });
6784
- const collectedOperations = [];
6785
- await forBatches(operations, (nodes) => {
6786
- collectedOperations.push(...nodes);
6787
- return Promise.all(nodes.flatMap((n) => states.map((state) => dispatchOperation(state, n))));
6788
- }, {
6789
- concurrency: 8,
6790
- flush: flushPendingFiles
6791
- });
6792
- for (const state of states) {
6793
- if (!state.failed) try {
6794
- const { plugin, generatorContext, generators } = state;
6795
- await dispatchOperationsToGenerators(generators, collectedOperations, {
6796
- ...generatorContext,
6797
- options: plugin.options
6798
- }, (gen) => resolveRendererFor(gen, state));
6799
- } catch (caughtError) {
6800
- state.failed = true;
6801
- state.error = caughtError;
6802
- }
6803
- const duration = getElapsedMs(state.hrStart);
6804
- pluginTimings.set(state.plugin.name, duration);
6805
- await driver.hooks.emit("kubb:plugin:end", {
6806
- plugin: state.plugin,
6807
- duration,
6808
- success: !state.failed,
6809
- ...state.failed && state.error ? { error: state.error } : {},
6810
- config: driver.config,
6811
- get files() {
6812
- return driver.fileManager.files;
6813
- },
6814
- upsertFile: (...files) => driver.fileManager.upsert(...files)
6815
- });
6816
- if (state.failed && state.error) failedPlugins.add({
6817
- plugin: state.plugin,
6818
- error: state.error
6819
- });
6820
- await driver.hooks.emit("kubb:debug", {
6821
- date: /* @__PURE__ */ new Date(),
6822
- logs: [state.failed ? "\u2717 Plugin start failed" : `\u2713 Plugin started successfully (${formatMs(duration)})`]
6823
- });
6824
- }
6987
+ await driver.setup();
6988
+ __privateSet(this, _config, config);
6989
+ __privateSet(this, _driver, driver);
6990
+ __privateSet(this, _storage, storage);
6991
+ }
6992
+ /**
6993
+ * Runs the full pipeline and throws on any plugin error.
6994
+ * Automatically calls `setup()` if needed.
6995
+ */
6996
+ async build() {
6997
+ const out = await this.safeBuild();
6998
+ if (out.error) throw out.error;
6999
+ if (out.failedPlugins.size > 0) {
7000
+ const errors = [...out.failedPlugins].map(({ error }) => error);
7001
+ throw new BuildError(`Build Error with ${out.failedPlugins.size} failed plugins`, { errors });
6825
7002
  }
7003
+ return out;
7004
+ }
7005
+ /**
7006
+ * Runs the full pipeline and captures errors in `BuildOutput` instead of throwing.
7007
+ * Automatically calls `setup()` if needed.
7008
+ */
7009
+ async safeBuild() {
6826
7010
  try {
6827
- await driver.emitSetupHooks();
6828
- if (driver.adapter && driver.inputNode) await hooks.emit("kubb:build:start", {
6829
- config,
6830
- adapter: driver.adapter,
6831
- meta: driver.inputNode.meta,
6832
- getPlugin: driver.getPlugin.bind(driver),
6833
- get files() {
6834
- return driver.fileManager.files;
6835
- },
6836
- upsertFile: (...files2) => driver.fileManager.upsert(...files2)
6837
- });
6838
- const generatorPlugins = [];
6839
- for (const plugin of driver.plugins.values()) {
6840
- const context = driver.getContext(plugin);
6841
- const hrStart = process.hrtime();
6842
- try {
6843
- await hooks.emit("kubb:plugin:start", { plugin });
6844
- await hooks.emit("kubb:debug", {
6845
- date: /* @__PURE__ */ new Date(),
6846
- logs: ["Starting plugin...", ` \u2022 Plugin Name: ${plugin.name}`]
6847
- });
6848
- } catch (caughtError) {
6849
- const error = caughtError;
6850
- const duration2 = getElapsedMs(hrStart);
6851
- pluginTimings.set(plugin.name, duration2);
6852
- await hooks.emit("kubb:plugin:end", {
6853
- plugin,
6854
- duration: duration2,
6855
- success: false,
6856
- error,
6857
- config,
6858
- get files() {
6859
- return driver.fileManager.files;
6860
- },
6861
- upsertFile: (...files2) => driver.fileManager.upsert(...files2)
6862
- });
6863
- failedPlugins.add({
6864
- plugin,
6865
- error
6866
- });
6867
- continue;
6868
- }
6869
- if (((_a2 = plugin.generators) == null ? void 0 : _a2.length) || driver.hasEventGenerators(plugin.name)) {
6870
- generatorPlugins.push({
6871
- plugin,
6872
- context,
6873
- hrStart
6874
- });
6875
- continue;
6876
- }
6877
- const duration = getElapsedMs(hrStart);
6878
- pluginTimings.set(plugin.name, duration);
6879
- await hooks.emit("kubb:plugin:end", {
6880
- plugin,
6881
- duration,
6882
- success: true,
6883
- config,
6884
- get files() {
6885
- return driver.fileManager.files;
6886
- },
6887
- upsertFile: (...files2) => driver.fileManager.upsert(...files2)
6888
- });
6889
- await hooks.emit("kubb:debug", {
6890
- date: /* @__PURE__ */ new Date(),
6891
- logs: [`\u2713 Plugin started successfully (${formatMs(duration)})`]
6892
- });
6893
- }
6894
- if (generatorPlugins.length > 0) if (driver.inputNode) await withDrain(() => runPlugins(generatorPlugins), flushPendingFiles);
6895
- else for (const { plugin, hrStart } of generatorPlugins) {
6896
- const duration = getElapsedMs(hrStart);
6897
- pluginTimings.set(plugin.name, duration);
6898
- await hooks.emit("kubb:plugin:end", {
6899
- plugin,
6900
- duration,
6901
- success: true,
6902
- config,
6903
- get files() {
6904
- return driver.fileManager.files;
6905
- },
6906
- upsertFile: (...files2) => driver.fileManager.upsert(...files2)
6907
- });
6908
- }
6909
- await hooks.emit("kubb:plugins:end", {
6910
- config,
6911
- get files() {
6912
- return driver.fileManager.files;
6913
- },
6914
- upsertFile: (...files2) => driver.fileManager.upsert(...files2)
6915
- });
6916
- await flushPendingFiles();
6917
- const files = driver.fileManager.files;
6918
- await hooks.emit("kubb:build:end", {
6919
- files,
6920
- config,
6921
- outputDir: resolve(config.root, config.output.path)
6922
- });
6923
- return {
6924
- failedPlugins,
6925
- files,
6926
- driver,
6927
- pluginTimings,
6928
- storage
6929
- };
6930
- } catch (error) {
7011
+ var _usingCtx$1 = _usingCtx();
7012
+ if (!__privateGet(this, _driver)) await this.setup();
7013
+ const cleanup = _usingCtx$1.u(this);
7014
+ const driver = cleanup.driver;
7015
+ const storage = cleanup.storage;
7016
+ const { failedPlugins, pluginTimings, error } = await driver.run({ storage });
6931
7017
  return {
6932
7018
  failedPlugins,
6933
- files: [],
7019
+ files: driver.fileManager.files,
6934
7020
  driver,
6935
7021
  pluginTimings,
6936
- error,
6937
- storage
7022
+ storage,
7023
+ ...error ? { error } : {}
6938
7024
  };
7025
+ } catch (_) {
7026
+ _usingCtx$1.e = _;
7027
+ } finally {
7028
+ _usingCtx$1.d();
6939
7029
  }
6940
- } catch (_) {
6941
- _usingCtx$1.e = _;
6942
- } finally {
6943
- _usingCtx$1.d();
6944
7030
  }
6945
- }
6946
- async function build(setupResult) {
6947
- const { files, driver, failedPlugins, pluginTimings, error, storage } = await safeBuild(setupResult);
6948
- if (error) throw error;
6949
- if (failedPlugins.size > 0) {
6950
- const errors = [...failedPlugins].map(({ error: error2 }) => error2);
6951
- throw new BuildError(`Build Error with ${failedPlugins.size} failed plugins`, { errors });
7031
+ dispose() {
7032
+ var _a2;
7033
+ (_a2 = __privateGet(this, _driver)) == null ? void 0 : _a2.dispose();
6952
7034
  }
6953
- return {
6954
- failedPlugins,
6955
- files,
6956
- driver,
6957
- pluginTimings,
6958
- error: void 0,
6959
- storage
6960
- };
6961
- }
6962
- function getDiagnosticInfo() {
6963
- return {
6964
- nodeVersion: version$2,
6965
- KubbVersion: version$1,
6966
- platform: process.platform,
6967
- arch: process.arch,
6968
- cwd: process.cwd()
6969
- };
6970
- }
6971
- function isInputPath(config) {
6972
- return typeof (config == null ? void 0 : config.input) === "object" && config.input !== null && "path" in config.input;
6973
- }
7035
+ [Symbol.dispose]() {
7036
+ this.dispose();
7037
+ }
7038
+ }, _userConfig = new WeakMap(), _config = new WeakMap(), _driver = new WeakMap(), _storage = new WeakMap(), _Kubb_instances = new WeakSet(), configLogs_fn = function(config) {
7039
+ var _a2, _b, _c, _d, _e;
7040
+ const u = __privateGet(this, _userConfig);
7041
+ const diag = getDiagnosticInfo();
7042
+ return [
7043
+ "Configuration:",
7044
+ ` \u2022 Name: ${u.name || "unnamed"}`,
7045
+ ` \u2022 Root: ${u.root || process.cwd()}`,
7046
+ ` \u2022 Output: ${((_a2 = u.output) == null ? void 0 : _a2.path) || "not specified"}`,
7047
+ ` \u2022 Plugins: ${((_b = u.plugins) == null ? void 0 : _b.length) || 0}`,
7048
+ "Output Settings:",
7049
+ ` \u2022 Storage: ${config.storage.name}`,
7050
+ ` \u2022 Formatter: ${((_c = u.output) == null ? void 0 : _c.format) || "none"}`,
7051
+ ` \u2022 Linter: ${((_d = u.output) == null ? void 0 : _d.lint) || "none"}`,
7052
+ `Running adapter: ${((_e = config.adapter) == null ? void 0 : _e.name) || "none"}`,
7053
+ "Environment:",
7054
+ Object.entries(diag).map(([key, value]) => ` \u2022 ${key}: ${value}`).join("\n")
7055
+ ];
7056
+ }, _a);
6974
7057
  function createKubb(userConfig, options = {}) {
6975
- var _a2;
6976
- const hooks = (_a2 = options.hooks) != null ? _a2 : new AsyncEventEmitter();
6977
- let setupResult;
6978
- const instance = {
6979
- get hooks() {
6980
- return hooks;
6981
- },
6982
- get storage() {
6983
- if (!setupResult) throw new Error("[kubb] setup() must be called before accessing storage");
6984
- return setupResult.storage;
6985
- },
6986
- get driver() {
6987
- if (!setupResult) throw new Error("[kubb] setup() must be called before accessing driver");
6988
- return setupResult.driver;
6989
- },
6990
- get config() {
6991
- if (!setupResult) throw new Error("[kubb] setup() must be called before accessing config");
6992
- return setupResult.config;
6993
- },
6994
- async setup() {
6995
- setupResult = await setup(userConfig, { hooks });
6996
- },
6997
- async build() {
6998
- if (!setupResult) await instance.setup();
6999
- return build(setupResult);
7000
- },
7001
- async safeBuild() {
7002
- if (!setupResult) await instance.setup();
7003
- return safeBuild(setupResult);
7004
- }
7005
- };
7006
- return instance;
7058
+ return new Kubb(userConfig, options);
7007
7059
  }
7008
7060
  const memoryStorage = createStorage(() => {
7009
7061
  const store = /* @__PURE__ */ new Map();
@@ -7036,7 +7088,7 @@ const memoryStorage = createStorage(() => {
7036
7088
  };
7037
7089
  });
7038
7090
 
7039
- var version = "5.0.0-beta.20";
7091
+ var version = "5.0.0-beta.22";
7040
7092
 
7041
7093
  function isCommandMessage(msg) {
7042
7094
  return msg.type === "command";
@@ -7390,15 +7442,17 @@ function setupEventsStream(ws, hooks) {
7390
7442
  timestamp: Date.now()
7391
7443
  });
7392
7444
  });
7393
- hooks.on("kubb:file:processing:update", (ctx) => {
7445
+ hooks.on("kubb:files:processing:update", ({ files }) => {
7394
7446
  sendDataMessage({
7395
- type: "kubb:file:processing:update",
7447
+ type: "kubb:files:processing:update",
7396
7448
  data: [
7397
7449
  {
7398
- file: ctx.file.path,
7399
- processed: ctx.processed,
7400
- total: ctx.total,
7401
- percentage: ctx.percentage
7450
+ files: files.map((ctx) => ({
7451
+ file: ctx.file.path,
7452
+ processed: ctx.processed,
7453
+ total: ctx.total,
7454
+ percentage: ctx.percentage
7455
+ }))
7402
7456
  }
7403
7457
  ],
7404
7458
  timestamp: Date.now()