bunchee 4.2.10 → 4.3.0
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 +66 -52
- package/dist/bin/cli.js +253 -13
- package/dist/index.d.ts +17 -0
- package/dist/index.js +137 -74
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,39 +35,96 @@ npm install --save-dev bunchee typescript
|
|
|
35
35
|
|
|
36
36
|
Create your library entry file and package.json.
|
|
37
37
|
```sh
|
|
38
|
-
cd ./my-lib
|
|
39
|
-
touch ./src/index.ts
|
|
40
|
-
touch package.json
|
|
38
|
+
cd ./my-lib
|
|
39
|
+
mkdir src && touch ./src/index.ts
|
|
41
40
|
```
|
|
42
41
|
|
|
42
|
+
#### Prepare
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
# Use bunchee to prepare package.json configuration
|
|
46
|
+
npm bunchee --prepare
|
|
47
|
+
# "If you're using other package manager such as pnpm"
|
|
48
|
+
# pnpm bunchee --prepare
|
|
49
|
+
|
|
50
|
+
# "Or use with npx"
|
|
51
|
+
# npx bunchee@latest --prepare
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Or you can checkout the following cases to configure your package.json.
|
|
55
|
+
|
|
56
|
+
<details>
|
|
57
|
+
<summary> JavaScript</summary>
|
|
58
|
+
|
|
43
59
|
Then use use the [exports field in package.json](https://nodejs.org/api/packages.html#exports-sugar) to configure different conditions and leverage the same functionality as other bundlers, such as webpack. The exports field allows you to define multiple conditions.
|
|
44
60
|
```json
|
|
45
61
|
{
|
|
46
62
|
"files": ["dist"],
|
|
47
63
|
"exports": {
|
|
48
|
-
"import": "./dist/index.mjs",
|
|
49
|
-
"require": "./dist/index.cjs"
|
|
64
|
+
"import": "./dist/es/index.mjs",
|
|
65
|
+
"require": "./dist/cjs/index.cjs"
|
|
66
|
+
},
|
|
67
|
+
"scripts": {
|
|
68
|
+
"build": "bunchee"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
</details>
|
|
73
|
+
|
|
74
|
+
<details>
|
|
75
|
+
<summary>TypeScript</summary>
|
|
76
|
+
|
|
77
|
+
If you're build a TypeScript library, separate the types from the main entry file and specify the types path in package.json. When you're using `.mjs` or `.cjs` extensions with TypeScript and modern module resolution (above node16), TypeScript will require specific type declaration files like `.d.mts` or `.d.cts` to match the extension. `bunchee` can automatically generate them to match the types to match the condition and extensions. One example is to configure your exports like this in package.json:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"files": ["dist"],
|
|
82
|
+
"exports": {
|
|
83
|
+
"import": {
|
|
84
|
+
"types": "./dist/es/index.d.mts",
|
|
85
|
+
"default": "./dist/es/index.mjs"
|
|
86
|
+
},
|
|
87
|
+
"require": {
|
|
88
|
+
"types": "./dist/cjs/index.d.cts",
|
|
89
|
+
"default": "./dist/cjs/index.cjs"
|
|
90
|
+
}
|
|
50
91
|
},
|
|
51
92
|
"scripts": {
|
|
52
93
|
"build": "bunchee"
|
|
53
94
|
}
|
|
54
95
|
}
|
|
55
96
|
```
|
|
97
|
+
</details>
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
<details>
|
|
101
|
+
<summary>Hybrid (CJS & ESM) Module Resolution with TypeScript</summary>
|
|
102
|
+
If you're using TypeScript with Node 10 and Node 16 module resolution, you can use the `types` field in package.json to specify the types path. Then `bunchee` will generate the types file with the same extension as the main entry file.
|
|
56
103
|
|
|
57
|
-
If you want to use ESM package, change the `type` field in package.json to `module`, `bunchee` will change the output format to ESM.
|
|
58
104
|
```json
|
|
59
105
|
{
|
|
60
|
-
"type": "module",
|
|
61
106
|
"files": ["dist"],
|
|
107
|
+
"main": "./dist/cjs/index.cjs",
|
|
108
|
+
"module": "./dist/es/index.mjs",
|
|
109
|
+
"types": "./dist/cjs/index.d.ts",
|
|
62
110
|
"exports": {
|
|
63
|
-
"import":
|
|
64
|
-
|
|
111
|
+
"import": {
|
|
112
|
+
"types": "./dist/es/index.d.mts",
|
|
113
|
+
"default": "./dist/es/index.mjs"
|
|
114
|
+
},
|
|
115
|
+
"require": {
|
|
116
|
+
"types": "./dist/cjs/index.d.cts",
|
|
117
|
+
"default": "./dist/cjs/index.cjs"
|
|
118
|
+
}
|
|
65
119
|
},
|
|
66
120
|
"scripts": {
|
|
67
121
|
"build": "bunchee"
|
|
68
122
|
}
|
|
69
123
|
}
|
|
70
124
|
```
|
|
125
|
+
</details>
|
|
126
|
+
|
|
127
|
+
#### Build
|
|
71
128
|
|
|
72
129
|
Then files in `src` folders will be treated as entry files and match the export names in package.json. For example:
|
|
73
130
|
`src/index.ts` will match the exports name `"."` or the only main export.
|
|
@@ -122,28 +179,6 @@ Then you need to add two entry files `index.ts` and `lite.ts` in project root di
|
|
|
122
179
|
|
|
123
180
|
It will also look up for `index.<ext>` file under the directory having the name of the export path. For example, if you have `"./lite": "./dist/lite.js"` in exports field, then it will look up for `./lite/index.js` as the entry file as well.
|
|
124
181
|
|
|
125
|
-
### TypeScript Declaration
|
|
126
|
-
|
|
127
|
-
When you're using `.mjs` or `.cjs` extensions with TypeScript and modern module resolution (above node16), TypeScript will require specific type declaration files like `.d.mts` or `.d.cts` to match the extension.
|
|
128
|
-
`bunchee` can automatically generate them to match the types to match the condition and extensions. One example is to configure your exports like this in package.json:
|
|
129
|
-
|
|
130
|
-
```json
|
|
131
|
-
{
|
|
132
|
-
"exports": {
|
|
133
|
-
".": {
|
|
134
|
-
"import": {
|
|
135
|
-
"types": "./dist/index.d.ts",
|
|
136
|
-
"default": "./dist/index.mjs"
|
|
137
|
-
},
|
|
138
|
-
"require": {
|
|
139
|
-
"types": "./dist/index.d.ts",
|
|
140
|
-
"default": "./dist/index.js"
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
182
|
### Multiple Runtime
|
|
148
183
|
|
|
149
184
|
For exports condition like `react-native`, `react-server` and `edge-light` as they're special platforms, they could have different exports or different code conditions. In this case bunchee provides an override input source file convention if you want to build them as different code bundle.
|
|
@@ -322,7 +357,6 @@ This will match the export names `"foo"` and `"bar"` and will be treated as the
|
|
|
322
357
|
{
|
|
323
358
|
"exports": {
|
|
324
359
|
".": {
|
|
325
|
-
"types": "./dist/index.d.ts",
|
|
326
360
|
"import": "./dist/index.js"
|
|
327
361
|
},
|
|
328
362
|
"./foo": {
|
|
@@ -380,26 +414,6 @@ output
|
|
|
380
414
|
export default "hello world"
|
|
381
415
|
```
|
|
382
416
|
|
|
383
|
-
### TypeScript
|
|
384
|
-
|
|
385
|
-
By default bunchee includes Typescript v3.9.x inside as a dependency. If you want to use your own version, just install typescript as another dev dependency then bunchee will automatically pick it.
|
|
386
|
-
|
|
387
|
-
```sh
|
|
388
|
-
npm i -D bunchee typescript
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
Create `tsconfig.json` to specify any compiler options for TypeScript.
|
|
392
|
-
|
|
393
|
-
This library requires at least TypeScript 4.1.x.
|
|
394
|
-
|
|
395
|
-
Adding `"types"` or `"typing"` field in your package.json, types will be generated with that path.
|
|
396
|
-
|
|
397
|
-
```json
|
|
398
|
-
{
|
|
399
|
-
"types": "dist/types/index.d.ts"
|
|
400
|
-
}
|
|
401
|
-
```
|
|
402
|
-
|
|
403
417
|
### Node.js API
|
|
404
418
|
|
|
405
419
|
```ts
|
package/dist/bin/cli.js
CHANGED
|
@@ -1,16 +1,41 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
var path = require('path');
|
|
3
3
|
var arg = require('arg');
|
|
4
|
-
var
|
|
4
|
+
var fsp = require('fs/promises');
|
|
5
5
|
var require$$0 = require('tty');
|
|
6
6
|
var bunchee = require('bunchee');
|
|
7
|
+
var fs = require('fs');
|
|
7
8
|
|
|
8
9
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
10
|
|
|
10
11
|
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
11
12
|
var arg__default = /*#__PURE__*/_interopDefault(arg);
|
|
12
|
-
var
|
|
13
|
+
var fsp__default = /*#__PURE__*/_interopDefault(fsp);
|
|
13
14
|
var require$$0__default = /*#__PURE__*/_interopDefault(require$$0);
|
|
15
|
+
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
16
|
+
|
|
17
|
+
const availableExtensions = [
|
|
18
|
+
'js',
|
|
19
|
+
'cjs',
|
|
20
|
+
'mjs',
|
|
21
|
+
'jsx',
|
|
22
|
+
'ts',
|
|
23
|
+
'tsx',
|
|
24
|
+
'cts',
|
|
25
|
+
'mts'
|
|
26
|
+
];
|
|
27
|
+
const SRC = 'src';
|
|
28
|
+
const dtsExtensionsMap = {
|
|
29
|
+
js: 'd.ts',
|
|
30
|
+
cjs: 'd.cts',
|
|
31
|
+
mjs: 'd.mts'
|
|
32
|
+
};
|
|
33
|
+
const tsExtensions = [
|
|
34
|
+
'ts',
|
|
35
|
+
'tsx',
|
|
36
|
+
'cts',
|
|
37
|
+
'mts'
|
|
38
|
+
];
|
|
14
39
|
|
|
15
40
|
function getDefaultExportFromCjs (x) {
|
|
16
41
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
@@ -64,25 +89,29 @@ picocolors.exports.createColors = createColors;
|
|
|
64
89
|
var picocolorsExports = picocolors.exports;
|
|
65
90
|
var pc = /*@__PURE__*/ getDefaultExportFromCjs(picocolorsExports);
|
|
66
91
|
|
|
92
|
+
const defaultColorFn = (text)=>text;
|
|
93
|
+
function color(prefixColor) {
|
|
94
|
+
return pc.isColorSupported ? pc[prefixColor] : defaultColorFn;
|
|
95
|
+
}
|
|
67
96
|
const logger = {
|
|
68
97
|
log (...arg) {
|
|
69
|
-
console.log(
|
|
98
|
+
console.log(...arg);
|
|
70
99
|
},
|
|
71
100
|
warn (...arg) {
|
|
72
|
-
console.warn('
|
|
101
|
+
console.warn(color('yellow')('⚠️'), ...arg);
|
|
73
102
|
},
|
|
74
103
|
error (...arg) {
|
|
75
|
-
console.error('
|
|
104
|
+
console.error(color('red')('⨯'), ...arg);
|
|
76
105
|
},
|
|
77
106
|
info (...arg) {
|
|
78
|
-
console.log('
|
|
107
|
+
console.log(color('green')('✓'), ...arg);
|
|
79
108
|
}
|
|
80
109
|
};
|
|
81
110
|
function paint(prefix, prefixColor, ...arg) {
|
|
82
111
|
if (pc.isColorSupported) {
|
|
83
|
-
console.log(
|
|
112
|
+
console.log(pc[prefixColor](prefix), ...arg);
|
|
84
113
|
} else {
|
|
85
|
-
console.log(
|
|
114
|
+
console.log(prefix, ...arg);
|
|
86
115
|
}
|
|
87
116
|
}
|
|
88
117
|
|
|
@@ -97,15 +126,19 @@ async function getPackageMeta(cwd) {
|
|
|
97
126
|
const pkgFilePath = path__default.default.resolve(cwd, 'package.json');
|
|
98
127
|
let targetPackageJson = {};
|
|
99
128
|
try {
|
|
100
|
-
targetPackageJson = JSON.parse(await
|
|
129
|
+
targetPackageJson = JSON.parse(await fsp__default.default.readFile(pkgFilePath, {
|
|
101
130
|
encoding: 'utf-8'
|
|
102
131
|
}));
|
|
103
132
|
} catch (_) {}
|
|
104
133
|
return targetPackageJson;
|
|
105
134
|
}
|
|
135
|
+
function isTypescriptFile(filename) {
|
|
136
|
+
const ext = path__default.default.extname(filename).slice(1);
|
|
137
|
+
return tsExtensions.includes(ext);
|
|
138
|
+
}
|
|
106
139
|
async function fileExists(filePath) {
|
|
107
140
|
try {
|
|
108
|
-
await
|
|
141
|
+
await fsp__default.default.access(filePath);
|
|
109
142
|
return true;
|
|
110
143
|
} catch (err) {
|
|
111
144
|
if (err.code === 'ENOENT') {
|
|
@@ -114,8 +147,209 @@ async function fileExists(filePath) {
|
|
|
114
147
|
throw err;
|
|
115
148
|
}
|
|
116
149
|
}
|
|
150
|
+
const hasAvailableExtension = (filename)=>availableExtensions.includes(path__default.default.extname(filename).slice(1));
|
|
151
|
+
const baseNameWithoutExtension = (filename)=>path__default.default.basename(filename, path__default.default.extname(filename));
|
|
152
|
+
|
|
153
|
+
var version = "4.3.0";
|
|
117
154
|
|
|
118
|
-
|
|
155
|
+
function relativify(path) {
|
|
156
|
+
return path.startsWith('.') ? path : `./${path}`;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const DIST = 'dist';
|
|
160
|
+
// Output with posix style in package.json
|
|
161
|
+
function getDistPath(...subPaths) {
|
|
162
|
+
return `./${DIST}/${subPaths.join('/')}`;
|
|
163
|
+
}
|
|
164
|
+
const normalizeBaseNameToExportName = (baseName)=>{
|
|
165
|
+
return /^index(\.|$)/.test(baseName) ? '.' : relativify(baseName);
|
|
166
|
+
};
|
|
167
|
+
function createExportCondition(exportName, sourceFile, moduleType) {
|
|
168
|
+
const isTsSourceFile = isTypescriptFile(sourceFile);
|
|
169
|
+
let cjsExtension = 'js';
|
|
170
|
+
if (moduleType === 'module') {
|
|
171
|
+
cjsExtension = 'cjs';
|
|
172
|
+
}
|
|
173
|
+
if (isTsSourceFile) {
|
|
174
|
+
return {
|
|
175
|
+
import: {
|
|
176
|
+
types: getDistPath('es', `${exportName}.d.mts`),
|
|
177
|
+
default: getDistPath('es', `${exportName}.mjs`)
|
|
178
|
+
},
|
|
179
|
+
require: {
|
|
180
|
+
types: getDistPath('cjs', `${exportName}.${dtsExtensionsMap[cjsExtension]}`),
|
|
181
|
+
default: getDistPath('cjs', `${exportName}.${cjsExtension}`)
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
import: getDistPath(`${exportName}.mjs`),
|
|
187
|
+
require: getDistPath(`${exportName}.${cjsExtension}`)
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
async function collectSourceEntries(sourceFolderPath) {
|
|
191
|
+
const bins = new Map();
|
|
192
|
+
const exportsEntries = new Map();
|
|
193
|
+
const entryFileDirentList = await fsp__default.default.readdir(sourceFolderPath, {
|
|
194
|
+
withFileTypes: true
|
|
195
|
+
});
|
|
196
|
+
for (const dirent of entryFileDirentList){
|
|
197
|
+
if (dirent.isDirectory()) {
|
|
198
|
+
if (dirent.name === 'bin') {
|
|
199
|
+
const binDirentList = await fsp__default.default.readdir(path__default.default.join(sourceFolderPath, dirent.name), {
|
|
200
|
+
withFileTypes: true
|
|
201
|
+
});
|
|
202
|
+
for (const binDirent of binDirentList){
|
|
203
|
+
if (binDirent.isFile()) {
|
|
204
|
+
const binFile = path__default.default.join(sourceFolderPath, dirent.name, binDirent.name);
|
|
205
|
+
const binName = baseNameWithoutExtension(binDirent.name);
|
|
206
|
+
if (fs__default.default.existsSync(binFile)) {
|
|
207
|
+
bins.set(binName, binDirent.name);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
// Search folder/<index>.<ext> convention entries
|
|
213
|
+
const extensions = availableExtensions;
|
|
214
|
+
for (const extension of extensions){
|
|
215
|
+
const indexFile = path__default.default.join(sourceFolderPath, dirent.name, `index.${extension}`);
|
|
216
|
+
if (fs__default.default.existsSync(indexFile)) {
|
|
217
|
+
exportsEntries.set(dirent.name, indexFile);
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
} else if (dirent.isFile()) {
|
|
223
|
+
const isAvailableExtension = availableExtensions.includes(path__default.default.extname(dirent.name).slice(1));
|
|
224
|
+
if (isAvailableExtension) {
|
|
225
|
+
const baseName = baseNameWithoutExtension(dirent.name);
|
|
226
|
+
const isBinFile = baseName === 'bin';
|
|
227
|
+
if (isBinFile) {
|
|
228
|
+
bins.set('.', dirent.name);
|
|
229
|
+
} else {
|
|
230
|
+
if (hasAvailableExtension(dirent.name)) {
|
|
231
|
+
exportsEntries.set(baseName, dirent.name);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
bins,
|
|
239
|
+
exportsEntries
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function createExportConditionPair(exportName, sourceFile, moduleType) {
|
|
243
|
+
// <exportName>.<specialCondition>
|
|
244
|
+
let specialCondition;
|
|
245
|
+
let exportCondName;
|
|
246
|
+
if (exportName.indexOf('.') > 0) {
|
|
247
|
+
const [originExportName, specialConditionName] = exportName.split('.');
|
|
248
|
+
specialCondition = {
|
|
249
|
+
[specialConditionName]: getDistPath('es', `${originExportName}-${specialConditionName}.mjs`)
|
|
250
|
+
};
|
|
251
|
+
exportCondName = normalizeBaseNameToExportName(originExportName);
|
|
252
|
+
return [
|
|
253
|
+
exportCondName,
|
|
254
|
+
specialCondition
|
|
255
|
+
];
|
|
256
|
+
}
|
|
257
|
+
exportCondName = normalizeBaseNameToExportName(exportName);
|
|
258
|
+
const exportCond = createExportCondition(exportName, sourceFile, moduleType);
|
|
259
|
+
return [
|
|
260
|
+
exportCondName,
|
|
261
|
+
exportCond
|
|
262
|
+
];
|
|
263
|
+
}
|
|
264
|
+
async function prepare(cwd) {
|
|
265
|
+
const sourceFolder = path__default.default.resolve(cwd, SRC);
|
|
266
|
+
if (!fs__default.default.existsSync(sourceFolder)) {
|
|
267
|
+
logger.error(`Source folder ${sourceFolder} does not exist. Cannot proceed to configure \`exports\` field.`);
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
const pkgJsonPath = path__default.default.join(cwd, 'package.json');
|
|
271
|
+
let pkgJson = {};
|
|
272
|
+
if (fs__default.default.existsSync(pkgJsonPath)) {
|
|
273
|
+
const pkgJsonString = await fsp__default.default.readFile(pkgJsonPath, 'utf-8');
|
|
274
|
+
pkgJson = JSON.parse(pkgJsonString);
|
|
275
|
+
}
|
|
276
|
+
// configure `files` field with `dist`
|
|
277
|
+
const files = pkgJson.files || [];
|
|
278
|
+
if (!files.includes(DIST)) {
|
|
279
|
+
files.push(DIST);
|
|
280
|
+
}
|
|
281
|
+
pkgJson.files = files;
|
|
282
|
+
let isUsingTs = false;
|
|
283
|
+
// Collect bins and exports entries
|
|
284
|
+
const { bins, exportsEntries } = await collectSourceEntries(sourceFolder);
|
|
285
|
+
const tsconfigPath = path__default.default.join(cwd, 'tsconfig.json');
|
|
286
|
+
if (!fs__default.default.existsSync(tsconfigPath)) {
|
|
287
|
+
const sourceFiles = [
|
|
288
|
+
...exportsEntries.values()
|
|
289
|
+
].concat([
|
|
290
|
+
...bins.values()
|
|
291
|
+
]);
|
|
292
|
+
const hasTypeScriptFiles = sourceFiles.some((filename)=>isTypescriptFile(filename));
|
|
293
|
+
if (hasTypeScriptFiles) {
|
|
294
|
+
isUsingTs = true;
|
|
295
|
+
await fsp__default.default.writeFile(tsconfigPath, '{}', 'utf-8');
|
|
296
|
+
logger.log(`Detected using TypeScript but tsconfig.json is missing, created a ${pc.blue('tsconfig.json')} for you.`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
// Configure as ESM package by default if there's no `type` field
|
|
300
|
+
if (!pkgJson.type) {
|
|
301
|
+
pkgJson.type = 'module';
|
|
302
|
+
}
|
|
303
|
+
if (bins.size > 0) {
|
|
304
|
+
logger.log('Discovered binaries entries:');
|
|
305
|
+
const maxLengthOfBinName = Math.max(...Array.from(bins.keys()).map((binName)=>normalizeBaseNameToExportName(binName).length));
|
|
306
|
+
for (const [binName, binFile] of bins.entries()){
|
|
307
|
+
const spaces = ' '.repeat(Math.max(maxLengthOfBinName - normalizeBaseNameToExportName(binName).length, 0));
|
|
308
|
+
logger.log(` ${normalizeBaseNameToExportName(binName)}${spaces}: ${binFile}`);
|
|
309
|
+
}
|
|
310
|
+
if (bins.size === 1 && bins.has('.')) {
|
|
311
|
+
pkgJson.bin = getDistPath('bin', 'index.js');
|
|
312
|
+
} else {
|
|
313
|
+
pkgJson.bin = {};
|
|
314
|
+
for (const [binName] of bins.entries()){
|
|
315
|
+
pkgJson.bin[binName === '.' ? pkgJson.name : binName] = getDistPath('bin', binName + '.js');
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (exportsEntries.size > 0) {
|
|
320
|
+
logger.log('Discovered exports entries:');
|
|
321
|
+
const maxLengthOfExportName = Math.max(...Array.from(exportsEntries.keys()).map((exportName)=>normalizeBaseNameToExportName(exportName).length));
|
|
322
|
+
for (const [exportName, exportFile] of exportsEntries.entries()){
|
|
323
|
+
const spaces = ' '.repeat(Math.max(maxLengthOfExportName - normalizeBaseNameToExportName(exportName).length, 0));
|
|
324
|
+
logger.log(` ${normalizeBaseNameToExportName(exportName)}${spaces}: ${exportFile}`);
|
|
325
|
+
}
|
|
326
|
+
const pkgExports = {};
|
|
327
|
+
for (const [exportName, sourceFile] of exportsEntries.entries()){
|
|
328
|
+
const [key, value] = createExportConditionPair(exportName, sourceFile, pkgJson.type);
|
|
329
|
+
pkgExports[key] = {
|
|
330
|
+
...value,
|
|
331
|
+
...pkgExports[key]
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
// Configure node10 module resolution
|
|
335
|
+
if (exportsEntries.has('index')) {
|
|
336
|
+
const isESM = pkgJson.type === 'module';
|
|
337
|
+
const mainExport = pkgExports['.'];
|
|
338
|
+
const mainCondition = isESM ? 'import' : 'require';
|
|
339
|
+
pkgJson.main = isUsingTs ? mainExport[mainCondition].default : mainExport[mainCondition];
|
|
340
|
+
pkgJson.module = isUsingTs ? mainExport.import.default : mainExport.import;
|
|
341
|
+
if (isUsingTs) {
|
|
342
|
+
pkgJson.types = isESM ? mainExport.import.types : mainExport.require.types;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// Assign the properties by order: files, main, module, types, exports
|
|
346
|
+
if (Object.keys(pkgExports).length > 0) {
|
|
347
|
+
pkgJson.exports = pkgExports;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
await fsp__default.default.writeFile(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
|
|
351
|
+
logger.info('Configured `exports` in package.json');
|
|
352
|
+
}
|
|
119
353
|
|
|
120
354
|
const helpMessage = `
|
|
121
355
|
Usage: bunchee [options]
|
|
@@ -127,6 +361,7 @@ Options:
|
|
|
127
361
|
-o, --output <file> specify output filename
|
|
128
362
|
-f, --format <format> type of output (esm, amd, cjs, iife, umd, system), default: esm
|
|
129
363
|
-h, --help output usage information
|
|
364
|
+
--prepare auto configure package.json exports for building
|
|
130
365
|
--external <mod> specify an external dependency, separate by comma
|
|
131
366
|
--no-external do not bundle external dependencies
|
|
132
367
|
--target <target> js features target: swc target es versions. default: es2015
|
|
@@ -172,6 +407,7 @@ function parseCliArgs(argv) {
|
|
|
172
407
|
'--env': String,
|
|
173
408
|
'--external': String,
|
|
174
409
|
'--no-external': Boolean,
|
|
410
|
+
'--prepare': Boolean,
|
|
175
411
|
'-h': '--help',
|
|
176
412
|
'-v': '--version',
|
|
177
413
|
'-w': '--watch',
|
|
@@ -197,7 +433,8 @@ function parseCliArgs(argv) {
|
|
|
197
433
|
runtime: args['--runtime'],
|
|
198
434
|
target: args['--target'],
|
|
199
435
|
external: !!args['--no-external'] ? null : args['--external'],
|
|
200
|
-
env: args['--env']
|
|
436
|
+
env: args['--env'],
|
|
437
|
+
prepare: !!args['--prepare']
|
|
201
438
|
};
|
|
202
439
|
return parsedArgs;
|
|
203
440
|
}
|
|
@@ -225,6 +462,9 @@ async function run(args) {
|
|
|
225
462
|
if (args.help) {
|
|
226
463
|
return help();
|
|
227
464
|
}
|
|
465
|
+
if (args.prepare) {
|
|
466
|
+
return await prepare(cwd);
|
|
467
|
+
}
|
|
228
468
|
const entry = source ? path__default.default.resolve(cwd, source) : '';
|
|
229
469
|
try {
|
|
230
470
|
await bunchee.bundle(entry, bundleConfig);
|
|
@@ -241,7 +481,7 @@ async function run(args) {
|
|
|
241
481
|
return;
|
|
242
482
|
}
|
|
243
483
|
// build mode
|
|
244
|
-
|
|
484
|
+
logger.log();
|
|
245
485
|
paint('✓', 'green', `bunchee ${version} build completed`);
|
|
246
486
|
await lintPackage(cwd);
|
|
247
487
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { JscTarget } from '@swc/types';
|
|
2
2
|
import { OutputOptions } from 'rollup';
|
|
3
3
|
|
|
4
|
+
type ExportCondition = string | {
|
|
5
|
+
[key: string]: ExportCondition | string;
|
|
6
|
+
};
|
|
4
7
|
type BundleConfig = {
|
|
5
8
|
file?: string;
|
|
6
9
|
cwd?: string;
|
|
@@ -13,6 +16,20 @@ type BundleConfig = {
|
|
|
13
16
|
env?: string[];
|
|
14
17
|
dts?: boolean;
|
|
15
18
|
runtime?: string;
|
|
19
|
+
pkg?: PackageMetadata;
|
|
20
|
+
};
|
|
21
|
+
type PackageMetadata = {
|
|
22
|
+
name?: string;
|
|
23
|
+
main?: string;
|
|
24
|
+
bin?: string | Record<string, string>;
|
|
25
|
+
module?: string;
|
|
26
|
+
type?: 'commonjs' | 'module';
|
|
27
|
+
dependencies?: Record<string, string>;
|
|
28
|
+
peerDependencies?: Record<string, string>;
|
|
29
|
+
peerDependenciesMeta?: Record<string, Record<string, string>>;
|
|
30
|
+
exports?: string | Record<string, ExportCondition>;
|
|
31
|
+
types?: string;
|
|
32
|
+
typings?: string;
|
|
16
33
|
};
|
|
17
34
|
|
|
18
35
|
declare function bundle(entryPath: string, { cwd: _cwd, ...options }?: BundleConfig): Promise<any>;
|
package/dist/index.js
CHANGED
|
@@ -52,12 +52,11 @@ const availableExportConventions = [
|
|
|
52
52
|
'edge-light'
|
|
53
53
|
];
|
|
54
54
|
const availableESExtensionsRegex = /\.(m|c)?[jt]sx?$/;
|
|
55
|
-
const dtsExtensionRegex = /\.d\.(m|c)?ts$/;
|
|
56
55
|
const SRC = 'src';
|
|
57
|
-
const
|
|
58
|
-
js: '
|
|
59
|
-
cjs: '
|
|
60
|
-
mjs: '
|
|
56
|
+
const dtsExtensionsMap = {
|
|
57
|
+
js: 'd.ts',
|
|
58
|
+
cjs: 'd.cts',
|
|
59
|
+
mjs: 'd.mts'
|
|
61
60
|
};
|
|
62
61
|
const disabledWarnings = new Set([
|
|
63
62
|
'MIXED_EXPORTS',
|
|
@@ -120,27 +119,24 @@ picocolors.exports.createColors = createColors;
|
|
|
120
119
|
var picocolorsExports = picocolors.exports;
|
|
121
120
|
var pc = /*@__PURE__*/ getDefaultExportFromCjs(picocolorsExports);
|
|
122
121
|
|
|
122
|
+
const defaultColorFn = (text)=>text;
|
|
123
|
+
function color(prefixColor) {
|
|
124
|
+
return pc.isColorSupported ? pc[prefixColor] : defaultColorFn;
|
|
125
|
+
}
|
|
123
126
|
const logger = {
|
|
124
127
|
log (...arg) {
|
|
125
|
-
console.log(
|
|
128
|
+
console.log(...arg);
|
|
126
129
|
},
|
|
127
130
|
warn (...arg) {
|
|
128
|
-
console.warn('
|
|
131
|
+
console.warn(color('yellow')('⚠️'), ...arg);
|
|
129
132
|
},
|
|
130
133
|
error (...arg) {
|
|
131
|
-
console.error('
|
|
134
|
+
console.error(color('red')('⨯'), ...arg);
|
|
132
135
|
},
|
|
133
136
|
info (...arg) {
|
|
134
|
-
console.log('
|
|
137
|
+
console.log(color('green')('✓'), ...arg);
|
|
135
138
|
}
|
|
136
139
|
};
|
|
137
|
-
function paint(prefix, prefixColor, ...arg) {
|
|
138
|
-
if (pc.isColorSupported) {
|
|
139
|
-
console.log(' ' + pc[prefixColor](prefix), ...arg);
|
|
140
|
-
} else {
|
|
141
|
-
console.log(' ' + prefix, ...arg);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
140
|
|
|
145
141
|
function exit(err) {
|
|
146
142
|
logger.error(err);
|
|
@@ -209,7 +205,7 @@ async function getSourcePathFromExportPath(cwd, exportPath, exportType) {
|
|
|
209
205
|
return;
|
|
210
206
|
}
|
|
211
207
|
// Unlike path.basename, forcedly removing extension
|
|
212
|
-
function
|
|
208
|
+
function filePathWithoutExtension(file) {
|
|
213
209
|
return file ? file.replace(new RegExp(`${path__default.default.extname(file)}$`), '') : undefined;
|
|
214
210
|
}
|
|
215
211
|
const nonNullable = (n)=>Boolean(n);
|
|
@@ -223,8 +219,8 @@ function resolveTypescript(cwd) {
|
|
|
223
219
|
m.paths = module$1.Module._nodeModulePaths(cwd);
|
|
224
220
|
try {
|
|
225
221
|
ts = m.require('typescript');
|
|
226
|
-
} catch (
|
|
227
|
-
console.error(
|
|
222
|
+
} catch (e) {
|
|
223
|
+
console.error(e);
|
|
228
224
|
if (!hasLoggedTsWarning) {
|
|
229
225
|
hasLoggedTsWarning = true;
|
|
230
226
|
exit('Could not load TypeScript compiler. Try to install `typescript` as dev dependency');
|
|
@@ -610,7 +606,7 @@ const getExportTypeDist = (parsedExportCondition, cwd)=>{
|
|
|
610
606
|
continue;
|
|
611
607
|
}
|
|
612
608
|
const ext = path.extname(filePath).slice(1);
|
|
613
|
-
const typeFile = getDistPath(`${
|
|
609
|
+
const typeFile = getDistPath(`${filePathWithoutExtension(filePath) || ''}.${dtsExtensionsMap[ext]}`, cwd);
|
|
614
610
|
if (existed.has(typeFile)) {
|
|
615
611
|
continue;
|
|
616
612
|
}
|
|
@@ -691,7 +687,7 @@ function getExportConditionDist(pkg, parsedExportCondition, cwd) {
|
|
|
691
687
|
return dist;
|
|
692
688
|
}
|
|
693
689
|
function getTypeFilePath(entryFilePath, exportCondition, cwd) {
|
|
694
|
-
const name =
|
|
690
|
+
const name = filePathWithoutExtension(entryFilePath);
|
|
695
691
|
const firstDistPath = exportCondition ? Object.values(exportCondition.export)[0] : undefined;
|
|
696
692
|
const exportName = (exportCondition == null ? void 0 : exportCondition.name) || 'index';
|
|
697
693
|
return entryFilePath ? name + '.d.ts' : path.resolve(firstDistPath ? path.dirname(firstDistPath) : path.join(cwd, 'dist'), (exportName === '.' ? 'index' : exportName) + '.d.ts');
|
|
@@ -727,22 +723,20 @@ function getBuildEnv(envs) {
|
|
|
727
723
|
return envVars;
|
|
728
724
|
}
|
|
729
725
|
/**
|
|
730
|
-
* return { '<
|
|
731
|
-
*/ function
|
|
726
|
+
* return { '<absolute source path>': '<pkg>/<export>' }
|
|
727
|
+
*/ function getReversedAlias(entries) {
|
|
732
728
|
const alias = {};
|
|
733
729
|
for (const [entryImportPath, exportCondition] of Object.entries(entries)){
|
|
734
|
-
|
|
730
|
+
const exportType = entryImportPath.split('.')[1] // e.g. index.react-server, pick react-server
|
|
731
|
+
;
|
|
732
|
+
if (!exportType) {
|
|
733
|
+
alias[exportCondition.source] = entryImportPath;
|
|
734
|
+
}
|
|
735
735
|
}
|
|
736
736
|
return alias;
|
|
737
737
|
}
|
|
738
|
-
async function buildInputConfig(entry,
|
|
739
|
-
const
|
|
740
|
-
const reversedAlias = {};
|
|
741
|
-
for (const [key, value] of Object.entries(entriesAlias)){
|
|
742
|
-
if (value !== entry) {
|
|
743
|
-
reversedAlias[value] = key;
|
|
744
|
-
}
|
|
745
|
-
}
|
|
738
|
+
async function buildInputConfig(entry, options, buildContext, dts) {
|
|
739
|
+
const { entries, pkg, cwd, tsOptions: { tsConfigPath, tsCompilerOptions }, pluginContext } = buildContext;
|
|
746
740
|
const hasNoExternal = options.external === null;
|
|
747
741
|
var _options_external;
|
|
748
742
|
const externals = hasNoExternal ? [] : [
|
|
@@ -750,7 +744,8 @@ async function buildInputConfig(entry, entries, pkg, options, cwd, { tsConfigPat
|
|
|
750
744
|
pkg.dependencies,
|
|
751
745
|
pkg.peerDependenciesMeta
|
|
752
746
|
].filter((n)=>Boolean(n)).map((o)=>Object.keys(o)).reduce((a, b)=>a.concat(b), []).concat((_options_external = options.external) != null ? _options_external : []);
|
|
753
|
-
for (const [exportImportPath,
|
|
747
|
+
for (const [exportImportPath, exportCondition] of Object.entries(entries)){
|
|
748
|
+
const entryFilePath = exportCondition.source;
|
|
754
749
|
if (entryFilePath !== entry) {
|
|
755
750
|
externals.push(exportImportPath);
|
|
756
751
|
externals.push(entryFilePath);
|
|
@@ -782,12 +777,16 @@ async function buildInputConfig(entry, entries, pkg, options, cwd, { tsConfigPat
|
|
|
782
777
|
inlineSourcesContent: false,
|
|
783
778
|
isModule: true
|
|
784
779
|
};
|
|
785
|
-
const sizePlugin = pluginContext.
|
|
780
|
+
const sizePlugin = pluginContext.outputState.plugin(cwd);
|
|
786
781
|
// common plugins for both dts and ts assets that need to be processed
|
|
787
782
|
const commonPlugins = [
|
|
788
783
|
sizePlugin,
|
|
789
784
|
aliasEntries({
|
|
790
|
-
entries:
|
|
785
|
+
entries: {
|
|
786
|
+
...pluginContext.entriesAlias,
|
|
787
|
+
// Do not alias current alias of package
|
|
788
|
+
[entry]: null
|
|
789
|
+
}
|
|
791
790
|
})
|
|
792
791
|
];
|
|
793
792
|
const typesPlugins = [
|
|
@@ -960,14 +959,15 @@ function createSplitChunks(dependencyGraphMap, entryFiles) {
|
|
|
960
959
|
return;
|
|
961
960
|
};
|
|
962
961
|
}
|
|
963
|
-
function buildOutputConfigs(
|
|
962
|
+
function buildOutputConfigs(options, exportCondition, buildContext, dts) {
|
|
964
963
|
const { format } = options;
|
|
964
|
+
const { entries, pkg, exportPaths, cwd, tsOptions: { tsCompilerOptions }, pluginContext } = buildContext;
|
|
965
965
|
// Add esm mark and interop helper if esm export is detected
|
|
966
966
|
const useEsModuleMark = hasEsmExport(exportPaths, tsCompilerOptions);
|
|
967
967
|
const typings = getTypings(pkg);
|
|
968
968
|
const file = options.file && path.resolve(cwd, options.file);
|
|
969
969
|
const dtsDir = typings ? path.dirname(path.resolve(cwd, typings)) : path.resolve(cwd, 'dist');
|
|
970
|
-
const name =
|
|
970
|
+
const name = filePathWithoutExtension(file);
|
|
971
971
|
// TODO: simplify dts file name detection
|
|
972
972
|
const dtsFile = file ? file : exportCondition.export['types'] ? path.resolve(cwd, exportCondition.export['types']) : path.resolve(dtsDir, (exportCondition.name === '.' ? 'index' : exportCondition.name) + '.d.ts');
|
|
973
973
|
const dtsPathConfig = {
|
|
@@ -995,10 +995,11 @@ function buildOutputConfigs(entries, pkg, exportPaths, options, exportCondition,
|
|
|
995
995
|
entryFileNames: path.basename(outputFile)
|
|
996
996
|
};
|
|
997
997
|
}
|
|
998
|
-
async function buildEntryConfig(
|
|
998
|
+
async function buildEntryConfig(bundleConfig, pluginContext, dts) {
|
|
999
999
|
const configs = [];
|
|
1000
|
+
const { entries } = pluginContext;
|
|
1000
1001
|
for (const exportCondition of Object.values(entries)){
|
|
1001
|
-
const rollupConfig = buildConfig(
|
|
1002
|
+
const rollupConfig = buildConfig(bundleConfig, exportCondition, pluginContext, dts);
|
|
1002
1003
|
configs.push(rollupConfig);
|
|
1003
1004
|
}
|
|
1004
1005
|
return await Promise.all(configs);
|
|
@@ -1040,7 +1041,9 @@ async function buildEntryConfig(entries, pkg, exportPaths, bundleConfig, cwd, ts
|
|
|
1040
1041
|
name: entryExport,
|
|
1041
1042
|
export: exportCondForType
|
|
1042
1043
|
};
|
|
1043
|
-
const
|
|
1044
|
+
const nameWithExportPath = pkg.name ? path__default.default.join(pkg.name, exportCondition.name) : exportCondition.name;
|
|
1045
|
+
const needsDelimiter = !nameWithExportPath.endsWith('.') && exportType;
|
|
1046
|
+
const entryImportPath = nameWithExportPath + (needsDelimiter ? '.' : '') + exportType;
|
|
1044
1047
|
entries[entryImportPath] = exportCondition;
|
|
1045
1048
|
}
|
|
1046
1049
|
const binaryExports = pkg.bin;
|
|
@@ -1090,47 +1093,48 @@ async function buildEntryConfig(entries, pkg, exportPaths, bundleConfig, cwd, ts
|
|
|
1090
1093
|
await Promise.all(collectEntriesPromises);
|
|
1091
1094
|
return entries;
|
|
1092
1095
|
}
|
|
1093
|
-
async function buildConfig(
|
|
1096
|
+
async function buildConfig(bundleConfig, exportCondition, pluginContext, dts) {
|
|
1094
1097
|
const { file } = bundleConfig;
|
|
1098
|
+
const { pkg, cwd, tsOptions } = pluginContext;
|
|
1095
1099
|
const useTypescript = Boolean(tsOptions.tsConfigPath);
|
|
1096
1100
|
const options = {
|
|
1097
1101
|
...bundleConfig,
|
|
1098
1102
|
useTypescript
|
|
1099
1103
|
};
|
|
1100
1104
|
const entry = exportCondition.source;
|
|
1101
|
-
const inputOptions = await buildInputConfig(entry,
|
|
1105
|
+
const inputOptions = await buildInputConfig(entry, options, pluginContext, dts);
|
|
1102
1106
|
const outputExports = getExportConditionDist(pkg, exportCondition, cwd);
|
|
1103
1107
|
let outputConfigs = [];
|
|
1104
1108
|
// Generate dts job - single config
|
|
1105
1109
|
if (dts) {
|
|
1106
1110
|
const typeOutputExports = getExportTypeDist(exportCondition, cwd);
|
|
1107
|
-
outputConfigs = typeOutputExports.map((typeFile)=>buildOutputConfigs(
|
|
1111
|
+
outputConfigs = typeOutputExports.map((typeFile)=>buildOutputConfigs({
|
|
1108
1112
|
...bundleConfig,
|
|
1109
1113
|
format: 'es',
|
|
1110
1114
|
useTypescript,
|
|
1111
1115
|
file: typeFile
|
|
1112
|
-
}, exportCondition,
|
|
1116
|
+
}, exportCondition, pluginContext, dts));
|
|
1113
1117
|
} else {
|
|
1114
1118
|
// multi outputs with specified format
|
|
1115
1119
|
outputConfigs = outputExports.map((exportDist)=>{
|
|
1116
|
-
return buildOutputConfigs(
|
|
1120
|
+
return buildOutputConfigs({
|
|
1117
1121
|
...bundleConfig,
|
|
1118
1122
|
file: exportDist.file,
|
|
1119
1123
|
format: exportDist.format,
|
|
1120
1124
|
useTypescript
|
|
1121
|
-
}, exportCondition,
|
|
1125
|
+
}, exportCondition, pluginContext, dts);
|
|
1122
1126
|
});
|
|
1123
1127
|
// CLI output option is always prioritized
|
|
1124
1128
|
if (file) {
|
|
1125
1129
|
var _outputExports_;
|
|
1126
1130
|
const fallbackFormat = (_outputExports_ = outputExports[0]) == null ? void 0 : _outputExports_.format;
|
|
1127
1131
|
outputConfigs = [
|
|
1128
|
-
buildOutputConfigs(
|
|
1132
|
+
buildOutputConfigs({
|
|
1129
1133
|
...bundleConfig,
|
|
1130
1134
|
file,
|
|
1131
1135
|
format: bundleConfig.format || fallbackFormat,
|
|
1132
1136
|
useTypescript
|
|
1133
|
-
}, exportCondition,
|
|
1137
|
+
}, exportCondition, pluginContext, dts)
|
|
1134
1138
|
];
|
|
1135
1139
|
}
|
|
1136
1140
|
}
|
|
@@ -1141,7 +1145,11 @@ async function buildConfig(entries, pkg, exportPaths, bundleConfig, exportCondit
|
|
|
1141
1145
|
};
|
|
1142
1146
|
}
|
|
1143
1147
|
|
|
1144
|
-
function
|
|
1148
|
+
function relativify(path) {
|
|
1149
|
+
return path.startsWith('.') ? path : `./${path}`;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
function createOutputState({ entries }) {
|
|
1145
1153
|
const sizeStats = new Map();
|
|
1146
1154
|
function addSize({ fileName, size, sourceFileName, exportPath }) {
|
|
1147
1155
|
if (!sizeStats.has(exportPath)) {
|
|
@@ -1157,8 +1165,8 @@ function createChunkSizeCollector({ entries }) {
|
|
|
1157
1165
|
}
|
|
1158
1166
|
}
|
|
1159
1167
|
const reversedMapping = new Map();
|
|
1160
|
-
Object.entries(entries).forEach(([, entry])=>{
|
|
1161
|
-
reversedMapping.set(entry.source,
|
|
1168
|
+
Object.entries(entries).forEach(([resolvedExportName, entry])=>{
|
|
1169
|
+
reversedMapping.set(entry.source, resolvedExportName);
|
|
1162
1170
|
});
|
|
1163
1171
|
return {
|
|
1164
1172
|
plugin: (cwd)=>{
|
|
@@ -1189,20 +1197,70 @@ function createChunkSizeCollector({ entries }) {
|
|
|
1189
1197
|
}
|
|
1190
1198
|
};
|
|
1191
1199
|
}
|
|
1192
|
-
function
|
|
1200
|
+
function isBin(filename) {
|
|
1201
|
+
return filename === 'bin' || filename.startsWith('bin/');
|
|
1202
|
+
}
|
|
1203
|
+
function isTypeFile(filename) {
|
|
1204
|
+
return filename.endsWith('.d.ts') || filename.endsWith('.d.mts') || filename.endsWith('.d.cts');
|
|
1205
|
+
}
|
|
1206
|
+
function normalizeExportName(exportName) {
|
|
1207
|
+
const isBinary = isBin(exportName);
|
|
1208
|
+
let result = exportName;
|
|
1209
|
+
const isSubpathExport = exportName.includes('/');
|
|
1210
|
+
const isSpecialExport = exportName.includes('.');
|
|
1211
|
+
if (isBinary) {
|
|
1212
|
+
result = (exportName.replace(/bin(\/|$)/, '') || '.') + ' (bin)';
|
|
1213
|
+
} else if (isSubpathExport || isSpecialExport) {
|
|
1214
|
+
const subExportName = exportName.split('/')[1] || exportName;
|
|
1215
|
+
if (subExportName.includes('.') && subExportName !== '.') {
|
|
1216
|
+
const [originExportName, specialCondition] = subExportName.split('.');
|
|
1217
|
+
result = (isSubpathExport ? relativify(originExportName) : '.') + ' (' + specialCondition + ')';
|
|
1218
|
+
} else {
|
|
1219
|
+
result = isSubpathExport ? relativify(subExportName) : '.';
|
|
1220
|
+
}
|
|
1221
|
+
} else {
|
|
1222
|
+
result = '.';
|
|
1223
|
+
}
|
|
1224
|
+
return result;
|
|
1225
|
+
}
|
|
1226
|
+
function getExportNameWithoutExportCondition(exportName) {
|
|
1227
|
+
return exportName.includes('.') ? exportName.split('.')[0] : exportName;
|
|
1228
|
+
}
|
|
1229
|
+
function logOutputState(sizeCollector) {
|
|
1193
1230
|
const stats = sizeCollector.getSizeStats();
|
|
1194
1231
|
const allFileNameLengths = Array.from(stats.values()).flat(1).map(([filename])=>filename.length);
|
|
1195
|
-
const
|
|
1196
|
-
[
|
|
1232
|
+
const maxFilenameLength = Math.max(...allFileNameLengths);
|
|
1233
|
+
const statsArray = [
|
|
1197
1234
|
...stats.entries()
|
|
1198
|
-
].sort(([a], [b])=>
|
|
1199
|
-
|
|
1235
|
+
].sort(([a], [b])=>{
|
|
1236
|
+
const comp = getExportNameWithoutExportCondition(a).length - getExportNameWithoutExportCondition(b).length;
|
|
1237
|
+
return comp === 0 ? a.localeCompare(b) : comp;
|
|
1238
|
+
});
|
|
1239
|
+
const maxLengthOfExportName = Math.max(...statsArray.map(([exportName])=>normalizeExportName(exportName).length));
|
|
1240
|
+
console.log(pc.underline('Exports'), ' '.repeat(Math.max(maxLengthOfExportName - 'Exports'.length, 0)), pc.underline('File'), ' '.repeat(Math.max(maxFilenameLength - 'File'.length, 0)), pc.underline('Size'));
|
|
1241
|
+
statsArray.forEach(([exportName, filesList])=>{
|
|
1242
|
+
// sort by file type, first js files then types, js/mjs/cjs are prioritized than .d.ts/.d.mts/.d.cts
|
|
1243
|
+
filesList.sort(([a], [b])=>{
|
|
1244
|
+
const aIsType = isTypeFile(a);
|
|
1245
|
+
const bIsType = isTypeFile(b);
|
|
1246
|
+
if (aIsType && bIsType) {
|
|
1247
|
+
return 0;
|
|
1248
|
+
}
|
|
1249
|
+
if (aIsType) {
|
|
1250
|
+
return 1;
|
|
1251
|
+
}
|
|
1252
|
+
if (bIsType) {
|
|
1253
|
+
return -1;
|
|
1254
|
+
}
|
|
1255
|
+
return 0;
|
|
1256
|
+
}).forEach((item, index)=>{
|
|
1200
1257
|
const [filename, , size] = item;
|
|
1201
|
-
const
|
|
1202
|
-
const
|
|
1203
|
-
const
|
|
1258
|
+
const normalizedExportName = normalizeExportName(exportName);
|
|
1259
|
+
const prefix = index === 0 ? normalizedExportName + ' '.repeat(maxLengthOfExportName - normalizedExportName.length) : ' '.repeat(maxLengthOfExportName);
|
|
1260
|
+
const sizePadding = ' '.repeat(maxFilenameLength - filename.length);
|
|
1204
1261
|
const prettiedSize = prettyBytes__default.default(size);
|
|
1205
|
-
|
|
1262
|
+
const isType = isTypeFile(filename);
|
|
1263
|
+
console.log(` ${prefix} ${pc[isType ? 'dim' : 'bold'](filename)}${sizePadding} ${prettiedSize}`);
|
|
1206
1264
|
});
|
|
1207
1265
|
});
|
|
1208
1266
|
}
|
|
@@ -1233,7 +1291,7 @@ async function getExportables(cwd, excludeKeys) {
|
|
|
1233
1291
|
function mapWildcard(wildcardExports, exportables) {
|
|
1234
1292
|
return exportables.map((exportable)=>{
|
|
1235
1293
|
const isFile = exportable.includes('.');
|
|
1236
|
-
const filename = isFile ?
|
|
1294
|
+
const filename = isFile ? filePathWithoutExtension(exportable) : exportable;
|
|
1237
1295
|
return {
|
|
1238
1296
|
[`./${filename}`]: Object.fromEntries(Object.entries(wildcardExports['./*']).map(([key, value])=>[
|
|
1239
1297
|
key,
|
|
@@ -1320,12 +1378,9 @@ async function bundle(entryPath, { cwd: _cwd, ...options } = {}) {
|
|
|
1320
1378
|
const { input, exportName } = rollupConfig;
|
|
1321
1379
|
const exportPath = getExportPath(pkg, cwd, exportName);
|
|
1322
1380
|
// Log original entry file relative path
|
|
1323
|
-
|
|
1324
|
-
const buildMetadata = {
|
|
1325
|
-
source
|
|
1326
|
-
};
|
|
1381
|
+
typeof input.input === 'string' ? path.relative(cwd, input.input) : exportPath;
|
|
1327
1382
|
if (options.watch) {
|
|
1328
|
-
return Promise.resolve(runWatch(rollupConfig
|
|
1383
|
+
return Promise.resolve(runWatch(rollupConfig));
|
|
1329
1384
|
}
|
|
1330
1385
|
return runBundle(rollupConfig);
|
|
1331
1386
|
};
|
|
@@ -1337,21 +1392,30 @@ async function bundle(entryPath, { cwd: _cwd, ...options } = {}) {
|
|
|
1337
1392
|
return Promise.reject(err);
|
|
1338
1393
|
}
|
|
1339
1394
|
const entries = await collectEntries(pkg, entryPath, exportPaths, cwd);
|
|
1340
|
-
const sizeCollector =
|
|
1395
|
+
const sizeCollector = createOutputState({
|
|
1341
1396
|
entries
|
|
1342
1397
|
});
|
|
1343
|
-
const
|
|
1344
|
-
|
|
1345
|
-
|
|
1398
|
+
const entriesAlias = getReversedAlias(entries);
|
|
1399
|
+
const buildContext = {
|
|
1400
|
+
entries,
|
|
1401
|
+
pkg,
|
|
1402
|
+
exportPaths,
|
|
1403
|
+
cwd,
|
|
1404
|
+
tsOptions: defaultTsOptions,
|
|
1405
|
+
pluginContext: {
|
|
1406
|
+
outputState: sizeCollector,
|
|
1407
|
+
moduleDirectiveLayerMap: new Map(),
|
|
1408
|
+
entriesAlias
|
|
1409
|
+
}
|
|
1346
1410
|
};
|
|
1347
|
-
const buildConfigs = await buildEntryConfig(
|
|
1411
|
+
const buildConfigs = await buildEntryConfig(options, buildContext, false);
|
|
1348
1412
|
const assetsJobs = buildConfigs.map((rollupConfig)=>bundleOrWatch(rollupConfig));
|
|
1349
|
-
const typesJobs = hasTsConfig ? (await buildEntryConfig(
|
|
1413
|
+
const typesJobs = hasTsConfig ? (await buildEntryConfig(options, buildContext, true)).map((rollupConfig)=>bundleOrWatch(rollupConfig)) : [];
|
|
1350
1414
|
const result = await Promise.all(assetsJobs.concat(typesJobs));
|
|
1351
1415
|
if (result.length === 0) {
|
|
1352
1416
|
logger.warn('The "src" directory does not contain any entry files. ' + 'For proper usage, please refer to the following link: ' + 'https://github.com/huozhi/bunchee#usage');
|
|
1353
1417
|
}
|
|
1354
|
-
|
|
1418
|
+
logOutputState(sizeCollector);
|
|
1355
1419
|
return result;
|
|
1356
1420
|
}
|
|
1357
1421
|
function runWatch({ input, output }, metadata) {
|
|
@@ -1375,7 +1439,6 @@ function runWatch({ input, output }, metadata) {
|
|
|
1375
1439
|
}
|
|
1376
1440
|
case 'START':
|
|
1377
1441
|
{
|
|
1378
|
-
logger.log(`Start building ${metadata.source} ...`);
|
|
1379
1442
|
break;
|
|
1380
1443
|
}
|
|
1381
1444
|
case 'END':
|