bunchee 6.6.2 → 6.7.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
@@ -317,6 +317,23 @@ bunchee --no-external
317
317
 
318
318
  This will include all dependencies within your output bundle.
319
319
 
320
+ #### TypeScript-Go Compiler
321
+
322
+ TypeScript-Go (`@typescript/native-preview`) is a high-performance, Go-based implementation of the TypeScript compiler that can significantly speed up type declaration file generation.
323
+
324
+ To use TypeScript-Go for type generation, use the `--tsgo` flag:
325
+
326
+ ```sh
327
+ bunchee --tsgo
328
+ ```
329
+
330
+ **Note**: This requires `@typescript/native-preview` to be installed as a dev dependency. If it's not installed, bunchee will exit with an error.
331
+
332
+ ```sh
333
+ pnpm add -D bunchee @typescript/native-preview
334
+ bunchee --tsgo
335
+ ```
336
+
320
337
  #### Build Successful Command
321
338
 
322
339
  A command to be executed after a build is successful can be specified using the `--success` option, which is useful for development watching mode:
@@ -365,6 +382,14 @@ Then use use the [exports field in package.json](https://nodejs.org/api/packages
365
382
 
366
383
  If you're building a TypeScript library, separate the types from the main entry file and specify the types path in package.json. Types exports need to stay on the top of each export with `types` condition, and you can use `default` condition for the JS bundle file.
367
384
 
385
+ **bunchee** supports using the TypeScript-Go compiler (`@typescript/native-preview`) for faster type generation. To enable it, use the `--tsgo` flag:
386
+
387
+ ```sh
388
+ bunchee --tsgo
389
+ ```
390
+
391
+ Note: This requires `@typescript/native-preview` to be installed as a dev dependency. If it's not installed, bunchee will fall back to the regular TypeScript compiler with a warning.
392
+
368
393
  ```json5
369
394
  {
370
395
  "files": ["dist"],
@@ -545,6 +570,7 @@ await bundle(path.resolve('./src/index.ts'), {
545
570
  cwd: process.cwd(), // string
546
571
  clean: true, // boolean
547
572
  tsconfig: 'tsconfig.json', // string
573
+ tsgo: false, // Boolean - use TypeScript-Go compiler for type generation
548
574
  })
549
575
  ```
550
576
 
package/dist/bin/cli.js CHANGED
@@ -198,7 +198,7 @@ function validateEntryFiles(entryFiles) {
198
198
 
199
199
  function exit(err) {
200
200
  logger.error(err);
201
- process.exit(1);
201
+ throw typeof err === 'string' ? new Error(err) : err;
202
202
  }
203
203
  function hasPackageJson(cwd) {
204
204
  return fileExists(path__default.default.resolve(cwd, 'package.json'));
@@ -647,11 +647,12 @@ function lint$1(pkg) {
647
647
  }
648
648
  }
649
649
 
650
- var version = "6.6.2";
650
+ var version = "6.7.0";
651
651
 
652
- async function writeDefaultTsconfig(tsConfigPath) {
652
+ async function writeDefaultTsconfig(tsConfigPath, useTsGo) {
653
653
  await fs.promises.writeFile(tsConfigPath, JSON.stringify(DEFAULT_TS_CONFIG, null, 2), 'utf-8');
654
- logger.log(`Detected using TypeScript but tsconfig.json is missing, created a ${pc.blue('tsconfig.json')} for you.`);
654
+ const compilerName = 'TypeScript';
655
+ logger.log(`Detected using ${compilerName} but tsconfig.json is missing, created a ${pc.blue('tsconfig.json')} for you.`);
655
656
  }
656
657
 
657
658
  // ./index -> default
@@ -1082,7 +1083,7 @@ Options:
1082
1083
  -o, --output <file> specify output filename
1083
1084
  -f, --format <format> type of output (esm, amd, cjs, iife, umd, system), default: esm
1084
1085
  -h, --help output usage information
1085
-
1086
+
1086
1087
  --external <mod> specify an external dependency, separate by comma
1087
1088
  --no-external do not bundle external dependencies
1088
1089
  --no-clean do not clean dist folder before building, default: false
@@ -1095,6 +1096,7 @@ Options:
1095
1096
  --tsconfig path to tsconfig file, default: tsconfig.json
1096
1097
  --dts-bundle bundle type declaration files, default: false
1097
1098
  --success <cmd> run command after build success
1099
+ --tsgo use TypeScript-Go compiler for type generation
1098
1100
  `;
1099
1101
  function help() {
1100
1102
  logger.log(helpMessage);
@@ -1172,6 +1174,9 @@ async function parseCliArgs(argv) {
1172
1174
  }).option('success', {
1173
1175
  type: 'string',
1174
1176
  description: 'run command after build success'
1177
+ }).option('tsgo', {
1178
+ type: 'boolean',
1179
+ description: 'use TypeScript-Go compiler for type generation'
1175
1180
  }).command('prepare', 'auto configure package.json exports for building', ()=>{}, (argv)=>{
1176
1181
  return prepare(argv.cwd || process.cwd());
1177
1182
  }).command('lint', 'lint package.json', ()=>{}, (argv)=>{
@@ -1207,7 +1212,8 @@ async function parseCliArgs(argv) {
1207
1212
  clean: args['clean'] !== false,
1208
1213
  env: args['env'],
1209
1214
  tsconfig: args['tsconfig'],
1210
- onSuccess: args['success']
1215
+ onSuccess: args['success'],
1216
+ tsgo: args['tsgo']
1211
1217
  };
1212
1218
  // When minify is enabled, sourcemap should be enabled by default, unless explicitly opted out
1213
1219
  if (parsedArgs.minify && typeof args['sourcemap'] === 'undefined') {
@@ -1236,9 +1242,22 @@ async function run(args) {
1236
1242
  env: (env == null ? void 0 : env.split(',')) || [],
1237
1243
  clean,
1238
1244
  tsconfig,
1239
- onSuccess
1245
+ onSuccess,
1246
+ tsgo: args.tsgo
1240
1247
  };
1241
1248
  const cliEntry = source ? path__default.default.resolve(cwd, source) : '';
1249
+ // Check if ts-go is available when requested (before any build operations)
1250
+ if (args.tsgo) {
1251
+ try {
1252
+ require.resolve('@typescript/native-preview', {
1253
+ paths: [
1254
+ cwd
1255
+ ]
1256
+ });
1257
+ } catch {
1258
+ exit('--tsgo flag was specified but @typescript/native-preview is not installed. Please install it as a dev dependency: pnpm add -D @typescript/native-preview');
1259
+ }
1260
+ }
1242
1261
  // lint package by default
1243
1262
  await lint(cwd);
1244
1263
  const spinnerInstance = process.stdout.isTTY ? nanospinner.createSpinner('Building...\n\n', {
@@ -1389,4 +1408,7 @@ function logError(err) {
1389
1408
  const error = normalizeError(err);
1390
1409
  logger.error(error);
1391
1410
  }
1392
- main().catch(exit);
1411
+ main().catch((error)=>{
1412
+ logError(error);
1413
+ process.exit(1);
1414
+ });
package/dist/index.d.ts CHANGED
@@ -22,6 +22,7 @@ type BundleConfig = {
22
22
  clean?: boolean;
23
23
  tsconfig?: string;
24
24
  onSuccess?: string | (() => void | Promise<void>);
25
+ tsgo?: boolean;
25
26
  _callbacks?: {
26
27
  onBuildStart?: (state: any) => void;
27
28
  onBuildEnd?: (assetJobs: any) => void;
package/dist/index.js CHANGED
@@ -299,7 +299,7 @@ function validateEntryFiles(entryFiles) {
299
299
 
300
300
  function exit(err) {
301
301
  logger.error(err);
302
- process.exit(1);
302
+ throw typeof err === 'string' ? new Error(err) : err;
303
303
  }
304
304
  async function getPackageMeta(cwd) {
305
305
  const pkgFilePath = path__default.default.resolve(cwd, 'package.json');
@@ -1034,7 +1034,42 @@ const memoizeByKey = (fn)=>{
1034
1034
  const memoize = (fn)=>createMemoize(fn);
1035
1035
 
1036
1036
  let hasLoggedTsWarning = false;
1037
- function resolveTypescript(cwd) {
1037
+ let hasLoggedTsGoWarning = false;
1038
+ function resolveTsGo(cwd) {
1039
+ let tsgo;
1040
+ const m = new module$1.Module('', undefined);
1041
+ m.paths = module$1.Module._nodeModulePaths(cwd);
1042
+ try {
1043
+ // Bun does not yet support the `Module` class properly.
1044
+ if (typeof (m == null ? void 0 : m.require) === 'undefined') {
1045
+ const tsgoPath = require.resolve('@typescript/native-preview', {
1046
+ paths: [
1047
+ cwd
1048
+ ]
1049
+ });
1050
+ tsgo = require(tsgoPath);
1051
+ } else {
1052
+ tsgo = m.require('@typescript/native-preview');
1053
+ }
1054
+ // ts-go exports the TypeScript API as default or named export
1055
+ return tsgo.default || tsgo;
1056
+ } catch (e) {
1057
+ if (!hasLoggedTsGoWarning) {
1058
+ hasLoggedTsGoWarning = true;
1059
+ logger.warn('Could not load TypeScript-Go compiler. Make sure `@typescript/native-preview` is installed as a dev dependency.');
1060
+ }
1061
+ return null;
1062
+ }
1063
+ }
1064
+ function resolveTypescript(cwd, useTsGo) {
1065
+ if (useTsGo) {
1066
+ const tsgo = resolveTsGo(cwd);
1067
+ if (tsgo) {
1068
+ return tsgo;
1069
+ }
1070
+ // Error if ts-go is requested but not available
1071
+ exit('TypeScript-Go compiler not found. Please install @typescript/native-preview as a dev dependency: pnpm add -D @typescript/native-preview');
1072
+ }
1038
1073
  let ts;
1039
1074
  const m = new module$1.Module('', undefined);
1040
1075
  m.paths = module$1.Module._nodeModulePaths(cwd);
@@ -1064,11 +1099,11 @@ const resolveTsConfigPath = memoize((cwd, tsconfigFileName = 'tsconfig.json')=>{
1064
1099
  tsConfigPath = path.resolve(cwd, tsconfigFileName);
1065
1100
  return fileExists(tsConfigPath) ? tsConfigPath : undefined;
1066
1101
  });
1067
- function resolveTsConfigHandler(cwd, tsConfigPath) {
1102
+ function resolveTsConfigHandler(cwd, tsConfigPath, useTsGo) {
1068
1103
  let tsCompilerOptions = {};
1069
1104
  if (tsConfigPath) {
1070
1105
  // Use the original ts handler to avoid memory leak
1071
- const ts = resolveTypescript(cwd);
1106
+ const ts = resolveTypescript(cwd, useTsGo);
1072
1107
  const basePath = tsConfigPath ? path.dirname(tsConfigPath) : cwd;
1073
1108
  const tsconfigJSON = ts.readConfigFile(tsConfigPath, ts.sys.readFile).config;
1074
1109
  tsCompilerOptions = ts.parseJsonConfigFileContent(tsconfigJSON, ts.sys, basePath).options;
@@ -1080,15 +1115,28 @@ function resolveTsConfigHandler(cwd, tsConfigPath) {
1080
1115
  tsConfigPath
1081
1116
  };
1082
1117
  }
1083
- const resolveTsConfig = memoize(resolveTsConfigHandler);
1084
- async function convertCompilerOptions(cwd, json) {
1118
+ // Note: We can't memoize resolveTsConfigHandler directly with useTsGo parameter
1119
+ // because memoize doesn't handle optional parameters well. Instead, we'll create
1120
+ // a wrapper that handles the memoization per useTsGo value.
1121
+ const resolveTsConfigCache = new Map();
1122
+ function resolveTsConfig(cwd, tsConfigPath, useTsGo) {
1123
+ const cacheKey = `${cwd}:${tsConfigPath || ''}:${useTsGo ? 'tsgo' : 'ts'}`;
1124
+ if (resolveTsConfigCache.has(cacheKey)) {
1125
+ return resolveTsConfigCache.get(cacheKey);
1126
+ }
1127
+ const result = resolveTsConfigHandler(cwd, tsConfigPath, useTsGo);
1128
+ resolveTsConfigCache.set(cacheKey, result);
1129
+ return result;
1130
+ }
1131
+ async function convertCompilerOptions(cwd, json, useTsGo) {
1085
1132
  // Use the original ts handler to avoid memory leak
1086
- const ts = resolveTypescript(cwd);
1133
+ const ts = resolveTypescript(cwd, useTsGo);
1087
1134
  return ts.convertCompilerOptionsFromJson(json, './');
1088
1135
  }
1089
- async function writeDefaultTsconfig(tsConfigPath) {
1136
+ async function writeDefaultTsconfig(tsConfigPath, useTsGo) {
1090
1137
  await fs.promises.writeFile(tsConfigPath, JSON.stringify(DEFAULT_TS_CONFIG, null, 2), 'utf-8');
1091
- logger.log(`Detected using TypeScript but tsconfig.json is missing, created a ${pc.blue('tsconfig.json')} for you.`);
1138
+ const compilerName = useTsGo ? 'TypeScript-Go' : 'TypeScript';
1139
+ logger.log(`Detected using ${compilerName} but tsconfig.json is missing, created a ${pc.blue('tsconfig.json')} for you.`);
1092
1140
  }
1093
1141
 
1094
1142
  /**
@@ -1468,7 +1516,7 @@ const swcMinifyOptions = {
1468
1516
  toplevel: true
1469
1517
  }
1470
1518
  };
1471
- async function createDtsPlugin(tsCompilerOptions, tsConfigPath, respectExternal, cwd) {
1519
+ async function createDtsPlugin(tsCompilerOptions, tsConfigPath, respectExternal, cwd, useTsGo) {
1472
1520
  const enableIncrementalWithoutBuildInfo = (tsCompilerOptions == null ? void 0 : tsCompilerOptions.incremental) && !(tsCompilerOptions == null ? void 0 : tsCompilerOptions.tsBuildInfoFile);
1473
1521
  const incrementalOptions = enableIncrementalWithoutBuildInfo ? {
1474
1522
  incremental: false
@@ -1495,7 +1543,33 @@ async function createDtsPlugin(tsCompilerOptions, tsConfigPath, respectExternal,
1495
1543
  ...incrementalOptions,
1496
1544
  // error TS6379: Composite projects may not disable incremental compilation.
1497
1545
  ...compositeOptions
1498
- });
1546
+ }, useTsGo);
1547
+ // If useTsGo is enabled, we need to make ts-go available to rollup-plugin-dts
1548
+ // rollup-plugin-dts uses require('typescript') internally, so we need to
1549
+ // temporarily override the module cache to use ts-go
1550
+ if (useTsGo) {
1551
+ const tsgo = resolveTsGo(cwd);
1552
+ if (tsgo) {
1553
+ try {
1554
+ // First, try to resolve typescript to get its path
1555
+ const tsPath = require.resolve('typescript', {
1556
+ paths: [
1557
+ cwd
1558
+ ]
1559
+ });
1560
+ // Make ts-go available as 'typescript' for rollup-plugin-dts
1561
+ // This overrides the module cache so rollup-plugin-dts will use ts-go
1562
+ require.cache[tsPath] = {
1563
+ id: tsPath,
1564
+ exports: tsgo,
1565
+ loaded: true
1566
+ };
1567
+ } catch (e) {
1568
+ // If typescript cannot be resolved, we can't override it
1569
+ // rollup-plugin-dts will try to require it and may fail
1570
+ }
1571
+ }
1572
+ }
1499
1573
  const dtsPlugin = require('rollup-plugin-dts').default({
1500
1574
  tsconfig: tsConfigPath,
1501
1575
  compilerOptions: overrideResolvedTsOptions,
@@ -1589,8 +1663,8 @@ async function buildInputConfig(entry, bundleConfig, exportCondition, buildConte
1589
1663
  // Each process should be unique
1590
1664
  // Each package build should be unique
1591
1665
  // Composing above factors into a unique cache key to retrieve the memoized dts plugin with tsconfigs
1592
- const uniqueProcessId = 'dts-plugin:' + process.pid + tsConfigPath;
1593
- const dtsPlugin = await memoizeDtsPluginByKey(uniqueProcessId)(tsCompilerOptions, tsConfigPath, bundleConfig.dts && bundleConfig.dts.respectExternal, cwd);
1666
+ const uniqueProcessId = 'dts-plugin:' + process.pid + tsConfigPath + (buildContext.useTsGo ? ':tsgo' : '');
1667
+ const dtsPlugin = await memoizeDtsPluginByKey(uniqueProcessId)(tsCompilerOptions, tsConfigPath, bundleConfig.dts && bundleConfig.dts.respectExternal, cwd, buildContext.useTsGo);
1594
1668
  typesPlugins.push(dtsPlugin);
1595
1669
  }
1596
1670
  const plugins = (dts ? typesPlugins : [
@@ -1987,8 +2061,17 @@ async function bundle(cliEntryPath, { cwd: _cwd, onSuccess, ...options } = {}) {
1987
2061
  // Original input file path, client path might change later
1988
2062
  const inputFile = cliEntryPath;
1989
2063
  const isFromCli = Boolean(cliEntryPath);
2064
+ const useTsGo = options.tsgo === true;
2065
+ // Check if ts-go is available when requested (before resolving tsconfig)
2066
+ let tsgoInstance = null;
2067
+ if (useTsGo) {
2068
+ tsgoInstance = resolveTsGo(cwd);
2069
+ if (!tsgoInstance) {
2070
+ exit('--tsgo flag was specified but @typescript/native-preview is not installed. Please install it as a dev dependency: pnpm add -D @typescript/native-preview');
2071
+ }
2072
+ }
1990
2073
  const tsConfigPath = resolveTsConfigPath(cwd, options.tsconfig);
1991
- let tsConfig = resolveTsConfig(cwd, tsConfigPath);
2074
+ let tsConfig = resolveTsConfig(cwd, tsConfigPath, useTsGo);
1992
2075
  let hasTsConfig = Boolean(tsConfig == null ? void 0 : tsConfig.tsConfigPath);
1993
2076
  const defaultTsOptions = {
1994
2077
  tsConfigPath: tsConfig == null ? void 0 : tsConfig.tsConfigPath,
@@ -2058,7 +2141,7 @@ async function bundle(cliEntryPath, { cwd: _cwd, onSuccess, ...options } = {}) {
2058
2141
  // Otherwise, use the existing one.
2059
2142
  const defaultTsConfigPath = path.resolve(cwd, 'tsconfig.json');
2060
2143
  if (!fileExists(defaultTsConfigPath)) {
2061
- await writeDefaultTsconfig(defaultTsConfigPath);
2144
+ await writeDefaultTsconfig(defaultTsConfigPath, useTsGo);
2062
2145
  }
2063
2146
  defaultTsOptions.tsConfigPath = defaultTsConfigPath;
2064
2147
  hasTsConfig = true;
@@ -2070,12 +2153,15 @@ async function bundle(cliEntryPath, { cwd: _cwd, onSuccess, ...options } = {}) {
2070
2153
  const outputState = createOutputState({
2071
2154
  entries
2072
2155
  });
2156
+ // Use ts-go if it was successfully resolved earlier
2157
+ const useTsGoInContext = Boolean(useTsGo && hasTsConfig && tsgoInstance);
2073
2158
  const buildContext = {
2074
2159
  entries,
2075
2160
  pkg,
2076
2161
  cwd,
2077
2162
  tsOptions: defaultTsOptions,
2078
2163
  useTypeScript: hasTsConfig,
2164
+ useTsGo: useTsGoInContext,
2079
2165
  browserslistConfig,
2080
2166
  pluginContext: {
2081
2167
  outputState,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunchee",
3
- "version": "6.6.2",
3
+ "version": "6.7.0",
4
4
  "description": "zero config bundler for js/ts/jsx libraries",
5
5
  "bin": "./dist/bin/cli.js",
6
6
  "main": "./dist/index.js",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "license": "MIT",
39
39
  "dependencies": {
40
- "@rollup/plugin-commonjs": "^28.0.6",
40
+ "@rollup/plugin-commonjs": "^29.0.0",
41
41
  "@rollup/plugin-json": "^6.1.0",
42
42
  "@rollup/plugin-node-resolve": "^16.0.1",
43
43
  "@rollup/plugin-replace": "^6.0.2",
@@ -51,7 +51,7 @@
51
51
  "picomatch": "^4.0.2",
52
52
  "pretty-bytes": "^5.6.0",
53
53
  "rollup": "^4.52.4",
54
- "rollup-plugin-dts": "^6.2.3",
54
+ "rollup-plugin-dts": "^6.3.0",
55
55
  "rollup-plugin-swc3": "^0.11.1",
56
56
  "rollup-preserve-directives": "^1.1.3",
57
57
  "tinyglobby": "^0.2.14",
@@ -59,7 +59,8 @@
59
59
  "yargs": "^17.7.2"
60
60
  },
61
61
  "peerDependencies": {
62
- "typescript": "^4.1 || ^5.0"
62
+ "typescript": "^4.1 || ^5.0",
63
+ "@typescript/native-preview": "*"
63
64
  },
64
65
  "peerDependenciesMeta": {
65
66
  "typescript": {
@@ -67,6 +68,9 @@
67
68
  },
68
69
  "@swc/helpers": {
69
70
  "optional": true
71
+ },
72
+ "@typescript/native-preview": {
73
+ "optional": true
70
74
  }
71
75
  },
72
76
  "devDependencies": {
@@ -79,16 +83,17 @@
79
83
  "@types/picomatch": "^3.0.1",
80
84
  "@types/react": "^19.0.9",
81
85
  "@types/yargs": "^17.0.33",
86
+ "@typescript/native-preview": "*",
82
87
  "bunchee": "link:./",
83
88
  "cross-env": "^7.0.3",
84
89
  "husky": "^9.0.11",
85
90
  "lint-staged": "^15.2.2",
86
- "next": "16.0.0-canary.1",
91
+ "next": "16.0.10",
87
92
  "picocolors": "^1.0.0",
88
93
  "postcss": "^8.5.4",
89
94
  "prettier": "3.4.2",
90
- "react": "^19.0.0",
91
- "react-dom": "^19.0.0",
95
+ "react": "^19.2.1",
96
+ "react-dom": "^19.2.1",
92
97
  "tailwindcss": "^4.1.8",
93
98
  "typescript": "^5.9.2",
94
99
  "vitest": "^3.0.4"
@@ -100,7 +105,7 @@
100
105
  "test": "vitest run",
101
106
  "test:update": "TEST_UPDATE_SNAPSHOT=1 pnpm test",
102
107
  "test:post": "cross-env POST_BUILD=1 pnpm test test/compile.test.ts test/integration.test.ts",
103
- "docs:dev": "next dev docs",
108
+ "site": "next dev docs",
104
109
  "docs:build": "next build docs",
105
110
  "clean": "rm -rf ./dist",
106
111
  "new-test": "node ./scripts/new-test.js",