@kubb/core 5.0.0-alpha.21 → 5.0.0-alpha.23

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
@@ -16,14 +16,6 @@ import { sortBy } from "remeda";
16
16
  import * as pkg from "empathic/package";
17
17
  import { coerce, satisfies } from "semver";
18
18
  //#region ../../internals/utils/src/errors.ts
19
- /** Thrown when a plugin's configuration or input fails validation.
20
- *
21
- * @example
22
- * ```ts
23
- * throw new ValidationPluginError('Invalid config: "output.path" is required')
24
- * ```
25
- */
26
- var ValidationPluginError = class extends Error {};
27
19
  /**
28
20
  * Thrown when one or more errors occur during a Kubb build.
29
21
  * Carries the full list of underlying errors on `errors`.
@@ -344,28 +336,6 @@ async function clean(path) {
344
336
  });
345
337
  }
346
338
  //#endregion
347
- //#region ../../internals/utils/src/names.ts
348
- /**
349
- * Registers `originalName` in `data` without altering the returned name.
350
- * Use when you need to track usage frequency but always emit the original identifier.
351
- *
352
- * @example
353
- * ```ts
354
- * const seen: Record<string, number> = {}
355
- * setUniqueName('Foo', seen) // 'Foo' (seen = { Foo: 1 })
356
- * setUniqueName('Foo', seen) // 'Foo' (seen = { Foo: 2 })
357
- * ```
358
- */
359
- function setUniqueName(originalName, data) {
360
- let used = data[originalName] || 0;
361
- if (used) {
362
- data[originalName] = ++used;
363
- return originalName;
364
- }
365
- data[originalName] = 1;
366
- return originalName;
367
- }
368
- //#endregion
369
339
  //#region ../../internals/utils/src/promise.ts
370
340
  /** Returns `true` when `result` is a rejected `Promise.allSettled` result with a typed `reason`.
371
341
  *
@@ -965,6 +935,15 @@ function hookParallel(promises, concurrency = Number.POSITIVE_INFINITY) {
965
935
  }
966
936
  //#endregion
967
937
  //#region src/PluginDriver.ts
938
+ /**
939
+ * Returns `'single'` when `fileOrFolder` has a file extension, `'split'` otherwise.
940
+ *
941
+ * @example
942
+ * ```ts
943
+ * getMode('src/gen/types.ts') // 'single'
944
+ * getMode('src/gen/types') // 'split'
945
+ * ```
946
+ */
968
947
  function getMode(fileOrFolder) {
969
948
  if (!fileOrFolder) return "split";
970
949
  return extname(fileOrFolder) ? "single" : "split";
@@ -980,29 +959,30 @@ var PluginDriver = class {
980
959
  rootNode = void 0;
981
960
  adapter = void 0;
982
961
  #studioIsOpen = false;
983
- #plugins = /* @__PURE__ */ new Set();
984
- #usedPluginNames = {};
962
+ plugins = /* @__PURE__ */ new Map();
985
963
  constructor(config, options) {
986
964
  this.config = config;
987
965
  this.options = options;
988
- [...config.plugins || []].forEach((plugin) => {
989
- const parsedPlugin = this.#parse(plugin);
990
- this.#plugins.add(parsedPlugin);
966
+ config.plugins.map((plugin) => Object.assign({ install() {} }, plugin)).sort((a, b) => {
967
+ if (b.pre?.includes(a.name)) return 1;
968
+ if (b.post?.includes(a.name)) return -1;
969
+ return 0;
970
+ }).forEach((plugin) => {
971
+ this.plugins.set(plugin.name, plugin);
991
972
  });
992
973
  }
993
974
  get events() {
994
975
  return this.options.events;
995
976
  }
996
977
  getContext(plugin) {
997
- const plugins = [...this.#plugins];
998
978
  const driver = this;
999
979
  const baseContext = {
1000
- fabric: this.options.fabric,
1001
- config: this.config,
980
+ fabric: driver.options.fabric,
981
+ config: driver.config,
1002
982
  plugin,
1003
- events: this.options.events,
1004
- driver: this,
1005
- mode: getMode(resolve(this.config.root, this.config.output.path)),
983
+ getPlugin: driver.getPlugin.bind(driver),
984
+ events: driver.options.events,
985
+ driver,
1006
986
  addFile: async (...files) => {
1007
987
  await this.options.fabric.addFile(...files);
1008
988
  },
@@ -1015,6 +995,9 @@ var PluginDriver = class {
1015
995
  get adapter() {
1016
996
  return driver.adapter;
1017
997
  },
998
+ get resolver() {
999
+ return plugin.resolver;
1000
+ },
1018
1001
  openInStudio(options) {
1019
1002
  if (!driver.config.devtools || driver.#studioIsOpen) return;
1020
1003
  if (typeof driver.config.devtools !== "object") throw new Error("Devtools must be an object");
@@ -1025,8 +1008,8 @@ var PluginDriver = class {
1025
1008
  }
1026
1009
  };
1027
1010
  const mergedExtras = {};
1028
- for (const p of plugins) if (typeof p.inject === "function") {
1029
- const result = p.inject.call(baseContext, baseContext);
1011
+ for (const plugin of this.plugins.values()) if (typeof plugin.inject === "function") {
1012
+ const result = plugin.inject.call(baseContext, baseContext);
1030
1013
  if (result !== null && typeof result === "object") Object.assign(mergedExtras, result);
1031
1014
  }
1032
1015
  return {
@@ -1034,9 +1017,9 @@ var PluginDriver = class {
1034
1017
  ...mergedExtras
1035
1018
  };
1036
1019
  }
1037
- get plugins() {
1038
- return this.#getSortedPlugins();
1039
- }
1020
+ /**
1021
+ * @deprecated use resolvers context instead
1022
+ */
1040
1023
  getFile({ name, mode, extname, pluginName, options }) {
1041
1024
  const resolvedName = mode ? mode === "single" ? "" : this.resolveName({
1042
1025
  name,
@@ -1059,6 +1042,9 @@ var PluginDriver = class {
1059
1042
  exports: []
1060
1043
  };
1061
1044
  }
1045
+ /**
1046
+ * @deprecated use resolvers context instead
1047
+ */
1062
1048
  resolvePath = (params) => {
1063
1049
  const defaultPath = resolve(resolve(this.config.root, this.config.output.path), params.baseName);
1064
1050
  if (params.pluginName) return this.hookForPluginSync({
@@ -1079,15 +1065,15 @@ var PluginDriver = class {
1079
1065
  ]
1080
1066
  })?.result || defaultPath;
1081
1067
  };
1068
+ /**
1069
+ * @deprecated use resolvers context instead
1070
+ */
1082
1071
  resolveName = (params) => {
1083
- if (params.pluginName) {
1084
- const names = this.hookForPluginSync({
1085
- pluginName: params.pluginName,
1086
- hookName: "resolveName",
1087
- parameters: [params.name.trim(), params.type]
1088
- });
1089
- return transformReservedWord([...new Set(names)].at(0) || params.name);
1090
- }
1072
+ if (params.pluginName) return transformReservedWord(this.hookForPluginSync({
1073
+ pluginName: params.pluginName,
1074
+ hookName: "resolveName",
1075
+ parameters: [params.name.trim(), params.type]
1076
+ })?.at(0) ?? params.name);
1091
1077
  const name = this.hookFirstSync({
1092
1078
  hookName: "resolveName",
1093
1079
  parameters: [params.name.trim(), params.type]
@@ -1098,44 +1084,41 @@ var PluginDriver = class {
1098
1084
  * Run a specific hookName for plugin x.
1099
1085
  */
1100
1086
  async hookForPlugin({ pluginName, hookName, parameters }) {
1101
- const plugins = this.getPluginsByName(hookName, pluginName);
1087
+ const plugin = this.plugins.get(pluginName);
1088
+ if (!plugin) return [null];
1102
1089
  this.events.emit("plugins:hook:progress:start", {
1103
1090
  hookName,
1104
- plugins
1091
+ plugins: [plugin]
1092
+ });
1093
+ const result = await this.#execute({
1094
+ strategy: "hookFirst",
1095
+ hookName,
1096
+ parameters,
1097
+ plugin
1105
1098
  });
1106
- const items = [];
1107
- for (const plugin of plugins) {
1108
- const result = await this.#execute({
1109
- strategy: "hookFirst",
1110
- hookName,
1111
- parameters,
1112
- plugin
1113
- });
1114
- if (result !== void 0 && result !== null) items.push(result);
1115
- }
1116
1099
  this.events.emit("plugins:hook:progress:end", { hookName });
1117
- return items;
1100
+ return [result];
1118
1101
  }
1119
1102
  /**
1120
1103
  * Run a specific hookName for plugin x.
1121
1104
  */
1122
1105
  hookForPluginSync({ pluginName, hookName, parameters }) {
1123
- return this.getPluginsByName(hookName, pluginName).map((plugin) => {
1124
- return this.#executeSync({
1125
- strategy: "hookFirst",
1126
- hookName,
1127
- parameters,
1128
- plugin
1129
- });
1130
- }).filter((x) => x !== null);
1106
+ const plugin = this.plugins.get(pluginName);
1107
+ if (!plugin) return null;
1108
+ const result = this.#executeSync({
1109
+ strategy: "hookFirst",
1110
+ hookName,
1111
+ parameters,
1112
+ plugin
1113
+ });
1114
+ return result !== null ? [result] : [];
1131
1115
  }
1132
1116
  /**
1133
1117
  * Returns the first non-null result.
1134
1118
  */
1135
1119
  async hookFirst({ hookName, parameters, skipped }) {
1136
- const plugins = this.#getSortedPlugins(hookName).filter((plugin) => {
1137
- return skipped ? !skipped.has(plugin) : true;
1138
- });
1120
+ const plugins = [];
1121
+ for (const plugin of this.plugins.values()) if (hookName in plugin && (skipped ? !skipped.has(plugin) : true)) plugins.push(plugin);
1139
1122
  this.events.emit("plugins:hook:progress:start", {
1140
1123
  hookName,
1141
1124
  plugins
@@ -1162,10 +1145,9 @@ var PluginDriver = class {
1162
1145
  */
1163
1146
  hookFirstSync({ hookName, parameters, skipped }) {
1164
1147
  let parseResult = null;
1165
- const plugins = this.#getSortedPlugins(hookName).filter((plugin) => {
1166
- return skipped ? !skipped.has(plugin) : true;
1167
- });
1168
- for (const plugin of plugins) {
1148
+ for (const plugin of this.plugins.values()) {
1149
+ if (!(hookName in plugin)) continue;
1150
+ if (skipped?.has(plugin)) continue;
1169
1151
  parseResult = {
1170
1152
  result: this.#executeSync({
1171
1153
  strategy: "hookFirst",
@@ -1175,7 +1157,7 @@ var PluginDriver = class {
1175
1157
  }),
1176
1158
  plugin
1177
1159
  };
1178
- if (parseResult?.result != null) break;
1160
+ if (parseResult.result != null) break;
1179
1161
  }
1180
1162
  return parseResult;
1181
1163
  }
@@ -1183,7 +1165,8 @@ var PluginDriver = class {
1183
1165
  * Runs all plugins in parallel based on `this.plugin` order and `pre`/`post` settings.
1184
1166
  */
1185
1167
  async hookParallel({ hookName, parameters }) {
1186
- const plugins = this.#getSortedPlugins(hookName);
1168
+ const plugins = [];
1169
+ for (const plugin of this.plugins.values()) if (hookName in plugin) plugins.push(plugin);
1187
1170
  this.events.emit("plugins:hook:progress:start", {
1188
1171
  hookName,
1189
1172
  plugins
@@ -1202,7 +1185,7 @@ var PluginDriver = class {
1202
1185
  }), this.options.concurrency);
1203
1186
  results.forEach((result, index) => {
1204
1187
  if (isPromiseRejectedResult(result)) {
1205
- const plugin = this.#getSortedPlugins(hookName)[index];
1188
+ const plugin = plugins[index];
1206
1189
  if (plugin) {
1207
1190
  const startTime = pluginStartTimes.get(plugin) ?? performance.now();
1208
1191
  this.events.emit("error", result.reason, {
@@ -1225,7 +1208,8 @@ var PluginDriver = class {
1225
1208
  * Chains plugins
1226
1209
  */
1227
1210
  async hookSeq({ hookName, parameters }) {
1228
- const plugins = this.#getSortedPlugins(hookName);
1211
+ const plugins = [];
1212
+ for (const plugin of this.plugins.values()) if (hookName in plugin) plugins.push(plugin);
1229
1213
  this.events.emit("plugins:hook:progress:start", {
1230
1214
  hookName,
1231
1215
  plugins
@@ -1240,33 +1224,8 @@ var PluginDriver = class {
1240
1224
  }));
1241
1225
  this.events.emit("plugins:hook:progress:end", { hookName });
1242
1226
  }
1243
- #getSortedPlugins(hookName) {
1244
- const plugins = [...this.#plugins];
1245
- if (hookName) return plugins.filter((plugin) => hookName in plugin);
1246
- return plugins.map((plugin) => {
1247
- if (plugin.pre) {
1248
- let missingPlugins = plugin.pre.filter((pluginName) => !plugins.find((pluginToFind) => pluginToFind.name === pluginName));
1249
- if (missingPlugins.includes("plugin-oas") && this.adapter) missingPlugins = missingPlugins.filter((pluginName) => pluginName !== "plugin-oas");
1250
- if (missingPlugins.length > 0) throw new ValidationPluginError(`The plugin '${plugin.name}' has a pre set that references missing plugins for '${missingPlugins.join(", ")}'`);
1251
- }
1252
- return plugin;
1253
- }).sort((a, b) => {
1254
- if (b.pre?.includes(a.name)) return 1;
1255
- if (b.post?.includes(a.name)) return -1;
1256
- return 0;
1257
- });
1258
- }
1259
- getPluginByName(pluginName) {
1260
- return [...this.#plugins].find((item) => item.name === pluginName);
1261
- }
1262
- getPluginsByName(hookName, pluginName) {
1263
- const plugins = [...this.plugins];
1264
- const pluginByPluginName = plugins.filter((plugin) => hookName in plugin).filter((item) => item.name === pluginName);
1265
- if (!pluginByPluginName?.length) {
1266
- const corePlugin = plugins.find((plugin) => plugin.name === "core" && hookName in plugin);
1267
- return corePlugin ? [corePlugin] : [];
1268
- }
1269
- return pluginByPluginName;
1227
+ getPlugin(pluginName) {
1228
+ return this.plugins.get(pluginName);
1270
1229
  }
1271
1230
  /**
1272
1231
  * Run an async plugin hook and return the result.
@@ -1354,16 +1313,6 @@ var PluginDriver = class {
1354
1313
  return null;
1355
1314
  }
1356
1315
  }
1357
- #parse(plugin) {
1358
- const usedPluginNames = this.#usedPluginNames;
1359
- setUniqueName(plugin.name, usedPluginNames);
1360
- const usageCount = usedPluginNames[plugin.name];
1361
- if (usageCount && usageCount > 1) throw new ValidationPluginError(`Duplicate plugin "${plugin.name}" detected. Each plugin can only be used once. Use a different configuration instead of adding multiple instances of the same plugin.`);
1362
- return {
1363
- install() {},
1364
- ...plugin
1365
- };
1366
- }
1367
1316
  };
1368
1317
  //#endregion
1369
1318
  //#region src/createStorage.ts
@@ -1463,7 +1412,7 @@ const fsStorage = createStorage(() => ({
1463
1412
  }));
1464
1413
  //#endregion
1465
1414
  //#region package.json
1466
- var version$1 = "5.0.0-alpha.21";
1415
+ var version$1 = "5.0.0-alpha.23";
1467
1416
  //#endregion
1468
1417
  //#region src/utils/diagnostics.ts
1469
1418
  /**
@@ -1659,7 +1608,7 @@ async function safeBuild(options, overrides) {
1659
1608
  const pluginTimings = /* @__PURE__ */ new Map();
1660
1609
  const config = driver.config;
1661
1610
  try {
1662
- for (const plugin of driver.plugins) {
1611
+ for (const plugin of driver.plugins.values()) {
1663
1612
  const context = driver.getContext(plugin);
1664
1613
  const hrStart = process.hrtime();
1665
1614
  const installer = plugin.install.bind(context);
@@ -1769,7 +1718,7 @@ async function safeBuild(options, overrides) {
1769
1718
  }
1770
1719
  function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }) {
1771
1720
  const pluginNameMap = /* @__PURE__ */ new Map();
1772
- for (const plugin of driver.plugins) pluginNameMap.set(plugin.name, plugin);
1721
+ for (const plugin of driver.plugins.values()) pluginNameMap.set(plugin.name, plugin);
1773
1722
  return barrelFiles.flatMap((file) => {
1774
1723
  const containsOnlyTypes = file.sources?.every((source) => source.isTypeOnly);
1775
1724
  return (file.sources ?? []).flatMap((source) => {
@@ -1851,26 +1800,6 @@ function createPlugin(build) {
1851
1800
  return (options) => build(options ?? {});
1852
1801
  }
1853
1802
  //#endregion
1854
- //#region src/defineBuilder.ts
1855
- /**
1856
- * Defines a builder for a plugin — a named collection of schema-building helpers that
1857
- * can be exported alongside the plugin and imported by other plugins or generators.
1858
- *
1859
- * @example
1860
- * export const builder = defineBuilder<PluginTs>(() => ({
1861
- * name: 'default',
1862
- * buildParamsSchema({ params, node, resolver }) {
1863
- * return createSchema({ type: 'object', properties: [] })
1864
- * },
1865
- * buildDataSchemaNode({ node, resolver }) {
1866
- * return createSchema({ type: 'object', properties: [] })
1867
- * },
1868
- * }))
1869
- */
1870
- function defineBuilder(build) {
1871
- return build();
1872
- }
1873
- //#endregion
1874
1803
  //#region src/defineGenerator.ts
1875
1804
  function defineGenerator(generator) {
1876
1805
  if (generator.type === "react") return {
@@ -1918,34 +1847,6 @@ function defineLogger(logger) {
1918
1847
  return logger;
1919
1848
  }
1920
1849
  //#endregion
1921
- //#region src/definePreset.ts
1922
- /**
1923
- * Creates a typed preset object that bundles a name, resolvers, optional
1924
- * transformers, and optional generators — the building block for composable plugin presets.
1925
- *
1926
- * @example
1927
- * import { definePreset } from '@kubb/core'
1928
- * import { resolverTsLegacy } from '@kubb/plugin-ts'
1929
- *
1930
- * export const myPreset = definePreset('myPreset', { resolvers: [resolverTsLegacy] })
1931
- *
1932
- * @example
1933
- * // With custom transformers
1934
- * export const myPreset = definePreset('myPreset', { resolvers: [resolverTsLegacy], transformers: [myTransformer] })
1935
- *
1936
- * @example
1937
- * // With generators
1938
- * export const myPreset = definePreset('myPreset', { resolvers: [resolverTsLegacy], generators: [typeGeneratorLegacy] })
1939
- */
1940
- function definePreset(name, { resolvers, transformers, generators }) {
1941
- return {
1942
- name,
1943
- resolvers,
1944
- transformers,
1945
- generators
1946
- };
1947
- }
1948
- //#endregion
1949
1850
  //#region src/definePresets.ts
1950
1851
  /**
1951
1852
  * Creates a typed presets registry object — a named collection of {@link Preset} entries.
@@ -2092,19 +1993,13 @@ function defaultResolveOptions(node, { options, exclude = [], include, override
2092
1993
  */
2093
1994
  function defaultResolvePath({ baseName, pathMode, tag, path: groupPath }, { root, output, group }) {
2094
1995
  if ((pathMode ?? getMode(path.resolve(root, output.path))) === "single") return path.resolve(root, output.path);
2095
- if (group && (groupPath || tag)) {
2096
- const groupName = group.name ? group.name : (ctx) => {
2097
- if (group.type === "path") return `${ctx.group.split("/")[1]}`;
2098
- return `${camelCase(ctx.group)}Controller`;
2099
- };
2100
- return path.resolve(root, output.path, groupName({ group: group.type === "path" ? groupPath : tag }), baseName);
2101
- }
1996
+ if (group && (groupPath || tag)) return path.resolve(root, output.path, group.name({ group: group.type === "path" ? groupPath : tag }), baseName);
2102
1997
  return path.resolve(root, output.path, baseName);
2103
1998
  }
2104
1999
  /**
2105
2000
  * Default file resolver used by `defineResolver`.
2106
2001
  *
2107
- * Resolves a `KubbFile.File` by combining name resolution (`resolver.default`) with
2002
+ * Resolves a `FabricFile.File` by combining name resolution (`resolver.default`) with
2108
2003
  * path resolution (`resolver.resolvePath`). The resolved file always has empty
2109
2004
  * `sources`, `imports`, and `exports` arrays — consumers populate those separately.
2110
2005
  *
@@ -2240,7 +2135,7 @@ function defaultResolveFooter(node, { output }) {
2240
2135
  * - `default` — name casing strategy (camelCase / PascalCase)
2241
2136
  * - `resolveOptions` — include/exclude/override filtering
2242
2137
  * - `resolvePath` — output path computation
2243
- * - `resolveFile` — full `KubbFile.File` construction
2138
+ * - `resolveFile` — full `FabricFile.File` construction
2244
2139
  *
2245
2140
  * Methods in the builder have access to `this` (the full resolver object), so they
2246
2141
  * can call other resolver methods without circular imports.
@@ -2298,19 +2193,15 @@ async function renderOperations(nodes, options) {
2298
2193
  const { config, fabric, plugin, Component, driver, adapter } = options;
2299
2194
  if (!Component) return;
2300
2195
  const fabricChild = createReactFabric();
2301
- await fabricChild.render(/* @__PURE__ */ jsx(Fabric, {
2302
- meta: {
2303
- plugin,
2304
- driver
2305
- },
2306
- children: /* @__PURE__ */ jsx(Component, {
2307
- config,
2308
- plugin,
2309
- adapter,
2310
- nodes,
2311
- options: options.options
2312
- })
2313
- }));
2196
+ await fabricChild.render(/* @__PURE__ */ jsx(Fabric, { children: /* @__PURE__ */ jsx(Component, {
2197
+ config,
2198
+ plugin,
2199
+ driver,
2200
+ adapter,
2201
+ nodes,
2202
+ options: options.options,
2203
+ resolver: options.resolver
2204
+ }) }));
2314
2205
  fabric.context.fileManager.upsert(...fabricChild.files);
2315
2206
  fabricChild.unmount();
2316
2207
  }
@@ -2321,19 +2212,15 @@ async function renderOperation(node, options) {
2321
2212
  const { config, fabric, plugin, Component, adapter, driver } = options;
2322
2213
  if (!Component) return;
2323
2214
  const fabricChild = createReactFabric();
2324
- await fabricChild.render(/* @__PURE__ */ jsx(Fabric, {
2325
- meta: {
2326
- plugin,
2327
- driver
2328
- },
2329
- children: /* @__PURE__ */ jsx(Component, {
2330
- config,
2331
- plugin,
2332
- adapter,
2333
- node,
2334
- options: options.options
2335
- })
2336
- }));
2215
+ await fabricChild.render(/* @__PURE__ */ jsx(Fabric, { children: /* @__PURE__ */ jsx(Component, {
2216
+ config,
2217
+ plugin,
2218
+ driver,
2219
+ adapter,
2220
+ node,
2221
+ options: options.options,
2222
+ resolver: options.resolver
2223
+ }) }));
2337
2224
  fabric.context.fileManager.upsert(...fabricChild.files);
2338
2225
  fabricChild.unmount();
2339
2226
  }
@@ -2344,19 +2231,15 @@ async function renderSchema(node, options) {
2344
2231
  const { config, fabric, plugin, Component, adapter, driver } = options;
2345
2232
  if (!Component) return;
2346
2233
  const fabricChild = createReactFabric();
2347
- await fabricChild.render(/* @__PURE__ */ jsx(Fabric, {
2348
- meta: {
2349
- plugin,
2350
- driver
2351
- },
2352
- children: /* @__PURE__ */ jsx(Component, {
2353
- config,
2354
- plugin,
2355
- adapter,
2356
- node,
2357
- options: options.options
2358
- })
2359
- }));
2234
+ await fabricChild.render(/* @__PURE__ */ jsx(Fabric, { children: /* @__PURE__ */ jsx(Component, {
2235
+ config,
2236
+ plugin,
2237
+ driver,
2238
+ adapter,
2239
+ node,
2240
+ options: options.options,
2241
+ resolver: options.resolver
2242
+ }) }));
2360
2243
  fabric.context.fileManager.upsert(...fabricChild.files);
2361
2244
  fabricChild.unmount();
2362
2245
  }
@@ -2527,7 +2410,7 @@ async function detectFormatter() {
2527
2410
  //#region src/utils/TreeNode.ts
2528
2411
  /**
2529
2412
  * Tree structure used to build per-directory barrel (`index.ts`) files from a
2530
- * flat list of generated {@link KubbFile.File} entries.
2413
+ * flat list of generated {@link FabricFile.File} entries.
2531
2414
  *
2532
2415
  * Each node represents either a directory or a file within the output tree.
2533
2416
  * Use {@link TreeNode.build} to construct a root node from a file list, then
@@ -2569,24 +2452,39 @@ var TreeNode = class TreeNode {
2569
2452
  this.#cachedLeaves = leaves;
2570
2453
  return leaves;
2571
2454
  }
2455
+ /**
2456
+ * Visits this node and every descendant in depth-first order.
2457
+ */
2572
2458
  forEach(callback) {
2573
2459
  if (typeof callback !== "function") throw new TypeError("forEach() callback must be a function");
2574
2460
  callback(this);
2575
2461
  for (const child of this.children) child.forEach(callback);
2576
2462
  return this;
2577
2463
  }
2464
+ /**
2465
+ * Finds the first leaf that satisfies `predicate`, or `undefined` when none match.
2466
+ */
2578
2467
  findDeep(predicate) {
2579
2468
  if (typeof predicate !== "function") throw new TypeError("find() predicate must be a function");
2580
2469
  return this.leaves.find(predicate);
2581
2470
  }
2471
+ /**
2472
+ * Calls `callback` for every leaf of this node.
2473
+ */
2582
2474
  forEachDeep(callback) {
2583
2475
  if (typeof callback !== "function") throw new TypeError("forEach() callback must be a function");
2584
2476
  this.leaves.forEach(callback);
2585
2477
  }
2478
+ /**
2479
+ * Returns all leaves that satisfy `callback`.
2480
+ */
2586
2481
  filterDeep(callback) {
2587
2482
  if (typeof callback !== "function") throw new TypeError("filter() callback must be a function");
2588
2483
  return this.leaves.filter(callback);
2589
2484
  }
2485
+ /**
2486
+ * Maps every leaf through `callback` and returns the resulting array.
2487
+ */
2590
2488
  mapDeep(callback) {
2591
2489
  if (typeof callback !== "function") throw new TypeError("map() callback must be a function");
2592
2490
  return this.leaves.map(callback);
@@ -2754,12 +2652,23 @@ async function getBarrelFiles(files, { type, meta = {}, root, output }) {
2754
2652
  */
2755
2653
  async function getConfigs(config, args) {
2756
2654
  const resolved = await (typeof config === "function" ? config(args) : config);
2757
- return (Array.isArray(resolved) ? resolved : [resolved]).map((item) => ({ ...item }));
2655
+ return (Array.isArray(resolved) ? resolved : [resolved]).map((item) => ({
2656
+ plugins: [],
2657
+ ...item
2658
+ }));
2758
2659
  }
2759
2660
  //#endregion
2760
2661
  //#region src/utils/mergeResolvers.ts
2761
2662
  /**
2762
- * Merges an array of resolvers into a single resolver. Later entries override earlier ones (last wins).
2663
+ * Merges an ordered list of resolvers into a single resolver by shallow-merging each entry left to right.
2664
+ *
2665
+ * Later entries win when keys conflict, so the last resolver in the list takes highest precedence.
2666
+ *
2667
+ * @example
2668
+ * ```ts
2669
+ * const resolver = mergeResolvers(resolverTs, resolverTsLegacy)
2670
+ * // resolverTsLegacy methods override resolverTs where they overlap
2671
+ * ```
2763
2672
  */
2764
2673
  function mergeResolvers(...resolvers) {
2765
2674
  return resolvers.reduce((acc, curr) => ({
@@ -2778,7 +2687,7 @@ function mergeResolvers(...resolvers) {
2778
2687
  * - Combines preset generators with user-supplied generators; falls back to the `default` preset's generators when neither provides any.
2779
2688
  */
2780
2689
  function getPreset(params) {
2781
- const { preset: presetName, presets, resolvers, transformers: userTransformers, generators: userGenerators } = params;
2690
+ const { preset: presetName, presets, resolvers = [], transformers: userTransformers = [], generators: userGenerators = [] } = params;
2782
2691
  const [defaultResolver, ...userResolvers] = resolvers;
2783
2692
  const preset = presets[presetName];
2784
2693
  const resolver = mergeResolvers(mergeResolvers(defaultResolver, ...preset?.resolvers ?? []), ...userResolvers ?? []);
@@ -2875,6 +2784,6 @@ function satisfiesDependency(dependency, version, cwd) {
2875
2784
  return satisfies(semVer, version);
2876
2785
  }
2877
2786
  //#endregion
2878
- export { AsyncEventEmitter, FunctionParams, PluginDriver, URLPath, build, build as default, buildDefaultBanner, createAdapter, createPlugin, createStorage, defaultResolveBanner, defaultResolveFile, defaultResolveFooter, defaultResolveOptions, defaultResolvePath, defineBuilder, defineConfig, defineGenerator, defineLogger, definePreset, definePresets, definePrinter, defineResolver, detectFormatter, detectLinter, formatters, fsStorage, getBarrelFiles, getConfigs, getMode, getPreset, isInputPath, linters, logLevel, memoryStorage, mergeResolvers, renderOperation, renderOperations, renderSchema, safeBuild, satisfiesDependency, setup };
2787
+ export { AsyncEventEmitter, FunctionParams, PluginDriver, URLPath, build, build as default, buildDefaultBanner, createAdapter, createPlugin, createStorage, defaultResolveBanner, defaultResolveFile, defaultResolveFooter, defaultResolveOptions, defaultResolvePath, defineConfig, defineGenerator, defineLogger, definePresets, definePrinter, defineResolver, detectFormatter, detectLinter, formatters, fsStorage, getBarrelFiles, getConfigs, getMode, getPreset, isInputPath, linters, logLevel, memoryStorage, mergeResolvers, renderOperation, renderOperations, renderSchema, safeBuild, satisfiesDependency, setup };
2879
2788
 
2880
2789
  //# sourceMappingURL=index.js.map