tsdown 0.17.0-beta.4 → 0.17.0-beta.6

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-gX-yrJuu.mjs";
1
+ import { f as UserConfig, m as UserConfigFn, p as UserConfigExport } from "./index-BQZ2CZuJ.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-gX-yrJuu.mjs";
2
- import { t as defineConfig } from "./config-CsOGKn_i.mjs";
1
+ import { f as UserConfig, m as UserConfigFn, p as UserConfigExport } from "./index-BQZ2CZuJ.mjs";
2
+ import { t as defineConfig } from "./config-DPU-roRC.mjs";
3
3
  export { UserConfig, UserConfigExport, UserConfigFn, defineConfig };
@@ -2,38 +2,12 @@ import "ansis";
2
2
  import { BuildOptions, ExternalOption, InputOption, InputOptions, InternalModuleFormat, MinifyOptions, ModuleFormat, ModuleTypes, OutputAsset, OutputChunk, OutputOptions, Plugin, TreeshakingOptions } from "rolldown";
3
3
  import { Hookable } from "hookable";
4
4
  import { Options as DtsOptions } from "rolldown-plugin-dts";
5
- import { CheckPackageOptions } from "@arethetypeswrong/core";
6
5
  import { StartOptions } from "@vitejs/devtools/cli-commands";
7
6
  import { PackageJson } from "pkg-types";
7
+ import { CheckPackageOptions } from "@arethetypeswrong/core";
8
8
  import { Options as PublintOptions } from "publint";
9
9
  import { Options as UnusedOptions } from "unplugin-unused";
10
10
 
11
- //#region src/features/attw.d.ts
12
- interface AttwOptions extends CheckPackageOptions {
13
- /**
14
- * Profiles select a set of resolution modes to require/ignore. All are evaluated but failures outside
15
- * of those required are ignored.
16
- *
17
- * The available profiles are:
18
- * - `strict`: requires all resolutions
19
- * - `node16`: ignores node10 resolution failures
20
- * - `esm-only`: ignores CJS resolution failures
21
- *
22
- * @default 'strict'
23
- */
24
- profile?: "strict" | "node16" | "esm-only";
25
- /**
26
- * The level of the check.
27
- *
28
- * The available levels are:
29
- * - `error`: fails the build
30
- * - `warn`: warns the build
31
- *
32
- * @default 'warn'
33
- */
34
- level?: "error" | "warn";
35
- }
36
- //#endregion
37
11
  //#region src/utils/types.d.ts
38
12
  type Overwrite<T, U> = Omit<T, keyof U> & U;
39
13
  type Awaitable<T> = T | Promise<T>;
@@ -64,27 +38,6 @@ interface DebugOptions extends NonNullable<InputOptions["debug"]> {
64
38
  clean?: boolean;
65
39
  }
66
40
  //#endregion
67
- //#region src/features/exports.d.ts
68
- type TsdownChunks = Partial<Record<NormalizedFormat, Array<OutputChunk | OutputAsset>>>;
69
- interface ExportsOptions {
70
- /**
71
- * Generate exports that link to source code during development.
72
- * - string: add as a custom condition.
73
- * - true: all conditions point to source files, and add dist exports to `publishConfig`.
74
- */
75
- devExports?: boolean | string;
76
- /**
77
- * Exports for all files.
78
- */
79
- all?: boolean;
80
- customExports?: (exports: Record<string, any>, context: {
81
- pkg: PackageJson;
82
- chunks: TsdownChunks;
83
- outDir: string;
84
- isPublish: boolean;
85
- }) => Awaitable<Record<string, any>>;
86
- }
87
- //#endregion
88
41
  //#region src/features/hooks.d.ts
89
42
  interface BuildContext {
90
43
  options: ResolvedConfig;
@@ -112,10 +65,15 @@ interface TsdownHooks {
112
65
  * Invoked after each tsdown build completes.
113
66
  * Use this hook for cleanup or post-processing tasks.
114
67
  */
115
- "build:done": (ctx: BuildContext) => void | Promise<void>;
68
+ "build:done": (ctx: BuildContext & {
69
+ chunks: RolldownChunk[];
70
+ }) => void | Promise<void>;
116
71
  }
117
72
  //#endregion
118
73
  //#region src/utils/package.d.ts
74
+ interface PackageJsonWithPath extends PackageJson {
75
+ packageJsonPath: string;
76
+ }
119
77
  type PackageType = "module" | "commonjs" | undefined;
120
78
  //#endregion
121
79
  //#region src/features/output.d.ts
@@ -141,6 +99,61 @@ type ChunkAddonFunction = (ctx: {
141
99
  }) => ChunkAddonObject | string | undefined;
142
100
  type ChunkAddon = ChunkAddonObject | ChunkAddonFunction | string;
143
101
  //#endregion
102
+ //#region src/features/pkg/attw.d.ts
103
+ interface AttwOptions extends CheckPackageOptions {
104
+ /**
105
+ * Profiles select a set of resolution modes to require/ignore. All are evaluated but failures outside
106
+ * of those required are ignored.
107
+ *
108
+ * The available profiles are:
109
+ * - `strict`: requires all resolutions
110
+ * - `node16`: ignores node10 resolution failures
111
+ * - `esm-only`: ignores CJS resolution failures
112
+ *
113
+ * @default 'strict'
114
+ */
115
+ profile?: "strict" | "node16" | "esm-only";
116
+ /**
117
+ * The level of the check.
118
+ *
119
+ * The available levels are:
120
+ * - `error`: fails the build
121
+ * - `warn`: warns the build
122
+ *
123
+ * @default 'warn'
124
+ */
125
+ level?: "error" | "warn";
126
+ }
127
+ //#endregion
128
+ //#region src/utils/chunks.d.ts
129
+ type RolldownChunk = (OutputChunk | OutputAsset) & {
130
+ outDir: string;
131
+ };
132
+ type ChunksByFormat = Partial<Record<NormalizedFormat, RolldownChunk[]>>;
133
+ interface TsdownBundle extends AsyncDisposable {
134
+ chunks: RolldownChunk[];
135
+ config: ResolvedConfig;
136
+ }
137
+ //#endregion
138
+ //#region src/features/pkg/exports.d.ts
139
+ interface ExportsOptions {
140
+ /**
141
+ * Generate exports that link to source code during development.
142
+ * - string: add as a custom condition.
143
+ * - true: all conditions point to source files, and add dist exports to `publishConfig`.
144
+ */
145
+ devExports?: boolean | string;
146
+ /**
147
+ * Exports for all files.
148
+ */
149
+ all?: boolean;
150
+ customExports?: (exports: Record<string, any>, context: {
151
+ pkg: PackageJson;
152
+ chunks: ChunksByFormat;
153
+ isPublish: boolean;
154
+ }) => Awaitable<Record<string, any>>;
155
+ }
156
+ //#endregion
144
157
  //#region src/utils/logger.d.ts
145
158
  type LogType = "error" | "warn" | "info";
146
159
  type LogLevel = LogType | "silent";
@@ -176,7 +189,7 @@ interface ReportOptions {
176
189
  */
177
190
  maxCompressSize?: number;
178
191
  }
179
- declare function ReportPlugin(userOptions: ReportOptions, logger: Logger, cwd: string, cjsDts?: boolean, name?: string, isMultiFormat?: boolean): Plugin;
192
+ declare function ReportPlugin(userOptions: ReportOptions, logger: Logger, cwd: string, cjsDts?: boolean, name?: string, isDualFormat?: boolean): Plugin;
180
193
  //#endregion
181
194
  //#region src/config/types.d.ts
182
195
  type Sourcemap = boolean | "inline" | "hidden";
@@ -336,11 +349,17 @@ interface UserConfig {
336
349
  cjsDts: boolean;
337
350
  }) => Awaitable<InputOptions | void | null>);
338
351
  /** @default 'es' */
339
- format?: Format | Format[];
352
+ format?: Format | Format[] | Partial<Record<Format, Partial<ResolvedConfig>>>;
340
353
  globalName?: string;
341
354
  /** @default 'dist' */
342
355
  outDir?: string;
343
356
  /**
357
+ * Whether to write the files to disk.
358
+ * This option is incompatible with watch mode.
359
+ * @default true
360
+ */
361
+ write?: boolean;
362
+ /**
344
363
  * Whether to generate source map files.
345
364
  *
346
365
  * Note that this option will always be `true` if you have
@@ -447,10 +466,6 @@ interface UserConfig {
447
466
  */
448
467
  ignoreWatch?: Arrayable<string | RegExp>;
449
468
  /**
450
- * You can specify command to be executed after a successful build, specially useful for Watch mode
451
- */
452
- onSuccess?: string | ((config: ResolvedConfig, signal: AbortSignal) => void | Promise<void>);
453
- /**
454
469
  * **[experimental]** Enable debug mode.
455
470
  *
456
471
  * Both debug mode and Vite DevTools are still under development, and this is for early testers only.
@@ -461,6 +476,10 @@ interface UserConfig {
461
476
  */
462
477
  debug?: WithEnabled<DebugOptions>;
463
478
  /**
479
+ * You can specify command to be executed after a successful build, specially useful for Watch mode
480
+ */
481
+ onSuccess?: string | ((config: ResolvedConfig, signal: AbortSignal) => void | Promise<void>);
482
+ /**
464
483
  * Enables generation of TypeScript declaration files (`.d.ts`).
465
484
  *
466
485
  * By default, this option is auto-detected based on your project's `package.json`:
@@ -548,10 +567,10 @@ type UserConfigFn = (inlineConfig: InlineConfig, context: {
548
567
  }) => Awaitable<Arrayable<UserConfig>>;
549
568
  type UserConfigExport = Awaitable<Arrayable<UserConfig> | UserConfigFn>;
550
569
  type ResolvedConfig = Overwrite<MarkPartial<Omit<UserConfig, "workspace" | "fromVite" | "publicDir" | "silent" | "bundle" | "removeNodeProtocol" | "logLevel" | "failOnWarn" | "customLogger">, "globalName" | "inputOptions" | "outputOptions" | "minify" | "define" | "alias" | "external" | "onSuccess" | "outExtensions" | "hooks" | "copy" | "loader" | "name" | "banner" | "footer">, {
551
- format: NormalizedFormat[];
570
+ format: NormalizedFormat;
552
571
  target?: string[];
553
572
  clean: string[];
554
- pkg?: PackageJson;
573
+ pkg?: PackageJsonWithPath;
555
574
  nodeProtocol: "strip" | boolean;
556
575
  logger: Logger;
557
576
  ignoreWatch: Array<string | RegExp>;
@@ -567,4 +586,4 @@ type ResolvedConfig = Overwrite<MarkPartial<Omit<UserConfig, "workspace" | "from
567
586
  unused: false | UnusedOptions;
568
587
  }>;
569
588
  //#endregion
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 };
589
+ export { OutExtensionObject as A, TsdownBundle as C, ChunkAddonObject as D, ChunkAddonFunction as E, TsdownHooks as F, DebugOptions as I, CopyEntry as L, PackageType as M, BuildContext as N, OutExtensionContext as O, RolldownContext as P, CopyOptions as R, RolldownChunk as S, ChunkAddon 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, PackageJsonWithPath as j, OutExtensionFactory 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, AttwOptions as w, ExportsOptions as x, Logger as y, CopyOptionsFn as z };
package/dist/index.d.mts CHANGED
@@ -1,10 +1,8 @@
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-gX-yrJuu.mjs";
2
- import { t as defineConfig } from "./config-CsOGKn_i.mjs";
1
+ import { A as OutExtensionObject, C as TsdownBundle, D as ChunkAddonObject, E as ChunkAddonFunction, F as TsdownHooks, I as DebugOptions, L as CopyEntry, M as PackageType, N as BuildContext, O as OutExtensionContext, P as RolldownContext, R as CopyOptions, S as RolldownChunk, T as ChunkAddon, _ 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 PackageJsonWithPath, k as OutExtensionFactory, 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 AttwOptions, x as ExportsOptions, y as Logger, z as CopyOptionsFn } from "./index-BQZ2CZuJ.mjs";
2
+ import { t as defineConfig } from "./config-DPU-roRC.mjs";
3
3
 
4
4
  //#region src/index.d.ts
5
- interface TsdownBundle extends AsyncDisposable {
6
- chunks: TsdownChunks;
7
- }
5
+
8
6
  /**
9
7
  * Build with tsdown.
10
8
  */
@@ -17,8 +15,8 @@ declare function build(userOptions?: InlineConfig): Promise<TsdownBundle[]>;
17
15
  * @private
18
16
  * @param config Resolved options
19
17
  */
20
- declare function buildSingle(config: ResolvedConfig, configFiles: string[], clean: () => Promise<void>, restart: () => void): Promise<TsdownBundle>;
18
+ declare function buildSingle(config: ResolvedConfig, configFiles: string[], isDualFormat: boolean, clean: () => Promise<void>, restart: () => void, done: (bundle: TsdownBundle) => Promise<void>): Promise<TsdownBundle>;
21
19
  /** @internal */
22
20
  declare const shimFile: string;
23
21
  //#endregion
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 };
22
+ export { AttwOptions, BuildContext, CIOption, ChunkAddon, ChunkAddonFunction, ChunkAddonObject, CopyEntry, CopyOptions, CopyOptionsFn, DebugOptions, DtsOptions, ExportsOptions, Format, InlineConfig, type Logger, NoExternalFn, NormalizedFormat, OutExtensionContext, OutExtensionFactory, OutExtensionObject, PackageJsonWithPath, PackageType, PublintOptions, ReportOptions, ResolvedConfig, RolldownChunk, RolldownContext, Sourcemap, TreeshakingOptions, TsdownBundle, 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-Bz4Gwq5G.mjs";
3
- import { a as globalLogger } from "./package-xGnUa543.mjs";
2
+ import { n as buildSingle, r as shimFile, t as build } from "./src-9i07TsDd.mjs";
3
+ import { a as globalLogger } from "./package-ByEiRv2l.mjs";
4
4
 
5
5
  export { build, buildSingle, defineConfig, globalLogger, shimFile };
@@ -1,4 +1,5 @@
1
1
  import { bgRed, bgYellow, blue, green, rgb, yellow } from "ansis";
2
+ import process from "node:process";
2
3
 
3
4
  //#region src/utils/general.ts
4
5
  function toArray(val, defaultValue) {
@@ -42,6 +43,15 @@ async function importWithError(moduleName) {
42
43
  throw new Error(`Failed to import module "${moduleName}". Please ensure it is installed.`, { cause: error });
43
44
  }
44
45
  }
46
+ function promiseWithResolvers() {
47
+ let resolve;
48
+ return {
49
+ promise: new Promise((res) => {
50
+ resolve = res;
51
+ }),
52
+ resolve
53
+ };
54
+ }
45
55
 
46
56
  //#endregion
47
57
  //#region src/utils/logger.ts
@@ -67,20 +77,21 @@ function createLogger(level = "info", { customLogger, console = globalThis.conso
67
77
  output("info", `${blue`ℹ`} ${format(msgs)}`);
68
78
  },
69
79
  warn(...msgs) {
80
+ if (failOnWarn) return this.error(...msgs);
70
81
  const message = format(msgs);
71
- if (failOnWarn) throw new Error(message);
72
82
  warnedMessages.add(message);
73
83
  output("warn", `\n${bgYellow` WARN `} ${message}\n`);
74
84
  },
75
85
  warnOnce(...msgs) {
76
86
  const message = format(msgs);
77
87
  if (warnedMessages.has(message)) return;
78
- if (failOnWarn) throw new Error(message);
88
+ if (failOnWarn) return this.error(...msgs);
79
89
  warnedMessages.add(message);
80
90
  output("warn", `\n${bgYellow` WARN `} ${message}\n`);
81
91
  },
82
92
  error(...msgs) {
83
93
  output("error", `\n${bgRed` ERROR `} ${format(msgs)}\n`);
94
+ process.exitCode = 1;
84
95
  },
85
96
  success(...msgs) {
86
97
  output("info", `${green`✔`} ${format(msgs)}`);
@@ -150,7 +161,7 @@ function hue2rgb(p, q, t) {
150
161
 
151
162
  //#endregion
152
163
  //#region package.json
153
- var version = "0.17.0-beta.4";
164
+ var version = "0.17.0-beta.6";
154
165
 
155
166
  //#endregion
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 };
167
+ export { globalLogger as a, importWithError as c, pkgExists as d, promiseWithResolvers as f, toArray as g, slash as h, generateColor as i, matchPattern as l, resolveRegex as m, LogLevels as n, prettyFormat as o, resolveComma as p, createLogger as r, prettyName as s, version as t, noop as u };
@@ -1,5 +1,5 @@
1
- import { c as ResolvedConfig, v as ReportPlugin, y as Logger } from "./index-gX-yrJuu.mjs";
2
- import { OutputAsset, OutputChunk, Plugin } from "rolldown";
1
+ import { C as TsdownBundle, c as ResolvedConfig, v as ReportPlugin, y as Logger } from "./index-BQZ2CZuJ.mjs";
2
+ import { Plugin } from "rolldown";
3
3
 
4
4
  //#region src/features/external.d.ts
5
5
  declare function ExternalPlugin({
@@ -9,9 +9,6 @@ declare function ExternalPlugin({
9
9
  skipNodeModulesBundle
10
10
  }: ResolvedConfig): Plugin;
11
11
  //#endregion
12
- //#region src/features/shebang.d.ts
13
- declare function ShebangPlugin(logger: Logger, cwd: string, name?: string, isMultiFormat?: boolean): Plugin;
14
- //#endregion
15
12
  //#region src/features/node-protocol.d.ts
16
13
  /**
17
14
  * The `node:` protocol was added in Node.js v14.18.0.
@@ -19,14 +16,13 @@ declare function ShebangPlugin(logger: Logger, cwd: string, name?: string, isMul
19
16
  */
20
17
  declare function NodeProtocolPlugin(nodeProtocolOption: "strip" | true): Plugin;
21
18
  //#endregion
19
+ //#region src/features/shebang.d.ts
20
+ declare function ShebangPlugin(logger: Logger, cwd: string, name?: string, isDualFormat?: boolean): Plugin;
21
+ //#endregion
22
22
  //#region src/features/watch.d.ts
23
- interface WatchContext {
24
- config: ResolvedConfig;
25
- chunks: Array<OutputChunk | OutputAsset>;
26
- }
27
23
  declare function WatchPlugin(configFiles: string[], {
28
24
  config,
29
25
  chunks
30
- }: WatchContext): Plugin;
26
+ }: TsdownBundle): Plugin;
31
27
  //#endregion
32
28
  export { ExternalPlugin, NodeProtocolPlugin, ReportPlugin, ShebangPlugin, WatchPlugin };
package/dist/plugins.mjs CHANGED
@@ -1,5 +1,4 @@
1
- import "./config-DLSWqKoz.mjs";
2
- import { a as ShebangPlugin, c as ExternalPlugin, i as WatchPlugin, o as ReportPlugin, s as NodeProtocolPlugin } from "./src-Bz4Gwq5G.mjs";
3
- import "./package-xGnUa543.mjs";
1
+ import { a as ShebangPlugin, c as ExternalPlugin, i as WatchPlugin, o as ReportPlugin, s as NodeProtocolPlugin } from "./src-9i07TsDd.mjs";
2
+ import "./package-ByEiRv2l.mjs";
4
3
 
5
4
  export { ExternalPlugin, NodeProtocolPlugin, ReportPlugin, ShebangPlugin, WatchPlugin };
package/dist/run.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as globalLogger, f as resolveComma, h as toArray, t as version } from "./package-xGnUa543.mjs";
2
+ import { a as globalLogger, g as toArray, p as resolveComma, t as version } from "./package-ByEiRv2l.mjs";
3
3
  import module from "node:module";
4
4
  import { dim } from "ansis";
5
5
  import { VERSION } from "rolldown";
@@ -29,7 +29,7 @@ cli.help().version(version);
29
29
  cli.command("[...files]", "Bundle files", {
30
30
  ignoreOptionDefaultValue: true,
31
31
  allowUnknownOptions: true
32
- }).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("--external <module>", "Mark dependencies as external").option("--minify", "Minify output").option("--debug", "Enable debug mode").option("--debug-logs [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("-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("--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("-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) => {
32
+ }).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("--external <module>", "Mark dependencies as external").option("--minify", "Minify output").option("--debug", "Enable debug mode").option("--debug-logs [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("--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("-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) => {
33
33
  globalLogger.level = flags.logLevel || (flags.silent ? "error" : "info");
34
34
  globalLogger.info(`tsdown ${dim`v${version}`} powered by rolldown ${dim`v${VERSION}`}`);
35
35
  const { build: build$1 } = await import("./index.mjs");
@@ -1,11 +1,11 @@
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 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-xGnUa543.mjs";
3
+ import { a as globalLogger, c as importWithError, d as pkgExists, f as promiseWithResolvers, g as toArray, h as slash, i as generateColor, l as matchPattern, m as resolveRegex, n as LogLevels, o as prettyFormat, p as resolveComma, r as createLogger, s as prettyName, t as version, u as noop } from "./package-ByEiRv2l.mjs";
4
4
  import { builtinModules, isBuiltin } from "node:module";
5
5
  import path, { dirname, join, normalize, sep } from "node:path";
6
6
  import { fileURLToPath, pathToFileURL } from "node:url";
7
7
  import { blue, bold, dim, green, underline } from "ansis";
8
- import { clearCJSCache, init, isSupported } from "import-without-cache";
8
+ import { clearRequireCache, init, isSupported } from "import-without-cache";
9
9
  import { VERSION, build, watch } from "rolldown";
10
10
  import { createDebug } from "obug";
11
11
  import { access, chmod, cp, mkdtemp, readFile, rm, stat, writeFile } from "node:fs/promises";
@@ -16,13 +16,13 @@ import { RE_CSS, RE_DTS, RE_JS, RE_NODE_MODULES } from "rolldown-plugin-dts/file
16
16
  const minVersion = __cjs_require("semver/ranges/min-version.js");
17
17
  import { up } from "empathic/find";
18
18
  import { up as up$1 } from "empathic/package";
19
- import { tmpdir } from "node:os";
20
- import { exec } from "tinyexec";
21
19
  const coerce = __cjs_require("semver/functions/coerce.js");
22
20
  const satisfies = __cjs_require("semver/functions/satisfies.js");
23
21
  import { createHooks } from "hookable";
22
+ import { exec } from "tinyexec";
24
23
  const treeKill = __cjs_require("tree-kill");
25
- import util, { promisify } from "node:util";
24
+ import util, { formatWithOptions, promisify } from "node:util";
25
+ import { tmpdir } from "node:os";
26
26
  import { importGlobPlugin } from "rolldown/experimental";
27
27
  import { Buffer } from "node:buffer";
28
28
  import { brotliCompress, gzip } from "node:zlib";
@@ -167,8 +167,11 @@ async function loadConfigFile(inlineConfig, workspace) {
167
167
  file
168
168
  };
169
169
  }
170
+ const isBun = !!process.versions.bun;
171
+ const nativeTS = process.features.typescript || process.versions.deno;
172
+ const autoLoader = isBun || nativeTS && isSupported ? "native" : "unrun";
170
173
  function resolveConfigLoader(configLoader = "auto") {
171
- if (configLoader === "auto") return !!(process.features.typescript || process.versions.bun || process.versions.deno) && isSupported ? "native" : "unrun";
174
+ if (configLoader === "auto") return autoLoader;
172
175
  else return configLoader === "native" ? "native" : "unrun";
173
176
  }
174
177
  function createParser(loader) {
@@ -191,7 +194,7 @@ async function nativeImport(id) {
191
194
  if (isSupported) {
192
195
  importAttributes.cache = "no";
193
196
  init();
194
- } else url.searchParams.set("no-cache", crypto.randomUUID());
197
+ } else if (!isBun) url.searchParams.set("no-cache", crypto.randomUUID());
195
198
  const mod = await import(url.href, { with: importAttributes }).catch((error) => {
196
199
  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 });
197
200
  else throw error;
@@ -294,12 +297,11 @@ function detectIndentation(jsonText) {
294
297
  }
295
298
 
296
299
  //#endregion
297
- //#region src/features/exports.ts
300
+ //#region src/features/pkg/exports.ts
298
301
  async function writeExports(options, chunks) {
299
- if (!options.exports) return;
300
- const { outDir, pkg } = options;
301
- if (!pkg) throw new Error("`package.json` not found, cannot write exports");
302
- const { publishExports, ...generated } = await generateExports(pkg, outDir, chunks, options.exports);
302
+ const pkg = options.pkg;
303
+ const exports = options.exports;
304
+ const { publishExports, ...generated } = await generateExports(pkg, chunks, exports);
303
305
  const updatedPkg = {
304
306
  ...pkg,
305
307
  ...generated,
@@ -314,10 +316,8 @@ async function writeExports(options, chunks) {
314
316
  if (original.endsWith("\n")) contents += "\n";
315
317
  if (contents !== original) await writeFile(pkg.packageJsonPath, contents, "utf8");
316
318
  }
317
- async function generateExports(pkg, outDir, chunks, { devExports, all, customExports }) {
318
- const pkgJsonPath = pkg.packageJsonPath;
319
- const pkgRoot$1 = path.dirname(pkgJsonPath);
320
- const outDirRelative = slash(path.relative(pkgRoot$1, outDir));
319
+ async function generateExports(pkg, chunks, { devExports, all, customExports }) {
320
+ const pkgRoot$1 = path.dirname(pkg.packageJsonPath);
321
321
  let main, module$1, cjsTypes, esmTypes;
322
322
  const exportsMap = /* @__PURE__ */ new Map();
323
323
  for (const [format, chunksByFormat] of Object.entries(chunks)) {
@@ -331,6 +331,7 @@ async function generateExports(pkg, outDir, chunks, { devExports, all, customExp
331
331
  const isDts = name.endsWith(".d");
332
332
  if (isDts) name = name.slice(0, -2);
333
333
  const isIndex = onlyOneEntry || name === "index";
334
+ const outDirRelative = slash(path.relative(pkgRoot$1, chunk.outDir));
334
335
  const distFile = `${outDirRelative ? `./${outDirRelative}` : "."}/${normalizedName}`;
335
336
  if (isIndex) {
336
337
  name = ".";
@@ -359,7 +360,6 @@ async function generateExports(pkg, outDir, chunks, { devExports, all, customExp
359
360
  exportMeta(exports, all);
360
361
  if (customExports) exports = await customExports(exports, {
361
362
  pkg,
362
- outDir,
363
363
  chunks,
364
364
  isPublish: false
365
365
  });
@@ -369,7 +369,6 @@ async function generateExports(pkg, outDir, chunks, { devExports, all, customExp
369
369
  exportMeta(publishExports, all);
370
370
  if (customExports) publishExports = await customExports(publishExports, {
371
371
  pkg,
372
- outDir,
373
372
  chunks,
374
373
  isPublish: true
375
374
  });
@@ -390,8 +389,8 @@ function genSubExport(devExports, { src, es, cjs }) {
390
389
  else {
391
390
  value = {};
392
391
  if (typeof devExports === "string") value[devExports] = src;
393
- if (es) value[dualFormat ? "import" : "default"] = es;
394
392
  if (cjs) value[dualFormat ? "require" : "default"] = cjs;
393
+ if (es) value[dualFormat ? "import" : "default"] = es;
395
394
  }
396
395
  return value;
397
396
  }
@@ -483,28 +482,26 @@ function getPackageType(pkg) {
483
482
  }
484
483
  }
485
484
  function normalizeFormat(format) {
486
- return resolveComma(toArray(format, "es")).map((format$1) => {
487
- switch (format$1) {
488
- case "es":
489
- case "esm":
490
- case "module": return "es";
491
- case "cjs":
492
- case "commonjs": return "cjs";
493
- default: return format$1;
494
- }
495
- });
485
+ switch (format) {
486
+ case "es":
487
+ case "esm":
488
+ case "module": return "es";
489
+ case "cjs":
490
+ case "commonjs": return "cjs";
491
+ default: return format;
492
+ }
496
493
  }
497
494
 
498
495
  //#endregion
499
496
  //#region src/config/options.ts
500
497
  const debugLog = createDebug("tsdown:config:options");
501
498
  async function resolveUserConfig(userConfig, inlineConfig) {
502
- 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$10 = false } = userConfig;
499
+ 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$10 = false, write = true } = userConfig;
503
500
  const pkg = await readPackageJson(cwd);
504
501
  if (workspace) name ||= pkg?.name;
505
502
  if (!filterConfig(inlineConfig.filter, cwd, name)) {
506
503
  debugLog("[filter] skipping config %s", cwd);
507
- return;
504
+ return [];
508
505
  }
509
506
  const logger = createLogger(logLevel, {
510
507
  customLogger,
@@ -527,6 +524,11 @@ async function resolveUserConfig(userConfig, inlineConfig) {
527
524
  unused = resolveFeatureOption(unused, {});
528
525
  report = resolveFeatureOption(report, {});
529
526
  dts = resolveFeatureOption(dts, {});
527
+ if (!pkg) {
528
+ if (exports) throw new Error("`package.json` not found, cannot write exports");
529
+ if (publint$1) logger.warn(prettyName(name), "publint is enabled but package.json is not found");
530
+ if (attw$1) logger.warn(prettyName(name), "attw is enabled but package.json is not found");
531
+ }
530
532
  if (publicDir) if (copy$1) throw new TypeError("`publicDir` is deprecated. Cannot be used with `copy`");
531
533
  else logger.warn(`${blue`publicDir`} is deprecated. Use ${blue`copy`} instead.`);
532
534
  if (fromVite) {
@@ -556,7 +558,7 @@ async function resolveUserConfig(userConfig, inlineConfig) {
556
558
  if (debug$10.devtools) logger.warn("Devtools is not supported in watch mode, disabling it.");
557
559
  debug$10.devtools = false;
558
560
  } else debug$10.devtools ??= !!pkgExists("@vitejs/devtools/cli");
559
- return {
561
+ const config = {
560
562
  ...userConfig,
561
563
  alias,
562
564
  attw: attw$1,
@@ -571,7 +573,6 @@ async function resolveUserConfig(userConfig, inlineConfig) {
571
573
  exports,
572
574
  external,
573
575
  fixedExtension,
574
- format: normalizeFormat(format),
575
576
  globImport,
576
577
  hash,
577
578
  ignoreWatch,
@@ -594,8 +595,22 @@ async function resolveUserConfig(userConfig, inlineConfig) {
594
595
  tsconfig,
595
596
  unbundle,
596
597
  unused,
597
- watch: watch$1
598
+ watch: watch$1,
599
+ write
598
600
  };
601
+ const objectFormat = typeof format === "object" && !Array.isArray(format);
602
+ return (objectFormat ? Object.keys(format) : resolveComma(toArray(format, "es"))).map((fmt, idx) => {
603
+ const once = idx === 0;
604
+ const overrides = objectFormat ? format[fmt] : void 0;
605
+ return {
606
+ ...config,
607
+ copy: once ? config.copy : void 0,
608
+ hooks: once ? config.hooks : void 0,
609
+ onSuccess: once ? config.onSuccess : void 0,
610
+ format: normalizeFormat(fmt),
611
+ ...overrides
612
+ };
613
+ });
599
614
  }
600
615
  async function mergeUserOptions(defaults, user, args) {
601
616
  const userOutputOptions = typeof user === "function" ? await user(defaults, ...args) : user;
@@ -693,8 +708,9 @@ async function resolveConfig(inlineConfig) {
693
708
  } else debug$5("no root user config file found");
694
709
  const configs = (await Promise.all(rootConfigs.map(async (rootConfig) => {
695
710
  const { configs: workspaceConfigs, files: workspaceFiles } = await resolveWorkspace(rootConfig, inlineConfig);
711
+ debug$5("workspace configs %O", workspaceConfigs);
696
712
  if (workspaceFiles) files.push(...workspaceFiles);
697
- return (await Promise.all(workspaceConfigs.filter((config) => !config.workspace || config.entry).map((config) => resolveUserConfig(config, inlineConfig)))).filter((config) => !!config);
713
+ return (await Promise.all(workspaceConfigs.filter((config) => !config.workspace || config.entry).map((config) => resolveUserConfig(config, inlineConfig)))).flat().filter((config) => !!config);
698
714
  }))).flat();
699
715
  debug$5("resolved configs %O", configs);
700
716
  if (configs.length === 0) throw new Error("No valid configuration found.");
@@ -705,7 +721,69 @@ async function resolveConfig(inlineConfig) {
705
721
  }
706
722
 
707
723
  //#endregion
708
- //#region src/features/attw.ts
724
+ //#region src/features/cjs.ts
725
+ /**
726
+ * If the config includes the `cjs` format and
727
+ * one of its target >= node 23.0.0 / 22.12.0,
728
+ * warn the user about the deprecation of CommonJS.
729
+ */
730
+ function warnLegacyCJS(config) {
731
+ if (!config.format.includes("cjs") || !config.target) return;
732
+ if (config.target.some((t) => {
733
+ const version$1 = coerce(t.split("node")[1]);
734
+ return version$1 && satisfies(version$1, ">=23.0.0 || >=22.12.0");
735
+ })) config.logger.warnOnce("We recommend using the ESM format instead of CommonJS.\nThe ESM format is compatible with modern platforms and runtimes, and most new libraries are now distributed only in ESM format.\nLearn more at https://nodejs.org/en/learn/modules/publishing-a-package#how-did-we-get-here");
736
+ }
737
+
738
+ //#endregion
739
+ //#region src/features/copy.ts
740
+ async function copy(options) {
741
+ if (!options.copy) return;
742
+ const copy$1 = typeof options.copy === "function" ? await options.copy(options) : options.copy;
743
+ await Promise.all(toArray(copy$1).map((dir) => {
744
+ const from = typeof dir === "string" ? dir : dir.from;
745
+ const to = typeof dir === "string" ? path.resolve(options.outDir, path.basename(from)) : dir.to;
746
+ return cp$1(options.cwd, from, to);
747
+ }));
748
+ }
749
+ function cp$1(cwd, from, to) {
750
+ return fsCopy(path.resolve(cwd, from), path.resolve(cwd, to));
751
+ }
752
+
753
+ //#endregion
754
+ //#region src/features/hooks.ts
755
+ async function createHooks$1(options) {
756
+ const hooks = createHooks();
757
+ if (typeof options.hooks === "object") hooks.addHooks(options.hooks);
758
+ else if (typeof options.hooks === "function") await options.hooks(hooks);
759
+ return {
760
+ hooks,
761
+ context: {
762
+ options,
763
+ hooks
764
+ }
765
+ };
766
+ }
767
+ function executeOnSuccess(config) {
768
+ if (!config.onSuccess) return;
769
+ const ab = new AbortController();
770
+ if (typeof config.onSuccess === "string") {
771
+ const p = exec(config.onSuccess, [], { nodeOptions: {
772
+ shell: true,
773
+ stdio: "inherit"
774
+ } });
775
+ p.then(({ exitCode }) => {
776
+ if (exitCode) process.exitCode = exitCode;
777
+ });
778
+ ab.signal.addEventListener("abort", () => {
779
+ if (typeof p.pid === "number") treeKill(p.pid);
780
+ });
781
+ } else config.onSuccess(config, ab.signal);
782
+ return ab;
783
+ }
784
+
785
+ //#endregion
786
+ //#region src/features/pkg/attw.ts
709
787
  const debug$4 = createDebug("tsdown:attw");
710
788
  const label$1 = dim`[attw]`;
711
789
  /**
@@ -745,8 +823,6 @@ async function attw(options) {
745
823
  checkResult = await attwCore.checkPackage(pkg, attwOptions);
746
824
  } catch (error) {
747
825
  options.logger.error("ATTW check failed:", error);
748
- debug$4("Found errors, setting exit code to 1");
749
- process.exitCode = 1;
750
826
  return;
751
827
  } finally {
752
828
  await fsRemove(tempDir);
@@ -759,13 +835,8 @@ async function attw(options) {
759
835
  });
760
836
  if (problems.length) errorMessage = `problems found:\n${problems.map(formatProblem).join("\n")}`;
761
837
  } else errorMessage = `Package has no types`;
762
- if (errorMessage) {
763
- options.logger[level](prettyName(options.name), label$1, errorMessage);
764
- if (level === "error") {
765
- process.exitCode = 1;
766
- debug$4("Found problems, setting exit code to 1");
767
- }
768
- } else options.logger.success(prettyName(options.name), label$1, "No problems found", dim`(${Math.round(performance.now() - t)}ms)`);
838
+ if (errorMessage) options.logger[level](prettyName(options.name), label$1, errorMessage);
839
+ else options.logger.success(prettyName(options.name), label$1, "No problems found", dim`(${Math.round(performance.now() - t)}ms)`);
769
840
  }
770
841
  /**
771
842
  * Format an ATTW problem for display
@@ -794,69 +865,7 @@ function formatProblem(problem) {
794
865
  }
795
866
 
796
867
  //#endregion
797
- //#region src/features/cjs.ts
798
- /**
799
- * If the config includes the `cjs` format and
800
- * one of its target >= node 23.0.0 / 22.12.0,
801
- * warn the user about the deprecation of CommonJS.
802
- */
803
- function warnLegacyCJS(config) {
804
- if (!config.format.includes("cjs") || !config.target) return;
805
- if (config.target.some((t) => {
806
- const version$1 = coerce(t.split("node")[1]);
807
- return version$1 && satisfies(version$1, ">=23.0.0 || >=22.12.0");
808
- })) config.logger.warnOnce("We recommend using the ESM format instead of CommonJS.\nThe ESM format is compatible with modern platforms and runtimes, and most new libraries are now distributed only in ESM format.\nLearn more at https://nodejs.org/en/learn/modules/publishing-a-package#how-did-we-get-here");
809
- }
810
-
811
- //#endregion
812
- //#region src/features/copy.ts
813
- async function copy(options) {
814
- if (!options.copy) return;
815
- const copy$1 = typeof options.copy === "function" ? await options.copy(options) : options.copy;
816
- await Promise.all(toArray(copy$1).map((dir) => {
817
- const from = typeof dir === "string" ? dir : dir.from;
818
- const to = typeof dir === "string" ? path.resolve(options.outDir, path.basename(from)) : dir.to;
819
- return cp$1(options.cwd, from, to);
820
- }));
821
- }
822
- function cp$1(cwd, from, to) {
823
- return fsCopy(path.resolve(cwd, from), path.resolve(cwd, to));
824
- }
825
-
826
- //#endregion
827
- //#region src/features/hooks.ts
828
- async function createHooks$1(options) {
829
- const hooks = createHooks();
830
- if (typeof options.hooks === "object") hooks.addHooks(options.hooks);
831
- else if (typeof options.hooks === "function") await options.hooks(hooks);
832
- return {
833
- hooks,
834
- context: {
835
- options,
836
- hooks
837
- }
838
- };
839
- }
840
- function executeOnSuccess(config) {
841
- if (!config.onSuccess) return;
842
- const ab = new AbortController();
843
- if (typeof config.onSuccess === "string") {
844
- const p = exec(config.onSuccess, [], { nodeOptions: {
845
- shell: true,
846
- stdio: "inherit"
847
- } });
848
- p.then(({ exitCode }) => {
849
- if (exitCode) process.exitCode = exitCode;
850
- });
851
- ab.signal.addEventListener("abort", () => {
852
- if (typeof p.pid === "number") treeKill(p.pid);
853
- });
854
- } else config.onSuccess(config, ab.signal);
855
- return ab;
856
- }
857
-
858
- //#endregion
859
- //#region src/features/publint.ts
868
+ //#region src/features/pkg/publint.ts
860
869
  const debug$3 = createDebug("tsdown:publint");
861
870
  const label = dim`[publint]`;
862
871
  async function publint(options) {
@@ -878,9 +887,7 @@ async function publint(options) {
878
887
  options.logger.success(prettyName(options.name), label, "No issues found", dim`(${Math.round(performance.now() - t)}ms)`);
879
888
  return;
880
889
  }
881
- let hasError = false;
882
890
  for (const message of messages) {
883
- hasError ||= message.type === "error";
884
891
  const formattedMessage = formatMessage(message, options.pkg);
885
892
  const logType = {
886
893
  error: "error",
@@ -889,10 +896,66 @@ async function publint(options) {
889
896
  }[message.type];
890
897
  options.logger[logType](prettyName(options.name), label, formattedMessage);
891
898
  }
892
- if (hasError) {
893
- debug$3("Found errors, setting exit code to 1");
894
- process.exitCode = 1;
899
+ }
900
+
901
+ //#endregion
902
+ //#region src/features/pkg/index.ts
903
+ function initBundleByPkg(configs) {
904
+ const map = {};
905
+ for (const config of configs) {
906
+ const pkgJson = config.pkg?.packageJsonPath;
907
+ if (!pkgJson) continue;
908
+ if (!map[pkgJson]) {
909
+ const { promise, resolve } = promiseWithResolvers();
910
+ map[pkgJson] = {
911
+ promise,
912
+ resolve,
913
+ count: 0,
914
+ formats: /* @__PURE__ */ new Set(),
915
+ bundles: []
916
+ };
917
+ }
918
+ map[pkgJson].count++;
919
+ map[pkgJson].formats.add(config.format);
920
+ }
921
+ return map;
922
+ }
923
+ async function bundleDone(bundleByPkg, bundle) {
924
+ const pkg = bundle.config.pkg;
925
+ if (!pkg) return;
926
+ const ctx = bundleByPkg[pkg.packageJsonPath];
927
+ ctx.bundles.push(bundle);
928
+ if (ctx.bundles.length < ctx.count) return ctx.promise;
929
+ const configs = ctx.bundles.map(({ config }) => config);
930
+ const exportsConfigs = dedupeConfigs(configs, "exports");
931
+ if (exportsConfigs.length) {
932
+ if (exportsConfigs.length > 1) throw new Error(`Conflicting exports options for package at ${pkg.packageJsonPath}. Please merge them:\n${exportsConfigs.map((config) => `- ${formatWithOptions({ colors: true }, config.exports)}`).join("\n")}`);
933
+ const chunks = {};
934
+ for (const bundle$1 of ctx.bundles) {
935
+ if (!bundle$1.config.exports) continue;
936
+ chunks[bundle$1.config.format] ||= [];
937
+ chunks[bundle$1.config.format].push(...bundle$1.chunks);
938
+ }
939
+ await writeExports(exportsConfigs[0], chunks);
895
940
  }
941
+ const publintConfigs = dedupeConfigs(configs, "publint");
942
+ const attwConfigs = dedupeConfigs(configs, "attw");
943
+ if (publintConfigs.length > 1 || attwConfigs.length > 1) publintConfigs[1].logger.warn(`Multiple publint or attw configurations found for package at ${pkg.packageJsonPath}. Consider merging them for better consistency and performance.`);
944
+ await Promise.all([...publintConfigs.map((config) => publint(config)), ...attwConfigs.map((config) => attw(config))]);
945
+ ctx.resolve();
946
+ }
947
+ function dedupeConfigs(configs, key) {
948
+ const filtered = configs.filter((config) => config[key]);
949
+ if (!filtered.length) return [];
950
+ const seen = /* @__PURE__ */ new Set();
951
+ const results = filtered.filter((config) => {
952
+ if (!Object.keys(config[key]).length) return false;
953
+ if (seen.has(config[key])) return false;
954
+ seen.add(config[key]);
955
+ return true;
956
+ });
957
+ if (results.length === 0) return [filtered[0]];
958
+ return results;
896
959
  }
897
960
 
898
961
  //#endregion
@@ -1093,7 +1156,7 @@ const defaultOptions = {
1093
1156
  brotli: false,
1094
1157
  maxCompressSize: 1e6
1095
1158
  };
1096
- function ReportPlugin(userOptions, logger, cwd, cjsDts, name, isMultiFormat) {
1159
+ function ReportPlugin(userOptions, logger, cwd, cjsDts, name, isDualFormat) {
1097
1160
  const options = {
1098
1161
  ...defaultOptions,
1099
1162
  ...userOptions
@@ -1124,7 +1187,7 @@ function ReportPlugin(userOptions, logger, cwd, cjsDts, name, isMultiFormat) {
1124
1187
  return b.raw - a.raw;
1125
1188
  });
1126
1189
  const nameLabel = prettyName(name);
1127
- const formatLabel = isMultiFormat && prettyFormat(cjsDts ? "cjs" : outputOptions.format);
1190
+ const formatLabel = isDualFormat && prettyFormat(cjsDts ? "cjs" : outputOptions.format);
1128
1191
  for (const size of sizes) {
1129
1192
  const filenameColor = size.dts ? green : noop;
1130
1193
  logger.info(nameLabel, formatLabel, dim(outDir + path.sep) + filenameColor((size.isEntry ? bold : noop)(size.filename)), ` `.repeat(filenameLength - size.filename.length), dim(size.rawText), options.gzip && size.gzipText && dim`│ gzip: ${size.gzipText}`, options.brotli && size.brotliText && dim`│ brotli: ${size.brotliText}`);
@@ -1168,7 +1231,7 @@ async function calcSize(options, chunk) {
1168
1231
  //#endregion
1169
1232
  //#region src/features/shebang.ts
1170
1233
  const RE_SHEBANG = /^#!.*/;
1171
- function ShebangPlugin(logger, cwd, name, isMultiFormat) {
1234
+ function ShebangPlugin(logger, cwd, name, isDualFormat) {
1172
1235
  return {
1173
1236
  name: "tsdown:shebang",
1174
1237
  async writeBundle(options, bundle) {
@@ -1177,7 +1240,7 @@ function ShebangPlugin(logger, cwd, name, isMultiFormat) {
1177
1240
  if (!RE_SHEBANG.test(chunk.code)) continue;
1178
1241
  const filepath = path.resolve(cwd, options.file || path.join(options.dir, chunk.fileName));
1179
1242
  if (await fsExists(filepath)) {
1180
- logger.info(prettyName(name), isMultiFormat && prettyFormat(options.format), `Granting execute permission to ${underline(path.relative(cwd, filepath))}`);
1243
+ logger.info(prettyName(name), isDualFormat && prettyFormat(options.format), `Granting execute permission to ${underline(path.relative(cwd, filepath))}`);
1181
1244
  await chmod(filepath, 493);
1182
1245
  }
1183
1246
  }
@@ -1194,9 +1257,18 @@ function getShimsInject(format, platform) {
1194
1257
  };
1195
1258
  }
1196
1259
 
1260
+ //#endregion
1261
+ //#region src/utils/chunks.ts
1262
+ function addOutDirToChunks(chunks, outDir) {
1263
+ return chunks.map((chunk) => {
1264
+ chunk.outDir = outDir;
1265
+ return chunk;
1266
+ });
1267
+ }
1268
+
1197
1269
  //#endregion
1198
1270
  //#region src/features/watch.ts
1199
- const endsWithConfig = /[\\/](?:tsdown\.config.*|tsconfig\.json)$/;
1271
+ const endsWithConfig = /[\\/](?:tsdown\.config.*|package\.json|tsconfig\.json)$/;
1200
1272
  function WatchPlugin(configFiles, { config, chunks }) {
1201
1273
  return {
1202
1274
  name: "tsdown:watch",
@@ -1209,11 +1281,12 @@ function WatchPlugin(configFiles, { config, chunks }) {
1209
1281
  config.tsconfig && this.addWatchFile(config.tsconfig);
1210
1282
  for (const file of configFiles) this.addWatchFile(file);
1211
1283
  if (typeof config.watch !== "boolean") for (const file of resolveComma(toArray(config.watch))) this.addWatchFile(file);
1284
+ if (config.pkg) this.addWatchFile(config.pkg.packageJsonPath);
1212
1285
  },
1213
1286
  generateBundle: {
1214
1287
  order: "post",
1215
1288
  handler(outputOptions, bundle) {
1216
- chunks.push(...Object.values(bundle));
1289
+ chunks.push(...addOutDirToChunks(Object.values(bundle), config.outDir));
1217
1290
  }
1218
1291
  }
1219
1292
  };
@@ -1222,17 +1295,18 @@ function WatchPlugin(configFiles, { config, chunks }) {
1222
1295
  //#endregion
1223
1296
  //#region src/features/rolldown.ts
1224
1297
  const debug = createDebug("tsdown:rolldown");
1225
- async function getBuildOptions(config, format, configFiles, watchContext, cjsDts = false, isMultiFormat) {
1226
- const inputOptions = await resolveInputOptions(config, format, configFiles, watchContext, cjsDts, isMultiFormat);
1298
+ async function getBuildOptions(config, format, configFiles, bundle, cjsDts = false, isDualFormat) {
1299
+ const inputOptions = await resolveInputOptions(config, format, configFiles, bundle, cjsDts, isDualFormat);
1227
1300
  const outputOptions = await resolveOutputOptions(inputOptions, config, format, cjsDts);
1228
1301
  const rolldownConfig = {
1229
1302
  ...inputOptions,
1230
- output: outputOptions
1303
+ output: outputOptions,
1304
+ write: config.write
1231
1305
  };
1232
1306
  debug("rolldown config with format \"%s\" %O", cjsDts ? "cjs dts" : format, rolldownConfig);
1233
1307
  return rolldownConfig;
1234
1308
  }
1235
- async function resolveInputOptions(config, format, configFiles, watchContext, cjsDts, isMultiFormat) {
1309
+ async function resolveInputOptions(config, format, configFiles, bundle, cjsDts, isDualFormat) {
1236
1310
  const { alias, banner, cjsDefault, cwd, debug: debug$10, 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;
1237
1311
  const plugins = [];
1238
1312
  if (nodeProtocol) plugins.push(NodeProtocolPlugin(nodeProtocol));
@@ -1261,11 +1335,11 @@ async function resolveInputOptions(config, format, configFiles, watchContext, cj
1261
1335
  }));
1262
1336
  }
1263
1337
  if (target) plugins.push(await LightningCSSPlugin({ target }));
1264
- plugins.push(ShebangPlugin(logger, cwd, name, isMultiFormat));
1338
+ plugins.push(ShebangPlugin(logger, cwd, name, isDualFormat));
1265
1339
  if (globImport) plugins.push(importGlobPlugin());
1266
1340
  }
1267
- if (report && LogLevels[logger.level] >= 3) plugins.push(ReportPlugin(report, logger, cwd, cjsDts, name, isMultiFormat));
1268
- if (watch$1) plugins.push(WatchPlugin(configFiles, watchContext));
1341
+ if (report && LogLevels[logger.level] >= 3) plugins.push(ReportPlugin(report, logger, cwd, cjsDts, name, isDualFormat));
1342
+ if (watch$1) plugins.push(WatchPlugin(configFiles, bundle));
1269
1343
  if (!cjsDts) plugins.push(userPlugins);
1270
1344
  const define = {
1271
1345
  ...config.define,
@@ -1422,18 +1496,22 @@ async function build$1(userOptions = {}) {
1422
1496
  if (restarting) return;
1423
1497
  restarting = true;
1424
1498
  await Promise.all(disposeCbs.map((cb) => cb()));
1425
- clearCJSCache();
1499
+ clearRequireCache();
1426
1500
  build$1(userOptions);
1427
1501
  }
1502
+ const configChunksByPkg = initBundleByPkg(configs);
1503
+ function done(bundle) {
1504
+ return bundleDone(configChunksByPkg, bundle);
1505
+ }
1428
1506
  globalLogger.info("Build start");
1429
- const bundles = await Promise.all(configs.map((options) => buildSingle(options, configFiles, clean, restart)));
1507
+ const bundles = await Promise.all(configs.map((options) => {
1508
+ return buildSingle(options, configFiles, options.pkg ? configChunksByPkg[options.pkg.packageJsonPath].formats.size > 1 : true, clean, restart, done);
1509
+ }));
1430
1510
  const firstDevtoolsConfig = configs.find((config) => config.debug && config.debug.devtools);
1431
1511
  if (configs.some((config) => config.watch)) {
1432
1512
  disposeCbs.push(shortcuts(restart));
1433
1513
  for (const bundle of bundles) disposeCbs.push(bundle[asyncDispose]);
1434
- return;
1435
- }
1436
- if (firstDevtoolsConfig) {
1514
+ } else if (firstDevtoolsConfig) {
1437
1515
  const { start } = await importWithError("@vitejs/devtools/cli-commands");
1438
1516
  const devtoolsOptions = firstDevtoolsConfig.debug.devtools;
1439
1517
  await start({
@@ -1452,42 +1530,39 @@ async function build$1(userOptions = {}) {
1452
1530
  * @private
1453
1531
  * @param config Resolved options
1454
1532
  */
1455
- async function buildSingle(config, configFiles, clean, restart) {
1456
- const { format: formats, dts, watch: watch$1, logger } = config;
1533
+ async function buildSingle(config, configFiles, isDualFormat, clean, restart, done) {
1534
+ const { format, dts, watch: watch$1, logger, outDir } = config;
1457
1535
  const { hooks, context } = await createHooks$1(config);
1458
1536
  warnLegacyCJS(config);
1459
1537
  const startTime = performance.now();
1460
1538
  await hooks.callHook("build:prepare", context);
1461
1539
  await clean();
1462
1540
  const debugRolldownConfigDir = await getDebugRolldownDir();
1463
- const chunks = {};
1541
+ const chunks = [];
1464
1542
  let watcher;
1465
- const watchCtx = { config };
1466
1543
  let ab;
1467
- const isMultiFormat = formats.length > 1;
1468
- const configsByFormat = (await Promise.all(formats.map((format) => buildOptionsByFormat(format)))).flat();
1544
+ let updated = false;
1545
+ const bundle = {
1546
+ chunks,
1547
+ config,
1548
+ async [asyncDispose]() {
1549
+ ab?.abort();
1550
+ await watcher?.close();
1551
+ }
1552
+ };
1553
+ const configs = await initBuildOptions();
1469
1554
  if (watch$1) {
1470
- watcher = watch(configsByFormat.map((item) => item[1]));
1555
+ watcher = watch(configs);
1471
1556
  handleWatcher(watcher);
1472
1557
  } else {
1473
- const outputs = await build(configsByFormat.map((item) => item[1]));
1474
- for (const [i, output] of outputs.entries()) {
1475
- const format = configsByFormat[i][0];
1476
- chunks[format] ||= [];
1477
- chunks[format].push(...output.output);
1478
- }
1558
+ const outputs = await build(configs);
1559
+ for (const { output } of outputs) chunks.push(...addOutDirToChunks(output, outDir));
1479
1560
  }
1480
1561
  if (!watch$1) {
1481
1562
  logger.success(prettyName(config.name), `Build complete in ${green(`${Math.round(performance.now() - startTime)}ms`)}`);
1482
1563
  await postBuild();
1483
1564
  }
1484
- return {
1485
- chunks,
1486
- async [asyncDispose]() {
1487
- ab?.abort();
1488
- await watcher?.close();
1489
- }
1490
- };
1565
+ return bundle;
1491
1566
  function handleWatcher(watcher$1) {
1492
1567
  const changedFile = [];
1493
1568
  let hasError = false;
@@ -1501,10 +1576,8 @@ async function buildSingle(config, configFiles, clean, restart) {
1501
1576
  watcher$1.on("event", async (event) => {
1502
1577
  switch (event.code) {
1503
1578
  case "START":
1504
- for (const format of formats) {
1505
- await cleanupChunks(config.outDir, chunks[format]);
1506
- chunks[format].length = 0;
1507
- }
1579
+ await cleanupChunks(config.outDir, chunks);
1580
+ chunks.length = 0;
1508
1581
  hasError = false;
1509
1582
  break;
1510
1583
  case "END":
@@ -1529,25 +1602,25 @@ async function buildSingle(config, configFiles, clean, restart) {
1529
1602
  }
1530
1603
  });
1531
1604
  }
1532
- async function buildOptionsByFormat(format) {
1533
- const watchContext = {
1534
- ...watchCtx,
1535
- chunks: chunks[format] = []
1536
- };
1537
- const buildOptions = await getBuildOptions(config, format, configFiles, watchContext, false, isMultiFormat);
1605
+ async function initBuildOptions() {
1606
+ const buildOptions = await getBuildOptions(config, format, configFiles, bundle, false, isDualFormat);
1538
1607
  await hooks.callHook("build:before", {
1539
1608
  ...context,
1540
1609
  buildOptions
1541
1610
  });
1542
1611
  if (debugRolldownConfigDir) await debugBuildOptions(debugRolldownConfigDir, config.name, format, buildOptions);
1543
- const configs = [[format, buildOptions]];
1544
- if (format === "cjs" && dts) configs.push([format, await getBuildOptions(config, format, configFiles, watchContext, true, isMultiFormat)]);
1545
- return configs;
1612
+ const configs$1 = [buildOptions];
1613
+ if (format === "cjs" && dts) configs$1.push(await getBuildOptions(config, format, configFiles, bundle, true, isDualFormat));
1614
+ return configs$1;
1546
1615
  }
1547
1616
  async function postBuild() {
1548
- await Promise.all([writeExports(config, chunks), copy(config)]);
1549
- await Promise.all([publint(config), attw(config)]);
1550
- await hooks.callHook("build:done", context);
1617
+ if (updated) await copy(config);
1618
+ else await done(bundle);
1619
+ await hooks.callHook("build:done", {
1620
+ ...context,
1621
+ chunks
1622
+ });
1623
+ updated = true;
1551
1624
  ab?.abort();
1552
1625
  ab = executeOnSuccess(config);
1553
1626
  }
package/package.json CHANGED
@@ -1,27 +1,19 @@
1
1
  {
2
2
  "name": "tsdown",
3
- "version": "0.17.0-beta.4",
4
- "description": "The Elegant Bundler for Libraries",
5
3
  "type": "module",
4
+ "version": "0.17.0-beta.6",
5
+ "description": "The Elegant Bundler for Libraries",
6
+ "author": "Kevin Deng <sxzz@sxzz.moe>",
6
7
  "license": "MIT",
8
+ "funding": "https://github.com/sponsors/sxzz",
7
9
  "homepage": "http://tsdown.dev/",
8
- "bugs": {
9
- "url": "https://github.com/rolldown/tsdown/issues"
10
- },
11
10
  "repository": {
12
11
  "type": "git",
13
12
  "url": "git+https://github.com/rolldown/tsdown.git"
14
13
  },
15
- "author": "Kevin Deng <sxzz@sxzz.moe>",
16
- "funding": "https://github.com/sponsors/sxzz",
17
- "files": [
18
- "client.d.ts",
19
- "dist",
20
- "esm-shims.js"
21
- ],
22
- "main": "./dist/index.mjs",
23
- "module": "./dist/index.mjs",
24
- "types": "./dist/index.d.mts",
14
+ "bugs": {
15
+ "url": "https://github.com/rolldown/tsdown/issues"
16
+ },
25
17
  "exports": {
26
18
  ".": "./dist/index.mjs",
27
19
  "./config": "./dist/config.mjs",
@@ -30,6 +22,9 @@
30
22
  "./package.json": "./package.json",
31
23
  "./client": "./client.d.ts"
32
24
  },
25
+ "main": "./dist/index.mjs",
26
+ "module": "./dist/index.mjs",
27
+ "types": "./dist/index.d.mts",
33
28
  "typesVersions": {
34
29
  "*": {
35
30
  "*": [
@@ -41,9 +36,17 @@
41
36
  "bin": {
42
37
  "tsdown": "./dist/run.mjs"
43
38
  },
39
+ "files": [
40
+ "client.d.ts",
41
+ "dist",
42
+ "esm-shims.js"
43
+ ],
44
44
  "publishConfig": {
45
45
  "access": "public"
46
46
  },
47
+ "engines": {
48
+ "node": ">=20.19.0"
49
+ },
47
50
  "peerDependencies": {
48
51
  "@arethetypeswrong/core": "^0.18.1",
49
52
  "@vitejs/devtools": "^0.0.0-alpha.18",
@@ -77,54 +80,53 @@
77
80
  "cac": "^6.7.14",
78
81
  "empathic": "^2.0.0",
79
82
  "hookable": "^5.5.3",
80
- "import-without-cache": "^0.1.3",
83
+ "import-without-cache": "^0.2.2",
81
84
  "obug": "^2.1.1",
82
- "rolldown": "1.0.0-beta.52",
85
+ "rolldown": "1.0.0-beta.53",
83
86
  "rolldown-plugin-dts": "^0.18.1",
84
87
  "semver": "^7.7.3",
85
88
  "tinyexec": "^1.0.2",
86
89
  "tinyglobby": "^0.2.15",
87
90
  "tree-kill": "^1.2.2",
88
91
  "unconfig-core": "^7.4.1",
89
- "unrun": "^0.2.14"
92
+ "unrun": "^0.2.16"
90
93
  },
91
94
  "devDependencies": {
92
95
  "@arethetypeswrong/core": "^0.18.2",
93
- "@sxzz/eslint-config": "^7.4.0",
96
+ "@sxzz/eslint-config": "^7.4.1",
94
97
  "@sxzz/prettier-config": "^2.2.6",
95
98
  "@sxzz/test-utils": "^0.5.13",
96
99
  "@types/node": "^24.10.1",
97
100
  "@types/semver": "^7.7.1",
98
- "@unocss/eslint-plugin": "^66.5.9",
101
+ "@typescript/native-preview": "7.0.0-dev.20251203.1",
102
+ "@unocss/eslint-plugin": "^66.5.10",
99
103
  "@vitejs/devtools": "^0.0.0-alpha.18",
100
- "@vitest/coverage-v8": "4.0.14",
104
+ "@vitest/coverage-v8": "4.0.15",
101
105
  "@vueuse/core": "^14.1.0",
102
106
  "bumpp": "^10.3.2",
107
+ "dedent": "^1.7.0",
103
108
  "eslint": "^9.39.1",
104
109
  "is-in-ci": "^2.0.0",
105
110
  "lightningcss": "^1.30.2",
106
111
  "pkg-types": "^2.3.0",
107
- "prettier": "^3.7.1",
112
+ "prettier": "^3.7.4",
108
113
  "publint": "^0.3.15",
109
114
  "rolldown-plugin-require-cjs": "^0.3.2",
110
115
  "typescript": "~5.9.3",
111
- "unocss": "^66.5.9",
116
+ "unocss": "^66.5.10",
112
117
  "unplugin-lightningcss": "^0.4.3",
113
118
  "unplugin-unused": "^0.5.6",
114
- "vite": "npm:rolldown-vite@^7.2.8",
115
- "vitest": "^4.0.14"
116
- },
117
- "engines": {
118
- "node": ">=20.19.0"
119
+ "vite": "npm:rolldown-vite@^7.2.10",
120
+ "vitest": "^4.0.15"
119
121
  },
120
122
  "prettier": "@sxzz/prettier-config",
121
123
  "scripts": {
122
124
  "lint": "eslint --cache --max-warnings 0 .",
123
125
  "lint:fix": "pnpm run lint --fix",
124
126
  "build": "unrun ./src/run.ts",
125
- "dev": "unrun ./src/run.ts",
127
+ "dev": "node ./src/run.ts",
126
128
  "test": "vitest",
127
- "typecheck": "tsc --noEmit",
129
+ "typecheck": "tsgo --noEmit",
128
130
  "format": "prettier --cache --write .",
129
131
  "release": "bumpp -r",
130
132
  "docs:dev": "pnpm -C docs run dev",