tsdown 0.9.1 → 0.9.3

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
@@ -37,7 +37,7 @@ Please make sure to commit your changes before migrating. For more details, see
37
37
 
38
38
  ## Credits
39
39
 
40
- This project also partially contains code derived or copied from [tsup](https://github.com/egoist/tsup).
40
+ This project also partially contains code derived or copied from the following projects:
41
41
 
42
42
  - [tsup](https://github.com/egoist/tsup)
43
43
  - [pkgroll](https://github.com/privatenumber/pkgroll)
@@ -1,5 +1,7 @@
1
-
2
1
  //#region src/config.ts
2
+ /**
3
+ * Defines the configuration for tsdown.
4
+ */
3
5
  function defineConfig(options) {
4
6
  return options;
5
7
  }
@@ -1,4 +1,4 @@
1
- import { UserConfig } from "./options.d-ISLuYVFY.js";
1
+ import { UserConfig } from "./options.d-CRAKIn7H.js";
2
2
 
3
3
  //#region src/config.d.ts
4
4
  /**
package/dist/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import "./options.d-ISLuYVFY.js";
2
- import { defineConfig$1 as defineConfig } from "./config.d-BcOfBgs6.js";
1
+ import "./options.d-CRAKIn7H.js";
2
+ import { defineConfig$1 as defineConfig } from "./config.d-DHsClbv0.js";
3
3
 
4
4
  export { defineConfig };
package/dist/config.js CHANGED
@@ -1,3 +1,3 @@
1
- import { defineConfig } from "./config-0LDjKwZ7.js";
1
+ import { defineConfig } from "./config-yiJy1jd0.js";
2
2
 
3
3
  export { defineConfig };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Options, ResolvedOptions, UserConfig } from "./options.d-ISLuYVFY.js";
2
- import { defineConfig$1 as defineConfig } from "./config.d-BcOfBgs6.js";
1
+ import { Options, ResolvedOptions, UserConfig } from "./options.d-CRAKIn7H.js";
2
+ import { defineConfig$1 as defineConfig } from "./config.d-DHsClbv0.js";
3
3
  import Debug from "debug";
4
4
  import { ConsolaInstance } from "consola";
5
5
 
package/dist/index.js CHANGED
@@ -1,18 +1,18 @@
1
- import { defineConfig } from "./config-0LDjKwZ7.js";
2
- import { ExternalPlugin, ShebangPlugin, debounce, fsExists, fsRemove, lowestCommonAncestor, toArray } from "./plugins-DTE_EFWN.js";
3
- import { debug, logger, setSilent } from "./logger-9p9U7Sx7.js";
1
+ import { defineConfig } from "./config-yiJy1jd0.js";
2
+ import { ExternalPlugin, ReportPlugin, ShebangPlugin, debounce, fsExists, fsRemove, getPackageType, lowestCommonAncestor, normalizeFormat, readPackageJson, toArray } from "./plugins-BvgcOKes.js";
3
+ import { debug, logger, setSilent } from "./logger-Dt3D6T-U.js";
4
4
  import path from "node:path";
5
5
  import process from "node:process";
6
6
  import { fileURLToPath, pathToFileURL } from "node:url";
7
7
  import { build as build$1 } from "rolldown";
8
8
  import { transformPlugin } from "rolldown/experimental";
9
9
  import { exec } from "tinyexec";
10
- import { readFile, readdir, stat } from "node:fs/promises";
10
+ import { readdir, stat } from "node:fs/promises";
11
11
  import Debug from "debug";
12
12
  import { glob } from "tinyglobby";
13
13
  import { findUp } from "find-up-simple";
14
- import readline from "node:readline";
15
14
  import { blue, bold, dim, underline } from "ansis";
15
+ import readline from "node:readline";
16
16
  import { loadConfig } from "unconfig";
17
17
 
18
18
  //#region src/features/clean.ts
@@ -31,34 +31,6 @@ async function cleanOutDir(cwd, patterns) {
31
31
  }
32
32
  }
33
33
 
34
- //#endregion
35
- //#region src/utils/package.ts
36
- async function readPackageJson(dir) {
37
- const packageJsonPath = await findUp("package.json", { cwd: dir });
38
- if (!packageJsonPath) return;
39
- debug("Reading package.json:", packageJsonPath);
40
- const contents = await readFile(packageJsonPath, "utf8");
41
- return JSON.parse(contents);
42
- }
43
- function getPackageType(pkg) {
44
- if (pkg?.type) {
45
- if (!["module", "commonjs"].includes(pkg.type)) throw new Error(`Invalid package.json type: ${pkg.type}`);
46
- return pkg.type;
47
- }
48
- }
49
- function normalizeFormat(format) {
50
- return toArray(format, "es").map((format$1) => {
51
- switch (format$1) {
52
- case "es":
53
- case "esm":
54
- case "module": return "es";
55
- case "cjs":
56
- case "commonjs": return "cjs";
57
- default: return format$1;
58
- }
59
- });
60
- }
61
-
62
34
  //#endregion
63
35
  //#region src/features/output.ts
64
36
  function resolveJsOutputExtension(packageType, format, fixedExtension) {
@@ -213,18 +185,18 @@ async function watchBuild(options, configFile, rebuild, restart) {
213
185
 
214
186
  //#endregion
215
187
  //#region src/features/entry.ts
216
- async function resolveEntry(entry) {
188
+ async function resolveEntry(entry, cwd) {
217
189
  if (!entry || Object.keys(entry).length === 0) throw new Error(`No input files, try "tsdown <your-file>" instead`);
218
- const objectEntry = await toObjectEntry(entry);
190
+ const objectEntry = await toObjectEntry(entry, cwd);
219
191
  const entries = Object.values(objectEntry);
220
192
  if (entries.length === 0) throw new Error(`Cannot find entry: ${JSON.stringify(entry)}`);
221
193
  logger.info(`entry: ${blue(entries.join(", "))}`);
222
194
  return objectEntry;
223
195
  }
224
- async function toObjectEntry(entry) {
196
+ async function toObjectEntry(entry, cwd) {
225
197
  if (typeof entry === "string") entry = [entry];
226
198
  if (!Array.isArray(entry)) return entry;
227
- const resolvedEntry = await glob(entry);
199
+ const resolvedEntry = await glob(entry, { cwd });
228
200
  const base = lowestCommonAncestor(...resolvedEntry);
229
201
  return Object.fromEntries(resolvedEntry.map((file) => {
230
202
  const relative = path.relative(base, file);
@@ -248,8 +220,8 @@ async function resolveOptions(options) {
248
220
  ...subConfig,
249
221
  ...options
250
222
  };
251
- 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 } = subOptions;
252
- entry = await resolveEntry(entry);
223
+ 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 } = subOptions;
224
+ entry = await resolveEntry(entry, cwd);
253
225
  if (clean === true) clean = [];
254
226
  if (publint$1 === true) publint$1 = {};
255
227
  if (tsconfig !== false) {
@@ -268,7 +240,7 @@ async function resolveOptions(options) {
268
240
  if (!tsconfig) logger.warn(`No \`${tsconfig}\` found in \`${cwd}\``);
269
241
  }
270
242
  }
271
- if (tsconfig) logger.info(`Using tsconfig: ${underline(tsconfig)}`);
243
+ if (tsconfig) logger.info(`Using tsconfig: ${underline(path.relative(cwd, tsconfig))}`);
272
244
  }
273
245
  if (fromVite) {
274
246
  const viteUserConfig = await loadViteConfig(fromVite === true ? "vite" : fromVite, cwd);
@@ -297,7 +269,9 @@ async function resolveOptions(options) {
297
269
  skipNodeModulesBundle,
298
270
  publint: publint$1,
299
271
  alias,
300
- tsconfig
272
+ tsconfig,
273
+ cwd,
274
+ report
301
275
  };
302
276
  return config;
303
277
  }));
@@ -401,6 +375,9 @@ async function mergeUserOptions(defaults, user, args) {
401
375
 
402
376
  //#endregion
403
377
  //#region src/index.ts
378
+ /**
379
+ * Build with tsdown.
380
+ */
404
381
  async function build(userOptions = {}) {
405
382
  if (typeof userOptions.silent === "boolean") setSilent(userOptions.silent);
406
383
  debug("Loading config");
@@ -423,6 +400,11 @@ async function build(userOptions = {}) {
423
400
  }
424
401
  const dirname$1 = path.dirname(fileURLToPath(import.meta.url));
425
402
  const pkgRoot = path.resolve(dirname$1, "..");
403
+ /**
404
+ * Build a single configuration, without watch and shortcuts features.
405
+ *
406
+ * @param config Resolved options
407
+ */
426
408
  async function buildSingle(config) {
427
409
  const { outDir, format: formats, clean, dts, watch, onSuccess } = config;
428
410
  let onSuccessCleanup;
@@ -464,7 +446,7 @@ async function buildSingle(config) {
464
446
  }
465
447
  }
466
448
  async function getBuildOptions(config, pkg, format, cjsDts) {
467
- const { entry, external, plugins: userPlugins, outDir, platform, alias, treeshake, sourcemap, dts, minify, unused, target, define, shims, tsconfig } = config;
449
+ const { entry, external, plugins: userPlugins, outDir, platform, alias, treeshake, sourcemap, dts, minify, unused, target, define, shims, tsconfig, cwd, report } = config;
468
450
  const plugins = [];
469
451
  if (pkg || config.skipNodeModulesBundle) plugins.push(ExternalPlugin(config, pkg));
470
452
  if (dts) {
@@ -485,14 +467,17 @@ async function getBuildOptions(config, pkg, format, cjsDts) {
485
467
  plugins.push(Unused.rolldown(unused === true ? {} : unused));
486
468
  }
487
469
  if (target) plugins.push(transformPlugin({
488
- target: target && (typeof target === "string" ? target : target.join(",")),
489
- exclude: /\.d\.[cm]?ts$/
470
+ include: /\.[cm]?[jt]sx?$/,
471
+ exclude: /\.d\.[cm]?ts$/,
472
+ transformOptions: { target }
490
473
  }));
491
- plugins.push(ShebangPlugin());
474
+ plugins.push(ShebangPlugin(cwd));
492
475
  }
476
+ if (report) plugins.push(ReportPlugin(cwd, cjsDts));
493
477
  plugins.push(userPlugins);
494
478
  const inputOptions = await mergeUserOptions({
495
479
  input: entry,
480
+ cwd,
496
481
  external,
497
482
  resolve: {
498
483
  alias,
@@ -1,9 +1,12 @@
1
1
  import process from "node:process";
2
2
  import Debug from "debug";
3
- import { consola as consola$1 } from "consola";
3
+ import { consola } from "consola";
4
4
 
5
5
  //#region src/utils/logger.ts
6
- const logger = consola$1.withTag("tsdown");
6
+ /**
7
+ * Logger instance
8
+ */
9
+ const logger = consola.withTag("tsdown");
7
10
  const debug = Debug("tsdown");
8
11
  function setSilent(silent) {
9
12
  if (!("CONSOLA_LEVEL" in process.env)) logger.level = silent ? 0 : 3;
@@ -1,16 +1,16 @@
1
- import { version } from "./package-CSBuPH3y.js";
1
+ import { version } from "./package-C_4Rg-Ho.js";
2
2
  import process from "node:process";
3
3
  import { readFile, unlink, writeFile } from "node:fs/promises";
4
- import consola from "consola";
4
+ import consola$1 from "consola";
5
5
  import { existsSync } from "node:fs";
6
6
 
7
7
  //#region src/migrate.ts
8
8
  async function migrate({ cwd, dryRun }) {
9
- if (dryRun) consola.info("Dry run enabled. No changes were made.");
9
+ if (dryRun) consola$1.info("Dry run enabled. No changes were made.");
10
10
  else {
11
- const confirm = await consola.prompt("Please make sure to commit your changes before migrating. Continue?", { type: "confirm" });
11
+ const confirm = await consola$1.prompt("Please make sure to commit your changes before migrating. Continue?", { type: "confirm" });
12
12
  if (!confirm) {
13
- consola.error("Migration cancelled.");
13
+ consola$1.error("Migration cancelled.");
14
14
  process.exitCode = 1;
15
15
  return;
16
16
  }
@@ -18,15 +18,15 @@ async function migrate({ cwd, dryRun }) {
18
18
  if (cwd) process.chdir(cwd);
19
19
  let migrated = await migratePackageJson(dryRun);
20
20
  if (await migrateTsupConfig(dryRun)) migrated = true;
21
- if (migrated) consola.success("Migration completed. Remember to run install command with your package manager.");
21
+ if (migrated) consola$1.success("Migration completed. Remember to run install command with your package manager.");
22
22
  else {
23
- consola.error("No migration performed.");
23
+ consola$1.error("No migration performed.");
24
24
  process.exitCode = 1;
25
25
  }
26
26
  }
27
27
  async function migratePackageJson(dryRun) {
28
28
  if (!existsSync("package.json")) {
29
- consola.error("No package.json found");
29
+ consola$1.error("No package.json found");
30
30
  return false;
31
31
  }
32
32
  const pkgRaw = await readFile("package.json", "utf-8");
@@ -34,44 +34,44 @@ async function migratePackageJson(dryRun) {
34
34
  const semver = `^${version}`;
35
35
  let found = false;
36
36
  if (pkg.dependencies?.tsup) {
37
- consola.info("Migrating `dependencies` to tsdown.");
37
+ consola$1.info("Migrating `dependencies` to tsdown.");
38
38
  found = true;
39
39
  pkg.dependencies = renameKey(pkg.dependencies, "tsup", "tsdown", semver);
40
40
  }
41
41
  if (pkg.devDependencies?.tsup) {
42
- consola.info("Migrating `devDependencies` to tsdown.");
42
+ consola$1.info("Migrating `devDependencies` to tsdown.");
43
43
  found = true;
44
44
  pkg.devDependencies = renameKey(pkg.devDependencies, "tsup", "tsdown", semver);
45
45
  }
46
46
  if (pkg.peerDependencies?.tsup) {
47
- consola.info("Migrating `peerDependencies` to tsdown.");
47
+ consola$1.info("Migrating `peerDependencies` to tsdown.");
48
48
  found = true;
49
49
  pkg.peerDependencies = renameKey(pkg.peerDependencies, "tsup", "tsdown", "*");
50
50
  }
51
51
  if (pkg.scripts) {
52
52
  for (const key of Object.keys(pkg.scripts)) if (pkg.scripts[key].includes("tsup")) {
53
- consola.info(`Migrating \`${key}\` script to tsdown`);
53
+ consola$1.info(`Migrating \`${key}\` script to tsdown`);
54
54
  found = true;
55
55
  pkg.scripts[key] = pkg.scripts[key].replaceAll(/tsup(?:-node)?/g, "tsdown");
56
56
  }
57
57
  }
58
58
  if (pkg.tsup) {
59
- consola.info("Migrating `tsup` field in package.json to `tsdown`.");
59
+ consola$1.info("Migrating `tsup` field in package.json to `tsdown`.");
60
60
  found = true;
61
61
  pkg = renameKey(pkg, "tsup", "tsdown");
62
62
  }
63
63
  if (!found) {
64
- consola.warn("No tsup-related fields found in package.json");
64
+ consola$1.warn("No tsup-related fields found in package.json");
65
65
  return false;
66
66
  }
67
67
  const pkgStr = `${JSON.stringify(pkg, null, 2)}\n`;
68
68
  if (dryRun) {
69
69
  const { createPatch } = await import("diff");
70
- consola.info("[dry-run] package.json:");
70
+ consola$1.info("[dry-run] package.json:");
71
71
  console.info(createPatch("package.json", pkgRaw, pkgStr));
72
72
  } else {
73
73
  await writeFile("package.json", pkgStr);
74
- consola.success("Migrated `package.json`");
74
+ consola$1.success("Migrated `package.json`");
75
75
  }
76
76
  return true;
77
77
  }
@@ -88,22 +88,22 @@ async function migrateTsupConfig(dryRun) {
88
88
  let found = false;
89
89
  for (const file of TSUP_FILES) {
90
90
  if (!existsSync(file)) continue;
91
- consola.info(`Found \`${file}\``);
91
+ consola$1.info(`Found \`${file}\``);
92
92
  found = true;
93
93
  const tsupConfigRaw = await readFile(file, "utf-8");
94
94
  const tsupConfig = tsupConfigRaw.replaceAll(/\btsup\b/g, "tsdown").replaceAll(/\bTSUP\b/g, "TSDOWN");
95
95
  const renamed = file.replaceAll("tsup", "tsdown");
96
96
  if (dryRun) {
97
97
  const { createTwoFilesPatch } = await import("diff");
98
- consola.info(`[dry-run] ${file} -> ${renamed}:`);
98
+ consola$1.info(`[dry-run] ${file} -> ${renamed}:`);
99
99
  console.info(createTwoFilesPatch(file, renamed, tsupConfigRaw, tsupConfig));
100
100
  } else {
101
101
  await writeFile(renamed, tsupConfig, "utf8");
102
102
  await unlink(file);
103
- consola.success(`Migrated \`${file}\` to \`${renamed}\``);
103
+ consola$1.success(`Migrated \`${file}\` to \`${renamed}\``);
104
104
  }
105
105
  }
106
- if (!found) consola.warn("No tsup config found");
106
+ if (!found) consola$1.warn("No tsup config found");
107
107
  return found;
108
108
  }
109
109
  function renameKey(obj, oldKey, newKey, newValue) {
@@ -111,6 +111,11 @@ interface Options$3 {
111
111
  * Requires `publint` to be installed.
112
112
  */
113
113
  publint?: boolean | Options;
114
+ /**
115
+ * Enable size reporting after bundling.
116
+ * @default true
117
+ */
118
+ report?: boolean;
114
119
  }
115
120
  /**
116
121
  * Options without specifying config file path.
@@ -122,6 +127,7 @@ type ResolvedOptions = Omit<Overwrite<MarkPartial<Options$3, "globalName" | "inp
122
127
  clean: string[] | false
123
128
  dts: false | Options$1
124
129
  tsconfig: string | false
130
+ cwd: string
125
131
  }>, "config" | "fromVite">;
126
132
 
127
133
  //#endregion
@@ -0,0 +1,5 @@
1
+ //#region package.json
2
+ var version = "0.9.3";
3
+
4
+ //#endregion
5
+ export { version };
@@ -0,0 +1,232 @@
1
+ import { debug, logger } from "./logger-Dt3D6T-U.js";
2
+ import path, { dirname, normalize, sep } from "node:path";
3
+ import { access, chmod, readFile, rm } from "node:fs/promises";
4
+ import Debug from "debug";
5
+ import { findUp } from "find-up-simple";
6
+ import { Buffer } from "node:buffer";
7
+ import { promisify } from "node:util";
8
+ import { brotliCompress, gzip } from "node:zlib";
9
+ import { blue, bold, dim, green, underline, yellow } from "ansis";
10
+
11
+ //#region src/utils/fs.ts
12
+ function fsExists(path$1) {
13
+ return access(path$1).then(() => true, () => false);
14
+ }
15
+ function fsRemove(path$1) {
16
+ return rm(path$1, {
17
+ force: true,
18
+ recursive: true
19
+ }).catch(() => {});
20
+ }
21
+ function lowestCommonAncestor(...filepaths) {
22
+ if (filepaths.length === 0) return "";
23
+ if (filepaths.length === 1) return dirname(filepaths[0]);
24
+ filepaths = filepaths.map(normalize);
25
+ const [first, ...rest] = filepaths;
26
+ let ancestor = first.split(sep);
27
+ for (const filepath of rest) {
28
+ const directories = filepath.split(sep, ancestor.length);
29
+ let index = 0;
30
+ for (const directory of directories) if (directory === ancestor[index]) index += 1;
31
+ else {
32
+ ancestor = ancestor.slice(0, index);
33
+ break;
34
+ }
35
+ ancestor = ancestor.slice(0, index);
36
+ }
37
+ return ancestor.length <= 1 && ancestor[0] === "" ? sep + ancestor[0] : ancestor.join(sep);
38
+ }
39
+
40
+ //#endregion
41
+ //#region src/utils/general.ts
42
+ function toArray(val, defaultValue) {
43
+ if (Array.isArray(val)) return val;
44
+ else if (val == null) {
45
+ if (defaultValue) return [defaultValue];
46
+ return [];
47
+ } else return [val];
48
+ }
49
+ function debounce(fn, wait) {
50
+ let timeout;
51
+ return function(...args) {
52
+ if (timeout) clearTimeout(timeout);
53
+ timeout = setTimeout(() => {
54
+ timeout = void 0;
55
+ fn.apply(this, args);
56
+ }, wait);
57
+ };
58
+ }
59
+
60
+ //#endregion
61
+ //#region src/features/external.ts
62
+ const debug$2 = Debug("tsdown:external");
63
+ const RE_DTS$1 = /\.d\.[cm]?ts$/;
64
+ function ExternalPlugin(options, pkg) {
65
+ const deps = pkg && Array.from(getProductionDeps(pkg));
66
+ return {
67
+ name: "tsdown:external",
68
+ async resolveId(id, importer, { isEntry }) {
69
+ if (isEntry) return;
70
+ if (importer && RE_DTS$1.test(importer)) return;
71
+ const { noExternal } = options;
72
+ if (typeof noExternal === "function" && noExternal(id, importer)) return;
73
+ if (noExternal) {
74
+ const noExternalPatterns = toArray(noExternal);
75
+ if (noExternalPatterns.some((pattern) => {
76
+ return pattern instanceof RegExp ? pattern.test(id) : id === pattern;
77
+ })) return;
78
+ }
79
+ let shouldExternal = false;
80
+ if (options.skipNodeModulesBundle) {
81
+ const resolved = await this.resolve(id);
82
+ if (!resolved) return;
83
+ shouldExternal = resolved.external || /[\\/]node_modules[\\/]/.test(resolved.id);
84
+ }
85
+ if (deps) shouldExternal ||= deps.some((dep) => id === dep || id.startsWith(`${dep}/`));
86
+ if (shouldExternal) {
87
+ debug$2("External dependency:", id);
88
+ return {
89
+ id,
90
+ external: shouldExternal
91
+ };
92
+ }
93
+ }
94
+ };
95
+ }
96
+ function getProductionDeps(pkg) {
97
+ return new Set([...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]);
98
+ }
99
+
100
+ //#endregion
101
+ //#region src/utils/package.ts
102
+ async function readPackageJson(dir) {
103
+ const packageJsonPath = await findUp("package.json", { cwd: dir });
104
+ if (!packageJsonPath) return;
105
+ debug("Reading package.json:", packageJsonPath);
106
+ const contents = await readFile(packageJsonPath, "utf8");
107
+ return JSON.parse(contents);
108
+ }
109
+ function getPackageType(pkg) {
110
+ if (pkg?.type) {
111
+ if (!["module", "commonjs"].includes(pkg.type)) throw new Error(`Invalid package.json type: ${pkg.type}`);
112
+ return pkg.type;
113
+ }
114
+ }
115
+ function normalizeFormat(format) {
116
+ return toArray(format, "es").map((format$1) => {
117
+ switch (format$1) {
118
+ case "es":
119
+ case "esm":
120
+ case "module": return "es";
121
+ case "cjs":
122
+ case "commonjs": return "cjs";
123
+ default: return format$1;
124
+ }
125
+ });
126
+ }
127
+ function prettyFormat(format) {
128
+ switch (format) {
129
+ case "es": return "ESM";
130
+ case "cjs":
131
+ case "iife":
132
+ case "umd": return format.toUpperCase();
133
+ default: return format;
134
+ }
135
+ }
136
+
137
+ //#endregion
138
+ //#region src/utils/format.ts
139
+ function formatBytes(bytes) {
140
+ const numberFormatter = new Intl.NumberFormat("en", {
141
+ maximumFractionDigits: 2,
142
+ minimumFractionDigits: 2
143
+ });
144
+ return `${numberFormatter.format(bytes / 1e3)} kB`;
145
+ }
146
+
147
+ //#endregion
148
+ //#region src/features/report.ts
149
+ const debug$1 = Debug("tsdown:report");
150
+ const noop = (v) => v;
151
+ const brotliCompressAsync = promisify(brotliCompress);
152
+ const gzipAsync = promisify(gzip);
153
+ const RE_DTS = /\.d\.[cm]?ts$/;
154
+ function ReportPlugin(cwd, cjsDts) {
155
+ return {
156
+ name: "tsdown:report",
157
+ async writeBundle(options, bundle) {
158
+ const outDir = path.relative(cwd, options.file ? path.resolve(cwd, options.file, "..") : path.resolve(cwd, options.dir));
159
+ const sizes = [];
160
+ for (const chunk of Object.values(bundle)) {
161
+ const size = await calcSize(chunk);
162
+ sizes.push(size);
163
+ }
164
+ const filenameLength = Math.max(...sizes.map((size) => size.filename.length));
165
+ const rawTextLength = Math.max(...sizes.map((size) => size.rawText.length));
166
+ const gzipTextLength = Math.max(...sizes.map((size) => size.gzipText.length));
167
+ const brotliTextLength = Math.max(...sizes.map((size) => size.brotliText.length));
168
+ let totalRaw = 0;
169
+ for (const size of sizes) {
170
+ size.rawText = size.rawText.padStart(rawTextLength);
171
+ size.gzipText = size.gzipText.padStart(gzipTextLength);
172
+ size.brotliText = size.brotliText.padStart(brotliTextLength);
173
+ totalRaw += size.raw;
174
+ }
175
+ sizes.sort((a, b) => {
176
+ if (a.dts !== b.dts) return a.dts ? 1 : -1;
177
+ if (a.isEntry !== b.isEntry) return a.isEntry ? -1 : 1;
178
+ return b.brotli - a.brotli;
179
+ });
180
+ const format = cjsDts ? "cjs" : options.format;
181
+ const formatColor = format === "es" ? blue : format === "cjs" ? yellow : noop;
182
+ const formatText = formatColor(`[${prettyFormat(format)}]`);
183
+ for (const size of sizes) {
184
+ const filenameColor = size.dts ? green : noop;
185
+ logger.info(formatText, dim(`${outDir}/`) + filenameColor((size.isEntry ? bold : noop)(size.filename)), ` `.repeat(filenameLength - size.filename.length), dim`${size.rawText} │ gzip: ${size.gzipText} │ brotli: ${size.brotliText}`);
186
+ }
187
+ const totalSizeText = formatBytes(totalRaw);
188
+ logger.info(formatText, `${sizes.length} files, total: ${totalSizeText}`);
189
+ }
190
+ };
191
+ }
192
+ async function calcSize(chunk) {
193
+ debug$1(`Calculating size for ${chunk.fileName}`);
194
+ const content = chunk.type === "chunk" ? chunk.code : chunk.source;
195
+ const raw = Buffer.byteLength(content, "utf8");
196
+ const gzip$1 = (await gzipAsync(content)).length;
197
+ const brotli = (await brotliCompressAsync(content)).length;
198
+ return {
199
+ filename: chunk.fileName,
200
+ dts: RE_DTS.test(chunk.fileName),
201
+ isEntry: chunk.type === "chunk" && chunk.isEntry,
202
+ raw,
203
+ rawText: formatBytes(raw),
204
+ gzip: gzip$1,
205
+ gzipText: formatBytes(gzip$1),
206
+ brotli,
207
+ brotliText: formatBytes(brotli)
208
+ };
209
+ }
210
+
211
+ //#endregion
212
+ //#region src/features/shebang.ts
213
+ const RE_SHEBANG = /^#!.*/;
214
+ function ShebangPlugin(cwd) {
215
+ return {
216
+ name: "tsdown:shebang",
217
+ async writeBundle(options, bundle) {
218
+ for (const chunk of Object.values(bundle)) {
219
+ if (chunk.type !== "chunk" || !chunk.isEntry) continue;
220
+ if (!RE_SHEBANG.test(chunk.code)) continue;
221
+ const filepath = path.resolve(cwd, options.file || path.join(options.dir, chunk.fileName));
222
+ if (await fsExists(filepath)) {
223
+ logger.info(`Granting execute permission to ${underline(path.relative(cwd, filepath))}`);
224
+ await chmod(filepath, 493);
225
+ }
226
+ }
227
+ }
228
+ };
229
+ }
230
+
231
+ //#endregion
232
+ export { ExternalPlugin, ReportPlugin, ShebangPlugin, debounce, fsExists, fsRemove, getPackageType, lowestCommonAncestor, normalizeFormat, readPackageJson, toArray };
package/dist/plugins.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ResolvedOptions } from "./options.d-ISLuYVFY.js";
1
+ import { ResolvedOptions } from "./options.d-CRAKIn7H.js";
2
2
  import { Plugin } from "rolldown";
3
3
  import { PackageJson } from "pkg-types";
4
4
 
@@ -7,7 +7,11 @@ declare function ExternalPlugin(options: ResolvedOptions, pkg?: PackageJson): Pl
7
7
 
8
8
  //#endregion
9
9
  //#region src/features/shebang.d.ts
10
- declare function ShebangPlugin(): Plugin;
10
+ declare function ShebangPlugin(cwd: string): Plugin;
11
11
 
12
12
  //#endregion
13
- export { ExternalPlugin, ShebangPlugin };
13
+ //#region src/features/report.d.ts
14
+ declare function ReportPlugin(cwd: string, cjsDts?: boolean): Plugin;
15
+
16
+ //#endregion
17
+ export { ExternalPlugin, ReportPlugin, ShebangPlugin };
package/dist/plugins.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ExternalPlugin, ShebangPlugin } from "./plugins-DTE_EFWN.js";
2
- import "./logger-9p9U7Sx7.js";
1
+ import { ExternalPlugin, ReportPlugin, ShebangPlugin } from "./plugins-BvgcOKes.js";
2
+ import "./logger-Dt3D6T-U.js";
3
3
 
4
- export { ExternalPlugin, ShebangPlugin };
4
+ export { ExternalPlugin, ReportPlugin, ShebangPlugin };
package/dist/run.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { logger, setSilent } from "./logger-9p9U7Sx7.js";
3
- import { version } from "./package-CSBuPH3y.js";
2
+ import { logger, setSilent } from "./logger-Dt3D6T-U.js";
3
+ import { version } from "./package-C_4Rg-Ho.js";
4
4
  import process from "node:process";
5
5
  import { VERSION } from "rolldown";
6
6
  import { dim } from "ansis";
@@ -9,7 +9,7 @@ import { cac } from "cac";
9
9
  //#region src/cli.ts
10
10
  const cli = cac("tsdown");
11
11
  cli.help().version(version);
12
- 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("--minify", "Minify output").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").action(async (input, flags) => {
12
+ 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("--minify", "Minify output").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 }).action(async (input, flags) => {
13
13
  setSilent(!!flags.silent);
14
14
  logger.info(`tsdown ${dim`v${version}`} powered by rolldown ${dim`v${VERSION}`}`);
15
15
  const { build: build$1 } = await import("./index.js");
@@ -17,7 +17,7 @@ cli.command("[...files]", "Bundle files", { ignoreOptionDefaultValue: true }).op
17
17
  await build$1(flags);
18
18
  });
19
19
  cli.command("migrate", "Migrate from tsup to tsdown").option("-c, --cwd <dir>", "Working directory").option("-d, --dry-run", "Dry run").action(async (args) => {
20
- const { migrate } = await import("./migrate-BAvHnB3T.js");
20
+ const { migrate } = await import("./migrate-BB2Nt65I.js");
21
21
  await migrate(args);
22
22
  });
23
23
  async function runCLI() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsdown",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "The Elegant Bundler for Libraries",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -61,38 +61,37 @@
61
61
  "debug": "^4.4.0",
62
62
  "diff": "^7.0.0",
63
63
  "find-up-simple": "^1.0.1",
64
- "rolldown": "^1.0.0-beta.7",
65
- "rolldown-plugin-dts": "^0.8.0",
64
+ "rolldown": "1.0.0-beta.8-commit.d984417",
65
+ "rolldown-plugin-dts": "^0.8.3",
66
66
  "tinyexec": "^1.0.1",
67
- "tinyglobby": "^0.2.12",
68
- "unconfig": "^7.3.1"
67
+ "tinyglobby": "^0.2.13",
68
+ "unconfig": "^7.3.2"
69
69
  },
70
70
  "devDependencies": {
71
- "@sxzz/eslint-config": "^6.1.1",
71
+ "@sxzz/eslint-config": "^6.1.2",
72
72
  "@sxzz/prettier-config": "^2.2.1",
73
73
  "@sxzz/test-utils": "^0.5.5",
74
74
  "@types/debug": "^4.1.12",
75
75
  "@types/diff": "^7.0.2",
76
76
  "@types/node": "^22.14.1",
77
- "@unocss/eslint-plugin": "66.1.0-beta.12",
77
+ "@unocss/eslint-plugin": "^66.1.0-beta.12",
78
78
  "bumpp": "^10.1.0",
79
- "eslint": "^9.25.0",
79
+ "eslint": "^9.25.1",
80
80
  "pkg-types": "^2.1.0",
81
81
  "prettier": "^3.5.3",
82
82
  "publint": "^0.3.12",
83
83
  "tsup": "^8.4.0",
84
84
  "tsx": "^4.19.3",
85
- "typedoc": "^0.28.2",
85
+ "typedoc": "^0.28.3",
86
86
  "typedoc-plugin-markdown": "^4.6.2",
87
87
  "typescript": "~5.8.3",
88
88
  "unocss": "^66.1.0-beta.12",
89
- "unplugin-ast": "^0.14.6",
90
89
  "unplugin-unused": "^0.4.4",
91
90
  "vite": "^6.3.2",
92
91
  "vitepress": "^1.6.3",
93
92
  "vitepress-plugin-group-icons": "^1.5.2",
94
93
  "vitepress-plugin-llms": "^1.1.0",
95
- "vitest": "^3.1.1",
94
+ "vitest": "^3.1.2",
96
95
  "vue": "^3.5.13"
97
96
  },
98
97
  "engines": {
@@ -1,6 +0,0 @@
1
-
2
- //#region package.json
3
- var version = "0.9.1";
4
-
5
- //#endregion
6
- export { version };
@@ -1,117 +0,0 @@
1
- import { logger } from "./logger-9p9U7Sx7.js";
2
- import path, { dirname, normalize, sep } from "node:path";
3
- import { access, chmod, rm } from "node:fs/promises";
4
- import Debug from "debug";
5
- import { underline } from "ansis";
6
-
7
- //#region src/utils/fs.ts
8
- function fsExists(path$1) {
9
- return access(path$1).then(() => true, () => false);
10
- }
11
- function fsRemove(path$1) {
12
- return rm(path$1, {
13
- force: true,
14
- recursive: true
15
- }).catch(() => {});
16
- }
17
- function lowestCommonAncestor(...filepaths) {
18
- if (filepaths.length === 0) return "";
19
- if (filepaths.length === 1) return dirname(filepaths[0]);
20
- filepaths = filepaths.map(normalize);
21
- const [first, ...rest] = filepaths;
22
- let ancestor = first.split(sep);
23
- for (const filepath of rest) {
24
- const directories = filepath.split(sep, ancestor.length);
25
- let index = 0;
26
- for (const directory of directories) if (directory === ancestor[index]) index += 1;
27
- else {
28
- ancestor = ancestor.slice(0, index);
29
- break;
30
- }
31
- ancestor = ancestor.slice(0, index);
32
- }
33
- return ancestor.length <= 1 && ancestor[0] === "" ? sep + ancestor[0] : ancestor.join(sep);
34
- }
35
-
36
- //#endregion
37
- //#region src/utils/general.ts
38
- function toArray(val, defaultValue) {
39
- if (Array.isArray(val)) return val;
40
- else if (val == null) {
41
- if (defaultValue) return [defaultValue];
42
- return [];
43
- } else return [val];
44
- }
45
- function debounce(fn, wait) {
46
- let timeout;
47
- return function(...args) {
48
- if (timeout) clearTimeout(timeout);
49
- timeout = setTimeout(() => {
50
- timeout = void 0;
51
- fn.apply(this, args);
52
- }, wait);
53
- };
54
- }
55
-
56
- //#endregion
57
- //#region src/features/external.ts
58
- const debug = Debug("tsdown:external");
59
- const RE_DTS = /\.d\.[cm]?ts$/;
60
- function ExternalPlugin(options, pkg) {
61
- const deps = pkg && Array.from(getProductionDeps(pkg));
62
- return {
63
- name: "tsdown:external",
64
- async resolveId(id, importer, { isEntry }) {
65
- if (isEntry) return;
66
- if (importer && RE_DTS.test(importer)) return;
67
- const { noExternal } = options;
68
- if (typeof noExternal === "function" && noExternal(id, importer)) return;
69
- if (noExternal) {
70
- const noExternalPatterns = toArray(noExternal);
71
- if (noExternalPatterns.some((pattern) => {
72
- return pattern instanceof RegExp ? pattern.test(id) : id === pattern;
73
- })) return;
74
- }
75
- let shouldExternal = false;
76
- if (options.skipNodeModulesBundle) {
77
- const resolved = await this.resolve(id);
78
- if (!resolved) return;
79
- shouldExternal = resolved.external || /[\\/]node_modules[\\/]/.test(resolved.id);
80
- }
81
- if (deps) shouldExternal ||= deps.some((dep) => id === dep || id.startsWith(`${dep}/`));
82
- if (shouldExternal) {
83
- debug("External dependency:", id);
84
- return {
85
- id,
86
- external: shouldExternal
87
- };
88
- }
89
- }
90
- };
91
- }
92
- function getProductionDeps(pkg) {
93
- return new Set([...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]);
94
- }
95
-
96
- //#endregion
97
- //#region src/features/shebang.ts
98
- const RE_SHEBANG = /^#!.*/;
99
- function ShebangPlugin() {
100
- return {
101
- name: "tsdown:shebang",
102
- async writeBundle(options, bundle) {
103
- for (const chunk of Object.values(bundle)) {
104
- if (chunk.type !== "chunk" || !chunk.isEntry) continue;
105
- if (!RE_SHEBANG.test(chunk.code)) continue;
106
- const file = options.file || path.resolve(options.dir, chunk.fileName);
107
- if (await fsExists(file)) {
108
- logger.info(`Granting execute permission to ${underline(file)}`);
109
- await chmod(file, 493);
110
- }
111
- }
112
- }
113
- };
114
- }
115
-
116
- //#endregion
117
- export { ExternalPlugin, ShebangPlugin, debounce, fsExists, fsRemove, lowestCommonAncestor, toArray };