@kubb/middleware-barrel 5.0.0-beta.22 → 5.0.0-beta.24
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 +14 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +14 -7
- package/dist/index.js +14 -7
- package/dist/index.js.map +1 -1
- package/extension.yaml +36 -29
- package/package.json +3 -3
- package/src/middleware.ts +15 -9
package/dist/index.cjs
CHANGED
|
@@ -279,17 +279,28 @@ function isExcludedPath(filePath, prefixes) {
|
|
|
279
279
|
//#endregion
|
|
280
280
|
//#region src/middleware.ts
|
|
281
281
|
/**
|
|
282
|
-
*
|
|
282
|
+
* Canonical middleware name for `@kubb/middleware-barrel`. Used for driver
|
|
283
|
+
* lookups.
|
|
284
|
+
*/
|
|
285
|
+
const middlewareBarrelName = "middleware-barrel";
|
|
286
|
+
/**
|
|
287
|
+
* Generates an `index.ts` for every plugin output directory and one root
|
|
288
|
+
* barrel at `config.output.path/index.ts` after the build completes. Ships
|
|
289
|
+
* with Kubb and is registered by default in `defineConfig`.
|
|
283
290
|
*
|
|
284
|
-
* Each plugin inherits `output.barrel` from `config.output.barrel` (
|
|
285
|
-
* Set `barrel: false` on a plugin to
|
|
291
|
+
* Each plugin inherits `output.barrel` from `config.output.barrel` (which
|
|
292
|
+
* defaults to `{ type: 'named' }`). Set `barrel: false` on a plugin to skip
|
|
293
|
+
* its barrel and also exclude its files from the root barrel.
|
|
286
294
|
*
|
|
287
295
|
* @example
|
|
288
296
|
* ```ts
|
|
289
297
|
* import { defineConfig } from '@kubb/core'
|
|
290
298
|
* import { middlewareBarrel } from '@kubb/middleware-barrel'
|
|
299
|
+
* import { pluginTs } from '@kubb/plugin-ts'
|
|
300
|
+
* import { pluginZod } from '@kubb/plugin-zod'
|
|
291
301
|
*
|
|
292
302
|
* export default defineConfig({
|
|
303
|
+
* input: { path: './petStore.yaml' },
|
|
293
304
|
* output: { path: 'src/gen', barrel: { type: 'named' } },
|
|
294
305
|
* plugins: [
|
|
295
306
|
* pluginTs({ output: { path: 'types', barrel: { type: 'all' } } }),
|
|
@@ -299,10 +310,6 @@ function isExcludedPath(filePath, prefixes) {
|
|
|
299
310
|
* })
|
|
300
311
|
* ```
|
|
301
312
|
*/
|
|
302
|
-
/**
|
|
303
|
-
* Stable string identifier for the barrel middleware.
|
|
304
|
-
*/
|
|
305
|
-
const middlewareBarrelName = "middleware-barrel";
|
|
306
313
|
const middlewareBarrel = (0, _kubb_core.defineMiddleware)(() => {
|
|
307
314
|
const excludedPrefixes = /* @__PURE__ */ new Set();
|
|
308
315
|
return {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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 // 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 | 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, 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 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","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 { getBarrelFiles, getPluginOutputPrefix, isExcludedPath } from './utils.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 // 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 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(file)\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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"}
|
|
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 // 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 | 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, 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 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","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 { getBarrelFiles, getPluginOutputPrefix, isExcludedPath } from './utils.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 * 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 * @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 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(file)\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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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -87,17 +87,28 @@ declare global {
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
|
-
*
|
|
90
|
+
* Canonical middleware name for `@kubb/middleware-barrel`. Used for driver
|
|
91
|
+
* lookups.
|
|
92
|
+
*/
|
|
93
|
+
declare const middlewareBarrelName = "middleware-barrel";
|
|
94
|
+
/**
|
|
95
|
+
* Generates an `index.ts` for every plugin output directory and one root
|
|
96
|
+
* barrel at `config.output.path/index.ts` after the build completes. Ships
|
|
97
|
+
* with Kubb and is registered by default in `defineConfig`.
|
|
91
98
|
*
|
|
92
|
-
* Each plugin inherits `output.barrel` from `config.output.barrel` (
|
|
93
|
-
* Set `barrel: false` on a plugin to
|
|
99
|
+
* Each plugin inherits `output.barrel` from `config.output.barrel` (which
|
|
100
|
+
* defaults to `{ type: 'named' }`). Set `barrel: false` on a plugin to skip
|
|
101
|
+
* its barrel and also exclude its files from the root barrel.
|
|
94
102
|
*
|
|
95
103
|
* @example
|
|
96
104
|
* ```ts
|
|
97
105
|
* import { defineConfig } from '@kubb/core'
|
|
98
106
|
* import { middlewareBarrel } from '@kubb/middleware-barrel'
|
|
107
|
+
* import { pluginTs } from '@kubb/plugin-ts'
|
|
108
|
+
* import { pluginZod } from '@kubb/plugin-zod'
|
|
99
109
|
*
|
|
100
110
|
* export default defineConfig({
|
|
111
|
+
* input: { path: './petStore.yaml' },
|
|
101
112
|
* output: { path: 'src/gen', barrel: { type: 'named' } },
|
|
102
113
|
* plugins: [
|
|
103
114
|
* pluginTs({ output: { path: 'types', barrel: { type: 'all' } } }),
|
|
@@ -107,10 +118,6 @@ declare global {
|
|
|
107
118
|
* })
|
|
108
119
|
* ```
|
|
109
120
|
*/
|
|
110
|
-
/**
|
|
111
|
-
* Stable string identifier for the barrel middleware.
|
|
112
|
-
*/
|
|
113
|
-
declare const middlewareBarrelName = "middleware-barrel";
|
|
114
121
|
declare const middlewareBarrel: (options?: object | undefined) => Middleware;
|
|
115
122
|
//#endregion
|
|
116
123
|
export { type BarrelConfig, type BarrelType, type PluginBarrelConfig, middlewareBarrel, middlewareBarrelName };
|
package/dist/index.js
CHANGED
|
@@ -256,17 +256,28 @@ function isExcludedPath(filePath, prefixes) {
|
|
|
256
256
|
//#endregion
|
|
257
257
|
//#region src/middleware.ts
|
|
258
258
|
/**
|
|
259
|
-
*
|
|
259
|
+
* Canonical middleware name for `@kubb/middleware-barrel`. Used for driver
|
|
260
|
+
* lookups.
|
|
261
|
+
*/
|
|
262
|
+
const middlewareBarrelName = "middleware-barrel";
|
|
263
|
+
/**
|
|
264
|
+
* Generates an `index.ts` for every plugin output directory and one root
|
|
265
|
+
* barrel at `config.output.path/index.ts` after the build completes. Ships
|
|
266
|
+
* with Kubb and is registered by default in `defineConfig`.
|
|
260
267
|
*
|
|
261
|
-
* Each plugin inherits `output.barrel` from `config.output.barrel` (
|
|
262
|
-
* Set `barrel: false` on a plugin to
|
|
268
|
+
* Each plugin inherits `output.barrel` from `config.output.barrel` (which
|
|
269
|
+
* defaults to `{ type: 'named' }`). Set `barrel: false` on a plugin to skip
|
|
270
|
+
* its barrel and also exclude its files from the root barrel.
|
|
263
271
|
*
|
|
264
272
|
* @example
|
|
265
273
|
* ```ts
|
|
266
274
|
* import { defineConfig } from '@kubb/core'
|
|
267
275
|
* import { middlewareBarrel } from '@kubb/middleware-barrel'
|
|
276
|
+
* import { pluginTs } from '@kubb/plugin-ts'
|
|
277
|
+
* import { pluginZod } from '@kubb/plugin-zod'
|
|
268
278
|
*
|
|
269
279
|
* export default defineConfig({
|
|
280
|
+
* input: { path: './petStore.yaml' },
|
|
270
281
|
* output: { path: 'src/gen', barrel: { type: 'named' } },
|
|
271
282
|
* plugins: [
|
|
272
283
|
* pluginTs({ output: { path: 'types', barrel: { type: 'all' } } }),
|
|
@@ -276,10 +287,6 @@ function isExcludedPath(filePath, prefixes) {
|
|
|
276
287
|
* })
|
|
277
288
|
* ```
|
|
278
289
|
*/
|
|
279
|
-
/**
|
|
280
|
-
* Stable string identifier for the barrel middleware.
|
|
281
|
-
*/
|
|
282
|
-
const middlewareBarrelName = "middleware-barrel";
|
|
283
290
|
const middlewareBarrel = defineMiddleware(() => {
|
|
284
291
|
const excludedPrefixes = /* @__PURE__ */ new Set();
|
|
285
292
|
return {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"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 // 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 | 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, 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 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","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 { getBarrelFiles, getPluginOutputPrefix, isExcludedPath } from './utils.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 // 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 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(file)\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":";;;;;;;;;;;;;;;;;;;AAcA,SAAgB,YAAY,UAA0B;CACpD,OAAO,SAAS,WAAW,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;ACwBvC,SAAgB,UAAU,UAAkB,WAA6C;CACvF,MAAM,iBAAiB,YAAY,SAAS;CAC5C,MAAM,OAAkB;EAAE,MAAM;EAAgB,UAAU,EAAE;EAAE,QAAQ;EAAO;CAG7E,MAAM,6BAAa,IAAI,SAA4C;CACnE,WAAW,IAAI,sBAAM,IAAI,KAAK,CAAC;CAE/B,MAAM,aAAa,GAAG,eAAe;CAErC,KAAK,MAAM,YAAY,WAAW;EAChC,MAAM,aAAa,YAAY,SAAS;EACxC,IAAI,CAAC,WAAW,WAAW,WAAW,EAAE;EAExC,MAAM,QAAQ,WAAW,MAAM,WAAW,OAAO,CAAC,MAAM,IAAI;EAC5D,IAAI,MAAM,WAAW,GAAG;EAExB,IAAI,UAAU;EACd,MAAM,YAAY,MAAM,SAAS;EACjC,KAAK,MAAM,CAAC,GAAG,SAAS,MAAM,SAAS,EAAE;GACvC,IAAI,CAAC,MAAM;GAEX,MAAM,SAAS,MAAM;GACrB,MAAM,WAAW,WAAW,IAAI,QAAQ;GACxC,IAAI,QAAQ,SAAS,IAAI,KAAK;GAC9B,IAAI,CAAC,OAAO;IACV,QAAQ;KAAE,MAAM,GAAG,QAAQ,KAAK,GAAG;KAAQ,UAAU,EAAE;KAAE,QAAQ;KAAQ;IACzE,QAAQ,SAAS,KAAK,MAAM;IAC5B,SAAS,IAAI,MAAM,MAAM;IACzB,IAAI,CAAC,QAAQ,WAAW,IAAI,uBAAO,IAAI,KAAK,CAAC;;GAE/C,UAAU;;;CAId,SAAS,KAAK;CAEd,OAAO;;AAGT,SAAS,SAAS,MAAuB;CACvC,IAAI,KAAK,SAAS,WAAW,GAAG;CAChC,KAAK,SAAS,KAAK,cAAc;CACjC,KAAK,MAAM,SAAS,KAAK,UACvB,IAAI,CAAC,MAAM,QAAQ,SAAS,MAAM;;AAItC,SAAS,cAAc,GAAc,GAAsB;CACzD,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,IAAI;;;;ACjFtD,MAAM,oBAAoB,IAAI,IAAI;CAAC;CAAO;CAAQ;CAAO;CAAO,CAAC;AACjE,MAAM,gBAAgB;AAEtB,SAAS,qBAAqB,SAAiB,UAA0B;CACvE,OAAO,KAAK,SAAS,MAAM,QAAQ,SAAS,EAAE;;AAGhD,SAAS,aAAa,MAAuB;CAC3C,OAAO,KAAK,SAAS,cAAc;;AAGrC,SAAS,WAAW,SAAiB,SAAsC;CACzE,OAAO,WAAW;EAChB,UAAU;EACV,MAAM,GAAG,UAAU;EACnB;EACA,SAAS,EAAE;EACX,SAAS,EAAE;EAGX,QAAQ,KAAA;EACR,QAAQ,KAAA;EACT,CAAC;;AAWJ,SAAS,2BAA2B,SAA6C;CAC/E,IAAI,QAAQ,WAAW,GAAG,OAAO;CACjC,KAAK,MAAM,UAAU,SACnB,IAAI,OAAO,aAAa,OAAO;CAEjC,OAAO;;AAGT,SAAS,wBAAwB,SAA+D;CAC9F,MAAM,aAAa,IAAI,IAA0B,CAC/C,CAAC,uBAAO,IAAI,KAAK,CAAC,EAClB,CAAC,sBAAM,IAAI,KAAK,CAAC,CAClB,CAAC;CACF,KAAK,MAAM,UAAU,SAAS;EAC5B,IAAI,CAAC,OAAO,eAAe,CAAC,OAAO,MAAM;EACzC,WAAW,IAAI,QAAQ,OAAO,WAAW,CAAC,CAAE,IAAI,OAAO,KAAK;;CAE9D,OAAO;;AAGT,MAAM,eAA6B,EAAE,SAAS,UAAU,iBAAiB;CACvE,IAAI,cAAc,2BAA2B,WAAW,QAAQ,EAAE,OAAO,EAAE;CAC3E,OAAO,CAAC,aAAa,EAAE,MAAM,qBAAqB,SAAS,SAAS,EAAE,CAAC,CAAC;;AAG1E,MAAM,iBAA+B,EAAE,SAAS,UAAU,iBAAiB;CACzE,MAAM,aAAa,qBAAqB,SAAS,SAAS;CAE1D,IAAI,CAAC,YAAY,OAAO,CAAC,aAAa,EAAE,MAAM,YAAY,CAAC,CAAC;CAE5D,MAAM,kBAAkB,wBAAwB,WAAW,QAAQ;CACnE,MAAM,aAAa,gBAAgB,IAAI,MAAM;CAC7C,MAAM,YAAY,gBAAgB,IAAI,KAAK;CAE3C,IAAI,WAAW,SAAS,KAAK,UAAU,SAAS,GAAG;EACjD,IAAI,WAAW,QAAQ,SAAS,GAAG,OAAO,EAAE;EAC5C,OAAO,CAAC,aAAa,EAAE,MAAM,YAAY,CAAC,CAAC;;CAG7C,MAAM,UAA6B,EAAE;CACrC,IAAI,WAAW,OAAO,GACpB,QAAQ,KAAK,aAAa;EAAE,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM;EAAE,MAAM;EAAY,CAAC,CAAC;CAEhF,IAAI,UAAU,OAAO,GACnB,QAAQ,KAAK,aAAa;EAAE,MAAM,CAAC,GAAG,UAAU,CAAC,MAAM;EAAE,MAAM;EAAY,YAAY;EAAM,CAAC,CAAC;CAEjG,OAAO;;AAGT,MAAM,kBAAyD,IAAI,IAAI,CACrE,CAAC,OAAO,YAAY,EACpB,CAAC,SAAS,cAAc,CACzB,CAAC;;;;;AAYF,UAAU,eAAe,MAAiB,QAAwB,QAAgD;CAChH,MAAM,gBAA+B,EAAE;CAEvC,KAAK,MAAM,SAAS,KAAK,UAAU;EACjC,IAAI,MAAM,QAAQ;GAChB,IAAI,CAAC,aAAa,MAAM,KAAK,EAAE,cAAc,KAAK,MAAM,KAAK;GAC7D;;EAGF,MAAM,cAAc,OAAO,eAAe,OAAO,QAAQ,MAAM;EAC/D,KAAK,MAAM,QAAQ,aAAa,cAAc,KAAK,KAAK;;CAG1D,IAAI,CAAC,UAAU,CAAC,OAAO,WAAW,OAAO;CAEzC,MAAM,UAAU,cAAc,SAAS,aAAa,OAAO,SAAS;EAAE,SAAS,KAAK;EAAM;EAAU,YAAY,OAAO,YAAY,IAAI,SAAS,IAAI;EAAM,CAAC,CAAC;CAE5J,IAAI,QAAQ,SAAS,GACnB,MAAM,WAAW,KAAK,MAAM,QAAQ;CAGtC,OAAO;;;;;;AAOT,UAAU,WAAW,MAAsC;CACzD,MAAM,UAA6B,EAAE;CAErC,KAAK,MAAM,SAAS,KAAK,UAAU;EACjC,IAAI,MAAM,QAAQ;GAChB,IAAI,aAAa,MAAM,KAAK,EAAE;GAC9B,QAAQ,KAAK,aAAa,EAAE,MAAM,qBAAqB,KAAK,MAAM,MAAM,KAAK,EAAE,CAAC,CAAC;GACjF;;EAGF,OAAO,WAAW,MAAM;EACxB,QAAQ,KAAK,aAAa,EAAE,MAAM,qBAAqB,KAAK,MAAM,GAAG,MAAM,OAAO,gBAAgB,EAAE,CAAC,CAAC;;CAGxG,IAAI,QAAQ,SAAS,GACnB,MAAM,WAAW,KAAK,MAAM,QAAQ;;AASxC,SAAS,mBAAmB,OAAgC,YAAkC;CAC5F,MAAM,eAAe,GAAG,YAAY,WAAW,CAAC;CAChD,MAAM,8BAAc,IAAI,KAAuB;CAC/C,MAAM,QAAuB,EAAE;CAE/B,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,aAAa,YAAY,KAAK,KAAK;EACzC,IAAI,CAAC,WAAW,WAAW,aAAa,EAAE;EAC1C,IAAI,aAAa,WAAW,EAAE;EAC9B,IAAI,CAAC,kBAAkB,IAAI,QAAQ,WAAW,CAAC,EAAE;EAEjD,YAAY,IAAI,YAAY,KAAK;EACjC,MAAM,KAAK,WAAW;;CAGxB,OAAO;EAAE;EAAa;EAAO;;;;;;;;;;;;;;AA+C/B,UAAiB,eAAe,EAAE,YAAY,OAAO,YAAY,SAAS,OAAO,YAAY,SAAoD;CAC/I,MAAM,EAAE,aAAa,UAAU,mBAAmB,OAAO,WAAW;CACpE,IAAI,MAAM,WAAW,GAAG;CAExB,MAAM,OAAO,UAAU,YAAY,MAAM;CAEzC,IAAI,QAAQ;EACV,OAAO,WAAW,KAAK;EACvB;;CAGF,MAAM,WAAW,gBAAgB,IAAI,WAAW;CAChD,IAAI,CAAC,UAAU;CAEf,OAAO,eAAe,MAAM;EAAE;EAAa;EAAU;EAAW,EAAE,KAAK;;;;;;;AAQzE,SAAgB,sBAAsB,QAA0B,QAAwB;CACtF,OAAO,GAAG,YAAY,QAAQ,OAAO,MAAM,OAAO,OAAO,MAAM,OAAO,QAAQ,OAAO,KAAK,CAAC,CAAC;;;;;;;AAQ9F,SAAgB,eAAe,UAAkB,UAAwC;CACvF,MAAM,aAAa,YAAY,SAAS;CACxC,OAAO,SAAS,QAAQ,CAAC,MAAM,WAAW,WAAW,WAAW,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC5L1E,MAAa,uBAAuB;AAEpC,MAAa,mBAAmB,uBAAuB;CACrD,MAAM,mCAAmB,IAAI,KAAa;CAE1C,OAAO;EACL,MAAM;EACN,OAAO;GACL,kBAAkB,EAAE,QAAQ,QAAQ,OAAO,cAAc;IACvD,MAAM,eAAe,OAAO,QAAQ,QAAQ;IAC5C,MAAM,eAAe,OAAO,OAAO;IACnC,MAAM,gBAAgB,EAAE,MAAM,SAAS;IAGvC,MAAM,sBAAkD;KACtD,IAAI,iBAAiB,KAAA,GAAW,OAAO;KACvC,IAAI,iBAAiB,KAAA,GAAW,OAAO,iBAAiB,QAAQ,QAAQ;MAAE,GAAG;MAAc,QAAQ;MAAO;KAC1G,OAAO;QACL;IAEJ,IAAI,iBAAiB,OAAO;KAC1B,iBAAiB,IAAI,sBAAsB,QAAQ,OAAO,CAAC;KAC3D;;IAGF,MAAM,aAAa,aAAa;IAChC,MAAM,SAAS,aAAa,UAAU;IAEtC,MAAM,OAAO,QAAQ,OAAO,MAAM,OAAO,OAAO,KAAK;IACrD,MAAM,SAAS,QAAQ,MAAM,OAAO,QAAQ,OAAO,KAAK;IACxD,MAAM,WAAW,KAAK,SAAS,MAAM,OAAO;IAC5C,IAAI,SAAS,WAAW,KAAK,IAAI,KAAK,WAAW,SAAS,EACxD,MAAM,IAAI,MAAM,sBAAsB;IAExC,KAAK,MAAM,QAAQ,eAAe;KAAE,YAAY;KAAQ;KAAO;KAAY;KAAQ,WAAW;KAAM,CAAC,EACnG,WAAW,KAAK;;GAGpB,mBAAmB,EAAE,OAAO,QAAQ,cAAc;IAChD,MAAM,eAAe,OAAO,OAAO,UAAU,EAAE,MAAM,SAAS;IAE9D,MAAM,gBAAgB,iBAAiB,SAAS,IAAI,QAAQ,MAAM,QAAQ,MAAM,CAAC,eAAe,EAAE,MAAM,iBAAiB,CAAC;IAC1H,iBAAiB,OAAO;IAExB,IAAI,iBAAiB,OAAO;IAE5B,MAAM,aAAa,aAAa;IAEhC,KAAK,MAAM,QAAQ,eAAe;KAAE,YAAY,QAAQ,OAAO,MAAM,OAAO,OAAO,KAAK;KAAE,OAAO;KAAe;KAAY,CAAC,EAC3H,WAAW,KAAK;;GAGrB;EACF;EACD"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"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 // 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 | 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, 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 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","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 { getBarrelFiles, getPluginOutputPrefix, isExcludedPath } from './utils.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 * 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 * @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 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(file)\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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"}
|
package/extension.yaml
CHANGED
|
@@ -2,7 +2,7 @@ $schema: https://kubb.dev/schemas/extension.json
|
|
|
2
2
|
kind: middleware
|
|
3
3
|
id: middleware-barrel
|
|
4
4
|
name: Barrel
|
|
5
|
-
description:
|
|
5
|
+
description: Generates `index.ts` re-export files for every plugin output and one root barrel. Ships with Kubb and is enabled by default.
|
|
6
6
|
category: output
|
|
7
7
|
type: official
|
|
8
8
|
npmPackage: '@kubb/middleware-barrel'
|
|
@@ -26,9 +26,9 @@ resources:
|
|
|
26
26
|
changelog: https://github.com/kubb-labs/kubb/blob/main/packages/middleware-barrel/CHANGELOG.md
|
|
27
27
|
featured: true
|
|
28
28
|
intro: |-
|
|
29
|
-
|
|
29
|
+
`@kubb/middleware-barrel` generates an `index.ts` for every plugin output directory and one root barrel at `output.path/index.ts` after the build completes. The result is a single import surface for every consumer — `import { Pet, usePetByIdQuery, petMock } from './gen'`.
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
The middleware ships with Kubb and is registered by default in `defineConfig`, so barrels appear out of the box with no extra configuration. When `middlewareBarrel` is part of `config.middleware`, `defineConfig` also applies a default `output.barrel` of `{ type: 'named' }`. Custom middleware lists that omit `middlewareBarrel` leave `barrel` untouched.
|
|
32
32
|
|
|
33
33
|
Plugins inherit `output.barrel` from `config.output.barrel` when their own value is omitted. Setting `barrel: false` on a plugin disables that plugin's barrel **and** excludes its files from the root barrel.
|
|
34
34
|
options:
|
|
@@ -37,18 +37,20 @@ options:
|
|
|
37
37
|
required: false
|
|
38
38
|
default: "{ type: 'named' }"
|
|
39
39
|
description: |-
|
|
40
|
-
Re-export style for
|
|
40
|
+
Re-export style used for every generated barrel file. Set via `output.barrel` in `defineConfig` (applies to all plugins and the root barrel) or per plugin via that plugin's own `output.barrel`. It is not an argument to the middleware itself.
|
|
41
41
|
|
|
42
42
|
At the config level:
|
|
43
|
-
- `{ type: 'all' }` — `export * from '...'` for every generated file
|
|
44
|
-
- `{ type: 'named' }` — `export { name1, name2 } from '...'` using each file's named exports
|
|
45
|
-
- `false` — disables barrel generation entirely
|
|
46
43
|
|
|
47
|
-
|
|
48
|
-
- `{ type: 'named'
|
|
49
|
-
- `false` — disables barrel generation
|
|
44
|
+
- `{ type: 'all' }` — `export * from '...'` for every generated file.
|
|
45
|
+
- `{ type: 'named' }` — `export { Foo, Bar } from '...'` using each file's named exports.
|
|
46
|
+
- `false` — disables barrel generation entirely.
|
|
50
47
|
|
|
51
|
-
|
|
48
|
+
At the plugin level you also get `nested`:
|
|
49
|
+
|
|
50
|
+
- `{ type: 'named', nested: true }` — generates a barrel for every subdirectory, re-exporting only direct children. Lets callers import from any depth.
|
|
51
|
+
- `false` — disables the plugin's barrel and removes its files from the root barrel.
|
|
52
|
+
|
|
53
|
+
The `{ type: 'named' }` default kicks in only when `middlewareBarrel` is part of `config.middleware`.
|
|
52
54
|
codeBlock:
|
|
53
55
|
lang: typescript
|
|
54
56
|
title: kubb.config.ts
|
|
@@ -58,12 +60,13 @@ options:
|
|
|
58
60
|
import { middlewareBarrel } from '@kubb/middleware-barrel'
|
|
59
61
|
|
|
60
62
|
export default defineConfig({
|
|
61
|
-
input: { path: './
|
|
63
|
+
input: { path: './petStore.yaml' },
|
|
62
64
|
output: { path: './src/gen', barrel: { type: 'named' } },
|
|
63
65
|
middleware: [middlewareBarrel()],
|
|
66
|
+
plugins: [],
|
|
64
67
|
})
|
|
65
68
|
examples:
|
|
66
|
-
- name: "
|
|
69
|
+
- name: "{ type: 'named' } (default)"
|
|
67
70
|
files:
|
|
68
71
|
- name: kubb.config.ts
|
|
69
72
|
lang: typescript
|
|
@@ -72,10 +75,11 @@ examples:
|
|
|
72
75
|
import { defineConfig } from 'kubb'
|
|
73
76
|
|
|
74
77
|
export default defineConfig({
|
|
75
|
-
input: { path: './
|
|
78
|
+
input: { path: './petStore.yaml' },
|
|
76
79
|
output: { path: './src/gen' },
|
|
80
|
+
plugins: [],
|
|
77
81
|
})
|
|
78
|
-
- name:
|
|
82
|
+
- name: Generated output
|
|
79
83
|
lang: typescript
|
|
80
84
|
twoslash: false
|
|
81
85
|
code: |-
|
|
@@ -92,7 +96,7 @@ examples:
|
|
|
92
96
|
|
|
93
97
|
// src/gen/api/types/index.ts
|
|
94
98
|
export { User } from './User'
|
|
95
|
-
- name: "
|
|
99
|
+
- name: "{ type: 'all' }"
|
|
96
100
|
files:
|
|
97
101
|
- name: kubb.config.ts
|
|
98
102
|
lang: typescript
|
|
@@ -101,10 +105,11 @@ examples:
|
|
|
101
105
|
import { defineConfig } from 'kubb'
|
|
102
106
|
|
|
103
107
|
export default defineConfig({
|
|
104
|
-
input: { path: './
|
|
108
|
+
input: { path: './petStore.yaml' },
|
|
105
109
|
output: { path: './src/gen', barrel: { type: 'all' } },
|
|
110
|
+
plugins: [],
|
|
106
111
|
})
|
|
107
|
-
- name:
|
|
112
|
+
- name: Generated output
|
|
108
113
|
lang: typescript
|
|
109
114
|
twoslash: false
|
|
110
115
|
code: |-
|
|
@@ -121,7 +126,7 @@ examples:
|
|
|
121
126
|
|
|
122
127
|
// src/gen/api/types/index.ts
|
|
123
128
|
export * from './User'
|
|
124
|
-
- name: "
|
|
129
|
+
- name: "{ type: 'named', nested: true }"
|
|
125
130
|
files:
|
|
126
131
|
- name: kubb.config.ts
|
|
127
132
|
lang: typescript
|
|
@@ -130,10 +135,11 @@ examples:
|
|
|
130
135
|
import { defineConfig } from 'kubb'
|
|
131
136
|
|
|
132
137
|
export default defineConfig({
|
|
133
|
-
input: { path: './
|
|
138
|
+
input: { path: './petStore.yaml' },
|
|
134
139
|
output: { path: './src/gen', barrel: { type: 'named', nested: true } },
|
|
140
|
+
plugins: [],
|
|
135
141
|
})
|
|
136
|
-
- name:
|
|
142
|
+
- name: Generated output (chained structure)
|
|
137
143
|
lang: typescript
|
|
138
144
|
twoslash: false
|
|
139
145
|
code: |-
|
|
@@ -148,7 +154,7 @@ examples:
|
|
|
148
154
|
|
|
149
155
|
// src/gen/api/types/index.ts (exports files)
|
|
150
156
|
export * from './User'
|
|
151
|
-
- name: Disable barrel for a single plugin
|
|
157
|
+
- name: Disable the barrel for a single plugin
|
|
152
158
|
files:
|
|
153
159
|
- name: kubb.config.ts
|
|
154
160
|
lang: typescript
|
|
@@ -158,17 +164,17 @@ examples:
|
|
|
158
164
|
import { pluginTs } from '@kubb/plugin-ts'
|
|
159
165
|
import { pluginZod } from '@kubb/plugin-zod'
|
|
160
166
|
|
|
161
|
-
// pluginZod opts out: no zod/index.ts is created
|
|
167
|
+
// pluginZod opts out: no zod/index.ts is created,
|
|
162
168
|
// and zod files are excluded from the root index.ts.
|
|
163
169
|
export default defineConfig({
|
|
164
|
-
input: { path: './
|
|
170
|
+
input: { path: './petStore.yaml' },
|
|
165
171
|
output: { path: './src/gen' },
|
|
166
172
|
plugins: [
|
|
167
173
|
pluginTs(),
|
|
168
174
|
pluginZod({ output: { barrel: false } }),
|
|
169
175
|
],
|
|
170
176
|
})
|
|
171
|
-
- name: Disable the root barrel
|
|
177
|
+
- name: Disable only the root barrel
|
|
172
178
|
files:
|
|
173
179
|
- name: kubb.config.ts
|
|
174
180
|
lang: typescript
|
|
@@ -177,15 +183,16 @@ examples:
|
|
|
177
183
|
import { defineConfig } from 'kubb'
|
|
178
184
|
|
|
179
185
|
// No root index.ts is generated, but each plugin
|
|
180
|
-
// still gets its own barrel using its inherited
|
|
186
|
+
// still gets its own barrel using its inherited config.
|
|
181
187
|
export default defineConfig({
|
|
182
|
-
input: { path: './
|
|
188
|
+
input: { path: './petStore.yaml' },
|
|
183
189
|
output: { path: './src/gen', barrel: false },
|
|
190
|
+
plugins: [],
|
|
184
191
|
})
|
|
185
192
|
notes:
|
|
186
193
|
- type: tip
|
|
187
194
|
body: |-
|
|
188
|
-
`middleware-barrel`
|
|
195
|
+
`middleware-barrel` ships with Kubb and is enabled automatically when no `middleware` option is provided. Install it explicitly only when customising barrel behaviour alongside other middlewares.
|
|
189
196
|
- type: note
|
|
190
197
|
body: |-
|
|
191
|
-
`output.barrel` is
|
|
198
|
+
`output.barrel` is auto-defaulted to `{ type: 'named' }` only when `middlewareBarrel` is part of `config.middleware`. With a custom middleware list that omits it, set `output.barrel` yourself if you still want a barrel.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/middleware-barrel",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.24",
|
|
4
4
|
"description": "Barrel-file middleware for Kubb. Automatically generates index.ts re-export files per plugin output directory and an optional root barrel after all plugins complete.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"barrel",
|
|
@@ -43,13 +43,13 @@
|
|
|
43
43
|
"registry": "https://registry.npmjs.org/"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@kubb/ast": "5.0.0-beta.
|
|
46
|
+
"@kubb/ast": "5.0.0-beta.24"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@internals/utils": "0.0.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"@kubb/core": "5.0.0-beta.
|
|
52
|
+
"@kubb/core": "5.0.0-beta.24"
|
|
53
53
|
},
|
|
54
54
|
"engines": {
|
|
55
55
|
"node": ">=22"
|
package/src/middleware.ts
CHANGED
|
@@ -37,17 +37,29 @@ declare global {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
40
|
+
* Canonical middleware name for `@kubb/middleware-barrel`. Used for driver
|
|
41
|
+
* lookups.
|
|
42
|
+
*/
|
|
43
|
+
export const middlewareBarrelName = 'middleware-barrel' satisfies Middleware['name']
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Generates an `index.ts` for every plugin output directory and one root
|
|
47
|
+
* barrel at `config.output.path/index.ts` after the build completes. Ships
|
|
48
|
+
* with Kubb and is registered by default in `defineConfig`.
|
|
41
49
|
*
|
|
42
|
-
* Each plugin inherits `output.barrel` from `config.output.barrel` (
|
|
43
|
-
* Set `barrel: false` on a plugin to
|
|
50
|
+
* Each plugin inherits `output.barrel` from `config.output.barrel` (which
|
|
51
|
+
* defaults to `{ type: 'named' }`). Set `barrel: false` on a plugin to skip
|
|
52
|
+
* its barrel and also exclude its files from the root barrel.
|
|
44
53
|
*
|
|
45
54
|
* @example
|
|
46
55
|
* ```ts
|
|
47
56
|
* import { defineConfig } from '@kubb/core'
|
|
48
57
|
* import { middlewareBarrel } from '@kubb/middleware-barrel'
|
|
58
|
+
* import { pluginTs } from '@kubb/plugin-ts'
|
|
59
|
+
* import { pluginZod } from '@kubb/plugin-zod'
|
|
49
60
|
*
|
|
50
61
|
* export default defineConfig({
|
|
62
|
+
* input: { path: './petStore.yaml' },
|
|
51
63
|
* output: { path: 'src/gen', barrel: { type: 'named' } },
|
|
52
64
|
* plugins: [
|
|
53
65
|
* pluginTs({ output: { path: 'types', barrel: { type: 'all' } } }),
|
|
@@ -57,12 +69,6 @@ declare global {
|
|
|
57
69
|
* })
|
|
58
70
|
* ```
|
|
59
71
|
*/
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Stable string identifier for the barrel middleware.
|
|
63
|
-
*/
|
|
64
|
-
export const middlewareBarrelName = 'middleware-barrel' satisfies Middleware['name']
|
|
65
|
-
|
|
66
72
|
export const middlewareBarrel = defineMiddleware(() => {
|
|
67
73
|
const excludedPrefixes = new Set<string>()
|
|
68
74
|
|