tsdown 0.17.0-beta.3 → 0.17.0-beta.5

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,27 +1,28 @@
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-C_EvEUSK.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-CxZ5olT1.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 { clearRequireCache, init, isSupported } from "import-without-cache";
8
9
  import { VERSION, build, watch } from "rolldown";
10
+ import { createDebug } from "obug";
9
11
  import { access, chmod, cp, mkdtemp, readFile, rm, stat, writeFile } from "node:fs/promises";
10
12
  import process, { env } from "node:process";
11
- import { createDebug } from "obug";
12
13
  import { createConfigCoreLoader } from "unconfig-core";
13
14
  import { glob, isDynamicPattern } from "tinyglobby";
14
15
  import { RE_CSS, RE_DTS, RE_JS, RE_NODE_MODULES } from "rolldown-plugin-dts/filename";
15
16
  const minVersion = __cjs_require("semver/ranges/min-version.js");
16
17
  import { up } from "empathic/find";
17
18
  import { up as up$1 } from "empathic/package";
18
- import { tmpdir } from "node:os";
19
- import { exec } from "tinyexec";
20
19
  const coerce = __cjs_require("semver/functions/coerce.js");
21
20
  const satisfies = __cjs_require("semver/functions/satisfies.js");
22
21
  import { createHooks } from "hookable";
22
+ import { exec } from "tinyexec";
23
23
  const treeKill = __cjs_require("tree-kill");
24
- import util, { promisify } from "node:util";
24
+ import util, { formatWithOptions, promisify } from "node:util";
25
+ import { tmpdir } from "node:os";
25
26
  import { importGlobPlugin } from "rolldown/experimental";
26
27
  import { Buffer } from "node:buffer";
27
28
  import { brotliCompress, gzip } from "node:zlib";
@@ -72,29 +73,27 @@ function lowestCommonAncestor(...filepaths) {
72
73
  }
73
74
 
74
75
  //#endregion
75
- //#region src/config/config.ts
76
- const debug$8 = createDebug("tsdown:config");
76
+ //#region src/config/file.ts
77
+ const debug$9 = createDebug("tsdown:config:file");
77
78
  async function loadViteConfig(prefix, cwd, configLoader) {
78
79
  const loader = resolveConfigLoader(configLoader);
79
- debug$8("Loading Vite config via loader: ", loader);
80
+ debug$9("Loading Vite config via loader: ", loader);
80
81
  const parser = createParser(loader);
81
82
  const [result] = await createConfigCoreLoader({
82
83
  sources: [{
83
84
  files: [`${prefix}.config`],
84
85
  extensions: [
85
- "ts",
86
- "mts",
87
- "cts",
88
86
  "js",
89
87
  "mjs",
88
+ "ts",
90
89
  "cjs",
91
- "json",
92
- ""
90
+ "mts",
91
+ "mts"
93
92
  ],
94
93
  parser
95
94
  }],
96
95
  cwd
97
- }).load();
96
+ }).load(true);
98
97
  if (!result) return;
99
98
  const { config, source } = result;
100
99
  globalLogger.info(`Using Vite config: ${underline(source)}`);
@@ -106,10 +105,6 @@ async function loadViteConfig(prefix, cwd, configLoader) {
106
105
  return resolved;
107
106
  }
108
107
  const configPrefix = "tsdown.config";
109
- let noCacheLoad = false;
110
- function setNoCacheLoad() {
111
- noCacheLoad = true;
112
- }
113
108
  async function loadConfigFile(inlineConfig, workspace) {
114
109
  let cwd = inlineConfig.cwd || process.cwd();
115
110
  let overrideConfig = false;
@@ -127,7 +122,7 @@ async function loadConfigFile(inlineConfig, workspace) {
127
122
  }
128
123
  }
129
124
  const loader = resolveConfigLoader(inlineConfig.configLoader);
130
- debug$8("Using config loader:", loader);
125
+ debug$9("Using config loader:", loader);
131
126
  const parser = createParser(loader);
132
127
  const [result] = await createConfigCoreLoader({
133
128
  sources: overrideConfig ? [{
@@ -143,8 +138,7 @@ async function loadConfigFile(inlineConfig, workspace) {
143
138
  "js",
144
139
  "mjs",
145
140
  "cjs",
146
- "json",
147
- ""
141
+ "json"
148
142
  ],
149
143
  parser
150
144
  }, {
@@ -153,12 +147,12 @@ async function loadConfigFile(inlineConfig, workspace) {
153
147
  }],
154
148
  cwd,
155
149
  stopAt: workspace && path.dirname(workspace)
156
- }).load(noCacheLoad);
150
+ }).load(true);
157
151
  let exported = [];
158
152
  let file;
159
153
  if (result) {
160
154
  ({config: exported, source: file} = result);
161
- globalLogger.info(`Using tsdown config: ${underline(file)}`);
155
+ globalLogger.info(`config file: ${underline(file)}`, loader === "native" ? "" : `(${loader})`);
162
156
  exported = await exported;
163
157
  if (typeof exported === "function") exported = await exported(inlineConfig, { ci: is_in_ci_default });
164
158
  }
@@ -166,13 +160,18 @@ async function loadConfigFile(inlineConfig, workspace) {
166
160
  if (exported.length === 0) exported.push({});
167
161
  if (exported.some((config) => typeof config === "function")) throw new Error("Function should not be nested within multiple tsdown configurations. It must be at the top level.\nExample: export default defineConfig(() => [...])");
168
162
  return {
169
- configs: exported,
163
+ configs: exported.map((config) => ({
164
+ cwd,
165
+ ...config
166
+ })),
170
167
  file
171
168
  };
172
169
  }
170
+ const isBun = !!process.versions.bun;
171
+ const nativeTS = process.features.typescript || process.versions.deno;
172
+ const autoLoader = isBun || nativeTS && isSupported ? "native" : "unrun";
173
173
  function resolveConfigLoader(configLoader = "auto") {
174
- if (noCacheLoad) return "unrun";
175
- else if (configLoader === "auto") return !!(process.features.typescript || process.versions.bun || process.versions.deno) ? "native" : "unrun";
174
+ if (configLoader === "auto") return autoLoader;
176
175
  else return configLoader === "native" ? "native" : "unrun";
177
176
  }
178
177
  function createParser(loader) {
@@ -190,7 +189,13 @@ function createParser(loader) {
190
189
  };
191
190
  }
192
191
  async function nativeImport(id) {
193
- const mod = await import(pathToFileURL(id).href).catch((error) => {
192
+ const url = pathToFileURL(id);
193
+ const importAttributes = Object.create(null);
194
+ if (isSupported) {
195
+ importAttributes.cache = "no";
196
+ init();
197
+ } else if (!isBun) url.searchParams.set("no-cache", crypto.randomUUID());
198
+ const mod = await import(url.href, { with: importAttributes }).catch((error) => {
194
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 });
195
200
  else throw error;
196
201
  });
@@ -204,7 +209,7 @@ async function unrunImport(id) {
204
209
 
205
210
  //#endregion
206
211
  //#region src/features/clean.ts
207
- const debug$7 = createDebug("tsdown:clean");
212
+ const debug$8 = createDebug("tsdown:clean");
208
213
  const RE_LAST_SLASH = /[/\\]$/;
209
214
  async function cleanOutDir(configs) {
210
215
  const removes = /* @__PURE__ */ new Set();
@@ -222,10 +227,10 @@ async function cleanOutDir(configs) {
222
227
  if (!removes.size) return;
223
228
  globalLogger.info(`Cleaning ${removes.size} files`);
224
229
  await Promise.all([...removes].map(async (file) => {
225
- debug$7("Removing", file);
230
+ debug$8("Removing", file);
226
231
  await fsRemove(file);
227
232
  }));
228
- debug$7("Removed %d files", removes.size);
233
+ debug$8("Removed %d files", removes.size);
229
234
  }
230
235
  function resolveClean(clean, outDir, cwd) {
231
236
  if (clean === true) clean = [slash(outDir)];
@@ -236,7 +241,7 @@ function resolveClean(clean, outDir, cwd) {
236
241
  async function cleanupChunks(outDir, chunks) {
237
242
  await Promise.all(chunks.map(async (chunk) => {
238
243
  const filePath = path.resolve(outDir, chunk.fileName);
239
- debug$7("Removing chunk file", filePath);
244
+ debug$8("Removing chunk file", filePath);
240
245
  await fsRemove(filePath);
241
246
  }));
242
247
  }
@@ -292,12 +297,11 @@ function detectIndentation(jsonText) {
292
297
  }
293
298
 
294
299
  //#endregion
295
- //#region src/features/exports.ts
300
+ //#region src/features/pkg/exports.ts
296
301
  async function writeExports(options, chunks) {
297
- if (!options.exports) return;
298
- const { outDir, pkg } = options;
299
- if (!pkg) throw new Error("`package.json` not found, cannot write exports");
300
- 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);
301
305
  const updatedPkg = {
302
306
  ...pkg,
303
307
  ...generated,
@@ -312,10 +316,8 @@ async function writeExports(options, chunks) {
312
316
  if (original.endsWith("\n")) contents += "\n";
313
317
  if (contents !== original) await writeFile(pkg.packageJsonPath, contents, "utf8");
314
318
  }
315
- async function generateExports(pkg, outDir, chunks, { devExports, all, customExports }) {
316
- const pkgJsonPath = pkg.packageJsonPath;
317
- const pkgRoot$1 = path.dirname(pkgJsonPath);
318
- 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);
319
321
  let main, module$1, cjsTypes, esmTypes;
320
322
  const exportsMap = /* @__PURE__ */ new Map();
321
323
  for (const [format, chunksByFormat] of Object.entries(chunks)) {
@@ -329,6 +331,7 @@ async function generateExports(pkg, outDir, chunks, { devExports, all, customExp
329
331
  const isDts = name.endsWith(".d");
330
332
  if (isDts) name = name.slice(0, -2);
331
333
  const isIndex = onlyOneEntry || name === "index";
334
+ const outDirRelative = slash(path.relative(pkgRoot$1, chunk.outDir));
332
335
  const distFile = `${outDirRelative ? `./${outDirRelative}` : "."}/${normalizedName}`;
333
336
  if (isIndex) {
334
337
  name = ".";
@@ -357,7 +360,6 @@ async function generateExports(pkg, outDir, chunks, { devExports, all, customExp
357
360
  exportMeta(exports, all);
358
361
  if (customExports) exports = await customExports(exports, {
359
362
  pkg,
360
- outDir,
361
363
  chunks,
362
364
  isPublish: false
363
365
  });
@@ -367,7 +369,6 @@ async function generateExports(pkg, outDir, chunks, { devExports, all, customExp
367
369
  exportMeta(publishExports, all);
368
370
  if (customExports) publishExports = await customExports(publishExports, {
369
371
  pkg,
370
- outDir,
371
372
  chunks,
372
373
  isPublish: true
373
374
  });
@@ -388,8 +389,8 @@ function genSubExport(devExports, { src, es, cjs }) {
388
389
  else {
389
390
  value = {};
390
391
  if (typeof devExports === "string") value[devExports] = src;
391
- if (es) value[dualFormat ? "import" : "default"] = es;
392
392
  if (cjs) value[dualFormat ? "require" : "default"] = cjs;
393
+ if (es) value[dualFormat ? "import" : "default"] = es;
393
394
  }
394
395
  return value;
395
396
  }
@@ -463,11 +464,11 @@ async function resolveTsconfig(logger, tsconfig, cwd, name) {
463
464
 
464
465
  //#endregion
465
466
  //#region src/utils/package.ts
466
- const debug$6 = createDebug("tsdown:package");
467
+ const debug$7 = createDebug("tsdown:package");
467
468
  async function readPackageJson(dir) {
468
469
  const packageJsonPath = up$1({ cwd: dir });
469
470
  if (!packageJsonPath) return;
470
- debug$6("Reading package.json:", packageJsonPath);
471
+ debug$7("Reading package.json:", packageJsonPath);
471
472
  const contents = await readFile(packageJsonPath, "utf8");
472
473
  return {
473
474
  ...JSON.parse(contents),
@@ -481,105 +482,27 @@ function getPackageType(pkg) {
481
482
  }
482
483
  }
483
484
  function normalizeFormat(format) {
484
- return resolveComma(toArray(format, "es")).map((format$1) => {
485
- switch (format$1) {
486
- case "es":
487
- case "esm":
488
- case "module": return "es";
489
- case "cjs":
490
- case "commonjs": return "cjs";
491
- default: return format$1;
492
- }
493
- });
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
+ }
494
493
  }
495
494
 
496
495
  //#endregion
497
- //#region src/config/index.ts
498
- const debug$5 = createDebug("tsdown:options");
499
- const DEFAULT_EXCLUDE_WORKSPACE = [
500
- "**/node_modules/**",
501
- "**/dist/**",
502
- "**/test?(s)/**",
503
- "**/t?(e)mp/**"
504
- ];
505
- async function resolveConfig(inlineConfig) {
506
- debug$5("inline config %O", inlineConfig);
507
- const { configs: rootConfigs, file } = await loadConfigFile(inlineConfig);
508
- const files = [];
509
- if (file) {
510
- files.push(file);
511
- debug$5("loaded root user config file %s", file);
512
- debug$5("root user configs %O", rootConfigs);
513
- } else debug$5("no root user config file found");
514
- const configs = (await Promise.all(rootConfigs.map(async (rootConfig) => {
515
- const { configs: workspaceConfigs, files: workspaceFiles } = await resolveWorkspace(rootConfig, inlineConfig);
516
- if (workspaceFiles) files.push(...workspaceFiles);
517
- return Promise.all(workspaceConfigs.filter((config) => !config.workspace || config.entry).map((config) => resolveUserConfig(config, inlineConfig)));
518
- }))).flat();
519
- debug$5("resolved configs %O", configs);
520
- return {
521
- configs,
522
- files
523
- };
524
- }
525
- async function resolveWorkspace(config, inlineConfig) {
526
- const normalized = {
527
- ...config,
528
- ...inlineConfig
529
- };
530
- const rootCwd = normalized.cwd || process.cwd();
531
- let { workspace } = normalized;
532
- if (!workspace) return {
533
- configs: [normalized],
534
- files: []
535
- };
536
- if (workspace === true) workspace = {};
537
- else if (typeof workspace === "string" || Array.isArray(workspace)) workspace = { include: workspace };
538
- let { include: packages = "auto", exclude = DEFAULT_EXCLUDE_WORKSPACE, config: workspaceConfig } = workspace;
539
- if (packages === "auto") packages = (await glob("**/package.json", {
540
- ignore: exclude,
541
- cwd: rootCwd,
542
- expandDirectories: false
543
- })).filter((file) => file !== "package.json").map((file) => slash(path.resolve(rootCwd, file, "..")));
544
- else packages = (await glob(packages, {
545
- ignore: exclude,
546
- cwd: rootCwd,
547
- onlyDirectories: true,
548
- absolute: true,
549
- expandDirectories: false
550
- })).map((file) => slash(path.resolve(file)));
551
- if (packages.length === 0) throw new Error("No workspace packages found, please check your config");
552
- if (inlineConfig.filter) {
553
- inlineConfig.filter = resolveRegex(inlineConfig.filter);
554
- packages = packages.filter((path$1) => {
555
- return typeof inlineConfig.filter === "string" ? path$1.includes(inlineConfig.filter) : Array.isArray(inlineConfig.filter) ? inlineConfig.filter.some((filter) => path$1.includes(filter)) : inlineConfig.filter.test(path$1);
556
- });
557
- if (packages.length === 0) throw new Error("No packages matched the filters");
558
- }
559
- const files = [];
560
- return {
561
- configs: (await Promise.all(packages.map(async (cwd) => {
562
- debug$5("loading workspace config %s", cwd);
563
- const { configs, file } = await loadConfigFile({
564
- ...inlineConfig,
565
- config: workspaceConfig,
566
- cwd
567
- }, cwd);
568
- if (file) {
569
- debug$5("loaded workspace config file %s", file);
570
- files.push(file);
571
- } else debug$5("no workspace config file found in %s", cwd);
572
- return configs.map((config$1) => ({
573
- ...normalized,
574
- cwd,
575
- ...config$1
576
- }));
577
- }))).flat(),
578
- files
579
- };
580
- }
496
+ //#region src/config/options.ts
497
+ const debugLog = createDebug("tsdown:config:options");
581
498
  async function resolveUserConfig(userConfig, inlineConfig) {
582
- 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;
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;
500
+ const pkg = await readPackageJson(cwd);
501
+ if (workspace) name ||= pkg?.name;
502
+ if (!filterConfig(inlineConfig.filter, cwd, name)) {
503
+ debugLog("[filter] skipping config %s", cwd);
504
+ return [];
505
+ }
583
506
  const logger = createLogger(logLevel, {
584
507
  customLogger,
585
508
  failOnWarn: resolveFeatureOption(failOnWarn, true)
@@ -589,8 +512,6 @@ async function resolveUserConfig(userConfig, inlineConfig) {
589
512
  nodeProtocol = nodeProtocol ?? (removeNodeProtocol ? "strip" : false);
590
513
  outDir = path.resolve(cwd, outDir);
591
514
  clean = resolveClean(clean, outDir, cwd);
592
- const pkg = await readPackageJson(cwd);
593
- if (workspace) name ||= pkg?.name;
594
515
  entry = await resolveEntry(logger, entry, cwd, name);
595
516
  if (dts == null) dts = !!(pkg?.types || pkg?.typings || hasExportsTypes(pkg));
596
517
  target = resolveTarget(logger, target, pkg, name);
@@ -603,6 +524,11 @@ async function resolveUserConfig(userConfig, inlineConfig) {
603
524
  unused = resolveFeatureOption(unused, {});
604
525
  report = resolveFeatureOption(report, {});
605
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
+ }
606
532
  if (publicDir) if (copy$1) throw new TypeError("`publicDir` is deprecated. Cannot be used with `copy`");
607
533
  else logger.warn(`${blue`publicDir`} is deprecated. Use ${blue`copy`} instead.`);
608
534
  if (fromVite) {
@@ -627,12 +553,12 @@ async function resolveUserConfig(userConfig, inlineConfig) {
627
553
  noExternal = (id) => matchPattern(id, noExternalPatterns);
628
554
  }
629
555
  if (inlineOnly != null) inlineOnly = toArray(inlineOnly);
630
- debug$9 = resolveFeatureOption(debug$9, {});
631
- if (debug$9) if (watch$1) {
632
- if (debug$9.devtools) logger.warn("Devtools is not supported in watch mode, disabling it.");
633
- debug$9.devtools = false;
634
- } else debug$9.devtools ??= !!pkgExists("@vitejs/devtools/cli");
635
- return {
556
+ debug$10 = resolveFeatureOption(debug$10, {});
557
+ if (debug$10) if (watch$1) {
558
+ if (debug$10.devtools) logger.warn("Devtools is not supported in watch mode, disabling it.");
559
+ debug$10.devtools = false;
560
+ } else debug$10.devtools ??= !!pkgExists("@vitejs/devtools/cli");
561
+ const config = {
636
562
  ...userConfig,
637
563
  alias,
638
564
  attw: attw$1,
@@ -640,14 +566,13 @@ async function resolveUserConfig(userConfig, inlineConfig) {
640
566
  clean,
641
567
  copy: publicDir || copy$1,
642
568
  cwd,
643
- debug: debug$9,
569
+ debug: debug$10,
644
570
  dts,
645
571
  entry,
646
572
  env: env$1,
647
573
  exports,
648
574
  external,
649
575
  fixedExtension,
650
- format: normalizeFormat(format),
651
576
  globImport,
652
577
  hash,
653
578
  ignoreWatch,
@@ -670,8 +595,22 @@ async function resolveUserConfig(userConfig, inlineConfig) {
670
595
  tsconfig,
671
596
  unbundle,
672
597
  unused,
673
- watch: watch$1
598
+ watch: watch$1,
599
+ write
674
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
+ });
675
614
  }
676
615
  async function mergeUserOptions(defaults, user, args) {
677
616
  const userOutputOptions = typeof user === "function" ? await user(defaults, ...args) : user;
@@ -689,9 +628,162 @@ function resolveCIOption(value) {
689
628
  if (value === "local-only") return is_in_ci_default ? false : true;
690
629
  return value;
691
630
  }
631
+ function filterConfig(filter, configCwd, name) {
632
+ if (!filter) return true;
633
+ let cwd = path.relative(process.cwd(), configCwd);
634
+ if (cwd === "") cwd = ".";
635
+ if (filter instanceof RegExp) return name && filter.test(name) || filter.test(cwd);
636
+ return toArray(filter).some((value) => name && name === value || cwd === value);
637
+ }
638
+
639
+ //#endregion
640
+ //#region src/config/workspace.ts
641
+ const debug$6 = createDebug("tsdown:config:workspace");
642
+ const DEFAULT_EXCLUDE_WORKSPACE = [
643
+ "**/node_modules/**",
644
+ "**/dist/**",
645
+ "**/test?(s)/**",
646
+ "**/t?(e)mp/**"
647
+ ];
648
+ async function resolveWorkspace(config, inlineConfig) {
649
+ const normalized = {
650
+ ...config,
651
+ ...inlineConfig
652
+ };
653
+ const rootCwd = normalized.cwd || process.cwd();
654
+ let { workspace } = normalized;
655
+ if (!workspace) return {
656
+ configs: [normalized],
657
+ files: []
658
+ };
659
+ if (workspace === true) workspace = {};
660
+ else if (typeof workspace === "string" || Array.isArray(workspace)) workspace = { include: workspace };
661
+ let { include: packages = "auto", exclude = DEFAULT_EXCLUDE_WORKSPACE, config: workspaceConfig } = workspace;
662
+ if (packages === "auto") packages = (await glob("**/package.json", {
663
+ ignore: exclude,
664
+ cwd: rootCwd,
665
+ expandDirectories: false
666
+ })).filter((file) => file !== "package.json").map((file) => slash(path.resolve(rootCwd, file, "..")));
667
+ else packages = (await glob(packages, {
668
+ ignore: exclude,
669
+ cwd: rootCwd,
670
+ onlyDirectories: true,
671
+ absolute: true,
672
+ expandDirectories: false
673
+ })).map((file) => slash(path.resolve(file)));
674
+ if (packages.length === 0) throw new Error("No workspace packages found, please check your config");
675
+ const files = [];
676
+ return {
677
+ configs: (await Promise.all(packages.map(async (cwd) => {
678
+ debug$6("loading workspace config %s", cwd);
679
+ const { configs, file } = await loadConfigFile({
680
+ ...inlineConfig,
681
+ config: workspaceConfig,
682
+ cwd
683
+ }, cwd);
684
+ if (file) {
685
+ debug$6("loaded workspace config file %s", file);
686
+ files.push(file);
687
+ } else debug$6("no workspace config file found in %s", cwd);
688
+ return configs.map((config$1) => ({
689
+ ...normalized,
690
+ ...config$1
691
+ }));
692
+ }))).flat(),
693
+ files
694
+ };
695
+ }
692
696
 
693
697
  //#endregion
694
- //#region src/features/attw.ts
698
+ //#region src/config/index.ts
699
+ const debug$5 = createDebug("tsdown:config");
700
+ async function resolveConfig(inlineConfig) {
701
+ debug$5("inline config %O", inlineConfig);
702
+ const { configs: rootConfigs, file } = await loadConfigFile(inlineConfig);
703
+ const files = [];
704
+ if (file) {
705
+ files.push(file);
706
+ debug$5("loaded root user config file %s", file);
707
+ debug$5("root user configs %O", rootConfigs);
708
+ } else debug$5("no root user config file found");
709
+ const configs = (await Promise.all(rootConfigs.map(async (rootConfig) => {
710
+ const { configs: workspaceConfigs, files: workspaceFiles } = await resolveWorkspace(rootConfig, inlineConfig);
711
+ debug$5("workspace configs %O", workspaceConfigs);
712
+ if (workspaceFiles) files.push(...workspaceFiles);
713
+ return (await Promise.all(workspaceConfigs.filter((config) => !config.workspace || config.entry).map((config) => resolveUserConfig(config, inlineConfig)))).flat().filter((config) => !!config);
714
+ }))).flat();
715
+ debug$5("resolved configs %O", configs);
716
+ if (configs.length === 0) throw new Error("No valid configuration found.");
717
+ return {
718
+ configs,
719
+ files
720
+ };
721
+ }
722
+
723
+ //#endregion
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
695
787
  const debug$4 = createDebug("tsdown:attw");
696
788
  const label$1 = dim`[attw]`;
697
789
  /**
@@ -780,69 +872,7 @@ function formatProblem(problem) {
780
872
  }
781
873
 
782
874
  //#endregion
783
- //#region src/features/cjs.ts
784
- /**
785
- * If the config includes the `cjs` format and
786
- * one of its target >= node 23.0.0 / 22.12.0,
787
- * warn the user about the deprecation of CommonJS.
788
- */
789
- function warnLegacyCJS(config) {
790
- if (!config.format.includes("cjs") || !config.target) return;
791
- if (config.target.some((t) => {
792
- const version$1 = coerce(t.split("node")[1]);
793
- return version$1 && satisfies(version$1, ">=23.0.0 || >=22.12.0");
794
- })) 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");
795
- }
796
-
797
- //#endregion
798
- //#region src/features/copy.ts
799
- async function copy(options) {
800
- if (!options.copy) return;
801
- const copy$1 = typeof options.copy === "function" ? await options.copy(options) : options.copy;
802
- await Promise.all(toArray(copy$1).map((dir) => {
803
- const from = typeof dir === "string" ? dir : dir.from;
804
- const to = typeof dir === "string" ? path.resolve(options.outDir, path.basename(from)) : dir.to;
805
- return cp$1(options.cwd, from, to);
806
- }));
807
- }
808
- function cp$1(cwd, from, to) {
809
- return fsCopy(path.resolve(cwd, from), path.resolve(cwd, to));
810
- }
811
-
812
- //#endregion
813
- //#region src/features/hooks.ts
814
- async function createHooks$1(options) {
815
- const hooks = createHooks();
816
- if (typeof options.hooks === "object") hooks.addHooks(options.hooks);
817
- else if (typeof options.hooks === "function") await options.hooks(hooks);
818
- return {
819
- hooks,
820
- context: {
821
- options,
822
- hooks
823
- }
824
- };
825
- }
826
- function executeOnSuccess(config) {
827
- if (!config.onSuccess) return;
828
- const ab = new AbortController();
829
- if (typeof config.onSuccess === "string") {
830
- const p = exec(config.onSuccess, [], { nodeOptions: {
831
- shell: true,
832
- stdio: "inherit"
833
- } });
834
- p.then(({ exitCode }) => {
835
- if (exitCode) process.exitCode = exitCode;
836
- });
837
- ab.signal.addEventListener("abort", () => {
838
- if (typeof p.pid === "number") treeKill(p.pid);
839
- });
840
- } else config.onSuccess(config, ab.signal);
841
- return ab;
842
- }
843
-
844
- //#endregion
845
- //#region src/features/publint.ts
875
+ //#region src/features/pkg/publint.ts
846
876
  const debug$3 = createDebug("tsdown:publint");
847
877
  const label = dim`[publint]`;
848
878
  async function publint(options) {
@@ -881,6 +911,66 @@ async function publint(options) {
881
911
  }
882
912
  }
883
913
 
914
+ //#endregion
915
+ //#region src/features/pkg/index.ts
916
+ function initBundleByPkg(configs) {
917
+ const map = {};
918
+ for (const config of configs) {
919
+ const pkgJson = config.pkg?.packageJsonPath;
920
+ if (!pkgJson) continue;
921
+ if (!map[pkgJson]) {
922
+ const { promise, resolve } = promiseWithResolvers();
923
+ map[pkgJson] = {
924
+ promise,
925
+ resolve,
926
+ count: 0,
927
+ formats: /* @__PURE__ */ new Set(),
928
+ bundles: []
929
+ };
930
+ }
931
+ map[pkgJson].count++;
932
+ map[pkgJson].formats.add(config.format);
933
+ }
934
+ return map;
935
+ }
936
+ async function bundleDone(bundleByPkg, bundle) {
937
+ const pkg = bundle.config.pkg;
938
+ if (!pkg) return;
939
+ const ctx = bundleByPkg[pkg.packageJsonPath];
940
+ ctx.bundles.push(bundle);
941
+ if (ctx.bundles.length < ctx.count) return ctx.promise;
942
+ const configs = ctx.bundles.map(({ config }) => config);
943
+ const exportsConfigs = dedupeConfigs(configs, "exports");
944
+ if (exportsConfigs.length) {
945
+ 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")}`);
946
+ const chunks = {};
947
+ for (const bundle$1 of ctx.bundles) {
948
+ if (!bundle$1.config.exports) continue;
949
+ chunks[bundle$1.config.format] ||= [];
950
+ chunks[bundle$1.config.format].push(...bundle$1.chunks);
951
+ }
952
+ await writeExports(exportsConfigs[0], chunks);
953
+ }
954
+ const publintConfigs = dedupeConfigs(configs, "publint");
955
+ const attwConfigs = dedupeConfigs(configs, "attw");
956
+ 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.`);
957
+ await Promise.all([...publintConfigs.map((config) => publint(config)), ...attwConfigs.map((config) => attw(config))]);
958
+ ctx.resolve();
959
+ }
960
+ function dedupeConfigs(configs, key) {
961
+ const filtered = configs.filter((config) => config[key]);
962
+ if (!filtered.length) return [];
963
+ const seen = /* @__PURE__ */ new Set();
964
+ const results = filtered.filter((config) => {
965
+ if (!Object.keys(config[key]).length) return false;
966
+ if (seen.has(config[key])) return false;
967
+ seen.add(config[key]);
968
+ return true;
969
+ });
970
+ if (results.length === 0) return [filtered[0]];
971
+ return results;
972
+ }
973
+
884
974
  //#endregion
885
975
  //#region src/features/external.ts
886
976
  const debug$2 = createDebug("tsdown:external");
@@ -1079,7 +1169,7 @@ const defaultOptions = {
1079
1169
  brotli: false,
1080
1170
  maxCompressSize: 1e6
1081
1171
  };
1082
- function ReportPlugin(userOptions, logger, cwd, cjsDts, name, isMultiFormat) {
1172
+ function ReportPlugin(userOptions, logger, cwd, cjsDts, name, isDualFormat) {
1083
1173
  const options = {
1084
1174
  ...defaultOptions,
1085
1175
  ...userOptions
@@ -1110,7 +1200,7 @@ function ReportPlugin(userOptions, logger, cwd, cjsDts, name, isMultiFormat) {
1110
1200
  return b.raw - a.raw;
1111
1201
  });
1112
1202
  const nameLabel = prettyName(name);
1113
- const formatLabel = isMultiFormat && prettyFormat(cjsDts ? "cjs" : outputOptions.format);
1203
+ const formatLabel = isDualFormat && prettyFormat(cjsDts ? "cjs" : outputOptions.format);
1114
1204
  for (const size of sizes) {
1115
1205
  const filenameColor = size.dts ? green : noop;
1116
1206
  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}`);
@@ -1154,7 +1244,7 @@ async function calcSize(options, chunk) {
1154
1244
  //#endregion
1155
1245
  //#region src/features/shebang.ts
1156
1246
  const RE_SHEBANG = /^#!.*/;
1157
- function ShebangPlugin(logger, cwd, name, isMultiFormat) {
1247
+ function ShebangPlugin(logger, cwd, name, isDualFormat) {
1158
1248
  return {
1159
1249
  name: "tsdown:shebang",
1160
1250
  async writeBundle(options, bundle) {
@@ -1163,7 +1253,7 @@ function ShebangPlugin(logger, cwd, name, isMultiFormat) {
1163
1253
  if (!RE_SHEBANG.test(chunk.code)) continue;
1164
1254
  const filepath = path.resolve(cwd, options.file || path.join(options.dir, chunk.fileName));
1165
1255
  if (await fsExists(filepath)) {
1166
- logger.info(prettyName(name), isMultiFormat && prettyFormat(options.format), `Granting execute permission to ${underline(path.relative(cwd, filepath))}`);
1256
+ logger.info(prettyName(name), isDualFormat && prettyFormat(options.format), `Granting execute permission to ${underline(path.relative(cwd, filepath))}`);
1167
1257
  await chmod(filepath, 493);
1168
1258
  }
1169
1259
  }
@@ -1180,9 +1270,18 @@ function getShimsInject(format, platform) {
1180
1270
  };
1181
1271
  }
1182
1272
 
1273
+ //#endregion
1274
+ //#region src/utils/chunks.ts
1275
+ function addOutDirToChunks(chunks, outDir) {
1276
+ return chunks.map((chunk) => {
1277
+ chunk.outDir = outDir;
1278
+ return chunk;
1279
+ });
1280
+ }
1281
+
1183
1282
  //#endregion
1184
1283
  //#region src/features/watch.ts
1185
- const endsWithConfig = /[\\/](?:tsdown\.config.*|tsconfig\.json)$/;
1284
+ const endsWithConfig = /[\\/](?:tsdown\.config.*|package\.json|tsconfig\.json)$/;
1186
1285
  function WatchPlugin(configFiles, { config, chunks }) {
1187
1286
  return {
1188
1287
  name: "tsdown:watch",
@@ -1195,11 +1294,12 @@ function WatchPlugin(configFiles, { config, chunks }) {
1195
1294
  config.tsconfig && this.addWatchFile(config.tsconfig);
1196
1295
  for (const file of configFiles) this.addWatchFile(file);
1197
1296
  if (typeof config.watch !== "boolean") for (const file of resolveComma(toArray(config.watch))) this.addWatchFile(file);
1297
+ if (config.pkg) this.addWatchFile(config.pkg.packageJsonPath);
1198
1298
  },
1199
1299
  generateBundle: {
1200
1300
  order: "post",
1201
1301
  handler(outputOptions, bundle) {
1202
- chunks.push(...Object.values(bundle));
1302
+ chunks.push(...addOutDirToChunks(Object.values(bundle), config.outDir));
1203
1303
  }
1204
1304
  }
1205
1305
  };
@@ -1208,18 +1308,19 @@ function WatchPlugin(configFiles, { config, chunks }) {
1208
1308
  //#endregion
1209
1309
  //#region src/features/rolldown.ts
1210
1310
  const debug = createDebug("tsdown:rolldown");
1211
- async function getBuildOptions(config, format, configFiles, watchContext, cjsDts = false, isMultiFormat) {
1212
- const inputOptions = await resolveInputOptions(config, format, configFiles, watchContext, cjsDts, isMultiFormat);
1311
+ async function getBuildOptions(config, format, configFiles, bundle, cjsDts = false, isDualFormat) {
1312
+ const inputOptions = await resolveInputOptions(config, format, configFiles, bundle, cjsDts, isDualFormat);
1213
1313
  const outputOptions = await resolveOutputOptions(inputOptions, config, format, cjsDts);
1214
1314
  const rolldownConfig = {
1215
1315
  ...inputOptions,
1216
- output: outputOptions
1316
+ output: outputOptions,
1317
+ write: config.write
1217
1318
  };
1218
1319
  debug("rolldown config with format \"%s\" %O", cjsDts ? "cjs dts" : format, rolldownConfig);
1219
1320
  return rolldownConfig;
1220
1321
  }
1221
- async function resolveInputOptions(config, format, configFiles, watchContext, cjsDts, isMultiFormat) {
1222
- 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;
1322
+ async function resolveInputOptions(config, format, configFiles, bundle, cjsDts, isDualFormat) {
1323
+ 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;
1223
1324
  const plugins = [];
1224
1325
  if (nodeProtocol) plugins.push(NodeProtocolPlugin(nodeProtocol));
1225
1326
  if (config.pkg || config.skipNodeModulesBundle) plugins.push(ExternalPlugin(config));
@@ -1247,11 +1348,11 @@ async function resolveInputOptions(config, format, configFiles, watchContext, cj
1247
1348
  }));
1248
1349
  }
1249
1350
  if (target) plugins.push(await LightningCSSPlugin({ target }));
1250
- plugins.push(ShebangPlugin(logger, cwd, name, isMultiFormat));
1351
+ plugins.push(ShebangPlugin(logger, cwd, name, isDualFormat));
1251
1352
  if (globImport) plugins.push(importGlobPlugin());
1252
1353
  }
1253
- if (report && LogLevels[logger.level] >= 3) plugins.push(ReportPlugin(report, logger, cwd, cjsDts, name, isMultiFormat));
1254
- if (watch$1) plugins.push(WatchPlugin(configFiles, watchContext));
1354
+ if (report && LogLevels[logger.level] >= 3) plugins.push(ReportPlugin(report, logger, cwd, cjsDts, name, isDualFormat));
1355
+ if (watch$1) plugins.push(WatchPlugin(configFiles, bundle));
1255
1356
  if (!cjsDts) plugins.push(userPlugins);
1256
1357
  const define = {
1257
1358
  ...config.define,
@@ -1283,7 +1384,7 @@ async function resolveInputOptions(config, format, configFiles, watchContext, cj
1283
1384
  if (log.code === "MIXED_EXPORT") return;
1284
1385
  defaultHandler(level, log);
1285
1386
  } : void 0,
1286
- debug: debug$9 || void 0
1387
+ debug: debug$10 || void 0
1287
1388
  }, config.inputOptions, [format, { cjsDts }]);
1288
1389
  }
1289
1390
  async function resolveOutputOptions(inputOptions, config, format, cjsDts) {
@@ -1309,7 +1410,7 @@ async function getDebugRolldownDir() {
1309
1410
  return await mkdtemp(join(tmpdir(), "tsdown-config-"));
1310
1411
  }
1311
1412
  async function debugBuildOptions(dir, name, format, buildOptions) {
1312
- const outFile = join(dir, `tsdown.config.${format}.js`);
1413
+ const outFile = join(dir, `rolldown.config.${format}.js`);
1313
1414
  handlePluginInspect(buildOptions.plugins);
1314
1415
  const serialized = util.formatWithOptions({
1315
1416
  depth: null,
@@ -1408,18 +1509,22 @@ async function build$1(userOptions = {}) {
1408
1509
  if (restarting) return;
1409
1510
  restarting = true;
1410
1511
  await Promise.all(disposeCbs.map((cb) => cb()));
1411
- setNoCacheLoad();
1512
+ clearRequireCache();
1412
1513
  build$1(userOptions);
1413
1514
  }
1515
+ const configChunksByPkg = initBundleByPkg(configs);
1516
+ function done(bundle) {
1517
+ return bundleDone(configChunksByPkg, bundle);
1518
+ }
1414
1519
  globalLogger.info("Build start");
1415
- const bundles = await Promise.all(configs.map((options) => buildSingle(options, configFiles, clean, restart)));
1520
+ const bundles = await Promise.all(configs.map((options) => {
1521
+ return buildSingle(options, configFiles, options.pkg ? configChunksByPkg[options.pkg.packageJsonPath].formats.size > 1 : true, clean, restart, done);
1522
+ }));
1416
1523
  const firstDevtoolsConfig = configs.find((config) => config.debug && config.debug.devtools);
1417
1524
  if (configs.some((config) => config.watch)) {
1418
1525
  disposeCbs.push(shortcuts(restart));
1419
1526
  for (const bundle of bundles) disposeCbs.push(bundle[asyncDispose]);
1420
- return;
1421
- }
1422
- if (firstDevtoolsConfig) {
1527
+ } else if (firstDevtoolsConfig) {
1423
1528
  const { start } = await importWithError("@vitejs/devtools/cli-commands");
1424
1529
  const devtoolsOptions = firstDevtoolsConfig.debug.devtools;
1425
1530
  await start({
@@ -1438,42 +1543,39 @@ async function build$1(userOptions = {}) {
1438
1543
  * @private
1439
1544
  * @param config Resolved options
1440
1545
  */
1441
- async function buildSingle(config, configFiles, clean, restart) {
1442
- const { format: formats, dts, watch: watch$1, logger } = config;
1546
+ async function buildSingle(config, configFiles, isDualFormat, clean, restart, done) {
1547
+ const { format, dts, watch: watch$1, logger, outDir } = config;
1443
1548
  const { hooks, context } = await createHooks$1(config);
1444
1549
  warnLegacyCJS(config);
1445
1550
  const startTime = performance.now();
1446
1551
  await hooks.callHook("build:prepare", context);
1447
1552
  await clean();
1448
1553
  const debugRolldownConfigDir = await getDebugRolldownDir();
1449
- const chunks = {};
1554
+ const chunks = [];
1450
1555
  let watcher;
1451
- const watchCtx = { config };
1452
1556
  let ab;
1453
- const isMultiFormat = formats.length > 1;
1454
- const configsByFormat = (await Promise.all(formats.map((format) => buildOptionsByFormat(format)))).flat();
1557
+ let updated = false;
1558
+ const bundle = {
1559
+ chunks,
1560
+ config,
1561
+ async [asyncDispose]() {
1562
+ ab?.abort();
1563
+ await watcher?.close();
1564
+ }
1565
+ };
1566
+ const configs = await initBuildOptions();
1455
1567
  if (watch$1) {
1456
- watcher = watch(configsByFormat.map((item) => item[1]));
1568
+ watcher = watch(configs);
1457
1569
  handleWatcher(watcher);
1458
1570
  } else {
1459
- const outputs = await build(configsByFormat.map((item) => item[1]));
1460
- for (const [i, output] of outputs.entries()) {
1461
- const format = configsByFormat[i][0];
1462
- chunks[format] ||= [];
1463
- chunks[format].push(...output.output);
1464
- }
1571
+ const outputs = await build(configs);
1572
+ for (const { output } of outputs) chunks.push(...addOutDirToChunks(output, outDir));
1465
1573
  }
1466
1574
  if (!watch$1) {
1467
1575
  logger.success(prettyName(config.name), `Build complete in ${green(`${Math.round(performance.now() - startTime)}ms`)}`);
1468
1576
  await postBuild();
1469
1577
  }
1470
- return {
1471
- chunks,
1472
- async [asyncDispose]() {
1473
- ab?.abort();
1474
- await watcher?.close();
1475
- }
1476
- };
1578
+ return bundle;
1477
1579
  function handleWatcher(watcher$1) {
1478
1580
  const changedFile = [];
1479
1581
  let hasError = false;
@@ -1487,10 +1589,8 @@ async function buildSingle(config, configFiles, clean, restart) {
1487
1589
  watcher$1.on("event", async (event) => {
1488
1590
  switch (event.code) {
1489
1591
  case "START":
1490
- for (const format of formats) {
1491
- await cleanupChunks(config.outDir, chunks[format]);
1492
- chunks[format].length = 0;
1493
- }
1592
+ await cleanupChunks(config.outDir, chunks);
1593
+ chunks.length = 0;
1494
1594
  hasError = false;
1495
1595
  break;
1496
1596
  case "END":
@@ -1515,25 +1615,25 @@ async function buildSingle(config, configFiles, clean, restart) {
1515
1615
  }
1516
1616
  });
1517
1617
  }
1518
- async function buildOptionsByFormat(format) {
1519
- const watchContext = {
1520
- ...watchCtx,
1521
- chunks: chunks[format] = []
1522
- };
1523
- const buildOptions = await getBuildOptions(config, format, configFiles, watchContext, false, isMultiFormat);
1618
+ async function initBuildOptions() {
1619
+ const buildOptions = await getBuildOptions(config, format, configFiles, bundle, false, isDualFormat);
1524
1620
  await hooks.callHook("build:before", {
1525
1621
  ...context,
1526
1622
  buildOptions
1527
1623
  });
1528
1624
  if (debugRolldownConfigDir) await debugBuildOptions(debugRolldownConfigDir, config.name, format, buildOptions);
1529
- const configs = [[format, buildOptions]];
1530
- if (format === "cjs" && dts) configs.push([format, await getBuildOptions(config, format, configFiles, watchContext, true, isMultiFormat)]);
1531
- return configs;
1625
+ const configs$1 = [buildOptions];
1626
+ if (format === "cjs" && dts) configs$1.push(await getBuildOptions(config, format, configFiles, bundle, true, isDualFormat));
1627
+ return configs$1;
1532
1628
  }
1533
1629
  async function postBuild() {
1534
- await Promise.all([writeExports(config, chunks), copy(config)]);
1535
- await Promise.all([publint(config), attw(config)]);
1536
- await hooks.callHook("build:done", context);
1630
+ if (updated) await copy(config);
1631
+ else await done(bundle);
1632
+ await hooks.callHook("build:done", {
1633
+ ...context,
1634
+ chunks
1635
+ });
1636
+ updated = true;
1537
1637
  ab?.abort();
1538
1638
  ab = executeOnSuccess(config);
1539
1639
  }
@@ -1544,4 +1644,4 @@ const pkgRoot = path.resolve(dirname$1, "..");
1544
1644
  const shimFile = path.resolve(pkgRoot, "esm-shims.js");
1545
1645
 
1546
1646
  //#endregion
1547
- export { ReportPlugin as a, ShebangPlugin as i, buildSingle as n, NodeProtocolPlugin as o, shimFile as r, ExternalPlugin as s, build$1 as t };
1647
+ export { ShebangPlugin as a, ExternalPlugin as c, WatchPlugin as i, buildSingle as n, ReportPlugin as o, shimFile as r, NodeProtocolPlugin as s, build$1 as t };