bunchee 6.8.2 → 6.9.1
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/README.md +24 -0
- package/dist/bin/cli.js +177 -10
- package/dist/index.js +165 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -94,6 +94,21 @@ Here's a example of entry files and exports configuration:
|
|
|
94
94
|
}
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
+
#### Wildcard Exports
|
|
98
|
+
|
|
99
|
+
`bunchee` supports wildcard patterns in the `exports` field to automatically generate exports for multiple files:
|
|
100
|
+
|
|
101
|
+
```json5
|
|
102
|
+
{
|
|
103
|
+
"exports": {
|
|
104
|
+
".": "./dist/index.js",
|
|
105
|
+
"./features/*": "./dist/features/*.js"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
This will automatically discover files in `src/features/` and generate exports like `./features/foo`, `./features/bar`, etc. The wildcard `*` is substituted in both the export path and output path.
|
|
111
|
+
|
|
97
112
|
### Output Formats
|
|
98
113
|
|
|
99
114
|
**bunchee** detects the format of each entry-point based on export condition type or the file extension. It supports the following output formats:
|
|
@@ -215,6 +230,15 @@ This will match the `bin` field in package.json as:
|
|
|
215
230
|
|
|
216
231
|
> Note: For multiple `bin` files, the filename should match the key name in the `bin` field.
|
|
217
232
|
|
|
233
|
+
### Native Addon (.node) Support
|
|
234
|
+
|
|
235
|
+
`bunchee` supports bundling native Node.js addon files (`.node` binaries). When you import a `.node` file, it will be copied to the output directory and the import will be rewritten to load it at runtime.
|
|
236
|
+
|
|
237
|
+
```js
|
|
238
|
+
// src/index.js
|
|
239
|
+
import addon from './native-addon.node'
|
|
240
|
+
```
|
|
241
|
+
|
|
218
242
|
### Server Components
|
|
219
243
|
|
|
220
244
|
**bunchee** supports building React Server Components and Server Actions with directives like `"use client"` or `"use server"`. It generates separate chunks for the server or client boundaries. When integrated to framework like Next.js, it can correctly handles the boundaries with the split chunks.
|
package/dist/bin/cli.js
CHANGED
|
@@ -6,10 +6,10 @@ var perf_hooks = require('perf_hooks');
|
|
|
6
6
|
var fs = require('fs');
|
|
7
7
|
var fsp = require('fs/promises');
|
|
8
8
|
var require$$0 = require('tty');
|
|
9
|
+
var tinyglobby = require('tinyglobby');
|
|
9
10
|
var picomatch = require('picomatch');
|
|
10
11
|
var index_js = require('../index.js');
|
|
11
12
|
require('module');
|
|
12
|
-
var tinyglobby = require('tinyglobby');
|
|
13
13
|
var prettyBytes = require('pretty-bytes');
|
|
14
14
|
var nanospinner = require('nanospinner');
|
|
15
15
|
|
|
@@ -274,7 +274,9 @@ const getMainFieldExportType = (pkg)=>{
|
|
|
274
274
|
};
|
|
275
275
|
const isTestFile = (filename)=>/\.(test|spec)$/.test(baseNameWithoutExtension(filename));
|
|
276
276
|
function joinRelativePath(...segments) {
|
|
277
|
-
|
|
277
|
+
// Normalize to forward slashes for cross-platform compatibility
|
|
278
|
+
// Export paths in package.json always use POSIX-style paths
|
|
279
|
+
let result = path__default.default.posix.join(...segments);
|
|
278
280
|
// If the first segment starts with '.', ensure the result does too.
|
|
279
281
|
if (segments[0] === '.' && !result.startsWith('.')) {
|
|
280
282
|
result = './' + result;
|
|
@@ -312,6 +314,155 @@ function normalizePath(filePath) {
|
|
|
312
314
|
return filePath.replace(/\\/g, '/');
|
|
313
315
|
}
|
|
314
316
|
|
|
317
|
+
/**
|
|
318
|
+
* Check if an export key contains a wildcard pattern
|
|
319
|
+
*/ function hasWildcardPattern(exportKey) {
|
|
320
|
+
return exportKey.includes('*');
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Replace wildcard in output path with matched subpath
|
|
324
|
+
* Example: "./dist/features/*.js" with "foo" -> "./dist/features/foo.js"
|
|
325
|
+
*/ function substituteWildcardInPath(outputPath, matchedSubpath) {
|
|
326
|
+
return outputPath.replace(/\*/g, matchedSubpath);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Expand a wildcard export pattern by finding matching source files
|
|
330
|
+
* Returns a map of concrete export paths to their matched subpaths
|
|
331
|
+
* Example: "./features/*" with files ["foo.ts", "bar.ts"] in src/features/
|
|
332
|
+
* -> { "./features/foo": "foo", "./features/bar": "bar" }
|
|
333
|
+
*/ async function expandWildcardPattern(wildcardPattern, cwd) {
|
|
334
|
+
const expanded = new Map();
|
|
335
|
+
const sourceDir = path__default.default.join(cwd, SRC);
|
|
336
|
+
if (!fileExists(sourceDir)) {
|
|
337
|
+
return expanded;
|
|
338
|
+
}
|
|
339
|
+
// Convert wildcard pattern to glob pattern
|
|
340
|
+
// "./features/*" -> "features/*"
|
|
341
|
+
const cleanPattern = wildcardPattern.replace(/^\.\//, '');
|
|
342
|
+
// Extract the base path before the wildcard
|
|
343
|
+
// "features/*" -> "features"
|
|
344
|
+
const basePathParts = cleanPattern.split('*');
|
|
345
|
+
const basePath = basePathParts[0].replace(/\/$/, '');
|
|
346
|
+
// Build glob pattern to match files
|
|
347
|
+
// "features/*" -> "features/*.{js,ts,tsx,...}"
|
|
348
|
+
const extPattern = `{${[
|
|
349
|
+
...availableExtensions
|
|
350
|
+
].join(',')}}`;
|
|
351
|
+
const globPatterns = [
|
|
352
|
+
`${cleanPattern}.${extPattern}`,
|
|
353
|
+
`${cleanPattern}/index.${extPattern}`
|
|
354
|
+
];
|
|
355
|
+
let matches = [];
|
|
356
|
+
try {
|
|
357
|
+
matches = await tinyglobby.glob(globPatterns, {
|
|
358
|
+
cwd: sourceDir,
|
|
359
|
+
ignore: [
|
|
360
|
+
PRIVATE_GLOB_PATTERN,
|
|
361
|
+
TESTS_GLOB_PATTERN
|
|
362
|
+
],
|
|
363
|
+
expandDirectories: false
|
|
364
|
+
});
|
|
365
|
+
} catch (error) {
|
|
366
|
+
logger.warn(`Failed to expand wildcard pattern ${wildcardPattern}: ${error}`);
|
|
367
|
+
return expanded;
|
|
368
|
+
}
|
|
369
|
+
for (const match of matches){
|
|
370
|
+
// Extract the matched subpath
|
|
371
|
+
// "features/foo.ts" -> "foo"
|
|
372
|
+
// "features/bar/index.ts" -> "bar"
|
|
373
|
+
const relativePath = normalizePath(match);
|
|
374
|
+
const ext = path__default.default.extname(relativePath);
|
|
375
|
+
const withoutExt = relativePath.slice(0, -ext.length);
|
|
376
|
+
// Remove the base path to get just the matched part
|
|
377
|
+
// "features/foo" -> "foo" (when basePath is "features")
|
|
378
|
+
let matchedPart = withoutExt;
|
|
379
|
+
if (basePath && matchedPart.startsWith(basePath + '/')) {
|
|
380
|
+
matchedPart = matchedPart.slice(basePath.length + 1);
|
|
381
|
+
} else if (basePath && matchedPart === basePath) {
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
// Handle index files
|
|
385
|
+
let matchedSubpath;
|
|
386
|
+
if (matchedPart.endsWith('/index')) {
|
|
387
|
+
matchedSubpath = matchedPart.slice(0, -6); // Remove "/index"
|
|
388
|
+
// If there's still a path, take the last segment
|
|
389
|
+
const lastSlash = matchedSubpath.lastIndexOf('/');
|
|
390
|
+
matchedSubpath = lastSlash >= 0 ? matchedSubpath.slice(lastSlash + 1) : matchedSubpath;
|
|
391
|
+
} else {
|
|
392
|
+
// Take the first segment (what matches the *)
|
|
393
|
+
const firstSlash = matchedPart.indexOf('/');
|
|
394
|
+
matchedSubpath = firstSlash >= 0 ? matchedPart.slice(0, firstSlash) : matchedPart;
|
|
395
|
+
}
|
|
396
|
+
// Build the concrete export path
|
|
397
|
+
// "./features/*" + "foo" -> "./features/foo"
|
|
398
|
+
const concreteExportPath = basePath ? `./${basePath}/${matchedSubpath}` : `./${matchedSubpath}`;
|
|
399
|
+
expanded.set(concreteExportPath, matchedSubpath);
|
|
400
|
+
}
|
|
401
|
+
return expanded;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Process export value for wildcard patterns, substituting wildcards in output paths
|
|
406
|
+
*/ async function processWildcardExportValue(exportValue, originalExportKey, currentPath, exportTypes, exportToDist, matchedSubpath) {
|
|
407
|
+
// End of searching, export value is file path.
|
|
408
|
+
// <export key>: <export value> (string)
|
|
409
|
+
if (typeof exportValue === 'string') {
|
|
410
|
+
const composedTypes = new Set(exportTypes);
|
|
411
|
+
const exportType = originalExportKey.startsWith('.') ? 'default' : originalExportKey;
|
|
412
|
+
composedTypes.add(exportType);
|
|
413
|
+
const exportInfo = exportToDist.get(mapExportFullPath(currentPath));
|
|
414
|
+
const exportCondition = Array.from(composedTypes).join('.');
|
|
415
|
+
// Substitute wildcard in output path
|
|
416
|
+
const substitutedPath = substituteWildcardInPath(exportValue, matchedSubpath);
|
|
417
|
+
if (!exportInfo) {
|
|
418
|
+
const outputConditionPair = [
|
|
419
|
+
substitutedPath,
|
|
420
|
+
exportCondition
|
|
421
|
+
];
|
|
422
|
+
addToExportDistMap(exportToDist, currentPath, [
|
|
423
|
+
outputConditionPair
|
|
424
|
+
]);
|
|
425
|
+
} else {
|
|
426
|
+
exportInfo.push([
|
|
427
|
+
substitutedPath,
|
|
428
|
+
exportCondition
|
|
429
|
+
]);
|
|
430
|
+
}
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
const exportKeys = Object.keys(exportValue);
|
|
434
|
+
for (const exportKey of exportKeys){
|
|
435
|
+
// Clone the set to avoid modifying the parent set
|
|
436
|
+
const childExports = new Set(exportTypes);
|
|
437
|
+
// Normalize child export value to a map
|
|
438
|
+
const childExportValue = exportValue[exportKey];
|
|
439
|
+
// Substitute wildcard in nested string values
|
|
440
|
+
let processedChildValue = childExportValue;
|
|
441
|
+
if (typeof childExportValue === 'string') {
|
|
442
|
+
processedChildValue = substituteWildcardInPath(childExportValue, matchedSubpath);
|
|
443
|
+
} else if (typeof childExportValue === 'object' && childExportValue !== null) {
|
|
444
|
+
// Recursively process nested objects
|
|
445
|
+
const processed = {};
|
|
446
|
+
for (const [key, value] of Object.entries(childExportValue)){
|
|
447
|
+
if (typeof value === 'string') {
|
|
448
|
+
processed[key] = substituteWildcardInPath(value, matchedSubpath);
|
|
449
|
+
} else if (value !== null && value !== undefined) {
|
|
450
|
+
processed[key] = value;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
processedChildValue = processed;
|
|
454
|
+
}
|
|
455
|
+
// Visit export path: ./subpath, ./subpath2, ...
|
|
456
|
+
if (exportKey.startsWith('.')) {
|
|
457
|
+
const childPath = joinRelativePath(currentPath, exportKey);
|
|
458
|
+
await processWildcardExportValue(processedChildValue, exportKey, childPath, childExports, exportToDist, matchedSubpath);
|
|
459
|
+
} else {
|
|
460
|
+
// Visit export type: import, require, ...
|
|
461
|
+
childExports.add(exportKey);
|
|
462
|
+
await processWildcardExportValue(processedChildValue, exportKey, currentPath, childExports, exportToDist, matchedSubpath);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
315
466
|
function collectExportPath(exportValue, exportKey, currentPath, exportTypes, exportToDist) {
|
|
316
467
|
// End of searching, export value is file path.
|
|
317
468
|
// <export key>: <export value> (string)
|
|
@@ -373,7 +524,7 @@ function addToExportDistMap(exportToDist, exportPath, outputConditionPairs) {
|
|
|
373
524
|
* './index': { development: ..., default: ... }
|
|
374
525
|
* './index.react-server': { development: ..., default: ... }
|
|
375
526
|
* }
|
|
376
|
-
*/ function parseExports(pkg) {
|
|
527
|
+
*/ async function parseExports(pkg, cwd) {
|
|
377
528
|
var _pkg_exports;
|
|
378
529
|
const exportsField = (_pkg_exports = pkg.exports) != null ? _pkg_exports : {};
|
|
379
530
|
var _pkg_bin;
|
|
@@ -397,6 +548,17 @@ function addToExportDistMap(exportToDist, exportPath, outputConditionPairs) {
|
|
|
397
548
|
const exportValue = exportsField[exportKey];
|
|
398
549
|
const exportTypes = new Set();
|
|
399
550
|
const isExportPath = exportKey.startsWith('.');
|
|
551
|
+
// Handle wildcard patterns
|
|
552
|
+
if (isExportPath && hasWildcardPattern(exportKey) && cwd) {
|
|
553
|
+
// Expand wildcard pattern to concrete exports
|
|
554
|
+
const expanded = await expandWildcardPattern(exportKey, cwd);
|
|
555
|
+
for (const [concreteExportPath, matchedSubpath] of expanded){
|
|
556
|
+
const childPath = joinRelativePath(currentPath, concreteExportPath);
|
|
557
|
+
// Process the export value and substitute wildcards in output paths
|
|
558
|
+
await processWildcardExportValue(exportValue, exportKey, childPath, exportTypes, exportToDist, matchedSubpath);
|
|
559
|
+
}
|
|
560
|
+
continue;
|
|
561
|
+
}
|
|
400
562
|
const childPath = isExportPath ? joinRelativePath(currentPath, exportKey) : currentPath;
|
|
401
563
|
if (!isExportPath) {
|
|
402
564
|
exportTypes.add(exportKey);
|
|
@@ -515,10 +677,11 @@ function validateFilesField(packageJson) {
|
|
|
515
677
|
});
|
|
516
678
|
return state;
|
|
517
679
|
}
|
|
518
|
-
function lint$1(
|
|
680
|
+
async function lint$1(cwd) {
|
|
681
|
+
const pkg = await getPackageMeta(cwd);
|
|
519
682
|
const { name, main, exports } = pkg;
|
|
520
683
|
const isESM = isESModulePackage(pkg.type);
|
|
521
|
-
const parsedExports = parseExports(pkg);
|
|
684
|
+
const parsedExports = await parseExports(pkg, cwd);
|
|
522
685
|
if (!name) {
|
|
523
686
|
logger.warn('Missing package name');
|
|
524
687
|
}
|
|
@@ -693,7 +856,7 @@ function lint$1(pkg) {
|
|
|
693
856
|
}
|
|
694
857
|
}
|
|
695
858
|
|
|
696
|
-
var version = "6.
|
|
859
|
+
var version = "6.9.1";
|
|
697
860
|
|
|
698
861
|
async function writeDefaultTsconfig(tsConfigPath) {
|
|
699
862
|
await fs.promises.writeFile(tsConfigPath, JSON.stringify(DEFAULT_TS_CONFIG, null, 2), 'utf-8');
|
|
@@ -960,9 +1123,13 @@ function addBuildScripts(pkgJson, cwd) {
|
|
|
960
1123
|
}
|
|
961
1124
|
async function prepare(cwd, options) {
|
|
962
1125
|
const sourceFolder = path__default.default.resolve(cwd, SRC);
|
|
1126
|
+
// Create src/index.ts if src folder doesn't exist
|
|
963
1127
|
if (!fs__default.default.existsSync(sourceFolder)) {
|
|
964
|
-
|
|
965
|
-
|
|
1128
|
+
await fsp__default.default.mkdir(sourceFolder, {
|
|
1129
|
+
recursive: true
|
|
1130
|
+
});
|
|
1131
|
+
const indexPath = path__default.default.join(sourceFolder, 'index.ts');
|
|
1132
|
+
await fsp__default.default.writeFile(indexPath, "export function index() {\n return 'index'\n}\n", 'utf-8');
|
|
966
1133
|
}
|
|
967
1134
|
let hasPackageJson = false;
|
|
968
1135
|
const pkgJsonPath = path__default.default.join(cwd, 'package.json');
|
|
@@ -1202,10 +1369,10 @@ function help() {
|
|
|
1202
1369
|
}
|
|
1203
1370
|
async function lint(cwd) {
|
|
1204
1371
|
// Not package.json detected, skip package linting
|
|
1205
|
-
if (!
|
|
1372
|
+
if (!hasPackageJson(cwd)) {
|
|
1206
1373
|
return;
|
|
1207
1374
|
}
|
|
1208
|
-
await lint$1(
|
|
1375
|
+
await lint$1(cwd);
|
|
1209
1376
|
}
|
|
1210
1377
|
async function parseCliArgs(argv) {
|
|
1211
1378
|
const args = await yargs__default.default(helpers.hideBin(argv)).option('watch', {
|
package/dist/index.js
CHANGED
|
@@ -385,7 +385,9 @@ const getMainFieldExportType = (pkg)=>{
|
|
|
385
385
|
};
|
|
386
386
|
const isTestFile = (filename)=>/\.(test|spec)$/.test(baseNameWithoutExtension(filename));
|
|
387
387
|
function joinRelativePath(...segments) {
|
|
388
|
-
|
|
388
|
+
// Normalize to forward slashes for cross-platform compatibility
|
|
389
|
+
// Export paths in package.json always use POSIX-style paths
|
|
390
|
+
let result = path__default.default.posix.join(...segments);
|
|
389
391
|
// If the first segment starts with '.', ensure the result does too.
|
|
390
392
|
if (segments[0] === '.' && !result.startsWith('.')) {
|
|
391
393
|
result = './' + result;
|
|
@@ -437,6 +439,155 @@ function normalizePath(filePath) {
|
|
|
437
439
|
return filePath.replace(/\\/g, '/');
|
|
438
440
|
}
|
|
439
441
|
|
|
442
|
+
/**
|
|
443
|
+
* Check if an export key contains a wildcard pattern
|
|
444
|
+
*/ function hasWildcardPattern(exportKey) {
|
|
445
|
+
return exportKey.includes('*');
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Replace wildcard in output path with matched subpath
|
|
449
|
+
* Example: "./dist/features/*.js" with "foo" -> "./dist/features/foo.js"
|
|
450
|
+
*/ function substituteWildcardInPath(outputPath, matchedSubpath) {
|
|
451
|
+
return outputPath.replace(/\*/g, matchedSubpath);
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Expand a wildcard export pattern by finding matching source files
|
|
455
|
+
* Returns a map of concrete export paths to their matched subpaths
|
|
456
|
+
* Example: "./features/*" with files ["foo.ts", "bar.ts"] in src/features/
|
|
457
|
+
* -> { "./features/foo": "foo", "./features/bar": "bar" }
|
|
458
|
+
*/ async function expandWildcardPattern(wildcardPattern, cwd) {
|
|
459
|
+
const expanded = new Map();
|
|
460
|
+
const sourceDir = path__default.default.join(cwd, SRC);
|
|
461
|
+
if (!fileExists(sourceDir)) {
|
|
462
|
+
return expanded;
|
|
463
|
+
}
|
|
464
|
+
// Convert wildcard pattern to glob pattern
|
|
465
|
+
// "./features/*" -> "features/*"
|
|
466
|
+
const cleanPattern = wildcardPattern.replace(/^\.\//, '');
|
|
467
|
+
// Extract the base path before the wildcard
|
|
468
|
+
// "features/*" -> "features"
|
|
469
|
+
const basePathParts = cleanPattern.split('*');
|
|
470
|
+
const basePath = basePathParts[0].replace(/\/$/, '');
|
|
471
|
+
// Build glob pattern to match files
|
|
472
|
+
// "features/*" -> "features/*.{js,ts,tsx,...}"
|
|
473
|
+
const extPattern = `{${[
|
|
474
|
+
...availableExtensions
|
|
475
|
+
].join(',')}}`;
|
|
476
|
+
const globPatterns = [
|
|
477
|
+
`${cleanPattern}.${extPattern}`,
|
|
478
|
+
`${cleanPattern}/index.${extPattern}`
|
|
479
|
+
];
|
|
480
|
+
let matches = [];
|
|
481
|
+
try {
|
|
482
|
+
matches = await tinyglobby.glob(globPatterns, {
|
|
483
|
+
cwd: sourceDir,
|
|
484
|
+
ignore: [
|
|
485
|
+
PRIVATE_GLOB_PATTERN,
|
|
486
|
+
TESTS_GLOB_PATTERN
|
|
487
|
+
],
|
|
488
|
+
expandDirectories: false
|
|
489
|
+
});
|
|
490
|
+
} catch (error) {
|
|
491
|
+
logger.warn(`Failed to expand wildcard pattern ${wildcardPattern}: ${error}`);
|
|
492
|
+
return expanded;
|
|
493
|
+
}
|
|
494
|
+
for (const match of matches){
|
|
495
|
+
// Extract the matched subpath
|
|
496
|
+
// "features/foo.ts" -> "foo"
|
|
497
|
+
// "features/bar/index.ts" -> "bar"
|
|
498
|
+
const relativePath = normalizePath(match);
|
|
499
|
+
const ext = path__default.default.extname(relativePath);
|
|
500
|
+
const withoutExt = relativePath.slice(0, -ext.length);
|
|
501
|
+
// Remove the base path to get just the matched part
|
|
502
|
+
// "features/foo" -> "foo" (when basePath is "features")
|
|
503
|
+
let matchedPart = withoutExt;
|
|
504
|
+
if (basePath && matchedPart.startsWith(basePath + '/')) {
|
|
505
|
+
matchedPart = matchedPart.slice(basePath.length + 1);
|
|
506
|
+
} else if (basePath && matchedPart === basePath) {
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
// Handle index files
|
|
510
|
+
let matchedSubpath;
|
|
511
|
+
if (matchedPart.endsWith('/index')) {
|
|
512
|
+
matchedSubpath = matchedPart.slice(0, -6); // Remove "/index"
|
|
513
|
+
// If there's still a path, take the last segment
|
|
514
|
+
const lastSlash = matchedSubpath.lastIndexOf('/');
|
|
515
|
+
matchedSubpath = lastSlash >= 0 ? matchedSubpath.slice(lastSlash + 1) : matchedSubpath;
|
|
516
|
+
} else {
|
|
517
|
+
// Take the first segment (what matches the *)
|
|
518
|
+
const firstSlash = matchedPart.indexOf('/');
|
|
519
|
+
matchedSubpath = firstSlash >= 0 ? matchedPart.slice(0, firstSlash) : matchedPart;
|
|
520
|
+
}
|
|
521
|
+
// Build the concrete export path
|
|
522
|
+
// "./features/*" + "foo" -> "./features/foo"
|
|
523
|
+
const concreteExportPath = basePath ? `./${basePath}/${matchedSubpath}` : `./${matchedSubpath}`;
|
|
524
|
+
expanded.set(concreteExportPath, matchedSubpath);
|
|
525
|
+
}
|
|
526
|
+
return expanded;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Process export value for wildcard patterns, substituting wildcards in output paths
|
|
531
|
+
*/ async function processWildcardExportValue(exportValue, originalExportKey, currentPath, exportTypes, exportToDist, matchedSubpath) {
|
|
532
|
+
// End of searching, export value is file path.
|
|
533
|
+
// <export key>: <export value> (string)
|
|
534
|
+
if (typeof exportValue === 'string') {
|
|
535
|
+
const composedTypes = new Set(exportTypes);
|
|
536
|
+
const exportType = originalExportKey.startsWith('.') ? 'default' : originalExportKey;
|
|
537
|
+
composedTypes.add(exportType);
|
|
538
|
+
const exportInfo = exportToDist.get(mapExportFullPath(currentPath));
|
|
539
|
+
const exportCondition = Array.from(composedTypes).join('.');
|
|
540
|
+
// Substitute wildcard in output path
|
|
541
|
+
const substitutedPath = substituteWildcardInPath(exportValue, matchedSubpath);
|
|
542
|
+
if (!exportInfo) {
|
|
543
|
+
const outputConditionPair = [
|
|
544
|
+
substitutedPath,
|
|
545
|
+
exportCondition
|
|
546
|
+
];
|
|
547
|
+
addToExportDistMap(exportToDist, currentPath, [
|
|
548
|
+
outputConditionPair
|
|
549
|
+
]);
|
|
550
|
+
} else {
|
|
551
|
+
exportInfo.push([
|
|
552
|
+
substitutedPath,
|
|
553
|
+
exportCondition
|
|
554
|
+
]);
|
|
555
|
+
}
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
const exportKeys = Object.keys(exportValue);
|
|
559
|
+
for (const exportKey of exportKeys){
|
|
560
|
+
// Clone the set to avoid modifying the parent set
|
|
561
|
+
const childExports = new Set(exportTypes);
|
|
562
|
+
// Normalize child export value to a map
|
|
563
|
+
const childExportValue = exportValue[exportKey];
|
|
564
|
+
// Substitute wildcard in nested string values
|
|
565
|
+
let processedChildValue = childExportValue;
|
|
566
|
+
if (typeof childExportValue === 'string') {
|
|
567
|
+
processedChildValue = substituteWildcardInPath(childExportValue, matchedSubpath);
|
|
568
|
+
} else if (typeof childExportValue === 'object' && childExportValue !== null) {
|
|
569
|
+
// Recursively process nested objects
|
|
570
|
+
const processed = {};
|
|
571
|
+
for (const [key, value] of Object.entries(childExportValue)){
|
|
572
|
+
if (typeof value === 'string') {
|
|
573
|
+
processed[key] = substituteWildcardInPath(value, matchedSubpath);
|
|
574
|
+
} else if (value !== null && value !== undefined) {
|
|
575
|
+
processed[key] = value;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
processedChildValue = processed;
|
|
579
|
+
}
|
|
580
|
+
// Visit export path: ./subpath, ./subpath2, ...
|
|
581
|
+
if (exportKey.startsWith('.')) {
|
|
582
|
+
const childPath = joinRelativePath(currentPath, exportKey);
|
|
583
|
+
await processWildcardExportValue(processedChildValue, exportKey, childPath, childExports, exportToDist, matchedSubpath);
|
|
584
|
+
} else {
|
|
585
|
+
// Visit export type: import, require, ...
|
|
586
|
+
childExports.add(exportKey);
|
|
587
|
+
await processWildcardExportValue(processedChildValue, exportKey, currentPath, childExports, exportToDist, matchedSubpath);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
440
591
|
function collectExportPath(exportValue, exportKey, currentPath, exportTypes, exportToDist) {
|
|
441
592
|
// End of searching, export value is file path.
|
|
442
593
|
// <export key>: <export value> (string)
|
|
@@ -498,7 +649,7 @@ function addToExportDistMap(exportToDist, exportPath, outputConditionPairs) {
|
|
|
498
649
|
* './index': { development: ..., default: ... }
|
|
499
650
|
* './index.react-server': { development: ..., default: ... }
|
|
500
651
|
* }
|
|
501
|
-
*/ function parseExports(pkg) {
|
|
652
|
+
*/ async function parseExports(pkg, cwd) {
|
|
502
653
|
var _pkg_exports;
|
|
503
654
|
const exportsField = (_pkg_exports = pkg.exports) != null ? _pkg_exports : {};
|
|
504
655
|
var _pkg_bin;
|
|
@@ -522,6 +673,17 @@ function addToExportDistMap(exportToDist, exportPath, outputConditionPairs) {
|
|
|
522
673
|
const exportValue = exportsField[exportKey];
|
|
523
674
|
const exportTypes = new Set();
|
|
524
675
|
const isExportPath = exportKey.startsWith('.');
|
|
676
|
+
// Handle wildcard patterns
|
|
677
|
+
if (isExportPath && hasWildcardPattern(exportKey) && cwd) {
|
|
678
|
+
// Expand wildcard pattern to concrete exports
|
|
679
|
+
const expanded = await expandWildcardPattern(exportKey, cwd);
|
|
680
|
+
for (const [concreteExportPath, matchedSubpath] of expanded){
|
|
681
|
+
const childPath = joinRelativePath(currentPath, concreteExportPath);
|
|
682
|
+
// Process the export value and substitute wildcards in output paths
|
|
683
|
+
await processWildcardExportValue(exportValue, exportKey, childPath, exportTypes, exportToDist, matchedSubpath);
|
|
684
|
+
}
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
525
687
|
const childPath = isExportPath ? joinRelativePath(currentPath, exportKey) : currentPath;
|
|
526
688
|
if (!isExportPath) {
|
|
527
689
|
exportTypes.add(exportKey);
|
|
@@ -2203,7 +2365,7 @@ async function bundle(cliEntryPath, { cwd: _cwd, onSuccess, ...options } = {}) {
|
|
|
2203
2365
|
assignDefault(options, 'minify', false);
|
|
2204
2366
|
assignDefault(options, 'target', 'es2015');
|
|
2205
2367
|
const pkg = await getPackageMeta(cwd);
|
|
2206
|
-
const parsedExportsInfo = parseExports(pkg);
|
|
2368
|
+
const parsedExportsInfo = await parseExports(pkg, cwd);
|
|
2207
2369
|
const isMultiEntries = hasMultiEntryExport(parsedExportsInfo);
|
|
2208
2370
|
const hasBin = Boolean(pkg.bin);
|
|
2209
2371
|
// Original input file path, client path might change later
|