tsdown 0.16.7 → 0.17.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 { f as UserConfig, m as UserConfigFn, p as UserConfigExport } from "./index-QuvuIHHG.mjs";
1
+ import { f as UserConfig, m as UserConfigFn, p as UserConfigExport } from "./index-BrlHanBo.mjs";
2
2
 
3
3
  //#region src/config.d.ts
4
4
 
package/dist/config.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { f as UserConfig, m as UserConfigFn, p as UserConfigExport } from "./index-QuvuIHHG.mjs";
2
- import { t as defineConfig } from "./config-BYPCbyiH.mjs";
1
+ import { f as UserConfig, m as UserConfigFn, p as UserConfigExport } from "./index-BrlHanBo.mjs";
2
+ import { t as defineConfig } from "./config-CSoQwDij.mjs";
3
3
  export { UserConfig, UserConfigExport, UserConfigFn, defineConfig };
@@ -23,11 +23,11 @@ interface AttwOptions extends CheckPackageOptions {
23
23
  * The available profiles are:
24
24
  * - `strict`: requires all resolutions
25
25
  * - `node16`: ignores node10 resolution failures
26
- * - `esmOnly`: ignores CJS resolution failures
26
+ * - `esm-only`: ignores CJS resolution failures
27
27
  *
28
28
  * @default 'strict'
29
29
  */
30
- profile?: "strict" | "node16" | "esmOnly";
30
+ profile?: "strict" | "node16" | "esm-only";
31
31
  /**
32
32
  * The level of the check.
33
33
  *
@@ -201,6 +201,10 @@ interface Workspace {
201
201
  }
202
202
  type NoExternalFn = (id: string, importer: string | undefined) => boolean | null | undefined | void;
203
203
  type CIOption = "ci-only" | "local-only";
204
+ type WithEnabled<T> = boolean | undefined | CIOption | (T & {
205
+ /** @default true */
206
+ enabled?: boolean | CIOption;
207
+ });
204
208
  /**
205
209
  * Options for tsdown.
206
210
  */
@@ -422,7 +426,7 @@ interface UserConfig {
422
426
  logLevel?: LogLevel;
423
427
  /**
424
428
  * If true, fails the build on warnings.
425
- * @default false
429
+ * @default 'ci-only'
426
430
  */
427
431
  failOnWarn?: boolean | CIOption;
428
432
  /**
@@ -438,6 +442,9 @@ interface UserConfig {
438
442
  * @default false
439
443
  */
440
444
  watch?: boolean | Arrayable<string>;
445
+ /**
446
+ * Files or patterns to not watch while in watch mode.
447
+ */
441
448
  ignoreWatch?: Arrayable<string | RegExp>;
442
449
  /**
443
450
  * You can specify command to be executed after a successful build, specially useful for Watch mode
@@ -452,7 +459,7 @@ interface UserConfig {
452
459
  *
453
460
  * @default false
454
461
  */
455
- debug?: boolean | CIOption | DebugOptions;
462
+ debug?: WithEnabled<DebugOptions>;
456
463
  /**
457
464
  * Enables generation of TypeScript declaration files (`.d.ts`).
458
465
  *
@@ -460,19 +467,19 @@ interface UserConfig {
460
467
  * - If the `types` field is present, or if the main `exports` contains a `types` entry, declaration file generation is enabled by default.
461
468
  * - Otherwise, declaration file generation is disabled by default.
462
469
  */
463
- dts?: boolean | CIOption | DtsOptions;
470
+ dts?: WithEnabled<DtsOptions>;
464
471
  /**
465
472
  * Enable unused dependencies check with `unplugin-unused`
466
473
  * Requires `unplugin-unused` to be installed.
467
474
  * @default false
468
475
  */
469
- unused?: boolean | CIOption | UnusedOptions;
476
+ unused?: WithEnabled<UnusedOptions>;
470
477
  /**
471
478
  * Run publint after bundling.
472
479
  * Requires `publint` to be installed.
473
480
  * @default false
474
481
  */
475
- publint?: boolean | CIOption | PublintOptions;
482
+ publint?: WithEnabled<PublintOptions>;
476
483
  /**
477
484
  * Run `arethetypeswrong` after bundling.
478
485
  * Requires `@arethetypeswrong/core` to be installed.
@@ -480,12 +487,12 @@ interface UserConfig {
480
487
  * @default false
481
488
  * @see https://github.com/arethetypeswrong/arethetypeswrong.github.io
482
489
  */
483
- attw?: boolean | CIOption | AttwOptions;
490
+ attw?: WithEnabled<AttwOptions>;
484
491
  /**
485
492
  * Enable size reporting after bundling.
486
493
  * @default true
487
494
  */
488
- report?: boolean | CIOption | ReportOptions;
495
+ report?: WithEnabled<ReportOptions>;
489
496
  /**
490
497
  * `import.meta.glob` support.
491
498
  * @see https://vite.dev/guide/features.html#glob-import
@@ -498,7 +505,7 @@ interface UserConfig {
498
505
  * This will set the `main`, `module`, `types`, `exports` fields in `package.json`
499
506
  * to point to the generated files.
500
507
  */
501
- exports?: boolean | CIOption | ExportsOptions;
508
+ exports?: WithEnabled<ExportsOptions>;
502
509
  /**
503
510
  * @deprecated Alias for `copy`, will be removed in the future.
504
511
  */
@@ -560,4 +567,4 @@ type ResolvedConfig = Overwrite<MarkPartial<Omit<UserConfig, "workspace" | "from
560
567
  unused: false | UnusedOptions;
561
568
  }>;
562
569
  //#endregion
563
- export { ExportsOptions as A, OutExtensionContext as C, BuildContext as D, PackageType as E, CopyOptionsFn as F, AttwOptions as I, DebugOptions as M, CopyEntry as N, RolldownContext as O, CopyOptions as P, ChunkAddonObject as S, OutExtensionObject as T, ReportPlugin as _, NoExternalFn as a, ChunkAddon as b, ResolvedConfig as c, UnusedOptions as d, UserConfig as f, ReportOptions as g, Workspace as h, InlineConfig as i, TsdownChunks as j, TsdownHooks as k, Sourcemap as l, UserConfigFn as m, DtsOptions as n, NormalizedFormat as o, UserConfigExport as p, Format as r, PublintOptions as s, CIOption as t, TreeshakingOptions as u, Logger as v, OutExtensionFactory as w, ChunkAddonFunction as x, globalLogger as y };
570
+ export { TsdownHooks as A, ChunkAddonObject as C, PackageType as D, OutExtensionObject as E, CopyOptions as F, CopyOptionsFn as I, AttwOptions as L, TsdownChunks as M, DebugOptions as N, BuildContext as O, CopyEntry as P, ChunkAddonFunction as S, OutExtensionFactory as T, ReportOptions as _, NoExternalFn as a, globalLogger as b, ResolvedConfig as c, UnusedOptions as d, UserConfig as f, Workspace as g, WithEnabled as h, InlineConfig as i, ExportsOptions as j, RolldownContext as k, Sourcemap as l, UserConfigFn as m, DtsOptions as n, NormalizedFormat as o, UserConfigExport as p, Format as r, PublintOptions as s, CIOption as t, TreeshakingOptions as u, ReportPlugin as v, OutExtensionContext as w, ChunkAddon as x, Logger as y };
package/dist/index.d.mts CHANGED
@@ -1,14 +1,14 @@
1
- import { A as ExportsOptions, C as OutExtensionContext, D as BuildContext, E as PackageType, F as CopyOptionsFn, I as AttwOptions, M as DebugOptions, N as CopyEntry, O as RolldownContext, P as CopyOptions, S as ChunkAddonObject, T as OutExtensionObject, a as NoExternalFn, b as ChunkAddon, c as ResolvedConfig, d as UnusedOptions, f as UserConfig, g as ReportOptions, h as Workspace, i as InlineConfig, j as TsdownChunks, k as TsdownHooks, l as Sourcemap, m as UserConfigFn, n as DtsOptions, o as NormalizedFormat, p as UserConfigExport, r as Format, s as PublintOptions, t as CIOption, u as TreeshakingOptions, v as Logger, w as OutExtensionFactory, x as ChunkAddonFunction, y as globalLogger } from "./index-QuvuIHHG.mjs";
2
- import { t as defineConfig } from "./config-BYPCbyiH.mjs";
1
+ import { A as TsdownHooks, C as ChunkAddonObject, D as PackageType, E as OutExtensionObject, F as CopyOptions, I as CopyOptionsFn, L as AttwOptions, M as TsdownChunks, N as DebugOptions, O as BuildContext, P as CopyEntry, S as ChunkAddonFunction, T as OutExtensionFactory, _ as ReportOptions, a as NoExternalFn, b as globalLogger, c as ResolvedConfig, d as UnusedOptions, f as UserConfig, g as Workspace, h as WithEnabled, i as InlineConfig, j as ExportsOptions, k as RolldownContext, l as Sourcemap, m as UserConfigFn, n as DtsOptions, o as NormalizedFormat, p as UserConfigExport, r as Format, s as PublintOptions, t as CIOption, u as TreeshakingOptions, w as OutExtensionContext, x as ChunkAddon, y as Logger } from "./index-BrlHanBo.mjs";
2
+ import { t as defineConfig } from "./config-CSoQwDij.mjs";
3
3
 
4
4
  //#region src/index.d.ts
5
-
5
+ interface TsdownBundle extends AsyncDisposable {
6
+ chunks: TsdownChunks;
7
+ }
6
8
  /**
7
9
  * Build with tsdown.
8
10
  */
9
- declare function build(userOptions?: InlineConfig): Promise<void>;
10
- /** @internal */
11
- declare const shimFile: string;
11
+ declare function build(userOptions?: InlineConfig): Promise<TsdownBundle[]>;
12
12
  /**
13
13
  * Build a single configuration, without watch and shortcuts features.
14
14
  *
@@ -17,6 +17,8 @@ declare const shimFile: string;
17
17
  * @private
18
18
  * @param config Resolved options
19
19
  */
20
- declare function buildSingle(config: ResolvedConfig, clean: () => Promise<void>): Promise<(() => Promise<void>) | undefined>;
20
+ declare function buildSingle(config: ResolvedConfig, configFiles: string[], clean: () => Promise<void>, restart: () => void): Promise<TsdownBundle>;
21
+ /** @internal */
22
+ declare const shimFile: string;
21
23
  //#endregion
22
- export { AttwOptions, BuildContext, CIOption, ChunkAddon, ChunkAddonFunction, ChunkAddonObject, CopyEntry, CopyOptions, CopyOptionsFn, DebugOptions, DtsOptions, ExportsOptions, Format, InlineConfig, type Logger, NoExternalFn, NormalizedFormat, OutExtensionContext, OutExtensionFactory, OutExtensionObject, PackageType, PublintOptions, ReportOptions, ResolvedConfig, RolldownContext, Sourcemap, TreeshakingOptions, TsdownChunks, TsdownHooks, UnusedOptions, UserConfig, UserConfigExport, UserConfigFn, Workspace, build, buildSingle, defineConfig, globalLogger, shimFile };
24
+ export { AttwOptions, BuildContext, CIOption, ChunkAddon, ChunkAddonFunction, ChunkAddonObject, CopyEntry, CopyOptions, CopyOptionsFn, DebugOptions, DtsOptions, ExportsOptions, Format, InlineConfig, type Logger, NoExternalFn, NormalizedFormat, OutExtensionContext, OutExtensionFactory, OutExtensionObject, PackageType, PublintOptions, ReportOptions, ResolvedConfig, RolldownContext, Sourcemap, TreeshakingOptions, TsdownBundle, TsdownChunks, TsdownHooks, UnusedOptions, UserConfig, UserConfigExport, UserConfigFn, WithEnabled, Workspace, build, buildSingle, defineConfig, globalLogger, shimFile };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as defineConfig } from "./config-DLSWqKoz.mjs";
2
- import { n as buildSingle, r as shimFile, t as build } from "./src-CBlanU1_.mjs";
3
- import { a as globalLogger } from "./package-DMmUaSu9.mjs";
2
+ import { n as buildSingle, r as shimFile, t as build } from "./src-hEE2DSx9.mjs";
3
+ import { a as globalLogger } from "./package-r6WmI0kC.mjs";
4
4
 
5
5
  export { build, buildSingle, defineConfig, globalLogger, shimFile };
@@ -1,7 +1,7 @@
1
- import { a as globalLogger, t as version } from "./package-DMmUaSu9.mjs";
2
- import process from "node:process";
1
+ import { a as globalLogger, t as version } from "./package-r6WmI0kC.mjs";
3
2
  import { bold, green, underline } from "ansis";
4
3
  import { readFile, unlink, writeFile } from "node:fs/promises";
4
+ import process from "node:process";
5
5
  import { existsSync } from "node:fs";
6
6
  import { createInterface } from "node:readline/promises";
7
7
 
@@ -15,16 +15,6 @@ function resolveRegex(str) {
15
15
  if (typeof str === "string" && str.length > 2 && str[0] === "/" && str.at(-1) === "/") return new RegExp(str.slice(1, -1));
16
16
  return str;
17
17
  }
18
- function debounce(fn, wait) {
19
- let timeout;
20
- return function(...args) {
21
- if (timeout) clearTimeout(timeout);
22
- timeout = setTimeout(() => {
23
- timeout = void 0;
24
- fn.apply(this, args);
25
- }, wait);
26
- };
27
- }
28
18
  function slash(string) {
29
19
  return string.replaceAll("\\", "/");
30
20
  }
@@ -160,7 +150,7 @@ function hue2rgb(p, q, t) {
160
150
 
161
151
  //#endregion
162
152
  //#region package.json
163
- var version = "0.16.7";
153
+ var version = "0.17.0-beta.1";
164
154
 
165
155
  //#endregion
166
- export { globalLogger as a, debounce as c, noop as d, pkgExists as f, toArray as g, slash as h, generateColor as i, importWithError as l, resolveRegex as m, LogLevels as n, prettyFormat as o, resolveComma as p, createLogger as r, prettyName as s, version as t, matchPattern as u };
156
+ export { globalLogger as a, importWithError as c, pkgExists as d, resolveComma as f, toArray as h, generateColor as i, matchPattern as l, slash as m, LogLevels as n, prettyFormat as o, resolveRegex as p, createLogger as r, prettyName as s, version as t, noop as u };
@@ -1,4 +1,4 @@
1
- import { _ as ReportPlugin, c as ResolvedConfig, v as Logger } from "./index-QuvuIHHG.mjs";
1
+ import { c as ResolvedConfig, v as ReportPlugin, y as Logger } from "./index-BrlHanBo.mjs";
2
2
  import { Plugin } from "rolldown";
3
3
 
4
4
  //#region src/features/external.d.ts
package/dist/plugins.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import "./config-DLSWqKoz.mjs";
2
- import { a as ReportPlugin, i as ShebangPlugin, o as NodeProtocolPlugin, s as ExternalPlugin } from "./src-CBlanU1_.mjs";
3
- import "./package-DMmUaSu9.mjs";
2
+ import { a as ReportPlugin, i as ShebangPlugin, o as NodeProtocolPlugin, s as ExternalPlugin } from "./src-hEE2DSx9.mjs";
3
+ import "./package-r6WmI0kC.mjs";
4
4
 
5
5
  export { ExternalPlugin, NodeProtocolPlugin, ReportPlugin, ShebangPlugin };
package/dist/run.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { a as globalLogger, g as toArray, p as resolveComma, t as version } from "./package-DMmUaSu9.mjs";
2
+ import { a as globalLogger, f as resolveComma, h as toArray, t as version } from "./package-r6WmI0kC.mjs";
3
3
  import module from "node:module";
4
- import process from "node:process";
5
4
  import { dim } from "ansis";
6
5
  import { VERSION } from "rolldown";
6
+ import process from "node:process";
7
7
  import { createDebug, enable, namespaces } from "obug";
8
8
  import { cac } from "cac";
9
9
 
@@ -36,7 +36,7 @@ cli.command("[...files]", "Bundle files", {
36
36
  await build$1(flags);
37
37
  });
38
38
  cli.command("migrate", "Migrate from tsup to tsdown").option("-c, --cwd <dir>", "Working directory").option("-d, --dry-run", "Dry run").action(async (args) => {
39
- const { migrate } = await import("./migrate-D4tWVkLj.mjs");
39
+ const { migrate } = await import("./migrate-CcVRf9lh.mjs");
40
40
  await migrate(args);
41
41
  });
42
42
  async function runCLI() {
@@ -1,15 +1,13 @@
1
1
  import { createRequire as __cjs_createRequire } from "node:module";
2
2
  const __cjs_require = __cjs_createRequire(import.meta.url);
3
- import { a as globalLogger, c as debounce, d as noop, f as pkgExists, g as toArray, h as slash, i as generateColor, l as importWithError, m as resolveRegex, n as LogLevels, o as prettyFormat, p as resolveComma, r as createLogger, s as prettyName, t as version, u as matchPattern } from "./package-DMmUaSu9.mjs";
3
+ import { a as globalLogger, c as importWithError, d as pkgExists, f as resolveComma, h as toArray, i as generateColor, l as matchPattern, m as slash, n as LogLevels, o as prettyFormat, p as resolveRegex, r as createLogger, s as prettyName, t as version, u as noop } from "./package-r6WmI0kC.mjs";
4
4
  import { builtinModules, isBuiltin } from "node:module";
5
5
  import path, { dirname, join, normalize, sep } from "node:path";
6
- import process, { env } from "node:process";
7
6
  import { fileURLToPath, pathToFileURL } from "node:url";
8
7
  import { blue, bold, dim, green, underline } from "ansis";
9
- import { VERSION, build } from "rolldown";
10
- import { exec } from "tinyexec";
11
- const treeKill = __cjs_require("tree-kill");
8
+ import { VERSION, build, watch } from "rolldown";
12
9
  import { access, chmod, cp, mkdtemp, readFile, rm, stat, writeFile } from "node:fs/promises";
10
+ import process, { env } from "node:process";
13
11
  import { createDebug } from "obug";
14
12
  import { createConfigCoreLoader } from "unconfig-core";
15
13
  import { glob, isDynamicPattern } from "tinyglobby";
@@ -18,15 +16,16 @@ const minVersion = __cjs_require("semver/ranges/min-version.js");
18
16
  import { up } from "empathic/find";
19
17
  import { up as up$1 } from "empathic/package";
20
18
  import { tmpdir } from "node:os";
19
+ import { exec } from "tinyexec";
21
20
  const coerce = __cjs_require("semver/functions/coerce.js");
22
21
  const satisfies = __cjs_require("semver/functions/satisfies.js");
23
22
  import { createHooks } from "hookable";
23
+ const treeKill = __cjs_require("tree-kill");
24
24
  import util, { promisify } from "node:util";
25
25
  import { importGlobPlugin } from "rolldown/experimental";
26
26
  import { Buffer } from "node:buffer";
27
27
  import { brotliCompress, gzip } from "node:zlib";
28
28
  import readline from "node:readline";
29
- import { globalContext, invalidateContextFile } from "rolldown-plugin-dts/tsc-context";
30
29
 
31
30
  //#region node_modules/.pnpm/is-in-ci@2.0.0/node_modules/is-in-ci/index.js
32
31
  const check = (key) => key in env && env[key] !== "0" && env[key] !== "false";
@@ -107,9 +106,9 @@ async function loadViteConfig(prefix, cwd, configLoader) {
107
106
  return resolved;
108
107
  }
109
108
  const configPrefix = "tsdown.config";
110
- let isWatch = false;
111
- function setWatch() {
112
- isWatch = true;
109
+ let noCacheLoad = false;
110
+ function setNoCacheLoad() {
111
+ noCacheLoad = true;
113
112
  }
114
113
  async function loadConfigFile(inlineConfig, workspace) {
115
114
  let cwd = inlineConfig.cwd || process.cwd();
@@ -154,7 +153,7 @@ async function loadConfigFile(inlineConfig, workspace) {
154
153
  }],
155
154
  cwd,
156
155
  stopAt: workspace && path.dirname(workspace)
157
- }).load(isWatch);
156
+ }).load(noCacheLoad);
158
157
  let exported = [];
159
158
  let file;
160
159
  if (result) {
@@ -172,7 +171,7 @@ async function loadConfigFile(inlineConfig, workspace) {
172
171
  };
173
172
  }
174
173
  function resolveConfigLoader(configLoader = "auto") {
175
- if (isWatch) return "unrun";
174
+ if (noCacheLoad) return "unrun";
176
175
  else if (configLoader === "auto") return !!(process.features.typescript || process.versions.bun || process.versions.deno) ? "native" : "unrun";
177
176
  else return configLoader === "native" ? "native" : "unrun";
178
177
  }
@@ -234,6 +233,13 @@ function resolveClean(clean, outDir, cwd) {
234
233
  if (clean.some((item) => path.resolve(item) === cwd)) throw new Error("Cannot clean the current working directory. Please specify a different path to clean option.");
235
234
  return clean;
236
235
  }
236
+ async function cleanupChunks(outDir, chunks) {
237
+ await Promise.all(chunks.map(async (chunk) => {
238
+ const filePath = path.resolve(outDir, chunk.fileName);
239
+ debug$7("Removing chunk file", filePath);
240
+ await fsRemove(filePath);
241
+ }));
242
+ }
237
243
 
238
244
  //#endregion
239
245
  //#region src/features/entry.ts
@@ -566,7 +572,7 @@ async function resolveWorkspace(config, inlineConfig) {
566
572
  };
567
573
  }
568
574
  async function resolveUserConfig(userConfig, inlineConfig) {
569
- let { entry, format = ["es"], plugins = [], clean = true, silent = false, logLevel = silent ? "silent" : "info", failOnWarn = false, customLogger, treeshake = true, platform = "node", outDir = "dist", sourcemap = false, dts, unused = false, watch = false, ignoreWatch, shims = false, skipNodeModulesBundle = false, publint: publint$1 = false, attw: attw$1 = false, fromVite, alias, tsconfig, report = true, target, env: env$1 = {}, copy: copy$1, publicDir, hash = true, cwd = process.cwd(), name, workspace, external, noExternal, exports = false, bundle, unbundle = typeof bundle === "boolean" ? !bundle : false, removeNodeProtocol, nodeProtocol, cjsDefault = true, globImport = true, inlineOnly, fixedExtension = platform === "node", debug: debug$9 = false } = userConfig;
575
+ let { entry, format = ["es"], plugins = [], clean = true, silent = false, logLevel = silent ? "silent" : "info", failOnWarn = "ci-only", customLogger, treeshake = true, platform = "node", outDir = "dist", sourcemap = false, dts, unused = false, watch: watch$1 = false, ignoreWatch, shims = false, skipNodeModulesBundle = false, publint: publint$1 = false, attw: attw$1 = false, fromVite, alias, tsconfig, report = true, target, env: env$1 = {}, copy: copy$1, publicDir, hash = true, cwd = process.cwd(), name, workspace, external, noExternal, exports = false, bundle, unbundle = typeof bundle === "boolean" ? !bundle : false, removeNodeProtocol, nodeProtocol, cjsDefault = true, globImport = true, inlineOnly, fixedExtension = platform === "node", debug: debug$9 = false } = userConfig;
570
576
  const logger = createLogger(logLevel, {
571
577
  customLogger,
572
578
  failOnWarn: resolveFeatureOption(failOnWarn, true)
@@ -615,46 +621,49 @@ async function resolveUserConfig(userConfig, inlineConfig) {
615
621
  }
616
622
  if (inlineOnly != null) inlineOnly = toArray(inlineOnly);
617
623
  debug$9 = resolveFeatureOption(debug$9, {});
618
- if (debug$9) debug$9.devtools ??= !!pkgExists("@vitejs/devtools/cli");
624
+ if (debug$9) if (watch$1) {
625
+ if (debug$9.devtools) logger.warn("Devtools is not supported in watch mode, disabling it.");
626
+ debug$9.devtools = false;
627
+ } else debug$9.devtools ??= !!pkgExists("@vitejs/devtools/cli");
619
628
  return {
620
629
  ...userConfig,
630
+ alias,
631
+ attw: attw$1,
632
+ cjsDefault,
633
+ clean,
634
+ copy: publicDir || copy$1,
635
+ cwd,
636
+ debug: debug$9,
637
+ dts,
621
638
  entry,
622
- plugins,
639
+ env: env$1,
640
+ exports,
641
+ external,
642
+ fixedExtension,
623
643
  format: normalizeFormat(format),
624
- target,
625
- outDir,
626
- clean,
644
+ globImport,
645
+ hash,
646
+ ignoreWatch,
647
+ inlineOnly,
627
648
  logger,
628
- treeshake,
649
+ name,
650
+ nodeProtocol,
651
+ noExternal,
652
+ outDir,
653
+ pkg,
629
654
  platform,
630
- sourcemap,
631
- dts,
655
+ plugins,
656
+ publint: publint$1,
632
657
  report,
633
- unused,
634
- watch,
635
- ignoreWatch,
636
658
  shims,
637
659
  skipNodeModulesBundle,
638
- publint: publint$1,
639
- attw: attw$1,
640
- alias,
660
+ sourcemap,
661
+ target,
662
+ treeshake,
641
663
  tsconfig,
642
- cwd,
643
- env: env$1,
644
- pkg,
645
- copy: publicDir || copy$1,
646
- hash,
647
- name,
648
- external,
649
- noExternal,
650
- exports,
651
664
  unbundle,
652
- nodeProtocol,
653
- cjsDefault,
654
- globImport,
655
- inlineOnly,
656
- fixedExtension,
657
- debug: debug$9
665
+ unused,
666
+ watch: watch$1
658
667
  };
659
668
  }
660
669
  async function mergeUserOptions(defaults, user, args) {
@@ -665,15 +674,19 @@ async function mergeUserOptions(defaults, user, args) {
665
674
  };
666
675
  }
667
676
  function resolveFeatureOption(value, defaults) {
668
- if (value === true) return defaults;
669
- if (value === "ci-only") return is_in_ci_default ? defaults : false;
670
- if (value === "local-only") return is_in_ci_default ? false : defaults;
677
+ if (typeof value === "object" && value !== null) return resolveCIOption(value.enabled ?? true) ? value : false;
678
+ return resolveCIOption(value) ? defaults : false;
679
+ }
680
+ function resolveCIOption(value) {
681
+ if (value === "ci-only") return is_in_ci_default ? true : false;
682
+ if (value === "local-only") return is_in_ci_default ? false : true;
671
683
  return value;
672
684
  }
673
685
 
674
686
  //#endregion
675
687
  //#region src/features/attw.ts
676
688
  const debug$4 = createDebug("tsdown:attw");
689
+ const label$1 = dim`[attw]`;
677
690
  /**
678
691
  * ATTW profiles.
679
692
  * Defines the resolution modes to ignore for each profile.
@@ -683,44 +696,24 @@ const debug$4 = createDebug("tsdown:attw");
683
696
  const profiles = {
684
697
  strict: [],
685
698
  node16: ["node10"],
686
- esmOnly: ["node10", "node16-cjs"]
699
+ "esm-only": ["node10", "node16-cjs"]
687
700
  };
688
- /**
689
- * Format an ATTW problem for display
690
- */
691
- function formatProblem(problem) {
692
- const resolutionKind = "resolutionKind" in problem ? ` (${problem.resolutionKind})` : "";
693
- const entrypoint = "entrypoint" in problem ? ` at ${problem.entrypoint}` : "";
694
- switch (problem.kind) {
695
- case "NoResolution": return ` ❌ No resolution${resolutionKind}${entrypoint}`;
696
- case "UntypedResolution": return ` ⚠️ Untyped resolution${resolutionKind}${entrypoint}`;
697
- case "FalseESM": return ` 🔄 False ESM: Types indicate ESM (${problem.typesModuleKind}) but implementation is CJS (${problem.implementationModuleKind})\n Types: ${problem.typesFileName} | Implementation: ${problem.implementationFileName}`;
698
- case "FalseCJS": return ` 🔄 False CJS: Types indicate CJS (${problem.typesModuleKind}) but implementation is ESM (${problem.implementationModuleKind})\n Types: ${problem.typesFileName} | Implementation: ${problem.implementationFileName}`;
699
- case "CJSResolvesToESM": return ` ⚡ CJS resolves to ESM${resolutionKind}${entrypoint}`;
700
- case "NamedExports": {
701
- const missingExports = problem.missing?.length > 0 ? ` Missing: ${problem.missing.join(", ")}` : "";
702
- return ` 📤 Named exports problem${problem.isMissingAllNamed ? " (all named exports missing)" : ""}${missingExports}\n Types: ${problem.typesFileName} | Implementation: ${problem.implementationFileName}`;
703
- }
704
- case "FallbackCondition": return ` 🎯 Fallback condition used${resolutionKind}${entrypoint}`;
705
- case "FalseExportDefault": return ` 🎭 False export default\n Types: ${problem.typesFileName} | Implementation: ${problem.implementationFileName}`;
706
- case "MissingExportEquals": return ` 📝 Missing export equals\n Types: ${problem.typesFileName} | Implementation: ${problem.implementationFileName}`;
707
- case "InternalResolutionError": return ` 💥 Internal resolution error in ${problem.fileName} (${problem.resolutionOption})\n Module: ${problem.moduleSpecifier} | Mode: ${problem.resolutionMode}`;
708
- case "UnexpectedModuleSyntax": return ` 📋 Unexpected module syntax in ${problem.fileName}\n Expected: ${problem.moduleKind} | Found: ${problem.syntax === 99 ? "ESM" : "CJS"}`;
709
- case "CJSOnlyExportsDefault": return ` 🏷️ CJS only exports default in ${problem.fileName}`;
710
- default: return ` ❓ Unknown problem: ${JSON.stringify(problem)}`;
711
- }
712
- }
713
701
  async function attw(options) {
714
702
  if (!options.attw) return;
715
703
  if (!options.pkg) {
716
704
  options.logger.warn("attw is enabled but package.json is not found");
717
705
  return;
718
706
  }
719
- const { profile = "strict", level = "warn", ...attwOptions } = options.attw;
707
+ let { profile = "strict", level = "warn", ...attwOptions } = options.attw;
708
+ if (profile === "esmOnly") {
709
+ options.logger.warn("attw option \"esmOnly\" is deprecated, use \"esm-only\" instead");
710
+ profile = "esm-only";
711
+ }
720
712
  const t = performance.now();
721
713
  debug$4("Running attw check");
722
714
  const tempDir = await mkdtemp(path.join(tmpdir(), "tsdown-attw-"));
723
715
  const attwCore = await importWithError("@arethetypeswrong/core");
716
+ let checkResult;
724
717
  try {
725
718
  const { stdout: tarballInfo } = await exec("npm", [
726
719
  "pack",
@@ -732,25 +725,55 @@ async function attw(options) {
732
725
  if (!Array.isArray(parsed) || !parsed[0]?.filename) throw new Error("Invalid npm pack output format");
733
726
  const tarball = await readFile(path.join(tempDir, parsed[0].filename));
734
727
  const pkg = attwCore.createPackageFromTarballData(tarball);
735
- const checkResult = await attwCore.checkPackage(pkg, attwOptions);
736
- if (checkResult.types !== false && checkResult.problems.length) {
737
- const problems = checkResult.problems.filter((problem) => {
738
- if ("resolutionKind" in problem) return !profiles[profile]?.includes(problem.resolutionKind);
739
- return true;
740
- });
741
- if (problems.length) {
742
- const problemMessage = `Are the types wrong problems found:\n${problems.map(formatProblem).join("\n")}`;
743
- if (level === "error") throw new Error(problemMessage);
744
- options.logger.warn(prettyName(options.name), problemMessage);
745
- }
746
- } else options.logger.success(prettyName(options.name), `No Are the types wrong problems found`, dim`(${Math.round(performance.now() - t)}ms)`);
728
+ checkResult = await attwCore.checkPackage(pkg, attwOptions);
747
729
  } catch (error) {
748
730
  options.logger.error("ATTW check failed:", error);
749
731
  debug$4("Found errors, setting exit code to 1");
750
732
  process.exitCode = 1;
733
+ return;
751
734
  } finally {
752
735
  await fsRemove(tempDir);
753
736
  }
737
+ let errorMessage;
738
+ if (checkResult.types) {
739
+ const problems = checkResult.problems.filter((problem) => {
740
+ if ("resolutionKind" in problem) return !profiles[profile]?.includes(problem.resolutionKind);
741
+ return true;
742
+ });
743
+ if (problems.length) errorMessage = `problems found:\n${problems.map(formatProblem).join("\n")}`;
744
+ } else errorMessage = `Package has no types`;
745
+ if (errorMessage) {
746
+ options.logger[level](prettyName(options.name), label$1, errorMessage);
747
+ if (level === "error") {
748
+ process.exitCode = 1;
749
+ debug$4("Found problems, setting exit code to 1");
750
+ }
751
+ } else options.logger.success(prettyName(options.name), label$1, "No problems found", dim`(${Math.round(performance.now() - t)}ms)`);
752
+ }
753
+ /**
754
+ * Format an ATTW problem for display
755
+ */
756
+ function formatProblem(problem) {
757
+ const resolutionKind = "resolutionKind" in problem ? ` (${problem.resolutionKind})` : "";
758
+ const entrypoint = "entrypoint" in problem ? ` at ${problem.entrypoint}` : "";
759
+ switch (problem.kind) {
760
+ case "NoResolution": return ` ❌ No resolution${resolutionKind}${entrypoint}`;
761
+ case "UntypedResolution": return ` ⚠️ Untyped resolution${resolutionKind}${entrypoint}`;
762
+ case "FalseESM": return ` 🔄 False ESM: Types indicate ESM (${problem.typesModuleKind}) but implementation is CJS (${problem.implementationModuleKind})\n Types: ${problem.typesFileName} | Implementation: ${problem.implementationFileName}`;
763
+ case "FalseCJS": return ` 🔄 False CJS: Types indicate CJS (${problem.typesModuleKind}) but implementation is ESM (${problem.implementationModuleKind})\n Types: ${problem.typesFileName} | Implementation: ${problem.implementationFileName}`;
764
+ case "CJSResolvesToESM": return ` ⚡ CJS resolves to ESM${resolutionKind}${entrypoint}`;
765
+ case "NamedExports": {
766
+ const missingExports = problem.missing?.length > 0 ? ` Missing: ${problem.missing.join(", ")}` : "";
767
+ return ` 📤 Named exports problem${problem.isMissingAllNamed ? " (all named exports missing)" : ""}${missingExports}\n Types: ${problem.typesFileName} | Implementation: ${problem.implementationFileName}`;
768
+ }
769
+ case "FallbackCondition": return ` 🎯 Fallback condition used${resolutionKind}${entrypoint}`;
770
+ case "FalseExportDefault": return ` 🎭 False export default\n Types: ${problem.typesFileName} | Implementation: ${problem.implementationFileName}`;
771
+ case "MissingExportEquals": return ` 📝 Missing export equals\n Types: ${problem.typesFileName} | Implementation: ${problem.implementationFileName}`;
772
+ case "InternalResolutionError": return ` 💥 Internal resolution error in ${problem.fileName} (${problem.resolutionOption})\n Module: ${problem.moduleSpecifier} | Mode: ${problem.resolutionMode}`;
773
+ case "UnexpectedModuleSyntax": return ` 📋 Unexpected module syntax in ${problem.fileName}\n Expected: ${problem.moduleKind} | Found: ${problem.syntax === 99 ? "ESM" : "CJS"}`;
774
+ case "CJSOnlyExportsDefault": return ` 🏷️ CJS only exports default in ${problem.fileName}`;
775
+ default: return ` ❓ Unknown problem: ${JSON.stringify(problem)}`;
776
+ }
754
777
  }
755
778
 
756
779
  //#endregion
@@ -797,10 +820,28 @@ async function createHooks$1(options) {
797
820
  }
798
821
  };
799
822
  }
823
+ function executeOnSuccess(config) {
824
+ if (!config.onSuccess) return;
825
+ const ab = new AbortController();
826
+ if (typeof config.onSuccess === "string") {
827
+ const p = exec(config.onSuccess, [], { nodeOptions: {
828
+ shell: true,
829
+ stdio: "inherit"
830
+ } });
831
+ p.then(({ exitCode }) => {
832
+ if (exitCode) process.exitCode = exitCode;
833
+ });
834
+ ab.signal.addEventListener("abort", () => {
835
+ if (typeof p.pid === "number") treeKill(p.pid);
836
+ });
837
+ } else config.onSuccess(config, ab.signal);
838
+ return ab;
839
+ }
800
840
 
801
841
  //#endregion
802
842
  //#region src/features/publint.ts
803
843
  const debug$3 = createDebug("tsdown:publint");
844
+ const label = dim`[publint]`;
804
845
  async function publint(options) {
805
846
  if (!options.publint) return;
806
847
  if (!options.pkg) {
@@ -817,7 +858,7 @@ async function publint(options) {
817
858
  });
818
859
  debug$3("Found %d issues", messages.length);
819
860
  if (!messages.length) {
820
- options.logger.success(prettyName(options.name), `No publint issues found`, dim`(${Math.round(performance.now() - t)}ms)`);
861
+ options.logger.success(prettyName(options.name), label, "No issues found", dim`(${Math.round(performance.now() - t)}ms)`);
821
862
  return;
822
863
  }
823
864
  let hasError = false;
@@ -829,7 +870,7 @@ async function publint(options) {
829
870
  warning: "warn",
830
871
  suggestion: "info"
831
872
  }[message.type];
832
- options.logger[logType](prettyName(options.name), formattedMessage);
873
+ options.logger[logType](prettyName(options.name), label, formattedMessage);
833
874
  }
834
875
  if (hasError) {
835
876
  debug$3("Found errors, setting exit code to 1");
@@ -1143,11 +1184,36 @@ function getShimsInject(format, platform) {
1143
1184
  };
1144
1185
  }
1145
1186
 
1187
+ //#endregion
1188
+ //#region src/features/watch.ts
1189
+ const endsWithConfig = /[\\/](?:tsdown\.config.*|tsconfig\.json)$/;
1190
+ function WatchPlugin(configFiles, { config, chunks }) {
1191
+ return {
1192
+ name: "tsdown:watch",
1193
+ options: config.ignoreWatch.length ? (inputOptions) => {
1194
+ inputOptions.watch ||= {};
1195
+ inputOptions.watch.exclude = toArray(inputOptions.watch.exclude);
1196
+ inputOptions.watch.exclude.push(...config.ignoreWatch);
1197
+ } : void 0,
1198
+ buildStart() {
1199
+ config.tsconfig && this.addWatchFile(config.tsconfig);
1200
+ for (const file of configFiles) this.addWatchFile(file);
1201
+ if (typeof config.watch !== "boolean") for (const file of resolveComma(toArray(config.watch))) this.addWatchFile(file);
1202
+ },
1203
+ generateBundle: {
1204
+ order: "post",
1205
+ handler(outputOptions, bundle) {
1206
+ chunks.push(...Object.values(bundle));
1207
+ }
1208
+ }
1209
+ };
1210
+ }
1211
+
1146
1212
  //#endregion
1147
1213
  //#region src/features/rolldown.ts
1148
1214
  const debug = createDebug("tsdown:rolldown");
1149
- async function getBuildOptions(config, format, isMultiFormat, cjsDts = false) {
1150
- const inputOptions = await resolveInputOptions(config, format, cjsDts, isMultiFormat);
1215
+ async function getBuildOptions(config, format, configFiles, watchContext, cjsDts = false, isMultiFormat) {
1216
+ const inputOptions = await resolveInputOptions(config, format, configFiles, watchContext, cjsDts, isMultiFormat);
1151
1217
  const outputOptions = await resolveOutputOptions(inputOptions, config, format, cjsDts);
1152
1218
  const rolldownConfig = {
1153
1219
  ...inputOptions,
@@ -1156,8 +1222,8 @@ async function getBuildOptions(config, format, isMultiFormat, cjsDts = false) {
1156
1222
  debug("rolldown config with format \"%s\" %O", cjsDts ? "cjs dts" : format, rolldownConfig);
1157
1223
  return rolldownConfig;
1158
1224
  }
1159
- async function resolveInputOptions(config, format, cjsDts, isMultiFormat) {
1160
- const { entry, external, plugins: userPlugins, platform, alias, treeshake, dts, unused, target, shims, tsconfig, cwd, report, env: env$1, nodeProtocol, loader, name, logger, cjsDefault, banner, footer, globImport, debug: debug$9 } = config;
1225
+ async function resolveInputOptions(config, format, configFiles, watchContext, cjsDts, isMultiFormat) {
1226
+ const { alias, banner, cjsDefault, cwd, debug: debug$9, dts, entry, env: env$1, external, footer, globImport, loader, logger, name, nodeProtocol, platform, plugins: userPlugins, report, shims, target, treeshake, tsconfig, unused, watch: watch$1 } = config;
1161
1227
  const plugins = [];
1162
1228
  if (nodeProtocol) plugins.push(NodeProtocolPlugin(nodeProtocol));
1163
1229
  if (config.pkg || config.skipNodeModulesBundle) plugins.push(ExternalPlugin(config));
@@ -1189,6 +1255,7 @@ async function resolveInputOptions(config, format, cjsDts, isMultiFormat) {
1189
1255
  if (globImport) plugins.push(importGlobPlugin());
1190
1256
  }
1191
1257
  if (report && LogLevels[logger.level] >= 3) plugins.push(ReportPlugin(report, logger, cwd, cjsDts, name, isMultiFormat));
1258
+ if (watch$1) plugins.push(WatchPlugin(configFiles, watchContext));
1192
1259
  if (!cjsDts) plugins.push(userPlugins);
1193
1260
  const define = {
1194
1261
  ...config.define,
@@ -1325,52 +1392,9 @@ function shortcuts(restart) {
1325
1392
  return () => rl.close();
1326
1393
  }
1327
1394
 
1328
- //#endregion
1329
- //#region src/features/watch.ts
1330
- const endsWithConfig = /[\\/](?:(?:package|tsconfig)\.json|pnpm-(?:workspace|lock)\.yaml|tsdown\.config.*)$/;
1331
- async function watchBuild(options, configFiles, rebuild, restart) {
1332
- if (typeof options.watch === "boolean" && options.outDir === options.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.`);
1333
- const files = toArray(typeof options.watch === "boolean" ? options.cwd : options.watch);
1334
- options.logger.info(`Watching for changes in ${files.join(", ")}`);
1335
- files.push(...configFiles);
1336
- const { watch } = await import("chokidar");
1337
- const debouncedOnChange = debounce(onChange, 100);
1338
- const watcher = watch(files, {
1339
- cwd: options.cwd,
1340
- ignoreInitial: true,
1341
- ignorePermissionErrors: true,
1342
- ignored: [
1343
- /[\\/]\.git[\\/]/,
1344
- RE_NODE_MODULES,
1345
- options.outDir,
1346
- ...options.ignoreWatch
1347
- ]
1348
- });
1349
- let pending = [];
1350
- let pendingPromise;
1351
- watcher.on("all", (type, file) => {
1352
- pending.push(path.resolve(options.cwd, file));
1353
- debouncedOnChange();
1354
- });
1355
- return watcher;
1356
- async function onChange() {
1357
- await pendingPromise;
1358
- if (!pending.length) return;
1359
- for (const file of pending) invalidateContextFile(globalContext, file);
1360
- if (pending.some((file) => configFiles.includes(file) || endsWithConfig.test(file))) {
1361
- options.logger.info(`Restarting due to config change...`);
1362
- pendingPromise = restart();
1363
- } else {
1364
- options.logger.info(`Change detected: ${pending.join(", ")}`);
1365
- pendingPromise = rebuild();
1366
- }
1367
- pending = [];
1368
- await pendingPromise;
1369
- }
1370
- }
1371
-
1372
1395
  //#endregion
1373
1396
  //#region src/index.ts
1397
+ const asyncDispose = Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose");
1374
1398
  /**
1375
1399
  * Build with tsdown.
1376
1400
  */
@@ -1382,20 +1406,22 @@ async function build$1(userOptions = {}) {
1382
1406
  if (cleanPromise) return cleanPromise;
1383
1407
  return cleanPromise = cleanOutDir(configs);
1384
1408
  };
1385
- globalLogger.info("Build start");
1386
- const rebuilds = await Promise.all(configs.map((options) => buildSingle(options, clean)));
1387
1409
  const disposeCbs = [];
1388
- for (const [i, config] of configs.entries()) {
1389
- const rebuild = rebuilds[i];
1390
- if (!rebuild) continue;
1391
- setWatch();
1392
- const watcher = await watchBuild(config, configFiles, rebuild, restart);
1393
- disposeCbs.push(() => watcher.close());
1410
+ let restarting = false;
1411
+ async function restart() {
1412
+ if (restarting) return;
1413
+ restarting = true;
1414
+ await Promise.all(disposeCbs.map((cb) => cb()));
1415
+ setNoCacheLoad();
1416
+ build$1(userOptions);
1394
1417
  }
1395
- let firstDevtoolsConfig = configs.find((config) => config.debug && config.debug.devtools);
1396
- if (disposeCbs.length && firstDevtoolsConfig) {
1397
- globalLogger.warn("Devtools is not supported in watch mode, disabling it.");
1398
- firstDevtoolsConfig = void 0;
1418
+ globalLogger.info("Build start");
1419
+ const bundles = await Promise.all(configs.map((options) => buildSingle(options, configFiles, clean, restart)));
1420
+ const firstDevtoolsConfig = configs.find((config) => config.debug && config.debug.devtools);
1421
+ if (configs.some((config) => config.watch)) {
1422
+ disposeCbs.push(shortcuts(restart));
1423
+ for (const bundle of bundles) disposeCbs.push(bundle[asyncDispose]);
1424
+ return;
1399
1425
  }
1400
1426
  if (firstDevtoolsConfig) {
1401
1427
  const { start } = await importWithError("@vitejs/devtools/cli-commands");
@@ -1406,16 +1432,8 @@ async function build$1(userOptions = {}) {
1406
1432
  ...typeof devtoolsOptions === "object" ? devtoolsOptions : {}
1407
1433
  });
1408
1434
  }
1409
- if (disposeCbs.length) disposeCbs.push(shortcuts(restart));
1410
- async function restart() {
1411
- for (const dispose of disposeCbs) await dispose();
1412
- build$1(userOptions);
1413
- }
1435
+ return bundles;
1414
1436
  }
1415
- const dirname$1 = path.dirname(fileURLToPath(import.meta.url));
1416
- const pkgRoot = path.resolve(dirname$1, "..");
1417
- /** @internal */
1418
- const shimFile = path.resolve(pkgRoot, "esm-shims.js");
1419
1437
  /**
1420
1438
  * Build a single configuration, without watch and shortcuts features.
1421
1439
  *
@@ -1424,66 +1442,110 @@ const shimFile = path.resolve(pkgRoot, "esm-shims.js");
1424
1442
  * @private
1425
1443
  * @param config Resolved options
1426
1444
  */
1427
- async function buildSingle(config, clean) {
1428
- const { format: formats, dts, watch, onSuccess, logger } = config;
1429
- let ab;
1445
+ async function buildSingle(config, configFiles, clean, restart) {
1446
+ const { format: formats, dts, watch: watch$1, logger } = config;
1430
1447
  const { hooks, context } = await createHooks$1(config);
1431
1448
  warnLegacyCJS(config);
1432
- await rebuild(true);
1433
- if (watch) return () => rebuild();
1434
- async function rebuild(first) {
1435
- const startTime = performance.now();
1436
- await hooks.callHook("build:prepare", context);
1437
- ab?.abort();
1438
- if (first) await clean();
1439
- else await cleanOutDir([config]);
1440
- let hasErrors = false;
1441
- const isMultiFormat = formats.length > 1;
1442
- const chunks = {};
1443
- const debugRolldownDir = await getDebugRolldownDir();
1444
- await Promise.all(formats.map(async (format) => {
1445
- try {
1446
- const buildOptions = await getBuildOptions(config, format, isMultiFormat, false);
1447
- await hooks.callHook("build:before", {
1448
- ...context,
1449
- buildOptions
1450
- });
1451
- if (debugRolldownDir) await debugBuildOptions(debugRolldownDir, config.name, format, buildOptions);
1452
- const { output } = await build(buildOptions);
1453
- chunks[format] = output;
1454
- if (format === "cjs" && dts) {
1455
- const { output: output$1 } = await build(await getBuildOptions(config, format, isMultiFormat, true));
1456
- chunks[format].push(...output$1);
1457
- }
1458
- } catch (error) {
1459
- if (watch) {
1460
- logger.error(error);
1461
- hasErrors = true;
1462
- return;
1463
- }
1464
- throw error;
1449
+ const startTime = performance.now();
1450
+ await hooks.callHook("build:prepare", context);
1451
+ await clean();
1452
+ const debugRolldownConfigDir = await getDebugRolldownDir();
1453
+ const chunks = {};
1454
+ let watcher;
1455
+ const watchCtx = { config };
1456
+ let ab;
1457
+ const isMultiFormat = formats.length > 1;
1458
+ const configsByFormat = (await Promise.all(formats.map((format) => buildOptionsByFormat(format)))).flat();
1459
+ if (watch$1) {
1460
+ watcher = watch(configsByFormat.map((item) => item[1]));
1461
+ handleWatcher(watcher);
1462
+ } else {
1463
+ const outputs = await build(configsByFormat.map((item) => item[1]));
1464
+ for (const [i, output] of outputs.entries()) {
1465
+ const format = configsByFormat[i][0];
1466
+ chunks[format] ||= [];
1467
+ chunks[format].push(...output.output);
1468
+ }
1469
+ }
1470
+ if (!watch$1) {
1471
+ logger.success(prettyName(config.name), `Build complete in ${green(`${Math.round(performance.now() - startTime)}ms`)}`);
1472
+ await postBuild();
1473
+ }
1474
+ return {
1475
+ chunks,
1476
+ async [asyncDispose]() {
1477
+ ab?.abort();
1478
+ await watcher?.close();
1479
+ }
1480
+ };
1481
+ function handleWatcher(watcher$1) {
1482
+ const changedFile = [];
1483
+ let hasError = false;
1484
+ watcher$1.on("change", (id, event) => {
1485
+ if (event.event === "update") changedFile.push(id);
1486
+ if (configFiles.includes(id) || endsWithConfig.test(id)) {
1487
+ globalLogger.info(`Reload config: ${id}, restarting...`);
1488
+ restart();
1465
1489
  }
1466
- }));
1467
- if (hasErrors) return;
1490
+ });
1491
+ watcher$1.on("event", async (event) => {
1492
+ switch (event.code) {
1493
+ case "START":
1494
+ for (const format of formats) {
1495
+ await cleanupChunks(config.outDir, chunks[format]);
1496
+ chunks[format].length = 0;
1497
+ }
1498
+ hasError = false;
1499
+ break;
1500
+ case "END":
1501
+ if (!hasError) await postBuild();
1502
+ break;
1503
+ case "BUNDLE_START":
1504
+ if (changedFile.length > 0) {
1505
+ console.info("");
1506
+ logger.info(`Found ${bold(changedFile.join(", "))} changed, rebuilding...`);
1507
+ }
1508
+ changedFile.length = 0;
1509
+ break;
1510
+ case "BUNDLE_END":
1511
+ await event.result.close();
1512
+ logger.success(`Rebuilt in ${event.duration}ms.`);
1513
+ break;
1514
+ case "ERROR":
1515
+ await event.result.close();
1516
+ logger.error(event.error);
1517
+ hasError = true;
1518
+ break;
1519
+ }
1520
+ });
1521
+ }
1522
+ async function buildOptionsByFormat(format) {
1523
+ const watchContext = {
1524
+ ...watchCtx,
1525
+ chunks: chunks[format] = []
1526
+ };
1527
+ const buildOptions = await getBuildOptions(config, format, configFiles, watchContext, false, isMultiFormat);
1528
+ await hooks.callHook("build:before", {
1529
+ ...context,
1530
+ buildOptions
1531
+ });
1532
+ if (debugRolldownConfigDir) await debugBuildOptions(debugRolldownConfigDir, config.name, format, buildOptions);
1533
+ const configs = [[format, buildOptions]];
1534
+ if (format === "cjs" && dts) configs.push([format, await getBuildOptions(config, format, configFiles, watchContext, true, isMultiFormat)]);
1535
+ return configs;
1536
+ }
1537
+ async function postBuild() {
1468
1538
  await Promise.all([writeExports(config, chunks), copy(config)]);
1469
1539
  await Promise.all([publint(config), attw(config)]);
1470
1540
  await hooks.callHook("build:done", context);
1471
- logger.success(prettyName(config.name), `${first ? "Build" : "Rebuild"} complete in ${green(`${Math.round(performance.now() - startTime)}ms`)}`);
1472
- ab = new AbortController();
1473
- if (typeof onSuccess === "string") {
1474
- const p = exec(onSuccess, [], { nodeOptions: {
1475
- shell: true,
1476
- stdio: "inherit"
1477
- } });
1478
- p.then(({ exitCode }) => {
1479
- if (exitCode) process.exitCode = exitCode;
1480
- });
1481
- ab.signal.addEventListener("abort", () => {
1482
- if (typeof p.pid === "number") treeKill(p.pid);
1483
- });
1484
- } else await onSuccess?.(config, ab.signal);
1541
+ ab?.abort();
1542
+ ab = executeOnSuccess(config);
1485
1543
  }
1486
1544
  }
1545
+ const dirname$1 = path.dirname(fileURLToPath(import.meta.url));
1546
+ const pkgRoot = path.resolve(dirname$1, "..");
1547
+ /** @internal */
1548
+ const shimFile = path.resolve(pkgRoot, "esm-shims.js");
1487
1549
 
1488
1550
  //#endregion
1489
1551
  export { ReportPlugin as a, ShebangPlugin as i, buildSingle as n, NodeProtocolPlugin as o, shimFile as r, ExternalPlugin as s, build$1 as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsdown",
3
- "version": "0.16.7",
3
+ "version": "0.17.0-beta.1",
4
4
  "description": "The Elegant Bundler for Libraries",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -75,43 +75,42 @@
75
75
  "dependencies": {
76
76
  "ansis": "^4.2.0",
77
77
  "cac": "^6.7.14",
78
- "chokidar": "^4.0.3",
79
78
  "diff": "^8.0.2",
80
79
  "empathic": "^2.0.0",
81
80
  "hookable": "^5.5.3",
82
81
  "obug": "^2.1.1",
83
- "rolldown": "1.0.0-beta.51",
82
+ "rolldown": "1.0.0-beta.52",
84
83
  "rolldown-plugin-dts": "^0.18.1",
85
84
  "semver": "^7.7.3",
86
85
  "tinyexec": "^1.0.2",
87
86
  "tinyglobby": "^0.2.15",
88
87
  "tree-kill": "^1.2.2",
89
88
  "unconfig-core": "^7.4.1",
90
- "unrun": "^0.2.11"
89
+ "unrun": "^0.2.14"
91
90
  },
92
91
  "devDependencies": {
93
92
  "@arethetypeswrong/core": "^0.18.2",
94
- "@sxzz/eslint-config": "^7.3.2",
95
- "@sxzz/prettier-config": "^2.2.5",
93
+ "@sxzz/eslint-config": "^7.4.0",
94
+ "@sxzz/prettier-config": "^2.2.6",
96
95
  "@sxzz/test-utils": "^0.5.13",
97
96
  "@types/node": "^24.10.1",
98
97
  "@types/semver": "^7.7.1",
99
98
  "@unocss/eslint-plugin": "^66.5.9",
100
99
  "@vitejs/devtools": "^0.0.0-alpha.18",
101
- "@vueuse/core": "^14.0.0",
102
- "bumpp": "^10.3.1",
100
+ "@vueuse/core": "^14.1.0",
101
+ "bumpp": "^10.3.2",
103
102
  "eslint": "^9.39.1",
104
103
  "is-in-ci": "^2.0.0",
105
104
  "lightningcss": "^1.30.2",
106
105
  "pkg-types": "^2.3.0",
107
- "prettier": "^3.6.2",
106
+ "prettier": "^3.7.1",
108
107
  "publint": "^0.3.15",
109
- "rolldown-plugin-require-cjs": "^0.3.1",
108
+ "rolldown-plugin-require-cjs": "^0.3.2",
110
109
  "typescript": "~5.9.3",
111
110
  "unocss": "^66.5.9",
112
111
  "unplugin-lightningcss": "^0.4.3",
113
112
  "unplugin-unused": "^0.5.6",
114
- "vite": "npm:rolldown-vite@^7.2.7",
113
+ "vite": "npm:rolldown-vite@^7.2.8",
115
114
  "vitest": "^4.0.14"
116
115
  },
117
116
  "engines": {