@kubb/core 5.0.0-alpha.53 → 5.0.0-alpha.55

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.cjs CHANGED
@@ -1,9 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_PluginDriver = require("./PluginDriver-DUJnMDK5.cjs");
2
+ const require_PluginDriver = require("./PluginDriver-6bHJKAZ6.cjs");
3
3
  let node_events = require("node:events");
4
4
  let node_fs_promises = require("node:fs/promises");
5
5
  let node_path = require("node:path");
6
- node_path = require_PluginDriver.__toESM(node_path, 1);
7
6
  let _kubb_ast = require("@kubb/ast");
8
7
  _kubb_ast = require_PluginDriver.__toESM(_kubb_ast, 1);
9
8
  let node_process = require("node:process");
@@ -182,29 +181,6 @@ function formatMs(ms) {
182
181
  //#endregion
183
182
  //#region ../../internals/utils/src/fs.ts
184
183
  /**
185
- * Converts all backslashes to forward slashes.
186
- * Extended-length Windows paths (`\\?\...`) are left unchanged.
187
- */
188
- function toSlash(p) {
189
- if (p.startsWith("\\\\?\\")) return p;
190
- return p.replaceAll("\\", "/");
191
- }
192
- /**
193
- * Returns the relative path from `rootDir` to `filePath`, always using forward slashes
194
- * and prefixed with `./` when not already traversing upward.
195
- *
196
- * @example
197
- * ```ts
198
- * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'
199
- * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'
200
- * ```
201
- */
202
- function getRelativePath(rootDir, filePath) {
203
- if (!rootDir || !filePath) throw new Error(`Root and file should be filled in when retrieving the relativePath, ${rootDir || ""} ${filePath || ""}`);
204
- const relativePath = node_path.posix.relative(toSlash(rootDir), toSlash(filePath));
205
- return relativePath.startsWith("../") ? relativePath : `./${relativePath}`;
206
- }
207
- /**
208
184
  * Resolves to `true` when the file or directory at `path` exists.
209
185
  * Uses `Bun.file().exists()` when running under Bun, `fs.access` otherwise.
210
186
  *
@@ -735,7 +711,7 @@ const fsStorage = createStorage(() => ({
735
711
  }));
736
712
  //#endregion
737
713
  //#region package.json
738
- var version = "5.0.0-alpha.53";
714
+ var version = "5.0.0-alpha.55";
739
715
  //#endregion
740
716
  //#region src/utils/diagnostics.ts
741
717
  /**
@@ -754,239 +730,6 @@ function getDiagnosticInfo() {
754
730
  };
755
731
  }
756
732
  //#endregion
757
- //#region src/utils/TreeNode.ts
758
- /**
759
- * Tree structure used to build per-directory barrel (`index.ts`) files from a
760
- * flat list of generated {@link FileNode} entries.
761
- *
762
- * Each node represents either a directory or a file within the output tree.
763
- * Use {@link TreeNode.build} to construct a root node from a file list, then
764
- * traverse with {@link TreeNode.forEach}, {@link TreeNode.leaves}, or the
765
- * `*Deep` helpers.
766
- */
767
- var TreeNode = class TreeNode {
768
- data;
769
- parent;
770
- children = [];
771
- #cachedLeaves = void 0;
772
- constructor(data, parent) {
773
- this.data = data;
774
- this.parent = parent;
775
- }
776
- addChild(data) {
777
- const child = new TreeNode(data, this);
778
- if (!this.children) this.children = [];
779
- this.children.push(child);
780
- return child;
781
- }
782
- /**
783
- * Returns the root ancestor of this node, walking up via `parent` links.
784
- */
785
- get root() {
786
- if (!this.parent) return this;
787
- return this.parent.root;
788
- }
789
- /**
790
- * Returns all leaf descendants (nodes with no children) of this node.
791
- *
792
- * Results are cached after the first traversal.
793
- */
794
- get leaves() {
795
- if (!this.children || this.children.length === 0) return [this];
796
- if (this.#cachedLeaves) return this.#cachedLeaves;
797
- const leaves = [];
798
- for (const child of this.children) leaves.push(...child.leaves);
799
- this.#cachedLeaves = leaves;
800
- return leaves;
801
- }
802
- /**
803
- * Visits this node and every descendant in depth-first order.
804
- */
805
- forEach(callback) {
806
- if (typeof callback !== "function") throw new TypeError("forEach() callback must be a function");
807
- callback(this);
808
- for (const child of this.children) child.forEach(callback);
809
- return this;
810
- }
811
- /**
812
- * Finds the first leaf that satisfies `predicate`, or `undefined` when none match.
813
- */
814
- findDeep(predicate) {
815
- if (typeof predicate !== "function") throw new TypeError("find() predicate must be a function");
816
- return this.leaves.find(predicate);
817
- }
818
- /**
819
- * Calls `callback` for every leaf of this node.
820
- */
821
- forEachDeep(callback) {
822
- if (typeof callback !== "function") throw new TypeError("forEach() callback must be a function");
823
- this.leaves.forEach(callback);
824
- }
825
- /**
826
- * Returns all leaves that satisfy `callback`.
827
- */
828
- filterDeep(callback) {
829
- if (typeof callback !== "function") throw new TypeError("filter() callback must be a function");
830
- return this.leaves.filter(callback);
831
- }
832
- /**
833
- * Maps every leaf through `callback` and returns the resulting array.
834
- */
835
- mapDeep(callback) {
836
- if (typeof callback !== "function") throw new TypeError("map() callback must be a function");
837
- return this.leaves.map(callback);
838
- }
839
- /**
840
- * Builds a {@link TreeNode} tree from a flat list of files.
841
- *
842
- * - Filters to files under `root` (when provided) and skips `.json` files.
843
- * - Returns `null` when no files match.
844
- */
845
- static build(files, root) {
846
- try {
847
- const filteredTree = buildDirectoryTree(files, root);
848
- if (!filteredTree) return null;
849
- const treeNode = new TreeNode({
850
- name: filteredTree.name,
851
- path: filteredTree.path,
852
- file: filteredTree.file,
853
- type: require_PluginDriver.PluginDriver.getMode(filteredTree.path)
854
- });
855
- const recurse = (node, item) => {
856
- const subNode = node.addChild({
857
- name: item.name,
858
- path: item.path,
859
- file: item.file,
860
- type: require_PluginDriver.PluginDriver.getMode(item.path)
861
- });
862
- if (item.children?.length) item.children?.forEach((child) => {
863
- recurse(subNode, child);
864
- });
865
- };
866
- filteredTree.children?.forEach((child) => {
867
- recurse(treeNode, child);
868
- });
869
- return treeNode;
870
- } catch (error) {
871
- throw new Error("Something went wrong with creating barrel files with the TreeNode class", { cause: error });
872
- }
873
- }
874
- };
875
- const normalizePath = (p) => p.replaceAll("\\", "/");
876
- function buildDirectoryTree(files, rootFolder = "") {
877
- const normalizedRootFolder = normalizePath(rootFolder);
878
- const rootPrefix = normalizedRootFolder.endsWith("/") ? normalizedRootFolder : `${normalizedRootFolder}/`;
879
- const filteredFiles = files.filter((file) => {
880
- const normalizedFilePath = normalizePath(file.path);
881
- return rootFolder ? normalizedFilePath.startsWith(rootPrefix) && !normalizedFilePath.endsWith(".json") : !normalizedFilePath.endsWith(".json");
882
- });
883
- if (filteredFiles.length === 0) return null;
884
- const root = {
885
- name: rootFolder || "",
886
- path: rootFolder || "",
887
- children: []
888
- };
889
- filteredFiles.forEach((file) => {
890
- const parts = file.path.slice(rootFolder.length).split("/").filter(Boolean);
891
- let currentLevel = root.children;
892
- let currentPath = normalizePath(rootFolder);
893
- parts.forEach((part, index) => {
894
- currentPath = node_path.default.posix.join(currentPath, part);
895
- let existingNode = currentLevel.find((node) => node.name === part);
896
- if (!existingNode) {
897
- if (index === parts.length - 1) existingNode = {
898
- name: part,
899
- file,
900
- path: currentPath
901
- };
902
- else existingNode = {
903
- name: part,
904
- path: currentPath,
905
- children: []
906
- };
907
- currentLevel.push(existingNode);
908
- }
909
- if (!existingNode.file) currentLevel = existingNode.children;
910
- });
911
- });
912
- return root;
913
- }
914
- //#endregion
915
- //#region src/utils/getBarrelFiles.ts
916
- function getBarrelFilesByRoot(root, files) {
917
- const cachedFiles = /* @__PURE__ */ new Map();
918
- TreeNode.build(files, root)?.forEach((treeNode) => {
919
- if (!treeNode?.children || !treeNode.parent?.data.path) return;
920
- const barrelFile = (0, _kubb_ast.createFile)({
921
- path: (0, node_path.join)(treeNode.parent?.data.path, require_PluginDriver.BARREL_FILENAME),
922
- baseName: require_PluginDriver.BARREL_FILENAME,
923
- exports: [],
924
- imports: [],
925
- sources: []
926
- });
927
- const previousBarrelFile = cachedFiles.get(barrelFile.path);
928
- treeNode.leaves.forEach((item) => {
929
- if (!item.data.name) return;
930
- (item.data.file?.sources || []).forEach((source) => {
931
- if (!item.data.file?.path || !source.isIndexable || !source.name) return;
932
- if (previousBarrelFile?.sources.some((item) => item.name === source.name && item.isTypeOnly === source.isTypeOnly)) return;
933
- barrelFile.exports.push((0, _kubb_ast.createExport)({
934
- name: [source.name],
935
- path: getRelativePath(treeNode.parent?.data.path, item.data.path),
936
- isTypeOnly: source.isTypeOnly
937
- }));
938
- barrelFile.sources.push((0, _kubb_ast.createSource)({
939
- name: source.name,
940
- isTypeOnly: source.isTypeOnly,
941
- isExportable: false,
942
- isIndexable: false
943
- }));
944
- });
945
- });
946
- if (previousBarrelFile) {
947
- previousBarrelFile.sources.push(...barrelFile.sources);
948
- previousBarrelFile.exports.push(...barrelFile.exports);
949
- } else cachedFiles.set(barrelFile.path, barrelFile);
950
- });
951
- return [...cachedFiles.values()];
952
- }
953
- function trimExtName(text) {
954
- const dotIndex = text.lastIndexOf(".");
955
- if (dotIndex > 0 && !text.includes("/", dotIndex)) return text.slice(0, dotIndex);
956
- return text;
957
- }
958
- /**
959
- * Generates `index.ts` barrel files for all directories under `root/output.path`.
960
- *
961
- * - Returns an empty array when `type` is falsy or `'propagate'`.
962
- * - Skips generation when the output path itself ends with `index` (already a barrel).
963
- * - When `type` is `'all'`, strips named exports so every re-export becomes a wildcard (`export * from`).
964
- * - Attaches `meta` to each barrel file for downstream plugin identification.
965
- */
966
- async function getBarrelFiles(files, { type, meta = {}, root, output }) {
967
- if (!type || type === "propagate") return [];
968
- const pathToBuildFrom = (0, node_path.join)(root, output.path);
969
- if (trimExtName(pathToBuildFrom).endsWith("index")) return [];
970
- const barrelFiles = getBarrelFilesByRoot(pathToBuildFrom, files);
971
- if (type === "all") return barrelFiles.map((file) => {
972
- return {
973
- ...file,
974
- exports: file.exports.map((exportItem) => {
975
- return {
976
- ...exportItem,
977
- name: void 0
978
- };
979
- })
980
- };
981
- });
982
- return barrelFiles.map((indexFile) => {
983
- return {
984
- ...indexFile,
985
- meta
986
- };
987
- });
988
- }
989
- //#endregion
990
733
  //#region src/utils/isInputPath.ts
991
734
  function isInputPath(config) {
992
735
  return typeof config?.input === "object" && config.input !== null && "path" in config.input;
@@ -1036,7 +779,6 @@ async function setup(userConfig, options = {}) {
1036
779
  adapter: userConfig.adapter,
1037
780
  output: {
1038
781
  write: true,
1039
- barrelType: "named",
1040
782
  extension: require_PluginDriver.DEFAULT_EXTENSION,
1041
783
  defaultBanner: require_PluginDriver.DEFAULT_BANNER,
1042
784
  ...userConfig.output
@@ -1056,6 +798,7 @@ async function setup(userConfig, options = {}) {
1056
798
  await storage?.clear((0, node_path.resolve)(config.root, config.output.path));
1057
799
  }
1058
800
  const driver = new require_PluginDriver.PluginDriver(config, { hooks });
801
+ for (const middleware of config.middleware ?? []) middleware.install(hooks);
1059
802
  const adapter = config.adapter;
1060
803
  if (!adapter) throw new Error("No adapter configured. Please provide an adapter in your kubb.config.ts.");
1061
804
  const source = inputToAdapterSource(config);
@@ -1164,13 +907,15 @@ async function safeBuild(setupResult) {
1164
907
  config,
1165
908
  adapter: driver.adapter,
1166
909
  inputNode: driver.inputNode,
1167
- getPlugin: driver.getPlugin.bind(driver)
910
+ getPlugin: driver.getPlugin.bind(driver),
911
+ get files() {
912
+ return driver.fileManager.files;
913
+ },
914
+ upsertFile: (...files) => driver.fileManager.upsert(...files)
1168
915
  });
1169
916
  for (const plugin of driver.plugins.values()) {
1170
917
  const context = driver.getContext(plugin);
1171
918
  const hrStart = process.hrtime();
1172
- const { output } = plugin.options ?? {};
1173
- const root = (0, node_path.resolve)(config.root, config.output.path);
1174
919
  try {
1175
920
  const timestamp = /* @__PURE__ */ new Date();
1176
921
  await hooks.emit("kubb:plugin:start", { plugin });
@@ -1179,15 +924,6 @@ async function safeBuild(setupResult) {
1179
924
  logs: ["Starting plugin...", ` • Plugin Name: ${plugin.name}`]
1180
925
  });
1181
926
  if (plugin.generators?.length || driver.hasRegisteredGenerators(plugin.name)) await runPluginAstHooks(plugin, context);
1182
- if (output) {
1183
- const barrelFiles = await getBarrelFiles(driver.fileManager.files, {
1184
- type: output.barrelType ?? "named",
1185
- root,
1186
- output,
1187
- meta: { pluginName: plugin.name }
1188
- });
1189
- await context.upsertFile(...barrelFiles);
1190
- }
1191
927
  const duration = getElapsedMs(hrStart);
1192
928
  pluginTimings.set(plugin.name, duration);
1193
929
  await hooks.emit("kubb:plugin:end", {
@@ -1225,45 +961,6 @@ async function safeBuild(setupResult) {
1225
961
  });
1226
962
  }
1227
963
  }
1228
- if (config.output.barrelType) {
1229
- const rootPath = (0, node_path.resolve)((0, node_path.resolve)(config.root), config.output.path, require_PluginDriver.BARREL_FILENAME);
1230
- const rootDir = (0, node_path.dirname)(rootPath);
1231
- await hooks.emit("kubb:debug", {
1232
- date: /* @__PURE__ */ new Date(),
1233
- logs: [
1234
- "Generating barrel file",
1235
- ` • Type: ${config.output.barrelType}`,
1236
- ` • Path: ${rootPath}`
1237
- ]
1238
- });
1239
- const barrelFiles = driver.fileManager.files.filter((file) => {
1240
- return file.sources.some((source) => source.isIndexable);
1241
- });
1242
- await hooks.emit("kubb:debug", {
1243
- date: /* @__PURE__ */ new Date(),
1244
- logs: [`Found ${barrelFiles.length} indexable files for barrel export`]
1245
- });
1246
- const existingBarrel = driver.fileManager.files.find((f) => f.path === rootPath);
1247
- const rootFile = (0, _kubb_ast.createFile)({
1248
- path: rootPath,
1249
- baseName: require_PluginDriver.BARREL_FILENAME,
1250
- exports: buildBarrelExports({
1251
- barrelFiles,
1252
- rootDir,
1253
- existingExports: new Set(existingBarrel?.exports?.flatMap((e) => Array.isArray(e.name) ? e.name : [e.name]).filter((n) => Boolean(n)) ?? []),
1254
- config,
1255
- driver
1256
- }).map((e) => (0, _kubb_ast.createExport)(e)),
1257
- sources: [],
1258
- imports: [],
1259
- meta: {}
1260
- });
1261
- driver.fileManager.upsert(rootFile);
1262
- await hooks.emit("kubb:debug", {
1263
- date: /* @__PURE__ */ new Date(),
1264
- logs: [`✓ Generated barrel file (${rootFile.exports?.length || 0} exports)`]
1265
- });
1266
- }
1267
964
  const files = driver.fileManager.files;
1268
965
  const parsersMap = /* @__PURE__ */ new Map();
1269
966
  for (const parser of config.parsers) if (parser.extNames) for (const extname of parser.extNames) parsersMap.set(extname, parser);
@@ -1341,26 +1038,6 @@ async function build(setupResult) {
1341
1038
  sources
1342
1039
  };
1343
1040
  }
1344
- function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }) {
1345
- const pluginNameMap = /* @__PURE__ */ new Map();
1346
- for (const plugin of driver.plugins.values()) pluginNameMap.set(plugin.name, plugin);
1347
- return barrelFiles.flatMap((file) => {
1348
- const containsOnlyTypes = file.sources?.every((source) => source.isTypeOnly);
1349
- return (file.sources ?? []).flatMap((source) => {
1350
- if (!file.path || !source.isIndexable) return [];
1351
- const meta = file.meta;
1352
- const pluginOptions = (meta?.pluginName ? pluginNameMap.get(meta.pluginName) : void 0)?.options;
1353
- if (!pluginOptions || pluginOptions.output?.barrelType === false) return [];
1354
- const exportName = config.output.barrelType === "all" ? void 0 : source.name ? [source.name] : void 0;
1355
- if (exportName?.some((n) => existingExports.has(n))) return [];
1356
- return [(0, _kubb_ast.createExport)({
1357
- name: exportName,
1358
- path: getRelativePath(rootDir, file.path),
1359
- isTypeOnly: config.output.barrelType === "all" ? containsOnlyTypes : source.isTypeOnly
1360
- })];
1361
- });
1362
- });
1363
- }
1364
1041
  function inputToAdapterSource(config) {
1365
1042
  if (Array.isArray(config.input)) return {
1366
1043
  type: "paths",
@@ -1489,6 +1166,28 @@ function defineLogger(logger) {
1489
1166
  return logger;
1490
1167
  }
1491
1168
  //#endregion
1169
+ //#region src/defineMiddleware.ts
1170
+ /**
1171
+ * Identity factory for middleware.
1172
+ * Returns the middleware object unchanged but provides a typed entry-point
1173
+ * to define middleware with proper inference.
1174
+ *
1175
+ * @example
1176
+ * ```ts
1177
+ * export const myMiddleware = defineMiddleware({
1178
+ * name: 'my-middleware',
1179
+ * install(hooks) {
1180
+ * hooks.on('kubb:build:end', ({ files }) => {
1181
+ * console.log(`Build complete with ${files.length} files`)
1182
+ * })
1183
+ * },
1184
+ * })
1185
+ * ```
1186
+ */
1187
+ function defineMiddleware(middleware) {
1188
+ return middleware;
1189
+ }
1190
+ //#endregion
1492
1191
  //#region src/defineParser.ts
1493
1192
  /**
1494
1193
  * Defines a parser with type safety.
@@ -1608,6 +1307,7 @@ exports.createRenderer = createRenderer;
1608
1307
  exports.createStorage = createStorage;
1609
1308
  exports.defineGenerator = defineGenerator;
1610
1309
  exports.defineLogger = defineLogger;
1310
+ exports.defineMiddleware = defineMiddleware;
1611
1311
  exports.defineParser = defineParser;
1612
1312
  exports.definePlugin = definePlugin;
1613
1313
  exports.defineResolver = require_PluginDriver.defineResolver;