bunchee 4.2.11 → 4.3.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 +73 -55
- package/dist/bin/cli.js +255 -13
- package/dist/index.d.ts +17 -0
- package/dist/index.js +126 -65
- 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"
|
|
50
66
|
},
|
|
51
67
|
"scripts": {
|
|
52
68
|
"build": "bunchee"
|
|
53
69
|
}
|
|
54
70
|
}
|
|
55
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:
|
|
56
78
|
|
|
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
79
|
```json
|
|
59
80
|
{
|
|
60
|
-
"type": "module",
|
|
61
81
|
"files": ["dist"],
|
|
62
82
|
"exports": {
|
|
63
|
-
"import":
|
|
64
|
-
|
|
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
|
+
}
|
|
65
91
|
},
|
|
66
92
|
"scripts": {
|
|
67
93
|
"build": "bunchee"
|
|
68
94
|
}
|
|
69
95
|
}
|
|
70
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.
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"files": ["dist"],
|
|
107
|
+
"main": "./dist/cjs/index.cjs",
|
|
108
|
+
"module": "./dist/es/index.mjs",
|
|
109
|
+
"types": "./dist/cjs/index.d.ts",
|
|
110
|
+
"exports": {
|
|
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
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"scripts": {
|
|
121
|
+
"build": "bunchee"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
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.
|
|
@@ -78,6 +135,9 @@ The output format will based on the exports condition and also the file extensio
|
|
|
78
135
|
- It's CommonJS for `require` and ESM for `import` based on the exports condition.
|
|
79
136
|
- It's CommonJS for `.js` and ESM for `.mjs` based on the extension regardless the exports condition. Then for export condition like "node" you could choose the format with your extension.
|
|
80
137
|
|
|
138
|
+
> [!NOTE]
|
|
139
|
+
> All the `dependencies` and `peerDependencies` will be marked as external automatically and not included in the bundle. If you want to include them in the bundle, you can use the `--no-external` option.
|
|
140
|
+
|
|
81
141
|
## Usage
|
|
82
142
|
|
|
83
143
|
### File Conventions
|
|
@@ -122,28 +182,6 @@ Then you need to add two entry files `index.ts` and `lite.ts` in project root di
|
|
|
122
182
|
|
|
123
183
|
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
184
|
|
|
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
185
|
### Multiple Runtime
|
|
148
186
|
|
|
149
187
|
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.
|
|
@@ -242,13 +280,14 @@ bunchee ./src/index.js --runtime node --target es2019
|
|
|
242
280
|
|
|
243
281
|
#### Specifying extra external dependencies
|
|
244
282
|
|
|
245
|
-
|
|
283
|
+
By default, `bunchee` will mark all the `dependencies` and `peerDependencies` as externals so you don't need to pass them as CLI args.
|
|
284
|
+
But if there's any dependency that used but not in the dependency list and you want to mark as external, you can use the `--external` option to specify them.
|
|
246
285
|
|
|
247
286
|
```sh
|
|
248
|
-
bunchee --external=
|
|
287
|
+
bunchee --external=dep1,dep2,dep3
|
|
249
288
|
```
|
|
250
289
|
|
|
251
|
-
Replace `
|
|
290
|
+
Replace `dep1`, `dep2`, and `dep3` with the names of the dependencies you want to exclude from the bundle.
|
|
252
291
|
|
|
253
292
|
#### Bundling everything without external dependencies
|
|
254
293
|
|
|
@@ -322,7 +361,6 @@ This will match the export names `"foo"` and `"bar"` and will be treated as the
|
|
|
322
361
|
{
|
|
323
362
|
"exports": {
|
|
324
363
|
".": {
|
|
325
|
-
"types": "./dist/index.d.ts",
|
|
326
364
|
"import": "./dist/index.js"
|
|
327
365
|
},
|
|
328
366
|
"./foo": {
|
|
@@ -380,26 +418,6 @@ output
|
|
|
380
418
|
export default "hello world"
|
|
381
419
|
```
|
|
382
420
|
|
|
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
421
|
### Node.js API
|
|
404
422
|
|
|
405
423
|
```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,211 @@ 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.1";
|
|
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
|
+
let hasPackageJson = false;
|
|
271
|
+
const pkgJsonPath = path__default.default.join(cwd, 'package.json');
|
|
272
|
+
let pkgJson = {};
|
|
273
|
+
if (fs__default.default.existsSync(pkgJsonPath)) {
|
|
274
|
+
hasPackageJson = true;
|
|
275
|
+
const pkgJsonString = await fsp__default.default.readFile(pkgJsonPath, 'utf-8');
|
|
276
|
+
pkgJson = JSON.parse(pkgJsonString);
|
|
277
|
+
}
|
|
278
|
+
// configure `files` field with `dist`
|
|
279
|
+
const files = pkgJson.files || [];
|
|
280
|
+
if (!files.includes(DIST)) {
|
|
281
|
+
files.push(DIST);
|
|
282
|
+
}
|
|
283
|
+
pkgJson.files = files;
|
|
284
|
+
let isUsingTs = false;
|
|
285
|
+
// Collect bins and exports entries
|
|
286
|
+
const { bins, exportsEntries } = await collectSourceEntries(sourceFolder);
|
|
287
|
+
const tsconfigPath = path__default.default.join(cwd, 'tsconfig.json');
|
|
288
|
+
if (!fs__default.default.existsSync(tsconfigPath)) {
|
|
289
|
+
const sourceFiles = [
|
|
290
|
+
...exportsEntries.values()
|
|
291
|
+
].concat([
|
|
292
|
+
...bins.values()
|
|
293
|
+
]);
|
|
294
|
+
const hasTypeScriptFiles = sourceFiles.some((filename)=>isTypescriptFile(filename));
|
|
295
|
+
if (hasTypeScriptFiles) {
|
|
296
|
+
isUsingTs = true;
|
|
297
|
+
await fsp__default.default.writeFile(tsconfigPath, '{}', 'utf-8');
|
|
298
|
+
logger.log(`Detected using TypeScript but tsconfig.json is missing, created a ${pc.blue('tsconfig.json')} for you.`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// Configure as ESM package by default if there's no package.json
|
|
302
|
+
if (!hasPackageJson) {
|
|
303
|
+
pkgJson.type = 'module';
|
|
304
|
+
}
|
|
305
|
+
if (bins.size > 0) {
|
|
306
|
+
logger.log('Discovered binaries entries:');
|
|
307
|
+
const maxLengthOfBinName = Math.max(...Array.from(bins.keys()).map((binName)=>normalizeBaseNameToExportName(binName).length));
|
|
308
|
+
for (const [binName, binFile] of bins.entries()){
|
|
309
|
+
const spaces = ' '.repeat(Math.max(maxLengthOfBinName - normalizeBaseNameToExportName(binName).length, 0));
|
|
310
|
+
logger.log(` ${normalizeBaseNameToExportName(binName)}${spaces}: ${binFile}`);
|
|
311
|
+
}
|
|
312
|
+
if (bins.size === 1 && bins.has('.')) {
|
|
313
|
+
pkgJson.bin = getDistPath('bin', 'index.js');
|
|
314
|
+
} else {
|
|
315
|
+
pkgJson.bin = {};
|
|
316
|
+
for (const [binName] of bins.entries()){
|
|
317
|
+
pkgJson.bin[binName === '.' ? pkgJson.name : binName] = getDistPath('bin', binName + '.js');
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (exportsEntries.size > 0) {
|
|
322
|
+
logger.log('Discovered exports entries:');
|
|
323
|
+
const maxLengthOfExportName = Math.max(...Array.from(exportsEntries.keys()).map((exportName)=>normalizeBaseNameToExportName(exportName).length));
|
|
324
|
+
for (const [exportName, exportFile] of exportsEntries.entries()){
|
|
325
|
+
const spaces = ' '.repeat(Math.max(maxLengthOfExportName - normalizeBaseNameToExportName(exportName).length, 0));
|
|
326
|
+
logger.log(` ${normalizeBaseNameToExportName(exportName)}${spaces}: ${exportFile}`);
|
|
327
|
+
}
|
|
328
|
+
const pkgExports = {};
|
|
329
|
+
for (const [exportName, sourceFile] of exportsEntries.entries()){
|
|
330
|
+
const [key, value] = createExportConditionPair(exportName, sourceFile, pkgJson.type);
|
|
331
|
+
pkgExports[key] = {
|
|
332
|
+
...value,
|
|
333
|
+
...pkgExports[key]
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
// Configure node10 module resolution
|
|
337
|
+
if (exportsEntries.has('index')) {
|
|
338
|
+
const isESM = pkgJson.type === 'module';
|
|
339
|
+
const mainExport = pkgExports['.'];
|
|
340
|
+
const mainCondition = isESM ? 'import' : 'require';
|
|
341
|
+
pkgJson.main = isUsingTs ? mainExport[mainCondition].default : mainExport[mainCondition];
|
|
342
|
+
pkgJson.module = isUsingTs ? mainExport.import.default : mainExport.import;
|
|
343
|
+
if (isUsingTs) {
|
|
344
|
+
pkgJson.types = isESM ? mainExport.import.types : mainExport.require.types;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
// Assign the properties by order: files, main, module, types, exports
|
|
348
|
+
if (Object.keys(pkgExports).length > 0) {
|
|
349
|
+
pkgJson.exports = pkgExports;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
await fsp__default.default.writeFile(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
|
|
353
|
+
logger.info('Configured `exports` in package.json');
|
|
354
|
+
}
|
|
119
355
|
|
|
120
356
|
const helpMessage = `
|
|
121
357
|
Usage: bunchee [options]
|
|
@@ -127,6 +363,7 @@ Options:
|
|
|
127
363
|
-o, --output <file> specify output filename
|
|
128
364
|
-f, --format <format> type of output (esm, amd, cjs, iife, umd, system), default: esm
|
|
129
365
|
-h, --help output usage information
|
|
366
|
+
--prepare auto configure package.json exports for building
|
|
130
367
|
--external <mod> specify an external dependency, separate by comma
|
|
131
368
|
--no-external do not bundle external dependencies
|
|
132
369
|
--target <target> js features target: swc target es versions. default: es2015
|
|
@@ -172,6 +409,7 @@ function parseCliArgs(argv) {
|
|
|
172
409
|
'--env': String,
|
|
173
410
|
'--external': String,
|
|
174
411
|
'--no-external': Boolean,
|
|
412
|
+
'--prepare': Boolean,
|
|
175
413
|
'-h': '--help',
|
|
176
414
|
'-v': '--version',
|
|
177
415
|
'-w': '--watch',
|
|
@@ -197,7 +435,8 @@ function parseCliArgs(argv) {
|
|
|
197
435
|
runtime: args['--runtime'],
|
|
198
436
|
target: args['--target'],
|
|
199
437
|
external: !!args['--no-external'] ? null : args['--external'],
|
|
200
|
-
env: args['--env']
|
|
438
|
+
env: args['--env'],
|
|
439
|
+
prepare: !!args['--prepare']
|
|
201
440
|
};
|
|
202
441
|
return parsedArgs;
|
|
203
442
|
}
|
|
@@ -225,6 +464,9 @@ async function run(args) {
|
|
|
225
464
|
if (args.help) {
|
|
226
465
|
return help();
|
|
227
466
|
}
|
|
467
|
+
if (args.prepare) {
|
|
468
|
+
return await prepare(cwd);
|
|
469
|
+
}
|
|
228
470
|
const entry = source ? path__default.default.resolve(cwd, source) : '';
|
|
229
471
|
try {
|
|
230
472
|
await bunchee.bundle(entry, bundleConfig);
|
|
@@ -241,7 +483,7 @@ async function run(args) {
|
|
|
241
483
|
return;
|
|
242
484
|
}
|
|
243
485
|
// build mode
|
|
244
|
-
|
|
486
|
+
logger.log();
|
|
245
487
|
paint('✓', 'green', `bunchee ${version} build completed`);
|
|
246
488
|
await lintPackage(cwd);
|
|
247
489
|
}
|
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);
|
|
@@ -184,9 +180,11 @@ async function findSourceEntryFile(cwd, exportPath, exportTypeSuffix, ext) {
|
|
|
184
180
|
return filename;
|
|
185
181
|
}
|
|
186
182
|
const subFolderIndexFilename = resolveSourceFile(cwd, `${exportPath}/index${exportTypeSuffix ? `.${exportTypeSuffix}` : ''}.${ext}`);
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
183
|
+
try {
|
|
184
|
+
if (await fileExists(subFolderIndexFilename)) {
|
|
185
|
+
return subFolderIndexFilename;
|
|
186
|
+
}
|
|
187
|
+
} catch {}
|
|
190
188
|
return undefined;
|
|
191
189
|
}
|
|
192
190
|
// Map '.' -> './index.[ext]'
|
|
@@ -195,7 +193,7 @@ async function findSourceEntryFile(cwd, exportPath, exportTypeSuffix, ext) {
|
|
|
195
193
|
async function getSourcePathFromExportPath(cwd, exportPath, exportType) {
|
|
196
194
|
for (const ext of availableExtensions){
|
|
197
195
|
// ignore package.json
|
|
198
|
-
if (exportPath
|
|
196
|
+
if (exportPath === '/package.json') return;
|
|
199
197
|
if (exportPath === '.') exportPath = './index';
|
|
200
198
|
// Find convention-based source file for specific export types
|
|
201
199
|
// $binary represents `pkg.bin`
|
|
@@ -209,7 +207,7 @@ async function getSourcePathFromExportPath(cwd, exportPath, exportType) {
|
|
|
209
207
|
return;
|
|
210
208
|
}
|
|
211
209
|
// Unlike path.basename, forcedly removing extension
|
|
212
|
-
function
|
|
210
|
+
function filePathWithoutExtension(file) {
|
|
213
211
|
return file ? file.replace(new RegExp(`${path__default.default.extname(file)}$`), '') : undefined;
|
|
214
212
|
}
|
|
215
213
|
const nonNullable = (n)=>Boolean(n);
|
|
@@ -610,7 +608,7 @@ const getExportTypeDist = (parsedExportCondition, cwd)=>{
|
|
|
610
608
|
continue;
|
|
611
609
|
}
|
|
612
610
|
const ext = path.extname(filePath).slice(1);
|
|
613
|
-
const typeFile = getDistPath(`${
|
|
611
|
+
const typeFile = getDistPath(`${filePathWithoutExtension(filePath) || ''}.${dtsExtensionsMap[ext]}`, cwd);
|
|
614
612
|
if (existed.has(typeFile)) {
|
|
615
613
|
continue;
|
|
616
614
|
}
|
|
@@ -691,7 +689,7 @@ function getExportConditionDist(pkg, parsedExportCondition, cwd) {
|
|
|
691
689
|
return dist;
|
|
692
690
|
}
|
|
693
691
|
function getTypeFilePath(entryFilePath, exportCondition, cwd) {
|
|
694
|
-
const name =
|
|
692
|
+
const name = filePathWithoutExtension(entryFilePath);
|
|
695
693
|
const firstDistPath = exportCondition ? Object.values(exportCondition.export)[0] : undefined;
|
|
696
694
|
const exportName = (exportCondition == null ? void 0 : exportCondition.name) || 'index';
|
|
697
695
|
return entryFilePath ? name + '.d.ts' : path.resolve(firstDistPath ? path.dirname(firstDistPath) : path.join(cwd, 'dist'), (exportName === '.' ? 'index' : exportName) + '.d.ts');
|
|
@@ -739,7 +737,8 @@ function getBuildEnv(envs) {
|
|
|
739
737
|
}
|
|
740
738
|
return alias;
|
|
741
739
|
}
|
|
742
|
-
async function buildInputConfig(entry,
|
|
740
|
+
async function buildInputConfig(entry, options, buildContext, dts) {
|
|
741
|
+
const { entries, pkg, cwd, tsOptions: { tsConfigPath, tsCompilerOptions }, pluginContext } = buildContext;
|
|
743
742
|
const hasNoExternal = options.external === null;
|
|
744
743
|
var _options_external;
|
|
745
744
|
const externals = hasNoExternal ? [] : [
|
|
@@ -780,7 +779,7 @@ async function buildInputConfig(entry, entries, pkg, options, cwd, { tsConfigPat
|
|
|
780
779
|
inlineSourcesContent: false,
|
|
781
780
|
isModule: true
|
|
782
781
|
};
|
|
783
|
-
const sizePlugin = pluginContext.
|
|
782
|
+
const sizePlugin = pluginContext.outputState.plugin(cwd);
|
|
784
783
|
// common plugins for both dts and ts assets that need to be processed
|
|
785
784
|
const commonPlugins = [
|
|
786
785
|
sizePlugin,
|
|
@@ -962,14 +961,15 @@ function createSplitChunks(dependencyGraphMap, entryFiles) {
|
|
|
962
961
|
return;
|
|
963
962
|
};
|
|
964
963
|
}
|
|
965
|
-
function buildOutputConfigs(
|
|
964
|
+
function buildOutputConfigs(options, exportCondition, buildContext, dts) {
|
|
966
965
|
const { format } = options;
|
|
966
|
+
const { entries, pkg, exportPaths, cwd, tsOptions: { tsCompilerOptions }, pluginContext } = buildContext;
|
|
967
967
|
// Add esm mark and interop helper if esm export is detected
|
|
968
968
|
const useEsModuleMark = hasEsmExport(exportPaths, tsCompilerOptions);
|
|
969
969
|
const typings = getTypings(pkg);
|
|
970
970
|
const file = options.file && path.resolve(cwd, options.file);
|
|
971
971
|
const dtsDir = typings ? path.dirname(path.resolve(cwd, typings)) : path.resolve(cwd, 'dist');
|
|
972
|
-
const name =
|
|
972
|
+
const name = filePathWithoutExtension(file);
|
|
973
973
|
// TODO: simplify dts file name detection
|
|
974
974
|
const dtsFile = file ? file : exportCondition.export['types'] ? path.resolve(cwd, exportCondition.export['types']) : path.resolve(dtsDir, (exportCondition.name === '.' ? 'index' : exportCondition.name) + '.d.ts');
|
|
975
975
|
const dtsPathConfig = {
|
|
@@ -997,10 +997,11 @@ function buildOutputConfigs(entries, pkg, exportPaths, options, exportCondition,
|
|
|
997
997
|
entryFileNames: path.basename(outputFile)
|
|
998
998
|
};
|
|
999
999
|
}
|
|
1000
|
-
async function buildEntryConfig(
|
|
1000
|
+
async function buildEntryConfig(bundleConfig, pluginContext, dts) {
|
|
1001
1001
|
const configs = [];
|
|
1002
|
+
const { entries } = pluginContext;
|
|
1002
1003
|
for (const exportCondition of Object.values(entries)){
|
|
1003
|
-
const rollupConfig = buildConfig(
|
|
1004
|
+
const rollupConfig = buildConfig(bundleConfig, exportCondition, pluginContext, dts);
|
|
1004
1005
|
configs.push(rollupConfig);
|
|
1005
1006
|
}
|
|
1006
1007
|
return await Promise.all(configs);
|
|
@@ -1042,7 +1043,9 @@ async function buildEntryConfig(entries, pkg, exportPaths, bundleConfig, cwd, ts
|
|
|
1042
1043
|
name: entryExport,
|
|
1043
1044
|
export: exportCondForType
|
|
1044
1045
|
};
|
|
1045
|
-
const
|
|
1046
|
+
const nameWithExportPath = pkg.name ? path__default.default.join(pkg.name, exportCondition.name) : exportCondition.name;
|
|
1047
|
+
const needsDelimiter = !nameWithExportPath.endsWith('.') && exportType;
|
|
1048
|
+
const entryImportPath = nameWithExportPath + (needsDelimiter ? '.' : '') + exportType;
|
|
1046
1049
|
entries[entryImportPath] = exportCondition;
|
|
1047
1050
|
}
|
|
1048
1051
|
const binaryExports = pkg.bin;
|
|
@@ -1092,47 +1095,48 @@ async function buildEntryConfig(entries, pkg, exportPaths, bundleConfig, cwd, ts
|
|
|
1092
1095
|
await Promise.all(collectEntriesPromises);
|
|
1093
1096
|
return entries;
|
|
1094
1097
|
}
|
|
1095
|
-
async function buildConfig(
|
|
1098
|
+
async function buildConfig(bundleConfig, exportCondition, pluginContext, dts) {
|
|
1096
1099
|
const { file } = bundleConfig;
|
|
1100
|
+
const { pkg, cwd, tsOptions } = pluginContext;
|
|
1097
1101
|
const useTypescript = Boolean(tsOptions.tsConfigPath);
|
|
1098
1102
|
const options = {
|
|
1099
1103
|
...bundleConfig,
|
|
1100
1104
|
useTypescript
|
|
1101
1105
|
};
|
|
1102
1106
|
const entry = exportCondition.source;
|
|
1103
|
-
const inputOptions = await buildInputConfig(entry,
|
|
1107
|
+
const inputOptions = await buildInputConfig(entry, options, pluginContext, dts);
|
|
1104
1108
|
const outputExports = getExportConditionDist(pkg, exportCondition, cwd);
|
|
1105
1109
|
let outputConfigs = [];
|
|
1106
1110
|
// Generate dts job - single config
|
|
1107
1111
|
if (dts) {
|
|
1108
1112
|
const typeOutputExports = getExportTypeDist(exportCondition, cwd);
|
|
1109
|
-
outputConfigs = typeOutputExports.map((typeFile)=>buildOutputConfigs(
|
|
1113
|
+
outputConfigs = typeOutputExports.map((typeFile)=>buildOutputConfigs({
|
|
1110
1114
|
...bundleConfig,
|
|
1111
1115
|
format: 'es',
|
|
1112
1116
|
useTypescript,
|
|
1113
1117
|
file: typeFile
|
|
1114
|
-
}, exportCondition,
|
|
1118
|
+
}, exportCondition, pluginContext, dts));
|
|
1115
1119
|
} else {
|
|
1116
1120
|
// multi outputs with specified format
|
|
1117
1121
|
outputConfigs = outputExports.map((exportDist)=>{
|
|
1118
|
-
return buildOutputConfigs(
|
|
1122
|
+
return buildOutputConfigs({
|
|
1119
1123
|
...bundleConfig,
|
|
1120
1124
|
file: exportDist.file,
|
|
1121
1125
|
format: exportDist.format,
|
|
1122
1126
|
useTypescript
|
|
1123
|
-
}, exportCondition,
|
|
1127
|
+
}, exportCondition, pluginContext, dts);
|
|
1124
1128
|
});
|
|
1125
1129
|
// CLI output option is always prioritized
|
|
1126
1130
|
if (file) {
|
|
1127
1131
|
var _outputExports_;
|
|
1128
1132
|
const fallbackFormat = (_outputExports_ = outputExports[0]) == null ? void 0 : _outputExports_.format;
|
|
1129
1133
|
outputConfigs = [
|
|
1130
|
-
buildOutputConfigs(
|
|
1134
|
+
buildOutputConfigs({
|
|
1131
1135
|
...bundleConfig,
|
|
1132
1136
|
file,
|
|
1133
1137
|
format: bundleConfig.format || fallbackFormat,
|
|
1134
1138
|
useTypescript
|
|
1135
|
-
}, exportCondition,
|
|
1139
|
+
}, exportCondition, pluginContext, dts)
|
|
1136
1140
|
];
|
|
1137
1141
|
}
|
|
1138
1142
|
}
|
|
@@ -1143,7 +1147,11 @@ async function buildConfig(entries, pkg, exportPaths, bundleConfig, exportCondit
|
|
|
1143
1147
|
};
|
|
1144
1148
|
}
|
|
1145
1149
|
|
|
1146
|
-
function
|
|
1150
|
+
function relativify(path) {
|
|
1151
|
+
return path.startsWith('.') ? path : `./${path}`;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
function createOutputState({ entries }) {
|
|
1147
1155
|
const sizeStats = new Map();
|
|
1148
1156
|
function addSize({ fileName, size, sourceFileName, exportPath }) {
|
|
1149
1157
|
if (!sizeStats.has(exportPath)) {
|
|
@@ -1159,8 +1167,8 @@ function createChunkSizeCollector({ entries }) {
|
|
|
1159
1167
|
}
|
|
1160
1168
|
}
|
|
1161
1169
|
const reversedMapping = new Map();
|
|
1162
|
-
Object.entries(entries).forEach(([, entry])=>{
|
|
1163
|
-
reversedMapping.set(entry.source,
|
|
1170
|
+
Object.entries(entries).forEach(([resolvedExportName, entry])=>{
|
|
1171
|
+
reversedMapping.set(entry.source, resolvedExportName);
|
|
1164
1172
|
});
|
|
1165
1173
|
return {
|
|
1166
1174
|
plugin: (cwd)=>{
|
|
@@ -1191,20 +1199,70 @@ function createChunkSizeCollector({ entries }) {
|
|
|
1191
1199
|
}
|
|
1192
1200
|
};
|
|
1193
1201
|
}
|
|
1194
|
-
function
|
|
1202
|
+
function isBin(filename) {
|
|
1203
|
+
return filename === 'bin' || filename.startsWith('bin/');
|
|
1204
|
+
}
|
|
1205
|
+
function isTypeFile(filename) {
|
|
1206
|
+
return filename.endsWith('.d.ts') || filename.endsWith('.d.mts') || filename.endsWith('.d.cts');
|
|
1207
|
+
}
|
|
1208
|
+
function normalizeExportName(exportName) {
|
|
1209
|
+
const isBinary = isBin(exportName);
|
|
1210
|
+
let result = exportName;
|
|
1211
|
+
const isSubpathExport = exportName.includes('/');
|
|
1212
|
+
const isSpecialExport = exportName.includes('.');
|
|
1213
|
+
if (isBinary) {
|
|
1214
|
+
result = (exportName.replace(/bin(\/|$)/, '') || '.') + ' (bin)';
|
|
1215
|
+
} else if (isSubpathExport || isSpecialExport) {
|
|
1216
|
+
const subExportName = exportName.split('/')[1] || exportName;
|
|
1217
|
+
if (subExportName.includes('.') && subExportName !== '.') {
|
|
1218
|
+
const [originExportName, specialCondition] = subExportName.split('.');
|
|
1219
|
+
result = (isSubpathExport ? relativify(originExportName) : '.') + ' (' + specialCondition + ')';
|
|
1220
|
+
} else {
|
|
1221
|
+
result = isSubpathExport ? relativify(subExportName) : '.';
|
|
1222
|
+
}
|
|
1223
|
+
} else {
|
|
1224
|
+
result = '.';
|
|
1225
|
+
}
|
|
1226
|
+
return result;
|
|
1227
|
+
}
|
|
1228
|
+
function getExportNameWithoutExportCondition(exportName) {
|
|
1229
|
+
return exportName.includes('.') ? exportName.split('.')[0] : exportName;
|
|
1230
|
+
}
|
|
1231
|
+
function logOutputState(sizeCollector) {
|
|
1195
1232
|
const stats = sizeCollector.getSizeStats();
|
|
1196
1233
|
const allFileNameLengths = Array.from(stats.values()).flat(1).map(([filename])=>filename.length);
|
|
1197
|
-
const
|
|
1198
|
-
[
|
|
1234
|
+
const maxFilenameLength = Math.max(...allFileNameLengths);
|
|
1235
|
+
const statsArray = [
|
|
1199
1236
|
...stats.entries()
|
|
1200
|
-
].sort(([a], [b])=>
|
|
1201
|
-
|
|
1237
|
+
].sort(([a], [b])=>{
|
|
1238
|
+
const comp = getExportNameWithoutExportCondition(a).length - getExportNameWithoutExportCondition(b).length;
|
|
1239
|
+
return comp === 0 ? a.localeCompare(b) : comp;
|
|
1240
|
+
});
|
|
1241
|
+
const maxLengthOfExportName = Math.max(...statsArray.map(([exportName])=>normalizeExportName(exportName).length));
|
|
1242
|
+
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'));
|
|
1243
|
+
statsArray.forEach(([exportName, filesList])=>{
|
|
1244
|
+
// sort by file type, first js files then types, js/mjs/cjs are prioritized than .d.ts/.d.mts/.d.cts
|
|
1245
|
+
filesList.sort(([a], [b])=>{
|
|
1246
|
+
const aIsType = isTypeFile(a);
|
|
1247
|
+
const bIsType = isTypeFile(b);
|
|
1248
|
+
if (aIsType && bIsType) {
|
|
1249
|
+
return 0;
|
|
1250
|
+
}
|
|
1251
|
+
if (aIsType) {
|
|
1252
|
+
return 1;
|
|
1253
|
+
}
|
|
1254
|
+
if (bIsType) {
|
|
1255
|
+
return -1;
|
|
1256
|
+
}
|
|
1257
|
+
return 0;
|
|
1258
|
+
}).forEach((item, index)=>{
|
|
1202
1259
|
const [filename, , size] = item;
|
|
1203
|
-
const
|
|
1204
|
-
const
|
|
1205
|
-
const
|
|
1260
|
+
const normalizedExportName = normalizeExportName(exportName);
|
|
1261
|
+
const prefix = index === 0 ? normalizedExportName + ' '.repeat(maxLengthOfExportName - normalizedExportName.length) : ' '.repeat(maxLengthOfExportName);
|
|
1262
|
+
const sizePadding = ' '.repeat(maxFilenameLength - filename.length);
|
|
1206
1263
|
const prettiedSize = prettyBytes__default.default(size);
|
|
1207
|
-
|
|
1264
|
+
const isType = isTypeFile(filename);
|
|
1265
|
+
console.log(` ${prefix} ${pc[isType ? 'dim' : 'bold'](filename)}${sizePadding} ${prettiedSize}`);
|
|
1208
1266
|
});
|
|
1209
1267
|
});
|
|
1210
1268
|
}
|
|
@@ -1235,7 +1293,7 @@ async function getExportables(cwd, excludeKeys) {
|
|
|
1235
1293
|
function mapWildcard(wildcardExports, exportables) {
|
|
1236
1294
|
return exportables.map((exportable)=>{
|
|
1237
1295
|
const isFile = exportable.includes('.');
|
|
1238
|
-
const filename = isFile ?
|
|
1296
|
+
const filename = isFile ? filePathWithoutExtension(exportable) : exportable;
|
|
1239
1297
|
return {
|
|
1240
1298
|
[`./${filename}`]: Object.fromEntries(Object.entries(wildcardExports['./*']).map(([key, value])=>[
|
|
1241
1299
|
key,
|
|
@@ -1322,12 +1380,9 @@ async function bundle(entryPath, { cwd: _cwd, ...options } = {}) {
|
|
|
1322
1380
|
const { input, exportName } = rollupConfig;
|
|
1323
1381
|
const exportPath = getExportPath(pkg, cwd, exportName);
|
|
1324
1382
|
// Log original entry file relative path
|
|
1325
|
-
|
|
1326
|
-
const buildMetadata = {
|
|
1327
|
-
source
|
|
1328
|
-
};
|
|
1383
|
+
typeof input.input === 'string' ? path.relative(cwd, input.input) : exportPath;
|
|
1329
1384
|
if (options.watch) {
|
|
1330
|
-
return Promise.resolve(runWatch(rollupConfig
|
|
1385
|
+
return Promise.resolve(runWatch(rollupConfig));
|
|
1331
1386
|
}
|
|
1332
1387
|
return runBundle(rollupConfig);
|
|
1333
1388
|
};
|
|
@@ -1339,23 +1394,30 @@ async function bundle(entryPath, { cwd: _cwd, ...options } = {}) {
|
|
|
1339
1394
|
return Promise.reject(err);
|
|
1340
1395
|
}
|
|
1341
1396
|
const entries = await collectEntries(pkg, entryPath, exportPaths, cwd);
|
|
1342
|
-
const sizeCollector =
|
|
1397
|
+
const sizeCollector = createOutputState({
|
|
1343
1398
|
entries
|
|
1344
1399
|
});
|
|
1345
1400
|
const entriesAlias = getReversedAlias(entries);
|
|
1346
|
-
const
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1401
|
+
const buildContext = {
|
|
1402
|
+
entries,
|
|
1403
|
+
pkg,
|
|
1404
|
+
exportPaths,
|
|
1405
|
+
cwd,
|
|
1406
|
+
tsOptions: defaultTsOptions,
|
|
1407
|
+
pluginContext: {
|
|
1408
|
+
outputState: sizeCollector,
|
|
1409
|
+
moduleDirectiveLayerMap: new Map(),
|
|
1410
|
+
entriesAlias
|
|
1411
|
+
}
|
|
1350
1412
|
};
|
|
1351
|
-
const buildConfigs = await buildEntryConfig(
|
|
1413
|
+
const buildConfigs = await buildEntryConfig(options, buildContext, false);
|
|
1352
1414
|
const assetsJobs = buildConfigs.map((rollupConfig)=>bundleOrWatch(rollupConfig));
|
|
1353
|
-
const typesJobs = hasTsConfig ? (await buildEntryConfig(
|
|
1415
|
+
const typesJobs = hasTsConfig ? (await buildEntryConfig(options, buildContext, true)).map((rollupConfig)=>bundleOrWatch(rollupConfig)) : [];
|
|
1354
1416
|
const result = await Promise.all(assetsJobs.concat(typesJobs));
|
|
1355
1417
|
if (result.length === 0) {
|
|
1356
1418
|
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');
|
|
1357
1419
|
}
|
|
1358
|
-
|
|
1420
|
+
logOutputState(sizeCollector);
|
|
1359
1421
|
return result;
|
|
1360
1422
|
}
|
|
1361
1423
|
function runWatch({ input, output }, metadata) {
|
|
@@ -1379,7 +1441,6 @@ function runWatch({ input, output }, metadata) {
|
|
|
1379
1441
|
}
|
|
1380
1442
|
case 'START':
|
|
1381
1443
|
{
|
|
1382
|
-
logger.log(`Start building ${metadata.source} ...`);
|
|
1383
1444
|
break;
|
|
1384
1445
|
}
|
|
1385
1446
|
case 'END':
|