bunchee 3.3.4 → 3.4.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 CHANGED
@@ -61,7 +61,10 @@ Using pure ESM package?
61
61
  }
62
62
  ```
63
63
 
64
- Then just run `npm run build`, or `pnpm build` / `yarn build` if you're using these package managers.
64
+ Then just run `npm run build`, or `pnpm build` / `yarn build` if you're using these package managers. The output format will based on the exports condition and also the file extension. Given an example:
65
+
66
+ * It's CommonJS for `require` and ESM for `import` based on the exports condition.
67
+ * 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.
65
68
 
66
69
  ## Configuration
67
70
 
@@ -121,7 +124,6 @@ bunchee --env=ENV1,ENV2,ENV3
121
124
 
122
125
  Replace `ENV1`, `ENV2`, and `ENV3` with the names of the environment variables you want to include in your bundled code. These environment variables will be inlined during the bundling process.
123
126
 
124
-
125
127
  ### Entry Files Convention
126
128
 
127
129
  While `exports` field is becoming the standard of exporting in node.js, bunchee also supports to build multiple exports all in one command.
@@ -161,6 +163,35 @@ Then you need to add two entry files `index.ts` and `lite.ts` in project root di
161
163
  |- package.json
162
164
  ```
163
165
 
166
+ 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.
167
+
168
+ ### Special Exports Conventions
169
+
170
+ 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.
171
+
172
+ For instance:
173
+
174
+ ```json
175
+ {
176
+ "exports": {
177
+ "react-server": "./dist/react-server.mjs",
178
+ "edge-light": "./dist/edge-light.mjs",
179
+ "import": "./dist/index.mjs"
180
+ }
181
+ }
182
+ ```
183
+
184
+ You can use `index.<export-type>.<ext>` to override the input source file for specific export name. Or using `<export-path>/index.<export-type>.<ext>` also works. Such as:
185
+
186
+ ```
187
+ |- src/
188
+ |- index/.ts
189
+ |- index.react-server.ts
190
+ |- index.edge-light.ts
191
+ ```
192
+
193
+ This will match the export name `"react-server"` and `"edge-light"` then use the corresponding input source file to build the bundle.
194
+
164
195
  #### Package lint
165
196
 
166
197
  `bunchee` has support for checking the package bundles are matched with package exports configuration.
package/dist/cli.js CHANGED
@@ -76,7 +76,7 @@ const logger = {
76
76
  console.log('\x1b[33m' + arg + '\x1b[0m');
77
77
  },
78
78
  error (arg) {
79
- console.error('\x1b[31m' + arg + '\x1b[0m');
79
+ console.error('\x1b[31m' + (arg instanceof Error ? arg.stack : arg) + '\x1b[0m');
80
80
  }
81
81
  };
82
82
  function fileExists(filePath) {
@@ -97,7 +97,7 @@ function _fileExists() {
97
97
  return _fileExists.apply(this, arguments);
98
98
  }
99
99
 
100
- var version = "3.3.4";
100
+ var version = "3.4.1";
101
101
 
102
102
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
103
103
  try {
package/dist/index.js CHANGED
@@ -118,7 +118,7 @@ const logger = {
118
118
  console.log('\x1b[33m' + arg + '\x1b[0m');
119
119
  },
120
120
  error (arg) {
121
- console.error('\x1b[31m' + arg + '\x1b[0m');
121
+ console.error('\x1b[31m' + (arg instanceof Error ? arg.stack : arg) + '\x1b[0m');
122
122
  }
123
123
  };
124
124
  function fileExists(filePath) {
@@ -151,30 +151,55 @@ const SRC = 'src' // resolve from src/ directory
151
151
  function resolveSourceFile(cwd, filename) {
152
152
  return path__default.default.resolve(cwd, SRC, filename);
153
153
  }
154
+ function findSourceEntryFile(cwd, exportPath, exportTypeSuffix, ext) {
155
+ return _findSourceEntryFile.apply(this, arguments);
156
+ }
157
+ function _findSourceEntryFile() {
158
+ _findSourceEntryFile = _async_to_generator$3(function*(cwd, exportPath, exportTypeSuffix, ext) {
159
+ const filename = resolveSourceFile(cwd, `${exportPath}${exportTypeSuffix ? `.${exportTypeSuffix}` : ''}.${ext}`);
160
+ if (yield fileExists(filename)) {
161
+ return filename;
162
+ }
163
+ const subFolderIndexFilename = resolveSourceFile(cwd, `${exportPath}/index${exportTypeSuffix ? `.${exportTypeSuffix}` : ''}.${ext}`);
164
+ if (yield fileExists(subFolderIndexFilename)) {
165
+ return subFolderIndexFilename;
166
+ }
167
+ return undefined;
168
+ });
169
+ return _findSourceEntryFile.apply(this, arguments);
170
+ }
154
171
  // Map '.' -> './index.[ext]'
155
172
  // Map './lite' -> './lite.[ext]'
156
173
  // Return undefined if no match or if it's package.json exports
157
- function getSourcePathFromExportPath(cwd, exportPath) {
174
+ const availableExtensions = [
175
+ 'js',
176
+ 'cjs',
177
+ 'mjs',
178
+ 'jsx',
179
+ 'ts',
180
+ 'tsx'
181
+ ];
182
+ const availableExportConventions = [
183
+ 'react-server',
184
+ 'react-native',
185
+ 'edge-light'
186
+ ];
187
+ function getSourcePathFromExportPath(cwd, exportPath, exportType) {
158
188
  return _getSourcePathFromExportPath.apply(this, arguments);
159
189
  }
160
190
  function _getSourcePathFromExportPath() {
161
- _getSourcePathFromExportPath = _async_to_generator$3(function*(cwd, exportPath) {
162
- const exts = [
163
- 'js',
164
- 'cjs',
165
- 'mjs',
166
- 'jsx',
167
- 'ts',
168
- 'tsx'
169
- ];
170
- for (const ext of exts){
191
+ _getSourcePathFromExportPath = _async_to_generator$3(function*(cwd, exportPath, exportType) {
192
+ for (const ext of availableExtensions){
171
193
  // ignore package.json
172
194
  if (exportPath.endsWith('package.json')) return;
173
195
  if (exportPath === '.') exportPath = './index';
174
- const filename = resolveSourceFile(cwd, `${exportPath}.${ext}`);
175
- if (yield fileExists(filename)) {
176
- return filename;
196
+ // Find convention-based source file for specific export types
197
+ if (availableExportConventions.includes(exportType)) {
198
+ const filename = yield findSourceEntryFile(cwd, exportPath, exportType, ext);
199
+ if (filename) return filename;
177
200
  }
201
+ const filename = yield findSourceEntryFile(cwd, exportPath, null, ext);
202
+ if (filename) return filename;
178
203
  }
179
204
  return;
180
205
  });
@@ -184,6 +209,7 @@ function _getSourcePathFromExportPath() {
184
209
  function filenameWithoutExtension(file) {
185
210
  return file ? file.replace(new RegExp(`${path__default.default.extname(file)}$`), '') : undefined;
186
211
  }
212
+ const nonNullable = (n)=>Boolean(n);
187
213
 
188
214
  function getTypings(pkg) {
189
215
  return pkg.types || pkg.typings;
@@ -350,22 +376,19 @@ function constructDefaultExportCondition(value, packageType) {
350
376
  } : value;
351
377
  return constructFullExportCondition(objValue, packageType);
352
378
  }
353
- function isEsmExportName(name) {
379
+ function isEsmExportName(name, ext) {
354
380
  return [
355
381
  'import',
356
- 'module',
357
- 'react-native',
358
- 'react-server',
359
- 'edge-light'
360
- ].includes(name);
382
+ 'module'
383
+ ].includes(name) || ext === 'mjs';
361
384
  }
362
- function isCjsExportName(name) {
385
+ function isCjsExportName(name, ext) {
363
386
  return [
364
387
  'require',
365
388
  'main',
366
389
  'node',
367
390
  'default'
368
- ].includes(name);
391
+ ].includes(name) || ext === 'cjs';
369
392
  }
370
393
  function getExportConditionDist(pkg, parsedExportCondition, cwd) {
371
394
  const dist = [];
@@ -375,12 +398,14 @@ function getExportConditionDist(pkg, parsedExportCondition, cwd) {
375
398
  if (key === 'types') {
376
399
  continue;
377
400
  }
401
+ const filePath = parsedExportCondition.export[key];
402
+ const ext = path.extname(filePath).slice(1);
378
403
  const relativePath = parsedExportCondition.export[key];
379
404
  const distFile = getDistPath(relativePath, cwd);
380
405
  let format = 'esm';
381
- if (isEsmExportName(key)) {
406
+ if (isEsmExportName(key, ext)) {
382
407
  format = 'esm';
383
- } else if (isCjsExportName(key)) {
408
+ } else if (isCjsExportName(key, ext)) {
384
409
  format = 'cjs';
385
410
  }
386
411
  // Deduplicate the same path jobs
@@ -592,8 +617,8 @@ function hasEsmExport(exportPaths, tsCompilerOptions) {
592
617
  let hasEsm = false;
593
618
  for(const key in exportPaths){
594
619
  const exportInfo = exportPaths[key];
595
- const exportNames = Object.keys(exportInfo);
596
- if (exportNames.some((name)=>isEsmExportName(name))) {
620
+ const exportInfoEntries = Object.entries(exportInfo);
621
+ if (exportInfoEntries.some(([exportType, file])=>isEsmExportName(exportType, file))) {
597
622
  hasEsm = true;
598
623
  break;
599
624
  }
@@ -636,22 +661,61 @@ function buildEntryConfig(pkg, entryPath, exportPaths, bundleConfig, cwd, tsOpti
636
661
  }
637
662
  function _buildEntryConfig() {
638
663
  _buildEntryConfig = _async_to_generator$2(function*(pkg, entryPath, exportPaths, bundleConfig, cwd, tsOptions, dts) {
639
- const configs = Object.keys(exportPaths).map(/*#__PURE__*/ _async_to_generator$2(function*(entryExport) {
664
+ const configs = [];
665
+ Object.keys(exportPaths).forEach(/*#__PURE__*/ _async_to_generator$2(function*(entryExport) {
640
666
  // TODO: improve the source detection
641
- const source = entryPath || (yield getSourcePathFromExportPath(cwd, entryExport));
642
- if (!source) return undefined;
643
- // For dts, only build types filed
644
- if (dts && !exportPaths[entryExport]['types']) return undefined;
645
- const exportCondition = {
646
- source,
647
- name: entryExport,
648
- export: exportPaths[entryExport]
649
- };
650
- const entry = resolveSourceFile(cwd, source);
651
- const rollupConfig = buildConfig(entry, pkg, exportPaths, bundleConfig, exportCondition, cwd, tsOptions, dts);
652
- return rollupConfig;
667
+ const exportCond = exportPaths[entryExport];
668
+ const buildConfigs = [
669
+ createBuildConfig('', exportCond) // default config
670
+ ];
671
+ // For dts job, only build the default config.
672
+ // For assets job, build all configs.
673
+ if (!dts) {
674
+ if (exportCond['edge-light']) {
675
+ buildConfigs.push(createBuildConfig('edge-light', exportCond));
676
+ }
677
+ if (exportCond['react-server']) {
678
+ buildConfigs.push(createBuildConfig('react-server', exportCond));
679
+ }
680
+ if (exportCond['react-native']) {
681
+ buildConfigs.push(createBuildConfig('react-native', exportCond));
682
+ }
683
+ }
684
+ function createBuildConfig(exportType, exportCondRef) {
685
+ return _createBuildConfig.apply(this, arguments);
686
+ }
687
+ function _createBuildConfig() {
688
+ _createBuildConfig = _async_to_generator$2(function*(exportType, exportCondRef) {
689
+ let exportCondForType = _extends$1({}, exportCondRef);
690
+ // Special cases of export type, only pass down the exportPaths for the type
691
+ if (availableExportConventions.includes(exportType)) {
692
+ exportCondForType = {
693
+ [entryExport]: exportCondRef[exportType]
694
+ };
695
+ // Basic export type, pass down the exportPaths with erasing the special ones
696
+ } else {
697
+ for (const exportType of availableExportConventions){
698
+ delete exportCondForType[exportType];
699
+ }
700
+ }
701
+ const source = entryPath || (yield getSourcePathFromExportPath(cwd, entryExport, exportType));
702
+ if (!source) return undefined;
703
+ // For dts, only build types filed
704
+ if (dts && !exportCondRef['types']) return undefined;
705
+ const exportCondition = {
706
+ source,
707
+ name: entryExport,
708
+ export: exportCondForType
709
+ };
710
+ const entry = resolveSourceFile(cwd, source);
711
+ const rollupConfig = buildConfig(entry, pkg, exportPaths, bundleConfig, exportCondition, cwd, tsOptions, dts);
712
+ return rollupConfig;
713
+ });
714
+ return _createBuildConfig.apply(this, arguments);
715
+ }
716
+ configs.push(...buildConfigs);
653
717
  }));
654
- return (yield Promise.all(configs)).filter((n)=>Boolean(n));
718
+ return (yield Promise.all(configs)).filter(nonNullable);
655
719
  });
656
720
  return _buildEntryConfig.apply(this, arguments);
657
721
  }
@@ -876,7 +940,7 @@ function _bundle() {
876
940
  if (!isMultiEntries) {
877
941
  // Use specified string file path if possible, then fallback to the default behavior entry picking logic
878
942
  // e.g. "exports": "./dist/index.js" -> use "./index.<ext>" as entry
879
- entryPath = entryPath || (yield getSourcePathFromExportPath(cwd, '.')) || '';
943
+ entryPath = entryPath || (yield getSourcePathFromExportPath(cwd, '.', 'default')) || '';
880
944
  }
881
945
  if (entryPath) {
882
946
  let mainEntryPath;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunchee",
3
- "version": "3.3.4",
3
+ "version": "3.4.1",
4
4
  "description": "zero config bundler for js/ts/jsx libraries",
5
5
  "bin": {
6
6
  "bunchee": "./dist/cli.js"