@kubb/middleware-barrel 5.0.0-alpha.61 → 5.0.0-alpha.62
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 +4 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4 -9
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/middleware.ts +6 -17
package/dist/index.cjs
CHANGED
|
@@ -270,17 +270,15 @@ const middlewareBarrel = (0, _kubb_core.defineMiddleware)({
|
|
|
270
270
|
name: "middleware-barrel",
|
|
271
271
|
install(hooks) {
|
|
272
272
|
let ctx;
|
|
273
|
-
const
|
|
273
|
+
const excludedPaths = /* @__PURE__ */ new Set();
|
|
274
274
|
hooks.on("kubb:build:start", (buildCtx) => {
|
|
275
275
|
ctx = buildCtx;
|
|
276
276
|
});
|
|
277
277
|
hooks.on("kubb:plugin:end", ({ plugin }) => {
|
|
278
278
|
if (!ctx) return;
|
|
279
|
-
const
|
|
280
|
-
const barrelType = pluginOutput?.barrelType !== void 0 ? pluginOutput.barrelType : ctx.config.output.barrelType ?? "all";
|
|
279
|
+
const barrelType = plugin.options.output?.barrelType ?? ctx.config.output.barrelType ?? "all";
|
|
281
280
|
if (!barrelType) {
|
|
282
|
-
|
|
283
|
-
excludedOutputPaths.push(outputPath);
|
|
281
|
+
excludedPaths.add((0, node_path.resolve)(ctx.config.root, ctx.config.output.path, plugin.options.output.path));
|
|
284
282
|
return;
|
|
285
283
|
}
|
|
286
284
|
const barrelFiles = generatePerPluginBarrel({
|
|
@@ -296,10 +294,7 @@ const middlewareBarrel = (0, _kubb_core.defineMiddleware)({
|
|
|
296
294
|
if (!rootBarrelType) return;
|
|
297
295
|
const rootBarrelFiles = generateRootBarrel({
|
|
298
296
|
barrelType: rootBarrelType,
|
|
299
|
-
files:
|
|
300
|
-
const normalizedPath = f.path.replace(/\\/g, "/");
|
|
301
|
-
return !excludedOutputPaths.some((excluded) => normalizedPath.startsWith(excluded.replace(/\\/g, "/") + "/"));
|
|
302
|
-
}) : files,
|
|
297
|
+
files: excludedPaths.size > 0 ? files.filter((f) => ![...excludedPaths].some((excluded) => f.path.startsWith(excluded + "/"))) : files,
|
|
303
298
|
config
|
|
304
299
|
});
|
|
305
300
|
if (rootBarrelFiles.length > 0) upsertFile(...rootBarrelFiles);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["posix"],"sources":["../src/constants.ts","../src/utils/buildTree.ts","../src/utils/getBarrelFiles.ts","../src/utils/generatePerPluginBarrel.ts","../src/utils/generateRootBarrel.ts","../src/middleware.ts"],"sourcesContent":["\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 BuildTree = {\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<BuildTree>\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>): BuildTree {\n const root: BuildTree = { 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_FILENAME } from '../constants.ts'\nimport type { BarrelType } from '../types.ts'\nimport { buildTree, type BuildTree } from './buildTree.ts'\n\nconst SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx'])\n\n/**\n * Derives a relative module specifier from an absolute `filePath` relative to an absolute `fromDir`.\n * The source extension is preserved so that `@kubb/parser-ts` can apply the `extNames` mapping\n * (e.g. `.ts` → `.js` for ESM output).\n *\n * @example\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/pet.ts') // './pet.ts'\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/tags/tag.ts') // './tags/tag.ts'\n */\nfunction toRelativeModulePath(fromDir: string, filePath: string): string {\n const relative = filePath.slice(fromDir.length).replace(/^[/\\\\]/g, '')\n return `./${relative}`\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: BuildTree, 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: ReturnType<typeof createExport>[] = []\n\n for (const filePath of leafPaths) {\n const sourceFile = sourceFiles.find((f) => f.path === filePath)\n // Skip files whose sources all have isIndexable: false (e.g. internal injected files)\n if (sourceFile && sourceFile.sources.length > 0 && sourceFile.sources.every((s) => !s.isIndexable)) {\n continue\n }\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\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 `'named'` strategy:\n * each indexable source in each leaf file gets an individual named `export { name } from '...'`.\n */\nfunction getBarrelFilesNamed(treeNode: BuildTree, 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 // If the file has explicit sources but none are indexable, skip it entirely.\n // Only fall back to wildcard when there are no sources at all (unknown exports).\n if (sourceFile.sources.length > 0) continue\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\n continue\n }\n\n const valueNames = indexableSources.filter((s) => !s.isTypeOnly).map((s) => s.name as string)\n const typeNames = indexableSources.filter((s) => s.isTypeOnly).map((s) => s.name as string)\n const modulePath = toRelativeModulePath(treeNode.path, filePath)\n\n if (valueNames.length > 0) {\n exports.push(createExport({ name: valueNames, path: modulePath }))\n }\n if (typeNames.length > 0) {\n exports.push(createExport({ name: typeNames, path: modulePath, isTypeOnly: true }))\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: BuildTree): Array<FileNode> {\n return collectPropagatedBarrels(treeNode)\n}\n\nfunction collectPropagatedBarrels(node: BuildTree): 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_FILENAME}`\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: BuildTree): 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 and have a recognised source extension\n const relevantFiles = files.filter((f) => {\n const normalizedFilePath = f.path.replace(/\\\\/g, '/')\n const normalizedOutputPath = outputPath.replace(/\\\\/g, '/')\n if (!normalizedFilePath.startsWith(normalizedOutputPath + '/')) return false\n if (normalizedFilePath.endsWith(`/${BARREL_FILENAME}`)) return false\n const dotIndex = normalizedFilePath.lastIndexOf('.')\n const ext = dotIndex === -1 ? '' : normalizedFilePath.slice(dotIndex)\n return SOURCE_EXTENSIONS.has(ext)\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\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\n return getBarrelFiles(outputPath, files, barrelType)\n}\n","import { defineMiddleware } from '@kubb/core'\nimport type { KubbBuildStartContext } 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\ndeclare global {\n namespace Kubb {\n interface PluginOptionsRegistry {\n output: {\n /**\n * Controls which barrel file (index.ts) is generated for this plugin's output directory.\n *\n * - `'all'` — `export * from '...'` for every generated file.\n * - `'named'` — `export { … } from '...'` using the file's named exports.\n * - `'propagate'` — like `'all'` but also generates intermediate barrel files.\n * - `false` — disable barrel generation for this plugin.\n *\n * When omitted, the root `config.output.barrelType` is used as the default.\n */\n barrelType?: BarrelType | false\n }\n }\n interface ConfigOptionsRegistry {\n output: {\n /**\n * Controls the root barrel file (index.ts) generated at `config.output.path`.\n *\n * - `'all'` — `export * from '...'` for every plugin's barrel.\n * - `'named'` — `export { … } from '...'` using the barrel's named exports.\n * - `'propagate'` — like `'all'` but also generates intermediate barrel files.\n * - `false` — disable root barrel generation.\n *\n * Individual plugins can override this via their own `output.barrelType`.\n */\n barrelType?: BarrelType | false\n }\n }\n }\n}\n\n/**\n * Barrel-file generation middleware.\n *\n * When added to `config.middleware`, generates an `index.ts` barrel file for each\n * plugin. When `output.barrelType` is omitted on a plugin it inherits from `config.output.barrelType`,\n * and when that is also omitted both default to `'all'`. Set `barrelType: false` to disable\n * barrel generation for a specific plugin or for the root entirely.\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 install(hooks) {\n let ctx: KubbBuildStartContext\n // Track output paths of plugins with barrelType: false so the root barrel\n // can exclude their files.\n const excludedOutputPaths: string[] = []\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 const pluginOutput = plugin.options.output\n const barrelType = pluginOutput?.barrelType !== undefined ? pluginOutput.barrelType : (ctx.config.output.barrelType ?? 'all')\n\n if (!barrelType) {\n // Remember this plugin's output path so we can exclude it from the root barrel\n const outputPath = plugin.options.output.path\n excludedOutputPaths.push(outputPath)\n return\n }\n\n const barrelFiles = generatePerPluginBarrel({\n barrelType,\n plugin,\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 rootBarrelType = config.output.barrelType ?? 'all'\n\n if (!rootBarrelType) return\n\n // Exclude files that belong to plugins with barrelType: false\n const filteredFiles =\n excludedOutputPaths.length > 0\n ? files.filter((f) => {\n const normalizedPath = f.path.replace(/\\\\/g, '/')\n return !excludedOutputPaths.some((excluded) => normalizedPath.startsWith(excluded.replace(/\\\\/g, '/') + '/'))\n })\n : files\n\n const rootBarrelFiles = generateRootBarrel({\n barrelType: rootBarrelType,\n files: filteredFiles,\n config,\n })\n\n if (rootBarrelFiles.length > 0) {\n 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/buildTree.ts","../src/utils/getBarrelFiles.ts","../src/utils/generatePerPluginBarrel.ts","../src/utils/generateRootBarrel.ts","../src/middleware.ts"],"sourcesContent":["\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 BuildTree = {\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<BuildTree>\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>): BuildTree {\n const root: BuildTree = { 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_FILENAME } from '../constants.ts'\nimport type { BarrelType } from '../types.ts'\nimport { buildTree, type BuildTree } from './buildTree.ts'\n\nconst SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx'])\n\n/**\n * Derives a relative module specifier from an absolute `filePath` relative to an absolute `fromDir`.\n * The source extension is preserved so that `@kubb/parser-ts` can apply the `extNames` mapping\n * (e.g. `.ts` → `.js` for ESM output).\n *\n * @example\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/pet.ts') // './pet.ts'\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/tags/tag.ts') // './tags/tag.ts'\n */\nfunction toRelativeModulePath(fromDir: string, filePath: string): string {\n const relative = filePath.slice(fromDir.length).replace(/^[/\\\\]/g, '')\n return `./${relative}`\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: BuildTree, 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: ReturnType<typeof createExport>[] = []\n\n for (const filePath of leafPaths) {\n const sourceFile = sourceFiles.find((f) => f.path === filePath)\n // Skip files whose sources all have isIndexable: false (e.g. internal injected files)\n if (sourceFile && sourceFile.sources.length > 0 && sourceFile.sources.every((s) => !s.isIndexable)) {\n continue\n }\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\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 `'named'` strategy:\n * each indexable source in each leaf file gets an individual named `export { name } from '...'`.\n */\nfunction getBarrelFilesNamed(treeNode: BuildTree, 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 // If the file has explicit sources but none are indexable, skip it entirely.\n // Only fall back to wildcard when there are no sources at all (unknown exports).\n if (sourceFile.sources.length > 0) continue\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\n continue\n }\n\n const valueNames = indexableSources.filter((s) => !s.isTypeOnly).map((s) => s.name as string)\n const typeNames = indexableSources.filter((s) => s.isTypeOnly).map((s) => s.name as string)\n const modulePath = toRelativeModulePath(treeNode.path, filePath)\n\n if (valueNames.length > 0) {\n exports.push(createExport({ name: valueNames, path: modulePath }))\n }\n if (typeNames.length > 0) {\n exports.push(createExport({ name: typeNames, path: modulePath, isTypeOnly: true }))\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: BuildTree): Array<FileNode> {\n return collectPropagatedBarrels(treeNode)\n}\n\nfunction collectPropagatedBarrels(node: BuildTree): 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_FILENAME}`\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: BuildTree): 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 and have a recognised source extension\n const relevantFiles = files.filter((f) => {\n const normalizedFilePath = f.path.replace(/\\\\/g, '/')\n const normalizedOutputPath = outputPath.replace(/\\\\/g, '/')\n if (!normalizedFilePath.startsWith(normalizedOutputPath + '/')) return false\n if (normalizedFilePath.endsWith(`/${BARREL_FILENAME}`)) return false\n const dotIndex = normalizedFilePath.lastIndexOf('.')\n const ext = dotIndex === -1 ? '' : normalizedFilePath.slice(dotIndex)\n return SOURCE_EXTENSIONS.has(ext)\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\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\n return getBarrelFiles(outputPath, files, barrelType)\n}\n","import { defineMiddleware } from '@kubb/core'\nimport type { KubbBuildStartContext } from '@kubb/core'\nimport type { BarrelType } from './types.ts'\nimport { generatePerPluginBarrel } from './utils/generatePerPluginBarrel.ts'\nimport { generateRootBarrel } from './utils/generateRootBarrel.ts'\nimport {resolve} from \"node:path\";\n\ndeclare global {\n namespace Kubb {\n interface PluginOptionsRegistry {\n output: {\n /**\n * Controls which barrel file (index.ts) is generated for this plugin's output directory.\n *\n * - `'all'` — `export * from '...'` for every generated file.\n * - `'named'` — `export { … } from '...'` using the file's named exports.\n * - `'propagate'` — like `'all'` but also generates intermediate barrel files.\n * - `false` — disable barrel generation for this plugin.\n *\n * When omitted, the root `config.output.barrelType` is used as the default.\n */\n barrelType?: BarrelType | false\n }\n }\n interface ConfigOptionsRegistry {\n output: {\n /**\n * Controls the root barrel file (index.ts) generated at `config.output.path`.\n *\n * - `'all'` — `export * from '...'` for every plugin's barrel.\n * - `'named'` — `export { … } from '...'` using the barrel's named exports.\n * - `'propagate'` — like `'all'` but also generates intermediate barrel files.\n * - `false` — disable root barrel generation.\n *\n * Individual plugins can override this via their own `output.barrelType`.\n */\n barrelType?: BarrelType | false\n }\n }\n }\n}\n\n/**\n * Barrel-file generation middleware.\n *\n * When added to `config.middleware`, generates an `index.ts` barrel file for each\n * plugin. When `output.barrelType` is omitted on a plugin it inherits from `config.output.barrelType`,\n * and when that is also omitted both default to `'all'`. Set `barrelType: false` to disable\n * barrel generation for a specific plugin or for the root entirely.\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 install(hooks) {\n let ctx: KubbBuildStartContext\n const excludedPaths = new Set<string>()\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 const barrelType = plugin.options.output?.barrelType ?? ctx.config.output.barrelType ?? 'all'\n\n if (!barrelType) {\n excludedPaths.add(resolve(ctx.config.root, ctx.config.output.path, plugin.options.output.path))\n return\n }\n\n const barrelFiles = generatePerPluginBarrel({\n barrelType,\n plugin,\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 rootBarrelType = config.output.barrelType ?? 'all'\n if (!rootBarrelType) return\n\n const filteredFiles =\n excludedPaths.size > 0\n ? files.filter((f) => ![...excludedPaths].some((excluded) => f.path.startsWith(excluded + '/')))\n : files\n\n const rootBarrelFiles = generateRootBarrel({\n barrelType: rootBarrelType,\n files: filteredFiles,\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
|
@@ -269,17 +269,15 @@ const middlewareBarrel = defineMiddleware({
|
|
|
269
269
|
name: "middleware-barrel",
|
|
270
270
|
install(hooks) {
|
|
271
271
|
let ctx;
|
|
272
|
-
const
|
|
272
|
+
const excludedPaths = /* @__PURE__ */ new Set();
|
|
273
273
|
hooks.on("kubb:build:start", (buildCtx) => {
|
|
274
274
|
ctx = buildCtx;
|
|
275
275
|
});
|
|
276
276
|
hooks.on("kubb:plugin:end", ({ plugin }) => {
|
|
277
277
|
if (!ctx) return;
|
|
278
|
-
const
|
|
279
|
-
const barrelType = pluginOutput?.barrelType !== void 0 ? pluginOutput.barrelType : ctx.config.output.barrelType ?? "all";
|
|
278
|
+
const barrelType = plugin.options.output?.barrelType ?? ctx.config.output.barrelType ?? "all";
|
|
280
279
|
if (!barrelType) {
|
|
281
|
-
|
|
282
|
-
excludedOutputPaths.push(outputPath);
|
|
280
|
+
excludedPaths.add(resolve(ctx.config.root, ctx.config.output.path, plugin.options.output.path));
|
|
283
281
|
return;
|
|
284
282
|
}
|
|
285
283
|
const barrelFiles = generatePerPluginBarrel({
|
|
@@ -295,10 +293,7 @@ const middlewareBarrel = defineMiddleware({
|
|
|
295
293
|
if (!rootBarrelType) return;
|
|
296
294
|
const rootBarrelFiles = generateRootBarrel({
|
|
297
295
|
barrelType: rootBarrelType,
|
|
298
|
-
files:
|
|
299
|
-
const normalizedPath = f.path.replace(/\\/g, "/");
|
|
300
|
-
return !excludedOutputPaths.some((excluded) => normalizedPath.startsWith(excluded.replace(/\\/g, "/") + "/"));
|
|
301
|
-
}) : files,
|
|
296
|
+
files: excludedPaths.size > 0 ? files.filter((f) => ![...excludedPaths].some((excluded) => f.path.startsWith(excluded + "/"))) : files,
|
|
302
297
|
config
|
|
303
298
|
});
|
|
304
299
|
if (rootBarrelFiles.length > 0) upsertFile(...rootBarrelFiles);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/constants.ts","../src/utils/buildTree.ts","../src/utils/getBarrelFiles.ts","../src/utils/generatePerPluginBarrel.ts","../src/utils/generateRootBarrel.ts","../src/middleware.ts"],"sourcesContent":["\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 BuildTree = {\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<BuildTree>\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>): BuildTree {\n const root: BuildTree = { 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_FILENAME } from '../constants.ts'\nimport type { BarrelType } from '../types.ts'\nimport { buildTree, type BuildTree } from './buildTree.ts'\n\nconst SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx'])\n\n/**\n * Derives a relative module specifier from an absolute `filePath` relative to an absolute `fromDir`.\n * The source extension is preserved so that `@kubb/parser-ts` can apply the `extNames` mapping\n * (e.g. `.ts` → `.js` for ESM output).\n *\n * @example\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/pet.ts') // './pet.ts'\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/tags/tag.ts') // './tags/tag.ts'\n */\nfunction toRelativeModulePath(fromDir: string, filePath: string): string {\n const relative = filePath.slice(fromDir.length).replace(/^[/\\\\]/g, '')\n return `./${relative}`\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: BuildTree, 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: ReturnType<typeof createExport>[] = []\n\n for (const filePath of leafPaths) {\n const sourceFile = sourceFiles.find((f) => f.path === filePath)\n // Skip files whose sources all have isIndexable: false (e.g. internal injected files)\n if (sourceFile && sourceFile.sources.length > 0 && sourceFile.sources.every((s) => !s.isIndexable)) {\n continue\n }\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\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 `'named'` strategy:\n * each indexable source in each leaf file gets an individual named `export { name } from '...'`.\n */\nfunction getBarrelFilesNamed(treeNode: BuildTree, 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 // If the file has explicit sources but none are indexable, skip it entirely.\n // Only fall back to wildcard when there are no sources at all (unknown exports).\n if (sourceFile.sources.length > 0) continue\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\n continue\n }\n\n const valueNames = indexableSources.filter((s) => !s.isTypeOnly).map((s) => s.name as string)\n const typeNames = indexableSources.filter((s) => s.isTypeOnly).map((s) => s.name as string)\n const modulePath = toRelativeModulePath(treeNode.path, filePath)\n\n if (valueNames.length > 0) {\n exports.push(createExport({ name: valueNames, path: modulePath }))\n }\n if (typeNames.length > 0) {\n exports.push(createExport({ name: typeNames, path: modulePath, isTypeOnly: true }))\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: BuildTree): Array<FileNode> {\n return collectPropagatedBarrels(treeNode)\n}\n\nfunction collectPropagatedBarrels(node: BuildTree): 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_FILENAME}`\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: BuildTree): 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 and have a recognised source extension\n const relevantFiles = files.filter((f) => {\n const normalizedFilePath = f.path.replace(/\\\\/g, '/')\n const normalizedOutputPath = outputPath.replace(/\\\\/g, '/')\n if (!normalizedFilePath.startsWith(normalizedOutputPath + '/')) return false\n if (normalizedFilePath.endsWith(`/${BARREL_FILENAME}`)) return false\n const dotIndex = normalizedFilePath.lastIndexOf('.')\n const ext = dotIndex === -1 ? '' : normalizedFilePath.slice(dotIndex)\n return SOURCE_EXTENSIONS.has(ext)\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\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\n return getBarrelFiles(outputPath, files, barrelType)\n}\n","import { defineMiddleware } from '@kubb/core'\nimport type { KubbBuildStartContext } 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\ndeclare global {\n namespace Kubb {\n interface PluginOptionsRegistry {\n output: {\n /**\n * Controls which barrel file (index.ts) is generated for this plugin's output directory.\n *\n * - `'all'` — `export * from '...'` for every generated file.\n * - `'named'` — `export { … } from '...'` using the file's named exports.\n * - `'propagate'` — like `'all'` but also generates intermediate barrel files.\n * - `false` — disable barrel generation for this plugin.\n *\n * When omitted, the root `config.output.barrelType` is used as the default.\n */\n barrelType?: BarrelType | false\n }\n }\n interface ConfigOptionsRegistry {\n output: {\n /**\n * Controls the root barrel file (index.ts) generated at `config.output.path`.\n *\n * - `'all'` — `export * from '...'` for every plugin's barrel.\n * - `'named'` — `export { … } from '...'` using the barrel's named exports.\n * - `'propagate'` — like `'all'` but also generates intermediate barrel files.\n * - `false` — disable root barrel generation.\n *\n * Individual plugins can override this via their own `output.barrelType`.\n */\n barrelType?: BarrelType | false\n }\n }\n }\n}\n\n/**\n * Barrel-file generation middleware.\n *\n * When added to `config.middleware`, generates an `index.ts` barrel file for each\n * plugin. When `output.barrelType` is omitted on a plugin it inherits from `config.output.barrelType`,\n * and when that is also omitted both default to `'all'`. Set `barrelType: false` to disable\n * barrel generation for a specific plugin or for the root entirely.\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 install(hooks) {\n let ctx: KubbBuildStartContext\n // Track output paths of plugins with barrelType: false so the root barrel\n // can exclude their files.\n const excludedOutputPaths: string[] = []\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 const pluginOutput = plugin.options.output\n const barrelType = pluginOutput?.barrelType !== undefined ? pluginOutput.barrelType : (ctx.config.output.barrelType ?? 'all')\n\n if (!barrelType) {\n // Remember this plugin's output path so we can exclude it from the root barrel\n const outputPath = plugin.options.output.path\n excludedOutputPaths.push(outputPath)\n return\n }\n\n const barrelFiles = generatePerPluginBarrel({\n barrelType,\n plugin,\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 rootBarrelType = config.output.barrelType ?? 'all'\n\n if (!rootBarrelType) return\n\n // Exclude files that belong to plugins with barrelType: false\n const filteredFiles =\n excludedOutputPaths.length > 0\n ? files.filter((f) => {\n const normalizedPath = f.path.replace(/\\\\/g, '/')\n return !excludedOutputPaths.some((excluded) => normalizedPath.startsWith(excluded.replace(/\\\\/g, '/') + '/'))\n })\n : files\n\n const rootBarrelFiles = generateRootBarrel({\n barrelType: rootBarrelType,\n files: filteredFiles,\n config,\n })\n\n if (rootBarrelFiles.length > 0) {\n 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/buildTree.ts","../src/utils/getBarrelFiles.ts","../src/utils/generatePerPluginBarrel.ts","../src/utils/generateRootBarrel.ts","../src/middleware.ts"],"sourcesContent":["\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 BuildTree = {\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<BuildTree>\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>): BuildTree {\n const root: BuildTree = { 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_FILENAME } from '../constants.ts'\nimport type { BarrelType } from '../types.ts'\nimport { buildTree, type BuildTree } from './buildTree.ts'\n\nconst SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx'])\n\n/**\n * Derives a relative module specifier from an absolute `filePath` relative to an absolute `fromDir`.\n * The source extension is preserved so that `@kubb/parser-ts` can apply the `extNames` mapping\n * (e.g. `.ts` → `.js` for ESM output).\n *\n * @example\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/pet.ts') // './pet.ts'\n * toRelativeModulePath('/src/gen/types', '/src/gen/types/tags/tag.ts') // './tags/tag.ts'\n */\nfunction toRelativeModulePath(fromDir: string, filePath: string): string {\n const relative = filePath.slice(fromDir.length).replace(/^[/\\\\]/g, '')\n return `./${relative}`\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: BuildTree, 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: ReturnType<typeof createExport>[] = []\n\n for (const filePath of leafPaths) {\n const sourceFile = sourceFiles.find((f) => f.path === filePath)\n // Skip files whose sources all have isIndexable: false (e.g. internal injected files)\n if (sourceFile && sourceFile.sources.length > 0 && sourceFile.sources.every((s) => !s.isIndexable)) {\n continue\n }\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\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 `'named'` strategy:\n * each indexable source in each leaf file gets an individual named `export { name } from '...'`.\n */\nfunction getBarrelFilesNamed(treeNode: BuildTree, 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 // If the file has explicit sources but none are indexable, skip it entirely.\n // Only fall back to wildcard when there are no sources at all (unknown exports).\n if (sourceFile.sources.length > 0) continue\n exports.push(createExport({ path: toRelativeModulePath(treeNode.path, filePath) }))\n continue\n }\n\n const valueNames = indexableSources.filter((s) => !s.isTypeOnly).map((s) => s.name as string)\n const typeNames = indexableSources.filter((s) => s.isTypeOnly).map((s) => s.name as string)\n const modulePath = toRelativeModulePath(treeNode.path, filePath)\n\n if (valueNames.length > 0) {\n exports.push(createExport({ name: valueNames, path: modulePath }))\n }\n if (typeNames.length > 0) {\n exports.push(createExport({ name: typeNames, path: modulePath, isTypeOnly: true }))\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: BuildTree): Array<FileNode> {\n return collectPropagatedBarrels(treeNode)\n}\n\nfunction collectPropagatedBarrels(node: BuildTree): 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_FILENAME}`\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: BuildTree): 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 and have a recognised source extension\n const relevantFiles = files.filter((f) => {\n const normalizedFilePath = f.path.replace(/\\\\/g, '/')\n const normalizedOutputPath = outputPath.replace(/\\\\/g, '/')\n if (!normalizedFilePath.startsWith(normalizedOutputPath + '/')) return false\n if (normalizedFilePath.endsWith(`/${BARREL_FILENAME}`)) return false\n const dotIndex = normalizedFilePath.lastIndexOf('.')\n const ext = dotIndex === -1 ? '' : normalizedFilePath.slice(dotIndex)\n return SOURCE_EXTENSIONS.has(ext)\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\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\n return getBarrelFiles(outputPath, files, barrelType)\n}\n","import { defineMiddleware } from '@kubb/core'\nimport type { KubbBuildStartContext } from '@kubb/core'\nimport type { BarrelType } from './types.ts'\nimport { generatePerPluginBarrel } from './utils/generatePerPluginBarrel.ts'\nimport { generateRootBarrel } from './utils/generateRootBarrel.ts'\nimport {resolve} from \"node:path\";\n\ndeclare global {\n namespace Kubb {\n interface PluginOptionsRegistry {\n output: {\n /**\n * Controls which barrel file (index.ts) is generated for this plugin's output directory.\n *\n * - `'all'` — `export * from '...'` for every generated file.\n * - `'named'` — `export { … } from '...'` using the file's named exports.\n * - `'propagate'` — like `'all'` but also generates intermediate barrel files.\n * - `false` — disable barrel generation for this plugin.\n *\n * When omitted, the root `config.output.barrelType` is used as the default.\n */\n barrelType?: BarrelType | false\n }\n }\n interface ConfigOptionsRegistry {\n output: {\n /**\n * Controls the root barrel file (index.ts) generated at `config.output.path`.\n *\n * - `'all'` — `export * from '...'` for every plugin's barrel.\n * - `'named'` — `export { … } from '...'` using the barrel's named exports.\n * - `'propagate'` — like `'all'` but also generates intermediate barrel files.\n * - `false` — disable root barrel generation.\n *\n * Individual plugins can override this via their own `output.barrelType`.\n */\n barrelType?: BarrelType | false\n }\n }\n }\n}\n\n/**\n * Barrel-file generation middleware.\n *\n * When added to `config.middleware`, generates an `index.ts` barrel file for each\n * plugin. When `output.barrelType` is omitted on a plugin it inherits from `config.output.barrelType`,\n * and when that is also omitted both default to `'all'`. Set `barrelType: false` to disable\n * barrel generation for a specific plugin or for the root entirely.\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 install(hooks) {\n let ctx: KubbBuildStartContext\n const excludedPaths = new Set<string>()\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 const barrelType = plugin.options.output?.barrelType ?? ctx.config.output.barrelType ?? 'all'\n\n if (!barrelType) {\n excludedPaths.add(resolve(ctx.config.root, ctx.config.output.path, plugin.options.output.path))\n return\n }\n\n const barrelFiles = generatePerPluginBarrel({\n barrelType,\n plugin,\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 rootBarrelType = config.output.barrelType ?? 'all'\n if (!rootBarrelType) return\n\n const filteredFiles =\n excludedPaths.size > 0\n ? files.filter((f) => ![...excludedPaths].some((excluded) => f.path.startsWith(excluded + '/')))\n : files\n\n const rootBarrelFiles = generateRootBarrel({\n barrelType: rootBarrelType,\n files: filteredFiles,\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.62",
|
|
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.62"
|
|
48
48
|
},
|
|
49
49
|
"engines": {
|
|
50
50
|
"node": ">=22"
|
package/src/middleware.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { defineMiddleware } from '@kubb/core'
|
|
2
2
|
import type { KubbBuildStartContext } from '@kubb/core'
|
|
3
|
-
import './types.ts'
|
|
4
3
|
import type { BarrelType } from './types.ts'
|
|
5
4
|
import { generatePerPluginBarrel } from './utils/generatePerPluginBarrel.ts'
|
|
6
5
|
import { generateRootBarrel } from './utils/generateRootBarrel.ts'
|
|
7
|
-
|
|
6
|
+
import {resolve} from "node:path";
|
|
8
7
|
|
|
9
8
|
declare global {
|
|
10
9
|
namespace Kubb {
|
|
@@ -72,9 +71,7 @@ export const middlewareBarrel = defineMiddleware({
|
|
|
72
71
|
name: 'middleware-barrel',
|
|
73
72
|
install(hooks) {
|
|
74
73
|
let ctx: KubbBuildStartContext
|
|
75
|
-
|
|
76
|
-
// can exclude their files.
|
|
77
|
-
const excludedOutputPaths: string[] = []
|
|
74
|
+
const excludedPaths = new Set<string>()
|
|
78
75
|
|
|
79
76
|
hooks.on('kubb:build:start', (buildCtx) => {
|
|
80
77
|
ctx = buildCtx
|
|
@@ -83,13 +80,10 @@ export const middlewareBarrel = defineMiddleware({
|
|
|
83
80
|
hooks.on('kubb:plugin:end', ({ plugin }) => {
|
|
84
81
|
if (!ctx) return
|
|
85
82
|
|
|
86
|
-
const
|
|
87
|
-
const barrelType = pluginOutput?.barrelType !== undefined ? pluginOutput.barrelType : (ctx.config.output.barrelType ?? 'all')
|
|
83
|
+
const barrelType = plugin.options.output?.barrelType ?? ctx.config.output.barrelType ?? 'all'
|
|
88
84
|
|
|
89
85
|
if (!barrelType) {
|
|
90
|
-
|
|
91
|
-
const outputPath = plugin.options.output.path
|
|
92
|
-
excludedOutputPaths.push(outputPath)
|
|
86
|
+
excludedPaths.add(resolve(ctx.config.root, ctx.config.output.path, plugin.options.output.path))
|
|
93
87
|
return
|
|
94
88
|
}
|
|
95
89
|
|
|
@@ -107,16 +101,11 @@ export const middlewareBarrel = defineMiddleware({
|
|
|
107
101
|
|
|
108
102
|
hooks.on('kubb:plugins:end', ({ files, config, upsertFile }) => {
|
|
109
103
|
const rootBarrelType = config.output.barrelType ?? 'all'
|
|
110
|
-
|
|
111
104
|
if (!rootBarrelType) return
|
|
112
105
|
|
|
113
|
-
// Exclude files that belong to plugins with barrelType: false
|
|
114
106
|
const filteredFiles =
|
|
115
|
-
|
|
116
|
-
? files.filter((f) =>
|
|
117
|
-
const normalizedPath = f.path.replace(/\\/g, '/')
|
|
118
|
-
return !excludedOutputPaths.some((excluded) => normalizedPath.startsWith(excluded.replace(/\\/g, '/') + '/'))
|
|
119
|
-
})
|
|
107
|
+
excludedPaths.size > 0
|
|
108
|
+
? files.filter((f) => ![...excludedPaths].some((excluded) => f.path.startsWith(excluded + '/')))
|
|
120
109
|
: files
|
|
121
110
|
|
|
122
111
|
const rootBarrelFiles = generateRootBarrel({
|