@kubb/core 5.0.0-alpha.34 → 5.0.0-alpha.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/PluginDriver-B_65W4fv.js +1677 -0
  2. package/dist/PluginDriver-B_65W4fv.js.map +1 -0
  3. package/dist/{PluginDriver-BBi_41VF.d.ts → PluginDriver-C9iBgYbk.d.ts} +743 -376
  4. package/dist/PluginDriver-CCdkwR14.cjs +1806 -0
  5. package/dist/PluginDriver-CCdkwR14.cjs.map +1 -0
  6. package/dist/hooks.d.ts +1 -1
  7. package/dist/index.cjs +272 -1666
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.ts +62 -141
  10. package/dist/index.js +231 -1623
  11. package/dist/index.js.map +1 -1
  12. package/dist/mocks.cjs +165 -0
  13. package/dist/mocks.cjs.map +1 -0
  14. package/dist/mocks.d.ts +74 -0
  15. package/dist/mocks.js +159 -0
  16. package/dist/mocks.js.map +1 -0
  17. package/package.json +11 -5
  18. package/src/FileManager.ts +1 -1
  19. package/src/FileProcessor.ts +1 -1
  20. package/src/Kubb.ts +145 -38
  21. package/src/PluginDriver.ts +318 -40
  22. package/src/constants.ts +1 -1
  23. package/src/{build.ts → createKubb.ts} +180 -122
  24. package/src/createPlugin.ts +1 -0
  25. package/src/createRenderer.ts +57 -0
  26. package/src/defineGenerator.ts +57 -84
  27. package/src/defineLogger.ts +2 -2
  28. package/src/defineParser.ts +3 -2
  29. package/src/definePlugin.ts +95 -0
  30. package/src/defineResolver.ts +1 -1
  31. package/src/devtools.ts +1 -1
  32. package/src/index.ts +7 -6
  33. package/src/mocks.ts +234 -0
  34. package/src/renderNode.ts +35 -0
  35. package/src/types.ts +275 -210
  36. package/src/utils/TreeNode.ts +1 -1
  37. package/src/utils/getBarrelFiles.ts +3 -3
  38. package/src/utils/getFunctionParams.ts +14 -7
  39. package/src/utils/isInputPath.ts +2 -2
  40. package/src/utils/packageJSON.ts +2 -3
  41. package/src/defineConfig.ts +0 -51
  42. package/src/definePresets.ts +0 -16
  43. package/src/renderNode.tsx +0 -28
  44. package/src/utils/getConfigs.ts +0 -16
  45. package/src/utils/getPreset.ts +0 -78
package/dist/index.cjs CHANGED
@@ -1,23 +1,16 @@
1
- Object.defineProperties(exports, {
2
- __esModule: { value: true },
3
- [Symbol.toStringTag]: { value: "Module" }
4
- });
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
5
2
  const require_chunk = require("./chunk-ByKO4r7w.cjs");
3
+ const require_PluginDriver = require("./PluginDriver-CCdkwR14.cjs");
6
4
  let node_events = require("node:events");
7
5
  let node_fs = require("node:fs");
8
6
  let node_fs_promises = require("node:fs/promises");
9
7
  let node_path = require("node:path");
10
- node_path = require_chunk.__toESM(node_path);
8
+ node_path = require_chunk.__toESM(node_path, 1);
11
9
  let _kubb_ast = require("@kubb/ast");
12
- let node_perf_hooks = require("node:perf_hooks");
13
- let fflate = require("fflate");
10
+ _kubb_ast = require_chunk.__toESM(_kubb_ast, 1);
14
11
  let tinyexec = require("tinyexec");
15
- let _kubb_renderer_jsx = require("@kubb/renderer-jsx");
16
- let _kubb_renderer_jsx_jsx_runtime = require("@kubb/renderer-jsx/jsx-runtime");
17
12
  let node_process = require("node:process");
18
13
  let remeda = require("remeda");
19
- let empathic_package = require("empathic/package");
20
- empathic_package = require_chunk.__toESM(empathic_package);
21
14
  let semver = require("semver");
22
15
  //#region ../../internals/utils/src/errors.ts
23
16
  /**
@@ -135,6 +128,18 @@ var AsyncEventEmitter = class {
135
128
  this.#emitter.off(eventName, handler);
136
129
  }
137
130
  /**
131
+ * Returns the number of listeners registered for `eventName`.
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * emitter.on('build', handler)
136
+ * emitter.listenerCount('build') // 1
137
+ * ```
138
+ */
139
+ listenerCount(eventName) {
140
+ return this.#emitter.listenerCount(eventName);
141
+ }
142
+ /**
138
143
  * Removes all listeners from every event channel.
139
144
  *
140
145
  * @example
@@ -147,64 +152,6 @@ var AsyncEventEmitter = class {
147
152
  }
148
153
  };
149
154
  //#endregion
150
- //#region ../../internals/utils/src/casing.ts
151
- /**
152
- * Shared implementation for camelCase and PascalCase conversion.
153
- * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
154
- * and capitalizes each word according to `pascal`.
155
- *
156
- * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
157
- */
158
- function toCamelOrPascal(text, pascal) {
159
- 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) => {
160
- if (word.length > 1 && word === word.toUpperCase()) return word;
161
- if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
162
- return word.charAt(0).toUpperCase() + word.slice(1);
163
- }).join("").replace(/[^a-zA-Z0-9]/g, "");
164
- }
165
- /**
166
- * Splits `text` on `.` and applies `transformPart` to each segment.
167
- * The last segment receives `isLast = true`, all earlier segments receive `false`.
168
- * Segments are joined with `/` to form a file path.
169
- *
170
- * Only splits on dots followed by a letter so that version numbers
171
- * embedded in operationIds (e.g. `v2025.0`) are kept intact.
172
- */
173
- function applyToFileParts(text, transformPart) {
174
- const parts = text.split(/\.(?=[a-zA-Z])/);
175
- return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
176
- }
177
- /**
178
- * Converts `text` to camelCase.
179
- * When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
180
- *
181
- * @example
182
- * camelCase('hello-world') // 'helloWorld'
183
- * camelCase('pet.petId', { isFile: true }) // 'pet/petId'
184
- */
185
- function camelCase(text, { isFile, prefix = "", suffix = "" } = {}) {
186
- if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
187
- prefix,
188
- suffix
189
- } : {}));
190
- return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
191
- }
192
- /**
193
- * Converts `text` to PascalCase.
194
- * When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.
195
- *
196
- * @example
197
- * pascalCase('hello-world') // 'HelloWorld'
198
- * pascalCase('pet.petId', { isFile: true }) // 'pet/PetId'
199
- */
200
- function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
201
- if (isFile) return applyToFileParts(text, (part, isLast) => isLast ? pascalCase(part, {
202
- prefix,
203
- suffix
204
- }) : camelCase(part));
205
- return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
206
- }
207
- //#endregion
208
155
  //#region ../../internals/utils/src/time.ts
209
156
  /**
210
157
  * Calculates elapsed time in milliseconds from a high-resolution `process.hrtime` start time.
@@ -240,6 +187,26 @@ function formatMs(ms) {
240
187
  //#endregion
241
188
  //#region ../../internals/utils/src/fs.ts
242
189
  /**
190
+ * Walks up the directory tree from `cwd` (defaults to `process.cwd()`) and
191
+ * returns the absolute path of the nearest `package.json`, or `null` when none
192
+ * is found before reaching the filesystem root.
193
+ *
194
+ * @example
195
+ * ```ts
196
+ * const pkgPath = findPackageJSON('/home/user/project/src') // '/home/user/project/package.json'
197
+ * ```
198
+ */
199
+ function findPackageJSON(cwd) {
200
+ let dir = cwd ? (0, node_path.resolve)(cwd) : process.cwd();
201
+ while (true) {
202
+ const pkgPath = (0, node_path.join)(dir, "package.json");
203
+ if ((0, node_fs.existsSync)(pkgPath)) return pkgPath;
204
+ const parent = (0, node_path.dirname)(dir);
205
+ if (parent === dir) return null;
206
+ dir = parent;
207
+ }
208
+ }
209
+ /**
243
210
  * Converts all backslashes to forward slashes.
244
211
  * Extended-length Windows paths (`\\?\...`) are left unchanged.
245
212
  */
@@ -338,159 +305,6 @@ async function clean(path) {
338
305
  });
339
306
  }
340
307
  //#endregion
341
- //#region ../../internals/utils/src/string.ts
342
- /**
343
- * Strips the file extension from a path or file name.
344
- * Only removes the last `.ext` segment when the dot is not part of a directory name.
345
- *
346
- * @example
347
- * trimExtName('petStore.ts') // 'petStore'
348
- * trimExtName('/src/models/pet.ts') // '/src/models/pet'
349
- * trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'
350
- * trimExtName('noExtension') // 'noExtension'
351
- */
352
- function trimExtName$1(text) {
353
- const dotIndex = text.lastIndexOf(".");
354
- if (dotIndex > 0 && !text.includes("/", dotIndex)) return text.slice(0, dotIndex);
355
- return text;
356
- }
357
- require_chunk.__name(trimExtName$1, "trimExtName");
358
- //#endregion
359
- //#region ../../internals/utils/src/promise.ts
360
- /** Returns `true` when `result` is a rejected `Promise.allSettled` result with a typed `reason`.
361
- *
362
- * @example
363
- * ```ts
364
- * const results = await Promise.allSettled([p1, p2])
365
- * results.filter(isPromiseRejectedResult<Error>).map((r) => r.reason.message)
366
- * ```
367
- */
368
- function isPromiseRejectedResult(result) {
369
- return result.status === "rejected";
370
- }
371
- //#endregion
372
- //#region ../../internals/utils/src/reserved.ts
373
- /**
374
- * JavaScript and Java reserved words.
375
- * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
376
- */
377
- const reservedWords = new Set([
378
- "abstract",
379
- "arguments",
380
- "boolean",
381
- "break",
382
- "byte",
383
- "case",
384
- "catch",
385
- "char",
386
- "class",
387
- "const",
388
- "continue",
389
- "debugger",
390
- "default",
391
- "delete",
392
- "do",
393
- "double",
394
- "else",
395
- "enum",
396
- "eval",
397
- "export",
398
- "extends",
399
- "false",
400
- "final",
401
- "finally",
402
- "float",
403
- "for",
404
- "function",
405
- "goto",
406
- "if",
407
- "implements",
408
- "import",
409
- "in",
410
- "instanceof",
411
- "int",
412
- "interface",
413
- "let",
414
- "long",
415
- "native",
416
- "new",
417
- "null",
418
- "package",
419
- "private",
420
- "protected",
421
- "public",
422
- "return",
423
- "short",
424
- "static",
425
- "super",
426
- "switch",
427
- "synchronized",
428
- "this",
429
- "throw",
430
- "throws",
431
- "transient",
432
- "true",
433
- "try",
434
- "typeof",
435
- "var",
436
- "void",
437
- "volatile",
438
- "while",
439
- "with",
440
- "yield",
441
- "Array",
442
- "Date",
443
- "hasOwnProperty",
444
- "Infinity",
445
- "isFinite",
446
- "isNaN",
447
- "isPrototypeOf",
448
- "length",
449
- "Math",
450
- "name",
451
- "NaN",
452
- "Number",
453
- "Object",
454
- "prototype",
455
- "String",
456
- "toString",
457
- "undefined",
458
- "valueOf"
459
- ]);
460
- /**
461
- * Prefixes `word` with `_` when it is a reserved JavaScript/Java identifier or starts with a digit.
462
- *
463
- * @example
464
- * ```ts
465
- * transformReservedWord('class') // '_class'
466
- * transformReservedWord('42foo') // '_42foo'
467
- * transformReservedWord('status') // 'status'
468
- * ```
469
- */
470
- function transformReservedWord(word) {
471
- const firstChar = word.charCodeAt(0);
472
- if (word && (reservedWords.has(word) || firstChar >= 48 && firstChar <= 57)) return `_${word}`;
473
- return word;
474
- }
475
- /**
476
- * Returns `true` when `name` is a syntactically valid JavaScript variable name.
477
- *
478
- * @example
479
- * ```ts
480
- * isValidVarName('status') // true
481
- * isValidVarName('class') // false (reserved word)
482
- * isValidVarName('42foo') // false (starts with digit)
483
- * ```
484
- */
485
- function isValidVarName(name) {
486
- try {
487
- new Function(`var ${name}`);
488
- } catch {
489
- return false;
490
- }
491
- return true;
492
- }
493
- //#endregion
494
308
  //#region ../../internals/utils/src/urlPath.ts
495
309
  /**
496
310
  * Parses and transforms an OpenAPI/Swagger path string into various URL formats.
@@ -568,8 +382,8 @@ var URLPath = class {
568
382
  return this.getParams();
569
383
  }
570
384
  #transformParam(raw) {
571
- const param = isValidVarName(raw) ? raw : camelCase(raw);
572
- return this.#options.casing === "camelcase" ? camelCase(param) : param;
385
+ const param = require_PluginDriver.isValidVarName(raw) ? raw : require_PluginDriver.camelCase(raw);
386
+ return this.#options.casing === "camelcase" ? require_PluginDriver.camelCase(param) : param;
573
387
  }
574
388
  /**
575
389
  * Iterates over every `{param}` token in `path`, calling `fn` with the raw token and transformed name.
@@ -637,222 +451,24 @@ var URLPath = class {
637
451
  }
638
452
  };
639
453
  //#endregion
640
- //#region src/constants.ts
641
- /**
642
- * Base URL for the Kubb Studio web app.
643
- */
644
- const DEFAULT_STUDIO_URL = "https://studio.kubb.dev";
645
- /**
646
- * File name used for generated barrel (index) files.
647
- */
648
- const BARREL_FILENAME = "index.ts";
649
- /**
650
- * Default banner style written at the top of every generated file.
651
- */
652
- const DEFAULT_BANNER = "simple";
653
- /**
654
- * Default file-extension mapping used when no explicit mapping is configured.
655
- */
656
- const DEFAULT_EXTENSION = { ".ts": ".ts" };
657
- /**
658
- * Numeric log-level thresholds used internally to compare verbosity.
659
- *
660
- * Higher numbers are more verbose.
661
- */
662
- const logLevel = {
663
- silent: Number.NEGATIVE_INFINITY,
664
- error: 0,
665
- warn: 1,
666
- info: 3,
667
- verbose: 4,
668
- debug: 5
669
- };
454
+ //#region src/createAdapter.ts
670
455
  /**
671
- * CLI command descriptors for each supported linter.
456
+ * Creates an adapter factory. Call the returned function with optional options to get the adapter instance.
672
457
  *
673
- * Each entry contains the executable `command`, an `args` factory that maps an
674
- * output path to the correct argument list, and an `errorMessage` shown when
675
- * the linter is not found.
676
- */
677
- const linters = {
678
- eslint: {
679
- command: "eslint",
680
- args: (outputPath) => [outputPath, "--fix"],
681
- errorMessage: "Eslint not found"
682
- },
683
- biome: {
684
- command: "biome",
685
- args: (outputPath) => [
686
- "lint",
687
- "--fix",
688
- outputPath
689
- ],
690
- errorMessage: "Biome not found"
691
- },
692
- oxlint: {
693
- command: "oxlint",
694
- args: (outputPath) => ["--fix", outputPath],
695
- errorMessage: "Oxlint not found"
696
- }
697
- };
698
- /**
699
- * CLI command descriptors for each supported code formatter.
458
+ * @example
459
+ * export const myAdapter = createAdapter<MyAdapter>((options) => {
460
+ * return {
461
+ * name: 'my-adapter',
462
+ * options,
463
+ * async parse(source) { ... },
464
+ * }
465
+ * })
700
466
  *
701
- * Each entry contains the executable `command`, an `args` factory that maps an
702
- * output path to the correct argument list, and an `errorMessage` shown when
703
- * the formatter is not found.
467
+ * // instantiate
468
+ * const adapter = myAdapter({ validate: true })
704
469
  */
705
- const formatters = {
706
- prettier: {
707
- command: "prettier",
708
- args: (outputPath) => [
709
- "--ignore-unknown",
710
- "--write",
711
- outputPath
712
- ],
713
- errorMessage: "Prettier not found"
714
- },
715
- biome: {
716
- command: "biome",
717
- args: (outputPath) => [
718
- "format",
719
- "--write",
720
- outputPath
721
- ],
722
- errorMessage: "Biome not found"
723
- },
724
- oxfmt: {
725
- command: "oxfmt",
726
- args: (outputPath) => [outputPath],
727
- errorMessage: "Oxfmt not found"
728
- }
729
- };
730
- //#endregion
731
- //#region ../../node_modules/.pnpm/yocto-queue@1.2.2/node_modules/yocto-queue/index.js
732
- var Node = class {
733
- value;
734
- next;
735
- constructor(value) {
736
- this.value = value;
737
- }
738
- };
739
- var Queue = class {
740
- #head;
741
- #tail;
742
- #size;
743
- constructor() {
744
- this.clear();
745
- }
746
- enqueue(value) {
747
- const node = new Node(value);
748
- if (this.#head) {
749
- this.#tail.next = node;
750
- this.#tail = node;
751
- } else {
752
- this.#head = node;
753
- this.#tail = node;
754
- }
755
- this.#size++;
756
- }
757
- dequeue() {
758
- const current = this.#head;
759
- if (!current) return;
760
- this.#head = this.#head.next;
761
- this.#size--;
762
- if (!this.#head) this.#tail = void 0;
763
- return current.value;
764
- }
765
- peek() {
766
- if (!this.#head) return;
767
- return this.#head.value;
768
- }
769
- clear() {
770
- this.#head = void 0;
771
- this.#tail = void 0;
772
- this.#size = 0;
773
- }
774
- get size() {
775
- return this.#size;
776
- }
777
- *[Symbol.iterator]() {
778
- let current = this.#head;
779
- while (current) {
780
- yield current.value;
781
- current = current.next;
782
- }
783
- }
784
- *drain() {
785
- while (this.#head) yield this.dequeue();
786
- }
787
- };
788
- //#endregion
789
- //#region ../../node_modules/.pnpm/p-limit@7.3.0/node_modules/p-limit/index.js
790
- function pLimit(concurrency) {
791
- let rejectOnClear = false;
792
- if (typeof concurrency === "object") ({concurrency, rejectOnClear = false} = concurrency);
793
- validateConcurrency(concurrency);
794
- if (typeof rejectOnClear !== "boolean") throw new TypeError("Expected `rejectOnClear` to be a boolean");
795
- const queue = new Queue();
796
- let activeCount = 0;
797
- const resumeNext = () => {
798
- if (activeCount < concurrency && queue.size > 0) {
799
- activeCount++;
800
- queue.dequeue().run();
801
- }
802
- };
803
- const next = () => {
804
- activeCount--;
805
- resumeNext();
806
- };
807
- const run = async (function_, resolve, arguments_) => {
808
- const result = (async () => function_(...arguments_))();
809
- resolve(result);
810
- try {
811
- await result;
812
- } catch {}
813
- next();
814
- };
815
- const enqueue = (function_, resolve, reject, arguments_) => {
816
- const queueItem = { reject };
817
- new Promise((internalResolve) => {
818
- queueItem.run = internalResolve;
819
- queue.enqueue(queueItem);
820
- }).then(run.bind(void 0, function_, resolve, arguments_));
821
- if (activeCount < concurrency) resumeNext();
822
- };
823
- const generator = (function_, ...arguments_) => new Promise((resolve, reject) => {
824
- enqueue(function_, resolve, reject, arguments_);
825
- });
826
- Object.defineProperties(generator, {
827
- activeCount: { get: () => activeCount },
828
- pendingCount: { get: () => queue.size },
829
- clearQueue: { value() {
830
- if (!rejectOnClear) {
831
- queue.clear();
832
- return;
833
- }
834
- const abortError = AbortSignal.abort().reason;
835
- while (queue.size > 0) queue.dequeue().reject(abortError);
836
- } },
837
- concurrency: {
838
- get: () => concurrency,
839
- set(newConcurrency) {
840
- validateConcurrency(newConcurrency);
841
- concurrency = newConcurrency;
842
- queueMicrotask(() => {
843
- while (activeCount < concurrency && queue.size > 0) resumeNext();
844
- });
845
- }
846
- },
847
- map: { async value(iterable, function_) {
848
- const promises = Array.from(iterable, (value, index) => this(function_, value, index));
849
- return Promise.all(promises);
850
- } }
851
- });
852
- return generator;
853
- }
854
- function validateConcurrency(concurrency) {
855
- if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) throw new TypeError("Expected `concurrency` to be a number from 1 and up");
470
+ function createAdapter(build) {
471
+ return (options) => build(options ?? {});
856
472
  }
857
473
  //#endregion
858
474
  //#region src/FileProcessor.ts
@@ -864,7 +480,7 @@ function joinSources(file) {
864
480
  * Falls back to joining source values when no matching parser is found.
865
481
  */
866
482
  var FileProcessor = class {
867
- #limit = pLimit(100);
483
+ #limit = require_PluginDriver.pLimit(100);
868
484
  async parse(file, { parsers, extension } = {}) {
869
485
  const parseExtName = extension?.[file.extname] || void 0;
870
486
  if (!parsers || !file.extname) return joinSources(file);
@@ -898,634 +514,6 @@ var FileProcessor = class {
898
514
  }
899
515
  };
900
516
  //#endregion
901
- //#region src/devtools.ts
902
- /**
903
- * Encodes an `InputNode` as a compressed, URL-safe string.
904
- *
905
- * The JSON representation is deflate-compressed with {@link deflateSync} before
906
- * base64url encoding, which typically reduces payload size by 70–80 % and
907
- * keeps URLs well within browser and server path-length limits.
908
- *
909
- * Use {@link decodeAst} to reverse.
910
- */
911
- function encodeAst(input) {
912
- const compressed = (0, fflate.deflateSync)(new TextEncoder().encode(JSON.stringify(input)));
913
- return Buffer.from(compressed).toString("base64url");
914
- }
915
- /**
916
- * Constructs the Kubb Studio URL for the given `InputNode`.
917
- * When `options.ast` is `true`, navigates to the AST inspector (`/ast`).
918
- * The `input` is encoded and attached as the `?root=` query parameter so Studio
919
- * can decode and render it without a round-trip to any server.
920
- */
921
- function getStudioUrl(input, studioUrl, options = {}) {
922
- return `${studioUrl.replace(/\/$/, "")}${options.ast ? "/ast" : ""}?root=${encodeAst(input)}`;
923
- }
924
- /**
925
- * Opens the Kubb Studio URL for the given `InputNode` in the default browser —
926
- *
927
- * Falls back to printing the URL if the browser cannot be launched.
928
- */
929
- async function openInStudio(input, studioUrl, options = {}) {
930
- const url = getStudioUrl(input, studioUrl, options);
931
- const cmd = process.platform === "win32" ? "cmd" : process.platform === "darwin" ? "open" : "xdg-open";
932
- const args = process.platform === "win32" ? [
933
- "/c",
934
- "start",
935
- "",
936
- url
937
- ] : [url];
938
- try {
939
- await (0, tinyexec.x)(cmd, args);
940
- } catch {
941
- console.log(`\n ${url}\n`);
942
- }
943
- }
944
- //#endregion
945
- //#region src/FileManager.ts
946
- function mergeFile(a, b) {
947
- return {
948
- ...a,
949
- sources: [...a.sources || [], ...b.sources || []],
950
- imports: [...a.imports || [], ...b.imports || []],
951
- exports: [...a.exports || [], ...b.exports || []]
952
- };
953
- }
954
- /**
955
- * In-memory file store for generated files.
956
- *
957
- * Files with the same `path` are merged — sources, imports, and exports are concatenated.
958
- * The `files` getter returns all stored files sorted by path length (shortest first).
959
- *
960
- * @example
961
- * ```ts
962
- * import { FileManager } from '@kubb/core'
963
- *
964
- * const manager = new FileManager()
965
- * manager.upsert(myFile)
966
- * console.log(manager.files) // all stored files
967
- * ```
968
- */
969
- var FileManager = class {
970
- #cache = /* @__PURE__ */ new Map();
971
- #filesCache = null;
972
- /**
973
- * Adds one or more files. Files with the same path are merged — sources, imports,
974
- * and exports from all calls with the same path are concatenated together.
975
- */
976
- add(...files) {
977
- const resolvedFiles = [];
978
- const mergedFiles = /* @__PURE__ */ new Map();
979
- files.forEach((file) => {
980
- const existing = mergedFiles.get(file.path);
981
- if (existing) mergedFiles.set(file.path, mergeFile(existing, file));
982
- else mergedFiles.set(file.path, file);
983
- });
984
- for (const file of mergedFiles.values()) {
985
- const resolvedFile = (0, _kubb_ast.createFile)(file);
986
- this.#cache.set(resolvedFile.path, resolvedFile);
987
- this.#filesCache = null;
988
- resolvedFiles.push(resolvedFile);
989
- }
990
- return resolvedFiles;
991
- }
992
- /**
993
- * Adds or merges one or more files.
994
- * If a file with the same path already exists, its sources/imports/exports are merged together.
995
- */
996
- upsert(...files) {
997
- const resolvedFiles = [];
998
- const mergedFiles = /* @__PURE__ */ new Map();
999
- files.forEach((file) => {
1000
- const existing = mergedFiles.get(file.path);
1001
- if (existing) mergedFiles.set(file.path, mergeFile(existing, file));
1002
- else mergedFiles.set(file.path, file);
1003
- });
1004
- for (const file of mergedFiles.values()) {
1005
- const existing = this.#cache.get(file.path);
1006
- const resolvedFile = (0, _kubb_ast.createFile)(existing ? mergeFile(existing, file) : file);
1007
- this.#cache.set(resolvedFile.path, resolvedFile);
1008
- this.#filesCache = null;
1009
- resolvedFiles.push(resolvedFile);
1010
- }
1011
- return resolvedFiles;
1012
- }
1013
- getByPath(path) {
1014
- return this.#cache.get(path) ?? null;
1015
- }
1016
- deleteByPath(path) {
1017
- this.#cache.delete(path);
1018
- this.#filesCache = null;
1019
- }
1020
- clear() {
1021
- this.#cache.clear();
1022
- this.#filesCache = null;
1023
- }
1024
- /**
1025
- * All stored files, sorted by path length (shorter paths first).
1026
- * Barrel/index files (e.g. index.ts) are sorted last within each length bucket.
1027
- */
1028
- get files() {
1029
- if (this.#filesCache) return this.#filesCache;
1030
- const keys = [...this.#cache.keys()].sort((a, b) => {
1031
- if (a.length !== b.length) return a.length - b.length;
1032
- const aIsIndex = trimExtName$1(a).endsWith("index");
1033
- if (aIsIndex !== trimExtName$1(b).endsWith("index")) return aIsIndex ? 1 : -1;
1034
- return 0;
1035
- });
1036
- const files = [];
1037
- for (const key of keys) {
1038
- const file = this.#cache.get(key);
1039
- if (file) files.push(file);
1040
- }
1041
- this.#filesCache = files;
1042
- return files;
1043
- }
1044
- };
1045
- //#endregion
1046
- //#region src/utils/executeStrategies.ts
1047
- /**
1048
- * Runs promise functions in sequence, threading each result into the next call.
1049
- *
1050
- * - Each function receives the accumulated state from the previous call.
1051
- * - Skips functions that return a falsy value (acts as a no-op for that step).
1052
- * - Returns an array of all individual results.
1053
- * @deprecated
1054
- */
1055
- function hookSeq(promises) {
1056
- return promises.filter(Boolean).reduce((promise, func) => {
1057
- if (typeof func !== "function") throw new Error("HookSeq needs a function that returns a promise `() => Promise<unknown>`");
1058
- return promise.then((state) => {
1059
- const calledFunc = func(state);
1060
- if (calledFunc) return calledFunc.then(Array.prototype.concat.bind(state));
1061
- return state;
1062
- });
1063
- }, Promise.resolve([]));
1064
- }
1065
- /**
1066
- * Runs promise functions in sequence and returns the first non-null result.
1067
- *
1068
- * - Stops as soon as `nullCheck` passes for a result (default: `!== null`).
1069
- * - Subsequent functions are skipped once a match is found.
1070
- * @deprecated
1071
- */
1072
- function hookFirst(promises, nullCheck = (state) => state !== null) {
1073
- let promise = Promise.resolve(null);
1074
- for (const func of promises.filter(Boolean)) promise = promise.then((state) => {
1075
- if (nullCheck(state)) return state;
1076
- return func(state);
1077
- });
1078
- return promise;
1079
- }
1080
- /**
1081
- * Runs promise functions concurrently and returns all settled results.
1082
- *
1083
- * - Limits simultaneous executions to `concurrency` (default: unlimited).
1084
- * - Uses `Promise.allSettled` so individual failures do not cancel other tasks.
1085
- * @deprecated
1086
- */
1087
- function hookParallel(promises, concurrency = Number.POSITIVE_INFINITY) {
1088
- const limit = pLimit(concurrency);
1089
- const tasks = promises.filter(Boolean).map((promise) => limit(() => promise()));
1090
- return Promise.allSettled(tasks);
1091
- }
1092
- //#endregion
1093
- //#region src/PluginDriver.ts
1094
- /**
1095
- * Returns `'single'` when `fileOrFolder` has a file extension, `'split'` otherwise.
1096
- *
1097
- * @example
1098
- * ```ts
1099
- * getMode('src/gen/types.ts') // 'single'
1100
- * getMode('src/gen/types') // 'split'
1101
- * ```
1102
- */
1103
- function getMode(fileOrFolder) {
1104
- if (!fileOrFolder) return "split";
1105
- return (0, node_path.extname)(fileOrFolder) ? "single" : "split";
1106
- }
1107
- const hookFirstNullCheck = (state) => !!state?.result;
1108
- var PluginDriver = class {
1109
- config;
1110
- options;
1111
- /**
1112
- * The universal `@kubb/ast` `InputNode` produced by the adapter, set by
1113
- * the build pipeline after the adapter's `parse()` resolves.
1114
- */
1115
- inputNode = void 0;
1116
- adapter = void 0;
1117
- #studioIsOpen = false;
1118
- /**
1119
- * Central file store for all generated files.
1120
- * Plugins should use `this.addFile()` / `this.upsertFile()` (via their context) to
1121
- * add files; this property gives direct read/write access when needed.
1122
- */
1123
- fileManager = new FileManager();
1124
- plugins = /* @__PURE__ */ new Map();
1125
- constructor(config, options) {
1126
- this.config = config;
1127
- this.options = options;
1128
- config.plugins.map((plugin) => Object.assign({
1129
- buildStart() {},
1130
- buildEnd() {}
1131
- }, plugin)).filter((plugin) => {
1132
- if (typeof plugin.apply === "function") return plugin.apply(config);
1133
- return true;
1134
- }).sort((a, b) => {
1135
- if (b.pre?.includes(a.name)) return 1;
1136
- if (b.post?.includes(a.name)) return -1;
1137
- return 0;
1138
- }).forEach((plugin) => {
1139
- this.plugins.set(plugin.name, plugin);
1140
- });
1141
- }
1142
- get events() {
1143
- return this.options.events;
1144
- }
1145
- getContext(plugin) {
1146
- const driver = this;
1147
- const baseContext = {
1148
- config: driver.config,
1149
- get root() {
1150
- return (0, node_path.resolve)(driver.config.root, driver.config.output.path);
1151
- },
1152
- getMode(output) {
1153
- return getMode((0, node_path.resolve)(driver.config.root, driver.config.output.path, output.path));
1154
- },
1155
- events: driver.options.events,
1156
- plugin,
1157
- getPlugin: driver.getPlugin.bind(driver),
1158
- requirePlugin: driver.requirePlugin.bind(driver),
1159
- driver,
1160
- addFile: async (...files) => {
1161
- driver.fileManager.add(...files);
1162
- },
1163
- upsertFile: async (...files) => {
1164
- driver.fileManager.upsert(...files);
1165
- },
1166
- get inputNode() {
1167
- return driver.inputNode;
1168
- },
1169
- get adapter() {
1170
- return driver.adapter;
1171
- },
1172
- get resolver() {
1173
- return plugin.resolver;
1174
- },
1175
- get transformer() {
1176
- return plugin.transformer;
1177
- },
1178
- warn(message) {
1179
- driver.events.emit("warn", message);
1180
- },
1181
- error(error) {
1182
- driver.events.emit("error", typeof error === "string" ? new Error(error) : error);
1183
- },
1184
- info(message) {
1185
- driver.events.emit("info", message);
1186
- },
1187
- openInStudio(options) {
1188
- if (!driver.config.devtools || driver.#studioIsOpen) return;
1189
- if (typeof driver.config.devtools !== "object") throw new Error("Devtools must be an object");
1190
- if (!driver.inputNode || !driver.adapter) throw new Error("adapter is not defined, make sure you have set the parser in kubb.config.ts");
1191
- driver.#studioIsOpen = true;
1192
- const studioUrl = driver.config.devtools?.studioUrl ?? "https://studio.kubb.dev";
1193
- return openInStudio(driver.inputNode, studioUrl, options);
1194
- }
1195
- };
1196
- const mergedExtras = {};
1197
- for (const p of this.plugins.values()) if (typeof p.inject === "function") {
1198
- const result = p.inject.call(baseContext);
1199
- if (result !== null && typeof result === "object") Object.assign(mergedExtras, result);
1200
- }
1201
- return {
1202
- ...baseContext,
1203
- ...mergedExtras
1204
- };
1205
- }
1206
- /**
1207
- * @deprecated use resolvers context instead
1208
- */
1209
- getFile({ name, mode, extname, pluginName, options }) {
1210
- const resolvedName = mode ? mode === "single" ? "" : this.resolveName({
1211
- name,
1212
- pluginName,
1213
- type: "file"
1214
- }) : name;
1215
- const path = this.resolvePath({
1216
- baseName: `${resolvedName}${extname}`,
1217
- mode,
1218
- pluginName,
1219
- options
1220
- });
1221
- if (!path) throw new Error(`Filepath should be defined for resolvedName "${resolvedName}" and pluginName "${pluginName}"`);
1222
- return (0, _kubb_ast.createFile)({
1223
- path,
1224
- baseName: (0, node_path.basename)(path),
1225
- meta: { pluginName },
1226
- sources: [],
1227
- imports: [],
1228
- exports: []
1229
- });
1230
- }
1231
- /**
1232
- * @deprecated use resolvers context instead
1233
- */
1234
- resolvePath = (params) => {
1235
- const defaultPath = (0, node_path.resolve)((0, node_path.resolve)(this.config.root, this.config.output.path), params.baseName);
1236
- if (params.pluginName) return this.hookForPluginSync({
1237
- pluginName: params.pluginName,
1238
- hookName: "resolvePath",
1239
- parameters: [
1240
- params.baseName,
1241
- params.mode,
1242
- params.options
1243
- ]
1244
- })?.at(0) || defaultPath;
1245
- return this.hookFirstSync({
1246
- hookName: "resolvePath",
1247
- parameters: [
1248
- params.baseName,
1249
- params.mode,
1250
- params.options
1251
- ]
1252
- })?.result || defaultPath;
1253
- };
1254
- /**
1255
- * @deprecated use resolvers context instead
1256
- */
1257
- resolveName = (params) => {
1258
- if (params.pluginName) return transformReservedWord(this.hookForPluginSync({
1259
- pluginName: params.pluginName,
1260
- hookName: "resolveName",
1261
- parameters: [params.name.trim(), params.type]
1262
- })?.at(0) ?? params.name);
1263
- const name = this.hookFirstSync({
1264
- hookName: "resolveName",
1265
- parameters: [params.name.trim(), params.type]
1266
- })?.result;
1267
- return transformReservedWord(name ?? params.name);
1268
- };
1269
- /**
1270
- * Run a specific hookName for plugin x.
1271
- */
1272
- async hookForPlugin({ pluginName, hookName, parameters }) {
1273
- const plugin = this.plugins.get(pluginName);
1274
- if (!plugin) return [null];
1275
- this.events.emit("plugins:hook:progress:start", {
1276
- hookName,
1277
- plugins: [plugin]
1278
- });
1279
- const result = await this.#execute({
1280
- strategy: "hookFirst",
1281
- hookName,
1282
- parameters,
1283
- plugin
1284
- });
1285
- this.events.emit("plugins:hook:progress:end", { hookName });
1286
- return [result];
1287
- }
1288
- /**
1289
- * Run a specific hookName for plugin x.
1290
- */
1291
- hookForPluginSync({ pluginName, hookName, parameters }) {
1292
- const plugin = this.plugins.get(pluginName);
1293
- if (!plugin) return null;
1294
- const result = this.#executeSync({
1295
- strategy: "hookFirst",
1296
- hookName,
1297
- parameters,
1298
- plugin
1299
- });
1300
- return result !== null ? [result] : [];
1301
- }
1302
- /**
1303
- * Returns the first non-null result.
1304
- */
1305
- async hookFirst({ hookName, parameters, skipped }) {
1306
- const plugins = [];
1307
- for (const plugin of this.plugins.values()) if (hookName in plugin && (skipped ? !skipped.has(plugin) : true)) plugins.push(plugin);
1308
- this.events.emit("plugins:hook:progress:start", {
1309
- hookName,
1310
- plugins
1311
- });
1312
- const result = await hookFirst(plugins.map((plugin) => {
1313
- return async () => {
1314
- const value = await this.#execute({
1315
- strategy: "hookFirst",
1316
- hookName,
1317
- parameters,
1318
- plugin
1319
- });
1320
- return Promise.resolve({
1321
- plugin,
1322
- result: value
1323
- });
1324
- };
1325
- }), hookFirstNullCheck);
1326
- this.events.emit("plugins:hook:progress:end", { hookName });
1327
- return result;
1328
- }
1329
- /**
1330
- * Returns the first non-null result.
1331
- */
1332
- hookFirstSync({ hookName, parameters, skipped }) {
1333
- let parseResult = null;
1334
- for (const plugin of this.plugins.values()) {
1335
- if (!(hookName in plugin)) continue;
1336
- if (skipped?.has(plugin)) continue;
1337
- parseResult = {
1338
- result: this.#executeSync({
1339
- strategy: "hookFirst",
1340
- hookName,
1341
- parameters,
1342
- plugin
1343
- }),
1344
- plugin
1345
- };
1346
- if (parseResult.result != null) break;
1347
- }
1348
- return parseResult;
1349
- }
1350
- /**
1351
- * Runs all plugins in parallel based on `this.plugin` order and `pre`/`post` settings.
1352
- */
1353
- async hookParallel({ hookName, parameters }) {
1354
- const plugins = [];
1355
- for (const plugin of this.plugins.values()) if (hookName in plugin) plugins.push(plugin);
1356
- this.events.emit("plugins:hook:progress:start", {
1357
- hookName,
1358
- plugins
1359
- });
1360
- const pluginStartTimes = /* @__PURE__ */ new Map();
1361
- const results = await hookParallel(plugins.map((plugin) => {
1362
- return () => {
1363
- pluginStartTimes.set(plugin, node_perf_hooks.performance.now());
1364
- return this.#execute({
1365
- strategy: "hookParallel",
1366
- hookName,
1367
- parameters,
1368
- plugin
1369
- });
1370
- };
1371
- }), this.options.concurrency);
1372
- results.forEach((result, index) => {
1373
- if (isPromiseRejectedResult(result)) {
1374
- const plugin = plugins[index];
1375
- if (plugin) {
1376
- const startTime = pluginStartTimes.get(plugin) ?? node_perf_hooks.performance.now();
1377
- this.events.emit("error", result.reason, {
1378
- plugin,
1379
- hookName,
1380
- strategy: "hookParallel",
1381
- duration: Math.round(node_perf_hooks.performance.now() - startTime),
1382
- parameters
1383
- });
1384
- }
1385
- }
1386
- });
1387
- this.events.emit("plugins:hook:progress:end", { hookName });
1388
- return results.reduce((acc, result) => {
1389
- if (result.status === "fulfilled") acc.push(result.value);
1390
- return acc;
1391
- }, []);
1392
- }
1393
- /**
1394
- * Chains plugins
1395
- */
1396
- async hookSeq({ hookName, parameters }) {
1397
- const plugins = [];
1398
- for (const plugin of this.plugins.values()) if (hookName in plugin) plugins.push(plugin);
1399
- this.events.emit("plugins:hook:progress:start", {
1400
- hookName,
1401
- plugins
1402
- });
1403
- await hookSeq(plugins.map((plugin) => {
1404
- return () => this.#execute({
1405
- strategy: "hookSeq",
1406
- hookName,
1407
- parameters,
1408
- plugin
1409
- });
1410
- }));
1411
- this.events.emit("plugins:hook:progress:end", { hookName });
1412
- }
1413
- getPlugin(pluginName) {
1414
- return this.plugins.get(pluginName);
1415
- }
1416
- requirePlugin(pluginName) {
1417
- const plugin = this.plugins.get(pluginName);
1418
- if (!plugin) throw new Error(`[kubb] Plugin "${pluginName}" is required but not found. Make sure it is included in your Kubb config.`);
1419
- return plugin;
1420
- }
1421
- /**
1422
- * Run an async plugin hook and return the result.
1423
- * @param hookName Name of the plugin hook. Must be either in `PluginHooks` or `OutputPluginValueHooks`.
1424
- * @param args Arguments passed to the plugin hook.
1425
- * @param plugin The actual pluginObject to run.
1426
- */
1427
- #emitProcessingEnd({ startTime, output, strategy, hookName, plugin, parameters }) {
1428
- this.events.emit("plugins:hook:processing:end", {
1429
- duration: Math.round(node_perf_hooks.performance.now() - startTime),
1430
- parameters,
1431
- output,
1432
- strategy,
1433
- hookName,
1434
- plugin
1435
- });
1436
- }
1437
- #execute({ strategy, hookName, parameters, plugin }) {
1438
- const hook = plugin[hookName];
1439
- if (!hook) return null;
1440
- this.events.emit("plugins:hook:processing:start", {
1441
- strategy,
1442
- hookName,
1443
- parameters,
1444
- plugin
1445
- });
1446
- const startTime = node_perf_hooks.performance.now();
1447
- return (async () => {
1448
- try {
1449
- const output = typeof hook === "function" ? await Promise.resolve(hook.apply(this.getContext(plugin), parameters ?? [])) : hook;
1450
- this.#emitProcessingEnd({
1451
- startTime,
1452
- output,
1453
- strategy,
1454
- hookName,
1455
- plugin,
1456
- parameters
1457
- });
1458
- return output;
1459
- } catch (error) {
1460
- this.events.emit("error", error, {
1461
- plugin,
1462
- hookName,
1463
- strategy,
1464
- duration: Math.round(node_perf_hooks.performance.now() - startTime)
1465
- });
1466
- return null;
1467
- }
1468
- })();
1469
- }
1470
- /**
1471
- * Run a sync plugin hook and return the result.
1472
- * @param hookName Name of the plugin hook. Must be in `PluginHooks`.
1473
- * @param args Arguments passed to the plugin hook.
1474
- * @param plugin The actual plugin
1475
- */
1476
- #executeSync({ strategy, hookName, parameters, plugin }) {
1477
- const hook = plugin[hookName];
1478
- if (!hook) return null;
1479
- this.events.emit("plugins:hook:processing:start", {
1480
- strategy,
1481
- hookName,
1482
- parameters,
1483
- plugin
1484
- });
1485
- const startTime = node_perf_hooks.performance.now();
1486
- try {
1487
- const output = typeof hook === "function" ? hook.apply(this.getContext(plugin), parameters) : hook;
1488
- this.#emitProcessingEnd({
1489
- startTime,
1490
- output,
1491
- strategy,
1492
- hookName,
1493
- plugin,
1494
- parameters
1495
- });
1496
- return output;
1497
- } catch (error) {
1498
- this.events.emit("error", error, {
1499
- plugin,
1500
- hookName,
1501
- strategy,
1502
- duration: Math.round(node_perf_hooks.performance.now() - startTime)
1503
- });
1504
- return null;
1505
- }
1506
- }
1507
- };
1508
- //#endregion
1509
- //#region src/renderNode.tsx
1510
- /**
1511
- * Handles the return value of a plugin AST hook or generator method.
1512
- *
1513
- * - React element → rendered via renderer-jsx, files stored in `driver.fileManager`
1514
- * - `Array<FileNode>` → upserted directly into `driver.fileManager`
1515
- * - `void` / `null` / `undefined` → no-op (plugin handled it via `this.upsertFile`)
1516
- */
1517
- async function applyHookResult(result, driver) {
1518
- if (!result) return;
1519
- if (Array.isArray(result)) {
1520
- driver.fileManager.upsert(...result);
1521
- return;
1522
- }
1523
- const renderer = (0, _kubb_renderer_jsx.createRenderer)();
1524
- await renderer.render(/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: result }));
1525
- driver.fileManager.upsert(...renderer.files);
1526
- renderer.unmount();
1527
- }
1528
- //#endregion
1529
517
  //#region src/createStorage.ts
1530
518
  /**
1531
519
  * Creates a storage factory. Call the returned function with optional options to get the storage instance.
@@ -1623,7 +611,7 @@ const fsStorage = createStorage(() => ({
1623
611
  }));
1624
612
  //#endregion
1625
613
  //#region package.json
1626
- var version = "5.0.0-alpha.34";
614
+ var version = "5.0.0-alpha.36";
1627
615
  //#endregion
1628
616
  //#region src/utils/diagnostics.ts
1629
617
  /**
@@ -1738,14 +726,14 @@ var TreeNode = class TreeNode {
1738
726
  name: filteredTree.name,
1739
727
  path: filteredTree.path,
1740
728
  file: filteredTree.file,
1741
- type: getMode(filteredTree.path)
729
+ type: require_PluginDriver.getMode(filteredTree.path)
1742
730
  });
1743
731
  const recurse = (node, item) => {
1744
732
  const subNode = node.addChild({
1745
733
  name: item.name,
1746
734
  path: item.path,
1747
735
  file: item.file,
1748
- type: getMode(item.path)
736
+ type: require_PluginDriver.getMode(item.path)
1749
737
  });
1750
738
  if (item.children?.length) item.children?.forEach((child) => {
1751
739
  recurse(subNode, child);
@@ -1884,24 +872,14 @@ function isInputPath(config) {
1884
872
  return typeof config?.input === "object" && config.input !== null && "path" in config.input;
1885
873
  }
1886
874
  //#endregion
1887
- //#region src/build.ts
1888
- /**
1889
- * Initializes all Kubb infrastructure for a build without executing any plugins.
1890
- *
1891
- * - Validates the input path (when applicable).
1892
- * - Applies config defaults (`root`, `output.*`, `devtools`).
1893
- * - Runs the adapter (if configured) to produce the universal `InputNode`.
1894
- * When no adapter is supplied and `@kubb/adapter-oas` is installed as an
1895
- *
1896
- * Pass the returned {@link SetupResult} directly to {@link safeBuild} or {@link build}
1897
- * via the `overrides` argument to reuse the same infrastructure across multiple runs.
1898
- */
875
+ //#region src/createKubb.ts
1899
876
  async function setup(options) {
1900
- const { config: userConfig, events = new AsyncEventEmitter() } = options;
877
+ const { config: userConfig } = options;
878
+ const hooks = options.hooks ?? new AsyncEventEmitter();
1901
879
  const sources = /* @__PURE__ */ new Map();
1902
880
  const diagnosticInfo = getDiagnosticInfo();
1903
- if (Array.isArray(userConfig.input)) await events.emit("warn", "This feature is still under development — use with caution");
1904
- await events.emit("debug", {
881
+ if (Array.isArray(userConfig.input)) await hooks.emit("kubb:warn", "This feature is still under development — use with caution");
882
+ await hooks.emit("kubb:debug", {
1905
883
  date: /* @__PURE__ */ new Date(),
1906
884
  logs: [
1907
885
  "Configuration:",
@@ -1920,7 +898,7 @@ async function setup(options) {
1920
898
  try {
1921
899
  if (isInputPath(userConfig) && !new URLPath(userConfig.input.path).isURL) {
1922
900
  await exists(userConfig.input.path);
1923
- await events.emit("debug", {
901
+ await hooks.emit("kubb:debug", {
1924
902
  date: /* @__PURE__ */ new Date(),
1925
903
  logs: [`✓ Input file validated: ${userConfig.input.path}`]
1926
904
  });
@@ -1933,101 +911,80 @@ async function setup(options) {
1933
911
  }
1934
912
  if (!userConfig.adapter) throw new Error("Adapter should be defined");
1935
913
  const config = {
1936
- root: userConfig.root || process.cwd(),
1937
914
  ...userConfig,
915
+ root: userConfig.root || process.cwd(),
1938
916
  parsers: userConfig.parsers ?? [],
1939
917
  adapter: userConfig.adapter,
1940
918
  output: {
1941
919
  write: true,
1942
920
  barrelType: "named",
1943
- extension: DEFAULT_EXTENSION,
1944
- defaultBanner: DEFAULT_BANNER,
921
+ extension: require_PluginDriver.DEFAULT_EXTENSION,
922
+ defaultBanner: require_PluginDriver.DEFAULT_BANNER,
1945
923
  ...userConfig.output
1946
924
  },
1947
925
  devtools: userConfig.devtools ? {
1948
- studioUrl: DEFAULT_STUDIO_URL,
926
+ studioUrl: require_PluginDriver.DEFAULT_STUDIO_URL,
1949
927
  ...typeof userConfig.devtools === "boolean" ? {} : userConfig.devtools
1950
928
  } : void 0,
1951
929
  plugins: userConfig.plugins
1952
930
  };
1953
931
  const storage = config.output.write === false ? null : config.output.storage ?? fsStorage();
1954
932
  if (config.output.clean) {
1955
- await events.emit("debug", {
933
+ await hooks.emit("kubb:debug", {
1956
934
  date: /* @__PURE__ */ new Date(),
1957
935
  logs: ["Cleaning output directories", ` • Output: ${config.output.path}`]
1958
936
  });
1959
937
  await storage?.clear((0, node_path.resolve)(config.root, config.output.path));
1960
938
  }
1961
- const driver = new PluginDriver(config, {
1962
- events,
939
+ const driver = new require_PluginDriver.PluginDriver(config, {
940
+ hooks,
1963
941
  concurrency: 15
1964
942
  });
1965
943
  const adapter = config.adapter;
1966
944
  if (!adapter) throw new Error("No adapter configured. Please provide an adapter in your kubb.config.ts.");
1967
945
  const source = inputToAdapterSource(config);
1968
- await events.emit("debug", {
946
+ await hooks.emit("kubb:debug", {
1969
947
  date: /* @__PURE__ */ new Date(),
1970
948
  logs: [`Running adapter: ${adapter.name}`]
1971
949
  });
1972
950
  driver.adapter = adapter;
1973
951
  driver.inputNode = await adapter.parse(source);
1974
- await events.emit("debug", {
1975
- date: /* @__PURE__ */ new Date(),
1976
- logs: [
1977
- `✓ Adapter '${adapter.name}' resolved InputNode`,
1978
- ` • Schemas: ${driver.inputNode.schemas.length}`,
1979
- ` • Operations: ${driver.inputNode.operations.length}`
1980
- ]
1981
- });
1982
- return {
1983
- config,
1984
- events,
1985
- driver,
1986
- sources,
1987
- storage
1988
- };
1989
- }
1990
- /**
1991
- * Runs a full Kubb build and throws on any error or plugin failure.
1992
- *
1993
- * Internally delegates to {@link safeBuild} and rethrows collected errors.
1994
- * Pass an existing {@link SetupResult} via `overrides` to skip the setup phase.
1995
- */
1996
- async function build(options, overrides) {
1997
- const { files, driver, failedPlugins, pluginTimings, error, sources } = await safeBuild(options, overrides);
1998
- if (error) throw error;
1999
- if (failedPlugins.size > 0) {
2000
- const errors = [...failedPlugins].map(({ error }) => error);
2001
- throw new BuildError(`Build Error with ${failedPlugins.size} failed plugins`, { errors });
2002
- }
952
+ await hooks.emit("kubb:debug", {
953
+ date: /* @__PURE__ */ new Date(),
954
+ logs: [
955
+ `✓ Adapter '${adapter.name}' resolved InputNode`,
956
+ ` • Schemas: ${driver.inputNode.schemas.length}`,
957
+ ` • Operations: ${driver.inputNode.operations.length}`
958
+ ]
959
+ });
2003
960
  return {
2004
- failedPlugins,
2005
- files,
961
+ config,
962
+ hooks,
2006
963
  driver,
2007
- pluginTimings,
2008
- error: void 0,
2009
- sources
964
+ sources,
965
+ storage
2010
966
  };
2011
967
  }
2012
968
  /**
2013
969
  * Walks the AST and dispatches nodes to a plugin's direct AST hooks
2014
970
  * (`schema`, `operation`, `operations`).
2015
- *
2016
- * - Each hook accepts a single handler **or an array** — all entries are called in sequence.
2017
- * - Nodes that are excluded by `exclude`/`include` plugin options are skipped automatically.
2018
- * - Return values are handled via `applyHookResult`: React elements are rendered,
2019
- * `FileNode[]` are written via upsert, and `void` is a no-op (manual handling).
2020
- * - Barrel files are generated automatically when `output.barrelType` is set.
2021
971
  */
2022
972
  async function runPluginAstHooks(plugin, context) {
2023
973
  const { adapter, inputNode, resolver, driver } = context;
2024
974
  const { exclude, include, override } = plugin.options;
2025
975
  if (!adapter || !inputNode) throw new Error(`[${plugin.name}] No adapter found. Add an OAS adapter (e.g. pluginOas()) before this plugin in your Kubb config.`);
976
+ function resolveRenderer(gen) {
977
+ return gen.renderer === null ? void 0 : gen.renderer ?? plugin.renderer ?? context.config.renderer;
978
+ }
979
+ const generators = plugin.generators ?? [];
2026
980
  const collectedOperations = [];
981
+ const generatorContext = {
982
+ ...context,
983
+ resolver: driver.getResolver(plugin.name)
984
+ };
2027
985
  await (0, _kubb_ast.walk)(inputNode, {
2028
986
  depth: "shallow",
2029
987
  async schema(node) {
2030
- if (!plugin.schema) return;
2031
988
  const transformedNode = plugin.transformer ? (0, _kubb_ast.transform)(node, plugin.transformer) : node;
2032
989
  const options = resolver.resolveOptions(transformedNode, {
2033
990
  options: plugin.options,
@@ -2036,7 +993,15 @@ async function runPluginAstHooks(plugin, context) {
2036
993
  override
2037
994
  });
2038
995
  if (options === null) return;
2039
- await applyHookResult(await plugin.schema.call(context, transformedNode, options), driver);
996
+ const ctx = {
997
+ ...generatorContext,
998
+ options
999
+ };
1000
+ for (const gen of generators) {
1001
+ if (!gen.schema) continue;
1002
+ await require_PluginDriver.applyHookResult(await gen.schema(transformedNode, ctx), driver, resolveRenderer(gen));
1003
+ }
1004
+ await driver.hooks.emit("kubb:generate:schema", transformedNode, ctx);
2040
1005
  },
2041
1006
  async operation(node) {
2042
1007
  const transformedNode = plugin.transformer ? (0, _kubb_ast.transform)(node, plugin.transformer) : node;
@@ -2048,28 +1013,43 @@ async function runPluginAstHooks(plugin, context) {
2048
1013
  });
2049
1014
  if (options !== null) {
2050
1015
  collectedOperations.push(transformedNode);
2051
- if (plugin.operation) await applyHookResult(await plugin.operation.call(context, transformedNode, options), driver);
1016
+ const ctx = {
1017
+ ...generatorContext,
1018
+ options
1019
+ };
1020
+ for (const gen of generators) {
1021
+ if (!gen.operation) continue;
1022
+ await require_PluginDriver.applyHookResult(await gen.operation(transformedNode, ctx), driver, resolveRenderer(gen));
1023
+ }
1024
+ await driver.hooks.emit("kubb:generate:operation", transformedNode, ctx);
2052
1025
  }
2053
1026
  }
2054
1027
  });
2055
- if (plugin.operations && collectedOperations.length > 0) await applyHookResult(await plugin.operations.call(context, collectedOperations, plugin.options), driver);
1028
+ if (collectedOperations.length > 0) {
1029
+ const ctx = {
1030
+ ...generatorContext,
1031
+ options: plugin.options
1032
+ };
1033
+ for (const gen of generators) {
1034
+ if (!gen.operations) continue;
1035
+ await require_PluginDriver.applyHookResult(await gen.operations(collectedOperations, ctx), driver, resolveRenderer(gen));
1036
+ }
1037
+ await driver.hooks.emit("kubb:generate:operations", collectedOperations, ctx);
1038
+ }
2056
1039
  }
2057
- /**
2058
- * Runs a full Kubb build and captures errors instead of throwing.
2059
- *
2060
- * - Installs each plugin in order, recording failures in `failedPlugins`.
2061
- * - Generates the root barrel file when `output.barrelType` is set.
2062
- * - Writes all files through the driver's FileManager and FileProcessor.
2063
- *
2064
- * Returns a {@link BuildOutput} even on failure — inspect `error` and
2065
- * `failedPlugins` to determine whether the build succeeded.
2066
- */
2067
- async function safeBuild(options, overrides) {
2068
- const { driver, events, sources, storage } = overrides ? overrides : await setup(options);
1040
+ async function safeBuild(setupResult) {
1041
+ const { driver, hooks, sources, storage } = setupResult;
2069
1042
  const failedPlugins = /* @__PURE__ */ new Set();
2070
1043
  const pluginTimings = /* @__PURE__ */ new Map();
2071
1044
  const config = driver.config;
2072
1045
  try {
1046
+ await driver.emitSetupHooks();
1047
+ if (driver.adapter && driver.inputNode) await hooks.emit("kubb:build:start", {
1048
+ config,
1049
+ adapter: driver.adapter,
1050
+ inputNode: driver.inputNode,
1051
+ getPlugin: (name) => driver.getPlugin(name)
1052
+ });
2073
1053
  for (const plugin of driver.plugins.values()) {
2074
1054
  const context = driver.getContext(plugin);
2075
1055
  const hrStart = process.hrtime();
@@ -2077,13 +1057,13 @@ async function safeBuild(options, overrides) {
2077
1057
  const root = (0, node_path.resolve)(config.root, config.output.path);
2078
1058
  try {
2079
1059
  const timestamp = /* @__PURE__ */ new Date();
2080
- await events.emit("plugin:start", plugin);
2081
- await events.emit("debug", {
1060
+ await hooks.emit("kubb:plugin:start", plugin);
1061
+ await hooks.emit("kubb:debug", {
2082
1062
  date: timestamp,
2083
1063
  logs: ["Starting plugin...", ` • Plugin Name: ${plugin.name}`]
2084
1064
  });
2085
1065
  await plugin.buildStart.call(context);
2086
- if (plugin.schema || plugin.operation || plugin.operations) await runPluginAstHooks(plugin, context);
1066
+ if (plugin.generators?.length || driver.hasRegisteredGenerators(plugin.name)) await runPluginAstHooks(plugin, context);
2087
1067
  if (output) {
2088
1068
  const barrelFiles = await getBarrelFiles(driver.fileManager.files, {
2089
1069
  type: output.barrelType ?? "named",
@@ -2095,11 +1075,11 @@ async function safeBuild(options, overrides) {
2095
1075
  }
2096
1076
  const duration = getElapsedMs(hrStart);
2097
1077
  pluginTimings.set(plugin.name, duration);
2098
- await events.emit("plugin:end", plugin, {
1078
+ await hooks.emit("kubb:plugin:end", plugin, {
2099
1079
  duration,
2100
1080
  success: true
2101
1081
  });
2102
- await events.emit("debug", {
1082
+ await hooks.emit("kubb:debug", {
2103
1083
  date: /* @__PURE__ */ new Date(),
2104
1084
  logs: [`✓ Plugin started successfully (${formatMs(duration)})`]
2105
1085
  });
@@ -2107,12 +1087,12 @@ async function safeBuild(options, overrides) {
2107
1087
  const error = caughtError;
2108
1088
  const errorTimestamp = /* @__PURE__ */ new Date();
2109
1089
  const duration = getElapsedMs(hrStart);
2110
- await events.emit("plugin:end", plugin, {
1090
+ await hooks.emit("kubb:plugin:end", plugin, {
2111
1091
  duration,
2112
1092
  success: false,
2113
1093
  error
2114
1094
  });
2115
- await events.emit("debug", {
1095
+ await hooks.emit("kubb:debug", {
2116
1096
  date: errorTimestamp,
2117
1097
  logs: [
2118
1098
  "✗ Plugin start failed",
@@ -2129,9 +1109,9 @@ async function safeBuild(options, overrides) {
2129
1109
  }
2130
1110
  }
2131
1111
  if (config.output.barrelType) {
2132
- const rootPath = (0, node_path.resolve)((0, node_path.resolve)(config.root), config.output.path, BARREL_FILENAME);
1112
+ const rootPath = (0, node_path.resolve)((0, node_path.resolve)(config.root), config.output.path, require_PluginDriver.BARREL_FILENAME);
2133
1113
  const rootDir = (0, node_path.dirname)(rootPath);
2134
- await events.emit("debug", {
1114
+ await hooks.emit("kubb:debug", {
2135
1115
  date: /* @__PURE__ */ new Date(),
2136
1116
  logs: [
2137
1117
  "Generating barrel file",
@@ -2142,14 +1122,14 @@ async function safeBuild(options, overrides) {
2142
1122
  const barrelFiles = driver.fileManager.files.filter((file) => {
2143
1123
  return file.sources.some((source) => source.isIndexable);
2144
1124
  });
2145
- await events.emit("debug", {
1125
+ await hooks.emit("kubb:debug", {
2146
1126
  date: /* @__PURE__ */ new Date(),
2147
1127
  logs: [`Found ${barrelFiles.length} indexable files for barrel export`]
2148
1128
  });
2149
1129
  const existingBarrel = driver.fileManager.files.find((f) => f.path === rootPath);
2150
1130
  const rootFile = (0, _kubb_ast.createFile)({
2151
1131
  path: rootPath,
2152
- baseName: BARREL_FILENAME,
1132
+ baseName: require_PluginDriver.BARREL_FILENAME,
2153
1133
  exports: buildBarrelExports({
2154
1134
  barrelFiles,
2155
1135
  rootDir,
@@ -2162,7 +1142,7 @@ async function safeBuild(options, overrides) {
2162
1142
  meta: {}
2163
1143
  });
2164
1144
  driver.fileManager.upsert(rootFile);
2165
- await events.emit("debug", {
1145
+ await hooks.emit("kubb:debug", {
2166
1146
  date: /* @__PURE__ */ new Date(),
2167
1147
  logs: [`✓ Generated barrel file (${rootFile.exports?.length || 0} exports)`]
2168
1148
  });
@@ -2171,7 +1151,7 @@ async function safeBuild(options, overrides) {
2171
1151
  const parsersMap = /* @__PURE__ */ new Map();
2172
1152
  for (const parser of config.parsers) if (parser.extNames) for (const extname of parser.extNames) parsersMap.set(extname, parser);
2173
1153
  const fileProcessor = new FileProcessor();
2174
- await events.emit("debug", {
1154
+ await hooks.emit("kubb:debug", {
2175
1155
  date: /* @__PURE__ */ new Date(),
2176
1156
  logs: [`Writing ${files.length} files...`]
2177
1157
  });
@@ -2179,10 +1159,10 @@ async function safeBuild(options, overrides) {
2179
1159
  parsers: parsersMap,
2180
1160
  extension: config.output.extension,
2181
1161
  onStart: async (processingFiles) => {
2182
- await events.emit("files:processing:start", processingFiles);
1162
+ await hooks.emit("kubb:files:processing:start", processingFiles);
2183
1163
  },
2184
1164
  onUpdate: async ({ file, source, processed, total, percentage }) => {
2185
- await events.emit("file:processing:update", {
1165
+ await hooks.emit("kubb:file:processing:update", {
2186
1166
  file,
2187
1167
  source,
2188
1168
  processed,
@@ -2196,8 +1176,8 @@ async function safeBuild(options, overrides) {
2196
1176
  }
2197
1177
  },
2198
1178
  onEnd: async (processedFiles) => {
2199
- await events.emit("files:processing:end", processedFiles);
2200
- await events.emit("debug", {
1179
+ await hooks.emit("kubb:files:processing:end", processedFiles);
1180
+ await hooks.emit("kubb:debug", {
2201
1181
  date: /* @__PURE__ */ new Date(),
2202
1182
  logs: [`✓ File write process completed for ${processedFiles.length} files`]
2203
1183
  });
@@ -2207,6 +1187,11 @@ async function safeBuild(options, overrides) {
2207
1187
  const context = driver.getContext(plugin);
2208
1188
  await plugin.buildEnd.call(context);
2209
1189
  }
1190
+ await hooks.emit("kubb:build:end", {
1191
+ files,
1192
+ config,
1193
+ outputDir: (0, node_path.resolve)(config.root, config.output.path)
1194
+ });
2210
1195
  return {
2211
1196
  failedPlugins,
2212
1197
  files,
@@ -2223,7 +1208,25 @@ async function safeBuild(options, overrides) {
2223
1208
  error,
2224
1209
  sources
2225
1210
  };
1211
+ } finally {
1212
+ driver.dispose();
1213
+ }
1214
+ }
1215
+ async function build(setupResult) {
1216
+ const { files, driver, failedPlugins, pluginTimings, error, sources } = await safeBuild(setupResult);
1217
+ if (error) throw error;
1218
+ if (failedPlugins.size > 0) {
1219
+ const errors = [...failedPlugins].map(({ error }) => error);
1220
+ throw new BuildError(`Build Error with ${failedPlugins.size} failed plugins`, { errors });
2226
1221
  }
1222
+ return {
1223
+ failedPlugins,
1224
+ files,
1225
+ driver,
1226
+ pluginTimings,
1227
+ error: void 0,
1228
+ sources
1229
+ };
2227
1230
  }
2228
1231
  function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }) {
2229
1232
  const pluginNameMap = /* @__PURE__ */ new Map();
@@ -2245,10 +1248,6 @@ function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, dri
2245
1248
  });
2246
1249
  });
2247
1250
  }
2248
- /**
2249
- * Maps the resolved `Config['input']` shape into an `AdapterSource` that
2250
- * the adapter's `parse()` can consume.
2251
- */
2252
1251
  function inputToAdapterSource(config) {
2253
1252
  if (Array.isArray(config.input)) return {
2254
1253
  type: "paths",
@@ -2267,25 +1266,56 @@ function inputToAdapterSource(config) {
2267
1266
  path: (0, node_path.resolve)(config.root, config.input.path)
2268
1267
  };
2269
1268
  }
2270
- //#endregion
2271
- //#region src/createAdapter.ts
2272
1269
  /**
2273
- * Creates an adapter factory. Call the returned function with optional options to get the adapter instance.
1270
+ * Creates a Kubb instance bound to a single config entry.
1271
+ *
1272
+ * The instance holds shared state (`hooks`, `sources`, `driver`, `config`) across the
1273
+ * `setup → build` lifecycle. Attach event listeners to `kubb.hooks` before
1274
+ * calling `setup()` or `build()`.
2274
1275
  *
2275
1276
  * @example
2276
- * export const myAdapter = createAdapter<MyAdapter>((options) => {
2277
- * return {
2278
- * name: 'my-adapter',
2279
- * options,
2280
- * async parse(source) { ... },
2281
- * }
1277
+ * ```ts
1278
+ * const kubb = createKubb({ config })
1279
+ *
1280
+ * kubb.hooks.on('kubb:plugin:end', (plugin, { duration }) => {
1281
+ * console.log(`${plugin.name} completed in ${duration}ms`)
2282
1282
  * })
2283
1283
  *
2284
- * // instantiate
2285
- * const adapter = myAdapter({ validate: true })
1284
+ * const { files, failedPlugins } = await kubb.safeBuild()
1285
+ * ```
2286
1286
  */
2287
- function createAdapter(build) {
2288
- return (options) => build(options ?? {});
1287
+ function createKubb(options) {
1288
+ const hooks = options.hooks ?? new AsyncEventEmitter();
1289
+ let setupResult;
1290
+ const instance = {
1291
+ get hooks() {
1292
+ return hooks;
1293
+ },
1294
+ get sources() {
1295
+ return setupResult?.sources ?? /* @__PURE__ */ new Map();
1296
+ },
1297
+ get driver() {
1298
+ return setupResult?.driver;
1299
+ },
1300
+ get config() {
1301
+ return setupResult?.config;
1302
+ },
1303
+ async setup() {
1304
+ setupResult = await setup({
1305
+ config: options.config,
1306
+ hooks
1307
+ });
1308
+ },
1309
+ async build() {
1310
+ if (!setupResult) await instance.setup();
1311
+ return build(setupResult);
1312
+ },
1313
+ async safeBuild() {
1314
+ if (!setupResult) await instance.setup();
1315
+ return safeBuild(setupResult);
1316
+ }
1317
+ };
1318
+ return instance;
2289
1319
  }
2290
1320
  //#endregion
2291
1321
  //#region src/createPlugin.ts
@@ -2306,69 +1336,53 @@ function createAdapter(build) {
2306
1336
  * // instantiate
2307
1337
  * const plugin = myPlugin({ output: { path: 'src/gen' } })
2308
1338
  * ```
1339
+ * @deprecated use definePlugin instead
2309
1340
  */
2310
1341
  function createPlugin(build) {
2311
1342
  return (options) => build(options ?? {});
2312
1343
  }
2313
1344
  //#endregion
2314
- //#region src/defineConfig.ts
2315
- function defineConfig(config) {
2316
- return config;
2317
- }
2318
- //#endregion
2319
- //#region src/defineGenerator.ts
2320
- /**
2321
- * Defines a generator. Returns the object as-is with correct `this` typings.
2322
- * No type discrimination (`type: 'react' | 'core'`) needed — `applyHookResult`
2323
- * handles React elements and `File[]` uniformly.
2324
- */
2325
- function defineGenerator(generator) {
2326
- return generator;
2327
- }
1345
+ //#region src/createRenderer.ts
2328
1346
  /**
2329
- * Merges an array of generators into a single generator.
2330
- *
2331
- * The merged generator's `schema`, `operation`, and `operations` methods run
2332
- * the corresponding method from each input generator in sequence, applying each
2333
- * result via `applyHookResult`. This eliminates the need to write the loop
2334
- * manually in each plugin.
1347
+ * Creates a renderer factory for use in generator definitions.
2335
1348
  *
2336
- * @param generators - Array of generators to merge into a single generator.
1349
+ * Wrap your renderer factory function with this helper to register it as the
1350
+ * renderer for a generator. Core will call this factory once per render cycle
1351
+ * to obtain a fresh renderer instance.
2337
1352
  *
2338
1353
  * @example
2339
1354
  * ```ts
2340
- * const merged = mergeGenerators(generators)
1355
+ * // packages/renderer-jsx/src/index.ts
1356
+ * export const jsxRenderer = createRenderer(() => {
1357
+ * const runtime = new Runtime()
1358
+ * return {
1359
+ * async render(element) { await runtime.render(element) },
1360
+ * get files() { return runtime.nodes },
1361
+ * unmount(error) { runtime.unmount(error) },
1362
+ * }
1363
+ * })
2341
1364
  *
2342
- * return {
2343
- * name: pluginName,
2344
- * schema: merged.schema,
2345
- * operation: merged.operation,
2346
- * operations: merged.operations,
2347
- * }
1365
+ * // packages/plugin-zod/src/generators/zodGenerator.tsx
1366
+ * import { jsxRenderer } from '@kubb/renderer-jsx'
1367
+ * export const zodGenerator = defineGenerator<PluginZod>({
1368
+ * name: 'zod',
1369
+ * renderer: jsxRenderer,
1370
+ * schema(node, options) { return <File ...>...</File> },
1371
+ * })
2348
1372
  * ```
2349
1373
  */
2350
- function mergeGenerators(generators) {
2351
- return {
2352
- name: generators.length > 0 ? generators.map((g) => g.name).join("+") : "merged",
2353
- async schema(node, options) {
2354
- for (const gen of generators) {
2355
- if (!gen.schema) continue;
2356
- await applyHookResult(await gen.schema.call(this, node, options), this.driver);
2357
- }
2358
- },
2359
- async operation(node, options) {
2360
- for (const gen of generators) {
2361
- if (!gen.operation) continue;
2362
- await applyHookResult(await gen.operation.call(this, node, options), this.driver);
2363
- }
2364
- },
2365
- async operations(nodes, options) {
2366
- for (const gen of generators) {
2367
- if (!gen.operations) continue;
2368
- await applyHookResult(await gen.operations.call(this, nodes, options), this.driver);
2369
- }
2370
- }
2371
- };
1374
+ function createRenderer(factory) {
1375
+ return factory;
1376
+ }
1377
+ //#endregion
1378
+ //#region src/defineGenerator.ts
1379
+ /**
1380
+ * Defines a generator. Returns the object as-is with correct `this` typings.
1381
+ * `applyHookResult` handles renderer elements and `File[]` uniformly using
1382
+ * the generator's declared `renderer` factory.
1383
+ */
1384
+ function defineGenerator(generator) {
1385
+ return generator;
2372
1386
  }
2373
1387
  //#endregion
2374
1388
  //#region src/defineLogger.ts
@@ -2379,8 +1393,8 @@ function mergeGenerators(generators) {
2379
1393
  * export const myLogger = defineLogger({
2380
1394
  * name: 'my-logger',
2381
1395
  * install(context, options) {
2382
- * context.on('info', (message) => console.log('ℹ', message))
2383
- * context.on('error', (error) => console.error('✗', error.message))
1396
+ * context.on('kubb:info', (message) => console.log('ℹ', message))
1397
+ * context.on('kubb:error', (error) => console.error('✗', error.message))
2384
1398
  * },
2385
1399
  * })
2386
1400
  */
@@ -2413,359 +1427,6 @@ function defineParser(parser) {
2413
1427
  return parser;
2414
1428
  }
2415
1429
  //#endregion
2416
- //#region src/definePresets.ts
2417
- /**
2418
- * Creates a typed presets registry object — a named collection of {@link Preset} entries.
2419
- *
2420
- * @example
2421
- * import { definePreset, definePresets } from '@kubb/core'
2422
- * import { resolverTsLegacy } from '@kubb/plugin-ts'
2423
- *
2424
- * export const myPresets = definePresets({
2425
- * kubbV4: definePreset('kubbV4', { resolvers: [resolverTsLegacy] }),
2426
- * })
2427
- */
2428
- function definePresets(presets) {
2429
- return presets;
2430
- }
2431
- //#endregion
2432
- //#region src/defineResolver.ts
2433
- /**
2434
- * Checks if an operation matches a pattern for a given filter type (`tag`, `operationId`, `path`, `method`).
2435
- */
2436
- function matchesOperationPattern(node, type, pattern) {
2437
- switch (type) {
2438
- case "tag": return node.tags.some((tag) => !!tag.match(pattern));
2439
- case "operationId": return !!node.operationId.match(pattern);
2440
- case "path": return !!node.path.match(pattern);
2441
- case "method": return !!node.method.toLowerCase().match(pattern);
2442
- case "contentType": return !!node.requestBody?.contentType?.match(pattern);
2443
- default: return false;
2444
- }
2445
- }
2446
- /**
2447
- * Checks if a schema matches a pattern for a given filter type (`schemaName`).
2448
- *
2449
- * Returns `null` when the filter type doesn't apply to schemas.
2450
- */
2451
- function matchesSchemaPattern(node, type, pattern) {
2452
- switch (type) {
2453
- case "schemaName": return node.name ? !!node.name.match(pattern) : false;
2454
- default: return null;
2455
- }
2456
- }
2457
- /**
2458
- * Default name resolver used by `defineResolver`.
2459
- *
2460
- * - `camelCase` for `function` and `file` types.
2461
- * - `PascalCase` for `type`.
2462
- * - `camelCase` for everything else.
2463
- */
2464
- function defaultResolver(name, type) {
2465
- let resolvedName = camelCase(name);
2466
- if (type === "file" || type === "function") resolvedName = camelCase(name, { isFile: type === "file" });
2467
- if (type === "type") resolvedName = pascalCase(name);
2468
- return resolvedName;
2469
- }
2470
- /**
2471
- * Default option resolver — applies include/exclude filters and merges matching override options.
2472
- *
2473
- * Returns `null` when the node is filtered out by an `exclude` rule or not matched by any `include` rule.
2474
- *
2475
- * @example Include/exclude filtering
2476
- * ```ts
2477
- * const options = defaultResolveOptions(operationNode, {
2478
- * options: { output: 'types' },
2479
- * exclude: [{ type: 'tag', pattern: 'internal' }],
2480
- * })
2481
- * // → null when node has tag 'internal'
2482
- * ```
2483
- *
2484
- * @example Override merging
2485
- * ```ts
2486
- * const options = defaultResolveOptions(operationNode, {
2487
- * options: { enumType: 'asConst' },
2488
- * override: [{ type: 'operationId', pattern: 'listPets', options: { enumType: 'enum' } }],
2489
- * })
2490
- * // → { enumType: 'enum' } when operationId matches
2491
- * ```
2492
- */
2493
- function defaultResolveOptions(node, { options, exclude = [], include, override = [] }) {
2494
- if ((0, _kubb_ast.isOperationNode)(node)) {
2495
- if (exclude.some(({ type, pattern }) => matchesOperationPattern(node, type, pattern))) return null;
2496
- if (include && !include.some(({ type, pattern }) => matchesOperationPattern(node, type, pattern))) return null;
2497
- const overrideOptions = override.find(({ type, pattern }) => matchesOperationPattern(node, type, pattern))?.options;
2498
- return {
2499
- ...options,
2500
- ...overrideOptions
2501
- };
2502
- }
2503
- if ((0, _kubb_ast.isSchemaNode)(node)) {
2504
- if (exclude.some(({ type, pattern }) => matchesSchemaPattern(node, type, pattern) === true)) return null;
2505
- if (include) {
2506
- const applicable = include.map(({ type, pattern }) => matchesSchemaPattern(node, type, pattern)).filter((r) => r !== null);
2507
- if (applicable.length > 0 && !applicable.includes(true)) return null;
2508
- }
2509
- const overrideOptions = override.find(({ type, pattern }) => matchesSchemaPattern(node, type, pattern) === true)?.options;
2510
- return {
2511
- ...options,
2512
- ...overrideOptions
2513
- };
2514
- }
2515
- return options;
2516
- }
2517
- /**
2518
- * Default path resolver used by `defineResolver`.
2519
- *
2520
- * - Returns the output directory in `single` mode.
2521
- * - Resolves into a tag- or path-based subdirectory when `group` and a `tag`/`path` value are provided.
2522
- * - Falls back to a flat `output/baseName` path otherwise.
2523
- *
2524
- * A custom `group.name` function overrides the default subdirectory naming.
2525
- * For `tag` groups the default is `${camelCase(tag)}Controller`.
2526
- * For `path` groups the default is the first path segment after `/`.
2527
- *
2528
- * @example Flat output
2529
- * ```ts
2530
- * defaultResolvePath({ baseName: 'petTypes.ts' }, { root: '/src', output: { path: 'types' } })
2531
- * // → '/src/types/petTypes.ts'
2532
- * ```
2533
- *
2534
- * @example Tag-based grouping
2535
- * ```ts
2536
- * defaultResolvePath(
2537
- * { baseName: 'petTypes.ts', tag: 'pets' },
2538
- * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },
2539
- * )
2540
- * // → '/src/types/petsController/petTypes.ts'
2541
- * ```
2542
- *
2543
- * @example Path-based grouping
2544
- * ```ts
2545
- * defaultResolvePath(
2546
- * { baseName: 'petTypes.ts', path: '/pets/list' },
2547
- * { root: '/src', output: { path: 'types' }, group: { type: 'path' } },
2548
- * )
2549
- * // → '/src/types/pets/petTypes.ts'
2550
- * ```
2551
- *
2552
- * @example Single-file mode
2553
- * ```ts
2554
- * defaultResolvePath(
2555
- * { baseName: 'petTypes.ts', pathMode: 'single' },
2556
- * { root: '/src', output: { path: 'types' } },
2557
- * )
2558
- * // → '/src/types'
2559
- * ```
2560
- */
2561
- function defaultResolvePath({ baseName, pathMode, tag, path: groupPath }, { root, output, group }) {
2562
- if ((pathMode ?? getMode(node_path.default.resolve(root, output.path))) === "single") return node_path.default.resolve(root, output.path);
2563
- if (group && (groupPath || tag)) return node_path.default.resolve(root, output.path, group.name({ group: group.type === "path" ? groupPath : tag }), baseName);
2564
- return node_path.default.resolve(root, output.path, baseName);
2565
- }
2566
- /**
2567
- * Default file resolver used by `defineResolver`.
2568
- *
2569
- * Resolves a `FileNode` by combining name resolution (`resolver.default`) with
2570
- * path resolution (`resolver.resolvePath`). The resolved file always has empty
2571
- * `sources`, `imports`, and `exports` arrays — consumers populate those separately.
2572
- *
2573
- * In `single` mode the name is omitted and the file sits directly in the output directory.
2574
- *
2575
- * @example Resolve a schema file
2576
- * ```ts
2577
- * const file = defaultResolveFile.call(resolver,
2578
- * { name: 'pet', extname: '.ts' },
2579
- * { root: '/src', output: { path: 'types' } },
2580
- * )
2581
- * // → { baseName: 'pet.ts', path: '/src/types/pet.ts', sources: [], ... }
2582
- * ```
2583
- *
2584
- * @example Resolve an operation file with tag grouping
2585
- * ```ts
2586
- * const file = defaultResolveFile.call(resolver,
2587
- * { name: 'listPets', extname: '.ts', tag: 'pets' },
2588
- * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },
2589
- * )
2590
- * // → { baseName: 'listPets.ts', path: '/src/types/petsController/listPets.ts', ... }
2591
- * ```
2592
- */
2593
- function defaultResolveFile({ name, extname, tag, path: groupPath }, context) {
2594
- const pathMode = getMode(node_path.default.resolve(context.root, context.output.path));
2595
- const baseName = `${pathMode === "single" ? "" : this.default(name, "file")}${extname}`;
2596
- const filePath = this.resolvePath({
2597
- baseName,
2598
- pathMode,
2599
- tag,
2600
- path: groupPath
2601
- }, context);
2602
- return (0, _kubb_ast.createFile)({
2603
- path: filePath,
2604
- baseName: node_path.default.basename(filePath),
2605
- meta: { pluginName: this.pluginName },
2606
- sources: [],
2607
- imports: [],
2608
- exports: []
2609
- });
2610
- }
2611
- /**
2612
- * Generates the default "Generated by Kubb" banner from config and optional node metadata.
2613
- */
2614
- function buildDefaultBanner({ title, description, version, config }) {
2615
- try {
2616
- let source = "";
2617
- if (Array.isArray(config.input)) {
2618
- const first = config.input[0];
2619
- if (first && "path" in first) source = node_path.default.basename(first.path);
2620
- } else if ("path" in config.input) source = node_path.default.basename(config.input.path);
2621
- else if ("data" in config.input) source = "text content";
2622
- let banner = "/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n";
2623
- if (config.output.defaultBanner === "simple") {
2624
- banner += "*/\n";
2625
- return banner;
2626
- }
2627
- if (source) banner += `* Source: ${source}\n`;
2628
- if (title) banner += `* Title: ${title}\n`;
2629
- if (description) {
2630
- const formattedDescription = description.replace(/\n/gm, "\n* ");
2631
- banner += `* Description: ${formattedDescription}\n`;
2632
- }
2633
- if (version) banner += `* OpenAPI spec version: ${version}\n`;
2634
- banner += "*/\n";
2635
- return banner;
2636
- } catch (_error) {
2637
- return "/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/";
2638
- }
2639
- }
2640
- /**
2641
- * Default banner resolver — returns the banner string for a generated file.
2642
- *
2643
- * A user-supplied `output.banner` overrides the default Kubb "Generated by Kubb" notice.
2644
- * When no `output.banner` is set, the Kubb notice is used (including `title` and `version`
2645
- * from the OAS spec when a `node` is provided).
2646
- *
2647
- * - When `output.banner` is a function and `node` is provided, returns `output.banner(node)`.
2648
- * - When `output.banner` is a function and `node` is absent, falls back to the Kubb notice.
2649
- * - When `output.banner` is a string, returns it directly.
2650
- * - When `config.output.defaultBanner` is `false`, returns `undefined`.
2651
- * - Otherwise returns the Kubb "Generated by Kubb" notice.
2652
- *
2653
- * @example String banner overrides default
2654
- * ```ts
2655
- * defaultResolveBanner(undefined, { output: { banner: '// my banner' }, config })
2656
- * // → '// my banner'
2657
- * ```
2658
- *
2659
- * @example Function banner with node
2660
- * ```ts
2661
- * defaultResolveBanner(inputNode, { output: { banner: (node) => `// v${node.version}` }, config })
2662
- * // → '// v3.0.0'
2663
- * ```
2664
- *
2665
- * @example No user banner — Kubb notice with OAS metadata
2666
- * ```ts
2667
- * defaultResolveBanner(inputNode, { config })
2668
- * // → '/** Generated by Kubb ... Title: Pet Store ... *\/'
2669
- * ```
2670
- *
2671
- * @example Disabled default banner
2672
- * ```ts
2673
- * defaultResolveBanner(undefined, { config: { output: { defaultBanner: false }, ...config } })
2674
- * // → undefined
2675
- * ```
2676
- */
2677
- function defaultResolveBanner(node, { output, config }) {
2678
- if (typeof output?.banner === "function") return output.banner(node);
2679
- if (typeof output?.banner === "string") return output.banner;
2680
- if (config.output.defaultBanner === false) return;
2681
- return buildDefaultBanner({
2682
- title: node?.meta?.title,
2683
- version: node?.meta?.version,
2684
- config
2685
- });
2686
- }
2687
- /**
2688
- * Default footer resolver — returns the footer string for a generated file.
2689
- *
2690
- * - When `output.footer` is a function and `node` is provided, calls it with the node.
2691
- * - When `output.footer` is a function and `node` is absent, returns `undefined`.
2692
- * - When `output.footer` is a string, returns it directly.
2693
- * - Otherwise returns `undefined`.
2694
- *
2695
- * @example String footer
2696
- * ```ts
2697
- * defaultResolveFooter(undefined, { output: { footer: '// end of file' }, config })
2698
- * // → '// end of file'
2699
- * ```
2700
- *
2701
- * @example Function footer with node
2702
- * ```ts
2703
- * defaultResolveFooter(inputNode, { output: { footer: (node) => `// ${node.title}` }, config })
2704
- * // → '// Pet Store'
2705
- * ```
2706
- */
2707
- function defaultResolveFooter(node, { output }) {
2708
- if (typeof output?.footer === "function") return node ? output.footer(node) : void 0;
2709
- if (typeof output?.footer === "string") return output.footer;
2710
- }
2711
- /**
2712
- * Defines a resolver for a plugin, injecting built-in defaults for name casing,
2713
- * include/exclude/override filtering, path resolution, and file construction.
2714
- *
2715
- * All four defaults can be overridden by providing them in the builder function:
2716
- * - `default` — name casing strategy (camelCase / PascalCase)
2717
- * - `resolveOptions` — include/exclude/override filtering
2718
- * - `resolvePath` — output path computation
2719
- * - `resolveFile` — full `FileNode` construction
2720
- *
2721
- * Methods in the builder have access to `this` (the full resolver object), so they
2722
- * can call other resolver methods without circular imports.
2723
- *
2724
- * @example Basic resolver with naming helpers
2725
- * ```ts
2726
- * export const resolver = defineResolver<PluginTs>(() => ({
2727
- * name: 'default',
2728
- * resolveName(node) {
2729
- * return this.default(node.name, 'function')
2730
- * },
2731
- * resolveTypedName(node) {
2732
- * return this.default(node.name, 'type')
2733
- * },
2734
- * }))
2735
- * ```
2736
- *
2737
- * @example Override resolvePath for a custom output structure
2738
- * ```ts
2739
- * export const resolver = defineResolver<PluginTs>(() => ({
2740
- * name: 'custom',
2741
- * resolvePath({ baseName }, { root, output }) {
2742
- * return path.resolve(root, output.path, 'generated', baseName)
2743
- * },
2744
- * }))
2745
- * ```
2746
- *
2747
- * @example Use this.default inside a helper
2748
- * ```ts
2749
- * export const resolver = defineResolver<PluginTs>(() => ({
2750
- * name: 'default',
2751
- * resolveParamName(node, param) {
2752
- * return this.default(`${node.operationId} ${param.in} ${param.name}`, 'type')
2753
- * },
2754
- * }))
2755
- * ```
2756
- */
2757
- function defineResolver(build) {
2758
- return {
2759
- default: defaultResolver,
2760
- resolveOptions: defaultResolveOptions,
2761
- resolvePath: defaultResolvePath,
2762
- resolveFile: defaultResolveFile,
2763
- resolveBanner: defaultResolveBanner,
2764
- resolveFooter: defaultResolveFooter,
2765
- ...build()
2766
- };
2767
- }
2768
- //#endregion
2769
1430
  //#region src/storages/memoryStorage.ts
2770
1431
  /**
2771
1432
  * In-memory storage driver. Useful for testing and dry-run scenarios where
@@ -2853,22 +1514,6 @@ async function detectFormatter() {
2853
1514
  return null;
2854
1515
  }
2855
1516
  //#endregion
2856
- //#region src/utils/getConfigs.ts
2857
- /**
2858
- * Resolves a {@link ConfigInput} into a normalized array of {@link Config} objects.
2859
- *
2860
- * - Awaits the config when it is a `Promise`.
2861
- * - Calls the factory function with `args` when the config is a function.
2862
- * - Wraps a single config object in an array for uniform downstream handling.
2863
- */
2864
- async function getConfigs(config, args) {
2865
- const resolved = await (typeof config === "function" ? config(args) : config);
2866
- return (Array.isArray(resolved) ? resolved : [resolved]).map((item) => ({
2867
- plugins: [],
2868
- ...item
2869
- }));
2870
- }
2871
- //#endregion
2872
1517
  //#region src/utils/getFunctionParams.ts
2873
1518
  function order(items) {
2874
1519
  return (0, remeda.sortBy)(items.filter(Boolean), ([_key, item]) => {
@@ -2987,47 +1632,6 @@ var FunctionParams = class FunctionParams {
2987
1632
  }
2988
1633
  };
2989
1634
  //#endregion
2990
- //#region src/utils/getPreset.ts
2991
- /**
2992
- * Returns a copy of `defaults` where each function in `userOverrides` is wrapped
2993
- * so a `null`/`undefined` return falls back to the original. Non-function values
2994
- * are assigned directly. All calls use the merged object as `this`.
2995
- */
2996
- function withFallback(defaults, userOverrides) {
2997
- const merged = { ...defaults };
2998
- for (const key of Object.keys(userOverrides)) {
2999
- const userVal = userOverrides[key];
3000
- const defaultVal = defaults[key];
3001
- if (typeof userVal === "function" && typeof defaultVal === "function") merged[key] = (...args) => userVal.apply(merged, args) ?? defaultVal.apply(merged, args);
3002
- else if (userVal !== void 0) merged[key] = userVal;
3003
- }
3004
- return merged;
3005
- }
3006
- /**
3007
- * Resolves a named preset into a resolver, transformer, and generators.
3008
- *
3009
- * - Selects the preset resolver; wraps it with user overrides using null/undefined fallback.
3010
- * - Composes the preset's transformers into a single visitor; wraps it with the user transformer using null/undefined fallback.
3011
- * - Combines preset generators with user-supplied generators; falls back to the `default` preset's generators when neither provides any.
3012
- */
3013
- function getPreset(params) {
3014
- const { preset: presetName, presets, resolver: userResolver, transformer: userTransformer, generators: userGenerators = [] } = params;
3015
- const preset = presets[presetName];
3016
- const presetResolver = preset?.resolver ?? presets["default"].resolver;
3017
- const resolver = userResolver ? withFallback(presetResolver, userResolver) : presetResolver;
3018
- const presetTransformers = preset?.transformers ?? [];
3019
- const presetTransformer = presetTransformers.length > 0 ? (0, _kubb_ast.composeTransformers)(...presetTransformers) : void 0;
3020
- const transformer = presetTransformer && userTransformer ? withFallback(presetTransformer, userTransformer) : userTransformer ?? presetTransformer;
3021
- const presetGenerators = preset?.generators ?? [];
3022
- const defaultGenerators = presets["default"]?.generators ?? [];
3023
- return {
3024
- resolver,
3025
- transformer,
3026
- generators: presetGenerators.length > 0 || userGenerators.length > 0 ? [...presetGenerators, ...userGenerators] : defaultGenerators,
3027
- preset
3028
- };
3029
- }
3030
- //#endregion
3031
1635
  //#region src/utils/linters.ts
3032
1636
  /**
3033
1637
  * Returns `true` when the given linter is installed and callable.
@@ -3069,7 +1673,7 @@ async function detectLinter() {
3069
1673
  //#endregion
3070
1674
  //#region src/utils/packageJSON.ts
3071
1675
  function getPackageJSONSync(cwd) {
3072
- const pkgPath = empathic_package.up({ cwd });
1676
+ const pkgPath = findPackageJSON(cwd);
3073
1677
  if (!pkgPath) return null;
3074
1678
  return JSON.parse(readSync(pkgPath));
3075
1679
  }
@@ -3111,11 +1715,18 @@ function satisfiesDependency(dependency, version, cwd) {
3111
1715
  }
3112
1716
  //#endregion
3113
1717
  exports.AsyncEventEmitter = AsyncEventEmitter;
1718
+ exports.FileManager = require_PluginDriver.FileManager;
1719
+ exports.FileProcessor = FileProcessor;
3114
1720
  exports.FunctionParams = FunctionParams;
3115
- exports.PluginDriver = PluginDriver;
1721
+ exports.PluginDriver = require_PluginDriver.PluginDriver;
3116
1722
  exports.URLPath = URLPath;
3117
- exports.build = build;
3118
- exports.buildDefaultBanner = buildDefaultBanner;
1723
+ Object.defineProperty(exports, "ast", {
1724
+ enumerable: true,
1725
+ get: function() {
1726
+ return _kubb_ast;
1727
+ }
1728
+ });
1729
+ exports.buildDefaultBanner = require_PluginDriver.buildDefaultBanner;
3119
1730
  Object.defineProperty(exports, "composeTransformers", {
3120
1731
  enumerable: true,
3121
1732
  get: function() {
@@ -3124,42 +1735,37 @@ Object.defineProperty(exports, "composeTransformers", {
3124
1735
  });
3125
1736
  exports.createAdapter = createAdapter;
3126
1737
  exports.createFunctionParams = createFunctionParams;
1738
+ exports.createKubb = createKubb;
3127
1739
  exports.createPlugin = createPlugin;
1740
+ exports.createRenderer = createRenderer;
3128
1741
  exports.createStorage = createStorage;
3129
- exports.default = build;
3130
- exports.defaultResolveBanner = defaultResolveBanner;
3131
- exports.defaultResolveFile = defaultResolveFile;
3132
- exports.defaultResolveFooter = defaultResolveFooter;
3133
- exports.defaultResolveOptions = defaultResolveOptions;
3134
- exports.defaultResolvePath = defaultResolvePath;
3135
- exports.defineConfig = defineConfig;
1742
+ exports.defaultResolveBanner = require_PluginDriver.defaultResolveBanner;
1743
+ exports.defaultResolveFile = require_PluginDriver.defaultResolveFile;
1744
+ exports.defaultResolveFooter = require_PluginDriver.defaultResolveFooter;
1745
+ exports.defaultResolveOptions = require_PluginDriver.defaultResolveOptions;
1746
+ exports.defaultResolvePath = require_PluginDriver.defaultResolvePath;
3136
1747
  exports.defineGenerator = defineGenerator;
3137
1748
  exports.defineLogger = defineLogger;
3138
1749
  exports.defineParser = defineParser;
3139
- exports.definePresets = definePresets;
1750
+ exports.definePlugin = require_PluginDriver.definePlugin;
3140
1751
  Object.defineProperty(exports, "definePrinter", {
3141
1752
  enumerable: true,
3142
1753
  get: function() {
3143
1754
  return _kubb_ast.definePrinter;
3144
1755
  }
3145
1756
  });
3146
- exports.defineResolver = defineResolver;
1757
+ exports.defineResolver = require_PluginDriver.defineResolver;
3147
1758
  exports.detectFormatter = detectFormatter;
3148
1759
  exports.detectLinter = detectLinter;
3149
- exports.formatters = formatters;
1760
+ exports.formatters = require_PluginDriver.formatters;
3150
1761
  exports.fsStorage = fsStorage;
3151
1762
  exports.getBarrelFiles = getBarrelFiles;
3152
- exports.getConfigs = getConfigs;
3153
1763
  exports.getFunctionParams = getFunctionParams;
3154
- exports.getMode = getMode;
3155
- exports.getPreset = getPreset;
1764
+ exports.getMode = require_PluginDriver.getMode;
3156
1765
  exports.isInputPath = isInputPath;
3157
- exports.linters = linters;
3158
- exports.logLevel = logLevel;
1766
+ exports.linters = require_PluginDriver.linters;
1767
+ exports.logLevel = require_PluginDriver.logLevel;
3159
1768
  exports.memoryStorage = memoryStorage;
3160
- exports.mergeGenerators = mergeGenerators;
3161
- exports.safeBuild = safeBuild;
3162
1769
  exports.satisfiesDependency = satisfiesDependency;
3163
- exports.setup = setup;
3164
1770
 
3165
1771
  //# sourceMappingURL=index.cjs.map