@kubb/core 5.0.0-alpha.31 → 5.0.0-alpha.33

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.
package/dist/index.js CHANGED
@@ -1,15 +1,14 @@
1
- import { t as __exportAll } from "./chunk-O_arW02_.js";
1
+ import { t as __name } from "./chunk--u3MIqq1.js";
2
2
  import { EventEmitter } from "node:events";
3
3
  import { readFileSync } from "node:fs";
4
4
  import { access, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
5
- import path, { basename, dirname, extname, join, posix, relative, resolve } from "node:path";
6
- import { composeTransformers, composeTransformers as composeTransformers$1, definePrinter, isOperationNode, isSchemaNode, transform, walk } from "@kubb/ast";
7
- import { Fabric, createFabric, createReactFabric } from "@kubb/react-fabric";
8
- import { fsPlugin } from "@kubb/react-fabric/plugins";
5
+ import path, { basename, dirname, extname, join, posix, resolve } from "node:path";
6
+ import { composeTransformers, composeTransformers as composeTransformers$1, createExport, createFile, createSource, definePrinter, extractStringsFromNodes, isOperationNode, isSchemaNode, transform, walk } from "@kubb/ast";
9
7
  import { performance } from "node:perf_hooks";
10
8
  import { deflateSync } from "fflate";
11
9
  import { x } from "tinyexec";
12
- import { jsx } from "@kubb/react-fabric/jsx-runtime";
10
+ import { createRenderer } from "@kubb/renderer-jsx";
11
+ import { Fragment, jsx } from "@kubb/renderer-jsx/jsx-runtime";
13
12
  import { version } from "node:process";
14
13
  import { sortBy } from "remeda";
15
14
  import * as pkg from "empathic/package";
@@ -333,6 +332,24 @@ async function clean(path) {
333
332
  });
334
333
  }
335
334
  //#endregion
335
+ //#region ../../internals/utils/src/string.ts
336
+ /**
337
+ * Strips the file extension from a path or file name.
338
+ * Only removes the last `.ext` segment when the dot is not part of a directory name.
339
+ *
340
+ * @example
341
+ * trimExtName('petStore.ts') // 'petStore'
342
+ * trimExtName('/src/models/pet.ts') // '/src/models/pet'
343
+ * trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'
344
+ * trimExtName('noExtension') // 'noExtension'
345
+ */
346
+ function trimExtName$1(text) {
347
+ const dotIndex = text.lastIndexOf(".");
348
+ if (dotIndex > 0 && !text.includes("/", dotIndex)) return text.slice(0, dotIndex);
349
+ return text;
350
+ }
351
+ __name(trimExtName$1, "trimExtName");
352
+ //#endregion
336
353
  //#region ../../internals/utils/src/promise.ts
337
354
  /** Returns `true` when `result` is a rejected `Promise.allSettled` result with a typed `reason`.
338
355
  *
@@ -705,78 +722,6 @@ const formatters = {
705
722
  }
706
723
  };
707
724
  //#endregion
708
- //#region src/defineParser.ts
709
- /**
710
- * Defines a parser with type safety.
711
- *
712
- * Use this function to create parsers that transform generated files to strings
713
- * based on their extension.
714
- *
715
- * @example
716
- * ```ts
717
- * import { defineParser } from '@kubb/core'
718
- *
719
- * export const jsonParser = defineParser({
720
- * name: 'json',
721
- * extNames: ['.json'],
722
- * parse(file) {
723
- * return file.sources.map((s) => s.value).join('\n')
724
- * },
725
- * })
726
- * ```
727
- */
728
- function defineParser(parser) {
729
- return {
730
- install() {},
731
- type: "parser",
732
- ...parser
733
- };
734
- }
735
- //#endregion
736
- //#region src/devtools.ts
737
- /**
738
- * Encodes a `RootNode` as a compressed, URL-safe string.
739
- *
740
- * The JSON representation is deflate-compressed with {@link deflateSync} before
741
- * base64url encoding, which typically reduces payload size by 70–80 % and
742
- * keeps URLs well within browser and server path-length limits.
743
- *
744
- * Use {@link decodeAst} to reverse.
745
- */
746
- function encodeAst(root) {
747
- const compressed = deflateSync(new TextEncoder().encode(JSON.stringify(root)));
748
- return Buffer.from(compressed).toString("base64url");
749
- }
750
- /**
751
- * Constructs the Kubb Studio URL for the given `RootNode`.
752
- * When `options.ast` is `true`, navigates to the AST inspector (`/ast`).
753
- * The `root` is encoded and attached as the `?root=` query parameter so Studio
754
- * can decode and render it without a round-trip to any server.
755
- */
756
- function getStudioUrl(root, studioUrl, options = {}) {
757
- return `${studioUrl.replace(/\/$/, "")}${options.ast ? "/ast" : ""}?root=${encodeAst(root)}`;
758
- }
759
- /**
760
- * Opens the Kubb Studio URL for the given `RootNode` in the default browser —
761
- *
762
- * Falls back to printing the URL if the browser cannot be launched.
763
- */
764
- async function openInStudio(root, studioUrl, options = {}) {
765
- const url = getStudioUrl(root, studioUrl, options);
766
- const cmd = process.platform === "win32" ? "cmd" : process.platform === "darwin" ? "open" : "xdg-open";
767
- const args = process.platform === "win32" ? [
768
- "/c",
769
- "start",
770
- "",
771
- url
772
- ] : [url];
773
- try {
774
- await x(cmd, args);
775
- } catch {
776
- console.log(`\n ${url}\n`);
777
- }
778
- }
779
- //#endregion
780
725
  //#region ../../node_modules/.pnpm/yocto-queue@1.2.2/node_modules/yocto-queue/index.js
781
726
  var Node = class {
782
727
  value;
@@ -904,6 +849,194 @@ function validateConcurrency(concurrency) {
904
849
  if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) throw new TypeError("Expected `concurrency` to be a number from 1 and up");
905
850
  }
906
851
  //#endregion
852
+ //#region src/FileProcessor.ts
853
+ function joinSources(file) {
854
+ return file.sources.map((item) => extractStringsFromNodes(item.nodes)).filter(Boolean).join("\n\n");
855
+ }
856
+ /**
857
+ * Converts a single file to a string using the registered parsers.
858
+ * Falls back to joining source values when no matching parser is found.
859
+ */
860
+ var FileProcessor = class {
861
+ #limit = pLimit(100);
862
+ async parse(file, { parsers, extension } = {}) {
863
+ const parseExtName = extension?.[file.extname] || void 0;
864
+ if (!parsers || !file.extname) return joinSources(file);
865
+ const parser = parsers.get(file.extname);
866
+ if (!parser) return joinSources(file);
867
+ return parser.parse(file, { extname: parseExtName });
868
+ }
869
+ async run(files, { parsers, mode = "sequential", extension, onStart, onEnd, onUpdate } = {}) {
870
+ await onStart?.(files);
871
+ const total = files.length;
872
+ let processed = 0;
873
+ const processOne = async (file) => {
874
+ const source = await this.parse(file, {
875
+ extension,
876
+ parsers
877
+ });
878
+ const currentProcessed = ++processed;
879
+ const percentage = currentProcessed / total * 100;
880
+ await onUpdate?.({
881
+ file,
882
+ source,
883
+ processed: currentProcessed,
884
+ percentage,
885
+ total
886
+ });
887
+ };
888
+ if (mode === "sequential") for (const file of files) await processOne(file);
889
+ else await Promise.all(files.map((file) => this.#limit(() => processOne(file))));
890
+ await onEnd?.(files);
891
+ return files;
892
+ }
893
+ };
894
+ //#endregion
895
+ //#region src/devtools.ts
896
+ /**
897
+ * Encodes an `InputNode` as a compressed, URL-safe string.
898
+ *
899
+ * The JSON representation is deflate-compressed with {@link deflateSync} before
900
+ * base64url encoding, which typically reduces payload size by 70–80 % and
901
+ * keeps URLs well within browser and server path-length limits.
902
+ *
903
+ * Use {@link decodeAst} to reverse.
904
+ */
905
+ function encodeAst(input) {
906
+ const compressed = deflateSync(new TextEncoder().encode(JSON.stringify(input)));
907
+ return Buffer.from(compressed).toString("base64url");
908
+ }
909
+ /**
910
+ * Constructs the Kubb Studio URL for the given `InputNode`.
911
+ * When `options.ast` is `true`, navigates to the AST inspector (`/ast`).
912
+ * The `input` is encoded and attached as the `?root=` query parameter so Studio
913
+ * can decode and render it without a round-trip to any server.
914
+ */
915
+ function getStudioUrl(input, studioUrl, options = {}) {
916
+ return `${studioUrl.replace(/\/$/, "")}${options.ast ? "/ast" : ""}?root=${encodeAst(input)}`;
917
+ }
918
+ /**
919
+ * Opens the Kubb Studio URL for the given `InputNode` in the default browser —
920
+ *
921
+ * Falls back to printing the URL if the browser cannot be launched.
922
+ */
923
+ async function openInStudio(input, studioUrl, options = {}) {
924
+ const url = getStudioUrl(input, studioUrl, options);
925
+ const cmd = process.platform === "win32" ? "cmd" : process.platform === "darwin" ? "open" : "xdg-open";
926
+ const args = process.platform === "win32" ? [
927
+ "/c",
928
+ "start",
929
+ "",
930
+ url
931
+ ] : [url];
932
+ try {
933
+ await x(cmd, args);
934
+ } catch {
935
+ console.log(`\n ${url}\n`);
936
+ }
937
+ }
938
+ //#endregion
939
+ //#region src/FileManager.ts
940
+ function mergeFile(a, b) {
941
+ return {
942
+ ...a,
943
+ sources: [...a.sources || [], ...b.sources || []],
944
+ imports: [...a.imports || [], ...b.imports || []],
945
+ exports: [...a.exports || [], ...b.exports || []]
946
+ };
947
+ }
948
+ /**
949
+ * In-memory file store for generated files.
950
+ *
951
+ * Files with the same `path` are merged — sources, imports, and exports are concatenated.
952
+ * The `files` getter returns all stored files sorted by path length (shortest first).
953
+ *
954
+ * @example
955
+ * ```ts
956
+ * import { FileManager } from '@kubb/core'
957
+ *
958
+ * const manager = new FileManager()
959
+ * manager.upsert(myFile)
960
+ * console.log(manager.files) // all stored files
961
+ * ```
962
+ */
963
+ var FileManager = class {
964
+ #cache = /* @__PURE__ */ new Map();
965
+ #filesCache = null;
966
+ /**
967
+ * Adds one or more files. Files with the same path are merged — sources, imports,
968
+ * and exports from all calls with the same path are concatenated together.
969
+ */
970
+ add(...files) {
971
+ const resolvedFiles = [];
972
+ const mergedFiles = /* @__PURE__ */ new Map();
973
+ files.forEach((file) => {
974
+ const existing = mergedFiles.get(file.path);
975
+ if (existing) mergedFiles.set(file.path, mergeFile(existing, file));
976
+ else mergedFiles.set(file.path, file);
977
+ });
978
+ for (const file of mergedFiles.values()) {
979
+ const resolvedFile = createFile(file);
980
+ this.#cache.set(resolvedFile.path, resolvedFile);
981
+ this.#filesCache = null;
982
+ resolvedFiles.push(resolvedFile);
983
+ }
984
+ return resolvedFiles;
985
+ }
986
+ /**
987
+ * Adds or merges one or more files.
988
+ * If a file with the same path already exists, its sources/imports/exports are merged together.
989
+ */
990
+ upsert(...files) {
991
+ const resolvedFiles = [];
992
+ const mergedFiles = /* @__PURE__ */ new Map();
993
+ files.forEach((file) => {
994
+ const existing = mergedFiles.get(file.path);
995
+ if (existing) mergedFiles.set(file.path, mergeFile(existing, file));
996
+ else mergedFiles.set(file.path, file);
997
+ });
998
+ for (const file of mergedFiles.values()) {
999
+ const existing = this.#cache.get(file.path);
1000
+ const resolvedFile = createFile(existing ? mergeFile(existing, file) : file);
1001
+ this.#cache.set(resolvedFile.path, resolvedFile);
1002
+ this.#filesCache = null;
1003
+ resolvedFiles.push(resolvedFile);
1004
+ }
1005
+ return resolvedFiles;
1006
+ }
1007
+ getByPath(path) {
1008
+ return this.#cache.get(path) ?? null;
1009
+ }
1010
+ deleteByPath(path) {
1011
+ this.#cache.delete(path);
1012
+ this.#filesCache = null;
1013
+ }
1014
+ clear() {
1015
+ this.#cache.clear();
1016
+ this.#filesCache = null;
1017
+ }
1018
+ /**
1019
+ * All stored files, sorted by path length (shorter paths first).
1020
+ * Barrel/index files (e.g. index.ts) are sorted last within each length bucket.
1021
+ */
1022
+ get files() {
1023
+ if (this.#filesCache) return this.#filesCache;
1024
+ const keys = [...this.#cache.keys()].sort((a, b) => {
1025
+ if (a.length !== b.length) return a.length - b.length;
1026
+ const aIsIndex = trimExtName$1(a).endsWith("index");
1027
+ if (aIsIndex !== trimExtName$1(b).endsWith("index")) return aIsIndex ? 1 : -1;
1028
+ return 0;
1029
+ });
1030
+ const files = [];
1031
+ for (const key of keys) {
1032
+ const file = this.#cache.get(key);
1033
+ if (file) files.push(file);
1034
+ }
1035
+ this.#filesCache = files;
1036
+ return files;
1037
+ }
1038
+ };
1039
+ //#endregion
907
1040
  //#region src/utils/executeStrategies.ts
908
1041
  /**
909
1042
  * Runs promise functions in sequence, threading each result into the next call.
@@ -970,12 +1103,18 @@ var PluginDriver = class {
970
1103
  config;
971
1104
  options;
972
1105
  /**
973
- * The universal `@kubb/ast` `RootNode` produced by the adapter, set by
1106
+ * The universal `@kubb/ast` `InputNode` produced by the adapter, set by
974
1107
  * the build pipeline after the adapter's `parse()` resolves.
975
1108
  */
976
- rootNode = void 0;
1109
+ inputNode = void 0;
977
1110
  adapter = void 0;
978
1111
  #studioIsOpen = false;
1112
+ /**
1113
+ * Central file store for all generated files.
1114
+ * Plugins should use `this.addFile()` / `this.upsertFile()` (via their context) to
1115
+ * add files; this property gives direct read/write access when needed.
1116
+ */
1117
+ fileManager = new FileManager();
979
1118
  plugins = /* @__PURE__ */ new Map();
980
1119
  constructor(config, options) {
981
1120
  this.config = config;
@@ -1000,7 +1139,6 @@ var PluginDriver = class {
1000
1139
  getContext(plugin) {
1001
1140
  const driver = this;
1002
1141
  const baseContext = {
1003
- fabric: driver.options.fabric,
1004
1142
  config: driver.config,
1005
1143
  get root() {
1006
1144
  return resolve(driver.config.root, driver.config.output.path);
@@ -1014,13 +1152,13 @@ var PluginDriver = class {
1014
1152
  requirePlugin: driver.requirePlugin.bind(driver),
1015
1153
  driver,
1016
1154
  addFile: async (...files) => {
1017
- await this.options.fabric.addFile(...files);
1155
+ driver.fileManager.add(...files);
1018
1156
  },
1019
1157
  upsertFile: async (...files) => {
1020
- await this.options.fabric.upsertFile(...files);
1158
+ driver.fileManager.upsert(...files);
1021
1159
  },
1022
- get rootNode() {
1023
- return driver.rootNode;
1160
+ get inputNode() {
1161
+ return driver.inputNode;
1024
1162
  },
1025
1163
  get adapter() {
1026
1164
  return driver.adapter;
@@ -1043,10 +1181,10 @@ var PluginDriver = class {
1043
1181
  openInStudio(options) {
1044
1182
  if (!driver.config.devtools || driver.#studioIsOpen) return;
1045
1183
  if (typeof driver.config.devtools !== "object") throw new Error("Devtools must be an object");
1046
- if (!driver.rootNode || !driver.adapter) throw new Error("adapter is not defined, make sure you have set the parser in kubb.config.ts");
1184
+ if (!driver.inputNode || !driver.adapter) throw new Error("adapter is not defined, make sure you have set the parser in kubb.config.ts");
1047
1185
  driver.#studioIsOpen = true;
1048
1186
  const studioUrl = driver.config.devtools?.studioUrl ?? "https://studio.kubb.dev";
1049
- return openInStudio(driver.rootNode, studioUrl, options);
1187
+ return openInStudio(driver.inputNode, studioUrl, options);
1050
1188
  }
1051
1189
  };
1052
1190
  const mergedExtras = {};
@@ -1075,14 +1213,14 @@ var PluginDriver = class {
1075
1213
  options
1076
1214
  });
1077
1215
  if (!path) throw new Error(`Filepath should be defined for resolvedName "${resolvedName}" and pluginName "${pluginName}"`);
1078
- return {
1216
+ return createFile({
1079
1217
  path,
1080
1218
  baseName: basename(path),
1081
1219
  meta: { pluginName },
1082
1220
  sources: [],
1083
1221
  imports: [],
1084
1222
  exports: []
1085
- };
1223
+ });
1086
1224
  }
1087
1225
  /**
1088
1226
  * @deprecated use resolvers context instead
@@ -1366,20 +1504,20 @@ var PluginDriver = class {
1366
1504
  /**
1367
1505
  * Handles the return value of a plugin AST hook or generator method.
1368
1506
  *
1369
- * - React element → rendered via an isolated react-fabric context, files merged into `fabric`
1370
- * - `Array<KubbFile.File>` → upserted directly into `fabric`
1507
+ * - React element → rendered via renderer-jsx, files stored in `driver.fileManager`
1508
+ * - `Array<FileNode>` → upserted directly into `driver.fileManager`
1371
1509
  * - `void` / `null` / `undefined` → no-op (plugin handled it via `this.upsertFile`)
1372
1510
  */
1373
- async function applyHookResult(result, fabric) {
1511
+ async function applyHookResult(result, driver) {
1374
1512
  if (!result) return;
1375
1513
  if (Array.isArray(result)) {
1376
- await fabric.upsertFile(...result);
1514
+ driver.fileManager.upsert(...result);
1377
1515
  return;
1378
1516
  }
1379
- const fabricChild = createReactFabric();
1380
- await fabricChild.render(/* @__PURE__ */ jsx(Fabric, { children: result }));
1381
- fabric.context.fileManager.upsert(...fabricChild.files);
1382
- fabricChild.unmount();
1517
+ const renderer = createRenderer();
1518
+ await renderer.render(/* @__PURE__ */ jsx(Fragment, { children: result }));
1519
+ driver.fileManager.upsert(...renderer.files);
1520
+ renderer.unmount();
1383
1521
  }
1384
1522
  //#endregion
1385
1523
  //#region src/createStorage.ts
@@ -1479,7 +1617,7 @@ const fsStorage = createStorage(() => ({
1479
1617
  }));
1480
1618
  //#endregion
1481
1619
  //#region package.json
1482
- var version$1 = "5.0.0-alpha.31";
1620
+ var version$1 = "5.0.0-alpha.33";
1483
1621
  //#endregion
1484
1622
  //#region src/utils/diagnostics.ts
1485
1623
  /**
@@ -1501,7 +1639,7 @@ function getDiagnosticInfo() {
1501
1639
  //#region src/utils/TreeNode.ts
1502
1640
  /**
1503
1641
  * Tree structure used to build per-directory barrel (`index.ts`) files from a
1504
- * flat list of generated {@link KubbFile.File} entries.
1642
+ * flat list of generated {@link FileNode} entries.
1505
1643
  *
1506
1644
  * Each node represents either a directory or a file within the output tree.
1507
1645
  * Use {@link TreeNode.build} to construct a root node from a file list, then
@@ -1662,36 +1800,35 @@ function getBarrelFilesByRoot(root, files) {
1662
1800
  const cachedFiles = /* @__PURE__ */ new Map();
1663
1801
  TreeNode.build(files, root)?.forEach((treeNode) => {
1664
1802
  if (!treeNode?.children || !treeNode.parent?.data.path) return;
1665
- const barrelFile = {
1803
+ const barrelFile = createFile({
1666
1804
  path: join(treeNode.parent?.data.path, "index.ts"),
1667
1805
  baseName: "index.ts",
1668
1806
  exports: [],
1669
1807
  imports: [],
1670
1808
  sources: []
1671
- };
1809
+ });
1672
1810
  const previousBarrelFile = cachedFiles.get(barrelFile.path);
1673
1811
  treeNode.leaves.forEach((item) => {
1674
1812
  if (!item.data.name) return;
1675
1813
  (item.data.file?.sources || []).forEach((source) => {
1676
1814
  if (!item.data.file?.path || !source.isIndexable || !source.name) return;
1677
1815
  if (previousBarrelFile?.sources.some((item) => item.name === source.name && item.isTypeOnly === source.isTypeOnly)) return;
1678
- barrelFile.exports.push({
1816
+ barrelFile.exports.push(createExport({
1679
1817
  name: [source.name],
1680
1818
  path: getRelativePath(treeNode.parent?.data.path, item.data.path),
1681
1819
  isTypeOnly: source.isTypeOnly
1682
- });
1683
- barrelFile.sources.push({
1820
+ }));
1821
+ barrelFile.sources.push(createSource({
1684
1822
  name: source.name,
1685
1823
  isTypeOnly: source.isTypeOnly,
1686
- value: "",
1687
1824
  isExportable: false,
1688
1825
  isIndexable: false
1689
- });
1826
+ }));
1690
1827
  });
1691
1828
  });
1692
1829
  if (previousBarrelFile) {
1693
1830
  previousBarrelFile.sources.push(...barrelFile.sources);
1694
- previousBarrelFile.exports?.push(...barrelFile.exports || []);
1831
+ previousBarrelFile.exports.push(...barrelFile.exports);
1695
1832
  } else cachedFiles.set(barrelFile.path, barrelFile);
1696
1833
  });
1697
1834
  return [...cachedFiles.values()];
@@ -1717,7 +1854,7 @@ async function getBarrelFiles(files, { type, meta = {}, root, output }) {
1717
1854
  if (type === "all") return barrelFiles.map((file) => {
1718
1855
  return {
1719
1856
  ...file,
1720
- exports: file.exports?.map((exportItem) => {
1857
+ exports: file.exports.map((exportItem) => {
1721
1858
  return {
1722
1859
  ...exportItem,
1723
1860
  name: void 0
@@ -1747,8 +1884,7 @@ function isInputPath(config) {
1747
1884
  *
1748
1885
  * - Validates the input path (when applicable).
1749
1886
  * - Applies config defaults (`root`, `output.*`, `devtools`).
1750
- * - Creates the Fabric instance and wires storage, format, and lint hooks.
1751
- * - Runs the adapter (if configured) to produce the universal `RootNode`.
1887
+ * - Runs the adapter (if configured) to produce the universal `InputNode`.
1752
1888
  * When no adapter is supplied and `@kubb/adapter-oas` is installed as an
1753
1889
  *
1754
1890
  * Pass the returned {@link SetupResult} directly to {@link safeBuild} or {@link build}
@@ -1816,53 +1952,7 @@ async function setup(options) {
1816
1952
  });
1817
1953
  await storage?.clear(resolve(config.root, config.output.path));
1818
1954
  }
1819
- const fabric = createFabric();
1820
- fabric.use(fsPlugin);
1821
- for (const parser of config.parsers) fabric.use(parser);
1822
- fabric.use(defineParser({
1823
- name: "fallback",
1824
- extNames: void 0,
1825
- parse(file) {
1826
- return file.sources.map((item) => item.value).filter((value) => value != null).join("\n\n");
1827
- }
1828
- }));
1829
- fabric.context.on("files:processing:start", (files) => {
1830
- events.emit("files:processing:start", files);
1831
- events.emit("debug", {
1832
- date: /* @__PURE__ */ new Date(),
1833
- logs: [`Writing ${files.length} files...`]
1834
- });
1835
- });
1836
- fabric.context.on("file:processing:update", async (params) => {
1837
- const { file, source } = params;
1838
- await events.emit("file:processing:update", {
1839
- ...params,
1840
- config,
1841
- source
1842
- });
1843
- if (source) {
1844
- const key = relative(resolve(config.root), file.path);
1845
- await storage?.setItem(key, source);
1846
- sources.set(file.path, source);
1847
- }
1848
- });
1849
- fabric.context.on("files:processing:end", async (files) => {
1850
- await events.emit("files:processing:end", files);
1851
- await events.emit("debug", {
1852
- date: /* @__PURE__ */ new Date(),
1853
- logs: [`✓ File write process completed for ${files.length} files`]
1854
- });
1855
- });
1856
- await events.emit("debug", {
1857
- date: /* @__PURE__ */ new Date(),
1858
- logs: [
1859
- "✓ Fabric initialized",
1860
- ` • Storage: ${storage ? storage.name : "disabled (dry-run)"}`,
1861
- ` • Barrel type: ${config.output.barrelType || "none"}`
1862
- ]
1863
- });
1864
1955
  const driver = new PluginDriver(config, {
1865
- fabric,
1866
1956
  events,
1867
1957
  concurrency: 15
1868
1958
  });
@@ -1874,21 +1964,21 @@ async function setup(options) {
1874
1964
  logs: [`Running adapter: ${adapter.name}`]
1875
1965
  });
1876
1966
  driver.adapter = adapter;
1877
- driver.rootNode = await adapter.parse(source);
1967
+ driver.inputNode = await adapter.parse(source);
1878
1968
  await events.emit("debug", {
1879
1969
  date: /* @__PURE__ */ new Date(),
1880
1970
  logs: [
1881
- `✓ Adapter '${adapter.name}' resolved RootNode`,
1882
- ` • Schemas: ${driver.rootNode.schemas.length}`,
1883
- ` • Operations: ${driver.rootNode.operations.length}`
1971
+ `✓ Adapter '${adapter.name}' resolved InputNode`,
1972
+ ` • Schemas: ${driver.inputNode.schemas.length}`,
1973
+ ` • Operations: ${driver.inputNode.operations.length}`
1884
1974
  ]
1885
1975
  });
1886
1976
  return {
1887
1977
  config,
1888
1978
  events,
1889
- fabric,
1890
1979
  driver,
1891
- sources
1980
+ sources,
1981
+ storage
1892
1982
  };
1893
1983
  }
1894
1984
  /**
@@ -1898,7 +1988,7 @@ async function setup(options) {
1898
1988
  * Pass an existing {@link SetupResult} via `overrides` to skip the setup phase.
1899
1989
  */
1900
1990
  async function build(options, overrides) {
1901
- const { fabric, files, driver, failedPlugins, pluginTimings, error, sources } = await safeBuild(options, overrides);
1991
+ const { files, driver, failedPlugins, pluginTimings, error, sources } = await safeBuild(options, overrides);
1902
1992
  if (error) throw error;
1903
1993
  if (failedPlugins.size > 0) {
1904
1994
  const errors = [...failedPlugins].map(({ error }) => error);
@@ -1906,7 +1996,6 @@ async function build(options, overrides) {
1906
1996
  }
1907
1997
  return {
1908
1998
  failedPlugins,
1909
- fabric,
1910
1999
  files,
1911
2000
  driver,
1912
2001
  pluginTimings,
@@ -1921,15 +2010,15 @@ async function build(options, overrides) {
1921
2010
  * - Each hook accepts a single handler **or an array** — all entries are called in sequence.
1922
2011
  * - Nodes that are excluded by `exclude`/`include` plugin options are skipped automatically.
1923
2012
  * - Return values are handled via `applyHookResult`: React elements are rendered,
1924
- * `KubbFile.File[]` are written via upsert, and `void` is a no-op (manual handling).
2013
+ * `FileNode[]` are written via upsert, and `void` is a no-op (manual handling).
1925
2014
  * - Barrel files are generated automatically when `output.barrelType` is set.
1926
2015
  */
1927
2016
  async function runPluginAstHooks(plugin, context) {
1928
- const { adapter, rootNode, resolver, fabric } = context;
2017
+ const { adapter, inputNode, resolver, driver } = context;
1929
2018
  const { exclude, include, override } = plugin.options;
1930
- if (!adapter || !rootNode) throw new Error(`[${plugin.name}] No adapter found. Add an OAS adapter (e.g. pluginOas()) before this plugin in your Kubb config.`);
2019
+ 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.`);
1931
2020
  const collectedOperations = [];
1932
- await walk(rootNode, {
2021
+ await walk(inputNode, {
1933
2022
  depth: "shallow",
1934
2023
  async schema(node) {
1935
2024
  if (!plugin.schema) return;
@@ -1941,7 +2030,7 @@ async function runPluginAstHooks(plugin, context) {
1941
2030
  override
1942
2031
  });
1943
2032
  if (options === null) return;
1944
- await applyHookResult(await plugin.schema.call(context, transformedNode, options), fabric);
2033
+ await applyHookResult(await plugin.schema.call(context, transformedNode, options), driver);
1945
2034
  },
1946
2035
  async operation(node) {
1947
2036
  const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
@@ -1953,24 +2042,24 @@ async function runPluginAstHooks(plugin, context) {
1953
2042
  });
1954
2043
  if (options !== null) {
1955
2044
  collectedOperations.push(transformedNode);
1956
- if (plugin.operation) await applyHookResult(await plugin.operation.call(context, transformedNode, options), fabric);
2045
+ if (plugin.operation) await applyHookResult(await plugin.operation.call(context, transformedNode, options), driver);
1957
2046
  }
1958
2047
  }
1959
2048
  });
1960
- if (plugin.operations && collectedOperations.length > 0) await applyHookResult(await plugin.operations.call(context, collectedOperations, plugin.options), fabric);
2049
+ if (plugin.operations && collectedOperations.length > 0) await applyHookResult(await plugin.operations.call(context, collectedOperations, plugin.options), driver);
1961
2050
  }
1962
2051
  /**
1963
2052
  * Runs a full Kubb build and captures errors instead of throwing.
1964
2053
  *
1965
2054
  * - Installs each plugin in order, recording failures in `failedPlugins`.
1966
2055
  * - Generates the root barrel file when `output.barrelType` is set.
1967
- * - Writes all files through Fabric.
2056
+ * - Writes all files through the driver's FileManager and FileProcessor.
1968
2057
  *
1969
2058
  * Returns a {@link BuildOutput} even on failure — inspect `error` and
1970
2059
  * `failedPlugins` to determine whether the build succeeded.
1971
2060
  */
1972
2061
  async function safeBuild(options, overrides) {
1973
- const { fabric, driver, events, sources } = overrides ? overrides : await setup(options);
2062
+ const { driver, events, sources, storage } = overrides ? overrides : await setup(options);
1974
2063
  const failedPlugins = /* @__PURE__ */ new Set();
1975
2064
  const pluginTimings = /* @__PURE__ */ new Map();
1976
2065
  const config = driver.config;
@@ -1990,7 +2079,7 @@ async function safeBuild(options, overrides) {
1990
2079
  await plugin.buildStart.call(context);
1991
2080
  if (plugin.schema || plugin.operation || plugin.operations) await runPluginAstHooks(plugin, context);
1992
2081
  if (output) {
1993
- const barrelFiles = await getBarrelFiles(fabric.files, {
2082
+ const barrelFiles = await getBarrelFiles(driver.fileManager.files, {
1994
2083
  type: output.barrelType ?? "named",
1995
2084
  root,
1996
2085
  output,
@@ -2044,15 +2133,15 @@ async function safeBuild(options, overrides) {
2044
2133
  ` • Path: ${rootPath}`
2045
2134
  ]
2046
2135
  });
2047
- const barrelFiles = fabric.files.filter((file) => {
2136
+ const barrelFiles = driver.fileManager.files.filter((file) => {
2048
2137
  return file.sources.some((source) => source.isIndexable);
2049
2138
  });
2050
2139
  await events.emit("debug", {
2051
2140
  date: /* @__PURE__ */ new Date(),
2052
2141
  logs: [`Found ${barrelFiles.length} indexable files for barrel export`]
2053
2142
  });
2054
- const existingBarrel = fabric.files.find((f) => f.path === rootPath);
2055
- const rootFile = {
2143
+ const existingBarrel = driver.fileManager.files.find((f) => f.path === rootPath);
2144
+ const rootFile = createFile({
2056
2145
  path: rootPath,
2057
2146
  baseName: BARREL_FILENAME,
2058
2147
  exports: buildBarrelExports({
@@ -2061,26 +2150,59 @@ async function safeBuild(options, overrides) {
2061
2150
  existingExports: new Set(existingBarrel?.exports?.flatMap((e) => Array.isArray(e.name) ? e.name : [e.name]).filter((n) => Boolean(n)) ?? []),
2062
2151
  config,
2063
2152
  driver
2064
- }),
2153
+ }).map((e) => createExport(e)),
2065
2154
  sources: [],
2066
2155
  imports: [],
2067
2156
  meta: {}
2068
- };
2069
- await fabric.upsertFile(rootFile);
2157
+ });
2158
+ driver.fileManager.upsert(rootFile);
2070
2159
  await events.emit("debug", {
2071
2160
  date: /* @__PURE__ */ new Date(),
2072
2161
  logs: [`✓ Generated barrel file (${rootFile.exports?.length || 0} exports)`]
2073
2162
  });
2074
2163
  }
2075
- const files = [...fabric.files];
2076
- await fabric.write({ extension: config.output.extension });
2164
+ const files = driver.fileManager.files;
2165
+ const parsersMap = /* @__PURE__ */ new Map();
2166
+ for (const parser of config.parsers) if (parser.extNames) for (const extname of parser.extNames) parsersMap.set(extname, parser);
2167
+ const fileProcessor = new FileProcessor();
2168
+ await events.emit("debug", {
2169
+ date: /* @__PURE__ */ new Date(),
2170
+ logs: [`Writing ${files.length} files...`]
2171
+ });
2172
+ await fileProcessor.run(files, {
2173
+ parsers: parsersMap,
2174
+ extension: config.output.extension,
2175
+ onStart: async (processingFiles) => {
2176
+ await events.emit("files:processing:start", processingFiles);
2177
+ },
2178
+ onUpdate: async ({ file, source, processed, total, percentage }) => {
2179
+ await events.emit("file:processing:update", {
2180
+ file,
2181
+ source,
2182
+ processed,
2183
+ total,
2184
+ percentage,
2185
+ config
2186
+ });
2187
+ if (source) {
2188
+ await storage?.setItem(file.path, source);
2189
+ sources.set(file.path, source);
2190
+ }
2191
+ },
2192
+ onEnd: async (processedFiles) => {
2193
+ await events.emit("files:processing:end", processedFiles);
2194
+ await events.emit("debug", {
2195
+ date: /* @__PURE__ */ new Date(),
2196
+ logs: [`✓ File write process completed for ${processedFiles.length} files`]
2197
+ });
2198
+ }
2199
+ });
2077
2200
  for (const plugin of driver.plugins.values()) if (plugin.buildEnd) {
2078
2201
  const context = driver.getContext(plugin);
2079
2202
  await plugin.buildEnd.call(context);
2080
2203
  }
2081
2204
  return {
2082
2205
  failedPlugins,
2083
- fabric,
2084
2206
  files,
2085
2207
  driver,
2086
2208
  pluginTimings,
@@ -2089,7 +2211,6 @@ async function safeBuild(options, overrides) {
2089
2211
  } catch (error) {
2090
2212
  return {
2091
2213
  failedPlugins,
2092
- fabric,
2093
2214
  files: [],
2094
2215
  driver,
2095
2216
  pluginTimings,
@@ -2110,11 +2231,11 @@ function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, dri
2110
2231
  if (!pluginOptions || pluginOptions.output?.barrelType === false) return [];
2111
2232
  const exportName = config.output.barrelType === "all" ? void 0 : source.name ? [source.name] : void 0;
2112
2233
  if (exportName?.some((n) => existingExports.has(n))) return [];
2113
- return [{
2234
+ return [createExport({
2114
2235
  name: exportName,
2115
2236
  path: getRelativePath(rootDir, file.path),
2116
2237
  isTypeOnly: config.output.barrelType === "all" ? containsOnlyTypes : source.isTypeOnly
2117
- }];
2238
+ })];
2118
2239
  });
2119
2240
  });
2120
2241
  }
@@ -2226,19 +2347,19 @@ function mergeGenerators(generators) {
2226
2347
  async schema(node, options) {
2227
2348
  for (const gen of generators) {
2228
2349
  if (!gen.schema) continue;
2229
- await applyHookResult(await gen.schema.call(this, node, options), this.fabric);
2350
+ await applyHookResult(await gen.schema.call(this, node, options), this.driver);
2230
2351
  }
2231
2352
  },
2232
2353
  async operation(node, options) {
2233
2354
  for (const gen of generators) {
2234
2355
  if (!gen.operation) continue;
2235
- await applyHookResult(await gen.operation.call(this, node, options), this.fabric);
2356
+ await applyHookResult(await gen.operation.call(this, node, options), this.driver);
2236
2357
  }
2237
2358
  },
2238
2359
  async operations(nodes, options) {
2239
2360
  for (const gen of generators) {
2240
2361
  if (!gen.operations) continue;
2241
- await applyHookResult(await gen.operations.call(this, nodes, options), this.fabric);
2362
+ await applyHookResult(await gen.operations.call(this, nodes, options), this.driver);
2242
2363
  }
2243
2364
  }
2244
2365
  };
@@ -2261,6 +2382,31 @@ function defineLogger(logger) {
2261
2382
  return logger;
2262
2383
  }
2263
2384
  //#endregion
2385
+ //#region src/defineParser.ts
2386
+ /**
2387
+ * Defines a parser with type safety.
2388
+ *
2389
+ * Use this function to create parsers that transform generated files to strings
2390
+ * based on their extension.
2391
+ *
2392
+ * @example
2393
+ * ```ts
2394
+ * import { defineParser } from '@kubb/core'
2395
+ *
2396
+ * export const jsonParser = defineParser({
2397
+ * name: 'json',
2398
+ * extNames: ['.json'],
2399
+ * parse(file) {
2400
+ * const { extractStringsFromNodes } = await import('@kubb/ast')
2401
+ * return file.sources.map((s) => extractStringsFromNodes(s.nodes ?? [])).join('\n')
2402
+ * },
2403
+ * })
2404
+ * ```
2405
+ */
2406
+ function defineParser(parser) {
2407
+ return parser;
2408
+ }
2409
+ //#endregion
2264
2410
  //#region src/definePresets.ts
2265
2411
  /**
2266
2412
  * Creates a typed presets registry object — a named collection of {@link Preset} entries.
@@ -2414,7 +2560,7 @@ function defaultResolvePath({ baseName, pathMode, tag, path: groupPath }, { root
2414
2560
  /**
2415
2561
  * Default file resolver used by `defineResolver`.
2416
2562
  *
2417
- * Resolves a `KubbFile.File` by combining name resolution (`resolver.default`) with
2563
+ * Resolves a `FileNode` by combining name resolution (`resolver.default`) with
2418
2564
  * path resolution (`resolver.resolvePath`). The resolved file always has empty
2419
2565
  * `sources`, `imports`, and `exports` arrays — consumers populate those separately.
2420
2566
  *
@@ -2447,14 +2593,14 @@ function defaultResolveFile({ name, extname, tag, path: groupPath }, context) {
2447
2593
  tag,
2448
2594
  path: groupPath
2449
2595
  }, context);
2450
- return {
2596
+ return createFile({
2451
2597
  path: filePath,
2452
2598
  baseName: path.basename(filePath),
2453
2599
  meta: { pluginName: this.pluginName },
2454
2600
  sources: [],
2455
2601
  imports: [],
2456
2602
  exports: []
2457
- };
2603
+ });
2458
2604
  }
2459
2605
  /**
2460
2606
  * Generates the default "Generated by Kubb" banner from config and optional node metadata.
@@ -2506,13 +2652,13 @@ function buildDefaultBanner({ title, description, version, config }) {
2506
2652
  *
2507
2653
  * @example Function banner with node
2508
2654
  * ```ts
2509
- * defaultResolveBanner(rootNode, { output: { banner: (node) => `// v${node.version}` }, config })
2655
+ * defaultResolveBanner(inputNode, { output: { banner: (node) => `// v${node.version}` }, config })
2510
2656
  * // → '// v3.0.0'
2511
2657
  * ```
2512
2658
  *
2513
2659
  * @example No user banner — Kubb notice with OAS metadata
2514
2660
  * ```ts
2515
- * defaultResolveBanner(rootNode, { config })
2661
+ * defaultResolveBanner(inputNode, { config })
2516
2662
  * // → '/** Generated by Kubb ... Title: Pet Store ... *\/'
2517
2663
  * ```
2518
2664
  *
@@ -2548,7 +2694,7 @@ function defaultResolveBanner(node, { output, config }) {
2548
2694
  *
2549
2695
  * @example Function footer with node
2550
2696
  * ```ts
2551
- * defaultResolveFooter(rootNode, { output: { footer: (node) => `// ${node.title}` }, config })
2697
+ * defaultResolveFooter(inputNode, { output: { footer: (node) => `// ${node.title}` }, config })
2552
2698
  * // → '// Pet Store'
2553
2699
  * ```
2554
2700
  */
@@ -2564,7 +2710,7 @@ function defaultResolveFooter(node, { output }) {
2564
2710
  * - `default` — name casing strategy (camelCase / PascalCase)
2565
2711
  * - `resolveOptions` — include/exclude/override filtering
2566
2712
  * - `resolvePath` — output path computation
2567
- * - `resolveFile` — full `KubbFile.File` construction
2713
+ * - `resolveFile` — full `FileNode` construction
2568
2714
  *
2569
2715
  * Methods in the builder have access to `this` (the full resolver object), so they
2570
2716
  * can call other resolver methods without circular imports.
@@ -2614,9 +2760,6 @@ function defineResolver(build) {
2614
2760
  };
2615
2761
  }
2616
2762
  //#endregion
2617
- //#region src/KubbFile.ts
2618
- var KubbFile_exports = /* @__PURE__ */ __exportAll({});
2619
- //#endregion
2620
2763
  //#region src/storages/memoryStorage.ts
2621
2764
  /**
2622
2765
  * In-memory storage driver. Useful for testing and dry-run scenarios where
@@ -2665,82 +2808,6 @@ const memoryStorage = createStorage(() => {
2665
2808
  };
2666
2809
  });
2667
2810
  //#endregion
2668
- //#region src/utils/FunctionParams.ts
2669
- /**
2670
- * @deprecated use ast package instead
2671
- */
2672
- var FunctionParams = class FunctionParams {
2673
- #items = [];
2674
- get items() {
2675
- return this.#items.flat();
2676
- }
2677
- add(item) {
2678
- if (!item) return this;
2679
- if (Array.isArray(item)) {
2680
- item.filter((x) => x !== void 0).forEach((it) => {
2681
- this.#items.push(it);
2682
- });
2683
- return this;
2684
- }
2685
- this.#items.push(item);
2686
- return this;
2687
- }
2688
- static #orderItems(items) {
2689
- return sortBy(items.filter(Boolean), [(item) => Array.isArray(item), "desc"], [(item) => !Array.isArray(item) && item.default !== void 0, "asc"], [(item) => Array.isArray(item) || (item.required ?? true), "desc"]);
2690
- }
2691
- static #addParams(acc, item) {
2692
- const { enabled = true, name, type, required = true, ...rest } = item;
2693
- if (!enabled) return acc;
2694
- if (!name) {
2695
- acc.push(`${type}${rest.default ? ` = ${rest.default}` : ""}`);
2696
- return acc;
2697
- }
2698
- const parameterName = name.startsWith("{") ? name : camelCase(name);
2699
- if (type) if (required) acc.push(`${parameterName}: ${type}${rest.default ? ` = ${rest.default}` : ""}`);
2700
- else acc.push(`${parameterName}?: ${type}`);
2701
- else acc.push(`${parameterName}`);
2702
- return acc;
2703
- }
2704
- static toObject(items) {
2705
- let type = [];
2706
- let name = [];
2707
- const enabled = items.every((item) => item.enabled) ? items.at(0)?.enabled : true;
2708
- const required = items.every((item) => item.required) ?? true;
2709
- items.forEach((item) => {
2710
- name = FunctionParams.#addParams(name, {
2711
- ...item,
2712
- type: void 0
2713
- });
2714
- if (items.some((item) => item.type)) type = FunctionParams.#addParams(type, item);
2715
- });
2716
- return {
2717
- name: `{ ${name.join(", ")} }`,
2718
- type: type.length ? `{ ${type.join("; ")} }` : void 0,
2719
- enabled,
2720
- required
2721
- };
2722
- }
2723
- toObject() {
2724
- const items = FunctionParams.#orderItems(this.#items).flat();
2725
- return FunctionParams.toObject(items);
2726
- }
2727
- static toString(items) {
2728
- return FunctionParams.#orderItems(items).reduce((acc, item) => {
2729
- if (Array.isArray(item)) {
2730
- if (item.length <= 0) return acc;
2731
- const subItems = FunctionParams.#orderItems(item);
2732
- const objectItem = FunctionParams.toObject(subItems);
2733
- return FunctionParams.#addParams(acc, objectItem);
2734
- }
2735
- return FunctionParams.#addParams(acc, item);
2736
- }, []).join(", ");
2737
- }
2738
- toString() {
2739
- const items = FunctionParams.#orderItems(this.#items);
2740
- return FunctionParams.toString(items);
2741
- }
2742
- };
2743
- //#endregion
2744
2811
  //#region src/utils/formatters.ts
2745
2812
  /**
2746
2813
  * Returns `true` when the given formatter is installed and callable.
@@ -2796,6 +2863,124 @@ async function getConfigs(config, args) {
2796
2863
  }));
2797
2864
  }
2798
2865
  //#endregion
2866
+ //#region src/utils/getFunctionParams.ts
2867
+ function order(items) {
2868
+ return sortBy(items.filter(Boolean), ([_key, item]) => {
2869
+ if (item?.children) return 0;
2870
+ if (item?.optional) return 1;
2871
+ if (item?.default) return 2;
2872
+ return 0;
2873
+ });
2874
+ }
2875
+ function parseChild(key, item, options) {
2876
+ const entries = order(Object.entries(item.children));
2877
+ const types = [];
2878
+ const names = [];
2879
+ const optional = entries.every(([_key, item]) => item?.optional || !!item?.default);
2880
+ entries.forEach(([key, entryItem]) => {
2881
+ if (entryItem) {
2882
+ const name = parseItem(key, {
2883
+ ...entryItem,
2884
+ type: void 0
2885
+ }, options);
2886
+ if (entryItem.children) {
2887
+ const subTypes = Object.entries(entryItem.children).map(([key]) => {
2888
+ return key;
2889
+ }).join(", ");
2890
+ if (subTypes) names.push(`${name}: { ${subTypes} }`);
2891
+ else names.push(name);
2892
+ } else if (options.type === "call" && options.transformName) names.push(`${key}: ${name}`);
2893
+ else names.push(name);
2894
+ if (entries.some(([_key, item]) => item?.type)) types.push(parseItem(key, {
2895
+ ...entryItem,
2896
+ default: void 0
2897
+ }, options));
2898
+ }
2899
+ });
2900
+ const name = item.mode === "inline" ? key : names.length ? `{ ${names.join(", ")} }` : void 0;
2901
+ const type = item.type ? item.type : types.length ? `{ ${types.join("; ")} }` : void 0;
2902
+ if (!name) return null;
2903
+ return parseItem(name, {
2904
+ type,
2905
+ default: item.default,
2906
+ optional: !item.default ? optional : void 0
2907
+ }, options);
2908
+ }
2909
+ function parseItem(name, item, options) {
2910
+ const acc = [];
2911
+ const transformedName = options.transformName ? options.transformName(name) : name;
2912
+ const transformedType = options.transformType && item.type ? options.transformType(item.type) : item.type;
2913
+ if (options.type === "object") return transformedName;
2914
+ if (options.type === "objectValue") return item.value ? `${transformedName}: ${item.value}` : transformedName;
2915
+ if (item.type && options.type === "constructor") if (item.optional) if (transformedName.startsWith("{")) acc.push(`${transformedName}: ${transformedType} = {}`);
2916
+ else acc.push(`${transformedName}?: ${transformedType}`);
2917
+ else acc.push(`${transformedName}: ${transformedType}${item.default ? ` = ${item.default}` : ""}`);
2918
+ else if (item.default && options.type === "constructor") acc.push(`${transformedName} = ${item.default}`);
2919
+ else if (item.value) acc.push(`${transformedName} : ${item.value}`);
2920
+ else if (item.mode === "inlineSpread") acc.push(`... ${transformedName}`);
2921
+ else acc.push(transformedName);
2922
+ return acc[0];
2923
+ }
2924
+ function getFunctionParams(params, options) {
2925
+ return order(Object.entries(params)).reduce((acc, [key, item]) => {
2926
+ if (!item) return acc;
2927
+ if (item.children) {
2928
+ if (Object.keys(item.children).length === 0) return acc;
2929
+ if (item.mode === "inlineSpread") return [...acc, getFunctionParams(item.children, options)];
2930
+ const parsedItem = parseChild(key, item, options);
2931
+ if (!parsedItem) return acc;
2932
+ return [...acc, parsedItem];
2933
+ }
2934
+ const parsedItem = parseItem(key, item, options);
2935
+ return [...acc, parsedItem];
2936
+ }, []).join(", ");
2937
+ }
2938
+ /**
2939
+ * @deprecated use @kubb/ast
2940
+ */
2941
+ function createFunctionParams(params) {
2942
+ return params;
2943
+ }
2944
+ /**
2945
+ * @deprecated use @kubb/ast
2946
+ */
2947
+ var FunctionParams = class FunctionParams {
2948
+ #params;
2949
+ static factory(params) {
2950
+ return new FunctionParams(params);
2951
+ }
2952
+ constructor(params) {
2953
+ this.#params = params;
2954
+ }
2955
+ get params() {
2956
+ return this.#params;
2957
+ }
2958
+ get flatParams() {
2959
+ const flatter = (acc, [key, item]) => {
2960
+ if (item?.children) return Object.entries(item.children).reduce(flatter, acc);
2961
+ if (item) acc[key] = item;
2962
+ return acc;
2963
+ };
2964
+ return Object.entries(this.#params).reduce(flatter, {});
2965
+ }
2966
+ toCall({ transformName, transformType } = {}) {
2967
+ return getFunctionParams(this.#params, {
2968
+ type: "call",
2969
+ transformName,
2970
+ transformType
2971
+ });
2972
+ }
2973
+ toObject() {
2974
+ return getFunctionParams(this.#params, { type: "object" });
2975
+ }
2976
+ toObjectValue() {
2977
+ return getFunctionParams(this.#params, { type: "objectValue" });
2978
+ }
2979
+ toConstructor() {
2980
+ return getFunctionParams(this.#params, { type: "constructor" });
2981
+ }
2982
+ };
2983
+ //#endregion
2799
2984
  //#region src/utils/getPreset.ts
2800
2985
  /**
2801
2986
  * Returns a copy of `defaults` where each function in `userOverrides` is wrapped
@@ -2919,6 +3104,6 @@ function satisfiesDependency(dependency, version, cwd) {
2919
3104
  return satisfies(semVer, version);
2920
3105
  }
2921
3106
  //#endregion
2922
- export { AsyncEventEmitter, FunctionParams, KubbFile_exports as KubbFile, PluginDriver, URLPath, build, build as default, buildDefaultBanner, composeTransformers, createAdapter, createPlugin, createStorage, defaultResolveBanner, defaultResolveFile, defaultResolveFooter, defaultResolveOptions, defaultResolvePath, defineConfig, defineGenerator, defineLogger, defineParser, definePresets, definePrinter, defineResolver, detectFormatter, detectLinter, formatters, fsStorage, getBarrelFiles, getConfigs, getMode, getPreset, isInputPath, linters, logLevel, memoryStorage, mergeGenerators, safeBuild, satisfiesDependency, setup };
3107
+ export { AsyncEventEmitter, FunctionParams, PluginDriver, URLPath, build, build as default, buildDefaultBanner, composeTransformers, createAdapter, createFunctionParams, createPlugin, createStorage, defaultResolveBanner, defaultResolveFile, defaultResolveFooter, defaultResolveOptions, defaultResolvePath, defineConfig, defineGenerator, defineLogger, defineParser, definePresets, definePrinter, defineResolver, detectFormatter, detectLinter, formatters, fsStorage, getBarrelFiles, getConfigs, getFunctionParams, getMode, getPreset, isInputPath, linters, logLevel, memoryStorage, mergeGenerators, safeBuild, satisfiesDependency, setup };
2923
3108
 
2924
3109
  //# sourceMappingURL=index.js.map