bunchee 4.3.2 → 4.3.4

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
@@ -34,6 +34,7 @@ npm install --save-dev bunchee typescript
34
34
  ### Configuration
35
35
 
36
36
  Create your library entry file and package.json.
37
+
37
38
  ```sh
38
39
  cd ./my-lib
39
40
  mkdir src && touch ./src/index.ts
@@ -57,6 +58,7 @@ Or you can checkout the following cases to configure your package.json.
57
58
  <summary> JavaScript</summary>
58
59
 
59
60
  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.
61
+
60
62
  ```json
61
63
  {
62
64
  "files": ["dist"],
@@ -69,6 +71,7 @@ Then use use the [exports field in package.json](https://nodejs.org/api/packages
69
71
  }
70
72
  }
71
73
  ```
74
+
72
75
  </details>
73
76
 
74
77
  <details>
@@ -94,8 +97,8 @@ If you're build a TypeScript library, separate the types from the main entry fil
94
97
  }
95
98
  }
96
99
  ```
97
- </details>
98
100
 
101
+ </details>
99
102
 
100
103
  <details>
101
104
  <summary>Hybrid (CJS & ESM) Module Resolution with TypeScript</summary>
@@ -122,6 +125,7 @@ If you're using TypeScript with Node 10 and Node 16 module resolution, you can u
122
125
  }
123
126
  }
124
127
  ```
128
+
125
129
  </details>
126
130
 
127
131
  #### Build
@@ -240,7 +244,6 @@ This will match the `bin` field in package.json as:
240
244
 
241
245
  > Note: For multiple `bin` files, the filename should match the key name in the `bin` field.
242
246
 
243
-
244
247
  ### Server Components
245
248
 
246
249
  `bunchee` supports to build server components and server actions with library directives like `"use client"` or `"use server"`. It will generate the corresponding chunks for client and server that scope the client and server boundaries properly.
@@ -280,7 +283,7 @@ bunchee ./src/index.js --runtime node --target es2019
280
283
 
281
284
  #### Specifying extra external dependencies
282
285
 
283
- By default, `bunchee` will mark all the `dependencies` and `peerDependencies` as externals so you don't need to pass them as CLI args.
286
+ By default, `bunchee` will mark all the `dependencies` and `peerDependencies` as externals so you don't need to pass them as CLI args.
284
287
  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.
285
288
 
286
289
  ```sh
@@ -309,7 +312,6 @@ bunchee --env=ENV1,ENV2,ENV3
309
312
 
310
313
  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.
311
314
 
312
-
313
315
  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:
314
316
 
315
317
  ```
@@ -321,7 +323,6 @@ You can use `index.<export-type>.<ext>` to override the input source file for sp
321
323
 
322
324
  This will match the export name `"react-server"` and `"edge-light"` then use the corresponding input source file to build the bundle.
323
325
 
324
-
325
326
  ### Wildcard Exports
326
327
 
327
328
  Bunchee implements the Node.js feature of using the asterisk `*` as a wildcard to match the exportable entry files.
@@ -402,6 +403,7 @@ If you just want to import a file as string content, you can name the extension
402
403
  For example:
403
404
 
404
405
  src/index.ts
406
+
405
407
  ```js
406
408
  import data from './data.txt'
407
409
 
@@ -409,11 +411,13 @@ export default data
409
411
  ```
410
412
 
411
413
  src/data.txt
414
+
412
415
  ```txt
413
416
  hello world
414
417
  ```
415
418
 
416
419
  output
420
+
417
421
  ```
418
422
  export default "hello world"
419
423
  ```
@@ -450,7 +454,6 @@ If you specify `target` option in `tsconfig.json`, then you don't have to pass i
450
454
 
451
455
  `bunchee` has support for checking the package bundles are matched with package exports configuration.
452
456
 
453
-
454
457
  ### License
455
458
 
456
459
  MIT
package/dist/bin/cli.js CHANGED
@@ -14,7 +14,7 @@ var fs__default = /*#__PURE__*/_interopDefault(fs);
14
14
  var fsp__default = /*#__PURE__*/_interopDefault(fsp);
15
15
  var require$$0__default = /*#__PURE__*/_interopDefault(require$$0);
16
16
 
17
- const availableExtensions = [
17
+ const availableExtensions = new Set([
18
18
  'js',
19
19
  'cjs',
20
20
  'mjs',
@@ -23,19 +23,19 @@ const availableExtensions = [
23
23
  'tsx',
24
24
  'cts',
25
25
  'mts'
26
- ];
26
+ ]);
27
27
  const SRC = 'src';
28
28
  const dtsExtensionsMap = {
29
29
  js: 'd.ts',
30
30
  cjs: 'd.cts',
31
31
  mjs: 'd.mts'
32
32
  };
33
- const tsExtensions = [
33
+ const tsExtensions = new Set([
34
34
  'ts',
35
35
  'tsx',
36
36
  'cts',
37
37
  'mts'
38
- ];
38
+ ]);
39
39
 
40
40
  function getDefaultExportFromCjs (x) {
41
41
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
@@ -134,21 +134,28 @@ async function getPackageMeta(cwd) {
134
134
  }
135
135
  function isTypescriptFile(filename) {
136
136
  const ext = path__default.default.extname(filename).slice(1);
137
- return tsExtensions.includes(ext);
137
+ return tsExtensions.has(ext);
138
138
  }
139
139
  function fileExists(filePath) {
140
140
  return fs__default.default.existsSync(filePath);
141
141
  }
142
- const hasAvailableExtension = (filename)=>availableExtensions.includes(path__default.default.extname(filename).slice(1));
142
+ const hasAvailableExtension = (filename)=>availableExtensions.has(path__default.default.extname(filename).slice(1));
143
+ // TODO: add unit test
143
144
  const baseNameWithoutExtension = (filename)=>path__default.default.basename(filename, path__default.default.extname(filename));
144
145
 
145
- var version = "4.3.2";
146
+ var version = "4.3.4";
146
147
 
147
148
  function relativify(path) {
148
149
  return path.startsWith('.') ? path : `./${path}`;
149
150
  }
150
151
 
151
152
  const DIST = 'dist';
153
+ const DEFAULT_TS_CONFIG = {
154
+ compilerOptions: {
155
+ module: 'ESNext',
156
+ moduleResolution: 'bundler'
157
+ }
158
+ };
152
159
  // Output with posix style in package.json
153
160
  function getDistPath(...subPaths) {
154
161
  return `./${DIST}/${subPaths.join('/')}`;
@@ -159,14 +166,16 @@ const normalizeBaseNameToExportName = (baseName)=>{
159
166
  function createExportCondition(exportName, sourceFile, moduleType) {
160
167
  const isTsSourceFile = isTypescriptFile(sourceFile);
161
168
  let cjsExtension = 'js';
169
+ let esmExtension = 'mjs';
162
170
  if (moduleType === 'module') {
163
171
  cjsExtension = 'cjs';
172
+ esmExtension = 'js';
164
173
  }
165
174
  if (isTsSourceFile) {
166
175
  return {
167
176
  import: {
168
- types: getDistPath('es', `${exportName}.d.mts`),
169
- default: getDistPath('es', `${exportName}.mjs`)
177
+ types: getDistPath('es', `${exportName}.${dtsExtensionsMap[esmExtension]}`),
178
+ default: getDistPath('es', `${exportName}.${esmExtension}`)
170
179
  },
171
180
  require: {
172
181
  types: getDistPath('cjs', `${exportName}.${dtsExtensionsMap[cjsExtension]}`),
@@ -193,18 +202,17 @@ async function collectSourceEntries(sourceFolderPath) {
193
202
  });
194
203
  for (const binDirent of binDirentList){
195
204
  if (binDirent.isFile()) {
196
- const binFile = path__default.default.join(sourceFolderPath, dirent.name, binDirent.name);
205
+ const binFileAbsolutePath = path__default.default.join(sourceFolderPath, dirent.name, binDirent.name);
197
206
  const binName = baseNameWithoutExtension(binDirent.name);
198
- if (fs__default.default.existsSync(binFile)) {
207
+ if (fs__default.default.existsSync(binFileAbsolutePath)) {
199
208
  bins.set(binName, binDirent.name);
200
209
  }
201
210
  }
202
211
  }
203
212
  } else {
204
213
  // Search folder/<index>.<ext> convention entries
205
- const extensions = availableExtensions;
206
- for (const extension of extensions){
207
- const indexFile = path__default.default.join(sourceFolderPath, dirent.name, `index.${extension}`);
214
+ for (const extension of availableExtensions){
215
+ const indexFile = path__default.default.join(dirent.name, `index.${extension}`);
208
216
  if (fs__default.default.existsSync(indexFile)) {
209
217
  exportsEntries.set(dirent.name, indexFile);
210
218
  break;
@@ -212,7 +220,7 @@ async function collectSourceEntries(sourceFolderPath) {
212
220
  }
213
221
  }
214
222
  } else if (dirent.isFile()) {
215
- const isAvailableExtension = availableExtensions.includes(path__default.default.extname(dirent.name).slice(1));
223
+ const isAvailableExtension = availableExtensions.has(path__default.default.extname(dirent.name).slice(1));
216
224
  if (isAvailableExtension) {
217
225
  const baseName = baseNameWithoutExtension(dirent.name);
218
226
  const isBinFile = baseName === 'bin';
@@ -277,16 +285,16 @@ async function prepare(cwd) {
277
285
  // Collect bins and exports entries
278
286
  const { bins, exportsEntries } = await collectSourceEntries(sourceFolder);
279
287
  const tsconfigPath = path__default.default.join(cwd, 'tsconfig.json');
280
- if (!fs__default.default.existsSync(tsconfigPath)) {
281
- const sourceFiles = [
282
- ...exportsEntries.values()
283
- ].concat([
284
- ...bins.values()
285
- ]);
286
- const hasTypeScriptFiles = sourceFiles.some((filename)=>isTypescriptFile(filename));
287
- if (hasTypeScriptFiles) {
288
- isUsingTs = true;
289
- await fsp__default.default.writeFile(tsconfigPath, '{}', 'utf-8');
288
+ const sourceFiles = [
289
+ ...exportsEntries.values()
290
+ ].concat([
291
+ ...bins.values()
292
+ ]);
293
+ const hasTypeScriptFiles = sourceFiles.some((filename)=>isTypescriptFile(filename));
294
+ if (hasTypeScriptFiles) {
295
+ isUsingTs = true;
296
+ if (!fs__default.default.existsSync(tsconfigPath)) {
297
+ await fsp__default.default.writeFile(tsconfigPath, JSON.stringify(DEFAULT_TS_CONFIG, null, 2), 'utf-8');
290
298
  logger.log(`Detected using TypeScript but tsconfig.json is missing, created a ${pc.blue('tsconfig.json')} for you.`);
291
299
  }
292
300
  }
@@ -333,12 +341,19 @@ async function prepare(cwd) {
333
341
  pkgJson.main = isUsingTs ? mainExport[mainCondition].default : mainExport[mainCondition];
334
342
  pkgJson.module = isUsingTs ? mainExport.import.default : mainExport.import;
335
343
  if (isUsingTs) {
336
- pkgJson.types = isESM ? mainExport.import.types : mainExport.require.types;
344
+ pkgJson.types = mainExport[mainCondition].types;
337
345
  }
338
346
  }
339
347
  // Assign the properties by order: files, main, module, types, exports
340
348
  if (Object.keys(pkgExports).length > 0) {
341
- pkgJson.exports = pkgExports;
349
+ if (!pkgJson.exports) {
350
+ pkgJson.exports = pkgExports;
351
+ } else {
352
+ // Update existing exports
353
+ Object.keys(pkgExports).forEach((exportName)=>{
354
+ pkgJson.exports[exportName] = pkgExports[exportName];
355
+ });
356
+ }
342
357
  }
343
358
  }
344
359
  await fsp__default.default.writeFile(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ var esmShim__default = /*#__PURE__*/_interopDefault(esmShim);
30
30
  var preserveDirectives__default = /*#__PURE__*/_interopDefault(preserveDirectives);
31
31
  var prettyBytes__default = /*#__PURE__*/_interopDefault(prettyBytes);
32
32
 
33
- const availableExtensions = [
33
+ const availableExtensions = new Set([
34
34
  'js',
35
35
  'cjs',
36
36
  'mjs',
@@ -39,7 +39,7 @@ const availableExtensions = [
39
39
  'tsx',
40
40
  'cts',
41
41
  'mts'
42
- ];
42
+ ]);
43
43
  const nodeResolveExtensions = [
44
44
  '.mjs',
45
45
  '.cjs',
@@ -48,11 +48,11 @@ const nodeResolveExtensions = [
48
48
  '.node',
49
49
  '.jsx'
50
50
  ];
51
- const availableExportConventions = [
51
+ const availableExportConventions = new Set([
52
52
  'react-server',
53
53
  'react-native',
54
54
  'edge-light'
55
- ];
55
+ ]);
56
56
  const availableESExtensionsRegex = /\.(m|c)?[jt]sx?$/;
57
57
  const SRC = 'src';
58
58
  const dtsExtensionsMap = {
@@ -191,7 +191,7 @@ async function getSourcePathFromExportPath(cwd, exportPath, exportType) {
191
191
  if (exportPath === '.') exportPath = './index';
192
192
  // Find convention-based source file for specific export types
193
193
  // $binary represents `pkg.bin`
194
- if (availableExportConventions.includes(exportType) && exportType !== '$binary') {
194
+ if (availableExportConventions.has(exportType) && exportType !== '$binary') {
195
195
  const filename = await findSourceEntryFile(cwd, exportPath, exportType, ext);
196
196
  if (filename) return filename;
197
197
  }
@@ -200,13 +200,16 @@ async function getSourcePathFromExportPath(cwd, exportPath, exportType) {
200
200
  }
201
201
  return;
202
202
  }
203
+ // TODO: add unit test
203
204
  // Unlike path.basename, forcedly removing extension
204
205
  function filePathWithoutExtension(file) {
205
206
  return file ? file.replace(new RegExp(`${path__default.default.extname(file)}$`), '') : undefined;
206
207
  }
207
208
  const nonNullable = (n)=>Boolean(n);
208
- const hasAvailableExtension = (filename)=>availableExtensions.includes(path__default.default.extname(filename).slice(1));
209
+ const hasAvailableExtension = (filename)=>availableExtensions.has(path__default.default.extname(filename).slice(1));
209
210
  const hasCjsExtension = (filename)=>path__default.default.extname(filename) === '.cjs';
211
+ // TODO: add unit test
212
+ const baseNameWithoutExtension = (filename)=>path__default.default.basename(filename, path__default.default.extname(filename));
210
213
 
211
214
  let hasLoggedTsWarning = false;
212
215
  function resolveTypescript(cwd) {
@@ -391,9 +394,6 @@ function prependDirectives() {
391
394
  function getTypings(pkg) {
392
395
  return pkg.types || pkg.typings;
393
396
  }
394
- function getDistPath(distPath, cwd) {
395
- return path.resolve(cwd, distPath);
396
- }
397
397
  // Reached the end of the export path
398
398
  function isExportLike(field) {
399
399
  if (typeof field === 'string') return true;
@@ -585,31 +585,6 @@ function findExport(exportPath, exportCondition, paths, packageType, currentPath
585
585
  }
586
586
  return pathsMap;
587
587
  }
588
- const getExportTypeDist = (parsedExportCondition, cwd)=>{
589
- const existed = new Set();
590
- const exportTypes = Object.keys(parsedExportCondition.export);
591
- for (const key of exportTypes){
592
- if (key === 'module') {
593
- continue;
594
- }
595
- const filePath = parsedExportCondition.export[key];
596
- if (key === 'types') {
597
- const typeFile = getDistPath(filePath, cwd);
598
- if (existed.has(typeFile)) {
599
- continue;
600
- }
601
- existed.add(typeFile);
602
- continue;
603
- }
604
- const ext = path.extname(filePath).slice(1);
605
- const typeFile = getDistPath(`${filePathWithoutExtension(filePath) || ''}.${dtsExtensionsMap[ext]}`, cwd);
606
- if (existed.has(typeFile)) {
607
- continue;
608
- }
609
- existed.add(typeFile);
610
- }
611
- return Array.from(existed);
612
- };
613
588
  function getPackageType(pkg) {
614
589
  return pkg.type || 'commonjs';
615
590
  }
@@ -638,55 +613,43 @@ function isEsmExportName(name, ext) {
638
613
  'module'
639
614
  ].includes(name) || ext === 'mjs';
640
615
  }
641
- function isCjsExportName(pkg, name, ext) {
616
+ function isCjsExportName(pkg, exportCondition, ext) {
642
617
  const isESModule = isESModulePackage(pkg.type);
643
618
  return !isESModule && [
644
619
  'require',
645
- 'main',
646
- 'node'
647
- ].includes(name) && ext !== 'mjs' || ext === 'cjs';
620
+ 'main'
621
+ ].includes(exportCondition) && ext !== 'mjs' || ext === 'cjs';
648
622
  }
649
- function getExportConditionDist(pkg, parsedExportCondition, cwd) {
623
+ function getExportsDistFilesOfCondition(pkg, parsedExportCondition, cwd) {
650
624
  const dist = [];
651
- const existed = new Set();
652
- const exportTypes = Object.keys(parsedExportCondition.export);
653
- for (const exportType of exportTypes){
654
- if (exportType === 'types') {
625
+ const exportConditionNames = Object.keys(parsedExportCondition.export);
626
+ const uniqueFiles = new Set();
627
+ for (const exportCondition of exportConditionNames){
628
+ if (exportCondition === 'types') {
655
629
  continue;
656
630
  }
657
- const filePath = parsedExportCondition.export[exportType];
631
+ const filePath = parsedExportCondition.export[exportCondition];
658
632
  const ext = path.extname(filePath).slice(1);
659
- const relativePath = parsedExportCondition.export[exportType];
660
- const distFile = getDistPath(relativePath, cwd);
661
- let format = 'esm';
662
- if (isCjsExportName(pkg, exportType, ext)) {
663
- format = 'cjs';
664
- }
665
- // Deduplicate the same path jobs
666
- // TODO: detect conflicts paths but with different format
667
- if (existed.has(distFile)) {
633
+ const relativePath = parsedExportCondition.export[exportCondition];
634
+ const distFile = path.resolve(cwd, relativePath);
635
+ const format = isCjsExportName(pkg, exportCondition, ext) ? 'cjs' : 'esm';
636
+ if (uniqueFiles.has(distFile)) {
668
637
  continue;
669
638
  }
670
- existed.add(distFile);
639
+ uniqueFiles.add(distFile);
671
640
  dist.push({
672
641
  format,
673
642
  file: distFile
674
643
  });
675
644
  }
676
- if (dist.length === 0 && !pkg.bin) {
677
- const defaultFormat = isESModulePackage(pkg.type) ? 'esm' : 'cjs';
678
- dist.push({
679
- format: defaultFormat,
680
- file: getDistPath('dist/index.js', cwd)
681
- });
682
- }
683
645
  return dist;
684
646
  }
685
- function getTypeFilePath(entryFilePath, exportCondition, cwd) {
686
- const name = filePathWithoutExtension(entryFilePath);
687
- const firstDistPath = exportCondition ? Object.values(exportCondition.export)[0] : undefined;
688
- const exportName = (exportCondition == null ? void 0 : exportCondition.name) || 'index';
689
- return entryFilePath ? name + '.d.ts' : path.resolve(firstDistPath ? path.dirname(firstDistPath) : path.join(cwd, 'dist'), (exportName === '.' ? 'index' : exportName) + '.d.ts');
647
+ function getExportFileTypePath(absoluteJsBundlePath) {
648
+ const dirName = path.dirname(absoluteJsBundlePath);
649
+ const baseName = baseNameWithoutExtension(absoluteJsBundlePath);
650
+ const ext = path.extname(absoluteJsBundlePath).slice(1);
651
+ const typeExtension = dtsExtensionsMap[ext];
652
+ return path.join(dirName, baseName + '.' + typeExtension);
690
653
  }
691
654
  function getExportTypeFromFile(filename, pkgType) {
692
655
  const isESModule = isESModulePackage(pkgType);
@@ -719,7 +682,9 @@ function getBuildEnv(envs) {
719
682
  return envVars;
720
683
  }
721
684
  /**
722
- * return { '<absolute source path>': '<pkg>/<export>' }
685
+ * return {
686
+ * <absolute source path>: <pkg>/<export>
687
+ * }
723
688
  */ function getReversedAlias(entries) {
724
689
  const alias = {};
725
690
  for (const [entryImportPath, exportCondition] of Object.entries(entries)){
@@ -731,7 +696,7 @@ function getBuildEnv(envs) {
731
696
  }
732
697
  return alias;
733
698
  }
734
- async function buildInputConfig(entry, options, buildContext, dts) {
699
+ async function buildInputConfig(entry, options, buildContext, exportCondition, dts) {
735
700
  const { entries, pkg, cwd, tsOptions: { tsConfigPath, tsCompilerOptions }, pluginContext } = buildContext;
736
701
  const hasNoExternal = options.external === null;
737
702
  var _options_external;
@@ -747,11 +712,12 @@ async function buildInputConfig(entry, options, buildContext, dts) {
747
712
  externals.push(entryFilePath);
748
713
  }
749
714
  }
750
- const { useTypescript, runtime, target: jscTarget, minify: shouldMinify } = options;
715
+ const { useTypeScript } = buildContext;
716
+ const { runtime, target: jscTarget, minify: shouldMinify } = options;
751
717
  const hasSpecifiedTsTarget = Boolean(tsCompilerOptions.target && tsConfigPath);
752
718
  const swcParserConfig = {
753
- syntax: useTypescript ? 'typescript' : 'ecmascript',
754
- [useTypescript ? 'tsx' : 'jsx']: true,
719
+ syntax: useTypeScript ? 'typescript' : 'ecmascript',
720
+ [useTypeScript ? 'tsx' : 'jsx']: true,
755
721
  exportDefaultFrom: true
756
722
  };
757
723
  const swcOptions = {
@@ -791,7 +757,7 @@ async function buildInputConfig(entry, options, buildContext, dts) {
791
757
  skip: true
792
758
  })
793
759
  ];
794
- if (useTypescript) {
760
+ if (useTypeScript) {
795
761
  const { options: overrideResolvedTsOptions } = await convertCompilerOptions(cwd, {
796
762
  declaration: true,
797
763
  noEmit: false,
@@ -801,16 +767,14 @@ async function buildInputConfig(entry, options, buildContext, dts) {
801
767
  declarationMap: false,
802
768
  skipLibCheck: true,
803
769
  target: 'ESNext',
804
- // Some react types required this to be false by default.
805
- // Some type package like express might need this as it has other dependencies.
806
- // Let users able to toggle this in tsconfig.
807
- preserveSymlinks: 'preserveSymlinks' in tsCompilerOptions ? tsCompilerOptions.preserveSymlinks : false,
808
770
  ...!tsCompilerOptions.jsx ? {
809
771
  jsx: 'react-jsx'
810
772
  } : undefined,
811
773
  // error TS5074: Option '--incremental' can only be specified using tsconfig, emitting to single
812
774
  // file or when option '--tsBuildInfoFile' is specified.
813
- incremental: false
775
+ ...tsCompilerOptions.incremental && !tsCompilerOptions.tsBuildInfoFile ? {
776
+ incremental: false
777
+ } : undefined
814
778
  });
815
779
  const dtsPlugin = require('rollup-plugin-dts').default({
816
780
  tsconfig: tsConfigPath,
@@ -960,22 +924,17 @@ function buildOutputConfigs(options, exportCondition, buildContext, dts) {
960
924
  const { entries, pkg, exportPaths, cwd, tsOptions: { tsCompilerOptions }, pluginContext } = buildContext;
961
925
  // Add esm mark and interop helper if esm export is detected
962
926
  const useEsModuleMark = hasEsmExport(exportPaths, tsCompilerOptions);
963
- const typings = getTypings(pkg);
964
- const file = options.file && path.resolve(cwd, options.file);
965
- const dtsDir = typings ? path.dirname(path.resolve(cwd, typings)) : path.resolve(cwd, 'dist');
966
- const name = filePathWithoutExtension(file);
967
- // TODO: simplify dts file name detection
968
- const dtsFile = file ? file : exportCondition.export['types'] ? path.resolve(cwd, exportCondition.export['types']) : path.resolve(dtsDir, (exportCondition.name === '.' ? 'index' : exportCondition.name) + '.d.ts');
969
- const dtsPathConfig = {
970
- dir: dtsFile ? path.dirname(dtsFile) : dtsDir
971
- };
972
- const outputFile = dtsFile || file;
927
+ const absoluteOutputFile = path.resolve(cwd, options.file);
928
+ const name = filePathWithoutExtension(absoluteOutputFile);
929
+ var _exportCondition_export_types;
930
+ const dtsFile = path.resolve(cwd, dts ? options.file : (_exportCondition_export_types = exportCondition.export.types) != null ? _exportCondition_export_types : getExportFileTypePath(options.file));
931
+ const typesDir = path.dirname(dtsFile);
932
+ const jsDir = path.dirname(absoluteOutputFile);
933
+ const outputFile = dts ? dtsFile : absoluteOutputFile;
973
934
  const entryFiles = new Set(Object.values(entries).map((entry)=>entry.source));
974
935
  return {
975
936
  name: pkg.name || name,
976
- ...dts ? dtsPathConfig : {
977
- dir: path.dirname(outputFile)
978
- },
937
+ dir: dts ? typesDir : jsDir,
979
938
  format,
980
939
  exports: 'named',
981
940
  esModule: useEsModuleMark || 'if-default-prop',
@@ -1013,9 +972,9 @@ async function buildEntryConfig(bundleConfig, pluginContext, dts) {
1013
972
  ...exportCondRef
1014
973
  };
1015
974
  // Special cases of export type, only pass down the exportPaths for the type
1016
- if (availableExportConventions.includes(exportType)) {
975
+ if (availableExportConventions.has(exportType)) {
1017
976
  exportCondForType = {
1018
- [entryExport]: exportCondRef[exportType]
977
+ [exportType]: exportCondRef[exportType]
1019
978
  };
1020
979
  // Basic export type, pass down the exportPaths with erasing the special ones
1021
980
  } else {
@@ -1098,42 +1057,61 @@ async function buildConfig(bundleConfig, exportCondition, pluginContext, dts) {
1098
1057
  useTypescript
1099
1058
  };
1100
1059
  const entry = exportCondition.source;
1101
- const inputOptions = await buildInputConfig(entry, options, pluginContext, dts);
1102
- const outputExports = getExportConditionDist(pkg, exportCondition, cwd);
1103
- let outputConfigs = [];
1104
- // Generate dts job - single config
1105
- if (dts) {
1106
- const typeOutputExports = getExportTypeDist(exportCondition, cwd);
1107
- outputConfigs = typeOutputExports.map((typeFile)=>buildOutputConfigs({
1108
- ...bundleConfig,
1109
- format: 'es',
1110
- useTypescript,
1111
- file: typeFile
1112
- }, exportCondition, pluginContext, dts));
1060
+ const inputOptions = await buildInputConfig(entry, options, pluginContext, exportCondition, dts);
1061
+ const outputExports = getExportsDistFilesOfCondition(pkg, exportCondition, cwd);
1062
+ // If there's nothing found, give a default output
1063
+ if (outputExports.length === 0 && !pkg.bin) {
1064
+ const defaultFormat = isESModulePackage(pkg.type) ? 'esm' : 'cjs';
1065
+ outputExports.push({
1066
+ format: defaultFormat,
1067
+ file: path.join(cwd, 'dist/index.js')
1068
+ });
1069
+ }
1070
+ let bundleOptions = [];
1071
+ // multi outputs with specified format
1072
+ // CLI output option is always prioritized
1073
+ if (file) {
1074
+ var _outputExports_;
1075
+ const fallbackFormat = (_outputExports_ = outputExports[0]) == null ? void 0 : _outputExports_.format;
1076
+ bundleOptions = [
1077
+ {
1078
+ resolvedFile: path.resolve(cwd, file),
1079
+ format: bundleConfig.format || fallbackFormat
1080
+ }
1081
+ ];
1113
1082
  } else {
1114
- // multi outputs with specified format
1115
- outputConfigs = outputExports.map((exportDist)=>{
1116
- return buildOutputConfigs({
1117
- ...bundleConfig,
1118
- file: exportDist.file,
1119
- format: exportDist.format,
1120
- useTypescript
1121
- }, exportCondition, pluginContext, dts);
1083
+ bundleOptions = outputExports.map((exportDist)=>{
1084
+ return {
1085
+ resolvedFile: path.resolve(cwd, exportDist.file),
1086
+ format: exportDist.format
1087
+ };
1122
1088
  });
1123
- // CLI output option is always prioritized
1124
- if (file) {
1125
- var _outputExports_;
1126
- const fallbackFormat = (_outputExports_ = outputExports[0]) == null ? void 0 : _outputExports_.format;
1127
- outputConfigs = [
1128
- buildOutputConfigs({
1129
- ...bundleConfig,
1130
- file,
1131
- format: bundleConfig.format || fallbackFormat,
1132
- useTypescript
1133
- }, exportCondition, pluginContext, dts)
1134
- ];
1135
- }
1136
1089
  }
1090
+ if (dts) {
1091
+ // types could have duplicates, dedupe them
1092
+ // e.g. { types, import, .. } use the same `types` condition with all conditions
1093
+ const uniqTypes = new Set();
1094
+ bundleOptions.forEach((bundleOption)=>{
1095
+ if (exportCondition.export.types) {
1096
+ uniqTypes.add(path.resolve(cwd, exportCondition.export.types));
1097
+ }
1098
+ const typeForExtension = getExportFileTypePath(bundleOption.resolvedFile);
1099
+ uniqTypes.add(typeForExtension);
1100
+ });
1101
+ bundleOptions = Array.from(uniqTypes).map((typeFile)=>{
1102
+ return {
1103
+ resolvedFile: typeFile,
1104
+ format: 'es'
1105
+ };
1106
+ });
1107
+ }
1108
+ const outputConfigs = bundleOptions.map((bundleOption)=>{
1109
+ return buildOutputConfigs({
1110
+ ...bundleConfig,
1111
+ file: bundleOption.resolvedFile,
1112
+ format: bundleOption.format
1113
+ }, exportCondition, pluginContext, dts);
1114
+ });
1137
1115
  return {
1138
1116
  input: inputOptions,
1139
1117
  output: outputConfigs,
@@ -1336,8 +1314,6 @@ async function bundle(entryPath, { cwd: _cwd, ...options } = {}) {
1336
1314
  const resolvedWildcardExports = await resolveWildcardExports(pkg.exports, cwd);
1337
1315
  const packageType = getPackageType(pkg);
1338
1316
  const exportPaths = getExportPaths(pkg, packageType, resolvedWildcardExports);
1339
- const exportKeys = Object.keys(exportPaths).filter((key)=>key !== './package.json');
1340
- // const exportPathsLength = Object.keys(exportPaths).length
1341
1317
  const isMultiEntries = hasMultiEntryExport(exportPaths) // exportPathsLength > 1
1342
1318
  ;
1343
1319
  const hasBin = Boolean(pkg.bin);
@@ -1359,12 +1335,10 @@ async function bundle(entryPath, { cwd: _cwd, ...options } = {}) {
1359
1335
  // with -o option
1360
1336
  if (options.file) {
1361
1337
  mainEntryPath = options.file;
1362
- } else if (exportKeys.length === 0) {
1363
- mainEntryPath = path.resolve(cwd, 'dist/index.js');
1364
1338
  }
1365
1339
  if (mainEntryPath) {
1366
1340
  if (options.dts) {
1367
- typesEntryPath = getTypeFilePath(mainEntryPath, undefined, cwd);
1341
+ typesEntryPath = getExportFileTypePath(mainEntryPath);
1368
1342
  }
1369
1343
  exportPaths['.'] = constructDefaultExportCondition({
1370
1344
  main: mainEntryPath,
@@ -1409,6 +1383,7 @@ async function bundle(entryPath, { cwd: _cwd, ...options } = {}) {
1409
1383
  exportPaths,
1410
1384
  cwd,
1411
1385
  tsOptions: defaultTsOptions,
1386
+ useTypeScript: hasTsConfig,
1412
1387
  pluginContext: {
1413
1388
  outputState: sizeCollector,
1414
1389
  moduleDirectiveLayerMap: new Map(),
@@ -1422,7 +1397,9 @@ async function bundle(entryPath, { cwd: _cwd, ...options } = {}) {
1422
1397
  if (result.length === 0) {
1423
1398
  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');
1424
1399
  }
1425
- logOutputState(sizeCollector);
1400
+ if (!options.watch) {
1401
+ logOutputState(sizeCollector);
1402
+ }
1426
1403
  return result;
1427
1404
  }
1428
1405
  function runWatch({ input, output }, metadata) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunchee",
3
- "version": "4.3.2",
3
+ "version": "4.3.4",
4
4
  "description": "zero config bundler for js/ts/jsx libraries",
5
5
  "bin": "./dist/bin/cli.js",
6
6
  "main": "./dist/index.js",
@@ -54,12 +54,12 @@
54
54
  "@rollup/plugin-replace": "^5.0.5",
55
55
  "@rollup/plugin-wasm": "^6.2.2",
56
56
  "@rollup/pluginutils": "^5.1.0",
57
- "@swc/core": "^1.3.99",
57
+ "@swc/core": "^1.3.102",
58
58
  "@swc/helpers": "^0.5.3",
59
59
  "arg": "^5.0.2",
60
60
  "pretty-bytes": "^5.6.0",
61
61
  "publint": "~0.2.7",
62
- "rollup": "^4.9.1",
62
+ "rollup": "^4.9.4",
63
63
  "rollup-plugin-dts": "^6.1.0",
64
64
  "rollup-plugin-swc3": "^0.11.0",
65
65
  "rollup-preserve-directives": "^1.1.1",