@kubb/core 4.36.1 → 5.0.0-alpha.10

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 (47) hide show
  1. package/dist/{types-D30QAz2y.d.ts → PluginDriver-BkFepPdm.d.ts} +354 -291
  2. package/dist/hooks.cjs +85 -8
  3. package/dist/hooks.cjs.map +1 -1
  4. package/dist/hooks.d.ts +66 -4
  5. package/dist/hooks.js +83 -8
  6. package/dist/hooks.js.map +1 -1
  7. package/dist/index.cjs +346 -315
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.ts +91 -77
  10. package/dist/index.js +338 -305
  11. package/dist/index.js.map +1 -1
  12. package/package.json +7 -7
  13. package/src/Kubb.ts +27 -55
  14. package/src/{PluginManager.ts → PluginDriver.ts} +69 -82
  15. package/src/build.ts +32 -33
  16. package/src/constants.ts +1 -1
  17. package/src/createAdapter.ts +25 -0
  18. package/src/createPlugin.ts +28 -0
  19. package/src/createStorage.ts +58 -0
  20. package/src/defineGenerator.ts +134 -0
  21. package/src/defineLogger.ts +13 -3
  22. package/src/defineResolver.ts +131 -0
  23. package/src/hooks/index.ts +2 -1
  24. package/src/hooks/useKubb.ts +143 -0
  25. package/src/hooks/useMode.ts +5 -2
  26. package/src/hooks/usePlugin.ts +5 -2
  27. package/src/hooks/usePluginDriver.ts +11 -0
  28. package/src/index.ts +7 -7
  29. package/src/storages/fsStorage.ts +2 -2
  30. package/src/storages/memoryStorage.ts +2 -2
  31. package/src/types.ts +94 -48
  32. package/src/utils/FunctionParams.ts +2 -2
  33. package/src/utils/TreeNode.ts +1 -1
  34. package/src/utils/formatters.ts +1 -1
  35. package/src/utils/getBarrelFiles.ts +73 -11
  36. package/src/utils/getConfigs.ts +3 -21
  37. package/src/utils/linters.ts +1 -1
  38. package/src/utils/packageJSON.ts +61 -0
  39. package/src/BarrelManager.ts +0 -74
  40. package/src/PackageManager.ts +0 -180
  41. package/src/PromiseManager.ts +0 -40
  42. package/src/defineAdapter.ts +0 -22
  43. package/src/definePlugin.ts +0 -12
  44. package/src/defineStorage.ts +0 -56
  45. package/src/errors.ts +0 -1
  46. package/src/hooks/usePluginManager.ts +0 -8
  47. package/src/utils/getPlugins.ts +0 -23
package/dist/index.js CHANGED
@@ -1,11 +1,10 @@
1
1
  import "./chunk--u3MIqq1.js";
2
- import mod from "node:module";
2
+ import { definePrinter, isOperationNode, isSchemaNode } from "@kubb/ast";
3
+ import path, { basename, dirname, extname, join, posix, relative, resolve } from "node:path";
3
4
  import { EventEmitter } from "node:events";
4
5
  import { parseArgs, styleText } from "node:util";
5
6
  import { readFileSync } from "node:fs";
6
7
  import { access, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
7
- import path, { dirname, join, posix, relative, resolve } from "node:path";
8
- import { definePrinter } from "@kubb/ast";
9
8
  import { createFabric } from "@kubb/react-fabric";
10
9
  import { typescriptParser } from "@kubb/react-fabric/parsers";
11
10
  import { fsPlugin } from "@kubb/react-fabric/plugins";
@@ -13,11 +12,9 @@ import { performance } from "node:perf_hooks";
13
12
  import { deflateSync } from "fflate";
14
13
  import { x } from "tinyexec";
15
14
  import { version } from "node:process";
16
- import os from "node:os";
17
- import { pathToFileURL } from "node:url";
15
+ import { sortBy } from "remeda";
18
16
  import * as pkg from "empathic/package";
19
17
  import { coerce, satisfies } from "semver";
20
- import { sortBy } from "remeda";
21
18
  //#region ../../internals/utils/dist/index.js
22
19
  /** Thrown when a plugin's configuration or input fails validation. */
23
20
  var ValidationPluginError = class extends Error {};
@@ -134,6 +131,21 @@ function camelCase(text, { isFile, prefix = "", suffix = "" } = {}) {
134
131
  } : {}));
135
132
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
136
133
  }
134
+ /**
135
+ * Converts `text` to PascalCase.
136
+ * When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.
137
+ *
138
+ * @example
139
+ * pascalCase('hello-world') // 'HelloWorld'
140
+ * pascalCase('pet.petId', { isFile: true }) // 'pet/PetId'
141
+ */
142
+ function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
143
+ if (isFile) return applyToFileParts(text, (part, isLast) => isLast ? pascalCase(part, {
144
+ prefix,
145
+ suffix
146
+ }) : camelCase(part));
147
+ return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
148
+ }
137
149
  /** Returns a `CLIAdapter` with type inference. Pass a different adapter to `createCLI` to swap the CLI engine. */
138
150
  function defineCLIAdapter(adapter) {
139
151
  return adapter;
@@ -383,14 +395,6 @@ async function exists(path) {
383
395
  if (typeof Bun !== "undefined") return Bun.file(path).exists();
384
396
  return access(path).then(() => true, () => false);
385
397
  }
386
- /**
387
- * Reads the file at `path` as a UTF-8 string.
388
- * Uses `Bun.file().text()` when running under Bun, `fs.readFile` otherwise.
389
- */
390
- async function read(path) {
391
- if (typeof Bun !== "undefined") return Bun.file(path).text();
392
- return readFile(path, { encoding: "utf8" });
393
- }
394
398
  /** Synchronous counterpart of `read`. */
395
399
  function readSync(path) {
396
400
  return readFileSync(path, { encoding: "utf8" });
@@ -445,11 +449,15 @@ function setUniqueName(originalName, data) {
445
449
  data[originalName] = 1;
446
450
  return originalName;
447
451
  }
452
+ /** Type guard for a rejected `Promise.allSettled` result with a typed `reason`. */
453
+ function isPromiseRejectedResult(result) {
454
+ return result.status === "rejected";
455
+ }
448
456
  /**
449
457
  * JavaScript and Java reserved words.
450
458
  * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
451
459
  */
452
- const reservedWords = [
460
+ const reservedWords = new Set([
453
461
  "abstract",
454
462
  "arguments",
455
463
  "boolean",
@@ -531,14 +539,14 @@ const reservedWords = [
531
539
  "toString",
532
540
  "undefined",
533
541
  "valueOf"
534
- ];
542
+ ]);
535
543
  /**
536
544
  * Prefixes a word with `_` when it is a reserved JavaScript/Java identifier
537
545
  * or starts with a digit.
538
546
  */
539
547
  function transformReservedWord(word) {
540
548
  const firstChar = word.charCodeAt(0);
541
- if (word && (reservedWords.includes(word) || firstChar >= 48 && firstChar <= 57)) return `_${word}`;
549
+ if (word && (reservedWords.has(word) || firstChar >= 48 && firstChar <= 57)) return `_${word}`;
542
550
  return word;
543
551
  }
544
552
  /**
@@ -670,7 +678,6 @@ const DEFAULT_STUDIO_URL = "https://studio.kubb.dev";
670
678
  const BARREL_FILENAME = "index.ts";
671
679
  const DEFAULT_BANNER = "simple";
672
680
  const DEFAULT_EXTENSION = { ".ts": ".ts" };
673
- const PATH_SEPARATORS = ["/", "\\"];
674
681
  const logLevel = {
675
682
  silent: Number.NEGATIVE_INFINITY,
676
683
  error: 0,
@@ -931,29 +938,13 @@ function hookParallel(promises, concurrency = Number.POSITIVE_INFINITY) {
931
938
  return Promise.allSettled(tasks);
932
939
  }
933
940
  //#endregion
934
- //#region src/PromiseManager.ts
935
- var PromiseManager = class {
936
- #options = {};
937
- constructor(options = {}) {
938
- this.#options = options;
939
- }
940
- run(strategy, promises, { concurrency = Number.POSITIVE_INFINITY } = {}) {
941
- if (strategy === "seq") return hookSeq(promises);
942
- if (strategy === "first") return hookFirst(promises, this.#options.nullCheck);
943
- if (strategy === "parallel") return hookParallel(promises, concurrency);
944
- throw new Error(`${strategy} not implemented`);
945
- }
946
- };
947
- function isPromiseRejectedResult(result) {
948
- return result.status === "rejected";
949
- }
950
- //#endregion
951
- //#region src/PluginManager.ts
941
+ //#region src/PluginDriver.ts
952
942
  function getMode(fileOrFolder) {
953
943
  if (!fileOrFolder) return "split";
954
- return path.extname(fileOrFolder) ? "single" : "split";
944
+ return extname(fileOrFolder) ? "single" : "split";
955
945
  }
956
- var PluginManager = class {
946
+ const hookFirstNullCheck = (state) => !!state?.result;
947
+ var PluginDriver = class {
957
948
  config;
958
949
  options;
959
950
  /**
@@ -961,14 +952,13 @@ var PluginManager = class {
961
952
  * the build pipeline after the adapter's `parse()` resolves.
962
953
  */
963
954
  rootNode = void 0;
955
+ adapter = void 0;
964
956
  #studioIsOpen = false;
965
957
  #plugins = /* @__PURE__ */ new Set();
966
958
  #usedPluginNames = {};
967
- #promiseManager;
968
959
  constructor(config, options) {
969
960
  this.config = config;
970
961
  this.options = options;
971
- this.#promiseManager = new PromiseManager({ nullCheck: (state) => !!state?.result });
972
962
  [...config.plugins || []].forEach((plugin) => {
973
963
  const parsedPlugin = this.#parse(plugin);
974
964
  this.#plugins.add(parsedPlugin);
@@ -979,14 +969,14 @@ var PluginManager = class {
979
969
  }
980
970
  getContext(plugin) {
981
971
  const plugins = [...this.#plugins];
982
- const pluginManager = this;
972
+ const driver = this;
983
973
  const baseContext = {
984
974
  fabric: this.options.fabric,
985
975
  config: this.config,
986
976
  plugin,
987
977
  events: this.options.events,
988
- pluginManager: this,
989
- mode: getMode(path.resolve(this.config.root, this.config.output.path)),
978
+ driver: this,
979
+ mode: getMode(resolve(this.config.root, this.config.output.path)),
990
980
  addFile: async (...files) => {
991
981
  await this.options.fabric.addFile(...files);
992
982
  },
@@ -994,15 +984,18 @@ var PluginManager = class {
994
984
  await this.options.fabric.upsertFile(...files);
995
985
  },
996
986
  get rootNode() {
997
- return pluginManager.rootNode;
987
+ return driver.rootNode;
988
+ },
989
+ get adapter() {
990
+ return driver.adapter;
998
991
  },
999
992
  openInStudio(options) {
1000
- if (typeof pluginManager.config.devtools !== "object") throw new Error("Devtools must be an object");
1001
- if (!pluginManager.rootNode) throw new Error("RootNode is not defined, make sure you have set the parser in kubb.config.ts");
1002
- if (pluginManager.#studioIsOpen) return;
1003
- pluginManager.#studioIsOpen = true;
1004
- const studioUrl = pluginManager.config.devtools?.studioUrl ?? "https://studio.kubb.dev";
1005
- return openInStudio(pluginManager.rootNode, studioUrl, options);
993
+ if (!driver.config.devtools || driver.#studioIsOpen) return;
994
+ if (typeof driver.config.devtools !== "object") throw new Error("Devtools must be an object");
995
+ if (!driver.rootNode || !driver.adapter) throw new Error("adapter is not defined, make sure you have set the parser in kubb.config.ts");
996
+ driver.#studioIsOpen = true;
997
+ const studioUrl = driver.config.devtools?.studioUrl ?? "https://studio.kubb.dev";
998
+ return openInStudio(driver.rootNode, studioUrl, options);
1006
999
  }
1007
1000
  };
1008
1001
  const mergedExtras = {};
@@ -1018,29 +1011,32 @@ var PluginManager = class {
1018
1011
  get plugins() {
1019
1012
  return this.#getSortedPlugins();
1020
1013
  }
1021
- getFile({ name, mode, extname, pluginKey, options }) {
1022
- const baseName = `${name}${extname}`;
1014
+ getFile({ name, mode, extname, pluginName, options }) {
1015
+ const resolvedName = mode ? mode === "single" ? "" : this.resolveName({
1016
+ name,
1017
+ pluginName,
1018
+ type: "file"
1019
+ }) : name;
1023
1020
  const path = this.resolvePath({
1024
- baseName,
1021
+ baseName: `${resolvedName}${extname}`,
1025
1022
  mode,
1026
- pluginKey,
1023
+ pluginName,
1027
1024
  options
1028
1025
  });
1029
- if (!path) throw new Error(`Filepath should be defined for resolvedName "${name}" and pluginKey [${JSON.stringify(pluginKey)}]`);
1026
+ if (!path) throw new Error(`Filepath should be defined for resolvedName "${resolvedName}" and pluginName "${pluginName}"`);
1030
1027
  return {
1031
1028
  path,
1032
- baseName,
1033
- meta: { pluginKey },
1029
+ baseName: basename(path),
1030
+ meta: { pluginName },
1034
1031
  sources: [],
1035
1032
  imports: [],
1036
1033
  exports: []
1037
1034
  };
1038
1035
  }
1039
1036
  resolvePath = (params) => {
1040
- const root = path.resolve(this.config.root, this.config.output.path);
1041
- const defaultPath = path.resolve(root, params.baseName);
1042
- if (params.pluginKey) return this.hookForPluginSync({
1043
- pluginKey: params.pluginKey,
1037
+ const defaultPath = resolve(resolve(this.config.root, this.config.output.path), params.baseName);
1038
+ if (params.pluginName) return this.hookForPluginSync({
1039
+ pluginName: params.pluginName,
1044
1040
  hookName: "resolvePath",
1045
1041
  parameters: [
1046
1042
  params.baseName,
@@ -1058,9 +1054,9 @@ var PluginManager = class {
1058
1054
  })?.result || defaultPath;
1059
1055
  };
1060
1056
  resolveName = (params) => {
1061
- if (params.pluginKey) {
1057
+ if (params.pluginName) {
1062
1058
  const names = this.hookForPluginSync({
1063
- pluginKey: params.pluginKey,
1059
+ pluginName: params.pluginName,
1064
1060
  hookName: "resolveName",
1065
1061
  parameters: [params.name.trim(), params.type]
1066
1062
  });
@@ -1075,8 +1071,8 @@ var PluginManager = class {
1075
1071
  /**
1076
1072
  * Run a specific hookName for plugin x.
1077
1073
  */
1078
- async hookForPlugin({ pluginKey, hookName, parameters }) {
1079
- const plugins = this.getPluginsByKey(hookName, pluginKey);
1074
+ async hookForPlugin({ pluginName, hookName, parameters }) {
1075
+ const plugins = this.getPluginsByName(hookName, pluginName);
1080
1076
  this.events.emit("plugins:hook:progress:start", {
1081
1077
  hookName,
1082
1078
  plugins
@@ -1097,8 +1093,8 @@ var PluginManager = class {
1097
1093
  /**
1098
1094
  * Run a specific hookName for plugin x.
1099
1095
  */
1100
- hookForPluginSync({ pluginKey, hookName, parameters }) {
1101
- return this.getPluginsByKey(hookName, pluginKey).map((plugin) => {
1096
+ hookForPluginSync({ pluginName, hookName, parameters }) {
1097
+ return this.getPluginsByName(hookName, pluginName).map((plugin) => {
1102
1098
  return this.#executeSync({
1103
1099
  strategy: "hookFirst",
1104
1100
  hookName,
@@ -1118,7 +1114,7 @@ var PluginManager = class {
1118
1114
  hookName,
1119
1115
  plugins
1120
1116
  });
1121
- const promises = plugins.map((plugin) => {
1117
+ const result = await hookFirst(plugins.map((plugin) => {
1122
1118
  return async () => {
1123
1119
  const value = await this.#execute({
1124
1120
  strategy: "hookFirst",
@@ -1131,8 +1127,7 @@ var PluginManager = class {
1131
1127
  result: value
1132
1128
  });
1133
1129
  };
1134
- });
1135
- const result = await this.#promiseManager.run("first", promises);
1130
+ }), hookFirstNullCheck);
1136
1131
  this.events.emit("plugins:hook:progress:end", { hookName });
1137
1132
  return result;
1138
1133
  }
@@ -1168,7 +1163,7 @@ var PluginManager = class {
1168
1163
  plugins
1169
1164
  });
1170
1165
  const pluginStartTimes = /* @__PURE__ */ new Map();
1171
- const promises = plugins.map((plugin) => {
1166
+ const results = await hookParallel(plugins.map((plugin) => {
1172
1167
  return () => {
1173
1168
  pluginStartTimes.set(plugin, performance.now());
1174
1169
  return this.#execute({
@@ -1178,8 +1173,7 @@ var PluginManager = class {
1178
1173
  plugin
1179
1174
  });
1180
1175
  };
1181
- });
1182
- const results = await this.#promiseManager.run("parallel", promises, { concurrency: this.options.concurrency });
1176
+ }), this.options.concurrency);
1183
1177
  results.forEach((result, index) => {
1184
1178
  if (isPromiseRejectedResult(result)) {
1185
1179
  const plugin = this.#getSortedPlugins(hookName)[index];
@@ -1210,15 +1204,14 @@ var PluginManager = class {
1210
1204
  hookName,
1211
1205
  plugins
1212
1206
  });
1213
- const promises = plugins.map((plugin) => {
1207
+ await hookSeq(plugins.map((plugin) => {
1214
1208
  return () => this.#execute({
1215
1209
  strategy: "hookSeq",
1216
1210
  hookName,
1217
1211
  parameters,
1218
1212
  plugin
1219
1213
  });
1220
- });
1221
- await this.#promiseManager.run("seq", promises);
1214
+ }));
1222
1215
  this.events.emit("plugins:hook:progress:end", { hookName });
1223
1216
  }
1224
1217
  #getSortedPlugins(hookName) {
@@ -1226,7 +1219,8 @@ var PluginManager = class {
1226
1219
  if (hookName) return plugins.filter((plugin) => hookName in plugin);
1227
1220
  return plugins.map((plugin) => {
1228
1221
  if (plugin.pre) {
1229
- const missingPlugins = plugin.pre.filter((pluginName) => !plugins.find((pluginToFind) => pluginToFind.name === pluginName));
1222
+ let missingPlugins = plugin.pre.filter((pluginName) => !plugins.find((pluginToFind) => pluginToFind.name === pluginName));
1223
+ if (missingPlugins.includes("plugin-oas") && this.adapter) missingPlugins = missingPlugins.filter((pluginName) => pluginName !== "plugin-oas");
1230
1224
  if (missingPlugins.length > 0) throw new ValidationPluginError(`The plugin '${plugin.name}' has a pre set that references missing plugins for '${missingPlugins.join(", ")}'`);
1231
1225
  }
1232
1226
  return plugin;
@@ -1236,24 +1230,12 @@ var PluginManager = class {
1236
1230
  return 0;
1237
1231
  });
1238
1232
  }
1239
- getPluginByKey(pluginKey) {
1240
- const plugins = [...this.#plugins];
1241
- const [searchPluginName] = pluginKey;
1242
- return plugins.find((item) => {
1243
- const [name] = item.key;
1244
- return name === searchPluginName;
1245
- });
1233
+ getPluginByName(pluginName) {
1234
+ return [...this.#plugins].find((item) => item.name === pluginName);
1246
1235
  }
1247
- getPluginsByKey(hookName, pluginKey) {
1236
+ getPluginsByName(hookName, pluginName) {
1248
1237
  const plugins = [...this.plugins];
1249
- const [searchPluginName, searchIdentifier] = pluginKey;
1250
- const pluginByPluginName = plugins.filter((plugin) => hookName in plugin).filter((item) => {
1251
- const [name, identifier] = item.key;
1252
- const identifierCheck = identifier?.toString() === searchIdentifier?.toString();
1253
- const nameCheck = name === searchPluginName;
1254
- if (searchIdentifier) return identifierCheck && nameCheck;
1255
- return nameCheck;
1256
- });
1238
+ const pluginByPluginName = plugins.filter((plugin) => hookName in plugin).filter((item) => item.name === pluginName);
1257
1239
  if (!pluginByPluginName?.length) {
1258
1240
  const corePlugin = plugins.find((plugin) => plugin.name === "core" && hookName in plugin);
1259
1241
  return corePlugin ? [corePlugin] : [];
@@ -1350,28 +1332,20 @@ var PluginManager = class {
1350
1332
  const usedPluginNames = this.#usedPluginNames;
1351
1333
  setUniqueName(plugin.name, usedPluginNames);
1352
1334
  const usageCount = usedPluginNames[plugin.name];
1353
- if (usageCount && usageCount > 1) this.events.emit("warn", `Multiple instances of plugin "${plugin.name}" detected. This behavior is deprecated and will be removed in v5.`, `Plugin key: [${plugin.name}, ${usageCount}]`);
1335
+ 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.`);
1354
1336
  return {
1355
1337
  install() {},
1356
- ...plugin,
1357
- key: [plugin.name, usedPluginNames[plugin.name]].filter(Boolean)
1338
+ ...plugin
1358
1339
  };
1359
1340
  }
1360
1341
  };
1361
1342
  //#endregion
1362
- //#region src/defineStorage.ts
1343
+ //#region src/createStorage.ts
1363
1344
  /**
1364
- * Wraps a storage builder so the `options` argument is optional, following the
1365
- * same factory pattern as `definePlugin`, `defineLogger`, and `defineAdapter`.
1366
- *
1367
- * The builder receives the resolved options object and must return a
1368
- * `DefineStorage`-compatible object that includes a `name` string.
1345
+ * Creates a storage factory. Call the returned function with optional options to get the storage instance.
1369
1346
  *
1370
1347
  * @example
1371
- * ```ts
1372
- * import { defineStorage } from '@kubb/core'
1373
- *
1374
- * export const memoryStorage = defineStorage((_options) => {
1348
+ * export const memoryStorage = createStorage(() => {
1375
1349
  * const store = new Map<string, string>()
1376
1350
  * return {
1377
1351
  * name: 'memory',
@@ -1379,13 +1353,15 @@ var PluginManager = class {
1379
1353
  * async getItem(key) { return store.get(key) ?? null },
1380
1354
  * async setItem(key, value) { store.set(key, value) },
1381
1355
  * async removeItem(key) { store.delete(key) },
1382
- * async getKeys() { return [...store.keys()] },
1383
- * async clear() { store.clear() },
1356
+ * async getKeys(base) {
1357
+ * const keys = [...store.keys()]
1358
+ * return base ? keys.filter((k) => k.startsWith(base)) : keys
1359
+ * },
1360
+ * async clear(base) { if (!base) store.clear() },
1384
1361
  * }
1385
1362
  * })
1386
- * ```
1387
1363
  */
1388
- function defineStorage(build) {
1364
+ function createStorage(build) {
1389
1365
  return (options) => build(options ?? {});
1390
1366
  }
1391
1367
  //#endregion
@@ -1413,7 +1389,7 @@ function defineStorage(build) {
1413
1389
  * })
1414
1390
  * ```
1415
1391
  */
1416
- const fsStorage = defineStorage(() => ({
1392
+ const fsStorage = createStorage(() => ({
1417
1393
  name: "fs",
1418
1394
  async hasItem(key) {
1419
1395
  try {
@@ -1461,7 +1437,7 @@ const fsStorage = defineStorage(() => ({
1461
1437
  }));
1462
1438
  //#endregion
1463
1439
  //#region package.json
1464
- var version$1 = "4.36.1";
1440
+ var version$1 = "5.0.0-alpha.10";
1465
1441
  //#endregion
1466
1442
  //#region src/utils/diagnostics.ts
1467
1443
  /**
@@ -1575,7 +1551,7 @@ async function setup(options) {
1575
1551
  ` • Barrel type: ${definedConfig.output.barrelType || "none"}`
1576
1552
  ]
1577
1553
  });
1578
- const pluginManager = new PluginManager(definedConfig, {
1554
+ const pluginDriver = new PluginDriver(definedConfig, {
1579
1555
  fabric,
1580
1556
  events,
1581
1557
  concurrency: 15
@@ -1586,25 +1562,26 @@ async function setup(options) {
1586
1562
  date: /* @__PURE__ */ new Date(),
1587
1563
  logs: [`Running adapter: ${definedConfig.adapter.name}`]
1588
1564
  });
1589
- pluginManager.rootNode = await definedConfig.adapter.parse(source);
1565
+ pluginDriver.adapter = definedConfig.adapter;
1566
+ pluginDriver.rootNode = await definedConfig.adapter.parse(source);
1590
1567
  await events.emit("debug", {
1591
1568
  date: /* @__PURE__ */ new Date(),
1592
1569
  logs: [
1593
1570
  `✓ Adapter '${definedConfig.adapter.name}' resolved RootNode`,
1594
- ` • Schemas: ${pluginManager.rootNode.schemas.length}`,
1595
- ` • Operations: ${pluginManager.rootNode.operations.length}`
1571
+ ` • Schemas: ${pluginDriver.rootNode.schemas.length}`,
1572
+ ` • Operations: ${pluginDriver.rootNode.operations.length}`
1596
1573
  ]
1597
1574
  });
1598
1575
  }
1599
1576
  return {
1600
1577
  events,
1601
1578
  fabric,
1602
- pluginManager,
1579
+ driver: pluginDriver,
1603
1580
  sources
1604
1581
  };
1605
1582
  }
1606
1583
  async function build(options, overrides) {
1607
- const { fabric, files, pluginManager, failedPlugins, pluginTimings, error, sources } = await safeBuild(options, overrides);
1584
+ const { fabric, files, driver, failedPlugins, pluginTimings, error, sources } = await safeBuild(options, overrides);
1608
1585
  if (error) throw error;
1609
1586
  if (failedPlugins.size > 0) {
1610
1587
  const errors = [...failedPlugins].map(({ error }) => error);
@@ -1614,20 +1591,20 @@ async function build(options, overrides) {
1614
1591
  failedPlugins,
1615
1592
  fabric,
1616
1593
  files,
1617
- pluginManager,
1594
+ driver,
1618
1595
  pluginTimings,
1619
1596
  error: void 0,
1620
1597
  sources
1621
1598
  };
1622
1599
  }
1623
1600
  async function safeBuild(options, overrides) {
1624
- const { fabric, pluginManager, events, sources } = overrides ? overrides : await setup(options);
1601
+ const { fabric, driver, events, sources } = overrides ? overrides : await setup(options);
1625
1602
  const failedPlugins = /* @__PURE__ */ new Set();
1626
1603
  const pluginTimings = /* @__PURE__ */ new Map();
1627
- const config = pluginManager.config;
1604
+ const config = driver.config;
1628
1605
  try {
1629
- for (const plugin of pluginManager.plugins) {
1630
- const context = pluginManager.getContext(plugin);
1606
+ for (const plugin of driver.plugins) {
1607
+ const context = driver.getContext(plugin);
1631
1608
  const hrStart = process.hrtime();
1632
1609
  const installer = plugin.install.bind(context);
1633
1610
  try {
@@ -1635,7 +1612,7 @@ async function safeBuild(options, overrides) {
1635
1612
  await events.emit("plugin:start", plugin);
1636
1613
  await events.emit("debug", {
1637
1614
  date: timestamp,
1638
- logs: ["Installing plugin...", ` • Plugin Key: [${plugin.key.join(", ")}]`]
1615
+ logs: ["Installing plugin...", ` • Plugin Name: ${plugin.name}`]
1639
1616
  });
1640
1617
  await installer(context);
1641
1618
  const duration = getElapsedMs(hrStart);
@@ -1661,7 +1638,7 @@ async function safeBuild(options, overrides) {
1661
1638
  date: errorTimestamp,
1662
1639
  logs: [
1663
1640
  "✗ Plugin installation failed",
1664
- ` • Plugin Key: ${JSON.stringify(plugin.key)}`,
1641
+ ` • Plugin Name: ${plugin.name}`,
1665
1642
  ` • Error: ${error.constructor.name} - ${error.message}`,
1666
1643
  " • Stack Trace:",
1667
1644
  error.stack || "No stack trace available"
@@ -1700,7 +1677,7 @@ async function safeBuild(options, overrides) {
1700
1677
  rootDir,
1701
1678
  existingExports: new Set(existingBarrel?.exports?.flatMap((e) => Array.isArray(e.name) ? e.name : [e.name]).filter((n) => Boolean(n)) ?? []),
1702
1679
  config,
1703
- pluginManager
1680
+ driver
1704
1681
  }),
1705
1682
  sources: [],
1706
1683
  imports: [],
@@ -1718,7 +1695,7 @@ async function safeBuild(options, overrides) {
1718
1695
  failedPlugins,
1719
1696
  fabric,
1720
1697
  files,
1721
- pluginManager,
1698
+ driver,
1722
1699
  pluginTimings,
1723
1700
  sources
1724
1701
  };
@@ -1727,22 +1704,22 @@ async function safeBuild(options, overrides) {
1727
1704
  failedPlugins,
1728
1705
  fabric,
1729
1706
  files: [],
1730
- pluginManager,
1707
+ driver,
1731
1708
  pluginTimings,
1732
1709
  error,
1733
1710
  sources
1734
1711
  };
1735
1712
  }
1736
1713
  }
1737
- function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, pluginManager }) {
1738
- const pluginKeyMap = /* @__PURE__ */ new Map();
1739
- for (const plugin of pluginManager.plugins) pluginKeyMap.set(JSON.stringify(plugin.key), plugin);
1714
+ function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }) {
1715
+ const pluginNameMap = /* @__PURE__ */ new Map();
1716
+ for (const plugin of driver.plugins) pluginNameMap.set(plugin.name, plugin);
1740
1717
  return barrelFiles.flatMap((file) => {
1741
1718
  const containsOnlyTypes = file.sources?.every((source) => source.isTypeOnly);
1742
1719
  return (file.sources ?? []).flatMap((source) => {
1743
1720
  if (!file.path || !source.isIndexable) return [];
1744
1721
  const meta = file.meta;
1745
- const pluginOptions = (meta?.pluginKey ? pluginKeyMap.get(JSON.stringify(meta.pluginKey)) : void 0)?.options;
1722
+ const pluginOptions = (meta?.pluginName ? pluginNameMap.get(meta.pluginName) : void 0)?.options;
1746
1723
  if (!pluginOptions || pluginOptions.output?.barrelType === false) return [];
1747
1724
  const exportName = config.output.barrelType === "all" ? void 0 : source.name ? [source.name] : void 0;
1748
1725
  if (exportName?.some((n) => existingExports.has(n))) return [];
@@ -1773,121 +1750,178 @@ function inputToAdapterSource(config) {
1773
1750
  };
1774
1751
  }
1775
1752
  //#endregion
1776
- //#region src/defineAdapter.ts
1753
+ //#region src/createAdapter.ts
1777
1754
  /**
1778
- * Wraps an adapter builder to make the options parameter optional.
1755
+ * Creates an adapter factory. Call the returned function with optional options to get the adapter instance.
1779
1756
  *
1780
1757
  * @example
1781
- * ```ts
1782
- * export const adapterOas = defineAdapter<OasAdapter>((options) => {
1783
- * const { validate = true, dateType = 'string' } = options
1758
+ * export const myAdapter = createAdapter<MyAdapter>((options) => {
1784
1759
  * return {
1785
- * name: adapterOasName,
1786
- * options: { validate, dateType, ... },
1787
- * parse(source) { ... },
1760
+ * name: 'my-adapter',
1761
+ * options,
1762
+ * async parse(source) { ... },
1788
1763
  * }
1789
1764
  * })
1790
- * ```
1765
+ *
1766
+ * // instantiate
1767
+ * const adapter = myAdapter({ validate: true })
1791
1768
  */
1792
- function defineAdapter(build) {
1769
+ function createAdapter(build) {
1793
1770
  return (options) => build(options ?? {});
1794
1771
  }
1795
1772
  //#endregion
1773
+ //#region src/createPlugin.ts
1774
+ /**
1775
+ * Creates a plugin factory. Call the returned function with optional options to get the plugin instance.
1776
+ *
1777
+ * @example
1778
+ * export const myPlugin = createPlugin<MyPlugin>((options) => {
1779
+ * return {
1780
+ * name: 'my-plugin',
1781
+ * options,
1782
+ * resolvePath(baseName) { ... },
1783
+ * resolveName(name, type) { ... },
1784
+ * }
1785
+ * })
1786
+ *
1787
+ * // instantiate
1788
+ * const plugin = myPlugin({ output: { path: 'src/gen' } })
1789
+ */
1790
+ function createPlugin(build) {
1791
+ return (options) => build(options ?? {});
1792
+ }
1793
+ //#endregion
1794
+ //#region src/defineGenerator.ts
1795
+ function defineGenerator(generator) {
1796
+ if (generator.type === "react") return {
1797
+ version: "2",
1798
+ Operations() {
1799
+ return null;
1800
+ },
1801
+ Operation() {
1802
+ return null;
1803
+ },
1804
+ Schema() {
1805
+ return null;
1806
+ },
1807
+ ...generator
1808
+ };
1809
+ return {
1810
+ version: "2",
1811
+ async operations() {
1812
+ return [];
1813
+ },
1814
+ async operation() {
1815
+ return [];
1816
+ },
1817
+ async schema() {
1818
+ return [];
1819
+ },
1820
+ ...generator
1821
+ };
1822
+ }
1823
+ //#endregion
1796
1824
  //#region src/defineLogger.ts
1825
+ /**
1826
+ * Wraps a logger definition into a typed {@link Logger}.
1827
+ *
1828
+ * @example
1829
+ * export const myLogger = defineLogger({
1830
+ * name: 'my-logger',
1831
+ * install(context, options) {
1832
+ * context.on('info', (message) => console.log('ℹ', message))
1833
+ * context.on('error', (error) => console.error('✗', error.message))
1834
+ * },
1835
+ * })
1836
+ */
1797
1837
  function defineLogger(logger) {
1798
- return { ...logger };
1838
+ return logger;
1799
1839
  }
1800
1840
  //#endregion
1801
- //#region src/definePlugin.ts
1841
+ //#region src/defineResolver.ts
1802
1842
  /**
1803
- * Wraps a plugin builder to make the options parameter optional.
1843
+ * Checks if an operation matches a pattern for a given filter type (`tag`, `operationId`, `path`, `method`).
1804
1844
  */
1805
- function definePlugin(build) {
1806
- return (options) => build(options ?? {});
1845
+ function matchesOperationPattern(node, type, pattern) {
1846
+ switch (type) {
1847
+ case "tag": return node.tags.some((tag) => !!tag.match(pattern));
1848
+ case "operationId": return !!node.operationId.match(pattern);
1849
+ case "path": return !!node.path.match(pattern);
1850
+ case "method": return !!node.method.toLowerCase().match(pattern);
1851
+ default: return false;
1852
+ }
1807
1853
  }
1808
- //#endregion
1809
- //#region src/PackageManager.ts
1810
- var PackageManager = class PackageManager {
1811
- static #cache = {};
1812
- #cwd;
1813
- constructor(workspace) {
1814
- if (workspace) this.#cwd = workspace;
1815
- }
1816
- set workspace(workspace) {
1817
- this.#cwd = workspace;
1818
- }
1819
- get workspace() {
1820
- return this.#cwd;
1821
- }
1822
- normalizeDirectory(directory) {
1823
- const lastChar = directory[directory.length - 1];
1824
- if (lastChar && !PATH_SEPARATORS.includes(lastChar)) return `${directory}/`;
1825
- return directory;
1826
- }
1827
- getLocation(path) {
1828
- let location = path;
1829
- if (this.#cwd) location = mod.createRequire(this.normalizeDirectory(this.#cwd)).resolve(path);
1830
- return location;
1831
- }
1832
- async import(path) {
1833
- let location = this.getLocation(path);
1834
- if (os.platform() === "win32") location = pathToFileURL(location).href;
1835
- const module = await import(location);
1836
- return module?.default ?? module;
1837
- }
1838
- async getPackageJSON() {
1839
- const pkgPath = pkg.up({ cwd: this.#cwd });
1840
- if (!pkgPath) return;
1841
- const json = await read(pkgPath);
1842
- return JSON.parse(json);
1843
- }
1844
- getPackageJSONSync() {
1845
- const pkgPath = pkg.up({ cwd: this.#cwd });
1846
- if (!pkgPath) return;
1847
- const json = readSync(pkgPath);
1848
- return JSON.parse(json);
1849
- }
1850
- static setVersion(dependency, version) {
1851
- PackageManager.#cache[dependency] = version;
1852
- }
1853
- #match(packageJSON, dependency) {
1854
- const dependencies = {
1855
- ...packageJSON.dependencies || {},
1856
- ...packageJSON.devDependencies || {}
1854
+ /**
1855
+ * Checks if a schema matches a pattern for a given filter type (`schemaName`).
1856
+ * Returns `null` when the filter type doesn't apply to schemas.
1857
+ */
1858
+ function matchesSchemaPattern(node, type, pattern) {
1859
+ switch (type) {
1860
+ case "schemaName": return node.name ? !!node.name.match(pattern) : false;
1861
+ default: return null;
1862
+ }
1863
+ }
1864
+ /**
1865
+ * Default name resolver — `camelCase` for most types, `PascalCase` for `type`.
1866
+ */
1867
+ function defaultResolver(name, type) {
1868
+ let resolvedName = camelCase(name);
1869
+ if (type === "file" || type === "function") resolvedName = camelCase(name, { isFile: type === "file" });
1870
+ if (type === "type") resolvedName = pascalCase(name);
1871
+ return resolvedName;
1872
+ }
1873
+ /**
1874
+ * Default option resolver — applies include/exclude filters and merges any matching override options.
1875
+ * Returns `null` when the node is filtered out.
1876
+ */
1877
+ function defaultResolveOptions(node, { options, exclude = [], include, override = [] }) {
1878
+ if (isOperationNode(node)) {
1879
+ if (exclude.some(({ type, pattern }) => matchesOperationPattern(node, type, pattern))) return null;
1880
+ if (include && !include.some(({ type, pattern }) => matchesOperationPattern(node, type, pattern))) return null;
1881
+ const overrideOptions = override.find(({ type, pattern }) => matchesOperationPattern(node, type, pattern))?.options;
1882
+ return {
1883
+ ...options,
1884
+ ...overrideOptions
1857
1885
  };
1858
- if (typeof dependency === "string" && dependencies[dependency]) return dependencies[dependency];
1859
- const matchedDependency = Object.keys(dependencies).find((dep) => dep.match(dependency));
1860
- return matchedDependency ? dependencies[matchedDependency] : void 0;
1861
- }
1862
- async getVersion(dependency) {
1863
- if (typeof dependency === "string" && PackageManager.#cache[dependency]) return PackageManager.#cache[dependency];
1864
- const packageJSON = await this.getPackageJSON();
1865
- if (!packageJSON) return;
1866
- return this.#match(packageJSON, dependency);
1867
- }
1868
- getVersionSync(dependency) {
1869
- if (typeof dependency === "string" && PackageManager.#cache[dependency]) return PackageManager.#cache[dependency];
1870
- const packageJSON = this.getPackageJSONSync();
1871
- if (!packageJSON) return;
1872
- return this.#match(packageJSON, dependency);
1873
- }
1874
- async isValid(dependency, version) {
1875
- const packageVersion = await this.getVersion(dependency);
1876
- if (!packageVersion) return false;
1877
- if (packageVersion === version) return true;
1878
- const semVer = coerce(packageVersion);
1879
- if (!semVer) return false;
1880
- return satisfies(semVer, version);
1881
- }
1882
- isValidSync(dependency, version) {
1883
- const packageVersion = this.getVersionSync(dependency);
1884
- if (!packageVersion) return false;
1885
- if (packageVersion === version) return true;
1886
- const semVer = coerce(packageVersion);
1887
- if (!semVer) return false;
1888
- return satisfies(semVer, version);
1889
1886
  }
1890
- };
1887
+ if (isSchemaNode(node)) {
1888
+ if (exclude.some(({ type, pattern }) => matchesSchemaPattern(node, type, pattern) === true)) return null;
1889
+ if (include) {
1890
+ const applicable = include.map(({ type, pattern }) => matchesSchemaPattern(node, type, pattern)).filter((r) => r !== null);
1891
+ if (applicable.length > 0 && !applicable.includes(true)) return null;
1892
+ }
1893
+ const overrideOptions = override.find(({ type, pattern }) => matchesSchemaPattern(node, type, pattern) === true)?.options;
1894
+ return {
1895
+ ...options,
1896
+ ...overrideOptions
1897
+ };
1898
+ }
1899
+ return options;
1900
+ }
1901
+ /**
1902
+ * Defines a resolver for a plugin, with built-in defaults for name casing and include/exclude/override filtering.
1903
+ * Override `default` or `resolveOptions` in the builder to customize the behavior.
1904
+ *
1905
+ * @example
1906
+ * export const resolver = defineResolver<PluginTs>(() => ({
1907
+ * resolveName(name) {
1908
+ * return this.default(name, 'function')
1909
+ * },
1910
+ * resolveTypedName(name) {
1911
+ * return this.default(name, 'type')
1912
+ * },
1913
+ * resolveParamName(node, param) {
1914
+ * return this.resolveName(`${node.operationId} ${param.in} ${param.name}`)
1915
+ * },
1916
+ * }))
1917
+ */
1918
+ function defineResolver(build) {
1919
+ return {
1920
+ default: defaultResolver,
1921
+ resolveOptions: defaultResolveOptions,
1922
+ ...build()
1923
+ };
1924
+ }
1891
1925
  //#endregion
1892
1926
  //#region src/storages/memoryStorage.ts
1893
1927
  /**
@@ -1907,7 +1941,7 @@ var PackageManager = class PackageManager {
1907
1941
  * })
1908
1942
  * ```
1909
1943
  */
1910
- const memoryStorage = defineStorage(() => {
1944
+ const memoryStorage = createStorage(() => {
1911
1945
  const store = /* @__PURE__ */ new Map();
1912
1946
  return {
1913
1947
  name: "memory",
@@ -1939,7 +1973,7 @@ const memoryStorage = defineStorage(() => {
1939
1973
  //#endregion
1940
1974
  //#region src/utils/FunctionParams.ts
1941
1975
  /**
1942
- * @deprecated
1976
+ * @deprecated use ast package instead
1943
1977
  */
1944
1978
  var FunctionParams = class FunctionParams {
1945
1979
  #items = [];
@@ -2053,11 +2087,12 @@ async function isFormatterAvailable(formatter) {
2053
2087
  * ```
2054
2088
  */
2055
2089
  async function detectFormatter() {
2056
- for (const formatter of [
2090
+ const formatterNames = new Set([
2057
2091
  "biome",
2058
2092
  "oxfmt",
2059
2093
  "prettier"
2060
- ]) if (await isFormatterAvailable(formatter)) return formatter;
2094
+ ]);
2095
+ for (const formatter of formatterNames) if (await isFormatterAvailable(formatter)) return formatter;
2061
2096
  }
2062
2097
  //#endregion
2063
2098
  //#region src/utils/TreeNode.ts
@@ -2180,50 +2215,46 @@ function buildDirectoryTree(files, rootFolder = "") {
2180
2215
  return root;
2181
2216
  }
2182
2217
  //#endregion
2183
- //#region src/BarrelManager.ts
2218
+ //#region src/utils/getBarrelFiles.ts
2184
2219
  /** biome-ignore-all lint/suspicious/useIterableCallbackReturn: not needed */
2185
- var BarrelManager = class {
2186
- getFiles({ files: generatedFiles, root }) {
2187
- const cachedFiles = /* @__PURE__ */ new Map();
2188
- TreeNode.build(generatedFiles, root)?.forEach((treeNode) => {
2189
- if (!treeNode || !treeNode.children || !treeNode.parent?.data.path) return;
2190
- const barrelFile = {
2191
- path: join(treeNode.parent?.data.path, "index.ts"),
2192
- baseName: "index.ts",
2193
- exports: [],
2194
- imports: [],
2195
- sources: []
2196
- };
2197
- const previousBarrelFile = cachedFiles.get(barrelFile.path);
2198
- treeNode.leaves.forEach((item) => {
2199
- if (!item.data.name) return;
2200
- (item.data.file?.sources || []).forEach((source) => {
2201
- if (!item.data.file?.path || !source.isIndexable || !source.name) return;
2202
- if (previousBarrelFile?.sources.some((item) => item.name === source.name && item.isTypeOnly === source.isTypeOnly)) return;
2203
- barrelFile.exports.push({
2204
- name: [source.name],
2205
- path: getRelativePath(treeNode.parent?.data.path, item.data.path),
2206
- isTypeOnly: source.isTypeOnly
2207
- });
2208
- barrelFile.sources.push({
2209
- name: source.name,
2210
- isTypeOnly: source.isTypeOnly,
2211
- value: "",
2212
- isExportable: false,
2213
- isIndexable: false
2214
- });
2220
+ function getBarrelFilesByRoot(root, files) {
2221
+ const cachedFiles = /* @__PURE__ */ new Map();
2222
+ TreeNode.build(files, root)?.forEach((treeNode) => {
2223
+ if (!treeNode || !treeNode.children || !treeNode.parent?.data.path) return;
2224
+ const barrelFile = {
2225
+ path: join(treeNode.parent?.data.path, "index.ts"),
2226
+ baseName: "index.ts",
2227
+ exports: [],
2228
+ imports: [],
2229
+ sources: []
2230
+ };
2231
+ const previousBarrelFile = cachedFiles.get(barrelFile.path);
2232
+ treeNode.leaves.forEach((item) => {
2233
+ if (!item.data.name) return;
2234
+ (item.data.file?.sources || []).forEach((source) => {
2235
+ if (!item.data.file?.path || !source.isIndexable || !source.name) return;
2236
+ if (previousBarrelFile?.sources.some((item) => item.name === source.name && item.isTypeOnly === source.isTypeOnly)) return;
2237
+ barrelFile.exports.push({
2238
+ name: [source.name],
2239
+ path: getRelativePath(treeNode.parent?.data.path, item.data.path),
2240
+ isTypeOnly: source.isTypeOnly
2241
+ });
2242
+ barrelFile.sources.push({
2243
+ name: source.name,
2244
+ isTypeOnly: source.isTypeOnly,
2245
+ value: "",
2246
+ isExportable: false,
2247
+ isIndexable: false
2215
2248
  });
2216
2249
  });
2217
- if (previousBarrelFile) {
2218
- previousBarrelFile.sources.push(...barrelFile.sources);
2219
- previousBarrelFile.exports?.push(...barrelFile.exports || []);
2220
- } else cachedFiles.set(barrelFile.path, barrelFile);
2221
2250
  });
2222
- return [...cachedFiles.values()];
2223
- }
2224
- };
2225
- //#endregion
2226
- //#region src/utils/getBarrelFiles.ts
2251
+ if (previousBarrelFile) {
2252
+ previousBarrelFile.sources.push(...barrelFile.sources);
2253
+ previousBarrelFile.exports?.push(...barrelFile.exports || []);
2254
+ } else cachedFiles.set(barrelFile.path, barrelFile);
2255
+ });
2256
+ return [...cachedFiles.values()];
2257
+ }
2227
2258
  function trimExtName(text) {
2228
2259
  const dotIndex = text.lastIndexOf(".");
2229
2260
  if (dotIndex > 0 && !text.includes("/", dotIndex)) return text.slice(0, dotIndex);
@@ -2231,14 +2262,9 @@ function trimExtName(text) {
2231
2262
  }
2232
2263
  async function getBarrelFiles(files, { type, meta = {}, root, output }) {
2233
2264
  if (!type || type === "propagate") return [];
2234
- const barrelManager = new BarrelManager();
2235
2265
  const pathToBuildFrom = join(root, output.path);
2236
2266
  if (trimExtName(pathToBuildFrom).endsWith("index")) return [];
2237
- const barrelFiles = barrelManager.getFiles({
2238
- files,
2239
- root: pathToBuildFrom,
2240
- meta
2241
- });
2267
+ const barrelFiles = getBarrelFilesByRoot(pathToBuildFrom, files);
2242
2268
  if (type === "all") return barrelFiles.map((file) => {
2243
2269
  return {
2244
2270
  ...file,
@@ -2258,35 +2284,13 @@ async function getBarrelFiles(files, { type, meta = {}, root, output }) {
2258
2284
  });
2259
2285
  }
2260
2286
  //#endregion
2261
- //#region src/utils/getPlugins.ts
2262
- function isJSONPlugins(plugins) {
2263
- return Array.isArray(plugins) && plugins.some((plugin) => Array.isArray(plugin) && typeof plugin[0] === "string");
2264
- }
2265
- function isObjectPlugins(plugins) {
2266
- return plugins instanceof Object && !Array.isArray(plugins);
2267
- }
2268
- function getPlugins(plugins) {
2269
- if (isObjectPlugins(plugins)) throw new Error("Object plugins are not supported anymore, best to use http://kubb.dev/getting-started/configure#json");
2270
- if (isJSONPlugins(plugins)) throw new Error("JSON plugins are not supported anymore, best to use http://kubb.dev/getting-started/configure#json");
2271
- return Promise.resolve(plugins);
2272
- }
2273
- //#endregion
2274
2287
  //#region src/utils/getConfigs.ts
2275
2288
  /**
2276
2289
  * Converting UserConfig to Config Array without a change in the object beside the JSON convert.
2277
2290
  */
2278
2291
  async function getConfigs(config, args) {
2279
- let userConfigs = await (typeof config === "function" ? Promise.resolve(config(args)) : Promise.resolve(config));
2280
- if (!Array.isArray(userConfigs)) userConfigs = [userConfigs];
2281
- const results = [];
2282
- for (const item of userConfigs) {
2283
- const plugins = item.plugins ? await getPlugins(item.plugins) : void 0;
2284
- results.push({
2285
- ...item,
2286
- plugins
2287
- });
2288
- }
2289
- return results;
2292
+ const resolved = await (typeof config === "function" ? config(args) : config);
2293
+ return (Array.isArray(resolved) ? resolved : [resolved]).map((item) => ({ ...item }));
2290
2294
  }
2291
2295
  //#endregion
2292
2296
  //#region src/utils/linters.ts
@@ -2299,13 +2303,42 @@ async function isLinterAvailable(linter) {
2299
2303
  }
2300
2304
  }
2301
2305
  async function detectLinter() {
2302
- for (const linter of [
2306
+ const linterNames = new Set([
2303
2307
  "biome",
2304
2308
  "oxlint",
2305
2309
  "eslint"
2306
- ]) if (await isLinterAvailable(linter)) return linter;
2310
+ ]);
2311
+ for (const linter of linterNames) if (await isLinterAvailable(linter)) return linter;
2312
+ }
2313
+ //#endregion
2314
+ //#region src/utils/packageJSON.ts
2315
+ function getPackageJSONSync(cwd) {
2316
+ const pkgPath = pkg.up({ cwd });
2317
+ if (!pkgPath) return;
2318
+ return JSON.parse(readSync(pkgPath));
2319
+ }
2320
+ function match(packageJSON, dependency) {
2321
+ const dependencies = {
2322
+ ...packageJSON.dependencies || {},
2323
+ ...packageJSON.devDependencies || {}
2324
+ };
2325
+ if (typeof dependency === "string" && dependencies[dependency]) return dependencies[dependency];
2326
+ const matched = Object.keys(dependencies).find((dep) => dep.match(dependency));
2327
+ return matched ? dependencies[matched] : void 0;
2328
+ }
2329
+ function getVersionSync(dependency, cwd) {
2330
+ const packageJSON = getPackageJSONSync(cwd);
2331
+ return packageJSON ? match(packageJSON, dependency) : void 0;
2332
+ }
2333
+ function satisfiesDependency(dependency, version, cwd) {
2334
+ const packageVersion = getVersionSync(dependency, cwd);
2335
+ if (!packageVersion) return false;
2336
+ if (packageVersion === version) return true;
2337
+ const semVer = coerce(packageVersion);
2338
+ if (!semVer) return false;
2339
+ return satisfies(semVer, version);
2307
2340
  }
2308
2341
  //#endregion
2309
- export { AsyncEventEmitter, FunctionParams, PackageManager, PluginManager, PromiseManager, URLPath, build, build as default, defineAdapter, defineConfig, defineLogger, definePlugin, definePrinter, defineStorage, detectFormatter, detectLinter, formatters, fsStorage, getBarrelFiles, getConfigs, getMode, isInputPath, linters, logLevel, memoryStorage, safeBuild, setup };
2342
+ export { FunctionParams, PluginDriver, build, build as default, createAdapter, createPlugin, createStorage, defaultResolveOptions, defineConfig, defineGenerator, defineLogger, definePrinter, defineResolver, detectFormatter, detectLinter, formatters, fsStorage, getBarrelFiles, getConfigs, getMode, isInputPath, linters, logLevel, memoryStorage, safeBuild, satisfiesDependency, setup };
2310
2343
 
2311
2344
  //# sourceMappingURL=index.js.map