bunchee 3.2.1 → 3.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/dist/cli.js CHANGED
@@ -97,7 +97,7 @@ function _fileExists() {
97
97
  return _fileExists.apply(this, arguments);
98
98
  }
99
99
 
100
- var version = "3.2.1";
100
+ var version = "3.3.1";
101
101
 
102
102
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
103
103
  try {
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { JscTarget } from '@swc/core';
2
2
  import { OutputOptions } from 'rollup';
3
3
 
4
- type ExportType = 'require' | 'export' | 'default' | string;
5
4
  type BundleConfig = {
6
5
  file?: string;
7
6
  cwd?: string;
@@ -15,13 +14,7 @@ type BundleConfig = {
15
14
  env?: string[];
16
15
  dts?: boolean;
17
16
  runtime?: string;
18
- exportCondition?: {
19
- source: string;
20
- name: string;
21
- export: ExportCondition;
22
- };
23
17
  };
24
- type ExportCondition = string | Record<ExportType, string>;
25
18
 
26
19
  declare function bundle(entryPath: string, { cwd: _cwd, ...options }?: BundleConfig): Promise<any>;
27
20
 
package/dist/index.js CHANGED
@@ -39,7 +39,8 @@ function chunkSizeCollector() {
39
39
  const dir = options.dir || options.file && path__default.default.dirname(options.file);
40
40
  let fileName = chunk.fileName;
41
41
  if (dir) {
42
- fileName = path__default.default.relative(cwd, path__default.default.join(dir, fileName));
42
+ const filePath = path__default.default.join(dir, fileName);
43
+ fileName = filePath.startsWith(cwd) ? path__default.default.relative(cwd, filePath) : filePath;
43
44
  }
44
45
  addSize(fileName, code.length);
45
46
  return null;
@@ -66,20 +67,87 @@ function getTypings(pkg) {
66
67
  function getDistPath(distPath, cwd) {
67
68
  return path.resolve(cwd, distPath);
68
69
  }
69
- function findExport(field) {
70
- if (!field) return;
71
- if (typeof field === 'string') return field;
72
- const value = field['.'] || field['import'] || field['module'] || field['default'];
73
- return findExport(value);
70
+ // Reached the end of the export path
71
+ function isExportLike(field) {
72
+ if (typeof field === 'string') return true;
73
+ return Object.entries(field).every(// Every value is string and key is not start with '.'
74
+ // TODO: check key is ExportType
75
+ ([key, value])=>typeof value === 'string' && !key.startsWith('.'));
76
+ }
77
+ function constructFullExportCondition(value, packageType) {
78
+ const isCommonjs = packageType === 'commonjs';
79
+ let result;
80
+ if (typeof value === 'string') {
81
+ result = {
82
+ [isCommonjs ? 'require' : 'import']: value
83
+ };
84
+ } else {
85
+ // TODO: valid export condition, warn if it's not valid
86
+ const keys = Object.keys(value);
87
+ result = {};
88
+ keys.forEach((key)=>{
89
+ // Filter out nullable value
90
+ if (key in value && value[key]) {
91
+ result[key] = value[key];
92
+ }
93
+ });
94
+ }
95
+ return result;
96
+ }
97
+ function joinRelativePath(...segments) {
98
+ let result = path.join(...segments);
99
+ // If the first segment starts with './', ensure the result does too.
100
+ if (segments[0] === '.' && !result.startsWith('./')) {
101
+ result = './' + result;
102
+ }
103
+ return result;
74
104
  }
75
- function parseExport(exportsCondition) {
105
+ function findExport(name, value, paths, packageType) {
106
+ // TODO: handle export condition based on package.type
107
+ if (isExportLike(value)) {
108
+ paths[name] = constructFullExportCondition(value, packageType);
109
+ return;
110
+ }
111
+ Object.keys(value).forEach((subpath)=>{
112
+ const nextName = joinRelativePath(name, subpath);
113
+ const nestedValue = value[subpath];
114
+ findExport(nextName, nestedValue, paths, packageType);
115
+ });
116
+ }
117
+ /**
118
+ *
119
+ * Convert package.exports field to paths mapping
120
+ * Example
121
+ *
122
+ * Input:
123
+ * {
124
+ * ".": {
125
+ * "sub": {
126
+ * "import": "./sub.js",
127
+ * "require": "./sub.cjs",
128
+ * "types": "./sub.d.ts
129
+ * }
130
+ * }
131
+ * }
132
+ *
133
+ * Output:
134
+ * {
135
+ * "./sub": {
136
+ * "import": "./sub.js",
137
+ * "require": "./sub.cjs",
138
+ * "types": "./sub.d.ts,
139
+ * }
140
+ * }
141
+ *
142
+ */ function parseExport(exportsCondition, packageType) {
76
143
  const paths = {};
77
144
  if (typeof exportsCondition === 'string') {
78
- paths.export = exportsCondition;
79
- } else {
80
- paths.main = paths.main || exportsCondition['require'] || exportsCondition['node'] || exportsCondition['default'];
81
- paths.module = paths.module || exportsCondition['module'];
82
- paths.export = findExport(exportsCondition);
145
+ paths['.'] = constructFullExportCondition(exportsCondition, packageType);
146
+ } else if (typeof exportsCondition === 'object') {
147
+ Object.keys(exportsCondition).forEach((key)=>{
148
+ const value = exportsCondition[key];
149
+ findExport(key, value, paths, packageType);
150
+ });
83
151
  }
84
152
  return paths;
85
153
  }
@@ -124,55 +192,83 @@ function parseExport(exportsCondition) {
124
192
  * pkg.main and pkg.module will be added to ['.'] if exists
125
193
  */ function getExportPaths(pkg) {
126
194
  const pathsMap = {};
127
- const mainExport = {};
128
- if (pkg.main) {
129
- mainExport.main = pkg.main;
130
- }
131
- if (pkg.module) {
132
- mainExport.module = pkg.module;
133
- }
134
- pathsMap['.'] = mainExport;
195
+ const packageType = getPackageType(pkg);
135
196
  const { exports: exportsConditions } = pkg;
136
197
  if (exportsConditions) {
137
- if (typeof exportsConditions === 'string') {
138
- mainExport.export = exportsConditions;
139
- } else {
140
- const exportKeys = Object.keys(exportsConditions);
141
- if (exportKeys.some((key)=>key.startsWith('.'))) {
142
- exportKeys.forEach((subExport)=>{
143
- pathsMap[subExport] = parseExport(exportsConditions[subExport]);
144
- });
145
- } else {
146
- Object.assign(mainExport, parseExport(exportsConditions));
147
- }
148
- }
198
+ const paths = parseExport(exportsConditions, packageType);
199
+ Object.assign(pathsMap, paths);
200
+ }
201
+ // main export '.' from main/module/typings
202
+ const defaultMainExport = constructFullExportCondition({
203
+ [packageType === 'commonjs' ? 'require' : 'import']: pkg.main,
204
+ module: pkg.module,
205
+ types: getTypings(pkg)
206
+ }, packageType);
207
+ // Merge the main export into '.' paths
208
+ const mainExport = Object.assign({}, pathsMap['.'], defaultMainExport);
209
+ // main export is not empty
210
+ if (Object.keys(mainExport).length > 0) {
211
+ pathsMap['.'] = mainExport;
149
212
  }
150
- pathsMap['.'] = mainExport;
151
213
  return pathsMap;
152
214
  }
153
- function getExportDist(pkg, cwd) {
154
- const paths = getExportPaths(pkg)['.'];
215
+ function getPackageType(pkg) {
216
+ return pkg.type || 'commonjs';
217
+ }
218
+ function constructDefaultExportCondition(value, packageType) {
219
+ const objValue = typeof value === 'string' ? {
220
+ [packageType === 'commonjs' ? 'require' : 'import']: value,
221
+ types: getTypings(value)
222
+ } : value;
223
+ return constructFullExportCondition(objValue, packageType);
224
+ }
225
+ function isEsmExportName(name) {
226
+ return [
227
+ 'import',
228
+ 'module',
229
+ 'react-native',
230
+ 'react-server',
231
+ 'edge-light'
232
+ ].includes(name);
233
+ }
234
+ function isCjsExportName(name) {
235
+ return [
236
+ 'require',
237
+ 'main',
238
+ 'node',
239
+ 'default'
240
+ ].includes(name);
241
+ }
242
+ function getExportConditionDist(pkg, parsedExportCondition, cwd) {
155
243
  const dist = [];
156
- if (paths.main) {
157
- dist.push({
158
- format: 'cjs',
159
- file: getDistPath(paths.main, cwd)
160
- });
161
- }
162
- if (paths.module) {
163
- dist.push({
164
- format: 'esm',
165
- file: getDistPath(paths.module, cwd)
166
- });
167
- }
168
- if (paths.export) {
244
+ const existed = new Set();
245
+ const exportTypes = Object.keys(parsedExportCondition.export);
246
+ for (const key of exportTypes){
247
+ if (key === 'types') {
248
+ continue;
249
+ }
250
+ const relativePath = parsedExportCondition.export[key];
251
+ const distFile = getDistPath(relativePath, cwd);
252
+ let format = 'esm';
253
+ if (isEsmExportName(key)) {
254
+ format = 'esm';
255
+ } else if (isCjsExportName(key)) {
256
+ format = 'cjs';
257
+ }
258
+ // Deduplicate the same path jobs
259
+ // TODO: detect conflicts paths but with different format
260
+ if (existed.has(distFile)) {
261
+ continue;
262
+ }
263
+ existed.add(distFile);
169
264
  dist.push({
170
- format: 'esm',
171
- file: getDistPath(paths.export, cwd)
265
+ format,
266
+ file: distFile
172
267
  });
173
268
  }
174
- // default fallback to output `dist/index.js` in default esm format
175
269
  if (dist.length === 0) {
270
+ // TODO: Deprecate this warning and behavior in v3
271
+ console.error(`Doesn't fin any exports in ${pkg.name}, using default dist path dist/index.js`);
176
272
  dist.push({
177
273
  format: 'esm',
178
274
  file: getDistPath('dist/index.js', cwd)
@@ -180,40 +276,6 @@ function getExportDist(pkg, cwd) {
180
276
  }
181
277
  return dist;
182
278
  }
183
- function getExportConditionDist(pkg, exportCondition, cwd) {
184
- const dist = [];
185
- // "exports": "..."
186
- if (typeof exportCondition === 'string') {
187
- dist.push({
188
- format: pkg.type === 'module' ? 'esm' : 'cjs',
189
- file: getDistPath(exportCondition, cwd)
190
- });
191
- } else {
192
- // "./<subexport>": { }
193
- const subExports = exportCondition;
194
- // Ignore json exports, like "./package.json"
195
- if (typeof subExports === 'string') {
196
- dist.push({
197
- format: 'esm',
198
- file: getDistPath(subExports, cwd)
199
- });
200
- } else {
201
- if (subExports.require) {
202
- dist.push({
203
- format: 'cjs',
204
- file: getDistPath(subExports.require, cwd)
205
- });
206
- }
207
- if (subExports.import) {
208
- dist.push({
209
- format: 'esm',
210
- file: getDistPath(subExports.import, cwd)
211
- });
212
- }
213
- }
214
- }
215
- return dist;
216
- }
217
279
 
218
280
  function asyncGeneratorStep$3(gen, resolve, reject, _next, _throw, key, arg) {
219
281
  try {
@@ -516,16 +578,16 @@ function hasEsmExport(exportPaths, tsCompilerOptions) {
516
578
  let hasEsm = false;
517
579
  for(const key in exportPaths){
518
580
  const exportInfo = exportPaths[key];
519
- if (exportInfo.import || exportInfo.module) {
581
+ const exportNames = Object.keys(exportInfo);
582
+ if (exportNames.some((name)=>isEsmExportName(name))) {
520
583
  hasEsm = true;
521
584
  break;
522
585
  }
523
586
  }
524
587
  return Boolean(hasEsm || (tsCompilerOptions == null ? void 0 : tsCompilerOptions.esModuleInterop));
525
588
  }
526
- function buildOutputConfigs(pkg, options, cwd, { tsCompilerOptions }, dtsOnly) {
527
- const { format , exportCondition } = options;
528
- const exportPaths = getExportPaths(pkg);
589
+ function buildOutputConfigs(pkg, exportPaths, options, exportCondition, cwd, { tsCompilerOptions }, dtsOnly) {
590
+ const { format } = options;
529
591
  // Add esm mark and interop helper if esm export is detected
530
592
  const useEsModuleMark = hasEsmExport(exportPaths, tsCompilerOptions);
531
593
  const typings = getTypings(pkg);
@@ -533,7 +595,8 @@ function buildOutputConfigs(pkg, options, cwd, { tsCompilerOptions }, dtsOnly)
533
595
  const dtsDir = typings ? path.dirname(path.resolve(cwd, typings)) : path.resolve(cwd, 'dist');
534
596
  // file base name without extension
535
597
  const name = file ? file.replace(new RegExp(`${path.extname(file)}$`), '') : undefined;
536
- 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);
598
+ // TODO: simplify dts file name detection
599
+ const dtsFile = exportCondition.export['types'] ? path.resolve(cwd, exportCondition.export['types']) : 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);
537
600
  // If there's dts file, use `output.file`
538
601
  const dtsPathConfig = dtsFile ? {
539
602
  file: dtsFile
@@ -555,73 +618,71 @@ function buildOutputConfigs(pkg, options, cwd, { tsCompilerOptions }, dtsOnly)
555
618
  });
556
619
  }
557
620
  // build configs for each entry from package exports
558
- function buildEntryConfig(pkg, bundleConfig, cwd, tsOptions, dtsOnly) {
621
+ function buildEntryConfig(pkg, entryPath, exportPaths, bundleConfig, cwd, tsOptions, dtsOnly) {
559
622
  return _buildEntryConfig.apply(this, arguments);
560
623
  }
561
624
  function _buildEntryConfig() {
562
- _buildEntryConfig = _async_to_generator$2(function*(pkg, bundleConfig, cwd, tsOptions, dtsOnly) {
563
- const packageExports = pkg.exports || {};
564
- const configs = Object.keys(packageExports).map(/*#__PURE__*/ _async_to_generator$2(function*(entryExport) {
565
- const source = yield getSourcePathFromExportPath(cwd, entryExport);
625
+ _buildEntryConfig = _async_to_generator$2(function*(pkg, entryPath, exportPaths, bundleConfig, cwd, tsOptions, dtsOnly) {
626
+ const configs = Object.keys(exportPaths).map(/*#__PURE__*/ _async_to_generator$2(function*(entryExport) {
627
+ // TODO: improve the source detection
628
+ const source = entryPath || (yield getSourcePathFromExportPath(cwd, entryExport));
566
629
  if (!source) return undefined;
567
- if (dtsOnly && !(tsOptions == null ? void 0 : tsOptions.tsConfigPath)) return;
568
- bundleConfig.exportCondition = {
630
+ const exportCondition = {
569
631
  source,
570
632
  name: entryExport,
571
- export: packageExports[entryExport]
633
+ export: exportPaths[entryExport]
572
634
  };
573
635
  const entry = resolveSourceFile(cwd, source);
574
- const rollupConfig = buildConfig(entry, pkg, bundleConfig, cwd, tsOptions, dtsOnly);
636
+ const rollupConfig = buildConfig(entry, pkg, exportPaths, bundleConfig, exportCondition, cwd, tsOptions, dtsOnly);
575
637
  return rollupConfig;
576
638
  }));
577
639
  return (yield Promise.all(configs)).filter((n)=>Boolean(n));
578
640
  });
579
641
  return _buildEntryConfig.apply(this, arguments);
580
642
  }
581
- function buildConfig(entry, pkg, bundleConfig, cwd, tsOptions, dtsOnly) {
582
- var _options_exportCondition;
643
+ function buildConfig(entry, pkg, exportPaths, bundleConfig, exportCondition, cwd, tsOptions, dtsOnly) {
583
644
  const { file } = bundleConfig;
584
645
  const useTypescript = Boolean(tsOptions.tsConfigPath);
585
646
  const options = _extends$1({}, bundleConfig, {
586
647
  useTypescript
587
648
  });
588
649
  const inputOptions = buildInputConfig(entry, pkg, options, cwd, tsOptions, dtsOnly);
589
- const outputExports = options.exportCondition ? getExportConditionDist(pkg, options.exportCondition.export, cwd) : getExportDist(pkg, cwd);
650
+ const outputExports = getExportConditionDist(pkg, exportCondition, cwd);
590
651
  let outputConfigs = [];
591
652
  // Generate dts job - single config
592
653
  if (dtsOnly) {
593
654
  outputConfigs = [
594
- buildOutputConfigs(pkg, _extends$1({}, bundleConfig, {
655
+ buildOutputConfigs(pkg, exportPaths, _extends$1({}, bundleConfig, {
595
656
  format: 'es',
596
657
  useTypescript
597
- }), cwd, tsOptions, dtsOnly)
658
+ }), exportCondition, cwd, tsOptions, dtsOnly)
598
659
  ];
599
660
  } else {
600
661
  // multi outputs with specified format
601
662
  outputConfigs = outputExports.map((exportDist)=>{
602
- return buildOutputConfigs(pkg, _extends$1({}, bundleConfig, {
663
+ return buildOutputConfigs(pkg, exportPaths, _extends$1({}, bundleConfig, {
603
664
  file: exportDist.file,
604
665
  format: exportDist.format,
605
666
  useTypescript
606
- }), cwd, tsOptions, dtsOnly);
667
+ }), exportCondition, cwd, tsOptions, dtsOnly);
607
668
  });
608
669
  // CLI output option is always prioritized
609
670
  if (file) {
610
671
  var _outputExports_;
611
672
  const fallbackFormat = (_outputExports_ = outputExports[0]) == null ? void 0 : _outputExports_.format;
612
673
  outputConfigs = [
613
- buildOutputConfigs(pkg, _extends$1({}, bundleConfig, {
674
+ buildOutputConfigs(pkg, exportPaths, _extends$1({}, bundleConfig, {
614
675
  file,
615
676
  format: bundleConfig.format || fallbackFormat,
616
677
  useTypescript
617
- }), cwd, tsOptions, dtsOnly)
678
+ }), exportCondition, cwd, tsOptions, dtsOnly)
618
679
  ];
619
680
  }
620
681
  }
621
682
  return {
622
683
  input: inputOptions,
623
684
  output: outputConfigs,
624
- exportName: ((_options_exportCondition = options.exportCondition) == null ? void 0 : _options_exportCondition.name) || '.'
685
+ exportName: exportCondition.name || '.'
625
686
  };
626
687
  }
627
688
 
@@ -765,10 +826,8 @@ function assignDefault(options, name, defaultValue) {
765
826
  options[name] = defaultValue;
766
827
  }
767
828
  }
768
- function hasMultiEntryExport(pkg) {
769
- const packageExportsField = pkg.exports || {};
770
- if (typeof packageExportsField === 'string') return false;
771
- const exportKeys = (packageExportsField ? Object.keys(packageExportsField) : []).filter((key)=>key !== './package.json');
829
+ function hasMultiEntryExport(exportPaths) {
830
+ const exportKeys = Object.keys(exportPaths).filter((key)=>key !== './package.json');
772
831
  return exportKeys.length > 0 && exportKeys.every((name)=>name.startsWith('.'));
773
832
  }
774
833
  function bundle(entryPath) {
@@ -784,8 +843,12 @@ function _bundle() {
784
843
  assignDefault(options, 'minify', false);
785
844
  assignDefault(options, 'target', 'es2015');
786
845
  const pkg = yield getPackageMeta(cwd);
787
- const packageExportsField = pkg.exports || {};
788
- const isMultiEntries = hasMultiEntryExport(pkg);
846
+ const packageType = getPackageType(pkg);
847
+ const exportPaths = getExportPaths(pkg);
848
+ const exportKeys = Object.keys(exportPaths).filter((key)=>key !== './package.json');
849
+ // const exportPathsLength = Object.keys(exportPaths).length
850
+ const isMultiEntries = hasMultiEntryExport(exportPaths) // exportPathsLength > 1
851
+ ;
789
852
  const tsConfig = yield resolveTsConfig(cwd);
790
853
  const hasTsConfig = Boolean(tsConfig == null ? void 0 : tsConfig.tsConfigPath);
791
854
  const defaultTsOptions = {
@@ -798,6 +861,14 @@ function _bundle() {
798
861
  // e.g. "exports": "./dist/index.js" -> use "./index.<ext>" as entry
799
862
  entryPath = entryPath || (yield getSourcePathFromExportPath(cwd, '.')) || '';
800
863
  }
864
+ if (entryPath) {
865
+ // with -o option
866
+ if (options.file) {
867
+ exportPaths['.'] = constructDefaultExportCondition(options.file, packageType);
868
+ } else if (exportKeys.length === 0) {
869
+ exportPaths['.'] = constructDefaultExportCondition('dist/index.js', packageType);
870
+ }
871
+ }
801
872
  const bundleOrWatch = (rollupConfig)=>{
802
873
  const { input , exportName } = rollupConfig;
803
874
  const exportPath = getExportPath(pkg, cwd, exportName);
@@ -818,25 +889,16 @@ function _bundle() {
818
889
  return Promise.reject(err);
819
890
  }
820
891
  // has `types` field in package.json or has `types` exports in any export condition for multi-entries
821
- const hasTypings = !!getTypings(pkg) || typeof packageExportsField === 'object' && Array.from(Object.values(packageExportsField || {})).some((condition)=>condition.hasOwnProperty('types'));
892
+ const hasTypings = Object.values(exportPaths).some((condition)=>condition.hasOwnProperty('types'));
822
893
  // Enable types generation if it's types field specified in package.json
823
894
  if (hasTypings) {
824
895
  options.dts = hasTypings;
825
896
  }
826
897
  let result;
827
- if (isMultiEntries) {
828
- const buildConfigs = yield buildEntryConfig(pkg, options, cwd, defaultTsOptions, false);
829
- const assetsJobs = buildConfigs.map((rollupConfig)=>bundleOrWatch(rollupConfig));
830
- const typesJobs = options.dts ? (yield buildEntryConfig(pkg, options, cwd, defaultTsOptions, true)).map((rollupConfig)=>bundleOrWatch(rollupConfig)) : [];
831
- result = yield Promise.all(assetsJobs.concat(typesJobs));
832
- } else {
833
- // Generate types
834
- if (hasTsConfig && options.dts) {
835
- yield bundleOrWatch(buildConfig(entryPath, pkg, options, cwd, defaultTsOptions, true));
836
- }
837
- const rollupConfig = buildConfig(entryPath, pkg, options, cwd, defaultTsOptions, false);
838
- result = yield bundleOrWatch(rollupConfig);
839
- }
898
+ const buildConfigs = yield buildEntryConfig(pkg, entryPath, exportPaths, options, cwd, defaultTsOptions, false);
899
+ const assetsJobs = buildConfigs.map((rollupConfig)=>bundleOrWatch(rollupConfig));
900
+ const typesJobs = hasTsConfig && options.dts ? (yield buildEntryConfig(pkg, entryPath, exportPaths, options, cwd, defaultTsOptions, true)).map((rollupConfig)=>bundleOrWatch(rollupConfig)) : [];
901
+ result = yield Promise.all(assetsJobs.concat(typesJobs));
840
902
  logSizeStats();
841
903
  return result;
842
904
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunchee",
3
- "version": "3.2.1",
3
+ "version": "3.3.1",
4
4
  "description": "zero config bundler for js/ts/jsx libraries",
5
5
  "bin": {
6
6
  "bunchee": "./dist/cli.js"
package/dist/cli.d.ts DELETED
@@ -1 +0,0 @@
1
- #!/usr/bin/env node