@kubb/middleware-barrel 5.0.0-beta.5 → 5.0.0-beta.50

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/LICENSE CHANGED
@@ -1,14 +1,21 @@
1
- Copyright (c) 2026 Stijn Van Hulle
2
-
3
- This repository contains software under two licenses:
1
+ MIT License
4
2
 
5
- 1. Most of the code in this repository is licensed under the
6
- MIT License — see licenses/LICENSE-MIT for the full license text.
3
+ Copyright (c) 2026 Stijn Van Hulle
7
4
 
8
- 2. The following components are licensed under the
9
- GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later)
10
- see licenses/LICENSE-AGPL-3.0 for the full license text:
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
11
 
12
- - packages/agent (published as @kubb/agent)
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
13
14
 
14
- Each package's own LICENSE file or package.json specifies its applicable license.
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ <div align="center">
2
+ <a href="https://kubb.dev" target="_blank" rel="noopener noreferrer">
3
+ <img src="https://kubb.dev/og.png" alt="Kubb banner">
4
+ </a>
5
+
6
+ [![npm version][npm-version-src]][npm-version-href]
7
+ [![npm downloads][npm-downloads-src]][npm-downloads-href]
8
+ [![Stars][stars-src]][stars-href]
9
+ [![License][license-src]][license-href]
10
+ [![Node][node-src]][node-href]
11
+
12
+ <h4>
13
+ <a href="https://kubb.dev" target="_blank">Documentation</a>
14
+ <span> · </span>
15
+ <a href="https://github.com/kubb-labs/kubb/issues/" target="_blank">Report Bug</a>
16
+ <span> · </span>
17
+ <a href="https://github.com/kubb-labs/kubb/issues/" target="_blank">Request Feature</a>
18
+ </h4>
19
+ </div>
20
+
21
+ <br />
22
+
23
+ # @kubb/middleware-barrel
24
+
25
+ ### Barrel-file middleware for Kubb
26
+
27
+ Automatically generates `index.ts` re-export files for each plugin output directory and an optional root barrel after all plugins have run.
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ bun add @kubb/middleware-barrel
33
+ # or
34
+ pnpm add @kubb/middleware-barrel
35
+ # or
36
+ npm install @kubb/middleware-barrel
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ Add `middlewareBarrel` to the `middleware` array in your `kubb.config.ts`:
42
+
43
+ ```typescript
44
+ import { defineConfig } from 'kubb'
45
+ import { middlewareBarrel } from '@kubb/middleware-barrel'
46
+
47
+ export default defineConfig({
48
+ input: {
49
+ path: './openapi.yaml',
50
+ },
51
+ output: {
52
+ path: './src/gen',
53
+ },
54
+ middleware: [
55
+ middlewareBarrel({
56
+ type: 'named',
57
+ }),
58
+ ],
59
+ })
60
+ ```
61
+
62
+ ## Options
63
+
64
+ | Option | Type | Default | Description |
65
+ | ------ | --------------------------------- | --------- | ------------------------------------------- |
66
+ | `type` | `'all' \| 'named' \| 'propagate'` | `'named'` | Export style for the generated barrel files |
67
+
68
+ ### Export types
69
+
70
+ | Value | Output |
71
+ | ------------- | ------------------------------------------------------------------------------- |
72
+ | `'all'` | `export * from './...'` — wildcard re-exports |
73
+ | `'named'` | `export { ... } from './...'` — named re-exports, tree-shaking friendly |
74
+ | `'propagate'` | `export * from './...'` on index files only, propagating up through directories |
75
+
76
+ ## How it works
77
+
78
+ After every plugin finishes generating files, `@kubb/middleware-barrel` walks the output tree and creates an `index.ts` in each directory, re-exporting everything inside. It then creates a root `index.ts` at the top of the output path that re-exports from all plugin directories.
79
+
80
+ ## Supporting Kubb
81
+
82
+ Kubb is an open source project, and its development is funded entirely by sponsors. If you would like to become a sponsor, please consider:
83
+
84
+ - [Become a Sponsor on GitHub](https://github.com/sponsors/stijnvanhulle)
85
+ - [See sponsorship tiers and our sponsors](https://kubb.dev/sponsors)
86
+
87
+ <p align="center">
88
+ <a href="https://github.com/sponsors/stijnvanhulle">
89
+ <img src="https://raw.githubusercontent.com/stijnvanhulle/sponsors/main/sponsors.svg" alt="My sponsors" />
90
+ </a>
91
+ </p>
92
+
93
+ ## License
94
+
95
+ [MIT](https://github.com/kubb-labs/kubb/blob/main/licenses/LICENSE-MIT)
96
+
97
+ <!-- Badges -->
98
+
99
+ [npm-version-src]: https://shieldcn.dev/npm/v/@kubb/middleware-barrel.svg?variant=secondary&size=xs&theme=zinc&mode=dark
100
+ [npm-version-href]: https://npmx.dev/package/@kubb/middleware-barrel
101
+ [npm-downloads-src]: https://shieldcn.dev/npm/dm/@kubb/middleware-barrel.svg?variant=secondary&size=xs&theme=zinc&mode=dark
102
+ [npm-downloads-href]: https://npmx.dev/package/@kubb/middleware-barrel
103
+ [stars-src]: https://shieldcn.dev/github/stars/kubb-labs/kubb.svg?variant=secondary&size=xs&theme=zinc&mode=dark
104
+ [stars-href]: https://github.com/kubb-labs/kubb
105
+ [license-src]: https://shieldcn.dev/npm/license/@kubb/middleware-barrel.svg?variant=secondary&size=xs&theme=zinc
106
+ [license-href]: https://github.com/kubb-labs/kubb/blob/main/LICENSE
107
+ [node-src]: https://shieldcn.dev/npm/node/@kubb/middleware-barrel.svg?variant=secondary&size=xs&theme=zinc&mode=dark
108
+ [node-href]: https://npmx.dev/package/@kubb/middleware-barrel
package/dist/index.cjs CHANGED
@@ -69,7 +69,7 @@ function buildTree(rootPath, filePaths) {
69
69
  children: [],
70
70
  isFile: false
71
71
  };
72
- const childIndex = /* @__PURE__ */ new Map();
72
+ const childIndex = /* @__PURE__ */ new WeakMap();
73
73
  childIndex.set(root, /* @__PURE__ */ new Map());
74
74
  const rootPrefix = `${normalizedRoot}/`;
75
75
  for (const filePath of filePaths) {
@@ -109,39 +109,14 @@ function compareByPath(a, b) {
109
109
  return a.path < b.path ? -1 : a.path > b.path ? 1 : 0;
110
110
  }
111
111
  //#endregion
112
- //#region src/utils/excludedPaths.ts
113
- /**
114
- * Builds a POSIX-normalized prefix for a plugin's output directory, with a trailing `/`.
115
- *
116
- * Used to detect (and later exclude) files generated by plugins that opted out of the root barrel.
117
- */
118
- function getPluginOutputPrefix(plugin, config) {
119
- return `${toPosixPath((0, node_path.resolve)(config.root, config.output.path, plugin.options.output.path))}/`;
120
- }
121
- /**
122
- * Returns `true` when `filePath` lives under any of the given excluded directory prefixes.
123
- *
124
- * Both sides are POSIX-normalized so Windows backslash paths match correctly.
125
- */
126
- function isExcludedPath(filePath, prefixes) {
127
- const normalized = toPosixPath(filePath);
128
- return prefixes.values().some((prefix) => normalized.startsWith(prefix));
129
- }
130
- //#endregion
131
- //#region src/constants.ts
132
- /**
133
- * Full file name for barrel files (with extension).
134
- */
135
- const BARREL_FILENAME = "index.ts";
136
- //#endregion
137
- //#region src/utils/getBarrelFiles.ts
112
+ //#region src/utils.ts
138
113
  const SOURCE_EXTENSIONS = new Set([
139
114
  ".ts",
140
115
  ".tsx",
141
116
  ".js",
142
117
  ".jsx"
143
118
  ]);
144
- const BARREL_SUFFIX = `/${BARREL_FILENAME}`;
119
+ const BARREL_SUFFIX = `/index.ts`;
145
120
  function toRelativeModulePath(fromDir, filePath) {
146
121
  return `./${filePath.slice(fromDir.length + 1)}`;
147
122
  }
@@ -150,7 +125,7 @@ function isBarrelPath(path) {
150
125
  }
151
126
  function makeBarrel(dirPath, exports) {
152
127
  return (0, _kubb_ast.createFile)({
153
- baseName: BARREL_FILENAME,
128
+ baseName: "index.ts",
154
129
  path: `${dirPath}${BARREL_SUFFIX}`,
155
130
  exports,
156
131
  sources: [],
@@ -200,32 +175,33 @@ const namedStrategy = ({ dirPath, leafPath, sourceFile }) => {
200
175
  };
201
176
  const LEAF_STRATEGIES = new Map([["all", allStrategy], ["named", namedStrategy]]);
202
177
  /**
203
- * Post-order walk that emits a barrel per visited directory.
178
+ * Post-order walk that yields a barrel per visited directory.
179
+ * Returns the list of leaf file paths collected in this subtree (used by the parent call).
204
180
  */
205
- function walkAllOrNamed(node, params, isRoot, out) {
181
+ function* walkAllOrNamed(node, params, isRoot) {
206
182
  const subtreeLeaves = [];
207
183
  for (const child of node.children) {
208
184
  if (child.isFile) {
209
185
  if (!isBarrelPath(child.path)) subtreeLeaves.push(child.path);
210
186
  continue;
211
187
  }
212
- const childLeaves = walkAllOrNamed(child, params, false, out);
188
+ const childLeaves = yield* walkAllOrNamed(child, params, false);
213
189
  for (const leaf of childLeaves) subtreeLeaves.push(leaf);
214
190
  }
215
191
  if (!isRoot && !params.recursive) return subtreeLeaves;
216
192
  const exports = subtreeLeaves.flatMap((leafPath) => params.strategy({
217
193
  dirPath: node.path,
218
194
  leafPath,
219
- sourceFile: params.sourceFiles.get(leafPath)
195
+ sourceFile: params.sourceFiles.get(leafPath) ?? null
220
196
  }));
221
- if (exports.length > 0) out.push(makeBarrel(node.path, exports));
197
+ if (exports.length > 0) yield makeBarrel(node.path, exports);
222
198
  return subtreeLeaves;
223
199
  }
224
200
  /**
225
- * Recursive walk that emits one barrel per directory, re-exporting files and sub-barrels.
201
+ * Recursive walk that yields one barrel per directory, re-exporting files and sub-barrels.
226
202
  * Used when nested: true.
227
203
  */
228
- function walkNested(node, out) {
204
+ function* walkNested(node) {
229
205
  const exports = [];
230
206
  for (const child of node.children) {
231
207
  if (child.isFile) {
@@ -233,10 +209,10 @@ function walkNested(node, out) {
233
209
  exports.push((0, _kubb_ast.createExport)({ path: toRelativeModulePath(node.path, child.path) }));
234
210
  continue;
235
211
  }
236
- walkNested(child, out);
212
+ yield* walkNested(child);
237
213
  exports.push((0, _kubb_ast.createExport)({ path: toRelativeModulePath(node.path, `${child.path}${BARREL_SUFFIX}`) }));
238
214
  }
239
- if (exports.length > 0) out.push(makeBarrel(node.path, exports));
215
+ if (exports.length > 0) yield makeBarrel(node.path, exports);
240
216
  }
241
217
  function indexRelevantFiles(files, outputPath) {
242
218
  const outputPrefix = `${toPosixPath(outputPath)}/`;
@@ -256,40 +232,111 @@ function indexRelevantFiles(files, outputPath) {
256
232
  };
257
233
  }
258
234
  /**
259
- * Generates barrel `FileNode`s for the directory rooted at `outputPath`.
235
+ * Yields barrel `FileNode`s for the directory rooted at `outputPath`.
236
+ *
237
+ * @example
238
+ * ```ts
239
+ * for (const file of getBarrelFiles({ outputPath, files, barrelType })) {
240
+ * upsertFile(file)
241
+ * }
242
+ * // or collect into an array
243
+ * const barrels = [...getBarrelFiles({ outputPath, files, barrelType })]
244
+ * ```
260
245
  */
261
- function getBarrelFiles({ outputPath, files, barrelType, nested = false, recursive = false }) {
246
+ function* getBarrelFiles({ outputPath, files, barrelType, nested = false, recursive = false }) {
262
247
  const { sourceFiles, paths } = indexRelevantFiles(files, outputPath);
263
- if (paths.length === 0) return [];
248
+ if (paths.length === 0) return;
264
249
  const tree = buildTree(outputPath, paths);
265
- const result = [];
266
250
  if (nested) {
267
- walkNested(tree, result);
268
- return result;
251
+ yield* walkNested(tree);
252
+ return;
269
253
  }
270
254
  const strategy = LEAF_STRATEGIES.get(barrelType);
271
- if (!strategy) return result;
272
- walkAllOrNamed(tree, {
255
+ if (!strategy) return;
256
+ yield* walkAllOrNamed(tree, {
273
257
  sourceFiles,
274
258
  strategy,
275
259
  recursive
276
- }, true, result);
277
- return result;
260
+ }, true);
261
+ }
262
+ /**
263
+ * Builds a POSIX-normalized prefix for a plugin's output. A directory output gets a trailing `/`,
264
+ * while a `mode: 'file'` output (the path is the file itself) gets the exact path with no trailing `/`.
265
+ *
266
+ * Used to detect (and later exclude) files generated by plugins that opted out of the root barrel.
267
+ */
268
+ function getPluginOutputPrefix(plugin, config) {
269
+ const resolved = toPosixPath((0, node_path.resolve)(config.root, config.output.path, plugin.options.output.path));
270
+ return plugin.options.output.mode === "file" ? resolved : `${resolved}/`;
271
+ }
272
+ /**
273
+ * Returns `true` when `filePath` lives under any of the given excluded prefixes. A prefix with a
274
+ * trailing `/` matches a directory subtree, and a prefix without one matches that exact file
275
+ * (used for `mode: 'file'` outputs).
276
+ *
277
+ * Both sides are POSIX-normalized so Windows backslash paths match correctly.
278
+ */
279
+ function isExcludedPath(filePath, prefixes) {
280
+ const normalized = toPosixPath(filePath);
281
+ return prefixes.values().some((prefix) => prefix.endsWith("/") ? normalized.startsWith(prefix) : normalized === prefix);
278
282
  }
279
283
  //#endregion
280
284
  //#region src/middleware.ts
281
285
  /**
282
- * Generates `index.ts` barrel files for each plugin and a root barrel at `config.output.path/index.ts`.
286
+ * Applies a plugin's configured `output.banner`/`footer` to a barrel file, flagged as `isBarrel`.
283
287
  *
284
- * Each plugin inherits `output.barrel` from `config.output.barrel` (defaults to `{ type: 'named' }`).
285
- * Set `barrel: false` on a plugin to disable its barrel and exclude it from the root barrel.
288
+ * Resolves through the plugin's own resolver, and only when the plugin explicitly sets a
289
+ * banner/footer, so barrels stay banner-free by default and never inherit the implicit
290
+ * "Generated by Kubb" notice.
291
+ */
292
+ function withBarrelBannerFooter({ file, plugin, config }) {
293
+ const output = plugin.options?.output;
294
+ const resolver = plugin.resolver;
295
+ if (!resolver) return file;
296
+ const hasBanner = output?.banner !== void 0;
297
+ const hasFooter = output?.footer !== void 0;
298
+ if (!hasBanner && !hasFooter) return file;
299
+ const context = {
300
+ output,
301
+ config,
302
+ file: {
303
+ path: file.path,
304
+ baseName: file.baseName,
305
+ isBarrel: true
306
+ }
307
+ };
308
+ return {
309
+ ...file,
310
+ banner: hasBanner ? resolver.resolveBanner(void 0, context) : file.banner,
311
+ footer: hasFooter ? resolver.resolveFooter(void 0, context) : file.footer
312
+ };
313
+ }
314
+ /**
315
+ * Canonical middleware name for `@kubb/middleware-barrel`. Used for driver
316
+ * lookups.
317
+ */
318
+ const middlewareBarrelName = "middleware-barrel";
319
+ /**
320
+ * Generates an `index.ts` for every plugin output directory and one root
321
+ * barrel at `config.output.path/index.ts` after the build completes. Ships
322
+ * with Kubb and is registered by default in `defineConfig`.
323
+ *
324
+ * Each plugin inherits `output.barrel` from `config.output.barrel` (which
325
+ * defaults to `{ type: 'named' }`). Set `barrel: false` on a plugin to skip
326
+ * its barrel and also exclude its files from the root barrel.
327
+ *
328
+ * A plugin with `output.mode: 'file'` gets no per-plugin barrel, since its output
329
+ * is a single file. The root barrel re-exports that file directly.
286
330
  *
287
331
  * @example
288
332
  * ```ts
289
333
  * import { defineConfig } from '@kubb/core'
290
334
  * import { middlewareBarrel } from '@kubb/middleware-barrel'
335
+ * import { pluginTs } from '@kubb/plugin-ts'
336
+ * import { pluginZod } from '@kubb/plugin-zod'
291
337
  *
292
338
  * export default defineConfig({
339
+ * input: { path: './petStore.yaml' },
293
340
  * output: { path: 'src/gen', barrel: { type: 'named' } },
294
341
  * plugins: [
295
342
  * pluginTs({ output: { path: 'types', barrel: { type: 'all' } } }),
@@ -299,10 +346,6 @@ function getBarrelFiles({ outputPath, files, barrelType, nested = false, recursi
299
346
  * })
300
347
  * ```
301
348
  */
302
- /**
303
- * Stable string identifier for the barrel middleware.
304
- */
305
- const middlewareBarrelName = "middleware-barrel";
306
349
  const middlewareBarrel = (0, _kubb_core.defineMiddleware)(() => {
307
350
  const excludedPrefixes = /* @__PURE__ */ new Set();
308
351
  return {
@@ -312,31 +355,36 @@ const middlewareBarrel = (0, _kubb_core.defineMiddleware)(() => {
312
355
  const pluginBarrel = plugin.options.output?.barrel;
313
356
  const configBarrel = config.output.barrel;
314
357
  const defaultBarrel = { type: "named" };
315
- let barrelConfig;
316
- if (pluginBarrel !== void 0) barrelConfig = pluginBarrel;
317
- else if (configBarrel !== void 0) barrelConfig = configBarrel === false ? false : {
318
- ...configBarrel,
319
- nested: false
320
- };
321
- else barrelConfig = defaultBarrel;
358
+ const barrelConfig = (() => {
359
+ if (pluginBarrel !== void 0) return pluginBarrel;
360
+ if (configBarrel !== void 0) return configBarrel === false ? false : {
361
+ ...configBarrel,
362
+ nested: false
363
+ };
364
+ return defaultBarrel;
365
+ })();
322
366
  if (barrelConfig === false) {
323
367
  excludedPrefixes.add(getPluginOutputPrefix(plugin, config));
324
368
  return;
325
369
  }
370
+ if (plugin.options.output.mode === "file") return;
326
371
  const barrelType = barrelConfig.type;
327
372
  const nested = barrelConfig.nested ?? false;
328
373
  const base = (0, node_path.resolve)(config.root, config.output.path);
329
374
  const target = (0, node_path.resolve)(base, plugin.options.output.path);
330
375
  const relative = node_path.default.relative(base, target);
331
376
  if (relative.startsWith("..") || node_path.default.isAbsolute(relative)) throw new Error("Invalid output path");
332
- const barrelFiles = getBarrelFiles({
377
+ for (const file of getBarrelFiles({
333
378
  outputPath: target,
334
379
  files,
335
380
  barrelType,
336
381
  nested,
337
382
  recursive: true
338
- });
339
- if (barrelFiles.length > 0) upsertFile(...barrelFiles);
383
+ })) upsertFile(withBarrelBannerFooter({
384
+ file,
385
+ plugin,
386
+ config
387
+ }));
340
388
  },
341
389
  "kubb:plugins:end"({ files, config, upsertFile }) {
342
390
  const barrelConfig = config.output.barrel ?? { type: "named" };
@@ -344,12 +392,11 @@ const middlewareBarrel = (0, _kubb_core.defineMiddleware)(() => {
344
392
  excludedPrefixes.clear();
345
393
  if (barrelConfig === false) return;
346
394
  const barrelType = barrelConfig.type;
347
- const rootBarrelFiles = getBarrelFiles({
395
+ for (const file of getBarrelFiles({
348
396
  outputPath: (0, node_path.resolve)(config.root, config.output.path),
349
397
  files: filteredFiles,
350
398
  barrelType
351
- });
352
- if (rootBarrelFiles.length > 0) upsertFile(...rootBarrelFiles);
399
+ })) upsertFile(file);
353
400
  }
354
401
  }
355
402
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["path"],"sources":["../../../internals/utils/src/path.ts","../../../internals/utils/src/buildTree.ts","../src/utils/excludedPaths.ts","../src/constants.ts","../src/utils/getBarrelFiles.ts","../src/middleware.ts"],"sourcesContent":["/**\n * Converts a filesystem path to use POSIX (`/`) separators.\n *\n * Most of the codebase compares and composes paths as strings (prefix matching, joining for\n * import specifiers, splitting on `/`). On POSIX `path.resolve` already returns `/`-separated\n * paths, but on Windows it returns `\\`-separated paths, which breaks every such comparison.\n *\n * Routing every path that crosses a module boundary through `toPosixPath` keeps the rest of the\n * code platform-agnostic. The conversion runs unconditionally so Windows-specific behavior is\n * exercisable from POSIX CI.\n *\n * @example\n * toPosixPath('C:\\\\repo\\\\src\\\\pet.ts') // 'C:/repo/src/pet.ts'\n */\nexport function toPosixPath(filePath: string): string {\n return filePath.replaceAll('\\\\', '/')\n}\n","import { toPosixPath } from './path.ts'\n\n/**\n * A node in the directory tree used to compute barrel file exports.\n * Either represents a directory (with `children`) or a file (`isFile: true`, empty `children`).\n */\nexport type BuildTree = {\n /**\n * Absolute filesystem path of this directory or file. Always normalized to POSIX (`/`) separators.\n */\n path: string\n /**\n * Sub-directories and files contained within this directory.\n * Always empty for file nodes.\n */\n children: Array<BuildTree>\n /**\n * `true` when this node represents a file (leaf), `false` for directory nodes.\n */\n isFile: boolean\n}\n\n/**\n * Builds a directory tree rooted at `rootPath` from a list of absolute file paths.\n * Paths outside `rootPath` are silently ignored. Children are sorted alphabetically\n * by path so consumers (barrel exports, propagated indexes) emit a deterministic order.\n *\n * Both POSIX (`/`) and Windows (`\\`) separators are accepted in input paths; emitted node\n * paths are always POSIX-normalized so downstream prefix/lookup operations behave the same\n * across platforms.\n *\n * @example\n * ```ts\n * buildTree('/src/gen/types', [\n * '/src/gen/types/pet.ts',\n * '/src/gen/types/pets/listPets.ts',\n * ])\n * ```\n */\nexport function buildTree(rootPath: string, filePaths: ReadonlyArray<string>): BuildTree {\n const normalizedRoot = toPosixPath(rootPath)\n const root: BuildTree = { path: normalizedRoot, children: [], isFile: false }\n // Per-directory child lookup avoids the O(N) `Array.find` scan during insertion.\n const childIndex = new Map<BuildTree, Map<string, BuildTree>>()\n childIndex.set(root, new Map())\n\n const rootPrefix = `${normalizedRoot}/`\n\n for (const filePath of filePaths) {\n const normalized = toPosixPath(filePath)\n if (!normalized.startsWith(rootPrefix)) continue\n\n const parts = normalized.slice(rootPrefix.length).split('/')\n if (parts.length === 0) continue\n\n let current = root\n const lastIndex = parts.length - 1\n for (const [i, part] of parts.entries()) {\n if (!part) continue\n\n const isLast = i === lastIndex\n const siblings = childIndex.get(current)!\n let child = siblings.get(part)\n if (!child) {\n child = { path: `${current.path}/${part}`, children: [], isFile: isLast }\n current.children.push(child)\n siblings.set(part, child)\n if (!isLast) childIndex.set(child, new Map())\n }\n current = child\n }\n }\n\n sortTree(root)\n\n return root\n}\n\nfunction sortTree(node: BuildTree): void {\n if (node.children.length === 0) return\n node.children.sort(compareByPath)\n for (const child of node.children) {\n if (!child.isFile) sortTree(child)\n }\n}\n\nfunction compareByPath(a: BuildTree, b: BuildTree): number {\n return a.path < b.path ? -1 : a.path > b.path ? 1 : 0\n}\n","import { resolve } from 'node:path'\nimport type { Config, NormalizedPlugin } from '@kubb/core'\nimport { toPosixPath } from '@internals/utils'\n\n/**\n * Builds a POSIX-normalized prefix for a plugin's output directory, with a trailing `/`.\n *\n * Used to detect (and later exclude) files generated by plugins that opted out of the root barrel.\n */\nexport function getPluginOutputPrefix(plugin: NormalizedPlugin, config: Config): string {\n return `${toPosixPath(resolve(config.root, config.output.path, plugin.options.output.path))}/`\n}\n\n/**\n * Returns `true` when `filePath` lives under any of the given excluded directory prefixes.\n *\n * Both sides are POSIX-normalized so Windows backslash paths match correctly.\n */\nexport function isExcludedPath(filePath: string, prefixes: ReadonlySet<string>): boolean {\n const normalized = toPosixPath(filePath)\n return prefixes.values().some((prefix) => normalized.startsWith(prefix))\n}\n","/**\n * Full file name for barrel files (with extension).\n */\nexport const BARREL_FILENAME = 'index.ts' as const\n","import { extname } from 'node:path'\nimport { createExport, createFile } from '@kubb/ast'\nimport type { ExportNode, FileNode, SourceNode } from '@kubb/ast'\nimport { BARREL_FILENAME } from '../constants.ts'\nimport type { BarrelType } from '../types.ts'\nimport { type BuildTree, buildTree, toPosixPath } from '@internals/utils'\n\nconst SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx'])\nconst BARREL_SUFFIX = `/${BARREL_FILENAME}`\n\nfunction toRelativeModulePath(fromDir: string, filePath: string): string {\n return `./${filePath.slice(fromDir.length + 1)}`\n}\n\nfunction isBarrelPath(path: string): boolean {\n return path.endsWith(BARREL_SUFFIX)\n}\n\nfunction makeBarrel(dirPath: string, exports: Array<ExportNode>): FileNode {\n return createFile({\n baseName: BARREL_FILENAME,\n path: `${dirPath}${BARREL_SUFFIX}`,\n exports,\n sources: [],\n imports: [],\n // Barrel files must never carry a banner or footer: they only re-export\n // symbols and adding a directive like \"use server\" would break consumers.\n banner: undefined,\n footer: undefined,\n })\n}\n\ntype LeafContext = {\n dirPath: string\n leafPath: string\n sourceFile: FileNode | undefined\n}\n\ntype LeafStrategy = (ctx: LeafContext) => Array<ExportNode>\n\nfunction hasOnlyNonIndexableSources(sources: ReadonlyArray<SourceNode>): boolean {\n if (sources.length === 0) return false\n for (const source of sources) {\n if (source.isIndexable) return false\n }\n return true\n}\n\nfunction partitionIndexableNames(sources: ReadonlyArray<SourceNode>): Map<boolean, Set<string>> {\n const byTypeOnly = new Map<boolean, Set<string>>([\n [false, new Set()],\n [true, new Set()],\n ])\n for (const source of sources) {\n if (!source.isIndexable || !source.name) continue\n byTypeOnly.get(Boolean(source.isTypeOnly))!.add(source.name)\n }\n return byTypeOnly\n}\n\nconst allStrategy: LeafStrategy = ({ dirPath, leafPath, sourceFile }) => {\n if (sourceFile && hasOnlyNonIndexableSources(sourceFile.sources)) return []\n return [createExport({ path: toRelativeModulePath(dirPath, leafPath) })]\n}\n\nconst namedStrategy: LeafStrategy = ({ dirPath, leafPath, sourceFile }) => {\n const modulePath = toRelativeModulePath(dirPath, leafPath)\n\n if (!sourceFile) return [createExport({ path: modulePath })]\n\n const namesByTypeOnly = partitionIndexableNames(sourceFile.sources)\n const valueNames = namesByTypeOnly.get(false)!\n const typeNames = namesByTypeOnly.get(true)!\n\n if (valueNames.size === 0 && typeNames.size === 0) {\n if (sourceFile.sources.length > 0) return []\n return [createExport({ path: modulePath })]\n }\n\n const exports: Array<ExportNode> = []\n if (valueNames.size > 0) {\n exports.push(createExport({ name: [...valueNames].sort(), path: modulePath }))\n }\n if (typeNames.size > 0) {\n exports.push(createExport({ name: [...typeNames].sort(), path: modulePath, isTypeOnly: true }))\n }\n return exports\n}\n\nconst LEAF_STRATEGIES: ReadonlyMap<BarrelType, LeafStrategy> = new Map([\n ['all', allStrategy],\n ['named', namedStrategy],\n])\n\ntype LeafWalkParams = {\n sourceFiles: ReadonlyMap<string, FileNode>\n strategy: LeafStrategy\n recursive: boolean\n}\n\n/**\n * Post-order walk that emits a barrel per visited directory.\n */\nfunction walkAllOrNamed(node: BuildTree, params: LeafWalkParams, isRoot: boolean, out: Array<FileNode>): Array<string> {\n const subtreeLeaves: Array<string> = []\n\n for (const child of node.children) {\n if (child.isFile) {\n if (!isBarrelPath(child.path)) subtreeLeaves.push(child.path)\n continue\n }\n\n const childLeaves = walkAllOrNamed(child, params, false, out)\n for (const leaf of childLeaves) subtreeLeaves.push(leaf)\n }\n\n if (!isRoot && !params.recursive) return subtreeLeaves\n\n const exports = subtreeLeaves.flatMap((leafPath) => params.strategy({ dirPath: node.path, leafPath, sourceFile: params.sourceFiles.get(leafPath) }))\n\n if (exports.length > 0) {\n out.push(makeBarrel(node.path, exports))\n }\n\n return subtreeLeaves\n}\n\n/**\n * Recursive walk that emits one barrel per directory, re-exporting files and sub-barrels.\n * Used when nested: true.\n */\nfunction walkNested(node: BuildTree, out: Array<FileNode>): void {\n const exports: Array<ExportNode> = []\n\n for (const child of node.children) {\n if (child.isFile) {\n if (isBarrelPath(child.path)) continue\n exports.push(createExport({ path: toRelativeModulePath(node.path, child.path) }))\n continue\n }\n\n walkNested(child, out)\n exports.push(createExport({ path: toRelativeModulePath(node.path, `${child.path}${BARREL_SUFFIX}`) }))\n }\n\n if (exports.length > 0) {\n out.push(makeBarrel(node.path, exports))\n }\n}\n\ntype IndexedFiles = {\n sourceFiles: ReadonlyMap<string, FileNode>\n paths: ReadonlyArray<string>\n}\n\nfunction indexRelevantFiles(files: ReadonlyArray<FileNode>, outputPath: string): IndexedFiles {\n const outputPrefix = `${toPosixPath(outputPath)}/`\n const sourceFiles = new Map<string, FileNode>()\n const paths: Array<string> = []\n\n for (const file of files) {\n const normalized = toPosixPath(file.path)\n if (!normalized.startsWith(outputPrefix)) continue\n if (isBarrelPath(normalized)) continue\n if (!SOURCE_EXTENSIONS.has(extname(normalized))) continue\n\n sourceFiles.set(normalized, file)\n paths.push(normalized)\n }\n\n return { sourceFiles, paths }\n}\n\ntype GetBarrelFilesParams = {\n /**\n * Absolute directory the barrel(s) should be rooted at.\n * Only files living under this path are considered.\n */\n outputPath: string\n /**\n * Pool of generated files to scan for indexable sources.\n */\n files: ReadonlyArray<FileNode>\n /**\n * Export strategy used when emitting each barrel.\n * - `'all'` re-exports the whole module (`export * from './x'`)\n * - `'named'` re-exports only the indexable named symbols\n */\n barrelType: BarrelType\n /**\n * Generate an `index.ts` in every sub-directory, each re-exporting only what's directly inside it (hierarchical).\n * When false, uses flat generation strategy with optional recursive subdirectory barrels.\n *\n * @default false\n */\n nested?: boolean\n /**\n * Also generate a barrel for each sub-directory when nested is false.\n * No effect when nested is true (always generates hierarchical structure).\n *\n * @default false\n */\n recursive?: boolean\n}\n\n/**\n * Generates barrel `FileNode`s for the directory rooted at `outputPath`.\n */\nexport function getBarrelFiles({ outputPath, files, barrelType, nested = false, recursive = false }: GetBarrelFilesParams): Array<FileNode> {\n const { sourceFiles, paths } = indexRelevantFiles(files, outputPath)\n if (paths.length === 0) return []\n\n const tree = buildTree(outputPath, paths)\n const result: Array<FileNode> = []\n\n // Use nested walk for hierarchical barrel structure\n if (nested) {\n walkNested(tree, result)\n return result\n }\n\n const strategy = LEAF_STRATEGIES.get(barrelType)\n if (!strategy) return result\n\n walkAllOrNamed(tree, { sourceFiles, strategy, recursive }, true, result)\n return result\n}\n","import path from 'node:path'\nimport { resolve } from 'node:path'\nimport { defineMiddleware } from '@kubb/core'\nimport type { Middleware } from '@kubb/core'\nimport type { BarrelConfig, PluginBarrelConfig } from './types.ts'\nimport { getPluginOutputPrefix, isExcludedPath } from './utils/excludedPaths.ts'\nimport { getBarrelFiles } from './utils/getBarrelFiles.ts'\n\ndeclare global {\n namespace Kubb {\n interface PluginOptionsRegistry {\n output: {\n /**\n * Barrel configuration for this plugin's output.\n * Set to `false` to disable barrel generation for this plugin entirely; doing so also\n * excludes the plugin's files from the root barrel.\n *\n * Falls back to `config.output.barrel` when omitted.\n *\n * @default { type: 'named' }\n */\n barrel?: PluginBarrelConfig | false\n }\n }\n interface ConfigOptionsRegistry {\n output: {\n /**\n * Barrel configuration for the root barrel file at `config.output.path/index.ts`.\n * Set to `false` to disable root barrel generation. Individual plugins can override\n * this via their own `output.barrel`.\n *\n * @default { type: 'named' }\n */\n barrel?: BarrelConfig | false\n }\n }\n }\n}\n\n/**\n * Generates `index.ts` barrel files for each plugin and a root barrel at `config.output.path/index.ts`.\n *\n * Each plugin inherits `output.barrel` from `config.output.barrel` (defaults to `{ type: 'named' }`).\n * Set `barrel: false` on a plugin to disable its barrel and exclude it from the root barrel.\n *\n * @example\n * ```ts\n * import { defineConfig } from '@kubb/core'\n * import { middlewareBarrel } from '@kubb/middleware-barrel'\n *\n * export default defineConfig({\n * output: { path: 'src/gen', barrel: { type: 'named' } },\n * plugins: [\n * pluginTs({ output: { path: 'types', barrel: { type: 'all' } } }),\n * pluginZod({ output: { path: 'schemas' } }),\n * ],\n * middleware: [middlewareBarrel()],\n * })\n * ```\n */\n\n/**\n * Stable string identifier for the barrel middleware.\n */\nexport const middlewareBarrelName = 'middleware-barrel' satisfies Middleware['name']\n\nexport const middlewareBarrel = defineMiddleware(() => {\n const excludedPrefixes = new Set<string>()\n\n return {\n name: middlewareBarrelName,\n hooks: {\n 'kubb:plugin:end'({ plugin, config, files, upsertFile }) {\n const pluginBarrel = plugin.options.output?.barrel\n const configBarrel = config.output.barrel\n const defaultBarrel = { type: 'named' } as const\n\n let barrelConfig: PluginBarrelConfig | false\n if (pluginBarrel !== undefined) {\n barrelConfig = pluginBarrel\n } else if (configBarrel !== undefined) {\n // Root config barrel doesn't have nested, so we add it\n barrelConfig = configBarrel === false ? false : { ...configBarrel, nested: false }\n } else {\n barrelConfig = defaultBarrel\n }\n\n if (barrelConfig === false) {\n excludedPrefixes.add(getPluginOutputPrefix(plugin, config))\n return\n }\n\n const barrelType = barrelConfig.type\n const nested = barrelConfig.nested ?? false\n\n const base = resolve(config.root, config.output.path)\n const target = resolve(base, plugin.options.output.path)\n const relative = path.relative(base, target)\n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n throw new Error('Invalid output path')\n }\n const barrelFiles = getBarrelFiles({\n outputPath: target,\n files,\n barrelType,\n nested,\n recursive: true,\n })\n\n if (barrelFiles.length > 0) {\n upsertFile(...barrelFiles)\n }\n },\n 'kubb:plugins:end'({ files, config, upsertFile }) {\n const barrelConfig = config.output.barrel ?? { type: 'named' }\n\n const filteredFiles = excludedPrefixes.size === 0 ? files : files.filter((f) => !isExcludedPath(f.path, excludedPrefixes))\n excludedPrefixes.clear()\n\n if (barrelConfig === false) return\n\n const barrelType = barrelConfig.type\n\n const rootBarrelFiles = getBarrelFiles({\n outputPath: resolve(config.root, config.output.path),\n files: filteredFiles,\n barrelType,\n })\n\n if (rootBarrelFiles.length > 0) {\n upsertFile(...rootBarrelFiles)\n }\n },\n },\n }\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["path"],"sources":["../../../internals/utils/src/path.ts","../../../internals/utils/src/buildTree.ts","../src/utils.ts","../src/middleware.ts"],"sourcesContent":["/**\n * Converts a filesystem path to use POSIX (`/`) separators.\n *\n * Most of the codebase compares and composes paths as strings (prefix matching, joining for\n * import specifiers, splitting on `/`). On POSIX `path.resolve` already returns `/`-separated\n * paths, but on Windows it returns `\\`-separated paths, which breaks every such comparison.\n *\n * Routing every path that crosses a module boundary through `toPosixPath` keeps the rest of the\n * code platform-agnostic. The conversion runs unconditionally so Windows-specific behavior is\n * exercisable from POSIX CI.\n *\n * @example\n * toPosixPath('C:\\\\repo\\\\src\\\\pet.ts') // 'C:/repo/src/pet.ts'\n */\nexport function toPosixPath(filePath: string): string {\n return filePath.replaceAll('\\\\', '/')\n}\n","import { toPosixPath } from './path.ts'\n\n/**\n * A node in the directory tree used to compute barrel file exports.\n * Either represents a directory (with `children`) or a file (`isFile: true`, empty `children`).\n */\nexport type BuildTree = {\n /**\n * Absolute filesystem path of this directory or file. Always normalized to POSIX (`/`) separators.\n */\n path: string\n /**\n * Sub-directories and files contained within this directory.\n * Always empty for file nodes.\n */\n children: Array<BuildTree>\n /**\n * `true` when this node represents a file (leaf), `false` for directory nodes.\n */\n isFile: boolean\n}\n\n/**\n * Builds a directory tree rooted at `rootPath` from a list of absolute file paths.\n * Paths outside `rootPath` are silently ignored. Children are sorted alphabetically\n * by path so consumers (barrel exports, propagated indexes) emit a deterministic order.\n *\n * Both POSIX (`/`) and Windows (`\\`) separators are accepted in input paths; emitted node\n * paths are always POSIX-normalized so downstream prefix/lookup operations behave the same\n * across platforms.\n *\n * @example\n * ```ts\n * buildTree('/src/gen/types', [\n * '/src/gen/types/pet.ts',\n * '/src/gen/types/pets/listPets.ts',\n * ])\n * ```\n */\nexport function buildTree(rootPath: string, filePaths: ReadonlyArray<string>): BuildTree {\n const normalizedRoot = toPosixPath(rootPath)\n const root: BuildTree = { path: normalizedRoot, children: [], isFile: false }\n // Per-directory child lookup avoids the O(N) `Array.find` scan during insertion.\n // WeakMap keyed by object identity so directory nodes are GC-eligible once the tree is discarded.\n const childIndex = new WeakMap<BuildTree, Map<string, BuildTree>>()\n childIndex.set(root, new Map())\n\n const rootPrefix = `${normalizedRoot}/`\n\n for (const filePath of filePaths) {\n const normalized = toPosixPath(filePath)\n if (!normalized.startsWith(rootPrefix)) continue\n\n const parts = normalized.slice(rootPrefix.length).split('/')\n if (parts.length === 0) continue\n\n let current = root\n const lastIndex = parts.length - 1\n for (const [i, part] of parts.entries()) {\n if (!part) continue\n\n const isLast = i === lastIndex\n const siblings = childIndex.get(current)!\n let child = siblings.get(part)\n if (!child) {\n child = { path: `${current.path}/${part}`, children: [], isFile: isLast }\n current.children.push(child)\n siblings.set(part, child)\n if (!isLast) childIndex.set(child, new Map())\n }\n current = child\n }\n }\n\n sortTree(root)\n\n return root\n}\n\nfunction sortTree(node: BuildTree): void {\n if (node.children.length === 0) return\n node.children.sort(compareByPath)\n for (const child of node.children) {\n if (!child.isFile) sortTree(child)\n }\n}\n\nfunction compareByPath(a: BuildTree, b: BuildTree): number {\n return a.path < b.path ? -1 : a.path > b.path ? 1 : 0\n}\n","import { extname, resolve } from 'node:path'\nimport { createExport, createFile } from '@kubb/ast'\nimport type { ExportNode, FileNode, SourceNode } from '@kubb/ast'\nimport type { Config, NormalizedPlugin } from '@kubb/core'\nimport { type BuildTree, buildTree, toPosixPath } from '@internals/utils'\nimport type { BarrelType } from './types.ts'\n\nconst SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx'])\nconst BARREL_SUFFIX = `/index.ts`\n\nfunction toRelativeModulePath(fromDir: string, filePath: string): string {\n return `./${filePath.slice(fromDir.length + 1)}`\n}\n\nfunction isBarrelPath(path: string): boolean {\n return path.endsWith(BARREL_SUFFIX)\n}\n\nfunction makeBarrel(dirPath: string, exports: Array<ExportNode>): FileNode {\n return createFile({\n baseName: 'index.ts',\n path: `${dirPath}${BARREL_SUFFIX}`,\n exports,\n sources: [],\n imports: [],\n // Default to no banner/footer. The middleware resolves a configured plugin\n // banner/footer (with isBarrel: true) afterwards, so a `banner` function can\n // decide per file whether a barrel should carry a directive like \"use server\".\n banner: undefined,\n footer: undefined,\n })\n}\n\ntype LeafContext = {\n dirPath: string\n leafPath: string\n sourceFile: FileNode | null\n}\n\ntype LeafStrategy = (ctx: LeafContext) => Array<ExportNode>\n\nfunction hasOnlyNonIndexableSources(sources: ReadonlyArray<SourceNode>): boolean {\n if (sources.length === 0) return false\n for (const source of sources) {\n if (source.isIndexable) return false\n }\n return true\n}\n\nfunction partitionIndexableNames(sources: ReadonlyArray<SourceNode>): Map<boolean, Set<string>> {\n const byTypeOnly = new Map<boolean, Set<string>>([\n [false, new Set()],\n [true, new Set()],\n ])\n for (const source of sources) {\n if (!source.isIndexable || !source.name) continue\n byTypeOnly.get(Boolean(source.isTypeOnly))!.add(source.name)\n }\n return byTypeOnly\n}\n\nconst allStrategy: LeafStrategy = ({ dirPath, leafPath, sourceFile }) => {\n if (sourceFile && hasOnlyNonIndexableSources(sourceFile.sources)) return []\n return [createExport({ path: toRelativeModulePath(dirPath, leafPath) })]\n}\n\nconst namedStrategy: LeafStrategy = ({ dirPath, leafPath, sourceFile }) => {\n const modulePath = toRelativeModulePath(dirPath, leafPath)\n\n if (!sourceFile) return [createExport({ path: modulePath })]\n\n const namesByTypeOnly = partitionIndexableNames(sourceFile.sources)\n const valueNames = namesByTypeOnly.get(false)!\n const typeNames = namesByTypeOnly.get(true)!\n\n if (valueNames.size === 0 && typeNames.size === 0) {\n if (sourceFile.sources.length > 0) return []\n return [createExport({ path: modulePath })]\n }\n\n const exports: Array<ExportNode> = []\n if (valueNames.size > 0) {\n exports.push(createExport({ name: [...valueNames].sort(), path: modulePath }))\n }\n if (typeNames.size > 0) {\n exports.push(createExport({ name: [...typeNames].sort(), path: modulePath, isTypeOnly: true }))\n }\n return exports\n}\n\nconst LEAF_STRATEGIES: ReadonlyMap<BarrelType, LeafStrategy> = new Map([\n ['all', allStrategy],\n ['named', namedStrategy],\n])\n\ntype LeafWalkParams = {\n sourceFiles: ReadonlyMap<string, FileNode>\n strategy: LeafStrategy\n recursive: boolean\n}\n\n/**\n * Post-order walk that yields a barrel per visited directory.\n * Returns the list of leaf file paths collected in this subtree (used by the parent call).\n */\nfunction* walkAllOrNamed(node: BuildTree, params: LeafWalkParams, isRoot: boolean): Generator<FileNode, Array<string>> {\n const subtreeLeaves: Array<string> = []\n\n for (const child of node.children) {\n if (child.isFile) {\n if (!isBarrelPath(child.path)) subtreeLeaves.push(child.path)\n continue\n }\n\n const childLeaves = yield* walkAllOrNamed(child, params, false)\n for (const leaf of childLeaves) subtreeLeaves.push(leaf)\n }\n\n if (!isRoot && !params.recursive) return subtreeLeaves\n\n const exports = subtreeLeaves.flatMap((leafPath) => params.strategy({ dirPath: node.path, leafPath, sourceFile: params.sourceFiles.get(leafPath) ?? null }))\n\n if (exports.length > 0) {\n yield makeBarrel(node.path, exports)\n }\n\n return subtreeLeaves\n}\n\n/**\n * Recursive walk that yields one barrel per directory, re-exporting files and sub-barrels.\n * Used when nested: true.\n */\nfunction* walkNested(node: BuildTree): Generator<FileNode> {\n const exports: Array<ExportNode> = []\n\n for (const child of node.children) {\n if (child.isFile) {\n if (isBarrelPath(child.path)) continue\n exports.push(createExport({ path: toRelativeModulePath(node.path, child.path) }))\n continue\n }\n\n yield* walkNested(child)\n exports.push(createExport({ path: toRelativeModulePath(node.path, `${child.path}${BARREL_SUFFIX}`) }))\n }\n\n if (exports.length > 0) {\n yield makeBarrel(node.path, exports)\n }\n}\n\ntype IndexedFiles = {\n sourceFiles: ReadonlyMap<string, FileNode>\n paths: ReadonlyArray<string>\n}\n\nfunction indexRelevantFiles(files: ReadonlyArray<FileNode>, outputPath: string): IndexedFiles {\n const outputPrefix = `${toPosixPath(outputPath)}/`\n const sourceFiles = new Map<string, FileNode>()\n const paths: Array<string> = []\n\n for (const file of files) {\n const normalized = toPosixPath(file.path)\n if (!normalized.startsWith(outputPrefix)) continue\n if (isBarrelPath(normalized)) continue\n if (!SOURCE_EXTENSIONS.has(extname(normalized))) continue\n\n sourceFiles.set(normalized, file)\n paths.push(normalized)\n }\n\n return { sourceFiles, paths }\n}\n\ntype GetBarrelFilesParams = {\n /**\n * Absolute directory the barrel(s) should be rooted at.\n * Only files living under this path are considered.\n */\n outputPath: string\n /**\n * Pool of generated files to scan for indexable sources.\n */\n files: ReadonlyArray<FileNode>\n /**\n * Export strategy used when emitting each barrel.\n * - `'all'` re-exports the whole module (`export * from './x'`)\n * - `'named'` re-exports only the indexable named symbols\n */\n barrelType: BarrelType\n /**\n * Generate an `index.ts` in every sub-directory, each re-exporting only what's directly inside it (hierarchical).\n * When false, uses flat generation strategy with optional recursive subdirectory barrels.\n *\n * @default false\n */\n nested?: boolean\n /**\n * Also generate a barrel for each sub-directory when nested is false.\n * No effect when nested is true (always generates hierarchical structure).\n *\n * @default false\n */\n recursive?: boolean\n}\n\n/**\n * Yields barrel `FileNode`s for the directory rooted at `outputPath`.\n *\n * @example\n * ```ts\n * for (const file of getBarrelFiles({ outputPath, files, barrelType })) {\n * upsertFile(file)\n * }\n * // or collect into an array\n * const barrels = [...getBarrelFiles({ outputPath, files, barrelType })]\n * ```\n */\nexport function* getBarrelFiles({ outputPath, files, barrelType, nested = false, recursive = false }: GetBarrelFilesParams): Generator<FileNode> {\n const { sourceFiles, paths } = indexRelevantFiles(files, outputPath)\n if (paths.length === 0) return\n\n const tree = buildTree(outputPath, paths)\n\n if (nested) {\n yield* walkNested(tree)\n return\n }\n\n const strategy = LEAF_STRATEGIES.get(barrelType)\n if (!strategy) return\n\n yield* walkAllOrNamed(tree, { sourceFiles, strategy, recursive }, true)\n}\n\n/**\n * Builds a POSIX-normalized prefix for a plugin's output. A directory output gets a trailing `/`,\n * while a `mode: 'file'` output (the path is the file itself) gets the exact path with no trailing `/`.\n *\n * Used to detect (and later exclude) files generated by plugins that opted out of the root barrel.\n */\nexport function getPluginOutputPrefix(plugin: NormalizedPlugin, config: Config): string {\n const resolved = toPosixPath(resolve(config.root, config.output.path, plugin.options.output.path))\n return plugin.options.output.mode === 'file' ? resolved : `${resolved}/`\n}\n\n/**\n * Returns `true` when `filePath` lives under any of the given excluded prefixes. A prefix with a\n * trailing `/` matches a directory subtree, and a prefix without one matches that exact file\n * (used for `mode: 'file'` outputs).\n *\n * Both sides are POSIX-normalized so Windows backslash paths match correctly.\n */\nexport function isExcludedPath(filePath: string, prefixes: ReadonlySet<string>): boolean {\n const normalized = toPosixPath(filePath)\n return prefixes.values().some((prefix) => (prefix.endsWith('/') ? normalized.startsWith(prefix) : normalized === prefix))\n}\n","import path from 'node:path'\nimport { resolve } from 'node:path'\nimport type { FileNode } from '@kubb/ast'\nimport { defineMiddleware } from '@kubb/core'\nimport type { Config, Middleware, NormalizedPlugin } from '@kubb/core'\nimport type { BarrelConfig, PluginBarrelConfig } from './types.ts'\nimport { getBarrelFiles, getPluginOutputPrefix, isExcludedPath } from './utils.ts'\n\n/**\n * Applies a plugin's configured `output.banner`/`footer` to a barrel file, flagged as `isBarrel`.\n *\n * Resolves through the plugin's own resolver, and only when the plugin explicitly sets a\n * banner/footer, so barrels stay banner-free by default and never inherit the implicit\n * \"Generated by Kubb\" notice.\n */\nfunction withBarrelBannerFooter({ file, plugin, config }: { file: FileNode; plugin: NormalizedPlugin; config: Config }): FileNode {\n const output = plugin.options?.output\n const resolver = plugin.resolver\n if (!resolver) return file\n\n const hasBanner = output?.banner !== undefined\n const hasFooter = output?.footer !== undefined\n if (!hasBanner && !hasFooter) return file\n\n const context = { output, config, file: { path: file.path, baseName: file.baseName, isBarrel: true } }\n return {\n ...file,\n banner: hasBanner ? resolver.resolveBanner(undefined, context) : file.banner,\n footer: hasFooter ? resolver.resolveFooter(undefined, context) : file.footer,\n }\n}\n\ndeclare global {\n namespace Kubb {\n interface PluginOptionsRegistry {\n output: {\n /**\n * Barrel configuration for this plugin's output.\n * Set to `false` to disable barrel generation for this plugin entirely. Doing so also\n * excludes the plugin's files from the root barrel.\n *\n * Falls back to `config.output.barrel` when omitted.\n *\n * @default { type: 'named' }\n */\n barrel?: PluginBarrelConfig | false\n }\n }\n interface ConfigOptionsRegistry {\n output: {\n /**\n * Barrel configuration for the root barrel file at `config.output.path/index.ts`.\n * Set to `false` to disable root barrel generation. Individual plugins can override\n * this via their own `output.barrel`.\n *\n * @default { type: 'named' }\n */\n barrel?: BarrelConfig | false\n }\n }\n }\n}\n\n/**\n * Canonical middleware name for `@kubb/middleware-barrel`. Used for driver\n * lookups.\n */\nexport const middlewareBarrelName = 'middleware-barrel' satisfies Middleware['name']\n\n/**\n * Generates an `index.ts` for every plugin output directory and one root\n * barrel at `config.output.path/index.ts` after the build completes. Ships\n * with Kubb and is registered by default in `defineConfig`.\n *\n * Each plugin inherits `output.barrel` from `config.output.barrel` (which\n * defaults to `{ type: 'named' }`). Set `barrel: false` on a plugin to skip\n * its barrel and also exclude its files from the root barrel.\n *\n * A plugin with `output.mode: 'file'` gets no per-plugin barrel, since its output\n * is a single file. The root barrel re-exports that file directly.\n *\n * @example\n * ```ts\n * import { defineConfig } from '@kubb/core'\n * import { middlewareBarrel } from '@kubb/middleware-barrel'\n * import { pluginTs } from '@kubb/plugin-ts'\n * import { pluginZod } from '@kubb/plugin-zod'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: 'src/gen', barrel: { type: 'named' } },\n * plugins: [\n * pluginTs({ output: { path: 'types', barrel: { type: 'all' } } }),\n * pluginZod({ output: { path: 'schemas' } }),\n * ],\n * middleware: [middlewareBarrel()],\n * })\n * ```\n */\nexport const middlewareBarrel = defineMiddleware(() => {\n const excludedPrefixes = new Set<string>()\n\n return {\n name: middlewareBarrelName,\n hooks: {\n 'kubb:plugin:end'({ plugin, config, files, upsertFile }) {\n const pluginBarrel = plugin.options.output?.barrel\n const configBarrel = config.output.barrel\n const defaultBarrel = { type: 'named' } as const\n\n // Root config barrel doesn't have nested, so we add it\n const barrelConfig: PluginBarrelConfig | false = (() => {\n if (pluginBarrel !== undefined) return pluginBarrel\n if (configBarrel !== undefined) return configBarrel === false ? false : { ...configBarrel, nested: false }\n return defaultBarrel\n })()\n\n if (barrelConfig === false) {\n excludedPrefixes.add(getPluginOutputPrefix(plugin, config))\n return\n }\n\n // `mode: 'file'` writes a single file, so there is no directory to barrel. The root barrel\n // re-exports that file as a direct leaf of `config.output.path`.\n if (plugin.options.output.mode === 'file') {\n return\n }\n\n const barrelType = barrelConfig.type\n const nested = barrelConfig.nested ?? false\n\n const base = resolve(config.root, config.output.path)\n const target = resolve(base, plugin.options.output.path)\n const relative = path.relative(base, target)\n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n throw new Error('Invalid output path')\n }\n for (const file of getBarrelFiles({ outputPath: target, files, barrelType, nested, recursive: true })) {\n upsertFile(withBarrelBannerFooter({ file, plugin, config }))\n }\n },\n 'kubb:plugins:end'({ files, config, upsertFile }) {\n const barrelConfig = config.output.barrel ?? { type: 'named' }\n\n const filteredFiles = excludedPrefixes.size === 0 ? files : files.filter((f) => !isExcludedPath(f.path, excludedPrefixes))\n excludedPrefixes.clear()\n\n if (barrelConfig === false) return\n\n const barrelType = barrelConfig.type\n\n for (const file of getBarrelFiles({ outputPath: resolve(config.root, config.output.path), files: filteredFiles, barrelType })) {\n upsertFile(file)\n }\n },\n },\n }\n})\n"],"mappings":"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"}