@kubb/core 5.0.0-alpha.43 → 5.0.0-alpha.45

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.
@@ -27,7 +27,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  let node_path = require("node:path");
28
28
  node_path = __toESM(node_path, 1);
29
29
  let _kubb_ast = require("@kubb/ast");
30
- let node_perf_hooks = require("node:perf_hooks");
31
30
  let fflate = require("fflate");
32
31
  let tinyexec = require("tinyexec");
33
32
  //#region ../../internals/utils/src/casing.ts
@@ -88,141 +87,6 @@ function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
88
87
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
89
88
  }
90
89
  //#endregion
91
- //#region ../../internals/utils/src/promise.ts
92
- /** Returns `true` when `result` is a rejected `Promise.allSettled` result with a typed `reason`.
93
- *
94
- * @example
95
- * ```ts
96
- * const results = await Promise.allSettled([p1, p2])
97
- * results.filter(isPromiseRejectedResult<Error>).map((r) => r.reason.message)
98
- * ```
99
- */
100
- function isPromiseRejectedResult(result) {
101
- return result.status === "rejected";
102
- }
103
- //#endregion
104
- //#region ../../internals/utils/src/reserved.ts
105
- /**
106
- * JavaScript and Java reserved words.
107
- * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
108
- */
109
- const reservedWords = new Set([
110
- "abstract",
111
- "arguments",
112
- "boolean",
113
- "break",
114
- "byte",
115
- "case",
116
- "catch",
117
- "char",
118
- "class",
119
- "const",
120
- "continue",
121
- "debugger",
122
- "default",
123
- "delete",
124
- "do",
125
- "double",
126
- "else",
127
- "enum",
128
- "eval",
129
- "export",
130
- "extends",
131
- "false",
132
- "final",
133
- "finally",
134
- "float",
135
- "for",
136
- "function",
137
- "goto",
138
- "if",
139
- "implements",
140
- "import",
141
- "in",
142
- "instanceof",
143
- "int",
144
- "interface",
145
- "let",
146
- "long",
147
- "native",
148
- "new",
149
- "null",
150
- "package",
151
- "private",
152
- "protected",
153
- "public",
154
- "return",
155
- "short",
156
- "static",
157
- "super",
158
- "switch",
159
- "synchronized",
160
- "this",
161
- "throw",
162
- "throws",
163
- "transient",
164
- "true",
165
- "try",
166
- "typeof",
167
- "var",
168
- "void",
169
- "volatile",
170
- "while",
171
- "with",
172
- "yield",
173
- "Array",
174
- "Date",
175
- "hasOwnProperty",
176
- "Infinity",
177
- "isFinite",
178
- "isNaN",
179
- "isPrototypeOf",
180
- "length",
181
- "Math",
182
- "name",
183
- "NaN",
184
- "Number",
185
- "Object",
186
- "prototype",
187
- "String",
188
- "toString",
189
- "undefined",
190
- "valueOf"
191
- ]);
192
- /**
193
- * Prefixes `word` with `_` when it is a reserved JavaScript/Java identifier or starts with a digit.
194
- *
195
- * @example
196
- * ```ts
197
- * transformReservedWord('class') // '_class'
198
- * transformReservedWord('42foo') // '_42foo'
199
- * transformReservedWord('status') // 'status'
200
- * ```
201
- */
202
- function transformReservedWord(word) {
203
- const firstChar = word.charCodeAt(0);
204
- if (word && (reservedWords.has(word) || firstChar >= 48 && firstChar <= 57)) return `_${word}`;
205
- return word;
206
- }
207
- /**
208
- * Returns `true` when `name` is a syntactically valid JavaScript variable name.
209
- *
210
- * @example
211
- * ```ts
212
- * isValidVarName('status') // true
213
- * isValidVarName('class') // false (reserved word)
214
- * isValidVarName('42foo') // false (starts with digit)
215
- * ```
216
- */
217
- function isValidVarName(name) {
218
- try {
219
- new Function(`var ${name}`);
220
- } catch {
221
- return false;
222
- }
223
- return true;
224
- }
225
- //#endregion
226
90
  //#region ../../internals/utils/src/string.ts
227
91
  /**
228
92
  * Strips the file extension from a path or file name.
@@ -246,9 +110,16 @@ function trimExtName(text) {
246
110
  */
247
111
  const DEFAULT_STUDIO_URL = "https://studio.kubb.dev";
248
112
  /**
113
+ * Basename (without extension) of generated barrel files.
114
+ *
115
+ * Used to detect whether a path already points at a barrel so the generator
116
+ * avoids re-creating one on top of it.
117
+ */
118
+ const BARREL_BASENAME = "index";
119
+ /**
249
120
  * File name used for generated barrel (index) files.
250
121
  */
251
- const BARREL_FILENAME = "index.ts";
122
+ const BARREL_FILENAME = `${BARREL_BASENAME}.ts`;
252
123
  /**
253
124
  * Default banner style written at the top of every generated file.
254
125
  */
@@ -271,181 +142,29 @@ const logLevel = {
271
142
  debug: 5
272
143
  };
273
144
  //#endregion
274
- //#region ../../node_modules/.pnpm/yocto-queue@1.2.2/node_modules/yocto-queue/index.js
275
- var Node = class {
276
- value;
277
- next;
278
- constructor(value) {
279
- this.value = value;
280
- }
281
- };
282
- var Queue = class {
283
- #head;
284
- #tail;
285
- #size;
286
- constructor() {
287
- this.clear();
288
- }
289
- enqueue(value) {
290
- const node = new Node(value);
291
- if (this.#head) {
292
- this.#tail.next = node;
293
- this.#tail = node;
294
- } else {
295
- this.#head = node;
296
- this.#tail = node;
297
- }
298
- this.#size++;
299
- }
300
- dequeue() {
301
- const current = this.#head;
302
- if (!current) return;
303
- this.#head = this.#head.next;
304
- this.#size--;
305
- if (!this.#head) this.#tail = void 0;
306
- return current.value;
307
- }
308
- peek() {
309
- if (!this.#head) return;
310
- return this.#head.value;
311
- }
312
- clear() {
313
- this.#head = void 0;
314
- this.#tail = void 0;
315
- this.#size = 0;
316
- }
317
- get size() {
318
- return this.#size;
319
- }
320
- *[Symbol.iterator]() {
321
- let current = this.#head;
322
- while (current) {
323
- yield current.value;
324
- current = current.next;
145
+ //#region src/defineResolver.ts
146
+ const stringPatternCache = /* @__PURE__ */ new Map();
147
+ function testPattern(value, pattern) {
148
+ if (typeof pattern === "string") {
149
+ let regex = stringPatternCache.get(pattern);
150
+ if (!regex) {
151
+ regex = new RegExp(pattern);
152
+ stringPatternCache.set(pattern, regex);
325
153
  }
154
+ return regex.test(value);
326
155
  }
327
- *drain() {
328
- while (this.#head) yield this.dequeue();
329
- }
330
- };
331
- //#endregion
332
- //#region ../../node_modules/.pnpm/p-limit@7.3.0/node_modules/p-limit/index.js
333
- function pLimit(concurrency) {
334
- let rejectOnClear = false;
335
- if (typeof concurrency === "object") ({concurrency, rejectOnClear = false} = concurrency);
336
- validateConcurrency(concurrency);
337
- if (typeof rejectOnClear !== "boolean") throw new TypeError("Expected `rejectOnClear` to be a boolean");
338
- const queue = new Queue();
339
- let activeCount = 0;
340
- const resumeNext = () => {
341
- if (activeCount < concurrency && queue.size > 0) {
342
- activeCount++;
343
- queue.dequeue().run();
344
- }
345
- };
346
- const next = () => {
347
- activeCount--;
348
- resumeNext();
349
- };
350
- const run = async (function_, resolve, arguments_) => {
351
- const result = (async () => function_(...arguments_))();
352
- resolve(result);
353
- try {
354
- await result;
355
- } catch {}
356
- next();
357
- };
358
- const enqueue = (function_, resolve, reject, arguments_) => {
359
- const queueItem = { reject };
360
- new Promise((internalResolve) => {
361
- queueItem.run = internalResolve;
362
- queue.enqueue(queueItem);
363
- }).then(run.bind(void 0, function_, resolve, arguments_));
364
- if (activeCount < concurrency) resumeNext();
365
- };
366
- const generator = (function_, ...arguments_) => new Promise((resolve, reject) => {
367
- enqueue(function_, resolve, reject, arguments_);
368
- });
369
- Object.defineProperties(generator, {
370
- activeCount: { get: () => activeCount },
371
- pendingCount: { get: () => queue.size },
372
- clearQueue: { value() {
373
- if (!rejectOnClear) {
374
- queue.clear();
375
- return;
376
- }
377
- const abortError = AbortSignal.abort().reason;
378
- while (queue.size > 0) queue.dequeue().reject(abortError);
379
- } },
380
- concurrency: {
381
- get: () => concurrency,
382
- set(newConcurrency) {
383
- validateConcurrency(newConcurrency);
384
- concurrency = newConcurrency;
385
- queueMicrotask(() => {
386
- while (activeCount < concurrency && queue.size > 0) resumeNext();
387
- });
388
- }
389
- },
390
- map: { async value(iterable, function_) {
391
- const promises = Array.from(iterable, (value, index) => this(function_, value, index));
392
- return Promise.all(promises);
393
- } }
394
- });
395
- return generator;
396
- }
397
- function validateConcurrency(concurrency) {
398
- if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) throw new TypeError("Expected `concurrency` to be a number from 1 and up");
399
- }
400
- //#endregion
401
- //#region src/definePlugin.ts
402
- /**
403
- * Returns `true` when `plugin` is a hook-style plugin created with `definePlugin`.
404
- *
405
- * Used by `PluginDriver` to distinguish hook-style plugins from legacy `createPlugin` plugins
406
- * so it can normalize them and register their handlers on the `AsyncEventEmitter`.
407
- */
408
- function isHookStylePlugin(plugin) {
409
- return typeof plugin === "object" && plugin !== null && "hooks" in plugin;
410
- }
411
- /**
412
- * Creates a plugin factory using the new hook-style (`hooks:`) API.
413
- *
414
- * The returned factory is called with optional options and produces a `HookStylePlugin`
415
- * that coexists with plugins created via the legacy `createPlugin` API in the same
416
- * `kubb.config.ts`.
417
- *
418
- * Lifecycle handlers are registered on the `PluginDriver`'s `AsyncEventEmitter`, enabling
419
- * both the plugin's own handlers and external tooling (CLI, devtools) to observe every event.
420
- *
421
- * @example
422
- * ```ts
423
- * // With PluginFactoryOptions (recommended for real plugins)
424
- * export const pluginTs = definePlugin<PluginTs>((options) => ({
425
- * name: 'plugin-ts',
426
- * hooks: {
427
- * 'kubb:plugin:setup'(ctx) {
428
- * ctx.setResolver(resolverTs) // typed as Partial<ResolverTs>
429
- * },
430
- * },
431
- * }))
432
- * ```
433
- */
434
- function definePlugin(factory) {
435
- return (options) => factory(options ?? {});
156
+ return value.match(pattern) !== null;
436
157
  }
437
- //#endregion
438
- //#region src/defineResolver.ts
439
158
  /**
440
159
  * Checks if an operation matches a pattern for a given filter type (`tag`, `operationId`, `path`, `method`).
441
160
  */
442
161
  function matchesOperationPattern(node, type, pattern) {
443
162
  switch (type) {
444
- case "tag": return node.tags.some((tag) => !!tag.match(pattern));
445
- case "operationId": return !!node.operationId.match(pattern);
446
- case "path": return !!node.path.match(pattern);
447
- case "method": return !!node.method.toLowerCase().match(pattern);
448
- case "contentType": return !!node.requestBody?.contentType?.match(pattern);
163
+ case "tag": return node.tags.some((tag) => testPattern(tag, pattern));
164
+ case "operationId": return testPattern(node.operationId, pattern);
165
+ case "path": return testPattern(node.path, pattern);
166
+ case "method": return testPattern(node.method.toLowerCase(), pattern);
167
+ case "contentType": return node.requestBody?.contentType ? testPattern(node.requestBody.contentType, pattern) : false;
449
168
  default: return false;
450
169
  }
451
170
  }
@@ -456,7 +175,7 @@ function matchesOperationPattern(node, type, pattern) {
456
175
  */
457
176
  function matchesSchemaPattern(node, type, pattern) {
458
177
  switch (type) {
459
- case "schemaName": return node.name ? !!node.name.match(pattern) : false;
178
+ case "schemaName": return node.name ? testPattern(node.name, pattern) : false;
460
179
  default: return null;
461
180
  }
462
181
  }
@@ -850,17 +569,16 @@ var FileManager = class {
850
569
  add(...files) {
851
570
  const resolvedFiles = [];
852
571
  const mergedFiles = /* @__PURE__ */ new Map();
853
- files.forEach((file) => {
572
+ for (const file of files) {
854
573
  const existing = mergedFiles.get(file.path);
855
- if (existing) mergedFiles.set(file.path, mergeFile(existing, file));
856
- else mergedFiles.set(file.path, file);
857
- });
574
+ mergedFiles.set(file.path, existing ? mergeFile(existing, file) : file);
575
+ }
858
576
  for (const file of mergedFiles.values()) {
859
577
  const resolvedFile = (0, _kubb_ast.createFile)(file);
860
578
  this.#cache.set(resolvedFile.path, resolvedFile);
861
- this.#filesCache = null;
862
579
  resolvedFiles.push(resolvedFile);
863
580
  }
581
+ this.#filesCache = null;
864
582
  return resolvedFiles;
865
583
  }
866
584
  /**
@@ -870,18 +588,17 @@ var FileManager = class {
870
588
  upsert(...files) {
871
589
  const resolvedFiles = [];
872
590
  const mergedFiles = /* @__PURE__ */ new Map();
873
- files.forEach((file) => {
591
+ for (const file of files) {
874
592
  const existing = mergedFiles.get(file.path);
875
- if (existing) mergedFiles.set(file.path, mergeFile(existing, file));
876
- else mergedFiles.set(file.path, file);
877
- });
593
+ mergedFiles.set(file.path, existing ? mergeFile(existing, file) : file);
594
+ }
878
595
  for (const file of mergedFiles.values()) {
879
596
  const existing = this.#cache.get(file.path);
880
597
  const resolvedFile = (0, _kubb_ast.createFile)(existing ? mergeFile(existing, file) : file);
881
598
  this.#cache.set(resolvedFile.path, resolvedFile);
882
- this.#filesCache = null;
883
599
  resolvedFiles.push(resolvedFile);
884
600
  }
601
+ this.#filesCache = null;
885
602
  return resolvedFiles;
886
603
  }
887
604
  getByPath(path) {
@@ -901,10 +618,17 @@ var FileManager = class {
901
618
  */
902
619
  get files() {
903
620
  if (this.#filesCache) return this.#filesCache;
904
- const keys = [...this.#cache.keys()].sort((a, b) => {
905
- if (a.length !== b.length) return a.length - b.length;
906
- const aIsIndex = trimExtName(a).endsWith("index");
907
- if (aIsIndex !== trimExtName(b).endsWith("index")) return aIsIndex ? 1 : -1;
621
+ const keys = [...this.#cache.keys()];
622
+ const meta = /* @__PURE__ */ new Map();
623
+ for (const key of keys) meta.set(key, {
624
+ length: key.length,
625
+ isIndex: trimExtName(key).endsWith(BARREL_BASENAME)
626
+ });
627
+ keys.sort((a, b) => {
628
+ const ma = meta.get(a);
629
+ const mb = meta.get(b);
630
+ if (ma.length !== mb.length) return ma.length - mb.length;
631
+ if (ma.isIndex !== mb.isIndex) return ma.isIndex ? 1 : -1;
908
632
  return 0;
909
633
  });
910
634
  const files = [];
@@ -941,55 +665,7 @@ async function applyHookResult(result, driver, rendererFactory) {
941
665
  renderer.unmount();
942
666
  }
943
667
  //#endregion
944
- //#region src/utils/executeStrategies.ts
945
- /**
946
- * Runs promise functions in sequence, threading each result into the next call.
947
- *
948
- * - Each function receives the accumulated state from the previous call.
949
- * - Skips functions that return a falsy value (acts as a no-op for that step).
950
- * - Returns an array of all individual results.
951
- * @deprecated
952
- */
953
- function hookSeq(promises) {
954
- return promises.filter(Boolean).reduce((promise, func) => {
955
- if (typeof func !== "function") throw new Error("HookSeq needs a function that returns a promise `() => Promise<unknown>`");
956
- return promise.then((state) => {
957
- const calledFunc = func(state);
958
- if (calledFunc) return calledFunc.then(Array.prototype.concat.bind(state));
959
- return state;
960
- });
961
- }, Promise.resolve([]));
962
- }
963
- /**
964
- * Runs promise functions in sequence and returns the first non-null result.
965
- *
966
- * - Stops as soon as `nullCheck` passes for a result (default: `!== null`).
967
- * - Subsequent functions are skipped once a match is found.
968
- * @deprecated
969
- */
970
- function hookFirst(promises, nullCheck = (state) => state !== null) {
971
- let promise = Promise.resolve(null);
972
- for (const func of promises.filter(Boolean)) promise = promise.then((state) => {
973
- if (nullCheck(state)) return state;
974
- return func(state);
975
- });
976
- return promise;
977
- }
978
- /**
979
- * Runs promise functions concurrently and returns all settled results.
980
- *
981
- * - Limits simultaneous executions to `concurrency` (default: unlimited).
982
- * - Uses `Promise.allSettled` so individual failures do not cancel other tasks.
983
- * @deprecated
984
- */
985
- function hookParallel(promises, concurrency = Number.POSITIVE_INFINITY) {
986
- const limit = pLimit(concurrency);
987
- const tasks = promises.filter(Boolean).map((promise) => limit(() => promise()));
988
- return Promise.allSettled(tasks);
989
- }
990
- //#endregion
991
668
  //#region src/PluginDriver.ts
992
- const hookFirstNullCheck = (state) => !!state?.result;
993
669
  var PluginDriver = class PluginDriver {
994
670
  config;
995
671
  options;
@@ -1030,18 +706,8 @@ var PluginDriver = class PluginDriver {
1030
706
  #hookListeners = /* @__PURE__ */ new Map();
1031
707
  constructor(config, options) {
1032
708
  this.config = config;
1033
- this.options = {
1034
- ...options,
1035
- hooks: options.hooks
1036
- };
1037
- config.plugins.map((rawPlugin) => {
1038
- if (isHookStylePlugin(rawPlugin)) return this.#normalizeHookStylePlugin(rawPlugin);
1039
- return {
1040
- ...rawPlugin,
1041
- buildStart: rawPlugin.buildStart ?? (() => {}),
1042
- buildEnd: rawPlugin.buildEnd ?? (() => {})
1043
- };
1044
- }).filter((plugin) => {
709
+ this.options = options;
710
+ config.plugins.map((rawPlugin) => this.#normalizePlugin(rawPlugin)).filter((plugin) => {
1045
711
  if (typeof plugin.apply === "function") return plugin.apply(config);
1046
712
  return true;
1047
713
  }).sort((a, b) => {
@@ -1053,20 +719,13 @@ var PluginDriver = class PluginDriver {
1053
719
  });
1054
720
  }
1055
721
  get hooks() {
1056
- if (!this.options.hooks) throw new Error("hooks are not defined");
1057
722
  return this.options.hooks;
1058
723
  }
1059
724
  /**
1060
- * Creates a `Plugin`-compatible object from a hook-style plugin and registers
725
+ * Creates an `NormalizedPlugin` from a hook-style plugin and registers
1061
726
  * its lifecycle handlers on the `AsyncEventEmitter`.
1062
- *
1063
- * The normalized plugin has an empty `buildStart` — generators registered via
1064
- * `addGenerator()` in `kubb:plugin:setup` are stored on `normalizedPlugin.generators`
1065
- * and used by `runPluginAstHooks` during the build.
1066
727
  */
1067
- #normalizeHookStylePlugin(hookPlugin) {
1068
- const generators = [];
1069
- const driver = this;
728
+ #normalizePlugin(hookPlugin) {
1070
729
  const normalizedPlugin = {
1071
730
  name: hookPlugin.name,
1072
731
  dependencies: hookPlugin.dependencies,
@@ -1074,29 +733,7 @@ var PluginDriver = class PluginDriver {
1074
733
  output: { path: "." },
1075
734
  exclude: [],
1076
735
  override: []
1077
- },
1078
- generators,
1079
- inject: () => void 0,
1080
- resolveName(name, type) {
1081
- return driver.getResolver(hookPlugin.name).default(name, type);
1082
- },
1083
- resolvePath(baseName, pathMode, resolveOptions) {
1084
- const resolver = driver.getResolver(hookPlugin.name);
1085
- const opts = normalizedPlugin.options;
1086
- const group = resolveOptions?.group;
1087
- return resolver.resolvePath({
1088
- baseName,
1089
- pathMode,
1090
- tag: group?.tag,
1091
- path: group?.path
1092
- }, {
1093
- root: (0, node_path.resolve)(driver.config.root, driver.config.output.path),
1094
- output: opts.output,
1095
- group: opts.group
1096
- });
1097
- },
1098
- buildStart() {},
1099
- buildEnd() {}
736
+ }
1100
737
  };
1101
738
  this.registerPluginHooks(hookPlugin, normalizedPlugin);
1102
739
  return normalizedPlugin;
@@ -1113,6 +750,8 @@ var PluginDriver = class PluginDriver {
1113
750
  *
1114
751
  * External tooling can subscribe to any of these events via `hooks.on(...)` to observe
1115
752
  * the plugin lifecycle without modifying plugin behavior.
753
+ *
754
+ * @internal
1116
755
  */
1117
756
  registerPluginHooks(hookPlugin, normalizedPlugin) {
1118
757
  const { hooks } = hookPlugin;
@@ -1139,15 +778,13 @@ var PluginDriver = class PluginDriver {
1139
778
  ...opts
1140
779
  };
1141
780
  },
1142
- injectFile: (file) => {
1143
- const fileNode = (0, _kubb_ast.createFile)({
1144
- baseName: file.baseName,
1145
- path: file.path,
1146
- sources: file.sources ?? [],
781
+ injectFile: ({ sources = [], ...rest }) => {
782
+ this.fileManager.add((0, _kubb_ast.createFile)({
1147
783
  imports: [],
1148
- exports: []
1149
- });
1150
- this.fileManager.add(fileNode);
784
+ exports: [],
785
+ sources,
786
+ ...rest
787
+ }));
1151
788
  }
1152
789
  };
1153
790
  return hooks["kubb:plugin:setup"](pluginCtx);
@@ -1168,16 +805,17 @@ var PluginDriver = class PluginDriver {
1168
805
  * Call this once from `safeBuild` before the plugin execution loop begins.
1169
806
  */
1170
807
  async emitSetupHooks() {
808
+ const noop = () => {};
1171
809
  await this.hooks.emit("kubb:plugin:setup", {
1172
810
  config: this.config,
1173
- addGenerator: () => {},
1174
- setResolver: () => {},
1175
- setTransformer: () => {},
1176
- setRenderer: () => {},
1177
- setOptions: () => {},
1178
- injectFile: () => {},
1179
- updateConfig: () => {},
1180
- options: {}
811
+ options: {},
812
+ addGenerator: noop,
813
+ setResolver: noop,
814
+ setTransformer: noop,
815
+ setRenderer: noop,
816
+ setOptions: noop,
817
+ injectFile: noop,
818
+ updateConfig: noop
1181
819
  });
1182
820
  }
1183
821
  /**
@@ -1235,6 +873,12 @@ var PluginDriver = class PluginDriver {
1235
873
  hasRegisteredGenerators(pluginName) {
1236
874
  return this.#pluginsWithEventGenerators.has(pluginName);
1237
875
  }
876
+ /**
877
+ * Unregisters all plugin lifecycle listeners from the shared event emitter.
878
+ * Called at the end of a build to prevent listener leaks across repeated builds.
879
+ *
880
+ * @internal
881
+ */
1238
882
  dispose() {
1239
883
  for (const [event, handlers] of this.#hookListeners) for (const handler of handlers) this.hooks.off(event, handler);
1240
884
  this.#hookListeners.clear();
@@ -1258,6 +902,11 @@ var PluginDriver = class PluginDriver {
1258
902
  this.#defaultResolvers.set(pluginName, resolver);
1259
903
  return resolver;
1260
904
  }
905
+ /**
906
+ * Merges `partial` with the plugin's default resolver and stores the result.
907
+ * Also mirrors it onto `plugin.resolver` so callers using `getPlugin(name).resolver`
908
+ * get the up-to-date resolver without going through `getResolver()`.
909
+ */
1261
910
  setPluginResolver(pluginName, partial) {
1262
911
  const merged = {
1263
912
  ...this.#createDefaultResolver(pluginName),
@@ -1267,16 +916,18 @@ var PluginDriver = class PluginDriver {
1267
916
  const plugin = this.plugins.get(pluginName);
1268
917
  if (plugin) plugin.resolver = merged;
1269
918
  }
919
+ /**
920
+ * Returns the resolver for the given plugin.
921
+ *
922
+ * Resolution order: dynamic resolver set via `setPluginResolver` → static resolver on the
923
+ * plugin → lazily created default resolver (identity name, no path transforms).
924
+ */
1270
925
  getResolver(pluginName) {
1271
- const dynamicResolver = this.#resolvers.get(pluginName);
1272
- if (dynamicResolver) return dynamicResolver;
1273
- const pluginResolver = this.plugins.get(pluginName)?.resolver;
1274
- if (pluginResolver) return pluginResolver;
1275
- return this.#createDefaultResolver(pluginName);
926
+ return this.#resolvers.get(pluginName) ?? this.plugins.get(pluginName)?.resolver ?? this.#createDefaultResolver(pluginName);
1276
927
  }
1277
928
  getContext(plugin) {
1278
929
  const driver = this;
1279
- const baseContext = {
930
+ return {
1280
931
  config: driver.config,
1281
932
  get root() {
1282
933
  return (0, node_path.resolve)(driver.config.root, driver.config.output.path);
@@ -1325,225 +976,6 @@ var PluginDriver = class PluginDriver {
1325
976
  return openInStudio(driver.inputNode, studioUrl, options);
1326
977
  }
1327
978
  };
1328
- let mergedExtras = {};
1329
- for (const p of this.plugins.values()) if (typeof p.inject === "function") {
1330
- const result = p.inject.call(baseContext);
1331
- if (result !== null && typeof result === "object") mergedExtras = {
1332
- ...mergedExtras,
1333
- ...result
1334
- };
1335
- }
1336
- return {
1337
- ...baseContext,
1338
- ...mergedExtras
1339
- };
1340
- }
1341
- /**
1342
- * @deprecated use resolvers context instead
1343
- */
1344
- getFile({ name, mode, extname, pluginName, options }) {
1345
- const resolvedName = mode ? mode === "single" ? "" : this.resolveName({
1346
- name,
1347
- pluginName,
1348
- type: "file"
1349
- }) : name;
1350
- const path = this.resolvePath({
1351
- baseName: `${resolvedName}${extname}`,
1352
- mode,
1353
- pluginName,
1354
- options
1355
- });
1356
- if (!path) throw new Error(`Filepath should be defined for resolvedName "${resolvedName}" and pluginName "${pluginName}"`);
1357
- return (0, _kubb_ast.createFile)({
1358
- path,
1359
- baseName: (0, node_path.basename)(path),
1360
- meta: { pluginName },
1361
- sources: [],
1362
- imports: [],
1363
- exports: []
1364
- });
1365
- }
1366
- /**
1367
- * @deprecated use resolvers context instead
1368
- */
1369
- resolvePath = (params) => {
1370
- const defaultPath = (0, node_path.resolve)((0, node_path.resolve)(this.config.root, this.config.output.path), params.baseName);
1371
- if (params.pluginName) return this.hookForPluginSync({
1372
- pluginName: params.pluginName,
1373
- hookName: "resolvePath",
1374
- parameters: [
1375
- params.baseName,
1376
- params.mode,
1377
- params.options
1378
- ]
1379
- })?.at(0) || defaultPath;
1380
- return this.hookFirstSync({
1381
- hookName: "resolvePath",
1382
- parameters: [
1383
- params.baseName,
1384
- params.mode,
1385
- params.options
1386
- ]
1387
- })?.result || defaultPath;
1388
- };
1389
- /**
1390
- * @deprecated use resolvers context instead
1391
- */
1392
- resolveName = (params) => {
1393
- if (params.pluginName) return transformReservedWord(this.hookForPluginSync({
1394
- pluginName: params.pluginName,
1395
- hookName: "resolveName",
1396
- parameters: [params.name.trim(), params.type]
1397
- })?.at(0) ?? params.name);
1398
- const name = this.hookFirstSync({
1399
- hookName: "resolveName",
1400
- parameters: [params.name.trim(), params.type]
1401
- })?.result;
1402
- return transformReservedWord(name ?? params.name);
1403
- };
1404
- /**
1405
- * Run a specific hookName for plugin x.
1406
- */
1407
- async hookForPlugin({ pluginName, hookName, parameters }) {
1408
- const plugin = this.plugins.get(pluginName);
1409
- if (!plugin) return [null];
1410
- this.hooks.emit("kubb:plugins:hook:progress:start", {
1411
- hookName,
1412
- plugins: [plugin]
1413
- });
1414
- const result = await this.#execute({
1415
- strategy: "hookFirst",
1416
- hookName,
1417
- parameters,
1418
- plugin
1419
- });
1420
- this.hooks.emit("kubb:plugins:hook:progress:end", { hookName });
1421
- return [result];
1422
- }
1423
- /**
1424
- * Run a specific hookName for plugin x.
1425
- */
1426
- hookForPluginSync({ pluginName, hookName, parameters }) {
1427
- const plugin = this.plugins.get(pluginName);
1428
- if (!plugin) return null;
1429
- const result = this.#executeSync({
1430
- strategy: "hookFirst",
1431
- hookName,
1432
- parameters,
1433
- plugin
1434
- });
1435
- return result !== null ? [result] : [];
1436
- }
1437
- /**
1438
- * Returns the first non-null result.
1439
- */
1440
- async hookFirst({ hookName, parameters, skipped }) {
1441
- const plugins = [];
1442
- for (const plugin of this.plugins.values()) if (hookName in plugin && (skipped ? !skipped.has(plugin) : true)) plugins.push(plugin);
1443
- this.hooks.emit("kubb:plugins:hook:progress:start", {
1444
- hookName,
1445
- plugins
1446
- });
1447
- const result = await hookFirst(plugins.map((plugin) => {
1448
- return async () => {
1449
- const value = await this.#execute({
1450
- strategy: "hookFirst",
1451
- hookName,
1452
- parameters,
1453
- plugin
1454
- });
1455
- return Promise.resolve({
1456
- plugin,
1457
- result: value
1458
- });
1459
- };
1460
- }), hookFirstNullCheck);
1461
- this.hooks.emit("kubb:plugins:hook:progress:end", { hookName });
1462
- return result;
1463
- }
1464
- /**
1465
- * Returns the first non-null result.
1466
- */
1467
- hookFirstSync({ hookName, parameters, skipped }) {
1468
- let parseResult = null;
1469
- for (const plugin of this.plugins.values()) {
1470
- if (!(hookName in plugin)) continue;
1471
- if (skipped?.has(plugin)) continue;
1472
- parseResult = {
1473
- result: this.#executeSync({
1474
- strategy: "hookFirst",
1475
- hookName,
1476
- parameters,
1477
- plugin
1478
- }),
1479
- plugin
1480
- };
1481
- if (parseResult.result != null) break;
1482
- }
1483
- return parseResult;
1484
- }
1485
- /**
1486
- * Runs all plugins in parallel based on `this.plugin` order and `dependencies` settings.
1487
- */
1488
- async hookParallel({ hookName, parameters }) {
1489
- const plugins = [];
1490
- for (const plugin of this.plugins.values()) if (hookName in plugin) plugins.push(plugin);
1491
- this.hooks.emit("kubb:plugins:hook:progress:start", {
1492
- hookName,
1493
- plugins
1494
- });
1495
- const pluginStartTimes = /* @__PURE__ */ new Map();
1496
- const results = await hookParallel(plugins.map((plugin) => {
1497
- return () => {
1498
- pluginStartTimes.set(plugin, node_perf_hooks.performance.now());
1499
- return this.#execute({
1500
- strategy: "hookParallel",
1501
- hookName,
1502
- parameters,
1503
- plugin
1504
- });
1505
- };
1506
- }), this.options.concurrency);
1507
- results.forEach((result, index) => {
1508
- if (isPromiseRejectedResult(result)) {
1509
- const plugin = plugins[index];
1510
- if (plugin) {
1511
- const startTime = pluginStartTimes.get(plugin) ?? node_perf_hooks.performance.now();
1512
- this.hooks.emit("kubb:error", result.reason, {
1513
- plugin,
1514
- hookName,
1515
- strategy: "hookParallel",
1516
- duration: Math.round(node_perf_hooks.performance.now() - startTime),
1517
- parameters
1518
- });
1519
- }
1520
- }
1521
- });
1522
- this.hooks.emit("kubb:plugins:hook:progress:end", { hookName });
1523
- return results.reduce((acc, result) => {
1524
- if (result.status === "fulfilled") acc.push(result.value);
1525
- return acc;
1526
- }, []);
1527
- }
1528
- /**
1529
- * Execute a lifecycle hook sequentially for all plugins that implement it.
1530
- */
1531
- async hookSeq({ hookName, parameters }) {
1532
- const plugins = [];
1533
- for (const plugin of this.plugins.values()) if (hookName in plugin) plugins.push(plugin);
1534
- this.hooks.emit("kubb:plugins:hook:progress:start", {
1535
- hookName,
1536
- plugins
1537
- });
1538
- await hookSeq(plugins.map((plugin) => {
1539
- return () => this.#execute({
1540
- strategy: "hookSeq",
1541
- hookName,
1542
- parameters,
1543
- plugin
1544
- });
1545
- }));
1546
- this.hooks.emit("kubb:plugins:hook:progress:end", { hookName });
1547
979
  }
1548
980
  getPlugin(pluginName) {
1549
981
  return this.plugins.get(pluginName);
@@ -1553,88 +985,14 @@ var PluginDriver = class PluginDriver {
1553
985
  if (!plugin) throw new Error(`[kubb] Plugin "${pluginName}" is required but not found. Make sure it is included in your Kubb config.`);
1554
986
  return plugin;
1555
987
  }
1556
- /**
1557
- * Emit hook-processing completion metadata after a plugin hook resolves.
1558
- */
1559
- #emitProcessingEnd({ startTime, output, strategy, hookName, plugin, parameters }) {
1560
- this.hooks.emit("kubb:plugins:hook:processing:end", {
1561
- duration: Math.round(node_perf_hooks.performance.now() - startTime),
1562
- parameters,
1563
- output,
1564
- strategy,
1565
- hookName,
1566
- plugin
1567
- });
1568
- }
1569
- #execute({ strategy, hookName, parameters, plugin }) {
1570
- const hook = plugin[hookName];
1571
- if (!hook) return null;
1572
- this.hooks.emit("kubb:plugins:hook:processing:start", {
1573
- strategy,
1574
- hookName,
1575
- parameters,
1576
- plugin
1577
- });
1578
- const startTime = node_perf_hooks.performance.now();
1579
- return (async () => {
1580
- try {
1581
- const output = typeof hook === "function" ? await Promise.resolve(hook.apply(this.getContext(plugin), parameters ?? [])) : hook;
1582
- this.#emitProcessingEnd({
1583
- startTime,
1584
- output,
1585
- strategy,
1586
- hookName,
1587
- plugin,
1588
- parameters
1589
- });
1590
- return output;
1591
- } catch (error) {
1592
- this.hooks.emit("kubb:error", error, {
1593
- plugin,
1594
- hookName,
1595
- strategy,
1596
- duration: Math.round(node_perf_hooks.performance.now() - startTime)
1597
- });
1598
- return null;
1599
- }
1600
- })();
1601
- }
1602
- /**
1603
- * Execute a plugin lifecycle hook synchronously and return its output.
1604
- */
1605
- #executeSync({ strategy, hookName, parameters, plugin }) {
1606
- const hook = plugin[hookName];
1607
- if (!hook) return null;
1608
- this.hooks.emit("kubb:plugins:hook:processing:start", {
1609
- strategy,
1610
- hookName,
1611
- parameters,
1612
- plugin
1613
- });
1614
- const startTime = node_perf_hooks.performance.now();
1615
- try {
1616
- const output = typeof hook === "function" ? hook.apply(this.getContext(plugin), parameters) : hook;
1617
- this.#emitProcessingEnd({
1618
- startTime,
1619
- output,
1620
- strategy,
1621
- hookName,
1622
- plugin,
1623
- parameters
1624
- });
1625
- return output;
1626
- } catch (error) {
1627
- this.hooks.emit("kubb:error", error, {
1628
- plugin,
1629
- hookName,
1630
- strategy,
1631
- duration: Math.round(node_perf_hooks.performance.now() - startTime)
1632
- });
1633
- return null;
1634
- }
1635
- }
1636
988
  };
1637
989
  //#endregion
990
+ Object.defineProperty(exports, "BARREL_BASENAME", {
991
+ enumerable: true,
992
+ get: function() {
993
+ return BARREL_BASENAME;
994
+ }
995
+ });
1638
996
  Object.defineProperty(exports, "BARREL_FILENAME", {
1639
997
  enumerable: true,
1640
998
  get: function() {
@@ -1695,35 +1053,17 @@ Object.defineProperty(exports, "camelCase", {
1695
1053
  return camelCase;
1696
1054
  }
1697
1055
  });
1698
- Object.defineProperty(exports, "definePlugin", {
1699
- enumerable: true,
1700
- get: function() {
1701
- return definePlugin;
1702
- }
1703
- });
1704
1056
  Object.defineProperty(exports, "defineResolver", {
1705
1057
  enumerable: true,
1706
1058
  get: function() {
1707
1059
  return defineResolver;
1708
1060
  }
1709
1061
  });
1710
- Object.defineProperty(exports, "isValidVarName", {
1711
- enumerable: true,
1712
- get: function() {
1713
- return isValidVarName;
1714
- }
1715
- });
1716
1062
  Object.defineProperty(exports, "logLevel", {
1717
1063
  enumerable: true,
1718
1064
  get: function() {
1719
1065
  return logLevel;
1720
1066
  }
1721
1067
  });
1722
- Object.defineProperty(exports, "pLimit", {
1723
- enumerable: true,
1724
- get: function() {
1725
- return pLimit;
1726
- }
1727
- });
1728
1068
 
1729
- //# sourceMappingURL=PluginDriver-BQwm8hDd.cjs.map
1069
+ //# sourceMappingURL=PluginDriver-rVSfG8tW.cjs.map