@kubb/plugin-barrel 5.8.0 → 5.8.2
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/OVERVIEW.md +30 -0
- package/dist/index.cjs +168 -235
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +169 -236
- package/dist/index.js.map +1 -1
- package/kubb-extension.json +18 -0
- package/package.json +6 -3
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./rolldown-runtime-C0LytTxp.js";
|
|
2
2
|
import path, { extname, isAbsolute, posix, relative, resolve } from "node:path";
|
|
3
|
-
import { Diagnostics, ast,
|
|
3
|
+
import { Diagnostics, ast, defineExtension } from "@kubb/kit";
|
|
4
4
|
//#region ../../internals/utils/src/fs.ts
|
|
5
5
|
/**
|
|
6
6
|
* Converts a filesystem path to use POSIX (`/`) separators.
|
|
@@ -41,6 +41,15 @@ function isPathInside(path, parent) {
|
|
|
41
41
|
return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
|
|
42
42
|
}
|
|
43
43
|
//#endregion
|
|
44
|
+
//#region kubb-extension.json
|
|
45
|
+
var compatibility = {
|
|
46
|
+
"kubb": ">=5.8.0",
|
|
47
|
+
"node": ">=22"
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region package.json
|
|
51
|
+
var version = "5.8.2";
|
|
52
|
+
//#endregion
|
|
44
53
|
//#region src/utils.ts
|
|
45
54
|
const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
46
55
|
".ts",
|
|
@@ -50,219 +59,124 @@ const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
50
59
|
]);
|
|
51
60
|
const BARREL_SUFFIX = `/index.ts`;
|
|
52
61
|
/**
|
|
53
|
-
*
|
|
54
|
-
* Paths outside `rootPath` are silently ignored. Children are sorted alphabetically
|
|
55
|
-
* by path so consumers (barrel exports, propagated indexes) emit a deterministic order.
|
|
56
|
-
*
|
|
57
|
-
* Both POSIX (`/`) and Windows (`\`) separators are accepted in input paths; emitted node
|
|
58
|
-
* paths are always POSIX-normalized so downstream prefix/lookup operations behave the same
|
|
59
|
-
* across platforms.
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
|
-
* ```ts
|
|
63
|
-
* buildTree('/src/gen/types', [
|
|
64
|
-
* '/src/gen/types/pet.ts',
|
|
65
|
-
* '/src/gen/types/pets/listPets.ts',
|
|
66
|
-
* ])
|
|
67
|
-
* ```
|
|
62
|
+
* Orders paths split into segments the way a directory listing sorts them: by name at each level.
|
|
68
63
|
*/
|
|
69
|
-
function
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
isFile: false
|
|
75
|
-
};
|
|
76
|
-
const childIndex = /* @__PURE__ */ new WeakMap();
|
|
77
|
-
childIndex.set(root, /* @__PURE__ */ new Map());
|
|
78
|
-
const rootPrefix = `${normalizedRoot}/`;
|
|
79
|
-
for (const filePath of filePaths) {
|
|
80
|
-
const normalized = toPosixPath(filePath);
|
|
81
|
-
if (!normalized.startsWith(rootPrefix)) continue;
|
|
82
|
-
const parts = normalized.slice(rootPrefix.length).split("/");
|
|
83
|
-
let current = root;
|
|
84
|
-
const lastIndex = parts.length - 1;
|
|
85
|
-
for (const [i, part] of parts.entries()) {
|
|
86
|
-
if (!part) continue;
|
|
87
|
-
const isLast = i === lastIndex;
|
|
88
|
-
const siblings = childIndex.get(current);
|
|
89
|
-
let child = siblings.get(part);
|
|
90
|
-
if (!child) {
|
|
91
|
-
child = {
|
|
92
|
-
path: `${current.path}/${part}`,
|
|
93
|
-
children: [],
|
|
94
|
-
isFile: isLast
|
|
95
|
-
};
|
|
96
|
-
current.children.push(child);
|
|
97
|
-
siblings.set(part, child);
|
|
98
|
-
if (!isLast) childIndex.set(child, /* @__PURE__ */ new Map());
|
|
99
|
-
}
|
|
100
|
-
current = child;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
sortTree(root);
|
|
104
|
-
return root;
|
|
64
|
+
function compareSegments(a, b) {
|
|
65
|
+
const index = a.findIndex((segment, i) => segment !== b[i]);
|
|
66
|
+
if (index === -1) return a.length - b.length;
|
|
67
|
+
if (index >= b.length) return 1;
|
|
68
|
+
return a[index] < b[index] ? -1 : 1;
|
|
105
69
|
}
|
|
106
|
-
function
|
|
107
|
-
if (node.children.length === 0) return;
|
|
108
|
-
node.children.sort(compareByPath);
|
|
109
|
-
for (const child of node.children) if (!child.isFile) sortTree(child);
|
|
110
|
-
}
|
|
111
|
-
function compareByPath(a, b) {
|
|
112
|
-
return a.path < b.path ? -1 : a.path > b.path ? 1 : 0;
|
|
113
|
-
}
|
|
114
|
-
function toRelativeModulePath({ fromDir, filePath }) {
|
|
70
|
+
function toRelativeModulePath(fromDir, filePath) {
|
|
115
71
|
return `./${posix.relative(fromDir, filePath)}`;
|
|
116
72
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
function makeBarrel(
|
|
121
|
-
const
|
|
122
|
-
const uniqueExports =
|
|
123
|
-
for (const item of exports) {
|
|
73
|
+
/**
|
|
74
|
+
* Builds the `index.ts` for `dirPath`. Keeps the first export of each name and reports later duplicates once per build.
|
|
75
|
+
*/
|
|
76
|
+
function makeBarrel(dirPath, exports, { sourceFiles, reportedCollisions }) {
|
|
77
|
+
const owners = /* @__PURE__ */ new Map();
|
|
78
|
+
const uniqueExports = exports.flatMap((item) => {
|
|
124
79
|
const itemPath = posix.join(dirPath, item.path);
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
for (const name of itemNames ?? []) {
|
|
128
|
-
const first = names.get(name);
|
|
80
|
+
const uniqueNames = (item.name == null ? sourceFiles.get(itemPath)?.sources.flatMap((source) => source.name || []) ?? [] : [item.name].flat()).filter((name) => {
|
|
81
|
+
const first = owners.get(name);
|
|
129
82
|
if (!first) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
continue;
|
|
83
|
+
owners.set(name, item.path);
|
|
84
|
+
return true;
|
|
133
85
|
}
|
|
134
86
|
const key = [
|
|
135
87
|
name,
|
|
136
88
|
posix.join(dirPath, first),
|
|
137
89
|
itemPath
|
|
138
90
|
].join("\0");
|
|
139
|
-
if (reportedCollisions.has(key))
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
91
|
+
if (!reportedCollisions.has(key)) {
|
|
92
|
+
reportedCollisions.add(key);
|
|
93
|
+
Diagnostics.report({
|
|
94
|
+
code: Diagnostics.code.barrelDuplicateExport,
|
|
95
|
+
severity: "error",
|
|
96
|
+
message: `"${name}" is exported by both "${first}" and "${item.path}", so "${dirPath}${BARREL_SUFFIX}" cannot re-export both.`,
|
|
97
|
+
help: "Rename one of the colliding declarations, or configure the plugin resolver to produce distinct names."
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
});
|
|
102
|
+
if (item.name == null) return [item];
|
|
103
|
+
return uniqueNames.length > 0 ? [ast.factory.createExport({
|
|
149
104
|
...item,
|
|
150
105
|
name: Array.isArray(item.name) ? uniqueNames : uniqueNames[0]
|
|
151
|
-
})
|
|
152
|
-
}
|
|
106
|
+
})] : [];
|
|
107
|
+
});
|
|
153
108
|
return ast.factory.createFile({
|
|
154
109
|
baseName: "index.ts",
|
|
155
110
|
path: `${dirPath}${BARREL_SUFFIX}`,
|
|
156
111
|
exports: uniqueExports
|
|
157
112
|
});
|
|
158
113
|
}
|
|
159
|
-
function indexableNames(
|
|
114
|
+
function indexableNames(sources, isTypeOnly) {
|
|
160
115
|
const names = sources.flatMap((source) => source.isIndexable && source.name && Boolean(source.isTypeOnly) === isTypeOnly ? [source.name] : []);
|
|
161
116
|
return [...new Set(names)].sort();
|
|
162
117
|
}
|
|
163
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Re-exports the whole module, unless it has sources and none of them is indexable.
|
|
120
|
+
*/
|
|
121
|
+
const allStrategy = (path, sourceFile) => {
|
|
164
122
|
const sources = sourceFile?.sources ?? [];
|
|
165
|
-
|
|
166
|
-
return [ast.factory.createExport({ path: toRelativeModulePath({
|
|
167
|
-
fromDir: dirPath,
|
|
168
|
-
filePath: leafPath
|
|
169
|
-
}) })];
|
|
123
|
+
return sources.length > 0 && !sources.some((source) => source.isIndexable) ? [] : [ast.factory.createExport({ path })];
|
|
170
124
|
};
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
isTypeOnly: false
|
|
180
|
-
});
|
|
181
|
-
const typeNames = indexableNames({
|
|
182
|
-
sources: sourceFile.sources,
|
|
183
|
-
isTypeOnly: true
|
|
184
|
-
});
|
|
185
|
-
if (valueNames.length === 0 && typeNames.length === 0) {
|
|
186
|
-
if (sourceFile.sources.length > 0) return [];
|
|
187
|
-
return [ast.factory.createExport({ path: modulePath })];
|
|
188
|
-
}
|
|
189
|
-
const exports = [];
|
|
190
|
-
if (valueNames.length > 0) exports.push(ast.factory.createExport({
|
|
125
|
+
/**
|
|
126
|
+
* Re-exports the indexable names, values and types separately, or the whole module when it has no sources.
|
|
127
|
+
*/
|
|
128
|
+
const namedStrategy = (path, sourceFile) => {
|
|
129
|
+
if (!sourceFile?.sources.length) return [ast.factory.createExport({ path })];
|
|
130
|
+
const valueNames = indexableNames(sourceFile.sources, false);
|
|
131
|
+
const typeNames = indexableNames(sourceFile.sources, true);
|
|
132
|
+
return [...valueNames.length > 0 ? [ast.factory.createExport({
|
|
191
133
|
name: valueNames,
|
|
192
|
-
path
|
|
193
|
-
})
|
|
194
|
-
if (typeNames.length > 0) exports.push(ast.factory.createExport({
|
|
134
|
+
path
|
|
135
|
+
})] : [], ...typeNames.length > 0 ? [ast.factory.createExport({
|
|
195
136
|
name: typeNames,
|
|
196
|
-
path
|
|
137
|
+
path,
|
|
197
138
|
isTypeOnly: true
|
|
198
|
-
})
|
|
199
|
-
return exports;
|
|
139
|
+
})] : []];
|
|
200
140
|
};
|
|
201
141
|
/**
|
|
202
|
-
* Post-order walk that
|
|
203
|
-
*
|
|
142
|
+
* Post-order walk that builds a barrel re-exporting every leaf below the visited directory, for
|
|
143
|
+
* the start node and, with `recursive`, every sub-directory. Also returns the subtree's leaf paths.
|
|
204
144
|
*/
|
|
205
|
-
function
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (!isBarrelPath(child.path)) subtreeLeaves.push(child.path);
|
|
210
|
-
continue;
|
|
211
|
-
}
|
|
212
|
-
const childLeaves = yield* walkAllOrNamed(child, params, {
|
|
213
|
-
isRoot: false,
|
|
214
|
-
recursive
|
|
215
|
-
});
|
|
216
|
-
for (const leaf of childLeaves) subtreeLeaves.push(leaf);
|
|
217
|
-
}
|
|
218
|
-
if (!isRoot && !recursive) return subtreeLeaves;
|
|
219
|
-
const exports = subtreeLeaves.flatMap((leafPath) => params.strategy({
|
|
220
|
-
dirPath: node.path,
|
|
221
|
-
leafPath,
|
|
222
|
-
sourceFile: params.sourceFiles.get(leafPath)
|
|
223
|
-
}));
|
|
224
|
-
if (exports.length > 0) yield makeBarrel({
|
|
225
|
-
dirPath: node.path,
|
|
226
|
-
exports,
|
|
227
|
-
sourceFiles: params.sourceFiles,
|
|
228
|
-
reportedCollisions: params.reportedCollisions
|
|
145
|
+
function walkFlat(node, ctx, isRoot = true) {
|
|
146
|
+
const results = [...node.children.values()].map((child) => child.children ? walkFlat(child, ctx, false) : {
|
|
147
|
+
barrels: [],
|
|
148
|
+
leaves: [child.path]
|
|
229
149
|
});
|
|
230
|
-
|
|
150
|
+
const barrels = results.flatMap((result) => result.barrels);
|
|
151
|
+
const leaves = results.flatMap((result) => result.leaves);
|
|
152
|
+
const exports = isRoot || ctx.recursive ? leaves.flatMap((leaf) => ctx.leafExports(node.path, leaf)) : [];
|
|
153
|
+
return {
|
|
154
|
+
barrels: exports.length > 0 ? [...barrels, makeBarrel(node.path, exports, ctx)] : barrels,
|
|
155
|
+
leaves
|
|
156
|
+
};
|
|
231
157
|
}
|
|
232
158
|
/**
|
|
233
|
-
* Recursive walk that
|
|
159
|
+
* Recursive walk that builds one barrel per directory, re-exporting files and sub-barrels.
|
|
234
160
|
* Used when nested: true. Leaf files honor the barrel `strategy`, so `named` emits explicit
|
|
235
161
|
* named exports instead of wildcards. Sub-directory barrels are chained with a wildcard
|
|
236
|
-
* re-export, which forwards the names the child barrel already curated.
|
|
237
|
-
*
|
|
162
|
+
* re-export, which forwards the names the child barrel already curated. A sub-directory that
|
|
163
|
+
* produced no barrel is never re-exported.
|
|
238
164
|
*/
|
|
239
|
-
function
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}))
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
}) }));
|
|
255
|
-
}
|
|
256
|
-
if (exports.length > 0) {
|
|
257
|
-
yield makeBarrel({
|
|
258
|
-
dirPath: node.path,
|
|
259
|
-
exports,
|
|
260
|
-
sourceFiles: params.sourceFiles,
|
|
261
|
-
reportedCollisions: params.reportedCollisions
|
|
262
|
-
});
|
|
263
|
-
return true;
|
|
264
|
-
}
|
|
265
|
-
return false;
|
|
165
|
+
function walkNested(node, ctx) {
|
|
166
|
+
const results = [...node.children.values()].map((child) => {
|
|
167
|
+
if (!child.children) return {
|
|
168
|
+
barrels: [],
|
|
169
|
+
exports: ctx.leafExports(node.path, child.path)
|
|
170
|
+
};
|
|
171
|
+
const barrels = walkNested(child, ctx);
|
|
172
|
+
return {
|
|
173
|
+
barrels,
|
|
174
|
+
exports: barrels.length > 0 ? [ast.factory.createExport({ path: toRelativeModulePath(node.path, `${child.path}${BARREL_SUFFIX}`) })] : []
|
|
175
|
+
};
|
|
176
|
+
});
|
|
177
|
+
const barrels = results.flatMap((result) => result.barrels);
|
|
178
|
+
const exports = results.flatMap((result) => result.exports);
|
|
179
|
+
return exports.length > 0 ? [...barrels, makeBarrel(node.path, exports, ctx)] : barrels;
|
|
266
180
|
}
|
|
267
181
|
/**
|
|
268
182
|
* Indexes `files` once for the directory rooted at `outputPath`: filters to indexable source
|
|
@@ -270,62 +184,62 @@ function* walkNested(node, params) {
|
|
|
270
184
|
* derived from the same root rather than re-filtering and re-building per barrel.
|
|
271
185
|
*/
|
|
272
186
|
function buildBarrelIndex(outputPath, files) {
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
187
|
+
const tree = {
|
|
188
|
+
path: toPosixPath(outputPath),
|
|
189
|
+
children: /* @__PURE__ */ new Map()
|
|
190
|
+
};
|
|
191
|
+
const sourceFiles = new Map(files.flatMap((file) => {
|
|
192
|
+
const filePath = toPosixPath(file.path);
|
|
193
|
+
return filePath.startsWith(`${tree.path}/`) && !filePath.endsWith(BARREL_SUFFIX) && SOURCE_EXTENSIONS.has(extname(filePath)) ? [[filePath, file]] : [];
|
|
194
|
+
}));
|
|
195
|
+
[...sourceFiles.keys()].map((filePath) => filePath.slice(tree.path.length + 1).split("/").filter(Boolean)).sort(compareSegments).forEach((parts) => {
|
|
196
|
+
parts.reduce((dir, part, i) => {
|
|
197
|
+
const path = `${dir.path}/${part}`;
|
|
198
|
+
const child = dir.children.get(part) ?? (i === parts.length - 1 ? { path } : {
|
|
199
|
+
path,
|
|
200
|
+
children: /* @__PURE__ */ new Map()
|
|
201
|
+
});
|
|
202
|
+
dir.children.set(part, child);
|
|
203
|
+
return child.children ? child : dir;
|
|
204
|
+
}, tree);
|
|
205
|
+
});
|
|
282
206
|
return {
|
|
283
|
-
tree
|
|
207
|
+
tree,
|
|
284
208
|
sourceFiles
|
|
285
209
|
};
|
|
286
210
|
}
|
|
287
211
|
/**
|
|
288
|
-
* Locates the node for `targetPath` within an index tree
|
|
289
|
-
*
|
|
212
|
+
* Locates the directory node for `targetPath` within an index tree. Returns `undefined` when no
|
|
213
|
+
* file exists under `targetPath` (nothing to barrel).
|
|
290
214
|
*/
|
|
291
|
-
function
|
|
292
|
-
if (
|
|
293
|
-
if (
|
|
294
|
-
|
|
215
|
+
function findDirectory(tree, targetPath) {
|
|
216
|
+
if (targetPath === tree.path) return tree;
|
|
217
|
+
if (!targetPath.startsWith(`${tree.path}/`)) return void 0;
|
|
218
|
+
const node = targetPath.slice(tree.path.length + 1).split("/").reduce((current, part) => current?.children?.get(part), tree);
|
|
219
|
+
return node?.children ? node : void 0;
|
|
295
220
|
}
|
|
296
221
|
/**
|
|
297
|
-
*
|
|
222
|
+
* Returns the barrel `ast.FileNode`s for `targetPath` (or the index root), derived from a shared index.
|
|
298
223
|
* Locating the subtree is a bounded walk down from the root, so deriving many barrels (one per
|
|
299
224
|
* plugin, plus the root) from one index avoids re-scanning the full file set for each.
|
|
300
225
|
*
|
|
301
226
|
* @example
|
|
302
227
|
* ```ts
|
|
303
228
|
* const index = buildBarrelIndex(outputPath, files)
|
|
304
|
-
*
|
|
305
|
-
* upsertFile(file)
|
|
306
|
-
* }
|
|
229
|
+
* getBarrelFiles({ index, targetPath, barrelType }).forEach((file) => upsertFile(file))
|
|
307
230
|
* ```
|
|
308
231
|
*/
|
|
309
|
-
function
|
|
310
|
-
const node = targetPath ?
|
|
311
|
-
if (!node) return;
|
|
232
|
+
function getBarrelFiles({ index, targetPath, barrelType, nested = false, recursive = false, reportedCollisions = /* @__PURE__ */ new Set() }) {
|
|
233
|
+
const node = targetPath ? findDirectory(index.tree, toPosixPath(targetPath)) : index.tree;
|
|
234
|
+
if (!node) return [];
|
|
312
235
|
const strategy = barrelType === "named" ? namedStrategy : allStrategy;
|
|
313
|
-
|
|
314
|
-
yield* walkNested(node, {
|
|
315
|
-
sourceFiles: index.sourceFiles,
|
|
316
|
-
strategy,
|
|
317
|
-
reportedCollisions
|
|
318
|
-
});
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
yield* walkAllOrNamed(node, {
|
|
236
|
+
const ctx = {
|
|
322
237
|
sourceFiles: index.sourceFiles,
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
});
|
|
238
|
+
reportedCollisions,
|
|
239
|
+
recursive,
|
|
240
|
+
leafExports: (dirPath, leafPath) => strategy(toRelativeModulePath(dirPath, leafPath), index.sourceFiles.get(leafPath))
|
|
241
|
+
};
|
|
242
|
+
return nested ? walkNested(node, ctx) : walkFlat(node, ctx).barrels;
|
|
329
243
|
}
|
|
330
244
|
//#endregion
|
|
331
245
|
//#region src/plugin.ts
|
|
@@ -365,6 +279,7 @@ const pluginBarrelName = "plugin-barrel";
|
|
|
365
279
|
const states = /* @__PURE__ */ new WeakMap();
|
|
366
280
|
function getState(config) {
|
|
367
281
|
const state = states.get(config) ?? {
|
|
282
|
+
excludedPlugins: /* @__PURE__ */ new Set(),
|
|
368
283
|
excludedTargets: [],
|
|
369
284
|
pendingBarrels: []
|
|
370
285
|
};
|
|
@@ -404,20 +319,27 @@ function getState(config) {
|
|
|
404
319
|
* })
|
|
405
320
|
* ```
|
|
406
321
|
*/
|
|
407
|
-
const pluginBarrel =
|
|
408
|
-
|
|
322
|
+
const pluginBarrel = defineExtension({
|
|
323
|
+
kind: "plugin",
|
|
324
|
+
meta: {
|
|
325
|
+
name: pluginBarrelName,
|
|
326
|
+
version,
|
|
327
|
+
compatibility
|
|
328
|
+
},
|
|
409
329
|
enforce: "post",
|
|
410
330
|
hooks: {
|
|
411
331
|
"kubb:plugin:end"({ plugin, config }) {
|
|
412
332
|
if (plugin.name === "plugin-barrel") return;
|
|
413
|
-
const { excludedTargets, pendingBarrels } = getState(config);
|
|
333
|
+
const { excludedPlugins, excludedTargets, pendingBarrels } = getState(config);
|
|
414
334
|
const barrelConfig = plugin.options.output?.barrel ?? config.output.barrel ?? false;
|
|
415
335
|
const base = path.resolve(config.root, config.output.path);
|
|
416
|
-
const target = path.resolve(base, plugin.options.output.path);
|
|
336
|
+
const target = path.resolve(base, plugin.options.output.path ?? ".");
|
|
417
337
|
if (barrelConfig === false) {
|
|
418
|
-
|
|
338
|
+
excludedPlugins.add(plugin.name);
|
|
339
|
+
if (target !== base && isPathInside(target, base)) excludedTargets.push(target);
|
|
419
340
|
return;
|
|
420
341
|
}
|
|
342
|
+
if (target === base) return;
|
|
421
343
|
if (plugin.options.output.mode === "file") return;
|
|
422
344
|
if (!isPathInside(target, base)) throw new Diagnostics.Error({
|
|
423
345
|
code: Diagnostics.code.pathTraversal,
|
|
@@ -434,32 +356,43 @@ const pluginBarrel = definePlugin({
|
|
|
434
356
|
});
|
|
435
357
|
},
|
|
436
358
|
"kubb:plugins:end"({ files, config, upsertFile }) {
|
|
437
|
-
const { excludedTargets, pendingBarrels } = getState(config);
|
|
359
|
+
const { excludedPlugins, excludedTargets, pendingBarrels } = getState(config);
|
|
438
360
|
const rootBarrelConfig = config.output.barrel ?? false;
|
|
439
361
|
const outputPath = path.resolve(config.root, config.output.path);
|
|
440
|
-
const relevantFiles = files.filter((file) =>
|
|
362
|
+
const relevantFiles = files.filter((file) => {
|
|
363
|
+
const owner = file.meta?.pluginName;
|
|
364
|
+
if (owner) return !excludedPlugins.has(owner);
|
|
365
|
+
return !excludedTargets.some((target) => isPathInside(file.path, target));
|
|
366
|
+
});
|
|
367
|
+
excludedPlugins.clear();
|
|
441
368
|
excludedTargets.length = 0;
|
|
442
369
|
const index = buildBarrelIndex(outputPath, relevantFiles);
|
|
443
370
|
const reportedCollisions = /* @__PURE__ */ new Set();
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
file
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
371
|
+
pendingBarrels.forEach(({ plugin, target, barrelType, nested }) => {
|
|
372
|
+
getBarrelFiles({
|
|
373
|
+
index,
|
|
374
|
+
targetPath: target,
|
|
375
|
+
barrelType,
|
|
376
|
+
nested,
|
|
377
|
+
recursive: true,
|
|
378
|
+
reportedCollisions
|
|
379
|
+
}).forEach((file) => {
|
|
380
|
+
upsertFile(withBarrelBannerFooter({
|
|
381
|
+
file,
|
|
382
|
+
plugin,
|
|
383
|
+
config
|
|
384
|
+
}));
|
|
385
|
+
});
|
|
386
|
+
});
|
|
456
387
|
pendingBarrels.length = 0;
|
|
457
388
|
if (rootBarrelConfig === false) return;
|
|
458
|
-
|
|
389
|
+
getBarrelFiles({
|
|
459
390
|
index,
|
|
460
391
|
barrelType: rootBarrelConfig.type,
|
|
461
392
|
reportedCollisions
|
|
462
|
-
})
|
|
393
|
+
}).forEach((file) => {
|
|
394
|
+
upsertFile(file);
|
|
395
|
+
});
|
|
463
396
|
}
|
|
464
397
|
}
|
|
465
398
|
});
|