bunchee 3.0.0 → 3.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  # bunchee
2
2
  > zero config bundler for JavaScript/TypeScript/JSX library
3
3
 
4
- ![bunchee](https://user-images.githubusercontent.com/4800338/98430015-7ce64f00-20e5-11eb-8c64-41addfbd4ede.png)
4
+ ![bunchee](https://repository-images.githubusercontent.com/154026156/5d132698-0ff5-4644-a4fd-d9570e6229bc)
5
5
 
6
6
  <p align="left">
7
7
  <a href="https://npm.im/bunchee">
@@ -76,7 +76,7 @@ Then just run `npm run build`, or `pnpm build` / `yarn build` if you're using th
76
76
  - Runtime (`--runtime <runtime>`): Set build runtime (default: `'browser'`).
77
77
  - Environment (`--env <env,>`): Define environment variables. (default: `NODE_ENV`, separate by comma)
78
78
  - Working Directory (`--cwd <cwd>`): Set current working directory where containing `package.json`.
79
- - Types only (`--dts`): Generate TypeScript declaration files without assets.
79
+ - Types (`--dts`): Generate TypeScript declaration files along with assets.
80
80
  - Minify (`-m`): Compress output.
81
81
  - Watch (`-w`): Watch for source file changes.
82
82
 
@@ -124,7 +124,7 @@ Replace `ENV1`, `ENV2`, and `ENV3` with the names of the environment variables y
124
124
 
125
125
  ### Entry Files Convention
126
126
 
127
- While `exports` filed is becoming the standard of exporting in node.js, bunchee also supports to build multiple exports all in one command.
127
+ While `exports` field is becoming the standard of exporting in node.js, bunchee also supports to build multiple exports all in one command.
128
128
 
129
129
  What you need to do is just add an entry file with the name (`[name].[ext]`) that matches the exported name from exports field in package.json. For instance:
130
130
 
package/dist/cli.js CHANGED
@@ -37,6 +37,15 @@ function exit(err) {
37
37
  process.exit(1);
38
38
  }
39
39
  const formatDuration = (duration)=>duration >= 1000 ? `${duration / 1000}s` : `${duration}ms`;
40
+ function hasPackageJson(cwd) {
41
+ return _hasPackageJson.apply(this, arguments);
42
+ }
43
+ function _hasPackageJson() {
44
+ _hasPackageJson = _async_to_generator$1(function*(cwd) {
45
+ return yield fileExists(path.resolve(cwd, 'package.json'));
46
+ });
47
+ return _hasPackageJson.apply(this, arguments);
48
+ }
40
49
  function getPackageMeta(cwd) {
41
50
  return _getPackageMeta.apply(this, arguments);
42
51
  }
@@ -64,8 +73,25 @@ const logger = {
64
73
  console.error('\x1b[31m' + arg + '\x1b[0m');
65
74
  }
66
75
  };
76
+ function fileExists(filePath) {
77
+ return _fileExists.apply(this, arguments);
78
+ }
79
+ function _fileExists() {
80
+ _fileExists = _async_to_generator$1(function*(filePath) {
81
+ try {
82
+ yield fs.access(filePath);
83
+ return true;
84
+ } catch (err) {
85
+ if (err.code === 'ENOENT') {
86
+ return false;
87
+ }
88
+ throw err;
89
+ }
90
+ });
91
+ return _fileExists.apply(this, arguments);
92
+ }
67
93
 
68
- var version = "3.0.0";
94
+ var version = "3.1.0";
69
95
 
70
96
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
71
97
  try {
@@ -123,6 +149,10 @@ function lintPackage(cwd) {
123
149
  }
124
150
  function _lintPackage() {
125
151
  _lintPackage = _async_to_generator(function*(cwd) {
152
+ // Not package.json detected, skip package linting
153
+ if (!(yield hasPackageJson(cwd))) {
154
+ return;
155
+ }
126
156
  const { publint } = yield import('publint');
127
157
  const { printMessage } = yield import('publint/utils');
128
158
  const messages = yield publint({
package/dist/index.d.ts CHANGED
@@ -23,6 +23,6 @@ type BundleConfig = {
23
23
  };
24
24
  type ExportCondition = string | Record<ExportType, string>;
25
25
 
26
- declare function bundle(entryPath: string, { cwd, ...options }?: BundleConfig): Promise<any>;
26
+ declare function bundle(entryPath: string, { cwd: _cwd, ...options }?: BundleConfig): Promise<any>;
27
27
 
28
28
  export { BundleConfig, bundle };
package/dist/index.js CHANGED
@@ -3,25 +3,57 @@ Object.defineProperty(exports, '__esModule', { value: true });
3
3
  var fs = require('fs/promises');
4
4
  var path = require('path');
5
5
  var rollup = require('rollup');
6
- var fs$1 = require('fs');
7
- var module$1 = require('module');
8
6
  var rollupPluginSwc3 = require('rollup-plugin-swc3');
9
7
  var commonjs = require('@rollup/plugin-commonjs');
10
8
  var shebang = require('rollup-plugin-preserve-shebang');
11
9
  var json = require('@rollup/plugin-json');
12
10
  var pluginNodeResolve = require('@rollup/plugin-node-resolve');
13
11
  var replace = require('@rollup/plugin-replace');
12
+ var prettyBytes = require('pretty-bytes');
13
+ var module$1 = require('module');
14
14
 
15
- const rootDir = process.cwd();
16
- var config = {
17
- rootDir
18
- };
15
+ function chunkSizeCollector() {
16
+ const sizes = new Map();
17
+ function addSize(name, size) {
18
+ sizes.set(name, size);
19
+ }
20
+ return {
21
+ plugin: (cwd)=>{
22
+ return {
23
+ name: 'collect-sizes',
24
+ augmentChunkHash () {
25
+ // Do nothing, but use the hook to keep the plugin instance alive
26
+ },
27
+ renderChunk (code, chunk, options) {
28
+ const dir = options.dir || options.file && path.dirname(options.file);
29
+ let fileName = chunk.fileName;
30
+ if (dir) {
31
+ fileName = path.relative(cwd, path.join(dir, fileName));
32
+ }
33
+ addSize(fileName, code.length);
34
+ return null;
35
+ }
36
+ };
37
+ },
38
+ getSizeStats () {
39
+ const sizeStats = [];
40
+ sizes.forEach((size, name)=>{
41
+ sizeStats.push([
42
+ name,
43
+ prettyBytes(size),
44
+ size
45
+ ]);
46
+ });
47
+ return sizeStats;
48
+ }
49
+ };
50
+ }
19
51
 
20
52
  function getTypings(pkg) {
21
53
  return pkg.types || pkg.typings;
22
54
  }
23
- function getDistPath(distPath) {
24
- return path.resolve(config.rootDir, distPath);
55
+ function getDistPath(distPath, cwd) {
56
+ return path.resolve(cwd, distPath);
25
57
  }
26
58
  function findExport(field) {
27
59
  if (!field) return;
@@ -68,67 +100,64 @@ function getExportPaths(pkg) {
68
100
  pathsMap['.'] = mainExport;
69
101
  return pathsMap;
70
102
  }
71
- function getExportDist(pkg) {
103
+ function getExportDist(pkg, cwd) {
72
104
  const paths = getExportPaths(pkg)['.'];
73
105
  const dist = [];
74
106
  if (paths.main) {
75
107
  dist.push({
76
108
  format: 'cjs',
77
- file: getDistPath(paths.main)
109
+ file: getDistPath(paths.main, cwd)
78
110
  });
79
111
  }
80
112
  if (paths.module) {
81
113
  dist.push({
82
114
  format: 'esm',
83
- file: getDistPath(paths.module)
115
+ file: getDistPath(paths.module, cwd)
84
116
  });
85
117
  }
86
118
  if (paths.export) {
87
119
  dist.push({
88
120
  format: 'esm',
89
- file: getDistPath(paths.export)
121
+ file: getDistPath(paths.export, cwd)
90
122
  });
91
123
  }
92
124
  // default fallback to output `dist/index.js` in default esm format
93
125
  if (dist.length === 0) {
94
126
  dist.push({
95
127
  format: 'esm',
96
- file: getDistPath('dist/index.js')
128
+ file: getDistPath('dist/index.js', cwd)
97
129
  });
98
130
  }
99
131
  return dist;
100
132
  }
101
- function getExportConditionDist(pkg, exportCondition) {
102
- // const pkgExports = pkg.exports || {}
133
+ function getExportConditionDist(pkg, exportCondition, cwd) {
103
134
  const dist = [];
104
135
  // "exports": "..."
105
136
  if (typeof exportCondition === 'string') {
106
137
  dist.push({
107
138
  format: pkg.type === 'module' ? 'esm' : 'cjs',
108
- file: getDistPath(exportCondition)
139
+ file: getDistPath(exportCondition, cwd)
109
140
  });
110
141
  } else {
111
142
  // "./<subexport>": { }
112
- const subExports = exportCondition // pkgExports[subExport]
113
- ;
143
+ const subExports = exportCondition;
114
144
  // Ignore json exports, like "./package.json"
115
- // if (subExport.endsWith('.json')) return dist
116
145
  if (typeof subExports === 'string') {
117
146
  dist.push({
118
147
  format: 'esm',
119
- file: getDistPath(subExports)
148
+ file: getDistPath(subExports, cwd)
120
149
  });
121
150
  } else {
122
151
  if (subExports.require) {
123
152
  dist.push({
124
153
  format: 'cjs',
125
- file: getDistPath(subExports.require)
154
+ file: getDistPath(subExports.require, cwd)
126
155
  });
127
156
  }
128
157
  if (subExports.import) {
129
158
  dist.push({
130
159
  format: 'esm',
131
- file: getDistPath(subExports.import)
160
+ file: getDistPath(subExports.import, cwd)
132
161
  });
133
162
  }
134
163
  }
@@ -136,7 +165,7 @@ function getExportConditionDist(pkg, exportCondition) {
136
165
  return dist;
137
166
  }
138
167
 
139
- function asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, key, arg) {
168
+ function asyncGeneratorStep$3(gen, resolve, reject, _next, _throw, key, arg) {
140
169
  try {
141
170
  var info = gen[key](arg);
142
171
  var value = info.value;
@@ -150,16 +179,16 @@ function asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, key, arg) {
150
179
  Promise.resolve(value).then(_next, _throw);
151
180
  }
152
181
  }
153
- function _async_to_generator$1(fn) {
182
+ function _async_to_generator$3(fn) {
154
183
  return function() {
155
184
  var self = this, args = arguments;
156
185
  return new Promise(function(resolve, reject) {
157
186
  var gen = fn.apply(self, args);
158
187
  function _next(value) {
159
- asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "next", value);
188
+ asyncGeneratorStep$3(gen, resolve, reject, _next, _throw, "next", value);
160
189
  }
161
190
  function _throw(err) {
162
- asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "throw", err);
191
+ asyncGeneratorStep$3(gen, resolve, reject, _next, _throw, "throw", err);
163
192
  }
164
193
  _next(undefined);
165
194
  });
@@ -169,12 +198,11 @@ function exit(err) {
169
198
  logger.error(err);
170
199
  process.exit(1);
171
200
  }
172
- const formatDuration = (duration)=>duration >= 1000 ? `${duration / 1000}s` : `${duration}ms`;
173
201
  function getPackageMeta(cwd) {
174
202
  return _getPackageMeta.apply(this, arguments);
175
203
  }
176
204
  function _getPackageMeta() {
177
- _getPackageMeta = _async_to_generator$1(function*(cwd) {
205
+ _getPackageMeta = _async_to_generator$3(function*(cwd) {
178
206
  const pkgFilePath = path.resolve(cwd, 'package.json');
179
207
  let targetPackageJson = {};
180
208
  try {
@@ -197,15 +225,11 @@ const logger = {
197
225
  console.error('\x1b[31m' + arg + '\x1b[0m');
198
226
  }
199
227
  };
200
- function isTypescript(filename) {
201
- const ext = path.extname(filename);
202
- return ext === '.ts' || ext === '.tsx';
203
- }
204
228
  function fileExists(filePath) {
205
229
  return _fileExists.apply(this, arguments);
206
230
  }
207
231
  function _fileExists() {
208
- _fileExists = _async_to_generator$1(function*(filePath) {
232
+ _fileExists = _async_to_generator$3(function*(filePath) {
209
233
  try {
210
234
  yield fs.access(filePath);
211
235
  return true;
@@ -218,8 +242,78 @@ function _fileExists() {
218
242
  });
219
243
  return _fileExists.apply(this, arguments);
220
244
  }
245
+ // . -> pkg name
246
+ // ./lite -> <pkg name>/lite
247
+ function getExportPath(pkg, cwd, exportName) {
248
+ const name = pkg.name || path.basename(cwd);
249
+ if (exportName === '.' || !exportName) return name;
250
+ return path.join(name, exportName);
251
+ }
221
252
  const isNotNull = (n)=>Boolean(n);
253
+ const SRC = 'src' // resolve from src/ directory
254
+ ;
255
+ function resolveSourceFile(cwd, filename) {
256
+ return path.resolve(cwd, SRC, filename);
257
+ }
258
+ // Map '.' -> './index.[ext]'
259
+ // Map './lite' -> './lite.[ext]'
260
+ // Return undefined if no match or if it's package.json exports
261
+ function getSourcePathFromExportPath(cwd, exportPath) {
262
+ return _getSourcePathFromExportPath.apply(this, arguments);
263
+ }
264
+ function _getSourcePathFromExportPath() {
265
+ _getSourcePathFromExportPath = _async_to_generator$3(function*(cwd, exportPath) {
266
+ const exts = [
267
+ 'js',
268
+ 'cjs',
269
+ 'mjs',
270
+ 'jsx',
271
+ 'ts',
272
+ 'tsx'
273
+ ];
274
+ for (const ext of exts){
275
+ // ignore package.json
276
+ if (exportPath.endsWith('package.json')) return;
277
+ if (exportPath === '.') exportPath = './index';
278
+ const filename = resolveSourceFile(cwd, `${exportPath}.${ext}`);
279
+ if (yield fileExists(filename)) {
280
+ return filename;
281
+ }
282
+ }
283
+ return;
284
+ });
285
+ return _getSourcePathFromExportPath.apply(this, arguments);
286
+ }
222
287
 
288
+ function asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, key, arg) {
289
+ try {
290
+ var info = gen[key](arg);
291
+ var value = info.value;
292
+ } catch (error) {
293
+ reject(error);
294
+ return;
295
+ }
296
+ if (info.done) {
297
+ resolve(value);
298
+ } else {
299
+ Promise.resolve(value).then(_next, _throw);
300
+ }
301
+ }
302
+ function _async_to_generator$2(fn) {
303
+ return function() {
304
+ var self = this, args = arguments;
305
+ return new Promise(function(resolve, reject) {
306
+ var gen = fn.apply(self, args);
307
+ function _next(value) {
308
+ asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, "next", value);
309
+ }
310
+ function _throw(err) {
311
+ asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, "throw", err);
312
+ }
313
+ _next(undefined);
314
+ });
315
+ };
316
+ }
223
317
  function _extends$1() {
224
318
  _extends$1 = Object.assign || function(target) {
225
319
  for(var i = 1; i < arguments.length; i++){
@@ -245,22 +339,8 @@ const minifyOptions = {
245
339
  toplevel: true
246
340
  }
247
341
  };
248
- let hasLoggedTsWarning = false;
249
- function resolveTypescript(cwd) {
250
- let ts;
251
- const m = new module$1.Module('', undefined);
252
- m.paths = module$1.Module._nodeModulePaths(cwd);
253
- try {
254
- ts = m.require('typescript');
255
- } catch (_) {
256
- console.error(_);
257
- if (!hasLoggedTsWarning) {
258
- hasLoggedTsWarning = true;
259
- exit('Could not load TypeScript compiler. Try to install `typescript` as dev dependency');
260
- }
261
- }
262
- return ts;
263
- }
342
+ // This can also be passed down as stats from top level
343
+ const sizeCollector = chunkSizeCollector();
264
344
  function getBuildEnv(envs) {
265
345
  if (!envs.includes('NODE_ENV')) {
266
346
  envs.push('NODE_ENV');
@@ -274,7 +354,7 @@ function getBuildEnv(envs) {
274
354
  }, {});
275
355
  return envVars;
276
356
  }
277
- function buildInputConfig(entry, pkg, options, { tsConfigPath , tsCompilerOptions , dtsOnly }) {
357
+ function buildInputConfig(entry, pkg, options, cwd, { tsConfigPath , tsCompilerOptions }, dtsOnly) {
278
358
  var _options_external;
279
359
  const externals = options.noExternal ? [] : [
280
360
  pkg.peerDependencies,
@@ -285,8 +365,13 @@ function buildInputConfig(entry, pkg, options, { tsConfigPath , tsCompilerOption
285
365
  ] : []));
286
366
  const { useTypescript , runtime , target: jscTarget , minify } = options;
287
367
  const hasSpecifiedTsTarget = Boolean((tsCompilerOptions == null ? void 0 : tsCompilerOptions.target) && tsConfigPath);
288
- const plugins = (dtsOnly ? [
368
+ const sizePlugin = sizeCollector.plugin(cwd);
369
+ const commonPlugins = [
289
370
  shebang(),
371
+ sizePlugin
372
+ ];
373
+ const plugins = (dtsOnly ? [
374
+ ...commonPlugins,
290
375
  useTypescript && require('rollup-plugin-dts').default({
291
376
  compilerOptions: _extends$1({}, tsCompilerOptions, {
292
377
  declaration: true,
@@ -304,6 +389,7 @@ function buildInputConfig(entry, pkg, options, { tsConfigPath , tsCompilerOption
304
389
  })
305
390
  })
306
391
  ] : [
392
+ ...commonPlugins,
307
393
  replace({
308
394
  values: getBuildEnv(options.env || []),
309
395
  preventAssignment: true
@@ -322,7 +408,6 @@ function buildInputConfig(entry, pkg, options, { tsConfigPath , tsCompilerOption
322
408
  include: /node_modules\//
323
409
  }),
324
410
  json(),
325
- shebang(),
326
411
  rollupPluginSwc3.swc({
327
412
  include: /\.(m|c)?[jt]sx?$/,
328
413
  exclude: 'node_modules',
@@ -375,20 +460,19 @@ function buildInputConfig(entry, pkg, options, { tsConfigPath , tsCompilerOption
375
460
  }
376
461
  };
377
462
  }
378
- function buildOutputConfigs(options, pkg, { tsCompilerOptions , dtsOnly }) {
463
+ function buildOutputConfigs(pkg, options, cwd, { tsCompilerOptions }, dtsOnly) {
379
464
  const { format , exportCondition } = options;
380
465
  const exportPaths = getExportPaths(pkg);
381
466
  // respect if tsconfig.json has `esModuleInterop` config;
382
467
  // add ESModule mark if cjs and ESModule are both generated;
383
- // TODO: support `import` in exportCondition
384
468
  const mainExport = exportPaths['.'];
385
469
  const useEsModuleMark = Boolean(tsCompilerOptions.esModuleInterop || mainExport.main && mainExport.module);
386
470
  const typings = getTypings(pkg);
387
- const file = options.file && path.resolve(config.rootDir, options.file);
388
- const dtsDir = typings ? path.dirname(path.resolve(config.rootDir, typings)) : path.resolve(config.rootDir, 'dist');
471
+ const file = options.file && path.resolve(cwd, options.file);
472
+ const dtsDir = typings ? path.dirname(path.resolve(cwd, typings)) : path.resolve(cwd, 'dist');
389
473
  // file base name without extension
390
474
  const name = file ? file.replace(new RegExp(`${path.extname(file)}$`), '') : undefined;
391
- const dtsFile = file ? name + '.d.ts' : (exportCondition == null ? void 0 : exportCondition.name) ? path.resolve(dtsDir, (exportCondition.name === '.' ? 'index' : exportCondition.name) + '.d.ts') : typings && path.resolve(config.rootDir, typings);
475
+ const dtsFile = file ? name + '.d.ts' : (exportCondition == null ? void 0 : exportCondition.name) ? path.resolve(dtsDir, (exportCondition.name === '.' ? 'index' : exportCondition.name) + '.d.ts') : typings && path.resolve(cwd, typings);
392
476
  // If there's dts file, use `output.file`
393
477
  const dtsPathConfig = dtsFile ? {
394
478
  file: dtsFile
@@ -408,73 +492,157 @@ function buildOutputConfigs(options, pkg, { tsCompilerOptions , dtsOnly }) {
408
492
  sourcemap: options.sourcemap
409
493
  });
410
494
  }
411
- function buildConfig(entry, pkg, bundleConfig, dtsOnly) {
495
+ // build configs for each entry from package exports
496
+ function buildEntryConfig(pkg, bundleConfig, cwd, tsOptions, dtsOnly) {
497
+ return _buildEntryConfig.apply(this, arguments);
498
+ }
499
+ function _buildEntryConfig() {
500
+ _buildEntryConfig = _async_to_generator$2(function*(pkg, bundleConfig, cwd, tsOptions, dtsOnly) {
501
+ const packageExports = pkg.exports || {};
502
+ const configs = Object.keys(packageExports).map(/*#__PURE__*/ _async_to_generator$2(function*(entryExport) {
503
+ const source = yield getSourcePathFromExportPath(cwd, entryExport);
504
+ if (!source) return undefined;
505
+ if (dtsOnly && !(tsOptions == null ? void 0 : tsOptions.tsConfigPath)) return;
506
+ bundleConfig.exportCondition = {
507
+ source,
508
+ name: entryExport,
509
+ export: packageExports[entryExport]
510
+ };
511
+ const entry = resolveSourceFile(cwd, source);
512
+ const rollupConfig = buildConfig(entry, pkg, bundleConfig, cwd, tsOptions, dtsOnly);
513
+ return rollupConfig;
514
+ }));
515
+ return (yield Promise.all(configs)).filter((n)=>Boolean(n));
516
+ });
517
+ return _buildEntryConfig.apply(this, arguments);
518
+ }
519
+ function buildConfig(entry, pkg, bundleConfig, cwd, tsOptions, dtsOnly) {
412
520
  var _options_exportCondition;
413
521
  const { file } = bundleConfig;
414
- const useTypescript = isTypescript(entry);
522
+ const useTypescript = Boolean(tsOptions.tsConfigPath);
415
523
  const options = _extends$1({}, bundleConfig, {
416
524
  useTypescript
417
525
  });
418
- let tsCompilerOptions = {};
419
- let tsConfigPath;
420
- if (useTypescript) {
421
- const ts = resolveTypescript(config.rootDir);
422
- tsConfigPath = path.resolve(config.rootDir, 'tsconfig.json');
423
- if (fs$1.existsSync(tsConfigPath)) {
424
- const basePath = tsConfigPath ? path.dirname(tsConfigPath) : config.rootDir;
425
- const tsconfigJSON = ts.readConfigFile(tsConfigPath, ts.sys.readFile).config;
426
- tsCompilerOptions = ts.parseJsonConfigFileContent(tsconfigJSON, ts.sys, basePath).options;
427
- } else {
428
- tsConfigPath = undefined;
429
- exit('tsconfig.json is missing in your project directory');
430
- }
431
- }
432
- const typescriptOptions = {
433
- dtsOnly,
434
- tsConfigPath,
435
- tsCompilerOptions
436
- };
437
- const inputOptions = buildInputConfig(entry, pkg, options, typescriptOptions);
438
- const outputExports = options.exportCondition ? getExportConditionDist(pkg, options.exportCondition.export) : getExportDist(pkg);
526
+ const inputOptions = buildInputConfig(entry, pkg, options, cwd, tsOptions, dtsOnly);
527
+ const outputExports = options.exportCondition ? getExportConditionDist(pkg, options.exportCondition.export, cwd) : getExportDist(pkg, cwd);
439
528
  let outputConfigs = [];
440
529
  // Generate dts job - single config
441
530
  if (dtsOnly) {
442
531
  outputConfigs = [
443
- buildOutputConfigs(_extends$1({}, bundleConfig, {
532
+ buildOutputConfigs(pkg, _extends$1({}, bundleConfig, {
444
533
  format: 'es',
445
534
  useTypescript
446
- }), pkg, typescriptOptions)
535
+ }), cwd, tsOptions, dtsOnly)
447
536
  ];
448
537
  } else {
449
538
  // multi outputs with specified format
450
539
  outputConfigs = outputExports.map((exportDist)=>{
451
- return buildOutputConfigs(_extends$1({}, bundleConfig, {
540
+ return buildOutputConfigs(pkg, _extends$1({}, bundleConfig, {
452
541
  file: exportDist.file,
453
542
  format: exportDist.format,
454
543
  useTypescript
455
- }), pkg, typescriptOptions);
544
+ }), cwd, tsOptions, dtsOnly);
456
545
  });
457
546
  // CLI output option is always prioritized
458
547
  if (file) {
459
548
  var _outputExports_;
460
549
  const fallbackFormat = (_outputExports_ = outputExports[0]) == null ? void 0 : _outputExports_.format;
461
550
  outputConfigs = [
462
- buildOutputConfigs(_extends$1({}, bundleConfig, {
551
+ buildOutputConfigs(pkg, _extends$1({}, bundleConfig, {
463
552
  file,
464
553
  format: bundleConfig.format || fallbackFormat,
465
554
  useTypescript
466
- }), pkg, typescriptOptions)
555
+ }), cwd, tsOptions, dtsOnly)
467
556
  ];
468
557
  }
469
558
  }
470
559
  return {
471
560
  input: inputOptions,
472
561
  output: outputConfigs,
473
- exportName: ((_options_exportCondition = options.exportCondition) == null ? void 0 : _options_exportCondition.name) || '.',
474
- dtsOnly
562
+ exportName: ((_options_exportCondition = options.exportCondition) == null ? void 0 : _options_exportCondition.name) || '.'
475
563
  };
476
564
  }
477
565
 
566
+ function asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, key, arg) {
567
+ try {
568
+ var info = gen[key](arg);
569
+ var value = info.value;
570
+ } catch (error) {
571
+ reject(error);
572
+ return;
573
+ }
574
+ if (info.done) {
575
+ resolve(value);
576
+ } else {
577
+ Promise.resolve(value).then(_next, _throw);
578
+ }
579
+ }
580
+ function _async_to_generator$1(fn) {
581
+ return function() {
582
+ var self = this, args = arguments;
583
+ return new Promise(function(resolve, reject) {
584
+ var gen = fn.apply(self, args);
585
+ function _next(value) {
586
+ asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "next", value);
587
+ }
588
+ function _throw(err) {
589
+ asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "throw", err);
590
+ }
591
+ _next(undefined);
592
+ });
593
+ };
594
+ }
595
+ let hasLoggedTsWarning = false;
596
+ function resolveTypescript(cwd) {
597
+ let ts;
598
+ const m = new module$1.Module('', undefined);
599
+ m.paths = module$1.Module._nodeModulePaths(cwd);
600
+ try {
601
+ ts = m.require('typescript');
602
+ } catch (_) {
603
+ console.error(_);
604
+ if (!hasLoggedTsWarning) {
605
+ hasLoggedTsWarning = true;
606
+ exit('Could not load TypeScript compiler. Try to install `typescript` as dev dependency');
607
+ }
608
+ }
609
+ return ts;
610
+ }
611
+ function resolveTsConfig(cwd) {
612
+ return _resolveTsConfig.apply(this, arguments);
613
+ }
614
+ function _resolveTsConfig() {
615
+ _resolveTsConfig = _async_to_generator$1(function*(cwd) {
616
+ let tsCompilerOptions = {};
617
+ let tsConfigPath;
618
+ const ts = resolveTypescript(cwd);
619
+ tsConfigPath = path.resolve(cwd, 'tsconfig.json');
620
+ if (yield fileExists(tsConfigPath)) {
621
+ const basePath = tsConfigPath ? path.dirname(tsConfigPath) : cwd;
622
+ const tsconfigJSON = ts.readConfigFile(tsConfigPath, ts.sys.readFile).config;
623
+ tsCompilerOptions = ts.parseJsonConfigFileContent(tsconfigJSON, ts.sys, basePath).options;
624
+ } else {
625
+ tsConfigPath = undefined;
626
+ return null;
627
+ }
628
+ return {
629
+ tsCompilerOptions,
630
+ tsConfigPath
631
+ };
632
+ });
633
+ return _resolveTsConfig.apply(this, arguments);
634
+ }
635
+
636
+ function logSizeStats() {
637
+ const stats = sizeCollector.getSizeStats();
638
+ const maxLength = Math.max(...stats.map(([filename])=>filename.length));
639
+ stats.forEach(([filename, prettiedSize])=>{
640
+ const padding = ' '.repeat(maxLength - filename.length);
641
+ const action = filename.endsWith('.d.ts') ? 'Typed' : 'Built';
642
+ logger.log(` ✓ ${action} ${filename}${padding} - ${prettiedSize}`);
643
+ });
644
+ }
645
+
478
646
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
479
647
  try {
480
648
  var info = gen[key](arg);
@@ -530,144 +698,89 @@ function _object_without_properties_loose(source, excluded) {
530
698
  }
531
699
  return target;
532
700
  }
533
- const SRC = 'src' // resolve from src/ directory
534
- ;
535
- function logBuild(exportPath, dtsOnly, duration) {
536
- logger.log(` ✓ ${dtsOnly ? 'Typed' : 'Built'} ${exportPath} ${formatDuration(duration)}`);
537
- }
538
701
  function assignDefault(options, name, defaultValue) {
539
702
  if (!(name in options) || options[name] == null) {
540
703
  options[name] = defaultValue;
541
704
  }
542
705
  }
543
- function resolveSourceFile(cwd, filename) {
544
- return path.resolve(cwd, SRC, filename);
545
- }
546
- function getSourcePathFromExportPath(cwd, exportPath) {
547
- return _getSourcePathFromExportPath.apply(this, arguments);
548
- }
549
- function _getSourcePathFromExportPath() {
550
- _getSourcePathFromExportPath = // Map '.' -> './index.[ext]'
551
- // Map './lite' -> './lite.[ext]'
552
- // Return undefined if no match or if it's package.json exports
553
- _async_to_generator(function*(cwd, exportPath) {
554
- const exts = [
555
- 'js',
556
- 'cjs',
557
- 'mjs',
558
- 'jsx',
559
- 'ts',
560
- 'tsx'
561
- ];
562
- for (const ext of exts){
563
- // ignore package.json
564
- if (exportPath.endsWith('package.json')) return;
565
- if (exportPath === '.') exportPath = './index';
566
- const filename = resolveSourceFile(cwd, `${exportPath}.${ext}`);
567
- if (yield fileExists(filename)) {
568
- return filename;
569
- }
570
- }
571
- return;
572
- });
573
- return _getSourcePathFromExportPath.apply(this, arguments);
706
+ function hasMultiEntryExport(pkg) {
707
+ const packageExportsField = pkg.exports || {};
708
+ if (typeof packageExportsField === 'string') return false;
709
+ const exportKeys = (packageExportsField ? Object.keys(packageExportsField) : []).filter((key)=>key !== './package.json');
710
+ return exportKeys.length > 0 && exportKeys.every((name)=>name.startsWith('.'));
574
711
  }
575
712
  function bundle(entryPath) {
576
713
  return _bundle.apply(this, arguments);
577
714
  }
578
715
  function _bundle() {
579
716
  _bundle = _async_to_generator(function*(entryPath, _param = {}) {
580
- var { cwd } = _param, options = _object_without_properties_loose(_param, [
717
+ var { cwd: _cwd } = _param, options = _object_without_properties_loose(_param, [
581
718
  "cwd"
582
719
  ]);
583
- config.rootDir = path.resolve(process.cwd(), cwd || '');
720
+ const cwd = path.resolve(process.cwd(), _cwd || '');
584
721
  assignDefault(options, 'format', 'es');
585
722
  assignDefault(options, 'minify', false);
586
723
  assignDefault(options, 'target', 'es2015');
587
- if (options.dts === undefined && isTypescript(entryPath)) {
588
- options.dts = true;
589
- }
590
- const pkg = yield getPackageMeta(config.rootDir);
591
- const packageExports = pkg.exports || {};
592
- const isSingleEntry = typeof packageExports === 'string';
593
- const hasMultiEntries = packageExports && !isSingleEntry && Object.keys(packageExports).length > 0;
594
- if (isSingleEntry) {
724
+ const pkg = yield getPackageMeta(cwd);
725
+ const packageExportsField = pkg.exports || {};
726
+ const isMultiEntries = hasMultiEntryExport(pkg);
727
+ const tsConfig = yield resolveTsConfig(cwd);
728
+ const hasTsConfig = Boolean(tsConfig == null ? void 0 : tsConfig.tsConfigPath);
729
+ const defaultTsOptions = {
730
+ tsConfigPath: tsConfig == null ? void 0 : tsConfig.tsConfigPath,
731
+ tsCompilerOptions: (tsConfig == null ? void 0 : tsConfig.tsCompilerOptions) || {}
732
+ };
733
+ // Handle single entry file
734
+ if (!isMultiEntries) {
595
735
  // Use specified string file path if possible, then fallback to the default behavior entry picking logic
596
736
  // e.g. "exports": "./dist/index.js" -> use "./index.<ext>" as entry
597
- entryPath = entryPath || (yield getSourcePathFromExportPath(config.rootDir, '.')) || '';
598
- }
599
- function buildEntryConfig(packageExports, dtsOnly) {
600
- return _buildEntryConfig.apply(this, arguments);
601
- }
602
- function _buildEntryConfig() {
603
- _buildEntryConfig = _async_to_generator(function*(packageExports, dtsOnly) {
604
- const configs = Object.keys(packageExports).map(/*#__PURE__*/ _async_to_generator(function*(entryExport) {
605
- const source = yield getSourcePathFromExportPath(config.rootDir, entryExport);
606
- if (!source) return undefined;
607
- if (dtsOnly && !isTypescript(source)) return;
608
- options.exportCondition = {
609
- source,
610
- name: entryExport,
611
- export: packageExports[entryExport]
612
- };
613
- const entry = resolveSourceFile(cwd, source);
614
- const rollupConfig = buildConfig(entry, pkg, options, dtsOnly);
615
- return rollupConfig;
616
- }));
617
- return (yield Promise.all(configs)).filter((n)=>Boolean(n));
618
- });
619
- return _buildEntryConfig.apply(this, arguments);
737
+ entryPath = entryPath || (yield getSourcePathFromExportPath(cwd, '.')) || '';
620
738
  }
621
739
  const bundleOrWatch = (rollupConfig)=>{
622
740
  const { input , exportName } = rollupConfig;
623
- const exportPath = getExportPath(pkg, exportName);
741
+ const exportPath = getExportPath(pkg, cwd, exportName);
624
742
  // Log original entry file relative path
625
- const source = typeof input.input === 'string' ? path.relative(config.rootDir, input.input) : exportPath;
743
+ const source = typeof input.input === 'string' ? path.relative(cwd, input.input) : exportPath;
626
744
  const buildMetadata = {
627
745
  source
628
746
  };
629
747
  if (options.watch) {
630
748
  return Promise.resolve(runWatch(rollupConfig, buildMetadata));
631
749
  }
632
- return runBundle(rollupConfig, buildMetadata);
750
+ return runBundle(rollupConfig);
633
751
  };
634
- if (!(yield fileExists(entryPath))) {
635
- const hasSpecifiedEntryFile = entryPath === '' ? false : (yield fs.stat(entryPath)).isFile();
636
- if (!hasSpecifiedEntryFile && !hasMultiEntries) {
637
- const err = new Error(`Entry file \`${entryPath}\` is not existed`);
638
- err.name = 'NOT_EXISTED';
639
- return Promise.reject(err);
640
- }
641
- // has `types` field in package.json or has `types` exports in any export condition for multi-entries
642
- const hasTypings = !!getTypings(pkg) || typeof packageExports === 'object' && Array.from(Object.values(packageExports || {})).some((condition)=>condition.hasOwnProperty('types'));
643
- // If there's no entry file specified, should enable dts bundling based on package.json exports info
644
- if (!hasSpecifiedEntryFile && hasTypings) {
645
- options.dts = hasTypings;
646
- }
647
- if (hasMultiEntries) {
648
- const buildConfigs = yield buildEntryConfig(packageExports, false);
649
- const assetsJobs = buildConfigs.map((rollupConfig)=>bundleOrWatch(rollupConfig));
650
- const typesJobs = options.dts ? (yield buildEntryConfig(packageExports, true)).map((rollupConfig)=>bundleOrWatch(rollupConfig)) : [];
651
- return yield Promise.all(assetsJobs.concat(typesJobs));
652
- }
752
+ const hasSpecifiedEntryFile = entryPath ? (yield fileExists(entryPath)) && (yield fs.stat(entryPath)).isFile() : false;
753
+ if (!hasSpecifiedEntryFile && !isMultiEntries) {
754
+ const err = new Error(`Entry file \`${entryPath}\` is not existed`);
755
+ err.name = 'NOT_EXISTED';
756
+ return Promise.reject(err);
653
757
  }
654
- // Generate types
655
- if (isTypescript(entryPath) && options.dts) {
656
- yield bundleOrWatch(buildConfig(entryPath, pkg, options, true));
758
+ // has `types` field in package.json or has `types` exports in any export condition for multi-entries
759
+ const hasTypings = !!getTypings(pkg) || typeof packageExportsField === 'object' && Array.from(Object.values(packageExportsField || {})).some((condition)=>condition.hasOwnProperty('types'));
760
+ // Enable types generation if it's types field specified in package.json
761
+ if (hasTypings) {
762
+ options.dts = hasTypings;
763
+ }
764
+ let result;
765
+ if (isMultiEntries) {
766
+ const buildConfigs = yield buildEntryConfig(pkg, options, cwd, defaultTsOptions, false);
767
+ const assetsJobs = buildConfigs.map((rollupConfig)=>bundleOrWatch(rollupConfig));
768
+ const typesJobs = options.dts ? (yield buildEntryConfig(pkg, options, cwd, defaultTsOptions, true)).map((rollupConfig)=>bundleOrWatch(rollupConfig)) : [];
769
+ result = yield Promise.all(assetsJobs.concat(typesJobs));
770
+ } else {
771
+ // Generate types
772
+ if (hasTsConfig && options.dts) {
773
+ yield bundleOrWatch(buildConfig(entryPath, pkg, options, cwd, defaultTsOptions, true));
774
+ }
775
+ const rollupConfig = buildConfig(entryPath, pkg, options, cwd, defaultTsOptions, false);
776
+ result = yield bundleOrWatch(rollupConfig);
657
777
  }
658
- const rollupConfig = buildConfig(entryPath, pkg, options, false);
659
- return bundleOrWatch(rollupConfig);
778
+ logSizeStats();
779
+ return result;
660
780
  });
661
781
  return _bundle.apply(this, arguments);
662
782
  }
663
- // . -> pkg name
664
- // ./lite -> <pkg name>/lite
665
- function getExportPath(pkg, exportName) {
666
- const name = pkg.name || path.basename(config.rootDir);
667
- if (exportName === '.' || !exportName) return name;
668
- return path.join(name, exportName);
669
- }
670
- function runWatch({ input , output , dtsOnly }, metadata) {
783
+ function runWatch({ input , output }, metadata) {
671
784
  const watchOptions = [
672
785
  _extends({}, input, {
673
786
  output: output,
@@ -679,7 +792,6 @@ function runWatch({ input , output , dtsOnly }, metadata) {
679
792
  })
680
793
  ];
681
794
  const watcher = rollup.watch(watchOptions);
682
- let startTime = Date.now();
683
795
  watcher.on('event', (event)=>{
684
796
  switch(event.code){
685
797
  case 'ERROR':
@@ -688,14 +800,11 @@ function runWatch({ input , output , dtsOnly }, metadata) {
688
800
  }
689
801
  case 'START':
690
802
  {
691
- startTime = Date.now();
692
803
  logger.log(`Start building ${metadata.source} ...`);
693
804
  break;
694
805
  }
695
806
  case 'END':
696
807
  {
697
- const duration = Date.now() - startTime;
698
- logBuild(metadata.source, dtsOnly, duration);
699
808
  break;
700
809
  }
701
810
  default:
@@ -704,15 +813,11 @@ function runWatch({ input , output , dtsOnly }, metadata) {
704
813
  });
705
814
  return watcher;
706
815
  }
707
- function runBundle({ input , output , dtsOnly }, jobOptions) {
708
- const startTime = Date.now();
816
+ function runBundle({ input , output }) {
709
817
  return rollup.rollup(input).then((bundle)=>{
710
818
  const writeJobs = output.map((options)=>bundle.write(options));
711
819
  return Promise.all(writeJobs);
712
- }, onError).then(()=>{
713
- const duration = Date.now() - startTime;
714
- logBuild(jobOptions.source, dtsOnly, duration);
715
- });
820
+ }, onError);
716
821
  }
717
822
  function onError(error) {
718
823
  if (!error) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunchee",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "zero config bundler for js/ts/jsx libraries",
5
5
  "bin": {
6
6
  "bunchee": "./dist/cli.js"
@@ -31,6 +31,10 @@
31
31
  "dist",
32
32
  "*.md"
33
33
  ],
34
+ "prettier": {
35
+ "semi": false,
36
+ "singleQuote": true
37
+ },
34
38
  "engines": {
35
39
  "node": ">= 16"
36
40
  },
@@ -46,7 +50,9 @@
46
50
  "@rollup/plugin-node-resolve": "15.0.2",
47
51
  "@rollup/plugin-replace": "5.0.2",
48
52
  "@swc/core": "1.3.46",
53
+ "@swc/helpers": "0.5.0",
49
54
  "arg": "5.0.2",
55
+ "pretty-bytes": "5.6.0",
50
56
  "publint": "0.1.11",
51
57
  "rollup": "3.20.2",
52
58
  "rollup-plugin-dts": "5.3.0",
@@ -60,6 +66,9 @@
60
66
  "peerDependenciesMeta": {
61
67
  "typescript": {
62
68
  "optional": true
69
+ },
70
+ "@swc/helpers": {
71
+ "optional": true
63
72
  }
64
73
  },
65
74
  "devDependencies": {