@kubb/middleware-barrel 5.0.0-alpha.55 → 5.0.0-alpha.56
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 +11 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +11 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/middleware.ts +5 -7
- package/src/utils/generatePerPluginBarrel.ts +6 -2
- package/src/utils/getBarrelFiles.ts +4 -1
package/dist/index.cjs
CHANGED
|
@@ -190,11 +190,15 @@ function getBarrelFiles(outputPath, files, barrelType) {
|
|
|
190
190
|
/**
|
|
191
191
|
* Generates barrel files for a single plugin's output directory.
|
|
192
192
|
*
|
|
193
|
-
* The barrel file is placed at `resolve(config.root, plugin.options.output.path)/index.ts`
|
|
193
|
+
* The barrel file is placed at `resolve(config.root, config.output.path, plugin.options.output.path)/index.ts`
|
|
194
194
|
* and re-exports all files generated by that plugin, using the given `barrelType` strategy.
|
|
195
|
+
*
|
|
196
|
+
* Note: `plugin.options.output.path` is relative to `config.output.path`, not to `config.root`.
|
|
197
|
+
* Files generated by plugins land at `config.root + config.output.path + plugin.output.path`,
|
|
198
|
+
* so the barrel directory must be resolved with all three segments.
|
|
195
199
|
*/
|
|
196
200
|
function generatePerPluginBarrel({ barrelType, plugin, files, config }) {
|
|
197
|
-
return getBarrelFiles((0, node_path.resolve)(config.root, plugin.options.output.path), files, barrelType);
|
|
201
|
+
return getBarrelFiles((0, node_path.resolve)(config.root, config.output.path, plugin.options.output.path), files, barrelType);
|
|
198
202
|
}
|
|
199
203
|
//#endregion
|
|
200
204
|
//#region src/utils/generateRootBarrel.ts
|
|
@@ -260,16 +264,15 @@ const middlewareBarrel = (0, _kubb_core.defineMiddleware)({
|
|
|
260
264
|
});
|
|
261
265
|
if (barrelFiles.length > 0) ctx.upsertFile(...barrelFiles);
|
|
262
266
|
});
|
|
263
|
-
hooks.on("kubb:
|
|
264
|
-
|
|
265
|
-
const rootBarrelType = ctx.config.output.barrelType;
|
|
267
|
+
hooks.on("kubb:plugins:end", ({ files, config, upsertFile }) => {
|
|
268
|
+
const rootBarrelType = config.output.barrelType;
|
|
266
269
|
if (!rootBarrelType) return;
|
|
267
270
|
const rootBarrelFiles = generateRootBarrel({
|
|
268
271
|
barrelType: rootBarrelType,
|
|
269
|
-
files
|
|
270
|
-
config
|
|
272
|
+
files,
|
|
273
|
+
config
|
|
271
274
|
});
|
|
272
|
-
if (rootBarrelFiles.length > 0)
|
|
275
|
+
if (rootBarrelFiles.length > 0) upsertFile(...rootBarrelFiles);
|
|
273
276
|
});
|
|
274
277
|
}
|
|
275
278
|
});
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["posix"],"sources":["../src/constants.ts","../src/utils/TreeNode.ts","../src/utils/getBarrelFiles.ts","../src/utils/generatePerPluginBarrel.ts","../src/utils/generateRootBarrel.ts","../src/middleware.ts"],"sourcesContent":["/**\n * Base file name for barrel files (without extension).\n */\nexport const BARREL_BASENAME = 'index' as const\n\n/**\n * Full file name for barrel files (with extension).\n */\nexport const BARREL_FILENAME = 'index.ts' as const\n","import { posix } from 'node:path'\n\n/**\n * A node in a directory tree used to compute barrel file exports.\n *\n * Each `TreeNode` represents either a directory or a file entry.\n * Directory nodes have `children`; file nodes have an empty `children` array.\n */\nexport type TreeNode = {\n /**\n * Absolute path of the directory (root of this subtree) or file.\n */\n path: string\n /**\n * Child nodes (sub-directories and files) within this directory.\n */\n children: Array<TreeNode>\n /**\n * `true` when this node represents a file (leaf node).\n */\n isFile: boolean\n}\n\n/**\n * Builds a `TreeNode` directory tree from a list of absolute file paths.\n *\n * All `filePaths` must be inside `rootPath`. Paths that are outside\n * the root or that equal the root are silently ignored.\n *\n * @example\n * ```ts\n * const tree = buildTree('/src/gen/types', [\n * '/src/gen/types/pet.ts',\n * '/src/gen/types/user.ts',\n * '/src/gen/types/pets/listPets.ts',\n * ])\n * ```\n */\nexport function buildTree(rootPath: string, filePaths: ReadonlyArray<string>): TreeNode {\n const root: TreeNode = { path: rootPath, children: [], isFile: false }\n\n for (const filePath of filePaths) {\n // Only include files inside rootPath\n if (!filePath.startsWith(rootPath + posix.sep) && !filePath.startsWith(rootPath + '/')) {\n continue\n }\n\n const relative = filePath.slice(rootPath.length).replace(/^\\//g, '').replace(/^\\\\/g, '')\n const parts = relative.split(/[/\\\\]/).filter(Boolean)\n\n let current = root\n for (let i = 0; i < parts.length; i++) {\n const isLast = i === parts.length - 1\n const part = parts[i]!\n const childPath = `${current.path}/${part}`\n\n let child = current.children.find((c) => c.path === childPath)\n if (!child) {\n child = { path: childPath, children: [], isFile: isLast }\n current.children.push(child)\n }\n current = child\n }\n }\n\n return root\n}\n","import { createExport, createFile } from '@kubb/ast'\nimport type { FileNode } from '@kubb/ast'\nimport { BARREL_BASENAME, BARREL_FILENAME } from '../constants.ts'\nimport type { BarrelType } from '../types.ts'\nimport { buildTree, type TreeNode } from './TreeNode.ts'\n\n/**\n * Derives a relative module specifier (no extension) from an absolute `filePath`\n * relative to an absolute `fromDir`.\n *\n * @example\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/pet.ts') // './pet'\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/tags/tag.ts') // './tags/tag'\n */\nfunction toRelativeModulePath(fromDir: string, filePath: string): string {\n const relative = filePath.slice(fromDir.length).replace(/^[/\\\\]/g, '')\n // Strip extension\n const withoutExt = relative.replace(/\\.[^/.]+$/, '')\n return `./${withoutExt}`\n}\n\n/**\n * Generates barrel `FileNode[]` for a given directory tree node using the `'all'` strategy:\n * each leaf file gets a `export * from './relPath'` in the barrel of its nearest ancestor directory.\n *\n * Only a single barrel file (at `treeNode.path`) is generated — sub-directory files are referenced\n * with their full relative path from `treeNode.path`.\n */\nfunction getBarrelFilesAll(treeNode: TreeNode, _sourceFiles: ReadonlyArray<FileNode>): Array<FileNode> {\n // Collect all source file paths under this node (excluding barrel files themselves)\n const leafPaths = collectLeafPaths(treeNode).filter((p) => !p.endsWith(`/${BARREL_FILENAME}`))\n\n if (leafPaths.length === 0) return []\n\n const barrelPath = `${treeNode.path}/${BARREL_FILENAME}`\n const exports = leafPaths.map((filePath) =>\n createExport({\n path: toRelativeModulePath(treeNode.path, filePath),\n }),\n )\n\n return [\n createFile({\n baseName: BARREL_FILENAME,\n path: barrelPath,\n exports,\n sources: [],\n imports: [],\n }),\n ]\n}\n\n/**\n * Generates barrel `FileNode[]` for a given directory tree node using the `'named'` strategy:\n * each indexable source in each leaf file gets an individual named `export { name } from '...'`.\n */\nfunction getBarrelFilesNamed(treeNode: TreeNode, sourceFiles: ReadonlyArray<FileNode>): Array<FileNode> {\n const leafPaths = collectLeafPaths(treeNode).filter((p) => !p.endsWith(`/${BARREL_FILENAME}`))\n\n if (leafPaths.length === 0) return []\n\n const barrelPath = `${treeNode.path}/${BARREL_FILENAME}`\n const exports: ReturnType<typeof createExport>[] = []\n\n for (const filePath of leafPaths) {\n const sourceFile = sourceFiles.find((f) => f.path === filePath)\n if (!sourceFile) {\n // Fall back to wildcard if the source file is not in our set\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\n continue\n }\n\n const indexableSources = sourceFile.sources.filter((s) => s.isIndexable && s.name)\n if (indexableSources.length === 0) {\n // No named exports: fall back to wildcard\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\n continue\n }\n\n const names = indexableSources.map((s) => s.name as string)\n exports.push(\n createExport({\n name: names,\n path: toRelativeModulePath(treeNode.path, filePath),\n }),\n )\n }\n\n if (exports.length === 0) return []\n\n return [\n createFile({\n baseName: BARREL_FILENAME,\n path: barrelPath,\n exports,\n sources: [],\n imports: [],\n }),\n ]\n}\n\n/**\n * Generates barrel `FileNode[]` for a given directory tree node using the `'propagate'` strategy:\n * like `'all'` but also generates intermediate barrel files for every sub-directory, so that\n * consumers can import from any depth.\n *\n * Leaf barrels export directly from their files; parent barrels export from their sub-barrel files.\n */\nfunction getBarrelFilesPropagate(treeNode: TreeNode): Array<FileNode> {\n return collectPropagatedBarrels(treeNode)\n}\n\nfunction collectPropagatedBarrels(node: TreeNode): Array<FileNode> {\n const result: Array<FileNode> = []\n const barrelExports: ReturnType<typeof createExport>[] = []\n\n for (const child of node.children) {\n if (child.isFile) {\n if (!child.path.endsWith(`/${BARREL_FILENAME}`)) {\n barrelExports.push(createExport({ path: toRelativeModulePath(node.path, child.path) }))\n }\n } else {\n // Recurse into sub-directory\n const subBarrels = collectPropagatedBarrels(child)\n result.push(...subBarrels)\n\n // Export the sub-directory's barrel (not individual files)\n const subBarrelPath = `${child.path}/${BARREL_BASENAME}`\n barrelExports.push(createExport({ path: toRelativeModulePath(node.path, subBarrelPath) }))\n }\n }\n\n if (barrelExports.length > 0) {\n result.push(\n createFile({\n baseName: BARREL_FILENAME,\n path: `${node.path}/${BARREL_FILENAME}`,\n exports: barrelExports,\n sources: [],\n imports: [],\n }),\n )\n }\n\n return result\n}\n\n/**\n * Collects all leaf (file) paths within a tree node recursively.\n */\nfunction collectLeafPaths(node: TreeNode): Array<string> {\n if (node.isFile) return [node.path]\n return node.children.flatMap((c) => collectLeafPaths(c))\n}\n\n/**\n * Generates barrel `FileNode[]` for a directory rooted at `outputPath`, given the full set of\n * generated source `files`, using the specified `barrelType` strategy.\n *\n * Files not located inside `outputPath` are excluded automatically.\n *\n * @param outputPath Absolute path to the output directory.\n * @param files All generated files (across all plugins).\n * @param barrelType Barrel generation strategy.\n */\nexport function getBarrelFiles(outputPath: string, files: ReadonlyArray<FileNode>, barrelType: BarrelType): Array<FileNode> {\n // Only include files that live inside this outputPath\n const relevantFiles = files.filter((f) => {\n const normalizedFilePath = f.path.replace(/\\\\/g, '/')\n const normalizedOutputPath = outputPath.replace(/\\\\/g, '/')\n return normalizedFilePath.startsWith(normalizedOutputPath + '/') && !normalizedFilePath.endsWith(`/${BARREL_FILENAME}`)\n })\n\n if (relevantFiles.length === 0) return []\n\n const tree = buildTree(outputPath, relevantFiles.map((f) => f.path))\n\n switch (barrelType) {\n case 'all':\n return getBarrelFilesAll(tree, relevantFiles)\n case 'named':\n return getBarrelFilesNamed(tree, relevantFiles)\n case 'propagate':\n return getBarrelFilesPropagate(tree)\n default:\n return []\n }\n}\n","import { resolve } from 'node:path'\nimport type { FileNode } from '@kubb/ast'\nimport type { Config, NormalizedPlugin } from '@kubb/core'\nimport type { BarrelType } from '../types.ts'\nimport { getBarrelFiles } from './getBarrelFiles.ts'\n\nexport type GeneratePerPluginBarrelParams = {\n barrelType: BarrelType\n plugin: NormalizedPlugin\n files: ReadonlyArray<FileNode>\n config: Config\n}\n\n/**\n * Generates barrel files for a single plugin's output directory.\n *\n * The barrel file is placed at `resolve(config.root, plugin.options.output.path)/index.ts`\n * and re-exports all files generated by that plugin, using the given `barrelType` strategy.\n */\nexport function generatePerPluginBarrel({ barrelType, plugin, files, config }: GeneratePerPluginBarrelParams): Array<FileNode> {\n const outputPath = resolve(config.root, plugin.options.output.path)\n return getBarrelFiles(outputPath, files, barrelType)\n}\n","import { resolve } from 'node:path'\nimport type { FileNode } from '@kubb/ast'\nimport type { Config } from '@kubb/core'\nimport type { BarrelType } from '../types.ts'\nimport { getBarrelFiles } from './getBarrelFiles.ts'\n\nexport type GenerateRootBarrelParams = {\n barrelType: BarrelType\n files: ReadonlyArray<FileNode>\n config: Config\n}\n\n/**\n * Generates a root barrel file at `resolve(config.root, config.output.path)/index.ts`.\n *\n * The root barrel re-exports from all files across all plugins that are located\n * inside the root output directory, using the given `barrelType` strategy.\n *\n * In practice this re-exports the per-plugin barrels when `barrelType = 'propagate'`,\n * or all individual files when `barrelType = 'all'` or `'named'`.\n */\nexport function generateRootBarrel({ barrelType, files, config }: GenerateRootBarrelParams): Array<FileNode> {\n const outputPath = resolve(config.root, config.output.path)\n return getBarrelFiles(outputPath, files, barrelType)\n}\n","import { defineMiddleware } from '@kubb/core'\nimport type { KubbBuildStartContext, NormalizedPlugin } from '@kubb/core'\nimport './types.ts'\nimport type { BarrelType } from './types.ts'\nimport { generatePerPluginBarrel } from './utils/generatePerPluginBarrel.ts'\nimport { generateRootBarrel } from './utils/generateRootBarrel.ts'\n\n/**\n * Barrel-file generation middleware.\n *\n * When added to `config.middleware`, generates an `index.ts` barrel file for each\n * plugin that has `output.barrelType` set (or inherits it from `config.output.barrelType`),\n * as well as a root `index.ts` at `config.output.path` when `config.output.barrelType` is set.\n *\n * The `barrelType` option controls the re-export style:\n * - `'all'` — `export * from '...'` for each generated file\n * - `'named'` — `export { name1, name2 } from '...'` using each file's indexable sources\n * - `'propagate'` — like `'all'` with intermediate barrel files for sub-directories\n *\n * @example\n * ```ts\n * import { middlewareBarrel } from '@kubb/middleware-barrel'\n *\n * export default defineConfig({\n * output: { path: 'src/gen', barrelType: 'named' },\n * plugins: [\n * pluginTs({ output: { path: 'types', barrelType: 'all' } }),\n * pluginZod({ output: { path: 'schemas' } }),\n * ],\n * middleware: [middlewareBarrel],\n * })\n * ```\n */\nexport const middlewareBarrel = defineMiddleware({\n name: 'middleware-barrel',\n\n install(hooks) {\n let ctx: KubbBuildStartContext\n\n hooks.on('kubb:build:start', (buildCtx) => {\n ctx = buildCtx\n })\n\n hooks.on('kubb:plugin:end', ({ plugin }) => {\n if (!ctx) return\n\n // At runtime the plugin in kubb:plugin:end is always a NormalizedPlugin;\n // KubbPluginEndContext types it as Plugin for public API simplicity.\n const normalizedPlugin = plugin as NormalizedPlugin\n const pluginOutput = normalizedPlugin.options.output as { barrelType?: BarrelType | false } | undefined\n const rootOutput = ctx.config.output as { barrelType?: BarrelType | false }\n const barrelType = pluginOutput?.barrelType !== undefined ? pluginOutput.barrelType : rootOutput.barrelType\n\n if (!barrelType) return\n\n const barrelFiles = generatePerPluginBarrel({\n barrelType,\n plugin: normalizedPlugin,\n files: ctx.files,\n config: ctx.config,\n })\n\n if (barrelFiles.length > 0) {\n ctx.upsertFile(...barrelFiles)\n }\n })\n\n hooks.on('kubb:build:end', () => {\n if (!ctx) return\n\n const rootOutput = ctx.config.output as { barrelType?: BarrelType | false }\n const rootBarrelType = rootOutput.barrelType\n\n if (!rootBarrelType) return\n\n const rootBarrelFiles = generateRootBarrel({\n barrelType: rootBarrelType,\n files: ctx.files,\n config: ctx.config,\n })\n\n if (rootBarrelFiles.length > 0) {\n ctx.upsertFile(...rootBarrelFiles)\n }\n })\n },\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["posix"],"sources":["../src/constants.ts","../src/utils/TreeNode.ts","../src/utils/getBarrelFiles.ts","../src/utils/generatePerPluginBarrel.ts","../src/utils/generateRootBarrel.ts","../src/middleware.ts"],"sourcesContent":["/**\n * Base file name for barrel files (without extension).\n */\nexport const BARREL_BASENAME = 'index' as const\n\n/**\n * Full file name for barrel files (with extension).\n */\nexport const BARREL_FILENAME = 'index.ts' as const\n","import { posix } from 'node:path'\n\n/**\n * A node in a directory tree used to compute barrel file exports.\n *\n * Each `TreeNode` represents either a directory or a file entry.\n * Directory nodes have `children`; file nodes have an empty `children` array.\n */\nexport type TreeNode = {\n /**\n * Absolute path of the directory (root of this subtree) or file.\n */\n path: string\n /**\n * Child nodes (sub-directories and files) within this directory.\n */\n children: Array<TreeNode>\n /**\n * `true` when this node represents a file (leaf node).\n */\n isFile: boolean\n}\n\n/**\n * Builds a `TreeNode` directory tree from a list of absolute file paths.\n *\n * All `filePaths` must be inside `rootPath`. Paths that are outside\n * the root or that equal the root are silently ignored.\n *\n * @example\n * ```ts\n * const tree = buildTree('/src/gen/types', [\n * '/src/gen/types/pet.ts',\n * '/src/gen/types/user.ts',\n * '/src/gen/types/pets/listPets.ts',\n * ])\n * ```\n */\nexport function buildTree(rootPath: string, filePaths: ReadonlyArray<string>): TreeNode {\n const root: TreeNode = { path: rootPath, children: [], isFile: false }\n\n for (const filePath of filePaths) {\n // Only include files inside rootPath\n if (!filePath.startsWith(rootPath + posix.sep) && !filePath.startsWith(rootPath + '/')) {\n continue\n }\n\n const relative = filePath.slice(rootPath.length).replace(/^\\//g, '').replace(/^\\\\/g, '')\n const parts = relative.split(/[/\\\\]/).filter(Boolean)\n\n let current = root\n for (let i = 0; i < parts.length; i++) {\n const isLast = i === parts.length - 1\n const part = parts[i]!\n const childPath = `${current.path}/${part}`\n\n let child = current.children.find((c) => c.path === childPath)\n if (!child) {\n child = { path: childPath, children: [], isFile: isLast }\n current.children.push(child)\n }\n current = child\n }\n }\n\n return root\n}\n","import { createExport, createFile } from '@kubb/ast'\nimport type { FileNode } from '@kubb/ast'\nimport { BARREL_BASENAME, BARREL_FILENAME } from '../constants.ts'\nimport type { BarrelType } from '../types.ts'\nimport { buildTree, type TreeNode } from './TreeNode.ts'\n\n/**\n * Derives a relative module specifier (no extension) from an absolute `filePath`\n * relative to an absolute `fromDir`.\n *\n * @example\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/pet.ts') // './pet'\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/tags/tag.ts') // './tags/tag'\n */\nfunction toRelativeModulePath(fromDir: string, filePath: string): string {\n const relative = filePath.slice(fromDir.length).replace(/^[/\\\\]/g, '')\n // Strip extension\n const withoutExt = relative.replace(/\\.[^/.]+$/, '')\n return `./${withoutExt}`\n}\n\n/**\n * Generates barrel `FileNode[]` for a given directory tree node using the `'all'` strategy:\n * each leaf file gets a `export * from './relPath'` in the barrel of its nearest ancestor directory.\n *\n * Only a single barrel file (at `treeNode.path`) is generated — sub-directory files are referenced\n * with their full relative path from `treeNode.path`.\n */\nfunction getBarrelFilesAll(treeNode: TreeNode, _sourceFiles: ReadonlyArray<FileNode>): Array<FileNode> {\n // Collect all source file paths under this node (excluding barrel files themselves)\n const leafPaths = collectLeafPaths(treeNode).filter((p) => !p.endsWith(`/${BARREL_FILENAME}`))\n\n if (leafPaths.length === 0) return []\n\n const barrelPath = `${treeNode.path}/${BARREL_FILENAME}`\n const exports = leafPaths.map((filePath) =>\n createExport({\n path: toRelativeModulePath(treeNode.path, filePath),\n }),\n )\n\n return [\n createFile({\n baseName: BARREL_FILENAME,\n path: barrelPath,\n exports,\n sources: [],\n imports: [],\n }),\n ]\n}\n\n/**\n * Generates barrel `FileNode[]` for a given directory tree node using the `'named'` strategy:\n * each indexable source in each leaf file gets an individual named `export { name } from '...'`.\n */\nfunction getBarrelFilesNamed(treeNode: TreeNode, sourceFiles: ReadonlyArray<FileNode>): Array<FileNode> {\n const leafPaths = collectLeafPaths(treeNode).filter((p) => !p.endsWith(`/${BARREL_FILENAME}`))\n\n if (leafPaths.length === 0) return []\n\n const barrelPath = `${treeNode.path}/${BARREL_FILENAME}`\n const exports: ReturnType<typeof createExport>[] = []\n\n for (const filePath of leafPaths) {\n const sourceFile = sourceFiles.find((f) => f.path === filePath)\n if (!sourceFile) {\n // Fall back to wildcard if the source file is not in our set\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\n continue\n }\n\n const indexableSources = sourceFile.sources.filter((s) => s.isIndexable && s.name)\n if (indexableSources.length === 0) {\n // No named exports: fall back to wildcard\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\n continue\n }\n\n const names = indexableSources.map((s) => s.name as string)\n exports.push(\n createExport({\n name: names,\n path: toRelativeModulePath(treeNode.path, filePath),\n }),\n )\n }\n\n if (exports.length === 0) return []\n\n return [\n createFile({\n baseName: BARREL_FILENAME,\n path: barrelPath,\n exports,\n sources: [],\n imports: [],\n }),\n ]\n}\n\n/**\n * Generates barrel `FileNode[]` for a given directory tree node using the `'propagate'` strategy:\n * like `'all'` but also generates intermediate barrel files for every sub-directory, so that\n * consumers can import from any depth.\n *\n * Leaf barrels export directly from their files; parent barrels export from their sub-barrel files.\n */\nfunction getBarrelFilesPropagate(treeNode: TreeNode): Array<FileNode> {\n return collectPropagatedBarrels(treeNode)\n}\n\nfunction collectPropagatedBarrels(node: TreeNode): Array<FileNode> {\n const result: Array<FileNode> = []\n const barrelExports: ReturnType<typeof createExport>[] = []\n\n for (const child of node.children) {\n if (child.isFile) {\n if (!child.path.endsWith(`/${BARREL_FILENAME}`)) {\n barrelExports.push(createExport({ path: toRelativeModulePath(node.path, child.path) }))\n }\n } else {\n // Recurse into sub-directory\n const subBarrels = collectPropagatedBarrels(child)\n result.push(...subBarrels)\n\n // Export the sub-directory's barrel (not individual files)\n const subBarrelPath = `${child.path}/${BARREL_BASENAME}`\n barrelExports.push(createExport({ path: toRelativeModulePath(node.path, subBarrelPath) }))\n }\n }\n\n if (barrelExports.length > 0) {\n result.push(\n createFile({\n baseName: BARREL_FILENAME,\n path: `${node.path}/${BARREL_FILENAME}`,\n exports: barrelExports,\n sources: [],\n imports: [],\n }),\n )\n }\n\n return result\n}\n\n/**\n * Collects all leaf (file) paths within a tree node recursively.\n */\nfunction collectLeafPaths(node: TreeNode): Array<string> {\n if (node.isFile) return [node.path]\n return node.children.flatMap((c) => collectLeafPaths(c))\n}\n\n/**\n * Generates barrel `FileNode[]` for a directory rooted at `outputPath`, given the full set of\n * generated source `files`, using the specified `barrelType` strategy.\n *\n * Files not located inside `outputPath` are excluded automatically.\n *\n * @param outputPath Absolute path to the output directory.\n * @param files All generated files (across all plugins).\n * @param barrelType Barrel generation strategy.\n */\nexport function getBarrelFiles(outputPath: string, files: ReadonlyArray<FileNode>, barrelType: BarrelType): Array<FileNode> {\n // Only include files that live inside this outputPath\n const relevantFiles = files.filter((f) => {\n const normalizedFilePath = f.path.replace(/\\\\/g, '/')\n const normalizedOutputPath = outputPath.replace(/\\\\/g, '/')\n return normalizedFilePath.startsWith(normalizedOutputPath + '/') && !normalizedFilePath.endsWith(`/${BARREL_FILENAME}`)\n })\n\n if (relevantFiles.length === 0) return []\n\n const tree = buildTree(\n outputPath,\n relevantFiles.map((f) => f.path),\n )\n\n switch (barrelType) {\n case 'all':\n return getBarrelFilesAll(tree, relevantFiles)\n case 'named':\n return getBarrelFilesNamed(tree, relevantFiles)\n case 'propagate':\n return getBarrelFilesPropagate(tree)\n default:\n return []\n }\n}\n","import { resolve } from 'node:path'\nimport type { FileNode } from '@kubb/ast'\nimport type { Config, NormalizedPlugin } from '@kubb/core'\nimport type { BarrelType } from '../types.ts'\nimport { getBarrelFiles } from './getBarrelFiles.ts'\n\nexport type GeneratePerPluginBarrelParams = {\n barrelType: BarrelType\n plugin: NormalizedPlugin\n files: ReadonlyArray<FileNode>\n config: Config\n}\n\n/**\n * Generates barrel files for a single plugin's output directory.\n *\n * The barrel file is placed at `resolve(config.root, config.output.path, plugin.options.output.path)/index.ts`\n * and re-exports all files generated by that plugin, using the given `barrelType` strategy.\n *\n * Note: `plugin.options.output.path` is relative to `config.output.path`, not to `config.root`.\n * Files generated by plugins land at `config.root + config.output.path + plugin.output.path`,\n * so the barrel directory must be resolved with all three segments.\n */\nexport function generatePerPluginBarrel({ barrelType, plugin, files, config }: GeneratePerPluginBarrelParams): Array<FileNode> {\n const outputPath = resolve(config.root, config.output.path, plugin.options.output.path)\n return getBarrelFiles(outputPath, files, barrelType)\n}\n","import { resolve } from 'node:path'\nimport type { FileNode } from '@kubb/ast'\nimport type { Config } from '@kubb/core'\nimport type { BarrelType } from '../types.ts'\nimport { getBarrelFiles } from './getBarrelFiles.ts'\n\nexport type GenerateRootBarrelParams = {\n barrelType: BarrelType\n files: ReadonlyArray<FileNode>\n config: Config\n}\n\n/**\n * Generates a root barrel file at `resolve(config.root, config.output.path)/index.ts`.\n *\n * The root barrel re-exports from all files across all plugins that are located\n * inside the root output directory, using the given `barrelType` strategy.\n *\n * In practice this re-exports the per-plugin barrels when `barrelType = 'propagate'`,\n * or all individual files when `barrelType = 'all'` or `'named'`.\n */\nexport function generateRootBarrel({ barrelType, files, config }: GenerateRootBarrelParams): Array<FileNode> {\n const outputPath = resolve(config.root, config.output.path)\n return getBarrelFiles(outputPath, files, barrelType)\n}\n","import { defineMiddleware } from '@kubb/core'\nimport type { KubbBuildStartContext, NormalizedPlugin } from '@kubb/core'\nimport './types.ts'\nimport type { BarrelType } from './types.ts'\nimport { generatePerPluginBarrel } from './utils/generatePerPluginBarrel.ts'\nimport { generateRootBarrel } from './utils/generateRootBarrel.ts'\n\n/**\n * Barrel-file generation middleware.\n *\n * When added to `config.middleware`, generates an `index.ts` barrel file for each\n * plugin that has `output.barrelType` set (or inherits it from `config.output.barrelType`),\n * as well as a root `index.ts` at `config.output.path` when `config.output.barrelType` is set.\n *\n * The `barrelType` option controls the re-export style:\n * - `'all'` — `export * from '...'` for each generated file\n * - `'named'` — `export { name1, name2 } from '...'` using each file's indexable sources\n * - `'propagate'` — like `'all'` with intermediate barrel files for sub-directories\n *\n * @example\n * ```ts\n * import { middlewareBarrel } from '@kubb/middleware-barrel'\n *\n * export default defineConfig({\n * output: { path: 'src/gen', barrelType: 'named' },\n * plugins: [\n * pluginTs({ output: { path: 'types', barrelType: 'all' } }),\n * pluginZod({ output: { path: 'schemas' } }),\n * ],\n * middleware: [middlewareBarrel],\n * })\n * ```\n */\nexport const middlewareBarrel = defineMiddleware({\n name: 'middleware-barrel',\n\n install(hooks) {\n let ctx: KubbBuildStartContext\n\n hooks.on('kubb:build:start', (buildCtx) => {\n ctx = buildCtx\n })\n\n hooks.on('kubb:plugin:end', ({ plugin }) => {\n if (!ctx) return\n\n // At runtime the plugin in kubb:plugin:end is always a NormalizedPlugin;\n // KubbPluginEndContext types it as Plugin for public API simplicity.\n const normalizedPlugin = plugin as NormalizedPlugin\n const pluginOutput = normalizedPlugin.options.output as { barrelType?: BarrelType | false } | undefined\n const rootOutput = ctx.config.output as { barrelType?: BarrelType | false }\n const barrelType = pluginOutput?.barrelType !== undefined ? pluginOutput.barrelType : rootOutput.barrelType\n\n if (!barrelType) return\n\n const barrelFiles = generatePerPluginBarrel({\n barrelType,\n plugin: normalizedPlugin,\n files: ctx.files,\n config: ctx.config,\n })\n\n if (barrelFiles.length > 0) {\n ctx.upsertFile(...barrelFiles)\n }\n })\n\n hooks.on('kubb:plugins:end', ({ files, config, upsertFile }) => {\n const rootOutput = config.output as { barrelType?: BarrelType | false }\n const rootBarrelType = rootOutput.barrelType\n\n if (!rootBarrelType) return\n\n const rootBarrelFiles = generateRootBarrel({\n barrelType: rootBarrelType,\n files,\n config,\n })\n\n if (rootBarrelFiles.length > 0) {\n upsertFile(...rootBarrelFiles)\n }\n })\n },\n})\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -189,11 +189,15 @@ function getBarrelFiles(outputPath, files, barrelType) {
|
|
|
189
189
|
/**
|
|
190
190
|
* Generates barrel files for a single plugin's output directory.
|
|
191
191
|
*
|
|
192
|
-
* The barrel file is placed at `resolve(config.root, plugin.options.output.path)/index.ts`
|
|
192
|
+
* The barrel file is placed at `resolve(config.root, config.output.path, plugin.options.output.path)/index.ts`
|
|
193
193
|
* and re-exports all files generated by that plugin, using the given `barrelType` strategy.
|
|
194
|
+
*
|
|
195
|
+
* Note: `plugin.options.output.path` is relative to `config.output.path`, not to `config.root`.
|
|
196
|
+
* Files generated by plugins land at `config.root + config.output.path + plugin.output.path`,
|
|
197
|
+
* so the barrel directory must be resolved with all three segments.
|
|
194
198
|
*/
|
|
195
199
|
function generatePerPluginBarrel({ barrelType, plugin, files, config }) {
|
|
196
|
-
return getBarrelFiles(resolve(config.root, plugin.options.output.path), files, barrelType);
|
|
200
|
+
return getBarrelFiles(resolve(config.root, config.output.path, plugin.options.output.path), files, barrelType);
|
|
197
201
|
}
|
|
198
202
|
//#endregion
|
|
199
203
|
//#region src/utils/generateRootBarrel.ts
|
|
@@ -259,16 +263,15 @@ const middlewareBarrel = defineMiddleware({
|
|
|
259
263
|
});
|
|
260
264
|
if (barrelFiles.length > 0) ctx.upsertFile(...barrelFiles);
|
|
261
265
|
});
|
|
262
|
-
hooks.on("kubb:
|
|
263
|
-
|
|
264
|
-
const rootBarrelType = ctx.config.output.barrelType;
|
|
266
|
+
hooks.on("kubb:plugins:end", ({ files, config, upsertFile }) => {
|
|
267
|
+
const rootBarrelType = config.output.barrelType;
|
|
265
268
|
if (!rootBarrelType) return;
|
|
266
269
|
const rootBarrelFiles = generateRootBarrel({
|
|
267
270
|
barrelType: rootBarrelType,
|
|
268
|
-
files
|
|
269
|
-
config
|
|
271
|
+
files,
|
|
272
|
+
config
|
|
270
273
|
});
|
|
271
|
-
if (rootBarrelFiles.length > 0)
|
|
274
|
+
if (rootBarrelFiles.length > 0) upsertFile(...rootBarrelFiles);
|
|
272
275
|
});
|
|
273
276
|
}
|
|
274
277
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/constants.ts","../src/utils/TreeNode.ts","../src/utils/getBarrelFiles.ts","../src/utils/generatePerPluginBarrel.ts","../src/utils/generateRootBarrel.ts","../src/middleware.ts"],"sourcesContent":["/**\n * Base file name for barrel files (without extension).\n */\nexport const BARREL_BASENAME = 'index' as const\n\n/**\n * Full file name for barrel files (with extension).\n */\nexport const BARREL_FILENAME = 'index.ts' as const\n","import { posix } from 'node:path'\n\n/**\n * A node in a directory tree used to compute barrel file exports.\n *\n * Each `TreeNode` represents either a directory or a file entry.\n * Directory nodes have `children`; file nodes have an empty `children` array.\n */\nexport type TreeNode = {\n /**\n * Absolute path of the directory (root of this subtree) or file.\n */\n path: string\n /**\n * Child nodes (sub-directories and files) within this directory.\n */\n children: Array<TreeNode>\n /**\n * `true` when this node represents a file (leaf node).\n */\n isFile: boolean\n}\n\n/**\n * Builds a `TreeNode` directory tree from a list of absolute file paths.\n *\n * All `filePaths` must be inside `rootPath`. Paths that are outside\n * the root or that equal the root are silently ignored.\n *\n * @example\n * ```ts\n * const tree = buildTree('/src/gen/types', [\n * '/src/gen/types/pet.ts',\n * '/src/gen/types/user.ts',\n * '/src/gen/types/pets/listPets.ts',\n * ])\n * ```\n */\nexport function buildTree(rootPath: string, filePaths: ReadonlyArray<string>): TreeNode {\n const root: TreeNode = { path: rootPath, children: [], isFile: false }\n\n for (const filePath of filePaths) {\n // Only include files inside rootPath\n if (!filePath.startsWith(rootPath + posix.sep) && !filePath.startsWith(rootPath + '/')) {\n continue\n }\n\n const relative = filePath.slice(rootPath.length).replace(/^\\//g, '').replace(/^\\\\/g, '')\n const parts = relative.split(/[/\\\\]/).filter(Boolean)\n\n let current = root\n for (let i = 0; i < parts.length; i++) {\n const isLast = i === parts.length - 1\n const part = parts[i]!\n const childPath = `${current.path}/${part}`\n\n let child = current.children.find((c) => c.path === childPath)\n if (!child) {\n child = { path: childPath, children: [], isFile: isLast }\n current.children.push(child)\n }\n current = child\n }\n }\n\n return root\n}\n","import { createExport, createFile } from '@kubb/ast'\nimport type { FileNode } from '@kubb/ast'\nimport { BARREL_BASENAME, BARREL_FILENAME } from '../constants.ts'\nimport type { BarrelType } from '../types.ts'\nimport { buildTree, type TreeNode } from './TreeNode.ts'\n\n/**\n * Derives a relative module specifier (no extension) from an absolute `filePath`\n * relative to an absolute `fromDir`.\n *\n * @example\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/pet.ts') // './pet'\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/tags/tag.ts') // './tags/tag'\n */\nfunction toRelativeModulePath(fromDir: string, filePath: string): string {\n const relative = filePath.slice(fromDir.length).replace(/^[/\\\\]/g, '')\n // Strip extension\n const withoutExt = relative.replace(/\\.[^/.]+$/, '')\n return `./${withoutExt}`\n}\n\n/**\n * Generates barrel `FileNode[]` for a given directory tree node using the `'all'` strategy:\n * each leaf file gets a `export * from './relPath'` in the barrel of its nearest ancestor directory.\n *\n * Only a single barrel file (at `treeNode.path`) is generated — sub-directory files are referenced\n * with their full relative path from `treeNode.path`.\n */\nfunction getBarrelFilesAll(treeNode: TreeNode, _sourceFiles: ReadonlyArray<FileNode>): Array<FileNode> {\n // Collect all source file paths under this node (excluding barrel files themselves)\n const leafPaths = collectLeafPaths(treeNode).filter((p) => !p.endsWith(`/${BARREL_FILENAME}`))\n\n if (leafPaths.length === 0) return []\n\n const barrelPath = `${treeNode.path}/${BARREL_FILENAME}`\n const exports = leafPaths.map((filePath) =>\n createExport({\n path: toRelativeModulePath(treeNode.path, filePath),\n }),\n )\n\n return [\n createFile({\n baseName: BARREL_FILENAME,\n path: barrelPath,\n exports,\n sources: [],\n imports: [],\n }),\n ]\n}\n\n/**\n * Generates barrel `FileNode[]` for a given directory tree node using the `'named'` strategy:\n * each indexable source in each leaf file gets an individual named `export { name } from '...'`.\n */\nfunction getBarrelFilesNamed(treeNode: TreeNode, sourceFiles: ReadonlyArray<FileNode>): Array<FileNode> {\n const leafPaths = collectLeafPaths(treeNode).filter((p) => !p.endsWith(`/${BARREL_FILENAME}`))\n\n if (leafPaths.length === 0) return []\n\n const barrelPath = `${treeNode.path}/${BARREL_FILENAME}`\n const exports: ReturnType<typeof createExport>[] = []\n\n for (const filePath of leafPaths) {\n const sourceFile = sourceFiles.find((f) => f.path === filePath)\n if (!sourceFile) {\n // Fall back to wildcard if the source file is not in our set\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\n continue\n }\n\n const indexableSources = sourceFile.sources.filter((s) => s.isIndexable && s.name)\n if (indexableSources.length === 0) {\n // No named exports: fall back to wildcard\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\n continue\n }\n\n const names = indexableSources.map((s) => s.name as string)\n exports.push(\n createExport({\n name: names,\n path: toRelativeModulePath(treeNode.path, filePath),\n }),\n )\n }\n\n if (exports.length === 0) return []\n\n return [\n createFile({\n baseName: BARREL_FILENAME,\n path: barrelPath,\n exports,\n sources: [],\n imports: [],\n }),\n ]\n}\n\n/**\n * Generates barrel `FileNode[]` for a given directory tree node using the `'propagate'` strategy:\n * like `'all'` but also generates intermediate barrel files for every sub-directory, so that\n * consumers can import from any depth.\n *\n * Leaf barrels export directly from their files; parent barrels export from their sub-barrel files.\n */\nfunction getBarrelFilesPropagate(treeNode: TreeNode): Array<FileNode> {\n return collectPropagatedBarrels(treeNode)\n}\n\nfunction collectPropagatedBarrels(node: TreeNode): Array<FileNode> {\n const result: Array<FileNode> = []\n const barrelExports: ReturnType<typeof createExport>[] = []\n\n for (const child of node.children) {\n if (child.isFile) {\n if (!child.path.endsWith(`/${BARREL_FILENAME}`)) {\n barrelExports.push(createExport({ path: toRelativeModulePath(node.path, child.path) }))\n }\n } else {\n // Recurse into sub-directory\n const subBarrels = collectPropagatedBarrels(child)\n result.push(...subBarrels)\n\n // Export the sub-directory's barrel (not individual files)\n const subBarrelPath = `${child.path}/${BARREL_BASENAME}`\n barrelExports.push(createExport({ path: toRelativeModulePath(node.path, subBarrelPath) }))\n }\n }\n\n if (barrelExports.length > 0) {\n result.push(\n createFile({\n baseName: BARREL_FILENAME,\n path: `${node.path}/${BARREL_FILENAME}`,\n exports: barrelExports,\n sources: [],\n imports: [],\n }),\n )\n }\n\n return result\n}\n\n/**\n * Collects all leaf (file) paths within a tree node recursively.\n */\nfunction collectLeafPaths(node: TreeNode): Array<string> {\n if (node.isFile) return [node.path]\n return node.children.flatMap((c) => collectLeafPaths(c))\n}\n\n/**\n * Generates barrel `FileNode[]` for a directory rooted at `outputPath`, given the full set of\n * generated source `files`, using the specified `barrelType` strategy.\n *\n * Files not located inside `outputPath` are excluded automatically.\n *\n * @param outputPath Absolute path to the output directory.\n * @param files All generated files (across all plugins).\n * @param barrelType Barrel generation strategy.\n */\nexport function getBarrelFiles(outputPath: string, files: ReadonlyArray<FileNode>, barrelType: BarrelType): Array<FileNode> {\n // Only include files that live inside this outputPath\n const relevantFiles = files.filter((f) => {\n const normalizedFilePath = f.path.replace(/\\\\/g, '/')\n const normalizedOutputPath = outputPath.replace(/\\\\/g, '/')\n return normalizedFilePath.startsWith(normalizedOutputPath + '/') && !normalizedFilePath.endsWith(`/${BARREL_FILENAME}`)\n })\n\n if (relevantFiles.length === 0) return []\n\n const tree = buildTree(outputPath, relevantFiles.map((f) => f.path))\n\n switch (barrelType) {\n case 'all':\n return getBarrelFilesAll(tree, relevantFiles)\n case 'named':\n return getBarrelFilesNamed(tree, relevantFiles)\n case 'propagate':\n return getBarrelFilesPropagate(tree)\n default:\n return []\n }\n}\n","import { resolve } from 'node:path'\nimport type { FileNode } from '@kubb/ast'\nimport type { Config, NormalizedPlugin } from '@kubb/core'\nimport type { BarrelType } from '../types.ts'\nimport { getBarrelFiles } from './getBarrelFiles.ts'\n\nexport type GeneratePerPluginBarrelParams = {\n barrelType: BarrelType\n plugin: NormalizedPlugin\n files: ReadonlyArray<FileNode>\n config: Config\n}\n\n/**\n * Generates barrel files for a single plugin's output directory.\n *\n * The barrel file is placed at `resolve(config.root, plugin.options.output.path)/index.ts`\n * and re-exports all files generated by that plugin, using the given `barrelType` strategy.\n */\nexport function generatePerPluginBarrel({ barrelType, plugin, files, config }: GeneratePerPluginBarrelParams): Array<FileNode> {\n const outputPath = resolve(config.root, plugin.options.output.path)\n return getBarrelFiles(outputPath, files, barrelType)\n}\n","import { resolve } from 'node:path'\nimport type { FileNode } from '@kubb/ast'\nimport type { Config } from '@kubb/core'\nimport type { BarrelType } from '../types.ts'\nimport { getBarrelFiles } from './getBarrelFiles.ts'\n\nexport type GenerateRootBarrelParams = {\n barrelType: BarrelType\n files: ReadonlyArray<FileNode>\n config: Config\n}\n\n/**\n * Generates a root barrel file at `resolve(config.root, config.output.path)/index.ts`.\n *\n * The root barrel re-exports from all files across all plugins that are located\n * inside the root output directory, using the given `barrelType` strategy.\n *\n * In practice this re-exports the per-plugin barrels when `barrelType = 'propagate'`,\n * or all individual files when `barrelType = 'all'` or `'named'`.\n */\nexport function generateRootBarrel({ barrelType, files, config }: GenerateRootBarrelParams): Array<FileNode> {\n const outputPath = resolve(config.root, config.output.path)\n return getBarrelFiles(outputPath, files, barrelType)\n}\n","import { defineMiddleware } from '@kubb/core'\nimport type { KubbBuildStartContext, NormalizedPlugin } from '@kubb/core'\nimport './types.ts'\nimport type { BarrelType } from './types.ts'\nimport { generatePerPluginBarrel } from './utils/generatePerPluginBarrel.ts'\nimport { generateRootBarrel } from './utils/generateRootBarrel.ts'\n\n/**\n * Barrel-file generation middleware.\n *\n * When added to `config.middleware`, generates an `index.ts` barrel file for each\n * plugin that has `output.barrelType` set (or inherits it from `config.output.barrelType`),\n * as well as a root `index.ts` at `config.output.path` when `config.output.barrelType` is set.\n *\n * The `barrelType` option controls the re-export style:\n * - `'all'` — `export * from '...'` for each generated file\n * - `'named'` — `export { name1, name2 } from '...'` using each file's indexable sources\n * - `'propagate'` — like `'all'` with intermediate barrel files for sub-directories\n *\n * @example\n * ```ts\n * import { middlewareBarrel } from '@kubb/middleware-barrel'\n *\n * export default defineConfig({\n * output: { path: 'src/gen', barrelType: 'named' },\n * plugins: [\n * pluginTs({ output: { path: 'types', barrelType: 'all' } }),\n * pluginZod({ output: { path: 'schemas' } }),\n * ],\n * middleware: [middlewareBarrel],\n * })\n * ```\n */\nexport const middlewareBarrel = defineMiddleware({\n name: 'middleware-barrel',\n\n install(hooks) {\n let ctx: KubbBuildStartContext\n\n hooks.on('kubb:build:start', (buildCtx) => {\n ctx = buildCtx\n })\n\n hooks.on('kubb:plugin:end', ({ plugin }) => {\n if (!ctx) return\n\n // At runtime the plugin in kubb:plugin:end is always a NormalizedPlugin;\n // KubbPluginEndContext types it as Plugin for public API simplicity.\n const normalizedPlugin = plugin as NormalizedPlugin\n const pluginOutput = normalizedPlugin.options.output as { barrelType?: BarrelType | false } | undefined\n const rootOutput = ctx.config.output as { barrelType?: BarrelType | false }\n const barrelType = pluginOutput?.barrelType !== undefined ? pluginOutput.barrelType : rootOutput.barrelType\n\n if (!barrelType) return\n\n const barrelFiles = generatePerPluginBarrel({\n barrelType,\n plugin: normalizedPlugin,\n files: ctx.files,\n config: ctx.config,\n })\n\n if (barrelFiles.length > 0) {\n ctx.upsertFile(...barrelFiles)\n }\n })\n\n hooks.on('kubb:build:end', () => {\n if (!ctx) return\n\n const rootOutput = ctx.config.output as { barrelType?: BarrelType | false }\n const rootBarrelType = rootOutput.barrelType\n\n if (!rootBarrelType) return\n\n const rootBarrelFiles = generateRootBarrel({\n barrelType: rootBarrelType,\n files: ctx.files,\n config: ctx.config,\n })\n\n if (rootBarrelFiles.length > 0) {\n ctx.upsertFile(...rootBarrelFiles)\n }\n })\n },\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/constants.ts","../src/utils/TreeNode.ts","../src/utils/getBarrelFiles.ts","../src/utils/generatePerPluginBarrel.ts","../src/utils/generateRootBarrel.ts","../src/middleware.ts"],"sourcesContent":["/**\n * Base file name for barrel files (without extension).\n */\nexport const BARREL_BASENAME = 'index' as const\n\n/**\n * Full file name for barrel files (with extension).\n */\nexport const BARREL_FILENAME = 'index.ts' as const\n","import { posix } from 'node:path'\n\n/**\n * A node in a directory tree used to compute barrel file exports.\n *\n * Each `TreeNode` represents either a directory or a file entry.\n * Directory nodes have `children`; file nodes have an empty `children` array.\n */\nexport type TreeNode = {\n /**\n * Absolute path of the directory (root of this subtree) or file.\n */\n path: string\n /**\n * Child nodes (sub-directories and files) within this directory.\n */\n children: Array<TreeNode>\n /**\n * `true` when this node represents a file (leaf node).\n */\n isFile: boolean\n}\n\n/**\n * Builds a `TreeNode` directory tree from a list of absolute file paths.\n *\n * All `filePaths` must be inside `rootPath`. Paths that are outside\n * the root or that equal the root are silently ignored.\n *\n * @example\n * ```ts\n * const tree = buildTree('/src/gen/types', [\n * '/src/gen/types/pet.ts',\n * '/src/gen/types/user.ts',\n * '/src/gen/types/pets/listPets.ts',\n * ])\n * ```\n */\nexport function buildTree(rootPath: string, filePaths: ReadonlyArray<string>): TreeNode {\n const root: TreeNode = { path: rootPath, children: [], isFile: false }\n\n for (const filePath of filePaths) {\n // Only include files inside rootPath\n if (!filePath.startsWith(rootPath + posix.sep) && !filePath.startsWith(rootPath + '/')) {\n continue\n }\n\n const relative = filePath.slice(rootPath.length).replace(/^\\//g, '').replace(/^\\\\/g, '')\n const parts = relative.split(/[/\\\\]/).filter(Boolean)\n\n let current = root\n for (let i = 0; i < parts.length; i++) {\n const isLast = i === parts.length - 1\n const part = parts[i]!\n const childPath = `${current.path}/${part}`\n\n let child = current.children.find((c) => c.path === childPath)\n if (!child) {\n child = { path: childPath, children: [], isFile: isLast }\n current.children.push(child)\n }\n current = child\n }\n }\n\n return root\n}\n","import { createExport, createFile } from '@kubb/ast'\nimport type { FileNode } from '@kubb/ast'\nimport { BARREL_BASENAME, BARREL_FILENAME } from '../constants.ts'\nimport type { BarrelType } from '../types.ts'\nimport { buildTree, type TreeNode } from './TreeNode.ts'\n\n/**\n * Derives a relative module specifier (no extension) from an absolute `filePath`\n * relative to an absolute `fromDir`.\n *\n * @example\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/pet.ts') // './pet'\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/tags/tag.ts') // './tags/tag'\n */\nfunction toRelativeModulePath(fromDir: string, filePath: string): string {\n const relative = filePath.slice(fromDir.length).replace(/^[/\\\\]/g, '')\n // Strip extension\n const withoutExt = relative.replace(/\\.[^/.]+$/, '')\n return `./${withoutExt}`\n}\n\n/**\n * Generates barrel `FileNode[]` for a given directory tree node using the `'all'` strategy:\n * each leaf file gets a `export * from './relPath'` in the barrel of its nearest ancestor directory.\n *\n * Only a single barrel file (at `treeNode.path`) is generated — sub-directory files are referenced\n * with their full relative path from `treeNode.path`.\n */\nfunction getBarrelFilesAll(treeNode: TreeNode, _sourceFiles: ReadonlyArray<FileNode>): Array<FileNode> {\n // Collect all source file paths under this node (excluding barrel files themselves)\n const leafPaths = collectLeafPaths(treeNode).filter((p) => !p.endsWith(`/${BARREL_FILENAME}`))\n\n if (leafPaths.length === 0) return []\n\n const barrelPath = `${treeNode.path}/${BARREL_FILENAME}`\n const exports = leafPaths.map((filePath) =>\n createExport({\n path: toRelativeModulePath(treeNode.path, filePath),\n }),\n )\n\n return [\n createFile({\n baseName: BARREL_FILENAME,\n path: barrelPath,\n exports,\n sources: [],\n imports: [],\n }),\n ]\n}\n\n/**\n * Generates barrel `FileNode[]` for a given directory tree node using the `'named'` strategy:\n * each indexable source in each leaf file gets an individual named `export { name } from '...'`.\n */\nfunction getBarrelFilesNamed(treeNode: TreeNode, sourceFiles: ReadonlyArray<FileNode>): Array<FileNode> {\n const leafPaths = collectLeafPaths(treeNode).filter((p) => !p.endsWith(`/${BARREL_FILENAME}`))\n\n if (leafPaths.length === 0) return []\n\n const barrelPath = `${treeNode.path}/${BARREL_FILENAME}`\n const exports: ReturnType<typeof createExport>[] = []\n\n for (const filePath of leafPaths) {\n const sourceFile = sourceFiles.find((f) => f.path === filePath)\n if (!sourceFile) {\n // Fall back to wildcard if the source file is not in our set\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\n continue\n }\n\n const indexableSources = sourceFile.sources.filter((s) => s.isIndexable && s.name)\n if (indexableSources.length === 0) {\n // No named exports: fall back to wildcard\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\n continue\n }\n\n const names = indexableSources.map((s) => s.name as string)\n exports.push(\n createExport({\n name: names,\n path: toRelativeModulePath(treeNode.path, filePath),\n }),\n )\n }\n\n if (exports.length === 0) return []\n\n return [\n createFile({\n baseName: BARREL_FILENAME,\n path: barrelPath,\n exports,\n sources: [],\n imports: [],\n }),\n ]\n}\n\n/**\n * Generates barrel `FileNode[]` for a given directory tree node using the `'propagate'` strategy:\n * like `'all'` but also generates intermediate barrel files for every sub-directory, so that\n * consumers can import from any depth.\n *\n * Leaf barrels export directly from their files; parent barrels export from their sub-barrel files.\n */\nfunction getBarrelFilesPropagate(treeNode: TreeNode): Array<FileNode> {\n return collectPropagatedBarrels(treeNode)\n}\n\nfunction collectPropagatedBarrels(node: TreeNode): Array<FileNode> {\n const result: Array<FileNode> = []\n const barrelExports: ReturnType<typeof createExport>[] = []\n\n for (const child of node.children) {\n if (child.isFile) {\n if (!child.path.endsWith(`/${BARREL_FILENAME}`)) {\n barrelExports.push(createExport({ path: toRelativeModulePath(node.path, child.path) }))\n }\n } else {\n // Recurse into sub-directory\n const subBarrels = collectPropagatedBarrels(child)\n result.push(...subBarrels)\n\n // Export the sub-directory's barrel (not individual files)\n const subBarrelPath = `${child.path}/${BARREL_BASENAME}`\n barrelExports.push(createExport({ path: toRelativeModulePath(node.path, subBarrelPath) }))\n }\n }\n\n if (barrelExports.length > 0) {\n result.push(\n createFile({\n baseName: BARREL_FILENAME,\n path: `${node.path}/${BARREL_FILENAME}`,\n exports: barrelExports,\n sources: [],\n imports: [],\n }),\n )\n }\n\n return result\n}\n\n/**\n * Collects all leaf (file) paths within a tree node recursively.\n */\nfunction collectLeafPaths(node: TreeNode): Array<string> {\n if (node.isFile) return [node.path]\n return node.children.flatMap((c) => collectLeafPaths(c))\n}\n\n/**\n * Generates barrel `FileNode[]` for a directory rooted at `outputPath`, given the full set of\n * generated source `files`, using the specified `barrelType` strategy.\n *\n * Files not located inside `outputPath` are excluded automatically.\n *\n * @param outputPath Absolute path to the output directory.\n * @param files All generated files (across all plugins).\n * @param barrelType Barrel generation strategy.\n */\nexport function getBarrelFiles(outputPath: string, files: ReadonlyArray<FileNode>, barrelType: BarrelType): Array<FileNode> {\n // Only include files that live inside this outputPath\n const relevantFiles = files.filter((f) => {\n const normalizedFilePath = f.path.replace(/\\\\/g, '/')\n const normalizedOutputPath = outputPath.replace(/\\\\/g, '/')\n return normalizedFilePath.startsWith(normalizedOutputPath + '/') && !normalizedFilePath.endsWith(`/${BARREL_FILENAME}`)\n })\n\n if (relevantFiles.length === 0) return []\n\n const tree = buildTree(\n outputPath,\n relevantFiles.map((f) => f.path),\n )\n\n switch (barrelType) {\n case 'all':\n return getBarrelFilesAll(tree, relevantFiles)\n case 'named':\n return getBarrelFilesNamed(tree, relevantFiles)\n case 'propagate':\n return getBarrelFilesPropagate(tree)\n default:\n return []\n }\n}\n","import { resolve } from 'node:path'\nimport type { FileNode } from '@kubb/ast'\nimport type { Config, NormalizedPlugin } from '@kubb/core'\nimport type { BarrelType } from '../types.ts'\nimport { getBarrelFiles } from './getBarrelFiles.ts'\n\nexport type GeneratePerPluginBarrelParams = {\n barrelType: BarrelType\n plugin: NormalizedPlugin\n files: ReadonlyArray<FileNode>\n config: Config\n}\n\n/**\n * Generates barrel files for a single plugin's output directory.\n *\n * The barrel file is placed at `resolve(config.root, config.output.path, plugin.options.output.path)/index.ts`\n * and re-exports all files generated by that plugin, using the given `barrelType` strategy.\n *\n * Note: `plugin.options.output.path` is relative to `config.output.path`, not to `config.root`.\n * Files generated by plugins land at `config.root + config.output.path + plugin.output.path`,\n * so the barrel directory must be resolved with all three segments.\n */\nexport function generatePerPluginBarrel({ barrelType, plugin, files, config }: GeneratePerPluginBarrelParams): Array<FileNode> {\n const outputPath = resolve(config.root, config.output.path, plugin.options.output.path)\n return getBarrelFiles(outputPath, files, barrelType)\n}\n","import { resolve } from 'node:path'\nimport type { FileNode } from '@kubb/ast'\nimport type { Config } from '@kubb/core'\nimport type { BarrelType } from '../types.ts'\nimport { getBarrelFiles } from './getBarrelFiles.ts'\n\nexport type GenerateRootBarrelParams = {\n barrelType: BarrelType\n files: ReadonlyArray<FileNode>\n config: Config\n}\n\n/**\n * Generates a root barrel file at `resolve(config.root, config.output.path)/index.ts`.\n *\n * The root barrel re-exports from all files across all plugins that are located\n * inside the root output directory, using the given `barrelType` strategy.\n *\n * In practice this re-exports the per-plugin barrels when `barrelType = 'propagate'`,\n * or all individual files when `barrelType = 'all'` or `'named'`.\n */\nexport function generateRootBarrel({ barrelType, files, config }: GenerateRootBarrelParams): Array<FileNode> {\n const outputPath = resolve(config.root, config.output.path)\n return getBarrelFiles(outputPath, files, barrelType)\n}\n","import { defineMiddleware } from '@kubb/core'\nimport type { KubbBuildStartContext, NormalizedPlugin } from '@kubb/core'\nimport './types.ts'\nimport type { BarrelType } from './types.ts'\nimport { generatePerPluginBarrel } from './utils/generatePerPluginBarrel.ts'\nimport { generateRootBarrel } from './utils/generateRootBarrel.ts'\n\n/**\n * Barrel-file generation middleware.\n *\n * When added to `config.middleware`, generates an `index.ts` barrel file for each\n * plugin that has `output.barrelType` set (or inherits it from `config.output.barrelType`),\n * as well as a root `index.ts` at `config.output.path` when `config.output.barrelType` is set.\n *\n * The `barrelType` option controls the re-export style:\n * - `'all'` — `export * from '...'` for each generated file\n * - `'named'` — `export { name1, name2 } from '...'` using each file's indexable sources\n * - `'propagate'` — like `'all'` with intermediate barrel files for sub-directories\n *\n * @example\n * ```ts\n * import { middlewareBarrel } from '@kubb/middleware-barrel'\n *\n * export default defineConfig({\n * output: { path: 'src/gen', barrelType: 'named' },\n * plugins: [\n * pluginTs({ output: { path: 'types', barrelType: 'all' } }),\n * pluginZod({ output: { path: 'schemas' } }),\n * ],\n * middleware: [middlewareBarrel],\n * })\n * ```\n */\nexport const middlewareBarrel = defineMiddleware({\n name: 'middleware-barrel',\n\n install(hooks) {\n let ctx: KubbBuildStartContext\n\n hooks.on('kubb:build:start', (buildCtx) => {\n ctx = buildCtx\n })\n\n hooks.on('kubb:plugin:end', ({ plugin }) => {\n if (!ctx) return\n\n // At runtime the plugin in kubb:plugin:end is always a NormalizedPlugin;\n // KubbPluginEndContext types it as Plugin for public API simplicity.\n const normalizedPlugin = plugin as NormalizedPlugin\n const pluginOutput = normalizedPlugin.options.output as { barrelType?: BarrelType | false } | undefined\n const rootOutput = ctx.config.output as { barrelType?: BarrelType | false }\n const barrelType = pluginOutput?.barrelType !== undefined ? pluginOutput.barrelType : rootOutput.barrelType\n\n if (!barrelType) return\n\n const barrelFiles = generatePerPluginBarrel({\n barrelType,\n plugin: normalizedPlugin,\n files: ctx.files,\n config: ctx.config,\n })\n\n if (barrelFiles.length > 0) {\n ctx.upsertFile(...barrelFiles)\n }\n })\n\n hooks.on('kubb:plugins:end', ({ files, config, upsertFile }) => {\n const rootOutput = config.output as { barrelType?: BarrelType | false }\n const rootBarrelType = rootOutput.barrelType\n\n if (!rootBarrelType) return\n\n const rootBarrelFiles = generateRootBarrel({\n barrelType: rootBarrelType,\n files,\n config,\n })\n\n if (rootBarrelFiles.length > 0) {\n upsertFile(...rootBarrelFiles)\n }\n })\n },\n})\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/middleware-barrel",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.56",
|
|
4
4
|
"description": "Barrel-file generation middleware for Kubb. Generates index.ts barrel files for each plugin's output directory and a root index.ts after all plugins have run.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"barrel",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"registry": "https://registry.npmjs.org/"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@kubb/core": "5.0.0-alpha.
|
|
47
|
+
"@kubb/core": "5.0.0-alpha.56"
|
|
48
48
|
},
|
|
49
49
|
"engines": {
|
|
50
50
|
"node": ">=22"
|
package/src/middleware.ts
CHANGED
|
@@ -65,22 +65,20 @@ export const middlewareBarrel = defineMiddleware({
|
|
|
65
65
|
}
|
|
66
66
|
})
|
|
67
67
|
|
|
68
|
-
hooks.on('kubb:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const rootOutput = ctx.config.output as { barrelType?: BarrelType | false }
|
|
68
|
+
hooks.on('kubb:plugins:end', ({ files, config, upsertFile }) => {
|
|
69
|
+
const rootOutput = config.output as { barrelType?: BarrelType | false }
|
|
72
70
|
const rootBarrelType = rootOutput.barrelType
|
|
73
71
|
|
|
74
72
|
if (!rootBarrelType) return
|
|
75
73
|
|
|
76
74
|
const rootBarrelFiles = generateRootBarrel({
|
|
77
75
|
barrelType: rootBarrelType,
|
|
78
|
-
files
|
|
79
|
-
config
|
|
76
|
+
files,
|
|
77
|
+
config,
|
|
80
78
|
})
|
|
81
79
|
|
|
82
80
|
if (rootBarrelFiles.length > 0) {
|
|
83
|
-
|
|
81
|
+
upsertFile(...rootBarrelFiles)
|
|
84
82
|
}
|
|
85
83
|
})
|
|
86
84
|
},
|
|
@@ -14,10 +14,14 @@ export type GeneratePerPluginBarrelParams = {
|
|
|
14
14
|
/**
|
|
15
15
|
* Generates barrel files for a single plugin's output directory.
|
|
16
16
|
*
|
|
17
|
-
* The barrel file is placed at `resolve(config.root, plugin.options.output.path)/index.ts`
|
|
17
|
+
* The barrel file is placed at `resolve(config.root, config.output.path, plugin.options.output.path)/index.ts`
|
|
18
18
|
* and re-exports all files generated by that plugin, using the given `barrelType` strategy.
|
|
19
|
+
*
|
|
20
|
+
* Note: `plugin.options.output.path` is relative to `config.output.path`, not to `config.root`.
|
|
21
|
+
* Files generated by plugins land at `config.root + config.output.path + plugin.output.path`,
|
|
22
|
+
* so the barrel directory must be resolved with all three segments.
|
|
19
23
|
*/
|
|
20
24
|
export function generatePerPluginBarrel({ barrelType, plugin, files, config }: GeneratePerPluginBarrelParams): Array<FileNode> {
|
|
21
|
-
const outputPath = resolve(config.root, plugin.options.output.path)
|
|
25
|
+
const outputPath = resolve(config.root, config.output.path, plugin.options.output.path)
|
|
22
26
|
return getBarrelFiles(outputPath, files, barrelType)
|
|
23
27
|
}
|
|
@@ -173,7 +173,10 @@ export function getBarrelFiles(outputPath: string, files: ReadonlyArray<FileNode
|
|
|
173
173
|
|
|
174
174
|
if (relevantFiles.length === 0) return []
|
|
175
175
|
|
|
176
|
-
const tree = buildTree(
|
|
176
|
+
const tree = buildTree(
|
|
177
|
+
outputPath,
|
|
178
|
+
relevantFiles.map((f) => f.path),
|
|
179
|
+
)
|
|
177
180
|
|
|
178
181
|
switch (barrelType) {
|
|
179
182
|
case 'all':
|