tsdown 0.9.8 → 0.10.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.
@@ -1,4 +1,4 @@
1
- import { UserConfig, UserConfigFn } from "./options.d-BXikSiux.js";
1
+ import { UserConfig, UserConfigFn } from "./options.d-C1wrHXGf.js";
2
2
 
3
3
  //#region src/config.d.ts
4
4
  /**
package/dist/config.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { UserConfig, UserConfigFn } from "./options.d-BXikSiux.js";
2
- import { defineConfig$1 as defineConfig } from "./config.d-DI49UQhk.js";
3
-
1
+ import { UserConfig, UserConfigFn } from "./options.d-C1wrHXGf.js";
2
+ import { defineConfig$1 as defineConfig } from "./config.d-DpTGFaWV.js";
4
3
  export { UserConfig, UserConfigFn, defineConfig };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { BuildContext, Options, ResolvedOptions, TsdownHooks, UserConfig } from "./options.d-BXikSiux.js";
2
- import { defineConfig$1 as defineConfig } from "./config.d-DI49UQhk.js";
1
+ import { BuildContext, Options, ResolvedOptions, TsdownHooks, UserConfig } from "./options.d-C1wrHXGf.js";
2
+ import { defineConfig$1 as defineConfig } from "./config.d-DpTGFaWV.js";
3
3
  import { ConsolaInstance } from "consola";
4
4
 
5
5
  //#region src/utils/logger.d.ts
@@ -15,12 +15,16 @@ declare const logger: ConsolaInstance;
15
15
  */
16
16
  declare function build(userOptions?: Options): Promise<void>;
17
17
  declare const pkgRoot: string;
18
+
18
19
  /**
19
20
  * Build a single configuration, without watch and shortcuts features.
20
21
  *
22
+ * Internal API, not for public use
23
+ *
24
+ * @private
21
25
  * @param config Resolved options
22
26
  */
23
- declare function buildSingle(config: ResolvedOptions): Promise<(() => Promise<void>) | undefined>;
27
+ declare function buildSingle(config: ResolvedOptions, clean: () => Promise<void>): Promise<(() => Promise<void>) | undefined>;
24
28
 
25
29
  //#endregion
26
30
  export { BuildContext, Options, TsdownHooks, UserConfig, build, buildSingle, defineConfig, logger, pkgRoot };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { defineConfig } from "./config-CpIe1Ud_.js";
2
- import { ExternalPlugin, ReportPlugin, ShebangPlugin, fsExists, fsRemove, getPackageType, lowestCommonAncestor, normalizeFormat, prettyFormat, readPackageJson } from "./plugins-BcuTSrGE.js";
2
+ import { ExternalPlugin, ReportPlugin, ShebangPlugin, fsExists, fsRemove, getPackageType, lowestCommonAncestor, normalizeFormat, prettyFormat, readPackageJson } from "./plugins-DX6CtlR1.js";
3
3
  import { debounce, logger, resolveComma, setSilent, toArray } from "./general-C06aMSSY.js";
4
4
  import path from "node:path";
5
5
  import process from "node:process";
@@ -9,27 +9,38 @@ import Debug from "debug";
9
9
  import { build as build$1 } from "rolldown";
10
10
  import { transformPlugin } from "rolldown/experimental";
11
11
  import { exec } from "tinyexec";
12
- import { readdir, stat } from "node:fs/promises";
13
12
  import { glob } from "tinyglobby";
13
+ import { stat } from "node:fs/promises";
14
14
  import { createHooks } from "hookable";
15
+ import LightningCSS from "unplugin-lightningcss/rolldown";
15
16
  import readline from "node:readline";
16
17
  import { loadConfig } from "unconfig";
17
18
  import { up } from "empathic/find";
18
19
 
19
20
  //#region src/features/clean.ts
20
- const debug$2 = Debug("tsdown:clean");
21
- async function cleanOutDir(cwd, patterns) {
22
- const files = [];
23
- if (await fsExists(cwd)) files.push(...(await readdir(cwd)).map((file) => path.resolve(cwd, file)));
24
- if (patterns.length) files.push(...await glob(patterns, {
25
- cwd,
26
- absolute: true
27
- }));
28
- logger.info("Cleaning output folder");
29
- for (const file of files) {
30
- debug$2("Removing", file);
31
- await fsRemove(file);
21
+ const debug$3 = Debug("tsdown:clean");
22
+ async function cleanOutDir(configs) {
23
+ const removes = new Set();
24
+ for (const config of configs) {
25
+ if (!config.clean.length) continue;
26
+ const files = await glob(config.clean, {
27
+ cwd: config.cwd,
28
+ absolute: true
29
+ });
30
+ for (const file of files) removes.add(file);
32
31
  }
32
+ if (!removes.size) return;
33
+ logger.info("Cleaning %d files", removes.size);
34
+ await Promise.all([...removes].map(async (file) => {
35
+ debug$3("Removing", file);
36
+ await fsRemove(file);
37
+ }));
38
+ debug$3("Removed %d files", removes.size);
39
+ }
40
+ function resolveClean(clean, outDir) {
41
+ if (clean === true) clean = [outDir];
42
+ else if (!clean) clean = [];
43
+ return clean;
33
44
  }
34
45
 
35
46
  //#endregion
@@ -49,6 +60,55 @@ async function createHooks$1(options, pkg) {
49
60
  };
50
61
  }
51
62
 
63
+ //#endregion
64
+ //#region src/utils/lightningcss.ts
65
+ /**
66
+ * Converts esbuild target [^1] (which is also used by Rolldown [^2]) to Lightning CSS targets [^3].
67
+ *
68
+ * [^1]: https://esbuild.github.io/api/#target
69
+ * [^2]: https://github.com/rolldown/rolldown/blob/v1.0.0-beta.8/packages/rolldown/src/binding.d.ts#L1429-L1431
70
+ * [^3]: https://lightningcss.dev/transpilation.html
71
+ */
72
+ function esbuildTargetToLightningCSS(target) {
73
+ let targets;
74
+ const targetString = target.join(" ").toLowerCase();
75
+ const matches = [...targetString.matchAll(TARGET_REGEX)];
76
+ for (const match of matches) {
77
+ const name = match[1];
78
+ const browser = ESBUILD_LIGHTNINGCSS_MAPPING[name];
79
+ if (!browser) continue;
80
+ const version = match[2];
81
+ const versionInt = parseVersion(version);
82
+ if (versionInt == null) continue;
83
+ targets = targets || {};
84
+ targets[browser] = versionInt;
85
+ }
86
+ return targets;
87
+ }
88
+ const TARGET_REGEX = /([a-z]+)(\d+(?:\.\d+)*)/g;
89
+ const ESBUILD_LIGHTNINGCSS_MAPPING = {
90
+ chrome: "chrome",
91
+ edge: "edge",
92
+ firefox: "firefox",
93
+ ie: "ie",
94
+ ios: "ios_saf",
95
+ opera: "opera",
96
+ safari: "safari"
97
+ };
98
+ function parseVersion(version) {
99
+ const [major, minor = 0, patch = 0] = version.split("-")[0].split(".").map((v) => Number.parseInt(v, 10));
100
+ if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch)) return null;
101
+ return major << 16 | minor << 8 | patch;
102
+ }
103
+
104
+ //#endregion
105
+ //#region src/features/lightningcss.ts
106
+ function LightningCSSPlugin(options) {
107
+ const targets = options.target && esbuildTargetToLightningCSS(options.target);
108
+ if (!targets) return;
109
+ return LightningCSS({ options: { targets } });
110
+ }
111
+
52
112
  //#endregion
53
113
  //#region src/features/output.ts
54
114
  function resolveJsOutputExtension(packageType, format, fixedExtension) {
@@ -58,7 +118,7 @@ function resolveJsOutputExtension(packageType, format, fixedExtension) {
58
118
  default: return "js";
59
119
  }
60
120
  }
61
- function resolveChunkFilename(pkg, inputOptions, format, { outExtensions, fixedExtension }) {
121
+ function resolveChunkFilename({ outExtensions, fixedExtension, pkg }, inputOptions, format) {
62
122
  const packageType = getPackageType(pkg);
63
123
  let jsExtension;
64
124
  let dtsExtension;
@@ -83,13 +143,13 @@ function createChunkFilename(basename, jsExtension, dtsExtension) {
83
143
 
84
144
  //#endregion
85
145
  //#region src/features/publint.ts
86
- const debug$1 = Debug("tsdown:publint");
146
+ const debug$2 = Debug("tsdown:publint");
87
147
  async function publint(pkg) {
88
- debug$1("Running publint");
148
+ debug$2("Running publint");
89
149
  const { publint: publint$1 } = await import("publint");
90
150
  const { formatMessage } = await import("publint/utils");
91
151
  const { messages } = await publint$1();
92
- debug$1("Found %d issues", messages.length);
152
+ debug$2("Found %d issues", messages.length);
93
153
  if (!messages.length) logger.success("No publint issues found");
94
154
  let hasError = false;
95
155
  for (const message of messages) {
@@ -103,7 +163,7 @@ async function publint(pkg) {
103
163
  logger[logType](formattedMessage);
104
164
  }
105
165
  if (hasError) {
106
- debug$1("Found errors, setting exit code to 1");
166
+ debug$2("Found errors, setting exit code to 1");
107
167
  process.exitCode = 1;
108
168
  }
109
169
  }
@@ -225,43 +285,53 @@ async function toObjectEntry(entry, cwd) {
225
285
  }
226
286
 
227
287
  //#endregion
228
- //#region src/utils/tsconfig.ts
288
+ //#region src/features/tsconfig.ts
229
289
  function findTsconfig(cwd, name = "tsconfig.json") {
230
290
  return up(name, { cwd }) || false;
231
291
  }
292
+ async function resolveTsconfig(tsconfig, cwd) {
293
+ if (tsconfig !== false) {
294
+ if (tsconfig === true || tsconfig == null) {
295
+ const isSet = tsconfig;
296
+ tsconfig = findTsconfig(cwd);
297
+ if (isSet && !tsconfig) logger.warn(`No tsconfig found in \`${cwd}\``);
298
+ } else {
299
+ const tsconfigPath = path.resolve(cwd, tsconfig);
300
+ if (await fsExists(tsconfigPath)) tsconfig = tsconfigPath;
301
+ else if (tsconfig.includes("\\") || tsconfig.includes("/")) {
302
+ logger.warn(`tsconfig \`${tsconfig}\` doesn't exist`);
303
+ tsconfig = false;
304
+ } else {
305
+ tsconfig = findTsconfig(cwd, tsconfig);
306
+ if (!tsconfig) logger.warn(`No \`${tsconfig}\` found in \`${cwd}\``);
307
+ }
308
+ }
309
+ if (tsconfig) logger.info(`Using tsconfig: ${underline(path.relative(cwd, tsconfig))}`);
310
+ }
311
+ return tsconfig;
312
+ }
232
313
 
233
314
  //#endregion
234
315
  //#region src/options.ts
316
+ const debug$1 = Debug("tsdown:options");
235
317
  async function resolveOptions(options) {
236
318
  const { configs: userConfigs, file, cwd } = await loadConfigFile(options);
237
319
  if (userConfigs.length === 0) userConfigs.push({});
320
+ debug$1("Loaded config file %s from %s", file, cwd);
321
+ debug$1("User configs %o", userConfigs);
238
322
  const configs = await Promise.all(userConfigs.map(async (subConfig) => {
239
323
  const subOptions = {
240
324
  ...subConfig,
241
325
  ...options
242
326
  };
243
- let { entry, format = ["es"], plugins = [], clean = false, silent = false, treeshake = true, platform = "node", outDir = "dist", sourcemap = false, dts = false, unused = false, watch = false, shims = false, skipNodeModulesBundle = false, publint: publint$1 = false, fromVite, alias, tsconfig, report = true, target, env = {} } = subOptions;
327
+ let { entry, format = ["es"], plugins = [], clean = true, silent = false, treeshake = true, platform = "node", outDir = "dist", sourcemap = false, dts, unused = false, watch = false, shims = false, skipNodeModulesBundle = false, publint: publint$1 = false, fromVite, alias, tsconfig, report = true, target, env = {} } = subOptions;
328
+ outDir = path.resolve(outDir);
244
329
  entry = await resolveEntry(entry, cwd);
245
- if (clean === true) clean = [];
330
+ clean = resolveClean(clean, outDir);
331
+ const pkg = await readPackageJson(cwd);
332
+ if (dts == null) dts = !!(pkg?.types || pkg?.typings);
333
+ tsconfig = await resolveTsconfig(tsconfig, cwd);
246
334
  if (publint$1 === true) publint$1 = {};
247
- if (tsconfig !== false) {
248
- if (tsconfig === true || tsconfig == null) {
249
- const isSet = tsconfig;
250
- tsconfig = findTsconfig(cwd);
251
- if (isSet && !tsconfig) logger.warn(`No tsconfig found in \`${cwd}\``);
252
- } else {
253
- const tsconfigPath = path.resolve(cwd, tsconfig);
254
- if (await fsExists(tsconfigPath)) tsconfig = tsconfigPath;
255
- else if (tsconfig.includes("\\") || tsconfig.includes("/")) {
256
- logger.warn(`tsconfig \`${tsconfig}\` doesn't exist`);
257
- tsconfig = false;
258
- } else {
259
- tsconfig = findTsconfig(cwd, tsconfig);
260
- if (!tsconfig) logger.warn(`No \`${tsconfig}\` found in \`${cwd}\``);
261
- }
262
- }
263
- if (tsconfig) logger.info(`Using tsconfig: ${underline(path.relative(cwd, tsconfig))}`);
264
- }
265
335
  if (fromVite) {
266
336
  const viteUserConfig = await loadViteConfig(fromVite === true ? "vite" : fromVite, cwd);
267
337
  if (viteUserConfig) {
@@ -277,7 +347,7 @@ async function resolveOptions(options) {
277
347
  plugins,
278
348
  format: normalizeFormat(format),
279
349
  target: target ? resolveComma(toArray(target)) : void 0,
280
- outDir: path.resolve(outDir),
350
+ outDir,
281
351
  clean,
282
352
  silent,
283
353
  treeshake,
@@ -293,7 +363,8 @@ async function resolveOptions(options) {
293
363
  alias,
294
364
  tsconfig,
295
365
  cwd,
296
- env
366
+ env,
367
+ pkg
297
368
  };
298
369
  return config;
299
370
  }));
@@ -398,7 +469,7 @@ async function mergeUserOptions(defaults, user, args) {
398
469
 
399
470
  //#endregion
400
471
  //#region src/index.ts
401
- const debug = Debug("tsdown:config");
472
+ const debug = Debug("tsdown:main");
402
473
  /**
403
474
  * Build with tsdown.
404
475
  */
@@ -412,7 +483,12 @@ async function build(userOptions = {}) {
412
483
  debug("using resolved config: %O", config);
413
484
  });
414
485
  } else debug("No config file found");
415
- const rebuilds = await Promise.all(configs.map(buildSingle));
486
+ let cleanPromise;
487
+ const clean = () => {
488
+ if (cleanPromise) return cleanPromise;
489
+ return cleanPromise = cleanOutDir(configs);
490
+ };
491
+ const rebuilds = await Promise.all(configs.map((options) => buildSingle(options, clean)));
416
492
  const cleanCbs = [];
417
493
  for (const [i, config] of configs.entries()) {
418
494
  const rebuild = rebuilds[i];
@@ -422,7 +498,7 @@ async function build(userOptions = {}) {
422
498
  }
423
499
  if (cleanCbs.length) shortcuts(restart);
424
500
  async function restart() {
425
- for (const clean of cleanCbs) await clean();
501
+ for (const clean$1 of cleanCbs) await clean$1();
426
502
  build(userOptions);
427
503
  }
428
504
  }
@@ -431,12 +507,14 @@ const pkgRoot = path.resolve(dirname$1, "..");
431
507
  /**
432
508
  * Build a single configuration, without watch and shortcuts features.
433
509
  *
510
+ * Internal API, not for public use
511
+ *
512
+ * @private
434
513
  * @param config Resolved options
435
514
  */
436
- async function buildSingle(config) {
437
- const { outDir, format: formats, clean, dts, watch, onSuccess } = config;
515
+ async function buildSingle(config, clean) {
516
+ const { format: formats, dts, watch, onSuccess } = config;
438
517
  let onSuccessCleanup;
439
- const pkg = await readPackageJson(process.cwd());
440
518
  const { hooks, context } = await createHooks$1(config);
441
519
  await rebuild(true);
442
520
  if (watch) return () => rebuild();
@@ -444,19 +522,19 @@ async function buildSingle(config) {
444
522
  const startTime = performance.now();
445
523
  await hooks.callHook("build:prepare", context);
446
524
  onSuccessCleanup?.();
447
- if (clean) await cleanOutDir(outDir, clean);
525
+ await clean();
448
526
  let hasErrors = false;
449
527
  await Promise.all(formats.map(async (format) => {
450
528
  try {
451
529
  const formatLabel = prettyFormat(format);
452
530
  logger.info(formatLabel, "Build start");
453
- const buildOptions = await getBuildOptions(config, pkg, format);
531
+ const buildOptions = await getBuildOptions(config, format);
454
532
  await hooks.callHook("build:before", {
455
533
  ...context,
456
534
  buildOptions
457
535
  });
458
536
  await build$1(buildOptions);
459
- if (format === "cjs" && dts) await build$1(await getBuildOptions(config, pkg, format, true));
537
+ if (format === "cjs" && dts) await build$1(await getBuildOptions(config, format, true));
460
538
  } catch (error) {
461
539
  if (watch) {
462
540
  logger.error(error);
@@ -468,7 +546,7 @@ async function buildSingle(config) {
468
546
  }));
469
547
  if (hasErrors) return;
470
548
  await hooks.callHook("build:done", context);
471
- if (config.publint) if (pkg) await publint(pkg);
549
+ if (config.publint) if (config.pkg) await publint(config.pkg);
472
550
  else logger.warn("publint is enabled but package.json is not found");
473
551
  logger.success(`${first ? "Build" : "Rebuild"} complete in ${green(`${Math.round(performance.now() - startTime)}ms`)}`);
474
552
  if (typeof onSuccess === "string") {
@@ -483,10 +561,10 @@ async function buildSingle(config) {
483
561
  } else await onSuccess?.(config);
484
562
  }
485
563
  }
486
- async function getBuildOptions(config, pkg, format, cjsDts) {
564
+ async function getBuildOptions(config, format, cjsDts) {
487
565
  const { entry, external, plugins: userPlugins, outDir, platform, alias, treeshake, sourcemap, dts, minify, unused, target, define, shims, tsconfig, cwd, report, env } = config;
488
566
  const plugins = [];
489
- if (pkg || config.skipNodeModulesBundle) plugins.push(ExternalPlugin(config, pkg));
567
+ if (config.pkg || config.skipNodeModulesBundle) plugins.push(ExternalPlugin(config));
490
568
  if (dts) {
491
569
  const { dts: dtsPlugin } = await import("rolldown-plugin-dts");
492
570
  const options = {
@@ -511,7 +589,12 @@ async function getBuildOptions(config, pkg, format, cjsDts) {
511
589
  }));
512
590
  plugins.push(ShebangPlugin(cwd));
513
591
  }
514
- if (report) plugins.push(ReportPlugin(report, cwd, cjsDts));
592
+ if (report && logger.level >= 3) plugins.push(ReportPlugin(report, cwd, cjsDts));
593
+ if (target) plugins.push(
594
+ // Use Lightning CSS to handle CSS input. This is a temporary solution
595
+ // until Rolldown supports CSS syntax lowering natively.
596
+ LightningCSSPlugin({ target })
597
+ );
515
598
  plugins.push(userPlugins);
516
599
  const inputOptions = await mergeUserOptions({
517
600
  input: entry,
@@ -535,7 +618,7 @@ async function getBuildOptions(config, pkg, format, cjsDts) {
535
618
  plugins,
536
619
  inject: { ...shims && !cjsDts && getShimsInject(format, platform) }
537
620
  }, config.inputOptions, [format]);
538
- const [entryFileNames, chunkFileNames] = resolveChunkFilename(pkg, inputOptions, format, config);
621
+ const [entryFileNames, chunkFileNames] = resolveChunkFilename(config, inputOptions, format);
539
622
  const outputOptions = await mergeUserOptions({
540
623
  format: cjsDts ? "es" : format,
541
624
  name: config.globalName,
@@ -1,5 +1,6 @@
1
- import { version } from "./package-BBoT5Sps.js";
1
+ import { version } from "./package-D9H_HrcE.js";
2
2
  import process from "node:process";
3
+ import { green, underline } from "ansis";
3
4
  import { readFile, unlink, writeFile } from "node:fs/promises";
4
5
  import consola$1 from "consola";
5
6
  import { existsSync } from "node:fs";
@@ -8,7 +9,7 @@ import { existsSync } from "node:fs";
8
9
  async function migrate({ cwd, dryRun }) {
9
10
  if (dryRun) consola$1.info("Dry run enabled. No changes were made.");
10
11
  else {
11
- const confirm = await consola$1.prompt("Please make sure to commit your changes before migrating. Continue?", { type: "confirm" });
12
+ const confirm = await consola$1.prompt(`Before proceeding, review the migration guide at ${underline`https://tsdown.dev/guide/migrate-from-tsup`}, as this process will modify your files.\nUncommitted changes will be lost. Use the ${green`--dry-run`} flag to preview changes without applying them.\n\nContinue?`, { type: "confirm" });
12
13
  if (!confirm) {
13
14
  consola$1.error("Migration cancelled.");
14
15
  process.exitCode = 1;
@@ -0,0 +1,211 @@
1
+ import { BuildOptions, ExternalOption, InputOption, InputOptions, InternalModuleFormat, ModuleFormat, OutputOptions, Plugin } from "rolldown";
2
+ import { Hookable } from "hookable";
3
+ import { Options } from "publint";
4
+ import { Options as Options$1 } from "rolldown-plugin-dts";
5
+ import { Options as Options$2 } from "unplugin-unused";
6
+ import { PackageJson } from "pkg-types";
7
+
8
+ //#region src/features/hooks.d.ts
9
+ interface BuildContext {
10
+ options: ResolvedOptions;
11
+ pkg?: PackageJson;
12
+ hooks: Hookable<TsdownHooks>;
13
+ }
14
+ interface RolldownContext {
15
+ buildOptions: BuildOptions;
16
+ }
17
+
18
+ /**
19
+ * Hooks for tsdown.
20
+ */
21
+ interface TsdownHooks {
22
+ /**
23
+ * Invoked before each tsdown build starts.
24
+ * Use this hook to perform setup or preparation tasks.
25
+ */
26
+ "build:prepare": (ctx: BuildContext) => void | Promise<void>;
27
+ /**
28
+ * Invoked before each Rolldown build.
29
+ * For dual-format builds, this hook is called for each format.
30
+ * Useful for configuring or modifying the build context before bundling.
31
+ */
32
+ "build:before": (ctx: BuildContext & RolldownContext) => void | Promise<void>;
33
+ /**
34
+ * Invoked after each tsdown build completes.
35
+ * Use this hook for cleanup or post-processing tasks.
36
+ */
37
+ "build:done": (ctx: BuildContext) => void | Promise<void>;
38
+ } //#endregion
39
+ //#region src/utils/package.d.ts
40
+ type PackageType = "module" | "commonjs" | undefined;
41
+
42
+ //#endregion
43
+ //#region src/features/output.d.ts
44
+ interface OutExtensionContext {
45
+ options: InputOptions;
46
+ format: NormalizedFormat;
47
+ /** "type" field in project's package.json */
48
+ pkgType?: PackageType;
49
+ }
50
+ interface OutExtensionObject {
51
+ js?: string;
52
+ dts?: string;
53
+ }
54
+ type OutExtensionFactory = (ctx: OutExtensionContext) => OutExtensionObject;
55
+
56
+ //#endregion
57
+ //#region src/features/report.d.ts
58
+ interface ReportOptions {
59
+ /**
60
+ * Enable/disable brotli-compressed size reporting.
61
+ * Compressing large output files can be slow, so disabling this may increase build performance for large projects.
62
+ *
63
+ * @default false
64
+ */
65
+ brotli?: boolean;
66
+ /**
67
+ * Skip reporting compressed size for files larger than this size.
68
+ * @default 1_000_000 // 1MB
69
+ */
70
+ maxCompressSize?: number;
71
+ }
72
+ declare function ReportPlugin(options: ReportOptions, cwd: string, cjsDts?: boolean): Plugin;
73
+
74
+ //#endregion
75
+ //#region src/utils/types.d.ts
76
+ type Overwrite<T, U> = Omit<T, keyof U> & U;
77
+ type Awaitable<T> = T | Promise<T>;
78
+ type MarkPartial<T, K extends keyof T> = Omit<Required<T>, K> & Partial<Pick<T, K>>;
79
+ type Arrayable<T> = T | T[];
80
+
81
+ //#endregion
82
+ //#region src/options.d.ts
83
+ type Sourcemap = boolean | "inline" | "hidden";
84
+ type Format = Exclude<ModuleFormat, "experimental-app">;
85
+ type NormalizedFormat = Exclude<InternalModuleFormat, "app">;
86
+ interface MinifyOptions {
87
+ mangle?: boolean;
88
+ compress?: boolean;
89
+ removeWhitespace?: boolean;
90
+ }
91
+
92
+ /**
93
+ * Options for tsdown.
94
+ */
95
+ interface Options$3 {
96
+ entry?: InputOption;
97
+ external?: ExternalOption;
98
+ noExternal?: Arrayable<string | RegExp> | ((id: string, importer: string | undefined) => boolean | null | undefined | void);
99
+ alias?: Record<string, string>;
100
+ tsconfig?: string | boolean;
101
+ /** @default 'node' */
102
+ platform?: "node" | "neutral" | "browser";
103
+ inputOptions?: InputOptions | ((options: InputOptions, format: NormalizedFormat) => Awaitable<InputOptions | void | null>);
104
+ /** @default 'es' */
105
+ format?: Format | Format[];
106
+ globalName?: string;
107
+ /** @default 'dist' */
108
+ outDir?: string;
109
+ sourcemap?: Sourcemap;
110
+ /**
111
+ * Clean directories before build.
112
+ *
113
+ * Default to output directory.
114
+ */
115
+ clean?: boolean | string[];
116
+ /** @default false */
117
+ minify?: boolean | "dce-only" | MinifyOptions;
118
+ target?: string | string[];
119
+ define?: Record<string, string>;
120
+ /** @default false */
121
+ shims?: boolean;
122
+ /**
123
+ * Use a fixed extension for output files.
124
+ * The extension will always be `.cjs` or `.mjs`.
125
+ * Otherwise, it will depend on the package type.
126
+ * @default false
127
+ */
128
+ fixedExtension?: boolean;
129
+ /**
130
+ * Custom extensions for output files.
131
+ * `fixedExtension` will be overridden by this option.
132
+ */
133
+ outExtensions?: OutExtensionFactory;
134
+ outputOptions?: OutputOptions | ((options: OutputOptions, format: NormalizedFormat) => Awaitable<OutputOptions | void | null>);
135
+ /** @default true */
136
+ treeshake?: boolean;
137
+ plugins?: InputOptions["plugins"];
138
+ silent?: boolean;
139
+ /**
140
+ * Config file path
141
+ */
142
+ config?: boolean | string;
143
+ watch?: boolean | string | string[];
144
+ /**
145
+ * You can specify command to be executed after a successful build, specially useful for Watch mode
146
+ */
147
+ onSuccess?: string | ((config: ResolvedOptions) => void | Promise<void>);
148
+ /**
149
+ * Skip bundling node_modules.
150
+ */
151
+ skipNodeModulesBundle?: boolean;
152
+ /**
153
+ * Reuse config from Vite or Vitest (experimental)
154
+ * @default false
155
+ */
156
+ fromVite?: boolean | "vitest";
157
+ /**
158
+ * Emit TypeScript declaration files (.d.ts).
159
+ *
160
+ * By default, this feature is auto-detected based on the presence of the `types` field in the `package.json` file.
161
+ * - If the `types` field is present in `package.json`, declaration file emission is enabled.
162
+ * - If the `types` field is absent, declaration file emission is disabled by default.
163
+ */
164
+ dts?: boolean | Options$1;
165
+ /**
166
+ * Enable unused dependencies check with `unplugin-unused`
167
+ * Requires `unplugin-unused` to be installed.
168
+ */
169
+ unused?: boolean | Options$2;
170
+ /**
171
+ * Run publint after bundling.
172
+ * Requires `publint` to be installed.
173
+ */
174
+ publint?: boolean | Options;
175
+ /**
176
+ * Enable size reporting after bundling.
177
+ * @default true
178
+ */
179
+ report?: boolean | ReportOptions;
180
+ /**
181
+ * Compile-time env variables.
182
+ * @example
183
+ * ```ts
184
+ * {
185
+ * "DEBUG": true,
186
+ * "NODE_ENV": "production"
187
+ * }
188
+ * ```
189
+ */
190
+ env?: Record<string, any>;
191
+ hooks?: Partial<TsdownHooks> | ((hooks: Hookable<TsdownHooks>) => Awaitable<void>);
192
+ }
193
+
194
+ /**
195
+ * Options without specifying config file path.
196
+ */
197
+ type UserConfig = Arrayable<Omit<Options$3, "config">>;
198
+ type UserConfigFn = (cliOptions: Options$3) => Awaitable<UserConfig>;
199
+ type ResolvedOptions = Omit<Overwrite<MarkPartial<Options$3, "globalName" | "inputOptions" | "outputOptions" | "minify" | "define" | "alias" | "external" | "noExternal" | "onSuccess" | "fixedExtension" | "outExtensions" | "hooks">, {
200
+ format: NormalizedFormat[];
201
+ target?: string[];
202
+ clean: string[];
203
+ dts: false | Options$1;
204
+ report: false | ReportOptions;
205
+ tsconfig: string | false;
206
+ cwd: string;
207
+ pkg?: PackageJson;
208
+ }>, "config" | "fromVite">;
209
+
210
+ //#endregion
211
+ export { BuildContext, Options$3 as Options, ReportPlugin as ReportPlugin$1, ResolvedOptions, TsdownHooks, UserConfig, UserConfigFn };
@@ -0,0 +1,5 @@
1
+ //#region package.json
2
+ var version = "0.10.0";
3
+
4
+ //#endregion
5
+ export { version };
@@ -41,8 +41,8 @@ function lowestCommonAncestor(...filepaths) {
41
41
  //#region src/features/external.ts
42
42
  const debug$2 = Debug("tsdown:external");
43
43
  const RE_DTS$1 = /\.d\.[cm]?ts$/;
44
- function ExternalPlugin(options, pkg) {
45
- const deps = pkg && Array.from(getProductionDeps(pkg));
44
+ function ExternalPlugin(options) {
45
+ const deps = options.pkg && Array.from(getProductionDeps(options.pkg));
46
46
  return {
47
47
  name: "tsdown:external",
48
48
  async resolveId(id, importer, { isEntry }) {
package/dist/plugins.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { ReportPlugin$1 as ReportPlugin, ResolvedOptions } from "./options.d-BXikSiux.js";
1
+ import { ReportPlugin$1 as ReportPlugin, ResolvedOptions } from "./options.d-C1wrHXGf.js";
2
2
  import { Plugin } from "rolldown";
3
3
  import { PackageJson } from "pkg-types";
4
4
 
5
5
  //#region src/features/external.d.ts
6
- declare function ExternalPlugin(options: ResolvedOptions, pkg?: PackageJson): Plugin;
6
+ declare function ExternalPlugin(options: ResolvedOptions): Plugin;
7
7
 
8
8
  //#endregion
9
9
  //#region src/features/shebang.d.ts
package/dist/plugins.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ExternalPlugin, ReportPlugin, ShebangPlugin } from "./plugins-BcuTSrGE.js";
1
+ import { ExternalPlugin, ReportPlugin, ShebangPlugin } from "./plugins-DX6CtlR1.js";
2
2
  import "./general-C06aMSSY.js";
3
3
 
4
4
  export { ExternalPlugin, ReportPlugin, ShebangPlugin };
package/dist/run.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { logger, resolveComma, setSilent, toArray } from "./general-C06aMSSY.js";
3
- import { version } from "./package-BBoT5Sps.js";
3
+ import { version } from "./package-D9H_HrcE.js";
4
4
  import process from "node:process";
5
5
  import { dim } from "ansis";
6
6
  import Debug from "debug";
@@ -11,7 +11,7 @@ import { cac } from "cac";
11
11
  //#region src/cli.ts
12
12
  const cli = cac("tsdown");
13
13
  cli.help().version(version);
14
- cli.command("[...files]", "Bundle files", { ignoreOptionDefaultValue: true }).option("-c, --config <filename>", "Use a custom config file").option("--no-config", "Disable config file").option("--format <format>", "Bundle format: esm, cjs, iife", { default: "esm" }).option("--clean", "Clean output directory").option("--external <module>", "Mark dependencies as external").option("--minify", "Minify output").option("--debug [scope]", "Show debug logs").option("--target <target>", "Bundle target, e.g \"es2015\", \"esnext\"").option("--silent", "Suppress non-error logs").option("-d, --out-dir <dir>", "Output directory", { default: "dist" }).option("--treeshake", "Tree-shake bundle", { default: true }).option("--sourcemap", "Generate source map", { default: false }).option("--shims", "Enable cjs and esm shims ", { default: false }).option("--platform <platform>", "Target platform", { default: "node" }).option("--dts", "Generate dts files", { default: false }).option("--publint", "Enable publint", { default: false }).option("--unused", "Enable unused dependencies check", { default: false }).option("-w, --watch [path]", "Watch mode").option("--from-vite [vitest]", "Reuse config from Vite or Vitest").option("--report", "Size report", { default: true }).option("--env.* <value>", "Define compile-time env variables").action(async (input, flags) => {
14
+ cli.command("[...files]", "Bundle files", { ignoreOptionDefaultValue: true }).option("-c, --config <filename>", "Use a custom config file").option("--no-config", "Disable config file").option("--format <format>", "Bundle format: esm, cjs, iife", { default: "esm" }).option("--clean", "Clean output directory").option("--external <module>", "Mark dependencies as external").option("--minify", "Minify output").option("--debug [scope]", "Show debug logs").option("--target <target>", "Bundle target, e.g \"es2015\", \"esnext\"").option("--silent", "Suppress non-error logs").option("-d, --out-dir <dir>", "Output directory", { default: "dist" }).option("--treeshake", "Tree-shake bundle", { default: true }).option("--sourcemap", "Generate source map", { default: false }).option("--shims", "Enable cjs and esm shims ", { default: false }).option("--platform <platform>", "Target platform", { default: "node" }).option("--dts", "Generate dts files").option("--publint", "Enable publint", { default: false }).option("--unused", "Enable unused dependencies check", { default: false }).option("-w, --watch [path]", "Watch mode").option("--from-vite [vitest]", "Reuse config from Vite or Vitest").option("--report", "Size report", { default: true }).option("--env.* <value>", "Define compile-time env variables").action(async (input, flags) => {
15
15
  setSilent(!!flags.silent);
16
16
  logger.info(`tsdown ${dim`v${version}`} powered by rolldown ${dim`v${VERSION}`}`);
17
17
  const { build: build$1 } = await import("./index.js");
@@ -19,7 +19,7 @@ cli.command("[...files]", "Bundle files", { ignoreOptionDefaultValue: true }).op
19
19
  await build$1(flags);
20
20
  });
21
21
  cli.command("migrate", "Migrate from tsup to tsdown").option("-c, --cwd <dir>", "Working directory").option("-d, --dry-run", "Dry run").action(async (args) => {
22
- const { migrate } = await import("./migrate-fONPr2zj.js");
22
+ const { migrate } = await import("./migrate-Cq1rvewL.js");
23
23
  await migrate(args);
24
24
  });
25
25
  async function runCLI() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsdown",
3
- "version": "0.9.8",
3
+ "version": "0.10.0",
4
4
  "description": "The Elegant Bundler for Libraries",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -62,11 +62,13 @@
62
62
  "diff": "^7.0.0",
63
63
  "empathic": "^1.0.0",
64
64
  "hookable": "^5.5.3",
65
+ "lightningcss": "^1.29.3",
65
66
  "rolldown": "1.0.0-beta.8-commit.151352b",
66
- "rolldown-plugin-dts": "^0.8.3",
67
+ "rolldown-plugin-dts": "^0.9.5",
67
68
  "tinyexec": "^1.0.1",
68
69
  "tinyglobby": "^0.2.13",
69
- "unconfig": "^7.3.2"
70
+ "unconfig": "^7.3.2",
71
+ "unplugin-lightningcss": "^0.3.3"
70
72
  },
71
73
  "devDependencies": {
72
74
  "@sxzz/eslint-config": "^6.1.2",
@@ -74,7 +76,7 @@
74
76
  "@sxzz/test-utils": "^0.5.5",
75
77
  "@types/debug": "^4.1.12",
76
78
  "@types/diff": "^7.0.2",
77
- "@types/node": "^22.14.1",
79
+ "@types/node": "^22.15.2",
78
80
  "@unocss/eslint-plugin": "^66.1.0-beta.12",
79
81
  "bumpp": "^10.1.0",
80
82
  "eslint": "^9.25.1",
@@ -84,11 +86,11 @@
84
86
  "tsup": "^8.4.0",
85
87
  "tsx": "^4.19.3",
86
88
  "typedoc": "^0.28.3",
87
- "typedoc-plugin-markdown": "^4.6.2",
89
+ "typedoc-plugin-markdown": "^4.6.3",
88
90
  "typescript": "~5.8.3",
89
91
  "unocss": "^66.1.0-beta.12",
90
92
  "unplugin-unused": "^0.4.4",
91
- "vite": "^6.3.2",
93
+ "vite": "^6.3.3",
92
94
  "vitepress": "^1.6.3",
93
95
  "vitepress-plugin-group-icons": "^1.5.2",
94
96
  "vitepress-plugin-llms": "^1.1.0",
@@ -1,206 +0,0 @@
1
- import { BuildOptions, ExternalOption, InputOption, InputOptions, InternalModuleFormat, ModuleFormat, OutputOptions, Plugin } from "rolldown";
2
- import { Hookable } from "hookable";
3
- import { Options } from "publint";
4
- import { Options as Options$1 } from "rolldown-plugin-dts";
5
- import { Options as Options$2 } from "unplugin-unused";
6
- import { PackageJson } from "pkg-types";
7
-
8
- //#region src/features/hooks.d.ts
9
- interface BuildContext {
10
- options: ResolvedOptions;
11
- pkg?: PackageJson;
12
- hooks: Hookable<TsdownHooks>;
13
- }
14
- interface RolldownContext {
15
- buildOptions: BuildOptions;
16
- }
17
- /**
18
- * Hooks for tsdown.
19
- */
20
- interface TsdownHooks {
21
- /**
22
- * Invoked before each tsdown build starts.
23
- * Use this hook to perform setup or preparation tasks.
24
- */
25
- "build:prepare": (ctx: BuildContext) => void | Promise<void>;
26
- /**
27
- * Invoked before each Rolldown build.
28
- * For dual-format builds, this hook is called for each format.
29
- * Useful for configuring or modifying the build context before bundling.
30
- */
31
- "build:before": (ctx: BuildContext & RolldownContext) => void | Promise<void>;
32
- /**
33
- * Invoked after each tsdown build completes.
34
- * Use this hook for cleanup or post-processing tasks.
35
- */
36
- "build:done": (ctx: BuildContext) => void | Promise<void>;
37
- }
38
-
39
- //#endregion
40
- //#region src/utils/package.d.ts
41
- type PackageType = "module" | "commonjs" | undefined;
42
-
43
- //#endregion
44
- //#region src/features/output.d.ts
45
- interface OutExtensionContext {
46
- options: InputOptions;
47
- format: NormalizedFormat;
48
- /** "type" field in project's package.json */
49
- pkgType?: PackageType;
50
- }
51
- interface OutExtensionObject {
52
- js?: string;
53
- dts?: string;
54
- }
55
- type OutExtensionFactory = (ctx: OutExtensionContext) => OutExtensionObject;
56
-
57
- //#endregion
58
- //#region src/features/report.d.ts
59
- interface ReportOptions {
60
- /**
61
- * Enable/disable brotli-compressed size reporting.
62
- * Compressing large output files can be slow, so disabling this may increase build performance for large projects.
63
- *
64
- * @default false
65
- */
66
- brotli?: boolean;
67
- /**
68
- * Skip reporting compressed size for files larger than this size.
69
- * @default 1_000_000 // 1MB
70
- */
71
- maxCompressSize?: number;
72
- }
73
- declare function ReportPlugin(options: ReportOptions, cwd: string, cjsDts?: boolean): Plugin;
74
-
75
- //#endregion
76
- //#region src/utils/types.d.ts
77
- type Overwrite<
78
- T,
79
- U
80
- > = Omit<T, keyof U> & U;
81
- type Awaitable<T> = T | Promise<T>;
82
- type MarkPartial<
83
- T,
84
- K extends keyof T
85
- > = Omit<Required<T>, K> & Partial<Pick<T, K>>;
86
- type Arrayable<T> = T | T[];
87
-
88
- //#endregion
89
- //#region src/options.d.ts
90
- type Sourcemap = boolean | "inline" | "hidden";
91
- type Format = Exclude<ModuleFormat, "experimental-app">;
92
- type NormalizedFormat = Exclude<InternalModuleFormat, "app">;
93
- interface MinifyOptions {
94
- mangle?: boolean;
95
- compress?: boolean;
96
- removeWhitespace?: boolean;
97
- }
98
- /**
99
- * Options for tsdown.
100
- */
101
- interface Options$3 {
102
- entry?: InputOption;
103
- external?: ExternalOption;
104
- noExternal?: Arrayable<string | RegExp> | ((id: string, importer: string | undefined) => boolean | null | undefined | void);
105
- alias?: Record<string, string>;
106
- tsconfig?: string | boolean;
107
- /** @default 'node' */
108
- platform?: "node" | "neutral" | "browser";
109
- inputOptions?: InputOptions | ((options: InputOptions, format: NormalizedFormat) => Awaitable<InputOptions | void | null>);
110
- /** @default 'es' */
111
- format?: Format | Format[];
112
- globalName?: string;
113
- /** @default 'dist' */
114
- outDir?: string;
115
- sourcemap?: Sourcemap;
116
- clean?: boolean | string[];
117
- /** @default false */
118
- minify?: boolean | "dce-only" | MinifyOptions;
119
- target?: string | string[];
120
- define?: Record<string, string>;
121
- /** @default false */
122
- shims?: boolean;
123
- /**
124
- * Use a fixed extension for output files.
125
- * The extension will always be `.cjs` or `.mjs`.
126
- * Otherwise, it will depend on the package type.
127
- * @default false
128
- */
129
- fixedExtension?: boolean;
130
- /**
131
- * Custom extensions for output files.
132
- * `fixedExtension` will be overridden by this option.
133
- */
134
- outExtensions?: OutExtensionFactory;
135
- outputOptions?: OutputOptions | ((options: OutputOptions, format: NormalizedFormat) => Awaitable<OutputOptions | void | null>);
136
- /** @default true */
137
- treeshake?: boolean;
138
- plugins?: InputOptions["plugins"];
139
- silent?: boolean;
140
- /**
141
- * Config file path
142
- */
143
- config?: boolean | string;
144
- watch?: boolean | string | string[];
145
- /**
146
- * You can specify command to be executed after a successful build, specially useful for Watch mode
147
- */
148
- onSuccess?: string | ((config: ResolvedOptions) => void | Promise<void>);
149
- /**
150
- * Skip bundling node_modules.
151
- */
152
- skipNodeModulesBundle?: boolean;
153
- /**
154
- * Reuse config from Vite or Vitest (experimental)
155
- * @default false
156
- */
157
- fromVite?: boolean | "vitest";
158
- /**
159
- * Emit declaration files
160
- */
161
- dts?: boolean | Options$1;
162
- /**
163
- * Enable unused dependencies check with `unplugin-unused`
164
- * Requires `unplugin-unused` to be installed.
165
- */
166
- unused?: boolean | Options$2;
167
- /**
168
- * Run publint after bundling.
169
- * Requires `publint` to be installed.
170
- */
171
- publint?: boolean | Options;
172
- /**
173
- * Enable size reporting after bundling.
174
- * @default true
175
- */
176
- report?: boolean | ReportOptions;
177
- /**
178
- * Compile-time env variables.
179
- * @example
180
- * ```ts
181
- * {
182
- * "DEBUG": true,
183
- * "NODE_ENV": "production"
184
- * }
185
- * ```
186
- */
187
- env?: Record<string, any>;
188
- hooks?: Partial<TsdownHooks> | ((hooks: Hookable<TsdownHooks>) => Awaitable<void>);
189
- }
190
- /**
191
- * Options without specifying config file path.
192
- */
193
- type UserConfig = Arrayable<Omit<Options$3, "config">>;
194
- type UserConfigFn = (cliOptions: Options$3) => Awaitable<UserConfig>;
195
- type ResolvedOptions = Omit<Overwrite<MarkPartial<Options$3, "globalName" | "inputOptions" | "outputOptions" | "minify" | "define" | "alias" | "external" | "noExternal" | "onSuccess" | "fixedExtension" | "outExtensions" | "hooks">, {
196
- format: NormalizedFormat[]
197
- target?: string[]
198
- clean: string[] | false
199
- dts: false | Options$1
200
- report: false | ReportOptions
201
- tsconfig: string | false
202
- cwd: string
203
- }>, "config" | "fromVite">;
204
-
205
- //#endregion
206
- export { BuildContext, Options$3 as Options, ReportPlugin as ReportPlugin$1, ResolvedOptions, TsdownHooks, UserConfig, UserConfigFn };
@@ -1,5 +0,0 @@
1
- //#region package.json
2
- var version = "0.9.8";
3
-
4
- //#endregion
5
- export { version };