tsdown 0.10.2 → 0.11.0-beta.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.
@@ -1,4 +1,4 @@
1
- import { UserConfig, UserConfigFn } from "./options.d-BCXr2j3p.js";
1
+ import { UserConfig, UserConfigFn } from "./options.d-BLasdguL.js";
2
2
 
3
3
  //#region src/config.d.ts
4
4
  /**
package/dist/config.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { UserConfig, UserConfigFn } from "./options.d-BCXr2j3p.js";
2
- import { defineConfig$1 as defineConfig } from "./config.d-DRSsMo60.js";
1
+ import { UserConfig, UserConfigFn } from "./options.d-BLasdguL.js";
2
+ import { defineConfig$1 as defineConfig } from "./config.d-2sS1Su5e.js";
3
3
  export { UserConfig, UserConfigFn, defineConfig };
@@ -1,16 +1,3 @@
1
- import process from "node:process";
2
- import { consola } from "consola";
3
-
4
- //#region src/utils/logger.ts
5
- /**
6
- * Logger instance
7
- */
8
- const logger = consola.withTag("tsdown");
9
- function setSilent(silent) {
10
- if (!("CONSOLA_LEVEL" in process.env)) logger.level = silent ? 0 : 3;
11
- }
12
-
13
- //#endregion
14
1
  //#region src/utils/general.ts
15
2
  function toArray(val, defaultValue) {
16
3
  if (Array.isArray(val)) return val;
@@ -35,4 +22,4 @@ function debounce(fn, wait) {
35
22
  const noop = (v) => v;
36
23
 
37
24
  //#endregion
38
- export { debounce, logger, noop, resolveComma, setSilent, toArray };
25
+ export { debounce, noop, resolveComma, toArray };
package/dist/index.d.ts CHANGED
@@ -1,17 +1,16 @@
1
- import { BuildContext, Options, ResolvedOptions, TsdownHooks, UserConfig } from "./options.d-BCXr2j3p.js";
2
- import { defineConfig$1 as defineConfig } from "./config.d-DRSsMo60.js";
3
- import { ConsolaInstance } from "consola";
1
+ import { BuildContext, Options, ResolvedOptions, TsdownHooks, UserConfig } from "./options.d-BLasdguL.js";
2
+ import { defineConfig$1 as defineConfig } from "./config.d-2sS1Su5e.js";
4
3
 
5
4
  //#region src/utils/logger.d.ts
6
- /**
7
- * Logger instance
8
- */
9
- /**
10
- * Logger instance
11
- */
12
- declare const logger: ConsolaInstance;
13
-
14
- //#endregion
5
+ declare class Logger {
6
+ silent: boolean;
7
+ setSilent(value: boolean): void;
8
+ info(...args: any[]): void;
9
+ warn(...args: any[]): void;
10
+ error(...args: any[]): void;
11
+ success(...args: any[]): void;
12
+ }
13
+ declare const logger: Logger; //#endregion
15
14
  //#region src/index.d.ts
16
15
  /**
17
16
  * Build with tsdown.
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { defineConfig } from "./config-CpIe1Ud_.js";
2
- import { ExternalPlugin, ReportPlugin, ShebangPlugin, fsExists, fsRemove, getPackageType, lowestCommonAncestor, normalizeFormat, prettyFormat, readPackageJson } from "./plugins-DX6CtlR1.js";
3
- import { debounce, logger, resolveComma, setSilent, toArray } from "./general-C06aMSSY.js";
2
+ import { ExternalPlugin, NodeProtocolPlugin, ReportPlugin, ShebangPlugin, fsCopy, fsRemove, fsStat, getPackageType, lowestCommonAncestor, normalizeFormat, prettyFormat, readPackageJson } from "./plugins-xuho_Cqn.js";
3
+ import { logger } from "./logger-DKXLpcNj.js";
4
+ import { debounce, resolveComma, toArray } from "./general-nv5tYplM.js";
4
5
  import path from "node:path";
5
6
  import process from "node:process";
6
- import { fileURLToPath, pathToFileURL } from "node:url";
7
7
  import { blue, bold, dim, green, underline } from "ansis";
8
8
  import Debug from "debug";
9
9
  import { build as build$1 } from "rolldown";
@@ -12,9 +12,10 @@ import { exec } from "tinyexec";
12
12
  import { glob } from "tinyglobby";
13
13
  import { stat } from "node:fs/promises";
14
14
  import { createHooks } from "hookable";
15
- import LightningCSS from "unplugin-lightningcss/rolldown";
16
15
  import readline from "node:readline";
16
+ import { pathToFileURL } from "node:url";
17
17
  import { loadConfig } from "unconfig";
18
+ import minVersion from "semver/ranges/min-version";
18
19
  import { up } from "empathic/find";
19
20
 
20
21
  //#region src/features/clean.ts
@@ -36,7 +37,7 @@ async function cleanOutDir(configs) {
36
37
  }
37
38
  }
38
39
  if (!removes.size) return;
39
- logger.info("Cleaning %d files", removes.size);
40
+ logger.info(`Cleaning ${removes.size} files`);
40
41
  await Promise.all([...removes].map(async (file) => {
41
42
  debug$3("Removing", file);
42
43
  await fsRemove(file);
@@ -49,6 +50,21 @@ function resolveClean(clean, outDir) {
49
50
  return clean;
50
51
  }
51
52
 
53
+ //#endregion
54
+ //#region src/features/copy.ts
55
+ async function copy(options) {
56
+ if (!options.copy) return;
57
+ const copy$1 = typeof options.copy === "function" ? await options.copy(options) : options.copy;
58
+ await Promise.all(toArray(copy$1).map((dir) => {
59
+ const from = typeof dir === "string" ? dir : dir.from;
60
+ const to = typeof dir === "string" ? path.resolve(options.outDir, path.basename(from)) : dir.to;
61
+ return cp$1(options.cwd, from, to);
62
+ }));
63
+ }
64
+ function cp$1(cwd, from, to) {
65
+ return fsCopy(path.resolve(cwd, from), path.resolve(cwd, to));
66
+ }
67
+
52
68
  //#endregion
53
69
  //#region src/features/hooks.ts
54
70
  async function createHooks$1(options, pkg) {
@@ -109,10 +125,12 @@ function parseVersion(version) {
109
125
 
110
126
  //#endregion
111
127
  //#region src/features/lightningcss.ts
112
- function LightningCSSPlugin(options) {
128
+ async function LightningCSSPlugin(options) {
129
+ const LightningCSS = await import("unplugin-lightningcss/rolldown").catch(() => void 0);
130
+ if (!LightningCSS) return;
113
131
  const targets = options.target && esbuildTargetToLightningCSS(options.target);
114
132
  if (!targets) return;
115
- return LightningCSS({ options: { targets } });
133
+ return LightningCSS.default({ options: { targets } });
116
134
  }
117
135
 
118
136
  //#endregion
@@ -151,17 +169,22 @@ function createChunkFilename(basename, jsExtension, dtsExtension) {
151
169
  //#endregion
152
170
  //#region src/features/publint.ts
153
171
  const debug$2 = Debug("tsdown:publint");
154
- async function publint(pkg, options) {
172
+ async function publint(options) {
173
+ if (!options.publint) return;
174
+ if (!options.pkg) {
175
+ logger.warn("publint is enabled but package.json is not found");
176
+ return;
177
+ }
155
178
  debug$2("Running publint");
156
179
  const { publint: publint$1 } = await import("publint");
157
180
  const { formatMessage } = await import("publint/utils");
158
- const { messages } = await publint$1(options);
181
+ const { messages } = await publint$1(options.publint === true ? {} : options.publint);
159
182
  debug$2("Found %d issues", messages.length);
160
183
  if (!messages.length) logger.success("No publint issues found");
161
184
  let hasError = false;
162
185
  for (const message of messages) {
163
186
  hasError ||= message.type === "error";
164
- const formattedMessage = formatMessage(message, pkg);
187
+ const formattedMessage = formatMessage(message, options.pkg);
165
188
  const logType = {
166
189
  error: "error",
167
190
  warning: "warn",
@@ -243,7 +266,7 @@ function shortcuts(restart) {
243
266
  const endsWithPackageJson = /[\\/]package\.json$/;
244
267
  async function watchBuild(options, configFile, rebuild, restart) {
245
268
  const cwd = process.cwd();
246
- if (typeof options.watch === "boolean" && options.outDir === cwd) throw new Error("Watch is enabled, but output directory is the same as the current working directory.Please specify a different watch directory using `watch` option,or set `outDir` to a different directory.");
269
+ if (typeof options.watch === "boolean" && options.outDir === cwd) throw new Error(`Watch is enabled, but output directory is the same as the current working directory.Please specify a different watch directory using ${blue`watch`} option,or set ${blue`outDir`} to a different directory.`);
247
270
  const files = toArray(typeof options.watch === "boolean" ? cwd : options.watch);
248
271
  logger.info(`Watching for changes in ${files.join(", ")}`);
249
272
  if (configFile) files.push(configFile);
@@ -291,26 +314,46 @@ async function toObjectEntry(entry, cwd) {
291
314
  }));
292
315
  }
293
316
 
317
+ //#endregion
318
+ //#region src/features/target.ts
319
+ function resolveTarget(target, pkg) {
320
+ if (!target) {
321
+ const pkgTarget = resolvePackageTarget(pkg);
322
+ if (pkgTarget) target = pkgTarget;
323
+ else return;
324
+ }
325
+ return resolveComma(toArray(target));
326
+ }
327
+ function resolvePackageTarget(pkg) {
328
+ const nodeVersion = pkg?.engines?.node;
329
+ if (!nodeVersion) return;
330
+ const nodeMinVersion = minVersion(nodeVersion);
331
+ if (!nodeMinVersion) return;
332
+ if (nodeMinVersion.version === "0.0.0") return;
333
+ return `node${nodeMinVersion.version}`;
334
+ }
335
+
294
336
  //#endregion
295
337
  //#region src/features/tsconfig.ts
296
338
  function findTsconfig(cwd, name = "tsconfig.json") {
297
339
  return up(name, { cwd }) || false;
298
340
  }
299
341
  async function resolveTsconfig(tsconfig, cwd) {
342
+ const original = tsconfig;
300
343
  if (tsconfig !== false) {
301
344
  if (tsconfig === true || tsconfig == null) {
302
- const isSet = tsconfig;
303
345
  tsconfig = findTsconfig(cwd);
304
- if (isSet && !tsconfig) logger.warn(`No tsconfig found in \`${cwd}\``);
346
+ if (original && !tsconfig) logger.warn(`No tsconfig found in ${blue(cwd)}`);
305
347
  } else {
306
348
  const tsconfigPath = path.resolve(cwd, tsconfig);
307
- if (await fsExists(tsconfigPath)) tsconfig = tsconfigPath;
308
- else if (tsconfig.includes("\\") || tsconfig.includes("/")) {
309
- logger.warn(`tsconfig \`${tsconfig}\` doesn't exist`);
310
- tsconfig = false;
349
+ const stat$1 = await fsStat(tsconfigPath);
350
+ if (stat$1?.isFile()) tsconfig = tsconfigPath;
351
+ else if (stat$1?.isDirectory()) {
352
+ tsconfig = findTsconfig(tsconfigPath);
353
+ if (!tsconfig) logger.warn(`No tsconfig found in ${blue(tsconfigPath)}`);
311
354
  } else {
312
355
  tsconfig = findTsconfig(cwd, tsconfig);
313
- if (!tsconfig) logger.warn(`No \`${tsconfig}\` found in \`${cwd}\``);
356
+ if (!tsconfig) logger.warn(`tsconfig ${blue(original)} doesn't exist`);
314
357
  }
315
358
  }
316
359
  if (tsconfig) logger.info(`Using tsconfig: ${underline(path.relative(cwd, tsconfig))}`);
@@ -331,7 +374,7 @@ async function resolveOptions(options) {
331
374
  ...subConfig,
332
375
  ...options
333
376
  };
334
- 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;
377
+ 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 = {}, copy: copy$1, publicDir } = subOptions;
335
378
  outDir = path.resolve(outDir);
336
379
  entry = await resolveEntry(entry, cwd);
337
380
  clean = resolveClean(clean, outDir);
@@ -339,6 +382,9 @@ async function resolveOptions(options) {
339
382
  if (dts == null) dts = !!(pkg?.types || pkg?.typings);
340
383
  tsconfig = await resolveTsconfig(tsconfig, cwd);
341
384
  if (publint$1 === true) publint$1 = {};
385
+ target = resolveTarget(target, pkg);
386
+ if (publicDir) if (copy$1) throw new TypeError("`publicDir` is deprecated. Cannot be used with `copy`");
387
+ else logger.warn(`${blue`publicDir`} is deprecated. Use ${blue`copy`} instead.`);
342
388
  if (fromVite) {
343
389
  const viteUserConfig = await loadViteConfig(fromVite === true ? "vite" : fromVite, cwd);
344
390
  if (viteUserConfig) {
@@ -353,7 +399,7 @@ async function resolveOptions(options) {
353
399
  entry,
354
400
  plugins,
355
401
  format: normalizeFormat(format),
356
- target: target ? resolveComma(toArray(target)) : void 0,
402
+ target,
357
403
  outDir,
358
404
  clean,
359
405
  silent,
@@ -371,7 +417,8 @@ async function resolveOptions(options) {
371
417
  tsconfig,
372
418
  cwd,
373
419
  env,
374
- pkg
420
+ pkg,
421
+ copy: publicDir || copy$1
375
422
  };
376
423
  return config;
377
424
  }));
@@ -481,7 +528,7 @@ const debug = Debug("tsdown:main");
481
528
  * Build with tsdown.
482
529
  */
483
530
  async function build(userOptions = {}) {
484
- if (typeof userOptions.silent === "boolean") setSilent(userOptions.silent);
531
+ if (typeof userOptions.silent === "boolean") logger.setSilent(userOptions.silent);
485
532
  debug("Loading config");
486
533
  const { configs, file: configFile } = await resolveOptions(userOptions);
487
534
  if (configFile) {
@@ -509,8 +556,7 @@ async function build(userOptions = {}) {
509
556
  build(userOptions);
510
557
  }
511
558
  }
512
- const dirname$1 = path.dirname(fileURLToPath(import.meta.url));
513
- const pkgRoot = path.resolve(dirname$1, "..");
559
+ const pkgRoot = path.resolve(import.meta.dirname, "..");
514
560
  /**
515
561
  * Build a single configuration, without watch and shortcuts features.
516
562
  *
@@ -552,9 +598,9 @@ async function buildSingle(config, clean) {
552
598
  }
553
599
  }));
554
600
  if (hasErrors) return;
601
+ await publint(config);
602
+ await copy(config);
555
603
  await hooks.callHook("build:done", context);
556
- if (config.publint) if (config.pkg) await publint(config.pkg, config.publint === true ? {} : config.publint);
557
- else logger.warn("publint is enabled but package.json is not found");
558
604
  logger.success(`${first ? "Build" : "Rebuild"} complete in ${green(`${Math.round(performance.now() - startTime)}ms`)}`);
559
605
  if (typeof onSuccess === "string") {
560
606
  const p = exec(onSuccess, [], { nodeOptions: {
@@ -569,7 +615,7 @@ async function buildSingle(config, clean) {
569
615
  }
570
616
  }
571
617
  async function getBuildOptions(config, format, cjsDts) {
572
- const { entry, external, plugins: userPlugins, outDir, platform, alias, treeshake, sourcemap, dts, minify, unused, target, define, shims, tsconfig, cwd, report, env } = config;
618
+ const { entry, external, plugins: userPlugins, outDir, platform, alias, treeshake, sourcemap, dts, minify, unused, target, define, shims, tsconfig, cwd, report, env, removeNodeProtocol } = config;
573
619
  const plugins = [];
574
620
  if (config.pkg || config.skipNodeModulesBundle) plugins.push(ExternalPlugin(config));
575
621
  if (dts) {
@@ -596,13 +642,14 @@ async function getBuildOptions(config, format, cjsDts) {
596
642
  }));
597
643
  plugins.push(ShebangPlugin(cwd));
598
644
  }
599
- if (report && logger.level >= 3) plugins.push(ReportPlugin(report, cwd, cjsDts));
645
+ if (report && !logger.silent) plugins.push(ReportPlugin(report, cwd, cjsDts));
600
646
  if (target) plugins.push(
601
647
  // Use Lightning CSS to handle CSS input. This is a temporary solution
602
648
  // until Rolldown supports CSS syntax lowering natively.
603
- LightningCSSPlugin({ target })
649
+ await LightningCSSPlugin({ target })
604
650
  );
605
651
  plugins.push(userPlugins);
652
+ if (removeNodeProtocol) plugins.push(NodeProtocolPlugin());
606
653
  const inputOptions = await mergeUserOptions({
607
654
  input: entry,
608
655
  cwd,
@@ -0,0 +1,25 @@
1
+ import { bgRed, bgYellow, blue, green } from "ansis";
2
+
3
+ //#region src/utils/logger.ts
4
+ var Logger = class {
5
+ silent = false;
6
+ setSilent(value) {
7
+ this.silent = value;
8
+ }
9
+ info(...args) {
10
+ if (!this.silent) console.info(blue`ℹ`, ...args);
11
+ }
12
+ warn(...args) {
13
+ if (!this.silent) console.warn("\n", bgYellow` WARN `, ...args, "\n");
14
+ }
15
+ error(...args) {
16
+ if (!this.silent) console.error("\n", bgRed` ERROR `, ...args, "\n");
17
+ }
18
+ success(...args) {
19
+ if (!this.silent) console.info(green`✔`, ...args);
20
+ }
21
+ };
22
+ const logger = new Logger();
23
+
24
+ //#endregion
25
+ export { logger };
@@ -1,17 +1,25 @@
1
- import { version } from "./package-DNcXUvW0.js";
1
+ import { logger } from "./logger-DKXLpcNj.js";
2
+ import { version } from "./package-BqZXvp6d.js";
2
3
  import process from "node:process";
3
- import { green, underline } from "ansis";
4
+ import { bold, green, underline } from "ansis";
4
5
  import { readFile, unlink, writeFile } from "node:fs/promises";
5
- import consola$1 from "consola";
6
6
  import { existsSync } from "node:fs";
7
+ import { createInterface } from "node:readline/promises";
7
8
 
8
9
  //#region src/migrate.ts
9
10
  async function migrate({ cwd, dryRun }) {
10
- if (dryRun) consola$1.info("Dry run enabled. No changes were made.");
11
+ if (dryRun) logger.info("Dry run enabled. No changes were made.");
11
12
  else {
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" });
13
+ const rl = createInterface({
14
+ input: process.stdin,
15
+ output: process.stdout
16
+ });
17
+ logger.warn(`\n\nBefore 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.`);
18
+ const input = await rl.question(bold`Continue? (Y/n) `);
19
+ rl.close();
20
+ const confirm = input.toLowerCase() === "y" || input === "";
13
21
  if (!confirm) {
14
- consola$1.error("Migration cancelled.");
22
+ logger.error("Migration cancelled.");
15
23
  process.exitCode = 1;
16
24
  return;
17
25
  }
@@ -19,15 +27,15 @@ async function migrate({ cwd, dryRun }) {
19
27
  if (cwd) process.chdir(cwd);
20
28
  let migrated = await migratePackageJson(dryRun);
21
29
  if (await migrateTsupConfig(dryRun)) migrated = true;
22
- if (migrated) consola$1.success("Migration completed. Remember to run install command with your package manager.");
30
+ if (migrated) logger.success("Migration completed. Remember to run install command with your package manager.");
23
31
  else {
24
- consola$1.error("No migration performed.");
32
+ logger.error("No migration performed.");
25
33
  process.exitCode = 1;
26
34
  }
27
35
  }
28
36
  async function migratePackageJson(dryRun) {
29
37
  if (!existsSync("package.json")) {
30
- consola$1.error("No package.json found");
38
+ logger.error("No package.json found");
31
39
  return false;
32
40
  }
33
41
  const pkgRaw = await readFile("package.json", "utf-8");
@@ -35,44 +43,44 @@ async function migratePackageJson(dryRun) {
35
43
  const semver = `^${version}`;
36
44
  let found = false;
37
45
  if (pkg.dependencies?.tsup) {
38
- consola$1.info("Migrating `dependencies` to tsdown.");
46
+ logger.info("Migrating `dependencies` to tsdown.");
39
47
  found = true;
40
48
  pkg.dependencies = renameKey(pkg.dependencies, "tsup", "tsdown", semver);
41
49
  }
42
50
  if (pkg.devDependencies?.tsup) {
43
- consola$1.info("Migrating `devDependencies` to tsdown.");
51
+ logger.info("Migrating `devDependencies` to tsdown.");
44
52
  found = true;
45
53
  pkg.devDependencies = renameKey(pkg.devDependencies, "tsup", "tsdown", semver);
46
54
  }
47
55
  if (pkg.peerDependencies?.tsup) {
48
- consola$1.info("Migrating `peerDependencies` to tsdown.");
56
+ logger.info("Migrating `peerDependencies` to tsdown.");
49
57
  found = true;
50
58
  pkg.peerDependencies = renameKey(pkg.peerDependencies, "tsup", "tsdown", "*");
51
59
  }
52
60
  if (pkg.scripts) {
53
61
  for (const key of Object.keys(pkg.scripts)) if (pkg.scripts[key].includes("tsup")) {
54
- consola$1.info(`Migrating \`${key}\` script to tsdown`);
62
+ logger.info(`Migrating \`${key}\` script to tsdown`);
55
63
  found = true;
56
64
  pkg.scripts[key] = pkg.scripts[key].replaceAll(/tsup(?:-node)?/g, "tsdown");
57
65
  }
58
66
  }
59
67
  if (pkg.tsup) {
60
- consola$1.info("Migrating `tsup` field in package.json to `tsdown`.");
68
+ logger.info("Migrating `tsup` field in package.json to `tsdown`.");
61
69
  found = true;
62
70
  pkg = renameKey(pkg, "tsup", "tsdown");
63
71
  }
64
72
  if (!found) {
65
- consola$1.warn("No tsup-related fields found in package.json");
73
+ logger.warn("No tsup-related fields found in package.json");
66
74
  return false;
67
75
  }
68
76
  const pkgStr = `${JSON.stringify(pkg, null, 2)}\n`;
69
77
  if (dryRun) {
70
78
  const { createPatch } = await import("diff");
71
- consola$1.info("[dry-run] package.json:");
79
+ logger.info("[dry-run] package.json:");
72
80
  console.info(createPatch("package.json", pkgRaw, pkgStr));
73
81
  } else {
74
82
  await writeFile("package.json", pkgStr);
75
- consola$1.success("Migrated `package.json`");
83
+ logger.success("Migrated `package.json`");
76
84
  }
77
85
  return true;
78
86
  }
@@ -89,22 +97,22 @@ async function migrateTsupConfig(dryRun) {
89
97
  let found = false;
90
98
  for (const file of TSUP_FILES) {
91
99
  if (!existsSync(file)) continue;
92
- consola$1.info(`Found \`${file}\``);
100
+ logger.info(`Found \`${file}\``);
93
101
  found = true;
94
102
  const tsupConfigRaw = await readFile(file, "utf-8");
95
103
  const tsupConfig = tsupConfigRaw.replaceAll(/\btsup\b/g, "tsdown").replaceAll(/\bTSUP\b/g, "TSDOWN");
96
104
  const renamed = file.replaceAll("tsup", "tsdown");
97
105
  if (dryRun) {
98
106
  const { createTwoFilesPatch } = await import("diff");
99
- consola$1.info(`[dry-run] ${file} -> ${renamed}:`);
107
+ logger.info(`[dry-run] ${file} -> ${renamed}:`);
100
108
  console.info(createTwoFilesPatch(file, renamed, tsupConfigRaw, tsupConfig));
101
109
  } else {
102
110
  await writeFile(renamed, tsupConfig, "utf8");
103
111
  await unlink(file);
104
- consola$1.success(`Migrated \`${file}\` to \`${renamed}\``);
112
+ logger.success(`Migrated \`${file}\` to \`${renamed}\``);
105
113
  }
106
114
  }
107
- if (!found) consola$1.warn("No tsup config found");
115
+ if (!found) logger.warn("No tsup config found");
108
116
  return found;
109
117
  }
110
118
  function renameKey(obj, oldKey, newKey, newValue) {
@@ -5,6 +5,22 @@ import { Options as Options$1 } from "rolldown-plugin-dts";
5
5
  import { Options as Options$2 } from "unplugin-unused";
6
6
  import { PackageJson } from "pkg-types";
7
7
 
8
+ //#region src/utils/types.d.ts
9
+ type Overwrite<T, U> = Omit<T, keyof U> & U;
10
+ type Awaitable<T> = T | Promise<T>;
11
+ type MarkPartial<T, K extends keyof T> = Omit<Required<T>, K> & Partial<Pick<T, K>>;
12
+ type Arrayable<T> = T | T[];
13
+
14
+ //#endregion
15
+ //#region src/features/copy.d.ts
16
+ interface CopyEntry {
17
+ from: string;
18
+ to: string;
19
+ }
20
+ type CopyOptions = Arrayable<string | CopyEntry>;
21
+ type CopyOptionsFn = (options: ResolvedOptions) => Awaitable<CopyOptions>;
22
+
23
+ //#endregion
8
24
  //#region src/features/hooks.d.ts
9
25
  interface BuildContext {
10
26
  options: ResolvedOptions;
@@ -34,7 +50,9 @@ interface TsdownHooks {
34
50
  * Use this hook for cleanup or post-processing tasks.
35
51
  */
36
52
  "build:done": (ctx: BuildContext) => void | Promise<void>;
37
- } //#endregion
53
+ }
54
+
55
+ //#endregion
38
56
  //#region src/utils/package.d.ts
39
57
  type PackageType = "module" | "commonjs" | undefined;
40
58
 
@@ -70,13 +88,6 @@ interface ReportOptions {
70
88
  }
71
89
  declare function ReportPlugin(options: ReportOptions, cwd: string, cjsDts?: boolean): Plugin;
72
90
 
73
- //#endregion
74
- //#region src/utils/types.d.ts
75
- type Overwrite<T, U> = Omit<T, keyof U> & U;
76
- type Awaitable<T> = T | Promise<T>;
77
- type MarkPartial<T, K extends keyof T> = Omit<Required<T>, K> & Partial<Pick<T, K>>;
78
- type Arrayable<T> = T | T[];
79
-
80
91
  //#endregion
81
92
  //#region src/options.d.ts
82
93
  type Sourcemap = boolean | "inline" | "hidden";
@@ -108,6 +119,28 @@ interface Options$3 {
108
119
  clean?: boolean | string[];
109
120
  /** @default false */
110
121
  minify?: boolean | "dce-only" | MinifyOptions;
122
+ /**
123
+ * Specifies the compilation target environment(s).
124
+ *
125
+ * Determines the JavaScript version or runtime(s) for which the code should be compiled.
126
+ * If not set, defaults to the value of `engines.node` in your project's `package.json`.
127
+ *
128
+ * Accepts a single target (e.g., `'es2020'`, `'node18'`) or an array of targets.
129
+ *
130
+ * @see {@link https://tsdown.dev/guide/target#supported-targets} for a list of valid targets and more details.
131
+ *
132
+ * @example
133
+ * ```jsonc
134
+ * // Target a single environment
135
+ * { "target": "node18" }
136
+ * ```
137
+ *
138
+ * @example
139
+ * ```jsonc
140
+ * // Target multiple environments
141
+ * { "target": ["node18", "es2020"] }
142
+ * ```
143
+ */
111
144
  target?: string | string[];
112
145
  define?: Record<string, string>;
113
146
  /** @default false */
@@ -139,7 +172,7 @@ interface Options$3 {
139
172
  */
140
173
  onSuccess?: string | ((config: ResolvedOptions) => void | Promise<void>);
141
174
  /**
142
- * Skip bundling node_modules.
175
+ * Skip bundling `node_modules`.
143
176
  */
144
177
  skipNodeModulesBundle?: boolean;
145
178
  /**
@@ -181,14 +214,39 @@ interface Options$3 {
181
214
  * ```
182
215
  */
183
216
  env?: Record<string, any>;
217
+ /**
218
+ * @deprecated Alias for `copy`, will be removed in the future.
219
+ */
220
+ publicDir?: CopyOptions | CopyOptionsFn;
221
+ /**
222
+ * Copy files to another directory.
223
+ * @example
224
+ * ```ts
225
+ * [
226
+ * 'src/assets',
227
+ * { from: 'src/assets', to: 'dist/assets' },
228
+ * ]
229
+ * ```
230
+ */
231
+ copy?: CopyOptions | CopyOptionsFn;
184
232
  hooks?: Partial<TsdownHooks> | ((hooks: Hookable<TsdownHooks>) => Awaitable<void>);
233
+ /**
234
+ * If enabled, strips the `node:` protocol prefix from import source.
235
+ *
236
+ * @default false
237
+ *
238
+ * @example
239
+ * // With removeNodeProtocol enabled:
240
+ * import('node:fs'); // becomes import('fs')
241
+ */
242
+ removeNodeProtocol?: boolean;
185
243
  }
186
244
  /**
187
245
  * Options without specifying config file path.
188
246
  */
189
247
  type UserConfig = Arrayable<Omit<Options$3, "config">>;
190
248
  type UserConfigFn = (cliOptions: Options$3) => Awaitable<UserConfig>;
191
- type ResolvedOptions = Omit<Overwrite<MarkPartial<Options$3, "globalName" | "inputOptions" | "outputOptions" | "minify" | "define" | "alias" | "external" | "noExternal" | "onSuccess" | "fixedExtension" | "outExtensions" | "hooks">, {
249
+ type ResolvedOptions = Omit<Overwrite<MarkPartial<Omit<Options$3, "publicDir">, "globalName" | "inputOptions" | "outputOptions" | "minify" | "define" | "alias" | "external" | "noExternal" | "onSuccess" | "fixedExtension" | "outExtensions" | "hooks" | "removeNodeProtocol" | "copy">, {
192
250
  format: NormalizedFormat[];
193
251
  target?: string[];
194
252
  clean: string[];
@@ -0,0 +1,5 @@
1
+ //#region package.json
2
+ var version = "0.11.0-beta.1";
3
+
4
+ //#endregion
5
+ export { version };
@@ -1,8 +1,9 @@
1
- import { logger, noop, resolveComma, toArray } from "./general-C06aMSSY.js";
1
+ import { logger } from "./logger-DKXLpcNj.js";
2
+ import { noop, resolveComma, toArray } from "./general-nv5tYplM.js";
2
3
  import path, { dirname, normalize, sep } from "node:path";
3
4
  import { blue, bold, dim, green, underline, yellow } from "ansis";
4
5
  import Debug from "debug";
5
- import { access, chmod, readFile, rm } from "node:fs/promises";
6
+ import { access, chmod, cp, readFile, rm, stat } from "node:fs/promises";
6
7
  import { up } from "empathic/package";
7
8
  import { Buffer } from "node:buffer";
8
9
  import { promisify } from "node:util";
@@ -12,12 +13,21 @@ import { brotliCompress, gzip } from "node:zlib";
12
13
  function fsExists(path$1) {
13
14
  return access(path$1).then(() => true, () => false);
14
15
  }
16
+ function fsStat(path$1) {
17
+ return stat(path$1).catch(() => null);
18
+ }
15
19
  function fsRemove(path$1) {
16
20
  return rm(path$1, {
17
21
  force: true,
18
22
  recursive: true
19
23
  }).catch(() => {});
20
24
  }
25
+ function fsCopy(from, to) {
26
+ return cp(from, to, {
27
+ recursive: true,
28
+ force: true
29
+ });
30
+ }
21
31
  function lowestCommonAncestor(...filepaths) {
22
32
  if (filepaths.length === 0) return "";
23
33
  if (filepaths.length === 1) return dirname(filepaths[0]);
@@ -77,6 +87,28 @@ function getProductionDeps(pkg) {
77
87
  return new Set([...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]);
78
88
  }
79
89
 
90
+ //#endregion
91
+ //#region src/features/node-protocol.ts
92
+ /**
93
+ * The `node:` protocol was added in Node.js v14.18.0.
94
+ * @see https://nodejs.org/api/esm.html#node-imports
95
+ */
96
+ function NodeProtocolPlugin() {
97
+ return {
98
+ name: "tsdown:node-protocol",
99
+ resolveId: {
100
+ filter: { id: /^node:/ },
101
+ handler(id) {
102
+ return {
103
+ id: id.slice(5),
104
+ external: true,
105
+ moduleSideEffects: false
106
+ };
107
+ }
108
+ }
109
+ };
110
+ }
111
+
80
112
  //#endregion
81
113
  //#region src/utils/package.ts
82
114
  const debug$1 = Debug("tsdown:package");
@@ -222,4 +254,4 @@ function ShebangPlugin(cwd) {
222
254
  }
223
255
 
224
256
  //#endregion
225
- export { ExternalPlugin, ReportPlugin, ShebangPlugin, fsExists, fsRemove, getPackageType, lowestCommonAncestor, normalizeFormat, prettyFormat, readPackageJson };
257
+ export { ExternalPlugin, NodeProtocolPlugin, ReportPlugin, ShebangPlugin, fsCopy, fsRemove, fsStat, getPackageType, lowestCommonAncestor, normalizeFormat, prettyFormat, readPackageJson };
package/dist/plugins.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ReportPlugin$1 as ReportPlugin, ResolvedOptions } from "./options.d-BCXr2j3p.js";
1
+ import { ReportPlugin$1 as ReportPlugin, ResolvedOptions } from "./options.d-BLasdguL.js";
2
2
  import { Plugin } from "rolldown";
3
3
  import { PackageJson } from "pkg-types";
4
4
 
@@ -10,4 +10,12 @@ declare function ExternalPlugin(options: ResolvedOptions): Plugin;
10
10
  declare function ShebangPlugin(cwd: string): Plugin;
11
11
 
12
12
  //#endregion
13
- export { ExternalPlugin, ReportPlugin, ShebangPlugin };
13
+ //#region src/features/node-protocol.d.ts
14
+ /**
15
+ * The `node:` protocol was added in Node.js v14.18.0.
16
+ * @see https://nodejs.org/api/esm.html#node-imports
17
+ */
18
+ declare function NodeProtocolPlugin(): Plugin;
19
+
20
+ //#endregion
21
+ export { ExternalPlugin, NodeProtocolPlugin, ReportPlugin, ShebangPlugin };
package/dist/plugins.js CHANGED
@@ -1,4 +1,5 @@
1
- import { ExternalPlugin, ReportPlugin, ShebangPlugin } from "./plugins-DX6CtlR1.js";
2
- import "./general-C06aMSSY.js";
1
+ import { ExternalPlugin, NodeProtocolPlugin, ReportPlugin, ShebangPlugin } from "./plugins-xuho_Cqn.js";
2
+ import "./logger-DKXLpcNj.js";
3
+ import "./general-nv5tYplM.js";
3
4
 
4
- export { ExternalPlugin, ReportPlugin, ShebangPlugin };
5
+ export { ExternalPlugin, NodeProtocolPlugin, ReportPlugin, ShebangPlugin };
package/dist/run.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { logger, resolveComma, setSilent, toArray } from "./general-C06aMSSY.js";
3
- import { version } from "./package-DNcXUvW0.js";
2
+ import { logger } from "./logger-DKXLpcNj.js";
3
+ import { resolveComma, toArray } from "./general-nv5tYplM.js";
4
+ import { version } from "./package-BqZXvp6d.js";
4
5
  import process from "node:process";
5
6
  import { dim } from "ansis";
6
7
  import Debug from "debug";
@@ -11,15 +12,15 @@ import { cac } from "cac";
11
12
  //#region src/cli.ts
12
13
  const cli = cac("tsdown");
13
14
  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").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").option("--on-success <command>", "Command to run on success").action(async (input, flags) => {
15
- setSilent(!!flags.silent);
15
+ 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").option("--on-success <command>", "Command to run on success").option("--copy <dir>", "Copy files to output dir").option("--public-dir <dir>", "Alias for --copy, deprecated").option("--tsconfig <tsconfig>", "Set tsconfig path").action(async (input, flags) => {
16
+ logger.setSilent(!!flags.silent);
16
17
  logger.info(`tsdown ${dim`v${version}`} powered by rolldown ${dim`v${VERSION}`}`);
17
18
  const { build: build$1 } = await import("./index.js");
18
19
  if (input.length > 0) flags.entry = input;
19
20
  await build$1(flags);
20
21
  });
21
22
  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-Dm7wrtcG.js");
23
+ const { migrate } = await import("./migrate-xZ5d7bv9.js");
23
24
  await migrate(args);
24
25
  });
25
26
  async function runCLI() {
@@ -36,7 +37,7 @@ async function runCLI() {
36
37
  try {
37
38
  await cli.runMatchedCommand();
38
39
  } catch (error) {
39
- logger.fatal(error);
40
+ logger.error(error);
40
41
  process.exit(1);
41
42
  }
42
43
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsdown",
3
- "version": "0.10.2",
3
+ "version": "0.11.0-beta.1",
4
4
  "description": "The Elegant Bundler for Libraries",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -43,12 +43,16 @@
43
43
  },
44
44
  "peerDependencies": {
45
45
  "publint": "^0.3.0",
46
+ "unplugin-lightningcss": "^0.3.3",
46
47
  "unplugin-unused": "^0.4.0"
47
48
  },
48
49
  "peerDependenciesMeta": {
49
50
  "publint": {
50
51
  "optional": true
51
52
  },
53
+ "unplugin-lightningcss": {
54
+ "optional": true
55
+ },
52
56
  "unplugin-unused": {
53
57
  "optional": true
54
58
  }
@@ -57,18 +61,16 @@
57
61
  "ansis": "^3.17.0",
58
62
  "cac": "^6.7.14",
59
63
  "chokidar": "^4.0.3",
60
- "consola": "^3.4.2",
61
64
  "debug": "^4.4.0",
62
65
  "diff": "^7.0.0",
63
66
  "empathic": "^1.0.0",
64
67
  "hookable": "^5.5.3",
65
- "lightningcss": "^1.29.3",
66
68
  "rolldown": "1.0.0-beta.8-commit.852c603",
67
69
  "rolldown-plugin-dts": "^0.9.7",
70
+ "semver": "^7.7.1",
68
71
  "tinyexec": "^1.0.1",
69
72
  "tinyglobby": "^0.2.13",
70
- "unconfig": "^7.3.2",
71
- "unplugin-lightningcss": "^0.3.3"
73
+ "unconfig": "^7.3.2"
72
74
  },
73
75
  "devDependencies": {
74
76
  "@sxzz/eslint-config": "^6.2.0",
@@ -77,9 +79,11 @@
77
79
  "@types/debug": "^4.1.12",
78
80
  "@types/diff": "^7.0.2",
79
81
  "@types/node": "^22.15.3",
82
+ "@types/semver": "^7.7.0",
80
83
  "@unocss/eslint-plugin": "^66.1.0-beta.12",
81
84
  "bumpp": "^10.1.0",
82
85
  "eslint": "^9.25.1",
86
+ "lightningcss": "^1.29.3",
83
87
  "pkg-types": "^2.1.0",
84
88
  "prettier": "^3.5.3",
85
89
  "publint": "^0.3.12",
@@ -89,6 +93,7 @@
89
93
  "typedoc-plugin-markdown": "^4.6.3",
90
94
  "typescript": "~5.8.3",
91
95
  "unocss": "^66.1.0-beta.12",
96
+ "unplugin-lightningcss": "^0.3.3",
92
97
  "unplugin-unused": "^0.4.4",
93
98
  "vite": "^6.3.3",
94
99
  "vitepress": "^1.6.3",
@@ -98,7 +103,7 @@
98
103
  "vue": "^3.5.13"
99
104
  },
100
105
  "engines": {
101
- "node": ">=18.0.0"
106
+ "node": ">=20.18.0"
102
107
  },
103
108
  "prettier": "@sxzz/prettier-config",
104
109
  "scripts": {
@@ -1,5 +0,0 @@
1
- //#region package.json
2
- var version = "0.10.2";
3
-
4
- //#endregion
5
- export { version };