tsdown 0.17.2 → 0.17.4

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-BQZ2CZuJ.mjs";
1
+ import { f as UserConfig, m as UserConfigFn, p as UserConfigExport } from "./index-JmTA8ZMA.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-BQZ2CZuJ.mjs";
2
- import { t as defineConfig } from "./config-DPU-roRC.mjs";
1
+ import { f as UserConfig, m as UserConfigFn, p as UserConfigExport } from "./index-JmTA8ZMA.mjs";
2
+ import { t as defineConfig } from "./config-FoWTJggg.mjs";
3
3
  export { UserConfig, UserConfigExport, UserConfigFn, defineConfig };
@@ -16,8 +16,30 @@ type Arrayable<T> = T | T[];
16
16
  //#endregion
17
17
  //#region src/features/copy.d.ts
18
18
  interface CopyEntry {
19
- from: string;
20
- to: string;
19
+ /**
20
+ * Source path or glob pattern.
21
+ */
22
+ from: string | string[];
23
+ /**
24
+ * Destination path.
25
+ * If not specified, defaults to the output directory ("outDir").
26
+ */
27
+ to?: string;
28
+ /**
29
+ * Whether to flatten the copied files (not preserving directory structure).
30
+ *
31
+ * @default true
32
+ */
33
+ flatten?: boolean;
34
+ /**
35
+ * Output copied items to console.
36
+ * @default false
37
+ */
38
+ verbose?: boolean;
39
+ /**
40
+ * Change destination file or folder name.
41
+ */
42
+ rename?: string | ((name: string, extension: string, fullPath: string) => string);
21
43
  }
22
44
  type CopyOptions = Arrayable<string | CopyEntry>;
23
45
  type CopyOptionsFn = (options: ResolvedConfig) => Awaitable<CopyOptions>;
@@ -147,6 +169,17 @@ interface ExportsOptions {
147
169
  * Exports for all files.
148
170
  */
149
171
  all?: boolean;
172
+ /**
173
+ * Define filenames or RegExp patterns to exclude files from exports.
174
+ * This is useful for excluding files that should not be part of the package exports,
175
+ * such as bin files or internal utilities.
176
+ *
177
+ * @example
178
+ * ```js
179
+ * exclude: ['foo.ts', /\.spec\.ts$/, /internal/]
180
+ * ```
181
+ */
182
+ exclude?: (RegExp | string)[];
150
183
  customExports?: (exports: Record<string, any>, context: {
151
184
  pkg: PackageJson;
152
185
  chunks: ChunksByFormat;
@@ -189,7 +222,7 @@ interface ReportOptions {
189
222
  */
190
223
  maxCompressSize?: number;
191
224
  }
192
- declare function ReportPlugin(userOptions: ReportOptions, logger: Logger, cwd: string, cjsDts?: boolean, name?: string, isDualFormat?: boolean): Plugin;
225
+ declare function ReportPlugin(userOptions: ReportOptions, logger: Logger, cwd: string, cjsDts?: boolean, nameLabel?: string, isDualFormat?: boolean): Plugin;
193
226
  //#endregion
194
227
  //#region src/config/types.d.ts
195
228
  type Sourcemap = boolean | "inline" | "hidden";
@@ -535,7 +568,10 @@ interface UserConfig {
535
568
  * ```ts
536
569
  * [
537
570
  * 'src/assets',
571
+ * 'src/env.d.ts',
572
+ * 'src/styles/**\/*.css',
538
573
  * { from: 'src/assets', to: 'dist/assets' },
574
+ * { from: 'src/styles/**\/*.css', to: 'dist', flatten: true },
539
575
  * ]
540
576
  * ```
541
577
  */
@@ -567,6 +603,7 @@ type UserConfigFn = (inlineConfig: InlineConfig, context: {
567
603
  }) => Awaitable<Arrayable<UserConfig>>;
568
604
  type UserConfigExport = Awaitable<Arrayable<UserConfig> | UserConfigFn>;
569
605
  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">, {
606
+ nameLabel: string | undefined;
570
607
  format: NormalizedFormat;
571
608
  target?: string[];
572
609
  clean: string[];
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
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";
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-JmTA8ZMA.mjs";
2
+ import { t as defineConfig } from "./config-FoWTJggg.mjs";
3
3
  import * as Rolldown from "rolldown";
4
4
 
5
5
  //#region src/index.d.ts
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as defineConfig } from "./config-DLSWqKoz.mjs";
2
- import { i as shimFile, n as build, r as buildSingle, t as Rolldown } from "./src-CrG1HehQ.mjs";
3
- import { a as globalLogger } from "./package-Dh6dU6y0.mjs";
2
+ import { i as shimFile, n as build, r as buildSingle, t as Rolldown } from "./src-z7OtDtS0.mjs";
3
+ import { o as globalLogger } from "./package-Bh7CIGyj.mjs";
4
4
 
5
5
  export { Rolldown, build, buildSingle, defineConfig, globalLogger, shimFile };
@@ -100,9 +100,9 @@ function createLogger(level = "info", { customLogger, console = globalThis.conso
100
100
  return logger;
101
101
  }
102
102
  const globalLogger = createLogger();
103
- function prettyName(name) {
103
+ function getNameLabel(ansis, name) {
104
104
  if (!name) return void 0;
105
- return generateColor(name)(`[${name}]`);
105
+ return ansis(`[${name}]`);
106
106
  }
107
107
  function prettyFormat(format$1) {
108
108
  const formatColor = format$1 === "es" ? blue : format$1 === "cjs" ? yellow : noop;
@@ -161,7 +161,7 @@ function hue2rgb(p, q, t) {
161
161
 
162
162
  //#endregion
163
163
  //#region package.json
164
- var version = "0.17.2";
164
+ var version = "0.17.4";
165
165
 
166
166
  //#endregion
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 };
167
+ export { getNameLabel 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, globalLogger as o, resolveComma as p, createLogger as r, prettyFormat as s, version as t, noop as u };
@@ -1,4 +1,4 @@
1
- import { C as TsdownBundle, c as ResolvedConfig, v as ReportPlugin, y as Logger } from "./index-BQZ2CZuJ.mjs";
1
+ import { C as TsdownBundle, c as ResolvedConfig, v as ReportPlugin, y as Logger } from "./index-JmTA8ZMA.mjs";
2
2
  import { Plugin } from "rolldown";
3
3
 
4
4
  //#region src/features/external.d.ts
@@ -17,7 +17,7 @@ declare function ExternalPlugin({
17
17
  declare function NodeProtocolPlugin(nodeProtocolOption: "strip" | true): Plugin;
18
18
  //#endregion
19
19
  //#region src/features/shebang.d.ts
20
- declare function ShebangPlugin(logger: Logger, cwd: string, name?: string, isDualFormat?: boolean): Plugin;
20
+ declare function ShebangPlugin(logger: Logger, cwd: string, nameLabel?: string, isDualFormat?: boolean): Plugin;
21
21
  //#endregion
22
22
  //#region src/features/watch.d.ts
23
23
  declare function WatchPlugin(configFiles: string[], {
package/dist/plugins.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as WatchPlugin, c as NodeProtocolPlugin, l as ExternalPlugin, o as ShebangPlugin, s as ReportPlugin } from "./src-CrG1HehQ.mjs";
2
- import "./package-Dh6dU6y0.mjs";
1
+ import { a as WatchPlugin, c as NodeProtocolPlugin, l as ExternalPlugin, o as ShebangPlugin, s as ReportPlugin } from "./src-z7OtDtS0.mjs";
2
+ import "./package-Bh7CIGyj.mjs";
3
3
 
4
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, g as toArray, p as resolveComma, t as version } from "./package-Dh6dU6y0.mjs";
2
+ import { g as toArray, o as globalLogger, p as resolveComma, t as version } from "./package-Bh7CIGyj.mjs";
3
3
  import module from "node:module";
4
4
  import { dim } from "ansis";
5
5
  import { VERSION } from "rolldown";
@@ -60,7 +60,7 @@ async function runCLI() {
60
60
  try {
61
61
  await cli.runMatchedCommand();
62
62
  } catch (error) {
63
- globalLogger.error(error);
63
+ globalLogger.error(String(error.stack || error.message));
64
64
  process.exit(1);
65
65
  }
66
66
  }
@@ -1,6 +1,6 @@
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 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-Dh6dU6y0.mjs";
3
+ import { a as getNameLabel, 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 globalLogger, p as resolveComma, r as createLogger, s as prettyFormat, t as version, u as noop } from "./package-Bh7CIGyj.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";
@@ -12,6 +12,7 @@ import { createDebug } from "obug";
12
12
  import { access, chmod, cp, mkdtemp, readFile, rm, stat, writeFile } from "node:fs/promises";
13
13
  import process, { env } from "node:process";
14
14
  import { createConfigCoreLoader } from "unconfig-core";
15
+ import { createDefu } from "defu";
15
16
  import { glob, isDynamicPattern } from "tinyglobby";
16
17
  import { RE_CSS, RE_DTS, RE_JS, RE_NODE_MODULES } from "rolldown-plugin-dts/filename";
17
18
  const minVersion = __cjs_require("semver/ranges/min-version.js");
@@ -162,8 +163,8 @@ async function loadConfigFile(inlineConfig, workspace) {
162
163
  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(() => [...])");
163
164
  return {
164
165
  configs: exported.map((config) => ({
165
- cwd,
166
- ...config
166
+ ...config,
167
+ cwd: config.cwd ? path.resolve(cwd, config.cwd) : cwd
167
168
  })),
168
169
  file
169
170
  };
@@ -249,17 +250,16 @@ async function cleanChunks(outDir, chunks) {
249
250
 
250
251
  //#endregion
251
252
  //#region src/features/entry.ts
252
- async function resolveEntry(logger, entry, cwd, name) {
253
- const nameLabel = name ? `[${name}] ` : "";
253
+ async function resolveEntry(logger, entry, cwd, color, nameLabel) {
254
254
  if (!entry || Object.keys(entry).length === 0) {
255
255
  const defaultEntry = path.resolve(cwd, "src/index.ts");
256
256
  if (await fsExists(defaultEntry)) entry = { index: defaultEntry };
257
- else throw new Error(`${nameLabel}No input files, try "tsdown <your-file>" or create src/index.ts`);
257
+ else throw new Error(`${nameLabel} No input files, try "tsdown <your-file>" or create src/index.ts`);
258
258
  }
259
259
  const entryMap = await toObjectEntry(entry, cwd);
260
260
  const entries = Object.values(entryMap);
261
- if (entries.length === 0) throw new Error(`${nameLabel}Cannot find entry: ${JSON.stringify(entry)}`);
262
- logger.info(prettyName(name), `entry: ${generateColor(name)(entries.map((entry$1) => path.relative(cwd, entry$1)).join(", "))}`);
261
+ if (entries.length === 0) throw new Error(`${nameLabel} Cannot find entry: ${JSON.stringify(entry)}`);
262
+ logger.info(nameLabel, `entry: ${color(entries.map((entry$1) => path.relative(cwd, entry$1)).join(", "))}`);
263
263
  return entryMap;
264
264
  }
265
265
  async function toObjectEntry(entry, cwd) {
@@ -317,15 +317,19 @@ async function writeExports(options, chunks) {
317
317
  if (original.endsWith("\n")) contents += "\n";
318
318
  if (contents !== original) await writeFile(pkg.packageJsonPath, contents, "utf8");
319
319
  }
320
- async function generateExports(pkg, chunks, { devExports, all, customExports }) {
320
+ function shouldExclude(fileName, exclude) {
321
+ if (!exclude?.length) return false;
322
+ return matchPattern(fileName, exclude);
323
+ }
324
+ async function generateExports(pkg, chunks, { devExports, all, exclude, customExports }) {
321
325
  const pkgRoot$1 = path.dirname(pkg.packageJsonPath);
322
326
  let main, module$1, cjsTypes, esmTypes;
323
327
  const exportsMap = /* @__PURE__ */ new Map();
324
328
  for (const [format, chunksByFormat] of Object.entries(chunks)) {
325
329
  if (format !== "es" && format !== "cjs") continue;
326
- const onlyOneEntry = chunksByFormat.filter((chunk) => chunk.type === "chunk" && chunk.isEntry && !RE_DTS.test(chunk.fileName)).length === 1;
327
- for (const chunk of chunksByFormat) {
328
- if (chunk.type !== "chunk" || !chunk.isEntry) continue;
330
+ const filteredChunks = chunksByFormat.filter((chunk) => chunk.type === "chunk" && chunk.isEntry && !shouldExclude(chunk.fileName, exclude));
331
+ const onlyOneEntry = filteredChunks.filter((chunk) => !RE_DTS.test(chunk.fileName)).length === 1;
332
+ for (const chunk of filteredChunks) {
329
333
  const normalizedName = slash(chunk.fileName);
330
334
  const ext = path.extname(chunk.fileName);
331
335
  let name = normalizedName.slice(0, -ext.length);
@@ -414,7 +418,7 @@ function hasExportsTypes(pkg) {
414
418
 
415
419
  //#endregion
416
420
  //#region src/features/target.ts
417
- function resolveTarget(logger, target, pkg, name) {
421
+ function resolveTarget(logger, target, color, pkg, nameLabel) {
418
422
  if (target === false) return;
419
423
  if (target == null) {
420
424
  const pkgTarget = resolvePackageTarget(pkg);
@@ -423,7 +427,7 @@ function resolveTarget(logger, target, pkg, name) {
423
427
  }
424
428
  if (typeof target === "number") throw new TypeError(`Invalid target: ${target}`);
425
429
  const targets = resolveComma(toArray(target));
426
- if (targets.length) logger.info(prettyName(name), `target${targets.length > 1 ? "s" : ""}: ${generateColor(name)(targets.join(", "))}`);
430
+ if (targets.length) logger.info(nameLabel, `target${targets.length > 1 ? "s" : ""}: ${color(targets.join(", "))}`);
427
431
  return targets;
428
432
  }
429
433
  function resolvePackageTarget(pkg) {
@@ -440,7 +444,7 @@ function resolvePackageTarget(pkg) {
440
444
  function findTsconfig(cwd, name = "tsconfig.json") {
441
445
  return up(name, { cwd }) || false;
442
446
  }
443
- async function resolveTsconfig(logger, tsconfig, cwd, name) {
447
+ async function resolveTsconfig(logger, tsconfig, cwd, color, nameLabel) {
444
448
  const original = tsconfig;
445
449
  if (tsconfig !== false) {
446
450
  if (tsconfig === true || tsconfig == null) {
@@ -458,7 +462,7 @@ async function resolveTsconfig(logger, tsconfig, cwd, name) {
458
462
  if (!tsconfig) logger.warn(`tsconfig ${blue(original)} doesn't exist`);
459
463
  }
460
464
  }
461
- if (tsconfig) logger.info(prettyName(name), `tsconfig: ${generateColor(name)(path.relative(cwd, tsconfig))}`);
465
+ if (tsconfig) logger.info(nameLabel, `tsconfig: ${color(path.relative(cwd, tsconfig))}`);
462
466
  }
463
467
  return tsconfig;
464
468
  }
@@ -500,6 +504,8 @@ async function resolveUserConfig(userConfig, inlineConfig) {
500
504
  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;
501
505
  const pkg = await readPackageJson(cwd);
502
506
  if (workspace) name ||= pkg?.name;
507
+ const color = generateColor(name);
508
+ const nameLabel = getNameLabel(color, name);
503
509
  if (!filterConfig(inlineConfig.filter, cwd, name)) {
504
510
  debugLog("[filter] skipping config %s", cwd);
505
511
  return [];
@@ -513,10 +519,10 @@ async function resolveUserConfig(userConfig, inlineConfig) {
513
519
  nodeProtocol = nodeProtocol ?? (removeNodeProtocol ? "strip" : false);
514
520
  outDir = path.resolve(cwd, outDir);
515
521
  clean = resolveClean(clean, outDir, cwd);
516
- entry = await resolveEntry(logger, entry, cwd, name);
522
+ entry = await resolveEntry(logger, entry, cwd, color, nameLabel);
517
523
  if (dts == null) dts = !!(pkg?.types || pkg?.typings || hasExportsTypes(pkg));
518
- target = resolveTarget(logger, target, pkg, name);
519
- tsconfig = await resolveTsconfig(logger, tsconfig, cwd, name);
524
+ target = resolveTarget(logger, target, color, pkg, nameLabel);
525
+ tsconfig = await resolveTsconfig(logger, tsconfig, cwd, color, nameLabel);
520
526
  if (typeof external === "string") external = resolveRegex(external);
521
527
  if (typeof noExternal === "string") noExternal = resolveRegex(noExternal);
522
528
  publint$1 = resolveFeatureOption(publint$1, {});
@@ -527,8 +533,8 @@ async function resolveUserConfig(userConfig, inlineConfig) {
527
533
  dts = resolveFeatureOption(dts, {});
528
534
  if (!pkg) {
529
535
  if (exports) throw new Error("`package.json` not found, cannot write exports");
530
- if (publint$1) logger.warn(prettyName(name), "publint is enabled but package.json is not found");
531
- if (attw$1) logger.warn(prettyName(name), "attw is enabled but package.json is not found");
536
+ if (publint$1) logger.warn(nameLabel, "publint is enabled but package.json is not found");
537
+ if (attw$1) logger.warn(nameLabel, "attw is enabled but package.json is not found");
532
538
  }
533
539
  if (publicDir) if (copy$1) throw new TypeError("`publicDir` is deprecated. Cannot be used with `copy`");
534
540
  else logger.warn(`${blue`publicDir`} is deprecated. Use ${blue`copy`} instead.`);
@@ -580,6 +586,7 @@ async function resolveUserConfig(userConfig, inlineConfig) {
580
586
  inlineOnly,
581
587
  logger,
582
588
  name,
589
+ nameLabel,
583
590
  nodeProtocol,
584
591
  noExternal,
585
592
  outDir,
@@ -606,19 +613,22 @@ async function resolveUserConfig(userConfig, inlineConfig) {
606
613
  return {
607
614
  ...config,
608
615
  copy: once ? config.copy : void 0,
609
- hooks: once ? config.hooks : void 0,
610
616
  onSuccess: once ? config.onSuccess : void 0,
611
617
  format: normalizeFormat(fmt),
612
618
  ...overrides
613
619
  };
614
620
  });
615
621
  }
622
+ const defu = createDefu((obj, key, value) => {
623
+ if (Array.isArray(obj[key]) && Array.isArray(value)) {
624
+ obj[key] = value;
625
+ return true;
626
+ }
627
+ });
616
628
  async function mergeUserOptions(defaults, user, args) {
617
629
  const userOutputOptions = typeof user === "function" ? await user(defaults, ...args) : user;
618
- return {
619
- ...defaults,
620
- ...userOutputOptions
621
- };
630
+ if (!userOutputOptions) return defaults;
631
+ return defu(userOutputOptions, defaults);
622
632
  }
623
633
  function resolveFeatureOption(value, defaults) {
624
634
  if (typeof value === "object" && value !== null) return resolveCIOption(value.enabled ?? true) ? value : false;
@@ -700,6 +710,7 @@ async function resolveWorkspace(config, inlineConfig) {
700
710
  const debug$5 = createDebug("tsdown:config");
701
711
  async function resolveConfig(inlineConfig) {
702
712
  debug$5("inline config %O", inlineConfig);
713
+ if (inlineConfig.cwd) inlineConfig.cwd = path.resolve(inlineConfig.cwd);
703
714
  const { configs: rootConfigs, file } = await loadConfigFile(inlineConfig);
704
715
  const files = [];
705
716
  if (file) {
@@ -740,15 +751,45 @@ function warnLegacyCJS(config) {
740
751
  //#region src/features/copy.ts
741
752
  async function copy(options) {
742
753
  if (!options.copy) return;
743
- const resolved = toArray(typeof options.copy === "function" ? await options.copy(options) : options.copy).map((dir) => {
744
- const from = path.resolve(options.cwd, typeof dir === "string" ? dir : dir.from);
745
- return [from, typeof dir === "string" ? path.resolve(options.outDir, path.basename(from)) : path.resolve(options.cwd, dir.to)];
746
- });
747
- const name = prettyName(options.name);
748
- await Promise.all(resolved.map(([from, to]) => {
749
- options.logger.info(name, `Copying files from ${path.relative(options.cwd, from)} to ${path.relative(options.cwd, to)}`);
754
+ const copy$1 = typeof options.copy === "function" ? await options.copy(options) : options.copy;
755
+ const resolved = (await Promise.all(toArray(copy$1).map(async (entry) => {
756
+ if (typeof entry === "string") entry = { from: [entry] };
757
+ let from = toArray(entry.from);
758
+ if (from.some((f) => isDynamicPattern(f))) from = await glob(from, {
759
+ cwd: options.cwd,
760
+ onlyFiles: true,
761
+ expandDirectories: false
762
+ });
763
+ return from.map((file) => resolveCopyEntry({
764
+ ...entry,
765
+ from: file
766
+ }));
767
+ }))).flat();
768
+ if (!resolved.length) {
769
+ options.logger.warn(options.nameLabel, `No files matched for copying.`);
770
+ return;
771
+ }
772
+ await Promise.all(resolved.map(({ from, to, verbose }) => {
773
+ if (verbose) options.logger.info(options.nameLabel, `Copying files from ${path.relative(options.cwd, from)} to ${path.relative(options.cwd, to)}`);
750
774
  return fsCopy(from, to);
751
775
  }));
776
+ function resolveCopyEntry(entry) {
777
+ const { flatten = true, rename } = entry;
778
+ const from = path.resolve(options.cwd, entry.from);
779
+ const to = entry.to ? path.resolve(options.cwd, entry.to) : options.outDir;
780
+ const { base, dir } = path.parse(path.relative(options.cwd, from));
781
+ const destFolder = flatten || !flatten && !dir ? to : dir.replace(dir.split(path.sep)[0], to);
782
+ const dest = path.join(destFolder, rename ? renameTarget(base, rename, from) : base);
783
+ return {
784
+ ...entry,
785
+ from,
786
+ to: dest
787
+ };
788
+ }
789
+ }
790
+ function renameTarget(target, rename, src) {
791
+ const parsedPath = path.parse(target);
792
+ return typeof rename === "string" ? rename : rename(parsedPath.name, parsedPath.ext.replace(".", ""), src);
752
793
  }
753
794
 
754
795
  //#endregion
@@ -836,8 +877,8 @@ async function attw(options) {
836
877
  });
837
878
  if (problems.length) errorMessage = `problems found:\n${problems.map(formatProblem).join("\n")}`;
838
879
  } else errorMessage = `Package has no types`;
839
- if (errorMessage) options.logger[level](prettyName(options.name), label$1, errorMessage);
840
- else options.logger.success(prettyName(options.name), label$1, "No problems found", dim`(${Math.round(performance.now() - t)}ms)`);
880
+ if (errorMessage) options.logger[level](options.nameLabel, label$1, errorMessage);
881
+ else options.logger.success(options.nameLabel, label$1, "No problems found", dim`(${Math.round(performance.now() - t)}ms)`);
841
882
  }
842
883
  /**
843
884
  * Format an ATTW problem for display
@@ -872,7 +913,7 @@ const label = dim`[publint]`;
872
913
  async function publint(options) {
873
914
  if (!options.publint) return;
874
915
  if (!options.pkg) {
875
- options.logger.warn(prettyName(options.name), "publint is enabled but package.json is not found");
916
+ options.logger.warn(options.nameLabel, "publint is enabled but package.json is not found");
876
917
  return;
877
918
  }
878
919
  const t = performance.now();
@@ -885,7 +926,7 @@ async function publint(options) {
885
926
  });
886
927
  debug$3("Found %d issues", messages.length);
887
928
  if (!messages.length) {
888
- options.logger.success(prettyName(options.name), label, "No issues found", dim`(${Math.round(performance.now() - t)}ms)`);
929
+ options.logger.success(options.nameLabel, label, "No issues found", dim`(${Math.round(performance.now() - t)}ms)`);
889
930
  return;
890
931
  }
891
932
  for (const message of messages) {
@@ -895,7 +936,7 @@ async function publint(options) {
895
936
  warning: "warn",
896
937
  suggestion: "info"
897
938
  }[message.type];
898
- options.logger[logType](prettyName(options.name), label, formattedMessage);
939
+ options.logger[logType](options.nameLabel, label, formattedMessage);
899
940
  }
900
941
  }
901
942
 
@@ -1157,7 +1198,7 @@ const defaultOptions = {
1157
1198
  brotli: false,
1158
1199
  maxCompressSize: 1e6
1159
1200
  };
1160
- function ReportPlugin(userOptions, logger, cwd, cjsDts, name, isDualFormat) {
1201
+ function ReportPlugin(userOptions, logger, cwd, cjsDts, nameLabel, isDualFormat) {
1161
1202
  const options = {
1162
1203
  ...defaultOptions,
1163
1204
  ...userOptions
@@ -1187,7 +1228,6 @@ function ReportPlugin(userOptions, logger, cwd, cjsDts, name, isDualFormat) {
1187
1228
  if (a.isEntry !== b.isEntry) return a.isEntry ? -1 : 1;
1188
1229
  return b.raw - a.raw;
1189
1230
  });
1190
- const nameLabel = prettyName(name);
1191
1231
  const formatLabel = isDualFormat && prettyFormat(cjsDts ? "cjs" : outputOptions.format);
1192
1232
  for (const size of sizes) {
1193
1233
  const filenameColor = size.dts ? green : noop;
@@ -1232,7 +1272,7 @@ async function calcSize(options, chunk) {
1232
1272
  //#endregion
1233
1273
  //#region src/features/shebang.ts
1234
1274
  const RE_SHEBANG = /^#!.*/;
1235
- function ShebangPlugin(logger, cwd, name, isDualFormat) {
1275
+ function ShebangPlugin(logger, cwd, nameLabel, isDualFormat) {
1236
1276
  return {
1237
1277
  name: "tsdown:shebang",
1238
1278
  async writeBundle(options, bundle) {
@@ -1241,7 +1281,7 @@ function ShebangPlugin(logger, cwd, name, isDualFormat) {
1241
1281
  if (!RE_SHEBANG.test(chunk.code)) continue;
1242
1282
  const filepath = path.resolve(cwd, options.file || path.join(options.dir, chunk.fileName));
1243
1283
  if (await fsExists(filepath)) {
1244
- logger.info(prettyName(name), isDualFormat && prettyFormat(options.format), `Granting execute permission to ${underline(path.relative(cwd, filepath))}`);
1284
+ logger.info(nameLabel, isDualFormat && prettyFormat(options.format), `Granting execute permission to ${underline(path.relative(cwd, filepath))}`);
1245
1285
  await chmod(filepath, 493);
1246
1286
  }
1247
1287
  }
@@ -1308,7 +1348,7 @@ async function getBuildOptions(config, format, configFiles, bundle, cjsDts = fal
1308
1348
  return rolldownConfig;
1309
1349
  }
1310
1350
  async function resolveInputOptions(config, format, configFiles, bundle, cjsDts, isDualFormat) {
1311
- 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;
1351
+ const { alias, banner, cjsDefault, cwd, debug: debug$10, dts, entry, env: env$1, external, footer, globImport, loader, logger, nameLabel, nodeProtocol, platform, plugins: userPlugins, report, shims, target, treeshake, tsconfig, unused, watch: watch$1 } = config;
1312
1352
  const plugins = [];
1313
1353
  if (nodeProtocol) plugins.push(NodeProtocolPlugin(nodeProtocol));
1314
1354
  if (config.pkg || config.skipNodeModulesBundle) plugins.push(ExternalPlugin(config));
@@ -1336,10 +1376,10 @@ async function resolveInputOptions(config, format, configFiles, bundle, cjsDts,
1336
1376
  }));
1337
1377
  }
1338
1378
  if (target) plugins.push(await LightningCSSPlugin({ target }));
1339
- plugins.push(ShebangPlugin(logger, cwd, name, isDualFormat));
1379
+ plugins.push(ShebangPlugin(logger, cwd, nameLabel, isDualFormat));
1340
1380
  if (globImport) plugins.push(importGlobPlugin({ root: cwd }));
1341
1381
  }
1342
- if (report && LogLevels[logger.level] >= 3) plugins.push(ReportPlugin(report, logger, cwd, cjsDts, name, isDualFormat));
1382
+ if (report && LogLevels[logger.level] >= 3) plugins.push(ReportPlugin(report, logger, cwd, cjsDts, nameLabel, isDualFormat));
1343
1383
  if (watch$1) plugins.push(WatchPlugin(configFiles, bundle));
1344
1384
  if (!cjsDts) plugins.push(userPlugins);
1345
1385
  const define = {
@@ -1432,6 +1472,7 @@ function shortcuts(restart) {
1432
1472
  let actionRunning = false;
1433
1473
  async function onInput(input) {
1434
1474
  if (actionRunning) return;
1475
+ input = input.trim().toLowerCase();
1435
1476
  const SHORTCUTS = [
1436
1477
  {
1437
1478
  key: "r",
@@ -1560,7 +1601,7 @@ async function buildSingle(config, configFiles, isDualFormat, clean, restart, do
1560
1601
  for (const { output } of outputs) chunks.push(...addOutDirToChunks(output, outDir));
1561
1602
  }
1562
1603
  if (!watch$1) {
1563
- logger.success(prettyName(config.name), `Build complete in ${green(`${Math.round(performance.now() - startTime)}ms`)}`);
1604
+ logger.success(config.nameLabel, `Build complete in ${green(`${Math.round(performance.now() - startTime)}ms`)}`);
1564
1605
  await postBuild();
1565
1606
  }
1566
1607
  return bundle;
@@ -1593,7 +1634,7 @@ async function buildSingle(config, configFiles, isDualFormat, clean, restart, do
1593
1634
  break;
1594
1635
  case "BUNDLE_END":
1595
1636
  await event.result.close();
1596
- logger.success(`Rebuilt in ${event.duration}ms.`);
1637
+ logger.success(config.nameLabel, `Rebuilt in ${event.duration}ms.`);
1597
1638
  break;
1598
1639
  case "ERROR":
1599
1640
  await event.result.close();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tsdown",
3
3
  "type": "module",
4
- "version": "0.17.2",
4
+ "version": "0.17.4",
5
5
  "description": "The Elegant Bundler for Libraries",
6
6
  "author": "Kevin Deng <sxzz@sxzz.moe>",
7
7
  "license": "MIT",
@@ -78,9 +78,10 @@
78
78
  "dependencies": {
79
79
  "ansis": "^4.2.0",
80
80
  "cac": "^6.7.14",
81
+ "defu": "^6.1.4",
81
82
  "empathic": "^2.0.0",
82
83
  "hookable": "^5.5.3",
83
- "import-without-cache": "^0.2.2",
84
+ "import-without-cache": "^0.2.3",
84
85
  "obug": "^2.1.1",
85
86
  "rolldown": "1.0.0-beta.53",
86
87
  "rolldown-plugin-dts": "^0.18.3",
@@ -95,28 +96,30 @@
95
96
  "@arethetypeswrong/core": "^0.18.2",
96
97
  "@sxzz/eslint-config": "^7.4.1",
97
98
  "@sxzz/prettier-config": "^2.2.6",
98
- "@sxzz/test-utils": "^0.5.13",
99
- "@types/node": "^24.10.1",
99
+ "@sxzz/test-utils": "^0.5.14",
100
+ "@types/node": "^25.0.1",
100
101
  "@types/semver": "^7.7.1",
101
- "@typescript/native-preview": "7.0.0-dev.20251208.1",
102
+ "@typescript/native-preview": "7.0.0-dev.20251212.1",
102
103
  "@unocss/eslint-plugin": "^66.5.10",
103
104
  "@vitejs/devtools": "^0.0.0-alpha.19",
104
105
  "@vitest/coverage-v8": "4.0.15",
106
+ "@vitest/ui": "^4.0.15",
105
107
  "@vueuse/core": "^14.1.0",
106
108
  "bumpp": "^10.3.2",
107
109
  "dedent": "^1.7.0",
108
- "eslint": "^9.39.1",
110
+ "eslint": "^9.39.2",
109
111
  "is-in-ci": "^2.0.0",
110
112
  "lightningcss": "^1.30.2",
113
+ "memfs": "^4.51.1",
111
114
  "pkg-types": "^2.3.0",
112
115
  "prettier": "^3.7.4",
113
- "publint": "^0.3.15",
116
+ "publint": "^0.3.16",
114
117
  "rolldown-plugin-require-cjs": "^0.3.3",
115
118
  "typescript": "~5.9.3",
116
119
  "unocss": "^66.5.10",
117
120
  "unplugin-lightningcss": "^0.4.3",
118
121
  "unplugin-unused": "^0.5.6",
119
- "vite": "npm:rolldown-vite@^7.2.10",
122
+ "vite": "^8.0.0-beta.2",
120
123
  "vitest": "^4.0.15"
121
124
  },
122
125
  "prettier": "@sxzz/prettier-config",