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

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
  *
@@ -5444,7 +5558,7 @@ eachParam_fn = function(fn) {
5444
5558
  const raw = match[1];
5445
5559
  fn(raw, __privateMethod$1(this, _URLPath_instances, transformParam_fn).call(this, raw));
5446
5560
  }
5447
- }, _a$1);
5561
+ }, _b);
5448
5562
  const DEFAULT_STUDIO_URL = "https://kubb.studio";
5449
5563
  const DEFAULT_BANNER = "simple";
5450
5564
  const DEFAULT_EXTENSION = { ".ts": ".ts" };
@@ -5596,7 +5710,7 @@ function buildDefaultBanner({ title, description, version, config }) {
5596
5710
  function defaultResolveBanner(meta, { output, config }) {
5597
5711
  if (typeof (output == null ? void 0 : output.banner) === "function") return output.banner(meta);
5598
5712
  if (typeof (output == null ? void 0 : output.banner) === "string") return output.banner;
5599
- if (config.output.defaultBanner === false) return;
5713
+ if (config.output.defaultBanner === false) return null;
5600
5714
  return buildDefaultBanner({
5601
5715
  title: meta == null ? void 0 : meta.title,
5602
5716
  version: meta == null ? void 0 : meta.version,
@@ -5606,6 +5720,7 @@ function defaultResolveBanner(meta, { output, config }) {
5606
5720
  function defaultResolveFooter(meta, { output }) {
5607
5721
  if (typeof (output == null ? void 0 : output.footer) === "function") return output.footer(meta);
5608
5722
  if (typeof (output == null ? void 0 : output.footer) === "string") return output.footer;
5723
+ return null;
5609
5724
  }
5610
5725
  function defineResolver(build) {
5611
5726
  let resolver;
@@ -5649,38 +5764,42 @@ function mergeFile(a, b) {
5649
5764
  ...a,
5650
5765
  banner: b.banner,
5651
5766
  footer: b.footer,
5652
- sources: [...a.sources || [], ...b.sources || []],
5653
- imports: [...a.imports || [], ...b.imports || []],
5654
- exports: [...a.exports || [], ...b.exports || []]
5767
+ sources: a.sources.length ? b.sources.length ? [...a.sources, ...b.sources] : a.sources : b.sources,
5768
+ imports: a.imports.length ? b.imports.length ? [...a.imports, ...b.imports] : a.imports : b.imports,
5769
+ exports: a.exports.length ? b.exports.length ? [...a.exports, ...b.exports] : a.exports : b.exports
5655
5770
  };
5656
5771
  }
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;
5772
+ function isIndexPath(path2) {
5773
+ return path2.endsWith("/index.ts") || path2 === "index.ts";
5664
5774
  }
5665
- var FileManager = (_b = class {
5775
+ function compareFiles(a, b) {
5776
+ const lenDiff = a.path.length - b.path.length;
5777
+ if (lenDiff !== 0) return lenDiff;
5778
+ const aIsIndex = isIndexPath(a.path);
5779
+ const bIsIndex = isIndexPath(b.path);
5780
+ if (aIsIndex && !bIsIndex) return 1;
5781
+ if (!aIsIndex && bIsIndex) return -1;
5782
+ return 0;
5783
+ }
5784
+ var FileManager = (_c = class {
5666
5785
  constructor() {
5667
5786
  __privateAdd$1(this, _FileManager_instances);
5668
5787
  __privateAdd$1(this, _cache, /* @__PURE__ */ new Map());
5669
- __privateAdd$1(this, _filesCache, null);
5788
+ __privateAdd$1(this, _sorted, null);
5789
+ __privateAdd$1(this, _onUpsert, null);
5670
5790
  }
5671
5791
  /**
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.
5792
+ * Registers a callback invoked with the resolved {@link FileNode} on every
5793
+ * `add` / `upsert`. Used by the build loop to track newly written files
5794
+ * without keeping its own scan-based diff. Single subscriber by design
5795
+ * setting again replaces the previous callback. Pass `null` to detach.
5675
5796
  */
5797
+ setOnUpsert(callback) {
5798
+ __privateSet$1(this, _onUpsert, callback);
5799
+ }
5676
5800
  add(...files) {
5677
5801
  return __privateMethod$1(this, _FileManager_instances, store_fn).call(this, files, false);
5678
5802
  }
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
5803
  upsert(...files) {
5685
5804
  return __privateMethod$1(this, _FileManager_instances, store_fn).call(this, files, true);
5686
5805
  }
@@ -5689,54 +5808,180 @@ var FileManager = (_b = class {
5689
5808
  return (_a2 = __privateGet$1(this, _cache).get(path2)) != null ? _a2 : null;
5690
5809
  }
5691
5810
  deleteByPath(path2) {
5692
- __privateGet$1(this, _cache).delete(path2);
5693
- __privateSet(this, _filesCache, null);
5811
+ if (!__privateGet$1(this, _cache).delete(path2)) return;
5812
+ __privateSet$1(this, _sorted, null);
5694
5813
  }
5695
5814
  clear() {
5696
5815
  __privateGet$1(this, _cache).clear();
5697
- __privateSet(this, _filesCache, null);
5816
+ __privateSet$1(this, _sorted, null);
5698
5817
  }
5699
5818
  /**
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.
5819
+ * Releases all stored files. Called by the core after `kubb:build:end`.
5702
5820
  */
5703
5821
  dispose() {
5704
5822
  this.clear();
5823
+ __privateSet$1(this, _onUpsert, null);
5705
5824
  }
5706
5825
  [Symbol.dispose]() {
5707
5826
  this.dispose();
5708
5827
  }
5709
5828
  /**
5710
- * All stored files, sorted by path length (shorter paths first).
5829
+ * All stored files in stable sort order (shortest path first, barrel files
5830
+ * last within a length bucket). Returns a cached view — do not mutate.
5711
5831
  */
5712
5832
  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);
5833
+ var _a2;
5834
+ return (_a2 = __privateGet$1(this, _sorted)) != null ? _a2 : __privateSet$1(this, _sorted, [...__privateGet$1(this, _cache).values()].sort(compareFiles));
5835
+ }
5836
+ }, _cache = new WeakMap(), _sorted = new WeakMap(), _onUpsert = new WeakMap(), _FileManager_instances = new WeakSet(), store_fn = function(files, mergeExisting) {
5837
+ var _a2;
5838
+ const batch = files.length > 1 ? __privateMethod$1(this, _FileManager_instances, dedupe_fn).call(this, files) : files;
5839
+ const resolved = [];
5840
+ for (const file of batch) {
5841
+ const existing = __privateGet$1(this, _cache).get(file.path);
5842
+ const merged = existing && mergeExisting ? createFile(mergeFile(existing, file)) : file;
5843
+ __privateGet$1(this, _cache).set(merged.path, merged);
5844
+ resolved.push(merged);
5845
+ (_a2 = __privateGet$1(this, _onUpsert)) == null ? void 0 : _a2.call(this, merged);
5846
+ }
5847
+ if (resolved.length > 0) __privateSet$1(this, _sorted, null);
5848
+ return resolved;
5849
+ }, dedupe_fn = function(files) {
5850
+ const seen = /* @__PURE__ */ new Map();
5851
+ for (const file of files) {
5852
+ const prev = seen.get(file.path);
5853
+ seen.set(file.path, prev ? mergeFile(prev, file) : file);
5854
+ }
5855
+ return [...seen.values()];
5856
+ }, _c);
5857
+ function joinSources(file) {
5858
+ const sources = file.sources;
5859
+ if (sources.length === 0) return "";
5860
+ const parts = [];
5861
+ for (const source of sources) {
5862
+ const s = extractStringsFromNodes(source.nodes);
5863
+ if (s) parts.push(s);
5864
+ }
5865
+ return parts.join("\n\n");
5866
+ }
5867
+ var FileProcessor = class {
5868
+ constructor() {
5869
+ __publicField$1(this, "events", new AsyncEventEmitter());
5870
+ }
5871
+ parse(file, { parsers, extension } = {}) {
5872
+ const parseExtName = (extension == null ? void 0 : extension[file.extname]) || void 0;
5873
+ if (!parsers || !file.extname) return joinSources(file);
5874
+ const parser = parsers.get(file.extname);
5875
+ if (!parser) return joinSources(file);
5876
+ return parser.parse(file, { extname: parseExtName });
5877
+ }
5878
+ *stream(files, options = {}) {
5879
+ const total = files.length;
5880
+ if (total === 0) return;
5881
+ let processed = 0;
5882
+ for (const file of files) {
5883
+ const source = this.parse(file, options);
5884
+ processed++;
5885
+ yield {
5886
+ file,
5887
+ source,
5888
+ processed,
5889
+ total,
5890
+ percentage: processed / total * 100
5891
+ };
5892
+ }
5893
+ }
5894
+ async run(files, options = {}) {
5895
+ await this.events.emit("start", files);
5896
+ for (const { file, source, processed, total, percentage } of this.stream(files, options)) await this.events.emit("update", {
5897
+ file,
5898
+ source,
5899
+ processed,
5900
+ percentage,
5901
+ total
5902
+ });
5903
+ await this.events.emit("end", files);
5904
+ return files;
5905
+ }
5906
+ /**
5907
+ * Clears all registered event listeners.
5908
+ */
5909
+ dispose() {
5910
+ this.events.removeAll();
5911
+ }
5912
+ [Symbol.dispose]() {
5913
+ this.dispose();
5914
+ }
5915
+ };
5916
+ function _usingCtx() {
5917
+ var r = "function" == typeof SuppressedError ? SuppressedError : function(r2, e2) {
5918
+ var n2 = Error();
5919
+ return n2.name = "SuppressedError", n2.error = r2, n2.suppressed = e2, n2;
5920
+ };
5921
+ var e = {};
5922
+ var n = [];
5923
+ function using(r2, e2) {
5924
+ if (null != e2) {
5925
+ if (Object(e2) !== e2) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
5926
+ if (r2) var o = e2[Symbol.asyncDispose || Symbol["for"]("Symbol.asyncDispose")];
5927
+ if (void 0 === o && (o = e2[Symbol.dispose || Symbol["for"]("Symbol.dispose")], r2)) var t = o;
5928
+ if ("function" != typeof o) throw new TypeError("Object is not disposable.");
5929
+ t && (o = function o2() {
5930
+ try {
5931
+ t.call(e2);
5932
+ } catch (r3) {
5933
+ return Promise.reject(r3);
5934
+ }
5935
+ }), n.push({
5936
+ v: e2,
5937
+ d: o,
5938
+ a: r2
5939
+ });
5940
+ } else r2 && n.push({
5941
+ d: e2,
5942
+ a: r2
5943
+ });
5944
+ return e2;
5945
+ }
5946
+ return {
5947
+ e,
5948
+ u: using.bind(null, false),
5949
+ a: using.bind(null, true),
5950
+ d: function d() {
5951
+ var o;
5952
+ var t = this.e;
5953
+ var s = 0;
5954
+ function next() {
5955
+ for (; o = n.pop(); ) try {
5956
+ if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
5957
+ if (o.d) {
5958
+ var r2 = o.d.call(o.v);
5959
+ if (o.a) return s |= 2, Promise.resolve(r2).then(next, err);
5960
+ } else s |= 1;
5961
+ } catch (r3) {
5962
+ return err(r3);
5963
+ }
5964
+ if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
5965
+ if (t !== e) throw t;
5966
+ }
5967
+ function err(n2) {
5968
+ return t = t !== e ? new r(n2, t) : n2, next();
5969
+ }
5970
+ return next();
5971
+ }
5972
+ };
5973
+ }
5736
5974
  function enforceOrder(enforce) {
5737
5975
  return enforce === "pre" ? -1 : enforce === "post" ? 1 : 0;
5738
5976
  }
5739
- var KubbDriver = (_c = class {
5977
+ const OPERATION_FILTER_TYPES = /* @__PURE__ */ new Set([
5978
+ "tag",
5979
+ "operationId",
5980
+ "path",
5981
+ "method",
5982
+ "contentType"
5983
+ ]);
5984
+ var KubbDriver = (_d = class {
5740
5985
  constructor(config, options) {
5741
5986
  __privateAdd$1(this, _KubbDriver_instances);
5742
5987
  __publicField$1(this, "config");
@@ -5745,8 +5990,8 @@ var KubbDriver = (_c = class {
5745
5990
  * The streaming `InputStreamNode` produced by the adapter.
5746
5991
  * Always set after adapter setup — parse-only adapters are wrapped automatically.
5747
5992
  */
5748
- __publicField$1(this, "inputNode");
5749
- __publicField$1(this, "adapter");
5993
+ __publicField$1(this, "inputNode", null);
5994
+ __publicField$1(this, "adapter", null);
5750
5995
  /**
5751
5996
  * Studio session state, kept together so `dispose()` can reset it atomically.
5752
5997
  *
@@ -5757,9 +6002,9 @@ var KubbDriver = (_c = class {
5757
6002
  * per studio session, even when `openInStudio()` is called multiple times.
5758
6003
  */
5759
6004
  __privateAdd$1(this, _studio, {
5760
- source: void 0,
6005
+ source: null,
5761
6006
  isOpen: false,
5762
- inputNode: void 0
6007
+ inputNode: null
5763
6008
  });
5764
6009
  __privateAdd$1(this, _middlewareListeners, []);
5765
6010
  /**
@@ -5768,6 +6013,7 @@ var KubbDriver = (_c = class {
5768
6013
  * add files; this property gives direct read/write access when needed.
5769
6014
  */
5770
6015
  __publicField$1(this, "fileManager", new FileManager());
6016
+ __privateAdd$1(this, _fileProcessor, new FileProcessor());
5771
6017
  __publicField$1(this, "plugins", /* @__PURE__ */ new Map());
5772
6018
  /**
5773
6019
  * Tracks which plugins have generators registered via `addGenerator()` (event-based path).
@@ -5781,9 +6027,10 @@ var KubbDriver = (_c = class {
5781
6027
  name: "default",
5782
6028
  pluginName
5783
6029
  }))));
6030
+ var _a2;
5784
6031
  this.config = config;
5785
6032
  this.options = options;
5786
- this.adapter = config.adapter;
6033
+ this.adapter = (_a2 = config.adapter) != null ? _a2 : null;
5787
6034
  }
5788
6035
  /**
5789
6036
  * Returns `'single'` when `fileOrFolder` has a file extension, `'split'` otherwise.
@@ -5906,24 +6153,165 @@ var KubbDriver = (_c = class {
5906
6153
  return __privateGet$1(this, _eventGeneratorPlugins).has(pluginName);
5907
6154
  }
5908
6155
  /**
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
6156
+ * Runs the full plugin pipeline. Returns timings/failures collected so far even
6157
+ * when an outer hook throws the orchestrator preserves partial state by capturing
6158
+ * the error into `error` instead of propagating.
5913
6159
  */
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
- });
6160
+ async run({ storage }) {
6161
+ var _a2;
6162
+ const hooks = this.hooks;
6163
+ const config = this.config;
6164
+ const failedPlugins = /* @__PURE__ */ new Set();
6165
+ const pluginTimings = /* @__PURE__ */ new Map();
6166
+ const parsersMap = /* @__PURE__ */ new Map();
6167
+ for (const parser of config.parsers) if (parser.extNames) for (const ext of parser.extNames) parsersMap.set(ext, parser);
6168
+ const pendingFiles = /* @__PURE__ */ new Map();
6169
+ this.fileManager.setOnUpsert((file) => {
6170
+ pendingFiles.set(file.path, file);
6171
+ });
6172
+ try {
6173
+ const flushPending = async () => {
6174
+ if (pendingFiles.size === 0) return;
6175
+ const files2 = [...pendingFiles.values()];
6176
+ pendingFiles.clear();
6177
+ await hooks.emit("kubb:debug", {
6178
+ date: /* @__PURE__ */ new Date(),
6179
+ logs: [`Writing ${files2.length} files...`]
6180
+ });
6181
+ await hooks.emit("kubb:files:processing:start", { files: files2 });
6182
+ const items = [...__privateGet$1(this, _fileProcessor).stream(files2, {
6183
+ parsers: parsersMap,
6184
+ extension: config.output.extension
6185
+ })];
6186
+ await hooks.emit("kubb:files:processing:update", { files: items.map(({ file, source, processed, total, percentage }) => ({
6187
+ file,
6188
+ source,
6189
+ processed,
6190
+ total,
6191
+ percentage,
6192
+ config
6193
+ })) });
6194
+ const queue = [];
6195
+ for (const { file, source } of items) if (source) {
6196
+ queue.push(storage.setItem(file.path, source));
6197
+ if (queue.length >= 50) await Promise.all(queue.splice(0));
6198
+ }
6199
+ await Promise.all(queue);
6200
+ await hooks.emit("kubb:files:processing:end", { files: files2 });
6201
+ await hooks.emit("kubb:debug", {
6202
+ date: /* @__PURE__ */ new Date(),
6203
+ logs: [`\u2713 File write process completed for ${files2.length} files`]
6204
+ });
6205
+ };
6206
+ await this.emitSetupHooks();
6207
+ if (this.adapter && this.inputNode) await hooks.emit("kubb:build:start", Object.assign({
6208
+ config,
6209
+ adapter: this.adapter,
6210
+ meta: this.inputNode.meta,
6211
+ getPlugin: this.getPlugin.bind(this)
6212
+ }, __privateMethod$1(this, _KubbDriver_instances, filesPayload_fn).call(this)));
6213
+ const generatorPlugins = [];
6214
+ for (const plugin of this.plugins.values()) {
6215
+ const context = this.getContext(plugin);
6216
+ const hrStart = process.hrtime();
6217
+ try {
6218
+ await hooks.emit("kubb:plugin:start", { plugin });
6219
+ await hooks.emit("kubb:debug", {
6220
+ date: /* @__PURE__ */ new Date(),
6221
+ logs: ["Starting plugin...", ` \u2022 Plugin Name: ${plugin.name}`]
6222
+ });
6223
+ } catch (caughtError) {
6224
+ const error = caughtError;
6225
+ const duration2 = getElapsedMs(hrStart);
6226
+ pluginTimings.set(plugin.name, duration2);
6227
+ await __privateMethod$1(this, _KubbDriver_instances, emitPluginEnd_fn).call(this, {
6228
+ plugin,
6229
+ duration: duration2,
6230
+ success: false,
6231
+ error
6232
+ });
6233
+ failedPlugins.add({
6234
+ plugin,
6235
+ error
6236
+ });
6237
+ continue;
6238
+ }
6239
+ if (((_a2 = plugin.generators) == null ? void 0 : _a2.length) || this.hasEventGenerators(plugin.name)) {
6240
+ generatorPlugins.push({
6241
+ plugin,
6242
+ context,
6243
+ hrStart
6244
+ });
6245
+ continue;
6246
+ }
6247
+ const duration = getElapsedMs(hrStart);
6248
+ pluginTimings.set(plugin.name, duration);
6249
+ await __privateMethod$1(this, _KubbDriver_instances, emitPluginEnd_fn).call(this, {
6250
+ plugin,
6251
+ duration,
6252
+ success: true
6253
+ });
6254
+ await hooks.emit("kubb:debug", {
6255
+ date: /* @__PURE__ */ new Date(),
6256
+ logs: [`\u2713 Plugin started successfully (${formatMs(duration)})`]
6257
+ });
6258
+ }
6259
+ if (generatorPlugins.length > 0) if (this.inputNode) {
6260
+ const { timings, failed } = await __privateMethod$1(this, _KubbDriver_instances, runGenerators_fn).call(this, generatorPlugins, flushPending);
6261
+ await flushPending();
6262
+ for (const [name, duration] of timings) pluginTimings.set(name, duration);
6263
+ for (const entry of failed) failedPlugins.add(entry);
6264
+ } else for (const { plugin, hrStart } of generatorPlugins) {
6265
+ const duration = getElapsedMs(hrStart);
6266
+ pluginTimings.set(plugin.name, duration);
6267
+ await __privateMethod$1(this, _KubbDriver_instances, emitPluginEnd_fn).call(this, {
6268
+ plugin,
6269
+ duration,
6270
+ success: true
6271
+ });
6272
+ }
6273
+ await hooks.emit("kubb:plugins:end", Object.assign({ config }, __privateMethod$1(this, _KubbDriver_instances, filesPayload_fn).call(this)));
6274
+ await flushPending();
6275
+ const files = this.fileManager.files;
6276
+ await hooks.emit("kubb:build:end", {
6277
+ files,
6278
+ config,
6279
+ outputDir: resolve(config.root, config.output.path)
6280
+ });
6281
+ return {
6282
+ failedPlugins,
6283
+ pluginTimings
6284
+ };
6285
+ } catch (caughtError) {
6286
+ return {
6287
+ failedPlugins,
6288
+ pluginTimings,
6289
+ error: caughtError
6290
+ };
6291
+ } finally {
6292
+ this.fileManager.setOnUpsert(null);
6293
+ }
6294
+ }
6295
+ /**
6296
+ * Unregisters all plugin lifecycle listeners from the shared event emitter.
6297
+ * Called at the end of a build to prevent listener leaks across repeated builds.
6298
+ *
6299
+ * @internal
6300
+ */
6301
+ dispose() {
6302
+ for (const [event, handlers] of __privateGet$1(this, _hookListeners)) for (const handler of handlers) this.hooks.off(event, handler);
6303
+ __privateGet$1(this, _hookListeners).clear();
6304
+ __privateGet$1(this, _eventGeneratorPlugins).clear();
6305
+ __privateGet$1(this, _resolvers).clear();
6306
+ __privateGet$1(this, _defaultResolvers).clear();
6307
+ this.fileManager.dispose();
6308
+ __privateGet$1(this, _fileProcessor).dispose();
6309
+ this.inputNode = null;
6310
+ __privateSet$1(this, _studio, {
6311
+ source: null,
6312
+ isOpen: false,
6313
+ inputNode: null
6314
+ });
5927
6315
  for (const [event, handler] of __privateGet$1(this, _middlewareListeners)) this.hooks.off(event, handler);
5928
6316
  }
5929
6317
  [Symbol.dispose]() {
@@ -5955,7 +6343,7 @@ var KubbDriver = (_c = class {
5955
6343
  return resolve(driver.config.root, driver.config.output.path);
5956
6344
  },
5957
6345
  getMode(output) {
5958
- return _c.getMode(resolve(driver.config.root, driver.config.output.path, output.path));
6346
+ return _d.getMode(resolve(driver.config.root, driver.config.output.path, output.path));
5959
6347
  },
5960
6348
  hooks: driver.hooks,
5961
6349
  plugin,
@@ -5995,13 +6383,13 @@ var KubbDriver = (_c = class {
5995
6383
  driver.hooks.emit("kubb:info", { message });
5996
6384
  },
5997
6385
  async openInStudio(options) {
5998
- var _a2, _b2, _c2, _d;
6386
+ var _a2, _b2, _c2, _d2;
5999
6387
  if (!driver.config.devtools || __privateGet$1(driver, _studio).isOpen) return;
6000
6388
  if (typeof driver.config.devtools !== "object") throw new Error("Devtools must be an object");
6001
6389
  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
6390
  __privateGet$1(driver, _studio).isOpen = true;
6003
6391
  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));
6392
+ (_d2 = (_c2 = __privateGet$1(driver, _studio)).inputNode) != null ? _d2 : _c2.inputNode = Promise.resolve(driver.adapter.parse(__privateGet$1(driver, _studio).source));
6005
6393
  return openInStudio(await __privateGet$1(driver, _studio).inputNode, studioUrl, options);
6006
6394
  }
6007
6395
  };
@@ -6014,7 +6402,7 @@ var KubbDriver = (_c = class {
6014
6402
  if (!plugin) throw new Error(`[kubb] Plugin "${pluginName}" is required but not found. Make sure it is included in your Kubb config.`);
6015
6403
  return plugin;
6016
6404
  }
6017
- }, _studio = new WeakMap(), _middlewareListeners = new WeakMap(), _eventGeneratorPlugins = new WeakMap(), _resolvers = new WeakMap(), _defaultResolvers = new WeakMap(), _hookListeners = new WeakMap(), _KubbDriver_instances = new WeakSet(), /**
6405
+ }, _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
6406
  * Creates an `NormalizedPlugin` from a hook-style plugin and registers
6019
6407
  * its lifecycle handlers on the `AsyncEventEmitter`.
6020
6408
  */
@@ -6115,6 +6503,198 @@ registerPlugin_fn = function(plugin) {
6115
6503
  this.hooks.on(event, handler);
6116
6504
  __privateMethod$1(this, _KubbDriver_instances, trackHookListener_fn).call(this, event, handler);
6117
6505
  }
6506
+ }, filesPayload_fn = function() {
6507
+ const driver = this;
6508
+ return {
6509
+ get files() {
6510
+ return driver.fileManager.files;
6511
+ },
6512
+ upsertFile: (...files) => driver.fileManager.upsert(...files)
6513
+ };
6514
+ }, emitPluginEnd_fn = function({ plugin, duration, success, error }) {
6515
+ return this.hooks.emit("kubb:plugin:end", Object.assign({
6516
+ plugin,
6517
+ duration,
6518
+ success,
6519
+ ...error ? { error } : {},
6520
+ config: this.config
6521
+ }, __privateMethod$1(this, _KubbDriver_instances, filesPayload_fn).call(this)));
6522
+ }, runGenerators_fn = async function(entries, flushPending) {
6523
+ var _a2, _b2;
6524
+ const timings = /* @__PURE__ */ new Map();
6525
+ const failed = /* @__PURE__ */ new Set();
6526
+ const driver = this;
6527
+ const { schemas, operations } = this.inputNode;
6528
+ const states = entries.map(({ plugin, context, hrStart }) => {
6529
+ var _a3;
6530
+ const { exclude, include, override } = plugin.options;
6531
+ const hasExclude = Array.isArray(exclude) && exclude.length > 0;
6532
+ const hasInclude = Array.isArray(include) && include.length > 0;
6533
+ const hasOverride = Array.isArray(override) && override.length > 0;
6534
+ return {
6535
+ plugin,
6536
+ generatorContext: {
6537
+ ...context,
6538
+ resolver: this.getResolver(plugin.name)
6539
+ },
6540
+ generators: (_a3 = plugin.generators) != null ? _a3 : [],
6541
+ hrStart,
6542
+ failed: false,
6543
+ error: null,
6544
+ optionsAreStatic: !hasExclude && !hasInclude && !hasOverride,
6545
+ allowedSchemaNames: null
6546
+ };
6547
+ });
6548
+ const emitsSchemaHook = this.hooks.listenerCount("kubb:generate:schema") > 0;
6549
+ const emitsOperationHook = this.hooks.listenerCount("kubb:generate:operation") > 0;
6550
+ const pruningStates = states.filter(({ plugin }) => {
6551
+ var _a3, _b3;
6552
+ const { include } = plugin.options;
6553
+ 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);
6554
+ });
6555
+ if (pruningStates.length > 0) {
6556
+ const allSchemas = [];
6557
+ for await (const schema of schemas) allSchemas.push(schema);
6558
+ const includedOpsByState = new Map(pruningStates.map((s) => [s, []]));
6559
+ for await (const operation of operations) for (const state of pruningStates) {
6560
+ const { exclude, include, override } = state.plugin.options;
6561
+ if (state.generatorContext.resolver.resolveOptions(operation, {
6562
+ options: state.plugin.options,
6563
+ exclude,
6564
+ include,
6565
+ override
6566
+ }) !== null) (_a2 = includedOpsByState.get(state)) == null ? void 0 : _a2.push(operation);
6567
+ }
6568
+ for (const state of pruningStates) {
6569
+ state.allowedSchemaNames = collectUsedSchemaNames((_b2 = includedOpsByState.get(state)) != null ? _b2 : [], allSchemas);
6570
+ includedOpsByState.delete(state);
6571
+ }
6572
+ }
6573
+ const resolveRendererFor = (gen, state) => {
6574
+ var _a3, _b3;
6575
+ return gen.renderer === null ? void 0 : (_b3 = (_a3 = gen.renderer) != null ? _a3 : state.plugin.renderer) != null ? _b3 : state.generatorContext.config.renderer;
6576
+ };
6577
+ const dispatchSchema = async (state, node) => {
6578
+ if (state.failed) return;
6579
+ try {
6580
+ const { plugin, generatorContext, generators } = state;
6581
+ const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
6582
+ if (state.allowedSchemaNames !== null && transformedNode.name && !state.allowedSchemaNames.has(transformedNode.name)) return;
6583
+ const { exclude, include, override } = plugin.options;
6584
+ const options = state.optionsAreStatic ? plugin.options : generatorContext.resolver.resolveOptions(transformedNode, {
6585
+ options: plugin.options,
6586
+ exclude,
6587
+ include,
6588
+ override
6589
+ });
6590
+ if (options === null) return;
6591
+ const ctx = {
6592
+ ...generatorContext,
6593
+ options
6594
+ };
6595
+ for (const gen of generators) {
6596
+ if (!gen.schema) continue;
6597
+ const raw = gen.schema(transformedNode, ctx);
6598
+ const applied = applyHookResult({
6599
+ result: isPromise(raw) ? await raw : raw,
6600
+ driver,
6601
+ rendererFactory: resolveRendererFor(gen, state)
6602
+ });
6603
+ if (isPromise(applied)) await applied;
6604
+ }
6605
+ if (emitsSchemaHook) await this.hooks.emit("kubb:generate:schema", transformedNode, ctx);
6606
+ } catch (caughtError) {
6607
+ state.failed = true;
6608
+ state.error = caughtError;
6609
+ }
6610
+ };
6611
+ const dispatchOperation = async (state, node) => {
6612
+ if (state.failed) return;
6613
+ try {
6614
+ const { plugin, generatorContext, generators } = state;
6615
+ const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
6616
+ const { exclude, include, override } = plugin.options;
6617
+ const options = state.optionsAreStatic ? plugin.options : generatorContext.resolver.resolveOptions(transformedNode, {
6618
+ options: plugin.options,
6619
+ exclude,
6620
+ include,
6621
+ override
6622
+ });
6623
+ if (options === null) return;
6624
+ const ctx = {
6625
+ ...generatorContext,
6626
+ options
6627
+ };
6628
+ for (const gen of generators) {
6629
+ if (!gen.operation) continue;
6630
+ const raw = gen.operation(transformedNode, ctx);
6631
+ const applied = applyHookResult({
6632
+ result: isPromise(raw) ? await raw : raw,
6633
+ driver,
6634
+ rendererFactory: resolveRendererFor(gen, state)
6635
+ });
6636
+ if (isPromise(applied)) await applied;
6637
+ }
6638
+ if (emitsOperationHook) await this.hooks.emit("kubb:generate:operation", transformedNode, ctx);
6639
+ } catch (caughtError) {
6640
+ state.failed = true;
6641
+ state.error = caughtError;
6642
+ }
6643
+ };
6644
+ const needsCollectedOperations = this.hooks.listenerCount("kubb:generate:operations") > 0 || states.some((s) => s.generators.some((g) => !!g.operations));
6645
+ const collectedOperations = needsCollectedOperations ? [] : void 0;
6646
+ await forBatches(schemas, (nodes) => Promise.all(nodes.flatMap((n) => states.map((state) => dispatchSchema(state, n)))), {
6647
+ concurrency: 8,
6648
+ flush: flushPending
6649
+ });
6650
+ await forBatches(operations, (nodes) => {
6651
+ if (needsCollectedOperations) collectedOperations.push(...nodes);
6652
+ return Promise.all(nodes.flatMap((n) => states.map((state) => dispatchOperation(state, n))));
6653
+ }, {
6654
+ concurrency: 8,
6655
+ flush: flushPending
6656
+ });
6657
+ for (const state of states) {
6658
+ if (!state.failed && needsCollectedOperations) try {
6659
+ const { plugin, generatorContext, generators } = state;
6660
+ const ctx = {
6661
+ ...generatorContext,
6662
+ options: plugin.options
6663
+ };
6664
+ for (const gen of generators) {
6665
+ if (!gen.operations) continue;
6666
+ await applyHookResult({
6667
+ result: await gen.operations(collectedOperations, ctx),
6668
+ driver,
6669
+ rendererFactory: resolveRendererFor(gen, state)
6670
+ });
6671
+ }
6672
+ await this.hooks.emit("kubb:generate:operations", collectedOperations, ctx);
6673
+ } catch (caughtError) {
6674
+ state.failed = true;
6675
+ state.error = caughtError;
6676
+ }
6677
+ const duration = getElapsedMs(state.hrStart);
6678
+ timings.set(state.plugin.name, duration);
6679
+ await __privateMethod$1(this, _KubbDriver_instances, emitPluginEnd_fn).call(this, {
6680
+ plugin: state.plugin,
6681
+ duration,
6682
+ success: !state.failed,
6683
+ error: state.failed && state.error ? state.error : void 0
6684
+ });
6685
+ if (state.failed && state.error) failed.add({
6686
+ plugin: state.plugin,
6687
+ error: state.error
6688
+ });
6689
+ await this.hooks.emit("kubb:debug", {
6690
+ date: /* @__PURE__ */ new Date(),
6691
+ logs: [state.failed ? "\u2717 Plugin start failed" : `\u2713 Plugin started successfully (${formatMs(duration)})`]
6692
+ });
6693
+ }
6694
+ return {
6695
+ timings,
6696
+ failed
6697
+ };
6118
6698
  }, trackHookListener_fn = function(event, handler) {
6119
6699
  let handlers = __privateGet$1(this, _hookListeners).get(event);
6120
6700
  if (!handlers) {
@@ -6122,7 +6702,7 @@ registerPlugin_fn = function(plugin) {
6122
6702
  __privateGet$1(this, _hookListeners).set(event, handlers);
6123
6703
  }
6124
6704
  handlers.add(handler);
6125
- }, _getDefaultResolver = new WeakMap(), _c);
6705
+ }, _getDefaultResolver = new WeakMap(), _d);
6126
6706
  function applyHookResult({ result, driver, rendererFactory }) {
6127
6707
  if (!result) return;
6128
6708
  if (Array.isArray(result)) {
@@ -6131,10 +6711,15 @@ function applyHookResult({ result, driver, rendererFactory }) {
6131
6711
  }
6132
6712
  if (!rendererFactory) return;
6133
6713
  const renderer = rendererFactory();
6134
- if (renderer.stream) {
6135
- for (const file of renderer.stream(result)) driver.fileManager.upsert(file);
6136
- renderer.unmount();
6714
+ if (renderer.stream) try {
6715
+ var _usingCtx$1 = _usingCtx();
6716
+ const r = _usingCtx$1.u(renderer);
6717
+ for (const file of r.stream(result)) driver.fileManager.upsert(file);
6137
6718
  return;
6719
+ } catch (_) {
6720
+ _usingCtx$1.e = _;
6721
+ } finally {
6722
+ _usingCtx$1.d();
6138
6723
  }
6139
6724
  return applyAsyncRender({
6140
6725
  renderer,
@@ -6143,9 +6728,16 @@ function applyHookResult({ result, driver, rendererFactory }) {
6143
6728
  });
6144
6729
  }
6145
6730
  async function applyAsyncRender({ renderer, result, driver }) {
6146
- await renderer.render(result);
6147
- driver.fileManager.upsert(...renderer.files);
6148
- renderer.unmount();
6731
+ try {
6732
+ var _usingCtx3 = _usingCtx();
6733
+ const r = _usingCtx3.u(renderer);
6734
+ await r.render(result);
6735
+ driver.fileManager.upsert(...r.files);
6736
+ } catch (_) {
6737
+ _usingCtx3.e = _;
6738
+ } finally {
6739
+ _usingCtx3.d();
6740
+ }
6149
6741
  }
6150
6742
  function inputToAdapterSource(config) {
6151
6743
  const input = config.input;
@@ -6169,130 +6761,13 @@ var __typeError = (msg) => {
6169
6761
  throw TypeError(msg);
6170
6762
  };
6171
6763
  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);
6764
+ var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
6173
6765
  var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
6174
6766
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
6175
6767
  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);
6768
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
6176
6769
  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
- }
6770
+ var _userConfig, _config, _driver, _storage, _Kubb_instances, configLogs_fn, _a;
6296
6771
  async function exists(path) {
6297
6772
  if (typeof Bun !== "undefined") return Bun.file(path).exists();
6298
6773
  return access(path).then(() => true, () => false);
@@ -6333,60 +6808,10 @@ async function clean(path) {
6333
6808
  force: true
6334
6809
  });
6335
6810
  }
6336
- var version$1 = "5.0.0-beta.20";
6337
- function createStorage(build2) {
6338
- return (options) => build2(options != null ? options : {});
6811
+ var version$1 = "5.0.0-beta.21";
6812
+ function createStorage(build) {
6813
+ return (options) => build(options != null ? options : {});
6339
6814
  }
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
6815
  const fsStorage = createStorage(() => ({
6391
6816
  name: "fs",
6392
6817
  async hasItem(key) {
@@ -6434,64 +6859,6 @@ const fsStorage = createStorage(() => ({
6434
6859
  await clean(resolve(base));
6435
6860
  }
6436
6861
  }));
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
6862
  function createSourcesView(storage) {
6496
6863
  const paths = /* @__PURE__ */ new Set();
6497
6864
  return createStorage(() => ({
@@ -6522,13 +6889,12 @@ function createSourcesView(storage) {
6522
6889
  }
6523
6890
  }))();
6524
6891
  }
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 = {
6892
+ function resolveConfig(userConfig) {
6893
+ var _a2, _b, _c;
6894
+ return {
6529
6895
  ...userConfig,
6530
6896
  root: userConfig.root || process.cwd(),
6531
- parsers: (_b = userConfig.parsers) != null ? _b : [],
6897
+ parsers: (_a2 = userConfig.parsers) != null ? _a2 : [],
6532
6898
  output: {
6533
6899
  format: false,
6534
6900
  lint: false,
@@ -6536,474 +6902,149 @@ async function setup(userConfig, options = {}) {
6536
6902
  defaultBanner: DEFAULT_BANNER,
6537
6903
  ...userConfig.output
6538
6904
  },
6539
- storage: (_c = userConfig.storage) != null ? _c : fsStorage(),
6905
+ storage: (_b = userConfig.storage) != null ? _b : fsStorage(),
6540
6906
  devtools: userConfig.devtools ? {
6541
6907
  studioUrl: DEFAULT_STUDIO_URL,
6542
6908
  ...typeof userConfig.devtools === "boolean" ? {} : userConfig.devtools
6543
6909
  } : void 0,
6544
- plugins: (_d = userConfig.plugins) != null ? _d : []
6910
+ plugins: (_c = userConfig.plugins) != null ? _c : []
6545
6911
  };
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();
6912
+ }
6913
+ function getDiagnosticInfo() {
6588
6914
  return {
6589
- config,
6590
- hooks,
6591
- driver,
6592
- storage,
6593
- dispose,
6594
- [Symbol.dispose]: dispose
6915
+ nodeVersion: version$2,
6916
+ KubbVersion: version$1,
6917
+ platform: process.platform,
6918
+ arch: process.arch,
6919
+ cwd: process.cwd()
6595
6920
  };
6596
- function dispose() {
6597
- driver.dispose();
6598
- }
6599
6921
  }
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", {
6922
+ function isInputPath(config) {
6923
+ return typeof (config == null ? void 0 : config.input) === "object" && config.input !== null && "path" in config.input;
6924
+ }
6925
+ var Kubb = (_a = class {
6926
+ constructor(userConfig, options = {}) {
6927
+ __privateAdd(this, _Kubb_instances);
6928
+ __publicField(this, "hooks");
6929
+ __privateAdd(this, _userConfig);
6930
+ __privateAdd(this, _config, null);
6931
+ __privateAdd(this, _driver, null);
6932
+ __privateAdd(this, _storage, null);
6933
+ var _a2;
6934
+ __privateSet(this, _userConfig, userConfig);
6935
+ this.hooks = (_a2 = options.hooks) != null ? _a2 : new AsyncEventEmitter();
6936
+ }
6937
+ get storage() {
6938
+ if (!__privateGet(this, _storage)) throw new Error("[kubb] setup() must be called before accessing storage");
6939
+ return __privateGet(this, _storage);
6940
+ }
6941
+ get driver() {
6942
+ if (!__privateGet(this, _driver)) throw new Error("[kubb] setup() must be called before accessing driver");
6943
+ return __privateGet(this, _driver);
6944
+ }
6945
+ get config() {
6946
+ if (!__privateGet(this, _config)) throw new Error("[kubb] setup() must be called before accessing config");
6947
+ return __privateGet(this, _config);
6948
+ }
6949
+ /**
6950
+ * Resolves config and initializes the driver. `build()` calls this automatically.
6951
+ */
6952
+ async setup() {
6953
+ const config = resolveConfig(__privateGet(this, _userConfig));
6954
+ const driver = new KubbDriver(config, { hooks: this.hooks });
6955
+ const storage = createSourcesView(config.storage);
6956
+ await this.hooks.emit("kubb:debug", {
6957
+ date: /* @__PURE__ */ new Date(),
6958
+ logs: __privateMethod(this, _Kubb_instances, configLogs_fn).call(this, config)
6959
+ });
6960
+ if (isInputPath(__privateGet(this, _userConfig)) && !new URLPath(__privateGet(this, _userConfig).input.path).isURL) try {
6961
+ await exists(__privateGet(this, _userConfig).input.path);
6962
+ await this.hooks.emit("kubb:debug", {
6617
6963
  date: /* @__PURE__ */ new Date(),
6618
- logs: [`Writing ${files.length} files...`]
6619
- });
6620
- await hooks.emit("kubb:files:processing:start", { files });
6621
- const stream = fileProcessor.stream(files, {
6622
- parsers: parsersMap,
6623
- extension: config.output.extension
6964
+ logs: [`\u2713 Input file validated: ${__privateGet(this, _userConfig).input.path}`]
6624
6965
  });
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", {
6966
+ } catch (caughtError) {
6967
+ 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 });
6968
+ }
6969
+ if (config.output.clean) {
6970
+ await this.hooks.emit("kubb:debug", {
6644
6971
  date: /* @__PURE__ */ new Date(),
6645
- logs: [`\u2713 File write process completed for ${files.length} files`]
6972
+ logs: ["Cleaning output directories", ` \u2022 Output: ${config.output.path}`]
6646
6973
  });
6974
+ await config.storage.clear(resolve(config.root, config.output.path));
6647
6975
  }
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
- }
6976
+ await driver.setup();
6977
+ __privateSet(this, _config, config);
6978
+ __privateSet(this, _driver, driver);
6979
+ __privateSet(this, _storage, storage);
6980
+ }
6981
+ /**
6982
+ * Runs the full pipeline and throws on any plugin error.
6983
+ * Automatically calls `setup()` if needed.
6984
+ */
6985
+ async build() {
6986
+ const out = await this.safeBuild();
6987
+ if (out.error) throw out.error;
6988
+ if (out.failedPlugins.size > 0) {
6989
+ const errors = [...out.failedPlugins].map(({ error }) => error);
6990
+ throw new BuildError(`Build Error with ${out.failedPlugins.size} failed plugins`, { errors });
6825
6991
  }
6992
+ return out;
6993
+ }
6994
+ /**
6995
+ * Runs the full pipeline and captures errors in `BuildOutput` instead of throwing.
6996
+ * Automatically calls `setup()` if needed.
6997
+ */
6998
+ async safeBuild() {
6826
6999
  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) {
7000
+ var _usingCtx$1 = _usingCtx();
7001
+ if (!__privateGet(this, _driver)) await this.setup();
7002
+ const cleanup = _usingCtx$1.u(this);
7003
+ const driver = cleanup.driver;
7004
+ const storage = cleanup.storage;
7005
+ const { failedPlugins, pluginTimings, error } = await driver.run({ storage });
6931
7006
  return {
6932
7007
  failedPlugins,
6933
- files: [],
7008
+ files: driver.fileManager.files,
6934
7009
  driver,
6935
7010
  pluginTimings,
6936
- error,
6937
- storage
7011
+ storage,
7012
+ ...error ? { error } : {}
6938
7013
  };
7014
+ } catch (_) {
7015
+ _usingCtx$1.e = _;
7016
+ } finally {
7017
+ _usingCtx$1.d();
6939
7018
  }
6940
- } catch (_) {
6941
- _usingCtx$1.e = _;
6942
- } finally {
6943
- _usingCtx$1.d();
6944
7019
  }
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 });
7020
+ dispose() {
7021
+ var _a2;
7022
+ (_a2 = __privateGet(this, _driver)) == null ? void 0 : _a2.dispose();
6952
7023
  }
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
- }
7024
+ [Symbol.dispose]() {
7025
+ this.dispose();
7026
+ }
7027
+ }, _userConfig = new WeakMap(), _config = new WeakMap(), _driver = new WeakMap(), _storage = new WeakMap(), _Kubb_instances = new WeakSet(), configLogs_fn = function(config) {
7028
+ var _a2, _b, _c, _d, _e;
7029
+ const u = __privateGet(this, _userConfig);
7030
+ const diag = getDiagnosticInfo();
7031
+ return [
7032
+ "Configuration:",
7033
+ ` \u2022 Name: ${u.name || "unnamed"}`,
7034
+ ` \u2022 Root: ${u.root || process.cwd()}`,
7035
+ ` \u2022 Output: ${((_a2 = u.output) == null ? void 0 : _a2.path) || "not specified"}`,
7036
+ ` \u2022 Plugins: ${((_b = u.plugins) == null ? void 0 : _b.length) || 0}`,
7037
+ "Output Settings:",
7038
+ ` \u2022 Storage: ${config.storage.name}`,
7039
+ ` \u2022 Formatter: ${((_c = u.output) == null ? void 0 : _c.format) || "none"}`,
7040
+ ` \u2022 Linter: ${((_d = u.output) == null ? void 0 : _d.lint) || "none"}`,
7041
+ `Running adapter: ${((_e = config.adapter) == null ? void 0 : _e.name) || "none"}`,
7042
+ "Environment:",
7043
+ Object.entries(diag).map(([key, value]) => ` \u2022 ${key}: ${value}`).join("\n")
7044
+ ];
7045
+ }, _a);
6974
7046
  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;
7047
+ return new Kubb(userConfig, options);
7007
7048
  }
7008
7049
  const memoryStorage = createStorage(() => {
7009
7050
  const store = /* @__PURE__ */ new Map();
@@ -7036,7 +7077,7 @@ const memoryStorage = createStorage(() => {
7036
7077
  };
7037
7078
  });
7038
7079
 
7039
- var version = "5.0.0-beta.20";
7080
+ var version = "5.0.0-beta.21";
7040
7081
 
7041
7082
  function isCommandMessage(msg) {
7042
7083
  return msg.type === "command";
@@ -7390,15 +7431,17 @@ function setupEventsStream(ws, hooks) {
7390
7431
  timestamp: Date.now()
7391
7432
  });
7392
7433
  });
7393
- hooks.on("kubb:file:processing:update", (ctx) => {
7434
+ hooks.on("kubb:files:processing:update", ({ files }) => {
7394
7435
  sendDataMessage({
7395
- type: "kubb:file:processing:update",
7436
+ type: "kubb:files:processing:update",
7396
7437
  data: [
7397
7438
  {
7398
- file: ctx.file.path,
7399
- processed: ctx.processed,
7400
- total: ctx.total,
7401
- percentage: ctx.percentage
7439
+ files: files.map((ctx) => ({
7440
+ file: ctx.file.path,
7441
+ processed: ctx.processed,
7442
+ total: ctx.total,
7443
+ percentage: ctx.percentage
7444
+ }))
7402
7445
  }
7403
7446
  ],
7404
7447
  timestamp: Date.now()