tsdown 0.21.8 → 0.21.9

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,12 +1,12 @@
1
1
  import { createRequire as __cjs_createRequire } from "node:module";
2
2
  const __cjs_require = __cjs_createRequire(import.meta.url);
3
- import { a as getPackageType, c as isGlobEntry, d as cleanOutDir, i as loadConfigFile, l as toObjectEntry, n as mergeUserOptions, o as writeExports, r as resolveUserConfig, s as buildExe, t as mergeConfig, u as cleanChunks } from "./options-CAjSicbD.mjs";
3
+ import { a as getPackageType, c as isGlobEntry, d as cleanOutDir, i as loadConfigFile, l as toObjectEntry, n as mergeUserOptions, o as writeExports, r as resolveUserConfig, s as buildExe, t as mergeConfig, u as cleanChunks } from "./options-8hmVMssn.mjs";
4
4
  import { r as fsRemove } from "./fs-Dd6Htx2P.mjs";
5
5
  import { a as pkgExists, l as slash, n as importWithError, o as promiseWithResolvers, t as debounce } from "./general-D3muxt2f.mjs";
6
6
  import { a as globalLogger, t as LogLevels } from "./logger-uV8l1UFa.mjs";
7
- import { a as getShimsInject, r as DepsPlugin } from "./format-a5Q6w07o.mjs";
8
- import { a as ReportPlugin, i as ShebangPlugin, n as endsWithConfig, o as NodeProtocolPlugin, r as addOutDirToChunks, s as copy, t as WatchPlugin } from "./watch-C9ZHIctp.mjs";
9
- import { t as version } from "./package-yVk5dXcU.mjs";
7
+ import { i as getShimsInject, n as DepsPlugin } from "./format-CajNSstg.mjs";
8
+ import { a as ReportPlugin, i as ShebangPlugin, n as endsWithConfig, o as NodeProtocolPlugin, r as addOutDirToChunks, s as copy, t as WatchPlugin } from "./watch-D6EGzM6P.mjs";
9
+ import { t as version } from "./package-JOXUdJGa.mjs";
10
10
  import { mkdtemp, readFile, readdir, writeFile } from "node:fs/promises";
11
11
  import path from "node:path";
12
12
  import process from "node:process";
@@ -18,12 +18,12 @@ import { RE_CSS, RE_DTS, RE_JS, filename_js_to_dts } from "rolldown-plugin-dts/i
18
18
  import { tmpdir } from "node:os";
19
19
  const satisfies = __cjs_require("semver/functions/satisfies.js");
20
20
  import { exec, x } from "tinyexec";
21
+ import { formatWithOptions, inspect } from "node:util";
21
22
  import { clearRequireCache } from "import-without-cache";
22
23
  import { VERSION, build, watch } from "rolldown";
23
24
  const coerce = __cjs_require("semver/functions/coerce.js");
24
25
  import { Hookable } from "hookable";
25
26
  const treeKill = __cjs_require("tree-kill");
26
- import { formatWithOptions, inspect } from "node:util";
27
27
  import { importGlobPlugin } from "rolldown/experimental";
28
28
  //#region \0rolldown/runtime.js
29
29
  var __defProp = Object.defineProperty;
@@ -45,13 +45,14 @@ const DEFAULT_EXCLUDE_WORKSPACE = [
45
45
  "**/test?(s)/**",
46
46
  "**/t?(e)mp/**"
47
47
  ];
48
- async function resolveWorkspace(config, inlineConfig) {
48
+ async function resolveWorkspace(config, inlineConfig, rootDeps) {
49
49
  const normalized = mergeConfig(config, inlineConfig);
50
50
  const rootCwd = normalized.cwd || process.cwd();
51
+ const deps = new Set(rootDeps);
51
52
  let { workspace } = normalized;
52
53
  if (!workspace) return {
53
54
  configs: [normalized],
54
- files: []
55
+ deps
55
56
  };
56
57
  if (workspace === true) workspace = {};
57
58
  else if (typeof workspace === "string" || Array.isArray(workspace)) workspace = { include: workspace };
@@ -69,22 +70,18 @@ async function resolveWorkspace(config, inlineConfig) {
69
70
  expandDirectories: false
70
71
  })).map((file) => slash(path.resolve(file)));
71
72
  if (packages.length === 0) throw new Error("No workspace packages found, please check your config");
72
- const files = [];
73
73
  return {
74
74
  configs: (await Promise.all(packages.map(async (cwd) => {
75
75
  debug$4("loading workspace config %s", cwd);
76
- const { configs, file } = await loadConfigFile({
76
+ const { configs, deps: workspaceDeps } = await loadConfigFile({
77
77
  ...inlineConfig,
78
78
  config: workspaceConfig,
79
79
  cwd
80
80
  }, cwd, normalized);
81
- if (file) {
82
- debug$4("loaded workspace config file %s", file);
83
- files.push(file);
84
- } else debug$4("no workspace config file found in %s", cwd);
81
+ workspaceDeps?.forEach((dep) => deps.add(dep));
85
82
  return configs.map((config) => mergeConfig(normalized, config));
86
83
  }))).flat(),
87
- files
84
+ deps
88
85
  };
89
86
  }
90
87
  //#endregion
@@ -93,24 +90,20 @@ const debug$3 = createDebug("tsdown:config");
93
90
  async function resolveConfig(inlineConfig) {
94
91
  debug$3("inline config %O", inlineConfig);
95
92
  if (inlineConfig.cwd) inlineConfig.cwd = path.resolve(inlineConfig.cwd);
96
- const { configs: rootConfigs, file } = await loadConfigFile(inlineConfig);
97
- const files = [];
98
- if (file) {
99
- files.push(file);
100
- debug$3("loaded root user config file %s", file);
101
- debug$3("root user configs %O", rootConfigs);
102
- } else debug$3("no root user config file found");
93
+ const { configs: rootConfigs, deps: rootDeps } = await loadConfigFile(inlineConfig);
94
+ const globalDeps = new Set(rootDeps);
103
95
  const configs = (await Promise.all(rootConfigs.map(async (rootConfig) => {
104
- const { configs: workspaceConfigs, files: workspaceFiles } = await resolveWorkspace(rootConfig, inlineConfig);
96
+ const { configs: workspaceConfigs, deps: workspaceDeps } = await resolveWorkspace(rootConfig, inlineConfig, rootDeps);
105
97
  debug$3("workspace configs %O", workspaceConfigs);
106
- if (workspaceFiles) files.push(...workspaceFiles);
107
- return (await Promise.all(workspaceConfigs.filter((config) => !config.workspace || config.entry).map((config) => resolveUserConfig(config, inlineConfig)))).flat().filter((config) => !!config);
98
+ const configs = (await Promise.all(workspaceConfigs.filter((config) => !config.workspace || config.entry).map((config) => resolveUserConfig(config, inlineConfig, workspaceDeps)))).flat().filter((config) => !!config);
99
+ workspaceDeps.forEach((dep) => globalDeps.add(dep));
100
+ return configs;
108
101
  }))).flat();
109
102
  debug$3("resolved configs %O", configs);
110
103
  if (configs.length === 0) throw new Error("No valid configuration found.");
111
104
  return {
112
105
  configs,
113
- files
106
+ deps: globalDeps
114
107
  };
115
108
  }
116
109
  //#endregion
@@ -474,8 +467,8 @@ function resolveChunkAddon(chunkAddon, format) {
474
467
  //#endregion
475
468
  //#region src/features/rolldown.ts
476
469
  const debug = createDebug("tsdown:rolldown");
477
- async function getBuildOptions(config, format, configFiles, bundle, cjsDts = false, isDualFormat) {
478
- const inputOptions = await resolveInputOptions(config, format, configFiles, bundle, cjsDts, isDualFormat);
470
+ async function getBuildOptions(config, format, configDeps, bundle, cjsDts = false, isDualFormat) {
471
+ const inputOptions = await resolveInputOptions(config, format, configDeps, bundle, cjsDts, isDualFormat);
479
472
  const outputOptions = await resolveOutputOptions(inputOptions, config, format, cjsDts);
480
473
  const rolldownConfig = {
481
474
  ...inputOptions,
@@ -485,7 +478,7 @@ async function getBuildOptions(config, format, configFiles, bundle, cjsDts = fal
485
478
  debug("rolldown config with format \"%s\" %O", cjsDts ? "cjs dts" : format, rolldownConfig);
486
479
  return rolldownConfig;
487
480
  }
488
- async function resolveInputOptions(config, format, configFiles, bundle, cjsDts, isDualFormat) {
481
+ async function resolveInputOptions(config, format, configDeps, bundle, cjsDts, isDualFormat) {
489
482
  const { alias, checks: { legacyCjs, ...checks } = {}, cjsDefault, cwd, deps: { neverBundle }, devtools, dts, entry, env, globImport, loader, logger, nameLabel, nodeProtocol, platform, plugins: userPlugins, report, shims, target, treeshake, tsconfig, unused, watch } = config;
490
483
  const plugins = [];
491
484
  if (nodeProtocol) plugins.push(NodeProtocolPlugin(nodeProtocol));
@@ -524,7 +517,7 @@ async function resolveInputOptions(config, format, configFiles, bundle, cjsDts,
524
517
  if (globImport) plugins.push(importGlobPlugin({ root: cwd }));
525
518
  }
526
519
  if (report && LogLevels[logger.level] >= 3) plugins.push(ReportPlugin(config, cjsDts, isDualFormat));
527
- if (watch) plugins.push(WatchPlugin(configFiles, bundle));
520
+ if (watch) plugins.push(WatchPlugin(configDeps, bundle));
528
521
  if (!cjsDts) plugins.push(userPlugins);
529
522
  if (cssPostPlugins) plugins.push(...cssPostPlugins);
530
523
  const define = {
@@ -691,8 +684,8 @@ const asyncDispose = Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose");
691
684
  */
692
685
  async function build$1(inlineConfig = {}) {
693
686
  globalLogger.level = inlineConfig.logLevel || "info";
694
- const { configs, files: configFiles } = await resolveConfig(inlineConfig);
695
- return buildWithConfigs(configs, configFiles, () => build$1(inlineConfig));
687
+ const { configs, deps: configDeps } = await resolveConfig(inlineConfig);
688
+ return buildWithConfigs(configs, configDeps, () => build$1(inlineConfig));
696
689
  }
697
690
  /**
698
691
  * Build with `ResolvedConfigs`.
@@ -700,7 +693,7 @@ async function build$1(inlineConfig = {}) {
700
693
  * **Internal API, not for public use**
701
694
  * @private
702
695
  */
703
- async function buildWithConfigs(configs, configFiles, _restart) {
696
+ async function buildWithConfigs(configs, configDeps, _restart) {
704
697
  let cleanPromise;
705
698
  const clean = () => {
706
699
  if (cleanPromise) return cleanPromise;
@@ -721,7 +714,7 @@ async function buildWithConfigs(configs, configFiles, _restart) {
721
714
  }
722
715
  globalLogger.info("Build start");
723
716
  const bundles = await Promise.all(configs.map((options) => {
724
- return buildSingle(options, configFiles, options.pkg ? configChunksByPkg[options.pkg.packageJsonPath].formats.size > 1 : true, clean, restart, done);
717
+ return buildSingle(options, configDeps, options.pkg ? configChunksByPkg[options.pkg.packageJsonPath].formats.size > 1 : true, clean, restart, done);
725
718
  }));
726
719
  const firstDevtoolsConfig = configs.find((config) => config.devtools && config.devtools.ui);
727
720
  if (configs.some((config) => config.watch)) {
@@ -734,7 +727,7 @@ async function buildWithConfigs(configs, configFiles, _restart) {
734
727
  * Build a single configuration, without watch and shortcuts features.
735
728
  * @param config Resolved options
736
729
  */
737
- async function buildSingle(config, configFiles, isDualFormat, clean, restart, done) {
730
+ async function buildSingle(config, configDeps, isDualFormat, clean, restart, done) {
738
731
  const { format, dts, watch: watch$1, logger, outDir } = config;
739
732
  const { hooks, context } = await createHooks(config);
740
733
  warnLegacyCJS(config);
@@ -781,7 +774,7 @@ async function buildSingle(config, configFiles, isDualFormat, clean, restart, do
781
774
  debouncedPostBuild.cancel();
782
775
  ab?.abort();
783
776
  }
784
- if (configFiles.includes(id) || endsWithConfig.test(id)) {
777
+ if (configDeps.has(id) || endsWithConfig.test(id)) {
785
778
  globalLogger.info(`Reload config: ${id}, restarting...`);
786
779
  restart();
787
780
  }
@@ -824,14 +817,14 @@ async function buildSingle(config, configFiles, isDualFormat, clean, restart, do
824
817
  });
825
818
  }
826
819
  async function initBuildOptions() {
827
- const buildOptions = await getBuildOptions(config, format, configFiles, bundle, false, isDualFormat);
820
+ const buildOptions = await getBuildOptions(config, format, configDeps, bundle, false, isDualFormat);
828
821
  await hooks.callHook("build:before", {
829
822
  ...context,
830
823
  buildOptions
831
824
  });
832
825
  if (debugRolldownConfigDir) await debugBuildOptions(debugRolldownConfigDir, config.name, format, buildOptions);
833
826
  const configs = [buildOptions];
834
- if (format === "cjs" && dts && (!isDualFormat || !dts.cjsReexport)) configs.push(await getBuildOptions(config, format, configFiles, bundle, true, isDualFormat));
827
+ if (format === "cjs" && dts && (!isDualFormat || !dts.cjsReexport)) configs.push(await getBuildOptions(config, format, configDeps, bundle, true, isDualFormat));
835
828
  return configs;
836
829
  }
837
830
  async function postBuild() {
@@ -1,4 +1,4 @@
1
- import { d as UserConfig, f as UserConfigExport, i as InlineConfig, o as ResolvedConfig, p as UserConfigFn } from "./types-C7s2EXSK.mjs";
1
+ import { d as UserConfig, f as UserConfigExport, i as InlineConfig, o as ResolvedConfig, p as UserConfigFn } from "./types-BZNNnDKc.mjs";
2
2
 
3
3
  //#region src/config/options.d.ts
4
4
  /**
@@ -7,7 +7,7 @@ import { d as UserConfig, f as UserConfigExport, i as InlineConfig, o as Resolve
7
7
  * **Internal API, not for public use**
8
8
  * @private
9
9
  */
10
- declare function resolveUserConfig(userConfig: UserConfig, inlineConfig: InlineConfig): Promise<ResolvedConfig[]>;
10
+ declare function resolveUserConfig(userConfig: UserConfig, inlineConfig: InlineConfig, configDeps: Set<string>): Promise<ResolvedConfig[]>;
11
11
  declare function mergeConfig(defaults: UserConfig, ...overrides: UserConfig[]): UserConfig;
12
12
  declare function mergeConfig(defaults: InlineConfig, ...overrides: InlineConfig[]): InlineConfig;
13
13
  //#endregion
package/dist/config.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { d as UserConfig, f as UserConfigExport, p as UserConfigFn } from "./types-C7s2EXSK.mjs";
2
- import { n as mergeConfig, t as defineConfig } from "./config-BjpbFAQr.mjs";
1
+ import { d as UserConfig, f as UserConfigExport, p as UserConfigFn } from "./types-BZNNnDKc.mjs";
2
+ import { n as mergeConfig, t as defineConfig } from "./config-CuK0i1Bc.mjs";
3
3
  export { UserConfig, UserConfigExport, UserConfigFn, defineConfig, mergeConfig };
package/dist/config.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as mergeConfig } from "./options-CAjSicbD.mjs";
1
+ import { t as mergeConfig } from "./options-8hmVMssn.mjs";
2
2
  //#region src/config.ts
3
3
  function defineConfig(options) {
4
4
  return options;
@@ -212,15 +212,5 @@ function formatBytes(bytes) {
212
212
  if (bytes > 1e6) return `${(bytes / 1e6).toFixed(2)} MB`;
213
213
  return `${(bytes / 1e3).toFixed(2)} kB`;
214
214
  }
215
- function detectIndentation(jsonText) {
216
- const lines = jsonText.split(/\r?\n/);
217
- for (const line of lines) {
218
- const match = line.match(/^(\s+)\S/);
219
- if (!match) continue;
220
- if (match[1].includes(" ")) return " ";
221
- return match[1].length;
222
- }
223
- return 2;
224
- }
225
215
  //#endregion
226
- export { getShimsInject as a, resolveDepsConfig as i, formatBytes as n, DepsPlugin as r, detectIndentation as t };
216
+ export { getShimsInject as i, DepsPlugin as n, resolveDepsConfig as r, formatBytes as t };
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { a as Arrayable, i as globalLogger, r as Logger } from "./index-DraNj4FA.mjs";
2
- import { A as RolldownContext, B as TsdownBundle, C as ChunkAddonObject, D as PackageJsonWithPath, E as OutExtensionObject, F as DepsConfig, H as CopyOptions, L as NoExternalFn, M as ExeOptions, N as SeaConfig, O as PackageType, P as DevtoolsOptions, R as ResolvedDepsConfig, S as ChunkAddonFunction, T as OutExtensionFactory, U as CopyOptionsFn, V as CopyEntry, a as NormalizedFormat, b as AttwOptions, c as TreeshakingOptions, d as UserConfig, f as UserConfigExport, g as ReportOptions, h as Workspace, i as InlineConfig, j as TsdownHooks, k as BuildContext, l as TsdownInputOption, m as WithEnabled, n as DtsOptions, o as ResolvedConfig, p as UserConfigFn, r as Format, s as Sourcemap, t as CIOption, u as UnusedOptions, v as PublintOptions, w as OutExtensionContext, x as ChunkAddon, y as ExportsOptions, z as RolldownChunk } from "./types-C7s2EXSK.mjs";
3
- import { n as mergeConfig, r as resolveUserConfig, t as defineConfig } from "./config-BjpbFAQr.mjs";
2
+ import { A as PackageType, B as ResolvedDepsConfig, C as ChunkAddon, D as OutExtensionFactory, E as OutExtensionContext, F as SeaConfig, G as CopyOptionsFn, H as TsdownBundle, I as DevtoolsOptions, L as DepsConfig, M as RolldownContext, N as TsdownHooks, O as OutExtensionObject, P as ExeOptions, S as AttwOptions, T as ChunkAddonObject, U as CopyEntry, V as RolldownChunk, W as CopyOptions, a as NormalizedFormat, b as PublintOptions, c as TreeshakingOptions, d as UserConfig, f as UserConfigExport, g as ReportOptions, h as Workspace, i as InlineConfig, j as BuildContext, k as PackageJsonWithPath, l as TsdownInputOption, m as WithEnabled, n as DtsOptions, o as ResolvedConfig, p as UserConfigFn, r as Format, s as Sourcemap, t as CIOption, u as UnusedOptions, v as TsdownPlugin, w as ChunkAddonFunction, x as ExportsOptions, y as TsdownPluginOption, z as NoExternalFn } from "./types-BZNNnDKc.mjs";
3
+ import { n as mergeConfig, r as resolveUserConfig, t as defineConfig } from "./config-CuK0i1Bc.mjs";
4
4
  import * as Rolldown from "rolldown";
5
5
 
6
6
  //#region src/build.d.ts
@@ -14,9 +14,9 @@ declare function build(inlineConfig?: InlineConfig): Promise<TsdownBundle[]>;
14
14
  * **Internal API, not for public use**
15
15
  * @private
16
16
  */
17
- declare function buildWithConfigs(configs: ResolvedConfig[], configFiles: string[], _restart: () => void): Promise<TsdownBundle[]>;
17
+ declare function buildWithConfigs(configs: ResolvedConfig[], configDeps: Set<string>, _restart: () => void): Promise<TsdownBundle[]>;
18
18
  //#endregion
19
19
  //#region src/features/debug.d.ts
20
20
  declare function enableDebug(debug?: boolean | Arrayable<string>): void;
21
21
  //#endregion
22
- export { AttwOptions, BuildContext, CIOption, ChunkAddon, ChunkAddonFunction, ChunkAddonObject, CopyEntry, CopyOptions, CopyOptionsFn, DepsConfig, DevtoolsOptions, DtsOptions, ExeOptions, ExportsOptions, Format, InlineConfig, type Logger, NoExternalFn, NormalizedFormat, OutExtensionContext, OutExtensionFactory, OutExtensionObject, PackageJsonWithPath, PackageType, PublintOptions, ReportOptions, ResolvedConfig, ResolvedDepsConfig, Rolldown, RolldownChunk, RolldownContext, SeaConfig, Sourcemap, TreeshakingOptions, TsdownBundle, TsdownHooks, TsdownInputOption, UnusedOptions, UserConfig, UserConfigExport, UserConfigFn, WithEnabled, Workspace, build, buildWithConfigs, defineConfig, enableDebug, globalLogger, mergeConfig, resolveUserConfig };
22
+ export { AttwOptions, BuildContext, CIOption, ChunkAddon, ChunkAddonFunction, ChunkAddonObject, CopyEntry, CopyOptions, CopyOptionsFn, DepsConfig, DevtoolsOptions, DtsOptions, ExeOptions, ExportsOptions, Format, InlineConfig, type Logger, NoExternalFn, NormalizedFormat, OutExtensionContext, OutExtensionFactory, OutExtensionObject, PackageJsonWithPath, PackageType, PublintOptions, ReportOptions, ResolvedConfig, ResolvedDepsConfig, Rolldown, RolldownChunk, RolldownContext, SeaConfig, Sourcemap, TreeshakingOptions, TsdownBundle, TsdownHooks, TsdownInputOption, TsdownPlugin, TsdownPluginOption, UnusedOptions, UserConfig, UserConfigExport, UserConfigFn, WithEnabled, Workspace, build, buildWithConfigs, defineConfig, enableDebug, globalLogger, mergeConfig, resolveUserConfig };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { n as buildWithConfigs, t as build } from "./build-y6nUUkVJ.mjs";
2
- import { r as resolveUserConfig, t as mergeConfig } from "./options-CAjSicbD.mjs";
1
+ import { n as buildWithConfigs, t as build } from "./build-OX8uszs6.mjs";
2
+ import { r as resolveUserConfig, t as mergeConfig } from "./options-8hmVMssn.mjs";
3
3
  import { a as globalLogger } from "./logger-uV8l1UFa.mjs";
4
4
  import { defineConfig } from "./config.mjs";
5
5
  import { t as enableDebug } from "./debug-CLlnG64L.mjs";
@@ -3,7 +3,7 @@ const __cjs_require = __cjs_createRequire(import.meta.url);
3
3
  import { a as lowestCommonAncestor, i as fsStat, n as fsExists, o as stripExtname, r as fsRemove } from "./fs-Dd6Htx2P.mjs";
4
4
  import { a as pkgExists, c as resolveRegex, l as slash, n as importWithError, r as matchPattern, s as resolveComma, u as toArray } from "./general-D3muxt2f.mjs";
5
5
  import { a as globalLogger, i as getNameLabel, n as createLogger, r as generateColor } from "./logger-uV8l1UFa.mjs";
6
- import { i as resolveDepsConfig, n as formatBytes, t as detectIndentation } from "./format-a5Q6w07o.mjs";
6
+ import { r as resolveDepsConfig, t as formatBytes } from "./format-CajNSstg.mjs";
7
7
  import { n as resolveTarget } from "./target-s30wya8e.mjs";
8
8
  import { mkdir, mkdtemp, readFile, writeFile } from "node:fs/promises";
9
9
  import path from "node:path";
@@ -18,10 +18,11 @@ import { tmpdir } from "node:os";
18
18
  const satisfies = __cjs_require("semver/functions/satisfies.js");
19
19
  import { x } from "tinyexec";
20
20
  import { readFileSync, writeFileSync } from "node:fs";
21
+ import { isDeepStrictEqual } from "node:util";
21
22
  import { up } from "empathic/find";
22
23
  import { up as up$1 } from "empathic/package";
23
24
  import { pathToFileURL } from "node:url";
24
- import { init, isSupported } from "import-without-cache";
25
+ import { depsStore, init, isSupported } from "import-without-cache";
25
26
  import { createConfigCoreLoader } from "unconfig-core";
26
27
  //#region node_modules/.pnpm/is-in-ci@2.0.0/node_modules/is-in-ci/index.js
27
28
  const check = (key) => key in env && env[key] !== "0" && env[key] !== "false";
@@ -231,25 +232,54 @@ async function buildSingleExe(config, bundledFile, outputFile, executable, targe
231
232
  config.logger.success(config.nameLabel, `Built executable: ${red(path.relative(config.cwd, outputPath))}`, dim`(${Math.round(performance.now() - t)}ms)`);
232
233
  }
233
234
  //#endregion
235
+ //#region src/utils/json.ts
236
+ function writeJsonFile(filePath, content) {
237
+ let originalText;
238
+ let originalJson = void 0;
239
+ let originalIndent = 2;
240
+ let originalEOL = "\n";
241
+ let originalHasTrailingNewline = false;
242
+ try {
243
+ originalText = readFileSync(filePath, "utf8");
244
+ originalJson = JSON.parse(originalText);
245
+ originalIndent = detectIndentation(originalText);
246
+ if (originalText.includes("\r\n")) originalEOL = "\r\n";
247
+ if (originalText.endsWith("\n")) originalHasTrailingNewline = true;
248
+ } catch {}
249
+ if (originalJson && (isDeepStrictEqual(originalJson, content) || JSON.stringify(originalJson) === JSON.stringify(content))) return;
250
+ let jsonString = JSON.stringify(content, null, originalIndent);
251
+ if (originalEOL !== "\n") jsonString = jsonString.replaceAll("\n", originalEOL);
252
+ if (originalHasTrailingNewline) jsonString += originalEOL;
253
+ if (originalText === jsonString) return;
254
+ writeFileSync(filePath, jsonString, "utf8");
255
+ }
256
+ function detectIndentation(jsonText) {
257
+ const lines = jsonText.split(/\r?\n/);
258
+ for (const line of lines) {
259
+ const match = line.match(/^(\s+)\S/);
260
+ if (!match) continue;
261
+ if (match[1].includes(" ")) return " ";
262
+ return match[1].length;
263
+ }
264
+ return 2;
265
+ }
266
+ //#endregion
234
267
  //#region src/features/pkg/exports.ts
235
268
  async function writeExports(options, chunks, inlinedDeps) {
236
269
  const { pkg } = options;
237
- const { publishExports, bin, ...generated } = await generateExports(pkg, chunks, options, inlinedDeps);
270
+ const { publishExports, publishBin, bin, ...generated } = await generateExports(pkg, chunks, options, inlinedDeps);
238
271
  const updatedPkg = {
239
272
  ...pkg,
240
273
  ...generated,
241
274
  ...bin === void 0 ? {} : { bin },
242
275
  packageJsonPath: void 0
243
276
  };
244
- if (publishExports) {
277
+ if (publishExports || publishBin) {
245
278
  updatedPkg.publishConfig ||= {};
246
- updatedPkg.publishConfig.exports = publishExports;
279
+ if (publishExports) updatedPkg.publishConfig.exports = publishExports;
280
+ if (publishBin) updatedPkg.publishConfig.bin = publishBin;
247
281
  }
248
- const original = readFileSync(pkg.packageJsonPath, "utf8");
249
- let contents = JSON.stringify(updatedPkg, null, detectIndentation(original));
250
- if (original.includes("\r\n")) contents = contents.replaceAll("\n", "\r\n");
251
- if (original.endsWith("\n")) contents += "\n";
252
- if (contents !== original) writeFileSync(pkg.packageJsonPath, contents, "utf8");
282
+ writeJsonFile(pkg.packageJsonPath, updatedPkg);
253
283
  }
254
284
  function shouldExclude(fileName, exclude) {
255
285
  if (!exclude?.length) return false;
@@ -331,12 +361,15 @@ async function generateExports(pkg, chunks, options, inlinedDeps) {
331
361
  isPublish: true
332
362
  });
333
363
  }
364
+ const binResult = generateBin(bin, !!devExports, pkg, chunks, pkgRoot, logger, cwd);
365
+ const publishBin = devExports && binResult ? generateBin(bin, false, pkg, chunks, pkgRoot, logger, cwd) : void 0;
334
366
  return {
335
367
  main: legacy ? main || module || pkg.main : void 0,
336
368
  module: legacy ? module || pkg.module : void 0,
337
369
  types: legacy ? cjsTypes || esmTypes || pkg.types : pkg.types,
338
370
  exports,
339
- bin: generateBin(bin, pkg, chunks, pkgRoot, logger, cwd),
371
+ bin: binResult,
372
+ publishBin,
340
373
  inlinedDependencies: emitInlinedDeps ? inlinedDeps : void 0,
341
374
  publishExports
342
375
  };
@@ -379,7 +412,7 @@ function hasExportsTypes(pkg) {
379
412
  return false;
380
413
  }
381
414
  const RE_SHEBANG = /^#!.*/;
382
- function generateBin(bin, pkg, chunks, pkgRoot, logger, cwd) {
415
+ function generateBin(bin, devExports, pkg, chunks, pkgRoot, logger, cwd) {
383
416
  if (!bin) return;
384
417
  if (bin === true || typeof bin === "string") {
385
418
  if (!pkg.name) throw new Error("Package name is required when using string form for `bin`");
@@ -396,7 +429,7 @@ function generateBin(bin, pkg, chunks, pkgRoot, logger, cwd) {
396
429
  if (seen.has(chunk.facadeModuleId)) continue;
397
430
  seen.add(chunk.facadeModuleId);
398
431
  if (detected) throw new Error("Multiple entry chunks with shebangs found. Use `exports.bin: { name: \"./src/file.ts\" }` to specify which one to use.");
399
- detected = join(pkgRoot, chunk.outDir, slash(chunk.fileName));
432
+ detected = devExports ? `./${slash(path.relative(pkgRoot, chunk.facadeModuleId))}` : join(pkgRoot, chunk.outDir, slash(chunk.fileName));
400
433
  }
401
434
  }
402
435
  if (detected == null) {
@@ -408,16 +441,20 @@ function generateBin(bin, pkg, chunks, pkgRoot, logger, cwd) {
408
441
  if (typeof bin === "string") {
409
442
  const match = findChunkBySource(bin);
410
443
  if (!match) throw new Error(`Could not find output chunk for bin entry "${bin}"`);
411
- return { [binName]: match };
444
+ return { [binName]: devExports ? normalizeSource(bin) : match };
412
445
  }
413
446
  }
414
447
  const result = {};
415
448
  for (const [cmdName, sourcePath] of Object.entries(bin)) {
416
449
  const match = findChunkBySource(sourcePath);
417
450
  if (!match) throw new Error(`Could not find output chunk for bin entry "${cmdName}": "${sourcePath}"`);
418
- result[cmdName] = match;
451
+ result[cmdName] = devExports ? normalizeSource(sourcePath) : match;
419
452
  }
420
453
  return result;
454
+ function normalizeSource(sourcePath) {
455
+ const resolved = path.resolve(cwd, sourcePath);
456
+ return `./${slash(path.relative(pkgRoot, resolved))}`;
457
+ }
421
458
  function findChunkBySource(sourcePath) {
422
459
  const resolved = path.resolve(cwd, sourcePath);
423
460
  for (const format of ["es", "cjs"]) {
@@ -448,6 +485,14 @@ function join(pkgRoot, outDir, fileName) {
448
485
  return `${outDirRelative ? `./${outDirRelative}` : "."}/${fileName}`;
449
486
  }
450
487
  //#endregion
488
+ //#region src/features/plugin.ts
489
+ async function flattenPlugins(plugins) {
490
+ const awaited = await plugins;
491
+ if (!awaited) return [];
492
+ if (Array.isArray(awaited)) return (await Promise.all(awaited.map(flattenPlugins))).flat();
493
+ return [awaited];
494
+ }
495
+ //#endregion
451
496
  //#region src/features/tsconfig.ts
452
497
  function findTsconfig(cwd, name = "tsconfig.json") {
453
498
  return up(name, { cwd }) || false;
@@ -526,14 +571,17 @@ async function loadViteConfig(prefix, cwd, configLoader) {
526
571
  cwd
527
572
  }).load(true);
528
573
  if (!result) return;
529
- const { config, source } = result;
574
+ let { config: [exported, deps], source } = result;
530
575
  globalLogger.info(`Using Vite config: ${underline(source)}`);
531
- const resolved = await config;
532
- if (typeof resolved === "function") return resolved({
576
+ exported = await exported;
577
+ if (typeof exported === "function") exported = await exported({
533
578
  command: "build",
534
579
  mode: "production"
535
580
  });
536
- return resolved;
581
+ return {
582
+ config: exported,
583
+ deps
584
+ };
537
585
  }
538
586
  const configPrefix = "tsdown.config";
539
587
  async function loadConfigFile(inlineConfig, workspace, rootConfig) {
@@ -581,8 +629,9 @@ async function loadConfigFile(inlineConfig, workspace, rootConfig) {
581
629
  }).load(true);
582
630
  let exported = [];
583
631
  let file;
632
+ let deps;
584
633
  if (result) {
585
- ({config: exported, source: file} = result);
634
+ ({config: [exported, deps], source: file} = result);
586
635
  globalLogger.info(`config file: ${underline(file)}`, loader === "native" ? "" : `(${loader})`);
587
636
  exported = await exported;
588
637
  if (typeof exported === "function") exported = await exported(inlineConfig, {
@@ -598,7 +647,7 @@ async function loadConfigFile(inlineConfig, workspace, rootConfig) {
598
647
  ...config,
599
648
  cwd: config.cwd ? path.resolve(cwd, config.cwd) : cwd
600
649
  })),
601
- file
650
+ deps
602
651
  };
603
652
  }
604
653
  const isBun = !!process.versions.bun;
@@ -615,31 +664,30 @@ function createParser(loader) {
615
664
  if (basename === configPrefix || isPkgJson || basename.endsWith(".json")) {
616
665
  const contents = await readFile(filepath, "utf8");
617
666
  const parsed = JSON.parse(contents);
618
- if (isPkgJson) return parsed?.tsdown;
619
- return parsed;
667
+ return [isPkgJson ? parsed?.tsdown : parsed, new Set([filepath])];
620
668
  }
621
- if (loader === "native") return nativeImport(filepath);
622
- return unrunImport(filepath);
669
+ return (loader === "native" ? nativeImport : unrunImport)(filepath);
623
670
  };
624
671
  }
625
672
  async function nativeImport(id) {
673
+ const deps = new Set([id]);
626
674
  const url = pathToFileURL(id);
627
675
  const importAttributes = Object.create(null);
628
676
  if (isSupported) {
629
677
  importAttributes.cache = "no";
630
678
  init({ skipNodeModules: true });
631
679
  } else if (!isBun) url.searchParams.set("no-cache", crypto.randomUUID());
632
- const mod = await import(url.href, { with: importAttributes }).catch((error) => {
680
+ const mod = await depsStore.run(deps, () => import(url.href, { with: importAttributes }).catch((error) => {
633
681
  if (error?.message?.includes?.("Cannot find module")) throw new Error(`Failed to load the config file. Try setting the --config-loader CLI flag to \`unrun\`.\n\n${error.message}`, { cause: error });
634
682
  if (typeof error?.stack === "string" && error.stack.includes("node:internal/modules/esm/translators")) throw new Error(`Failed to load the config file due to a known Node.js bug. Try setting the --config-loader CLI flag to \`unrun\` or upgrading Node.js to v24.11.1 or later.\n\n${error.message}`, { cause: error });
635
683
  throw error;
636
- });
637
- return mod.default || mod;
684
+ }));
685
+ return [mod.default || mod, deps];
638
686
  }
639
687
  async function unrunImport(id) {
640
688
  const { unrun } = await import("unrun");
641
- const { module } = await unrun({ path: pathToFileURL(id).href });
642
- return module;
689
+ const { module, dependencies } = await unrun({ path: pathToFileURL(id).href });
690
+ return [module, new Set(dependencies)];
643
691
  }
644
692
  //#endregion
645
693
  //#region src/config/options.ts
@@ -651,7 +699,14 @@ const parseEnv = process.getBuiltinModule("node:util").parseEnv;
651
699
  * **Internal API, not for public use**
652
700
  * @private
653
701
  */
654
- async function resolveUserConfig(userConfig, inlineConfig) {
702
+ async function resolveUserConfig(userConfig, inlineConfig, configDeps) {
703
+ {
704
+ const flat = await flattenPlugins(userConfig.plugins);
705
+ for (const plugin of flat) {
706
+ const result = await plugin.tsdownConfig?.(userConfig, inlineConfig);
707
+ if (result) userConfig = mergeConfig(userConfig, result);
708
+ }
709
+ }
655
710
  let { entry, format, plugins = [], clean = true, logLevel = "info", failOnWarn = false, customLogger, treeshake = true, platform = "node", outDir = "dist", sourcemap = false, dts, unused = false, watch = false, ignoreWatch, shims = false, publint = false, attw = false, fromVite, alias, tsconfig, report = true, target, env = {}, envFile, envPrefix = "TSDOWN_", copy, publicDir, hash = true, cwd = process.cwd(), name, workspace, exports = false, bundle, unbundle = typeof bundle === "boolean" ? !bundle : false, root, removeNodeProtocol, nodeProtocol, cjsDefault = true, globImport = true, css, injectStyle, fixedExtension = platform === "node", devtools = false, write = true, exe = false } = userConfig;
656
711
  const pkg = await readPackageJson(cwd);
657
712
  if (workspace) name ||= pkg?.name;
@@ -716,16 +771,19 @@ async function resolveUserConfig(userConfig, inlineConfig) {
716
771
  ...env
717
772
  };
718
773
  debug(`Environment variables: %O`, env);
774
+ configDeps = new Set(configDeps);
719
775
  if (fromVite) {
720
776
  const viteUserConfig = await loadViteConfig(fromVite === true ? "vite" : fromVite, cwd, inlineConfig.configLoader);
721
777
  if (viteUserConfig) {
722
- const viteAlias = viteUserConfig.resolve?.alias;
778
+ const { config, deps } = viteUserConfig;
779
+ deps?.forEach((dep) => configDeps.add(dep));
780
+ const viteAlias = config.resolve?.alias;
723
781
  if (Array.isArray(viteAlias)) throw new TypeError("Unsupported resolve.alias in Vite config. Use object instead of array");
724
782
  if (viteAlias) alias = {
725
783
  ...alias,
726
784
  ...viteAlias
727
785
  };
728
- if (viteUserConfig.plugins) plugins = [viteUserConfig.plugins, plugins];
786
+ if (config.plugins) plugins = [config.plugins, plugins];
729
787
  }
730
788
  }
731
789
  ignoreWatch = toArray(ignoreWatch).map((ignore) => {
@@ -745,6 +803,7 @@ async function resolveUserConfig(userConfig, inlineConfig) {
745
803
  attw,
746
804
  cjsDefault,
747
805
  clean,
806
+ configDeps,
748
807
  copy: publicDir || copy,
749
808
  css,
750
809
  cwd,
@@ -783,7 +842,7 @@ async function resolveUserConfig(userConfig, inlineConfig) {
783
842
  };
784
843
  if (exe) validateSea(config);
785
844
  const objectFormat = typeof format === "object" && !Array.isArray(format);
786
- return (objectFormat ? Object.keys(format) : resolveComma(toArray(format, "esm"))).map((fmt, idx) => {
845
+ const resolvedConfigs = (objectFormat ? Object.keys(format) : resolveComma(toArray(format, "esm"))).map((fmt, idx) => {
787
846
  const once = idx === 0;
788
847
  const overrides = objectFormat ? format[fmt] : void 0;
789
848
  return {
@@ -794,6 +853,11 @@ async function resolveUserConfig(userConfig, inlineConfig) {
794
853
  ...overrides
795
854
  };
796
855
  });
856
+ for (const resolved of resolvedConfigs) {
857
+ const finalPlugins = await flattenPlugins(resolved.plugins);
858
+ for (const plugin of finalPlugins) await plugin.tsdownConfigResolved?.(resolved);
859
+ }
860
+ return resolvedConfigs;
797
861
  }
798
862
  /** filter env variables by prefixes */
799
863
  function filterEnv(envDict, envPrefixes) {
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "0.21.8";
2
+ var version = "0.21.9";
3
3
  //#endregion
4
4
  export { version as t };
@@ -1,5 +1,5 @@
1
1
  import { r as Logger } from "./index-DraNj4FA.mjs";
2
- import { B as TsdownBundle, I as DepsPlugin, _ as ReportPlugin } from "./types-C7s2EXSK.mjs";
2
+ import { H as TsdownBundle, R as DepsPlugin, _ as ReportPlugin } from "./types-BZNNnDKc.mjs";
3
3
  import { Plugin } from "rolldown";
4
4
 
5
5
  //#region src/features/node-protocol.d.ts
@@ -13,7 +13,7 @@ declare function NodeProtocolPlugin(nodeProtocolOption: "strip" | true): Plugin;
13
13
  declare function ShebangPlugin(logger: Logger, cwd: string, nameLabel?: string, isDualFormat?: boolean): Plugin;
14
14
  //#endregion
15
15
  //#region src/features/watch.d.ts
16
- declare function WatchPlugin(configFiles: string[], {
16
+ declare function WatchPlugin(configDeps: Set<string>, {
17
17
  config,
18
18
  chunks
19
19
  }: TsdownBundle): Plugin;
package/dist/plugins.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { r as DepsPlugin } from "./format-a5Q6w07o.mjs";
2
- import { a as ReportPlugin, i as ShebangPlugin, o as NodeProtocolPlugin, t as WatchPlugin } from "./watch-C9ZHIctp.mjs";
1
+ import { n as DepsPlugin } from "./format-CajNSstg.mjs";
2
+ import { a as ReportPlugin, i as ShebangPlugin, o as NodeProtocolPlugin, t as WatchPlugin } from "./watch-D6EGzM6P.mjs";
3
3
  export { DepsPlugin, NodeProtocolPlugin, ReportPlugin, ShebangPlugin, WatchPlugin };
package/dist/run.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import { createRequire as __cjs_createRequire } from "node:module";
3
3
  const __cjs_require = __cjs_createRequire(import.meta.url);
4
4
  import { a as globalLogger } from "./logger-uV8l1UFa.mjs";
5
- import { t as version } from "./package-yVk5dXcU.mjs";
5
+ import { t as version } from "./package-JOXUdJGa.mjs";
6
6
  import { t as enableDebug } from "./debug-CLlnG64L.mjs";
7
7
  import module from "node:module";
8
8
  import process from "node:process";
@@ -20,7 +20,7 @@ cli.command("[...files]", "Bundle files", {
20
20
  }).option("-c, --config <filename>", "Use a custom config file").option("--config-loader <loader>", "Config loader to use: auto, native, unrun", { default: "auto" }).option("--no-config", "Disable config file").option("-f, --format <format>", "Bundle format: esm, cjs, iife, umd", { default: "esm" }).option("--clean", "Clean output directory, --no-clean to disable").option("--deps.never-bundle <module>", "Mark dependencies as external").option("--minify", "Minify output").option("--devtools", "Enable devtools integration").option("--debug [feat]", "Show debug logs").option("--target <target>", "Bundle target, e.g \"es2015\", \"esnext\"").option("-l, --logLevel <level>", "Set log level: info, warn, error, silent").option("--fail-on-warn", "Fail on warnings", { default: true }).option("--no-write", "Disable writing files to disk, incompatible with watch mode").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("--attw", "Enable Are the types wrong integration", { default: false }).option("--unused", "Enable unused dependencies check", { default: false }).option("-w, --watch [path]", "Watch mode").option("--ignore-watch <path>", "Ignore custom paths in 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("--env-file <file>", "Load environment variables from a file, when used together with --env, variables in --env take precedence").option("--env-prefix <prefix>", "Prefix for env variables to inject into the bundle", { default: "TSDOWN_" }).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").option("--unbundle", "Unbundle mode").option("--root <dir>", "Root directory of input files").option("--exe", "Bundle as executable").option("-W, --workspace [dir]", "Enable workspace mode").option("-F, --filter <pattern>", "Filter configs (cwd or name), e.g. /pkg-name$/ or pkg-name").option("--exports", "Generate export-related metadata for package.json (experimental)").action(async (input, flags) => {
21
21
  globalLogger.level = flags.logLevel || "info";
22
22
  globalLogger.info(`${blue`tsdown v${version}`} powered by ${hex("#ff7e17")`rolldown v${VERSION}`}`);
23
- const { build } = await import("./build-y6nUUkVJ.mjs").then((n) => n.r);
23
+ const { build } = await import("./build-OX8uszs6.mjs").then((n) => n.r);
24
24
  if (input.length > 0) flags.entry = input;
25
25
  await build(flags);
26
26
  });
@@ -54,7 +54,7 @@ async function runCLI() {
54
54
  }
55
55
  //#endregion
56
56
  //#region src/run.ts
57
- if (lt(process.version, "22.18.0")) console.warn(yellow`[tsdown] Node.js ${process.version} is deprecated. Support will be removed in the next minor release. Please upgrade to Node.js 22.18.0 or later.`);
57
+ if (!process.versions.bun && lt(process.version, "22.18.0")) console.warn(yellow`[tsdown] Node.js ${process.version} is deprecated. Support will be removed in the next minor release. Please upgrade to Node.js v22.18.0 or later.`);
58
58
  try {
59
59
  module.enableCompileCache?.();
60
60
  } catch {}
@@ -1,5 +1,5 @@
1
1
  import { a as Arrayable, c as Overwrite, n as LogLevel, o as Awaitable, r as Logger, s as MarkPartial, t as PackageJson } from "./index-DraNj4FA.mjs";
2
- import { BuildOptions, ChecksOptions, ExternalOption, InputOptions, InternalModuleFormat, MinifyOptions, ModuleFormat, ModuleTypes, OutputAsset, OutputChunk, OutputOptions, Plugin, TreeshakingOptions } from "rolldown";
2
+ import { BuildOptions, ChecksOptions, ExternalOption, InputOptions, InternalModuleFormat, MinifyOptions, ModuleFormat, ModuleTypes, OutputAsset, OutputChunk, OutputOptions, Plugin, RolldownPlugin, TreeshakingOptions } from "rolldown";
3
3
  import { Hookable } from "hookable";
4
4
  import { Buffer } from "node:buffer";
5
5
  import * as _$_tsdown_css0 from "@tsdown/css";
@@ -376,6 +376,56 @@ interface PublintOptions extends Omit<Options, "pack" | "pkgDir"> {
376
376
  module?: [typeof _$publint, typeof _$publint_utils0];
377
377
  }
378
378
  //#endregion
379
+ //#region src/features/plugin.d.ts
380
+ /**
381
+ * A tsdown-aware plugin. Extends Rolldown's `Plugin` with tsdown-specific
382
+ * lifecycle hooks.
383
+ *
384
+ * Plugins that only use Rolldown's own lifecycle continue to work unchanged;
385
+ * tsdown detects these optional methods via runtime duck-typing.
386
+ */
387
+ interface TsdownPlugin<A = any> extends Plugin<A> {
388
+ /**
389
+ * Modify tsdown's user config before it is resolved. Analogous to Vite's
390
+ * [`config`](https://vite.dev/guide/api-plugin.html#config) hook.
391
+ *
392
+ * The hook may mutate `config` in place, or return a partial {@link UserConfig}
393
+ * that will be deep-merged into the current config. Array fields are
394
+ * replaced (not concatenated) during merging — to append plugins, mutate
395
+ * `config.plugins` in place.
396
+ *
397
+ * The second argument is the original {@link InlineConfig} passed to
398
+ * `build()` (typically the CLI flags), useful for distinguishing values
399
+ * that came from the command line vs. the config file.
400
+ *
401
+ * Plugins injected via `fromVite` do not receive this hook, because they
402
+ * are loaded after the tsdownConfig phase. Likewise, new plugins added by
403
+ * another plugin's `tsdownConfig` do not themselves receive this hook
404
+ * (plugins are snapshotted before dispatch).
405
+ */
406
+ tsdownConfig?: (config: UserConfig, inlineConfig: InlineConfig) => Awaitable<UserConfig | void | null>;
407
+ /**
408
+ * Called after tsdown has fully resolved the user config. Analogous to
409
+ * Vite's [`configResolved`](https://vite.dev/guide/api-plugin.html#configresolved)
410
+ * hook.
411
+ *
412
+ * This hook fires once per produced {@link ResolvedConfig} — i.e. once
413
+ * per output format when `format` is an array. Typical usage is to stash
414
+ * the resolved config for later use in Rolldown hooks. Mutations made to
415
+ * `resolvedConfig` here are not supported.
416
+ */
417
+ tsdownConfigResolved?: (resolvedConfig: ResolvedConfig) => Awaitable<void>;
418
+ }
419
+ /**
420
+ * A tsdown plugin slot — accepts tsdown plugins, any Rolldown plugin form,
421
+ * `null`/`undefined`/`false`, promises, and nested arrays. Mirrors Rolldown's
422
+ * {@link RolldownPluginOption} but with {@link TsdownPlugin} as the atom so
423
+ * that tsdown-specific hooks are type-checked.
424
+ */
425
+ type TsdownPluginOption<A = any> = Awaitable<TsdownPlugin<A> | RolldownPlugin<A> | {
426
+ name: string;
427
+ } | undefined | null | void | false | TsdownPluginOption<A>[]>;
428
+ //#endregion
379
429
  //#region src/features/report.d.ts
380
430
  interface ReportOptions {
381
431
  /**
@@ -623,7 +673,7 @@ interface UserConfig {
623
673
  */
624
674
  legacyCjs?: boolean;
625
675
  };
626
- plugins?: InputOptions["plugins"];
676
+ plugins?: TsdownPluginOption;
627
677
  /**
628
678
  * Use with caution; ensure you understand the implications.
629
679
  */
@@ -894,6 +944,7 @@ type ResolvedConfig = Overwrite<MarkPartial<Omit<UserConfig, "workspace" | "from
894
944
  ignoreWatch: Array<string | RegExp>;
895
945
  deps: ResolvedDepsConfig; /** Resolved root directory of input files */
896
946
  root: string;
947
+ configDeps: Set<string>;
897
948
  dts: false | DtsOptions;
898
949
  report: false | ReportOptions;
899
950
  tsconfig: false | string;
@@ -905,4 +956,4 @@ type ResolvedConfig = Overwrite<MarkPartial<Omit<UserConfig, "workspace" | "from
905
956
  exe: false | ExeOptions;
906
957
  }>;
907
958
  //#endregion
908
- export { RolldownContext as A, TsdownBundle as B, ChunkAddonObject as C, PackageJsonWithPath as D, OutExtensionObject as E, DepsConfig as F, CopyOptions as H, DepsPlugin as I, NoExternalFn as L, ExeOptions as M, SeaConfig as N, PackageType as O, DevtoolsOptions as P, ResolvedDepsConfig as R, ChunkAddonFunction as S, OutExtensionFactory as T, CopyOptionsFn as U, CopyEntry as V, ReportPlugin as _, NormalizedFormat as a, AttwOptions as b, TreeshakingOptions as c, UserConfig as d, UserConfigExport as f, ReportOptions as g, Workspace as h, InlineConfig as i, TsdownHooks as j, BuildContext as k, TsdownInputOption as l, WithEnabled as m, DtsOptions as n, ResolvedConfig as o, UserConfigFn as p, Format as r, Sourcemap as s, CIOption as t, UnusedOptions as u, PublintOptions as v, OutExtensionContext as w, ChunkAddon as x, ExportsOptions as y, RolldownChunk as z };
959
+ export { PackageType as A, ResolvedDepsConfig as B, ChunkAddon as C, OutExtensionFactory as D, OutExtensionContext as E, SeaConfig as F, CopyOptionsFn as G, TsdownBundle as H, DevtoolsOptions as I, DepsConfig as L, RolldownContext as M, TsdownHooks as N, OutExtensionObject as O, ExeOptions as P, DepsPlugin as R, AttwOptions as S, ChunkAddonObject as T, CopyEntry as U, RolldownChunk as V, CopyOptions as W, ReportPlugin as _, NormalizedFormat as a, PublintOptions as b, TreeshakingOptions as c, UserConfig as d, UserConfigExport as f, ReportOptions as g, Workspace as h, InlineConfig as i, BuildContext as j, PackageJsonWithPath as k, TsdownInputOption as l, WithEnabled as m, DtsOptions as n, ResolvedConfig as o, UserConfigFn as p, Format as r, Sourcemap as s, CIOption as t, UnusedOptions as u, TsdownPlugin as v, ChunkAddonFunction as w, ExportsOptions as x, TsdownPluginOption as y, NoExternalFn as z };
@@ -1,7 +1,7 @@
1
1
  import { n as fsExists, t as fsCopy } from "./fs-Dd6Htx2P.mjs";
2
2
  import { i as noop, s as resolveComma, u as toArray } from "./general-D3muxt2f.mjs";
3
3
  import { o as prettyFormat } from "./logger-uV8l1UFa.mjs";
4
- import { n as formatBytes } from "./format-a5Q6w07o.mjs";
4
+ import { t as formatBytes } from "./format-CajNSstg.mjs";
5
5
  import { builtinModules } from "node:module";
6
6
  import { chmod } from "node:fs/promises";
7
7
  import path from "node:path";
@@ -204,7 +204,7 @@ function addOutDirToChunks(chunks, outDir) {
204
204
  //#endregion
205
205
  //#region src/features/watch.ts
206
206
  const endsWithConfig = /[\\/](?:tsdown\.config.*|package\.json|tsconfig\.json)$/;
207
- function WatchPlugin(configFiles, { config, chunks }) {
207
+ function WatchPlugin(configDeps, { config, chunks }) {
208
208
  return {
209
209
  name: "tsdown:watch",
210
210
  options: config.ignoreWatch.length ? (inputOptions) => {
@@ -214,7 +214,7 @@ function WatchPlugin(configFiles, { config, chunks }) {
214
214
  } : void 0,
215
215
  async buildStart() {
216
216
  config.tsconfig && this.addWatchFile(config.tsconfig);
217
- for (const file of configFiles) this.addWatchFile(file);
217
+ for (const file of configDeps) this.addWatchFile(file);
218
218
  if (typeof config.watch !== "boolean") for (const file of resolveComma(toArray(config.watch))) this.addWatchFile(file);
219
219
  if (config.pkg) this.addWatchFile(config.pkg.packageJsonPath);
220
220
  if (config.copy) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tsdown",
3
3
  "type": "module",
4
- "version": "0.21.8",
4
+ "version": "0.21.9",
5
5
  "description": "The Elegant Bundler for Libraries",
6
6
  "author": "Kevin Deng <sxzz@sxzz.moe>",
7
7
  "license": "MIT",
@@ -52,8 +52,8 @@
52
52
  "publint": "^0.3.0",
53
53
  "typescript": "^5.0.0 || ^6.0.0",
54
54
  "unplugin-unused": "^0.5.0",
55
- "@tsdown/css": "0.21.8",
56
- "@tsdown/exe": "0.21.8"
55
+ "@tsdown/css": "0.21.9",
56
+ "@tsdown/exe": "0.21.9"
57
57
  },
58
58
  "peerDependenciesMeta": {
59
59
  "@arethetypeswrong/core": {
@@ -83,18 +83,18 @@
83
83
  "cac": "^7.0.0",
84
84
  "defu": "^6.1.7",
85
85
  "empathic": "^2.0.0",
86
- "hookable": "^6.1.0",
87
- "import-without-cache": "^0.2.5",
86
+ "hookable": "^6.1.1",
87
+ "import-without-cache": "^0.3.3",
88
88
  "obug": "^2.1.1",
89
89
  "picomatch": "^4.0.4",
90
- "rolldown": "1.0.0-rc.15",
90
+ "rolldown": "1.0.0-rc.16",
91
91
  "rolldown-plugin-dts": "^0.23.2",
92
92
  "semver": "^7.7.4",
93
93
  "tinyexec": "^1.1.1",
94
94
  "tinyglobby": "^0.2.16",
95
95
  "tree-kill": "^1.2.2",
96
96
  "unconfig-core": "^7.5.0",
97
- "unrun": "^0.2.34"
97
+ "unrun": "^0.2.36"
98
98
  },
99
99
  "inlinedDependencies": {
100
100
  "is-in-ci": "2.0.0",
@@ -109,13 +109,13 @@
109
109
  "@types/node": "^25.6.0",
110
110
  "@types/picomatch": "^4.0.3",
111
111
  "@types/semver": "^7.7.1",
112
- "@typescript/native-preview": "7.0.0-dev.20260413.1",
112
+ "@typescript/native-preview": "7.0.0-dev.20260416.1",
113
113
  "@unocss/eslint-plugin": "^66.6.8",
114
114
  "@vitejs/devtools": "^0.1.13",
115
115
  "@vitest/coverage-v8": "^4.1.4",
116
116
  "@vitest/ui": "^4.1.4",
117
117
  "@vueuse/core": "^14.2.1",
118
- "baseline-browser-mapping": "^2.10.18",
118
+ "baseline-browser-mapping": "^2.10.19",
119
119
  "bumpp": "^11.0.1",
120
120
  "dedent": "^1.7.2",
121
121
  "eslint": "^10.2.0",
@@ -123,13 +123,13 @@
123
123
  "memfs": "^4.57.1",
124
124
  "package-manager-detector": "^1.6.0",
125
125
  "pkg-types": "^2.3.0",
126
- "postcss": "^8.5.9",
126
+ "postcss": "^8.5.10",
127
127
  "postcss-import": "^16.1.1",
128
- "prettier": "^3.8.2",
128
+ "prettier": "^3.8.3",
129
129
  "publint": "^0.3.18",
130
130
  "rolldown-plugin-require-cjs": "^0.4.0",
131
131
  "sass": "^1.99.0",
132
- "tsnapi": "^0.1.2",
132
+ "tsnapi": "^0.3.0",
133
133
  "typescript": "~6.0.2",
134
134
  "unocss": "^66.6.8",
135
135
  "unplugin-ast": "^0.16.0",
@@ -139,8 +139,8 @@
139
139
  "vite": "^8.0.8",
140
140
  "vitest": "^4.1.4",
141
141
  "vue": "^3.5.32",
142
- "@tsdown/exe": "0.21.8",
143
- "@tsdown/css": "0.21.8"
142
+ "@tsdown/exe": "0.21.9",
143
+ "@tsdown/css": "0.21.9"
144
144
  },
145
145
  "prettier": "@sxzz/prettier-config",
146
146
  "scripts": {