tsdown 0.18.2 → 0.18.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.
@@ -0,0 +1,794 @@
1
+ import { createRequire as __cjs_createRequire } from "node:module";
2
+ const __cjs_require = __cjs_createRequire(import.meta.url);
3
+ import { a as globalLogger, c as matchPattern, f as resolveComma, h as toArray, i as getNameLabel, m as slash, n as createLogger, p as resolveRegex, r as generateColor, u as pkgExists } from "./logger-s1ImI5j1.mjs";
4
+ import { access, cp, readFile, rm, stat } from "node:fs/promises";
5
+ import path, { dirname, extname, normalize, sep } from "node:path";
6
+ import process, { env } from "node:process";
7
+ import { parseEnv } from "node:util";
8
+ import { blue, underline } from "ansis";
9
+ import { createDefu } from "defu";
10
+ import { createDebug } from "obug";
11
+ import { glob, isDynamicPattern } from "tinyglobby";
12
+ const picomatch = __cjs_require("picomatch");
13
+ import { RE_CSS, RE_DTS } from "rolldown-plugin-dts/filename";
14
+ import { readFileSync, writeFileSync } from "node:fs";
15
+ const minVersion = __cjs_require("semver/ranges/min-version.js");
16
+ import { up } from "empathic/find";
17
+ import { up as up$1 } from "empathic/package";
18
+ import { pathToFileURL } from "node:url";
19
+ import { init, isSupported } from "import-without-cache";
20
+ import { createConfigCoreLoader } from "unconfig-core";
21
+
22
+ //#region node_modules/.pnpm/is-in-ci@2.0.0/node_modules/is-in-ci/index.js
23
+ const check = (key) => key in env && env[key] !== "0" && env[key] !== "false";
24
+ const isInCi = check("CI") || check("CONTINUOUS_INTEGRATION");
25
+ var is_in_ci_default = isInCi;
26
+
27
+ //#endregion
28
+ //#region src/utils/fs.ts
29
+ function fsExists(path$1) {
30
+ return access(path$1).then(() => true, () => false);
31
+ }
32
+ function fsStat(path$1) {
33
+ return stat(path$1).catch(() => null);
34
+ }
35
+ function fsRemove(path$1) {
36
+ return rm(path$1, {
37
+ force: true,
38
+ recursive: true
39
+ }).catch(() => {});
40
+ }
41
+ function fsCopy(from, to) {
42
+ return cp(from, to, {
43
+ recursive: true,
44
+ force: true
45
+ });
46
+ }
47
+ function lowestCommonAncestor(...filepaths) {
48
+ if (filepaths.length === 0) return "";
49
+ if (filepaths.length === 1) return dirname(filepaths[0]);
50
+ filepaths = filepaths.map(normalize);
51
+ const [first, ...rest] = filepaths;
52
+ let ancestor = first.split(sep);
53
+ for (const filepath of rest) {
54
+ const directories = filepath.split(sep, ancestor.length);
55
+ let index = 0;
56
+ for (const directory of directories) if (directory === ancestor[index]) index += 1;
57
+ else {
58
+ ancestor = ancestor.slice(0, index);
59
+ break;
60
+ }
61
+ ancestor = ancestor.slice(0, index);
62
+ }
63
+ return ancestor.length <= 1 && ancestor[0] === "" ? sep + ancestor[0] : ancestor.join(sep);
64
+ }
65
+ function stripExtname(filePath) {
66
+ const ext = extname(filePath);
67
+ if (!ext.length) return filePath;
68
+ return filePath.slice(0, -ext.length);
69
+ }
70
+
71
+ //#endregion
72
+ //#region src/features/clean.ts
73
+ const debug$2 = createDebug("tsdown:clean");
74
+ const RE_LAST_SLASH = /[/\\]$/;
75
+ async function cleanOutDir(configs) {
76
+ const removes = /* @__PURE__ */ new Set();
77
+ for (const config of configs) {
78
+ if (config.debug && (config.debug.clean ?? true)) config.clean.push(".rolldown");
79
+ if (!config.clean.length) continue;
80
+ const files = await glob(config.clean, {
81
+ cwd: config.cwd,
82
+ absolute: true,
83
+ onlyFiles: false,
84
+ dot: true
85
+ });
86
+ const normalizedOutDir = config.outDir.replace(RE_LAST_SLASH, "");
87
+ for (const file of files) if (file.replace(RE_LAST_SLASH, "") !== normalizedOutDir) removes.add(file);
88
+ }
89
+ if (!removes.size) return;
90
+ globalLogger.info(`Cleaning ${removes.size} files`);
91
+ await Promise.all([...removes].map(async (file) => {
92
+ debug$2("Removing", file);
93
+ await fsRemove(file);
94
+ }));
95
+ debug$2("Removed %d files", removes.size);
96
+ }
97
+ function resolveClean(clean, outDir, cwd) {
98
+ if (clean === true) clean = [slash(outDir)];
99
+ else if (!clean) clean = [];
100
+ if (clean.some((item) => path.resolve(item) === cwd)) throw new Error("Cannot clean the current working directory. Please specify a different path to clean option.");
101
+ return clean;
102
+ }
103
+ async function cleanChunks(outDir, chunks) {
104
+ await Promise.all(chunks.map(async (chunk) => {
105
+ const filePath = path.resolve(outDir, chunk.fileName);
106
+ debug$2("Removing chunk file", filePath);
107
+ await fsRemove(filePath);
108
+ }));
109
+ }
110
+
111
+ //#endregion
112
+ //#region src/features/css.ts
113
+ const RE_CSS_HASH = /-[\w-]+\.css$/;
114
+ const RE_CHUNK_HASH = /-[\w-]+\.(m?js|cjs)$/;
115
+ const RE_CHUNK_EXT = /\.(m?js|cjs)$/;
116
+ const defaultCssBundleName = "style.css";
117
+ /**
118
+ * Normalize CSS file name by removing hash pattern and extension.
119
+ * e.g., "async-DcjEOEdU.css" -> "async"
120
+ */
121
+ function normalizeCssFileName(cssFileName) {
122
+ return cssFileName.replace(RE_CSS_HASH, "").replace(RE_CSS, "");
123
+ }
124
+ /**
125
+ * Normalize chunk file name by removing hash pattern and extension.
126
+ * e.g., "async-CvIfFAic.mjs" -> "async"
127
+ */
128
+ function normalizeChunkFileName(chunkFileName) {
129
+ return chunkFileName.replace(RE_CHUNK_HASH, "").replace(RE_CHUNK_EXT, "");
130
+ }
131
+ /**
132
+ * CSS Code Split Plugin
133
+ *
134
+ * When css.splitting is false, this plugin merges all CSS files into a single file.
135
+ * When css.splitting is true (default), CSS code splitting is preserved.
136
+ * Based on Vite's implementation.
137
+ */
138
+ function CssCodeSplitPlugin(config) {
139
+ const { splitting, fileName } = config.css;
140
+ if (splitting) return;
141
+ let hasEmitted = false;
142
+ return {
143
+ name: "tsdown:css-code-split",
144
+ renderStart() {
145
+ hasEmitted = false;
146
+ },
147
+ generateBundle(_outputOptions, bundle) {
148
+ if (hasEmitted) return;
149
+ const cssAssets = /* @__PURE__ */ new Map();
150
+ for (const [fileName$1, asset] of Object.entries(bundle)) if (asset.type === "asset" && RE_CSS.test(fileName$1)) {
151
+ const source = typeof asset.source === "string" ? asset.source : new TextDecoder("utf-8").decode(asset.source);
152
+ cssAssets.set(fileName$1, source);
153
+ }
154
+ if (!cssAssets.size) return;
155
+ const chunkCSSMap = /* @__PURE__ */ new Map();
156
+ for (const [chunkFileName, item] of Object.entries(bundle)) if (item.type === "chunk") {
157
+ for (const moduleId of Object.keys(item.modules)) if (RE_CSS.test(moduleId)) {
158
+ if (!chunkCSSMap.has(chunkFileName)) chunkCSSMap.set(chunkFileName, []);
159
+ break;
160
+ }
161
+ }
162
+ for (const [cssFileName] of cssAssets) {
163
+ const cssBaseName = normalizeCssFileName(cssFileName);
164
+ for (const [chunkFileName] of chunkCSSMap) if (normalizeChunkFileName(chunkFileName) === cssBaseName || chunkFileName.startsWith(`${cssBaseName}-`)) {
165
+ chunkCSSMap.get(chunkFileName)?.push(cssFileName);
166
+ break;
167
+ }
168
+ }
169
+ let extractedCss = "";
170
+ const collected = /* @__PURE__ */ new Set();
171
+ const dynamicImports = /* @__PURE__ */ new Set();
172
+ function collect(chunk) {
173
+ if (!chunk || chunk.type !== "chunk" || collected.has(chunk)) return;
174
+ collected.add(chunk);
175
+ chunk.imports.forEach((importName) => {
176
+ collect(bundle[importName]);
177
+ });
178
+ chunk.dynamicImports.forEach((importName) => {
179
+ dynamicImports.add(importName);
180
+ });
181
+ const files = chunkCSSMap.get(chunk.fileName);
182
+ if (files && files.length > 0) for (const filename of files) extractedCss += cssAssets.get(filename) ?? "";
183
+ }
184
+ for (const chunk of Object.values(bundle)) if (chunk.type === "chunk" && chunk.isEntry) collect(chunk);
185
+ for (const chunkName of dynamicImports) collect(bundle[chunkName]);
186
+ if (extractedCss) {
187
+ hasEmitted = true;
188
+ for (const fileName$1 of cssAssets.keys()) delete bundle[fileName$1];
189
+ this.emitFile({
190
+ type: "asset",
191
+ source: extractedCss,
192
+ fileName,
193
+ originalFileName: defaultCssBundleName
194
+ });
195
+ }
196
+ }
197
+ };
198
+ }
199
+
200
+ //#endregion
201
+ //#region src/features/entry.ts
202
+ async function resolveEntry(logger, entry, cwd, color, nameLabel) {
203
+ if (!entry || Object.keys(entry).length === 0) {
204
+ const defaultEntry = path.resolve(cwd, "src/index.ts");
205
+ if (await fsExists(defaultEntry)) entry = { index: defaultEntry };
206
+ else throw new Error(`${nameLabel} No input files, try "tsdown <your-file>" or create src/index.ts`);
207
+ }
208
+ const entryMap = await toObjectEntry(entry, cwd);
209
+ const entries = Object.values(entryMap);
210
+ if (entries.length === 0) throw new Error(`${nameLabel} Cannot find entry: ${JSON.stringify(entry)}`);
211
+ logger.info(nameLabel, `entry: ${color(entries.map((entry$1) => path.relative(cwd, entry$1)).join(", "))}`);
212
+ return entryMap;
213
+ }
214
+ async function toObjectEntry(entry, cwd) {
215
+ if (typeof entry === "string") entry = [entry];
216
+ if (!Array.isArray(entry)) return Object.fromEntries((await Promise.all(Object.entries(entry).map(async ([key, value]) => {
217
+ if (!key.includes("*")) {
218
+ if (Array.isArray(value)) throw new TypeError(`Object entry "${key}" cannot have an array value when the key is not a glob pattern.`);
219
+ return [[key, value]];
220
+ }
221
+ const patterns = toArray(value);
222
+ const files = await glob(patterns, {
223
+ cwd,
224
+ expandDirectories: false
225
+ });
226
+ if (!files.length) throw new Error(`Cannot find files for entry key "${key}" with patterns: ${JSON.stringify(patterns)}`);
227
+ let valueGlobBase;
228
+ for (const pattern of patterns) {
229
+ if (pattern.startsWith("!")) continue;
230
+ const base$1 = picomatch.scan(pattern).base;
231
+ if (valueGlobBase === void 0) valueGlobBase = base$1;
232
+ else if (valueGlobBase !== base$1) throw new Error(`When using object entry with glob pattern key "${key}", all value glob patterns must have the same base directory.`);
233
+ }
234
+ if (valueGlobBase === void 0) throw new Error(`Cannot determine base directory for value glob patterns of key "${key}".`);
235
+ return files.map((file) => [slash(key.replaceAll("*", stripExtname(path.relative(valueGlobBase, file)))), path.resolve(cwd, file)]);
236
+ }))).flat());
237
+ const isGlob = entry.some((e) => isDynamicPattern(e));
238
+ let resolvedEntry;
239
+ if (isGlob) resolvedEntry = (await glob(entry, {
240
+ cwd,
241
+ expandDirectories: false,
242
+ absolute: true
243
+ })).map((file) => path.resolve(file));
244
+ else resolvedEntry = entry;
245
+ const base = lowestCommonAncestor(...resolvedEntry);
246
+ return Object.fromEntries(resolvedEntry.map((file) => {
247
+ return [slash(stripExtname(path.relative(base, file))), file];
248
+ }));
249
+ }
250
+
251
+ //#endregion
252
+ //#region src/utils/format.ts
253
+ function formatBytes(bytes) {
254
+ if (bytes === Infinity) return void 0;
255
+ return `${(bytes / 1e3).toFixed(2)} kB`;
256
+ }
257
+ function detectIndentation(jsonText) {
258
+ const lines = jsonText.split(/\r?\n/);
259
+ for (const line of lines) {
260
+ const match = line.match(/^(\s+)\S/);
261
+ if (!match) continue;
262
+ if (match[1].includes(" ")) return " ";
263
+ return match[1].length;
264
+ }
265
+ return 2;
266
+ }
267
+
268
+ //#endregion
269
+ //#region src/features/pkg/exports.ts
270
+ async function writeExports(options, chunks) {
271
+ const pkg = options.pkg;
272
+ const exports = options.exports;
273
+ const { publishExports, ...generated } = await generateExports(pkg, chunks, exports, options.logger);
274
+ const updatedPkg = {
275
+ ...pkg,
276
+ ...generated,
277
+ packageJsonPath: void 0
278
+ };
279
+ if (publishExports) {
280
+ updatedPkg.publishConfig ||= {};
281
+ updatedPkg.publishConfig.exports = publishExports;
282
+ }
283
+ const original = readFileSync(pkg.packageJsonPath, "utf8");
284
+ let contents = JSON.stringify(updatedPkg, null, detectIndentation(original));
285
+ if (original.endsWith("\n")) contents += "\n";
286
+ if (contents !== original) writeFileSync(pkg.packageJsonPath, contents, "utf8");
287
+ }
288
+ function shouldExclude(fileName, exclude) {
289
+ if (!exclude?.length) return false;
290
+ return matchPattern(fileName, exclude);
291
+ }
292
+ async function generateExports(pkg, chunks, { devExports, all, packageJson = true, exclude, customExports }, logger) {
293
+ const pkgRoot = path.dirname(pkg.packageJsonPath);
294
+ let main, module, cjsTypes, esmTypes;
295
+ const exportsMap = /* @__PURE__ */ new Map();
296
+ const formats = Object.keys(chunks);
297
+ if (!formats.includes("cjs") && !formats.includes("es")) logger.warn(`No CJS or ESM formats found in chunks for package ${pkg.name}`);
298
+ for (const [format, chunksByFormat] of Object.entries(chunks)) {
299
+ if (format !== "es" && format !== "cjs") continue;
300
+ const filteredChunks = chunksByFormat.filter((chunk) => chunk.type === "chunk" && chunk.isEntry && !shouldExclude(chunk.fileName, exclude));
301
+ const onlyOneEntry = filteredChunks.filter((chunk) => !RE_DTS.test(chunk.fileName)).length === 1;
302
+ for (const chunk of filteredChunks) {
303
+ const normalizedName = slash(chunk.fileName);
304
+ let name = stripExtname(normalizedName);
305
+ const isDts = name.endsWith(".d");
306
+ if (isDts) name = name.slice(0, -2);
307
+ const isIndex = onlyOneEntry || name === "index";
308
+ const outDirRelative = slash(path.relative(pkgRoot, chunk.outDir));
309
+ const distFile = `${outDirRelative ? `./${outDirRelative}` : "."}/${normalizedName}`;
310
+ if (isIndex) {
311
+ name = ".";
312
+ if (format === "cjs") if (isDts) cjsTypes = distFile;
313
+ else main = distFile;
314
+ else if (format === "es") if (isDts) esmTypes = distFile;
315
+ else module = distFile;
316
+ } else if (name.endsWith("/index")) name = `./${name.slice(0, -6)}`;
317
+ else name = `./${name}`;
318
+ let subExport = exportsMap.get(name);
319
+ if (!subExport) {
320
+ subExport = {};
321
+ exportsMap.set(name, subExport);
322
+ }
323
+ if (!isDts) {
324
+ subExport[format] = distFile;
325
+ if (chunk.facadeModuleId && !subExport.src) subExport.src = `./${slash(path.relative(pkgRoot, chunk.facadeModuleId))}`;
326
+ }
327
+ }
328
+ }
329
+ const sortedExportsMap = Array.from(exportsMap.entries()).toSorted(([a], [b]) => {
330
+ if (a === "index") return -1;
331
+ return a.localeCompare(b);
332
+ });
333
+ let exports = Object.fromEntries(sortedExportsMap.map(([name, subExport]) => [name, genSubExport(devExports, subExport)]));
334
+ exportMeta(exports, all, packageJson);
335
+ if (customExports) exports = await customExports(exports, {
336
+ pkg,
337
+ chunks,
338
+ isPublish: false
339
+ });
340
+ let publishExports;
341
+ if (devExports) {
342
+ publishExports = Object.fromEntries(sortedExportsMap.map(([name, subExport]) => [name, genSubExport(false, subExport)]));
343
+ exportMeta(publishExports, all, packageJson);
344
+ if (customExports) publishExports = await customExports(publishExports, {
345
+ pkg,
346
+ chunks,
347
+ isPublish: true
348
+ });
349
+ }
350
+ return {
351
+ main: main || module || pkg.main,
352
+ module: module || pkg.module,
353
+ types: cjsTypes || esmTypes || pkg.types,
354
+ exports,
355
+ publishExports
356
+ };
357
+ }
358
+ function genSubExport(devExports, { src, es, cjs }) {
359
+ if (devExports === true) return src;
360
+ let value;
361
+ const dualFormat = es && cjs;
362
+ if (!dualFormat && !devExports) value = cjs || es;
363
+ else {
364
+ value = {};
365
+ if (typeof devExports === "string") value[devExports] = src;
366
+ if (cjs) value[dualFormat ? "require" : "default"] = cjs;
367
+ if (es) value[dualFormat ? "import" : "default"] = es;
368
+ }
369
+ return value;
370
+ }
371
+ function exportMeta(exports, all, packageJson) {
372
+ if (all) exports["./*"] = "./*";
373
+ else if (packageJson) exports["./package.json"] = "./package.json";
374
+ }
375
+ function hasExportsTypes(pkg) {
376
+ const exports = pkg?.exports;
377
+ if (!exports) return false;
378
+ if (typeof exports === "object" && exports !== null && !Array.isArray(exports)) {
379
+ if ("types" in exports) return true;
380
+ if ("." in exports) {
381
+ const mainExport = exports["."];
382
+ if (typeof mainExport === "object" && mainExport !== null && "types" in mainExport) return true;
383
+ }
384
+ }
385
+ return false;
386
+ }
387
+
388
+ //#endregion
389
+ //#region src/features/target.ts
390
+ function resolveTarget(logger, target, color, pkg, nameLabel) {
391
+ if (target === false) return;
392
+ if (target == null) {
393
+ const pkgTarget = resolvePackageTarget(pkg);
394
+ if (pkgTarget) target = pkgTarget;
395
+ else return;
396
+ }
397
+ if (typeof target === "number") throw new TypeError(`Invalid target: ${target}`);
398
+ const targets = resolveComma(toArray(target));
399
+ if (targets.length) logger.info(nameLabel, `target${targets.length > 1 ? "s" : ""}: ${color(targets.join(", "))}`);
400
+ return targets;
401
+ }
402
+ function resolvePackageTarget(pkg) {
403
+ const nodeVersion = pkg?.engines?.node;
404
+ if (!nodeVersion) return;
405
+ const nodeMinVersion = minVersion(nodeVersion);
406
+ if (!nodeMinVersion) return;
407
+ if (nodeMinVersion.version === "0.0.0") return;
408
+ return `node${nodeMinVersion.version}`;
409
+ }
410
+
411
+ //#endregion
412
+ //#region src/features/tsconfig.ts
413
+ function findTsconfig(cwd, name = "tsconfig.json") {
414
+ return up(name, { cwd }) || false;
415
+ }
416
+ async function resolveTsconfig(logger, tsconfig, cwd, color, nameLabel) {
417
+ const original = tsconfig;
418
+ if (tsconfig !== false) {
419
+ if (tsconfig === true || tsconfig == null) {
420
+ tsconfig = findTsconfig(cwd);
421
+ if (original && !tsconfig) logger.warn(`No tsconfig found in ${blue(cwd)}`);
422
+ } else {
423
+ const tsconfigPath = path.resolve(cwd, tsconfig);
424
+ const stat$1 = await fsStat(tsconfigPath);
425
+ if (stat$1?.isFile()) tsconfig = tsconfigPath;
426
+ else if (stat$1?.isDirectory()) {
427
+ tsconfig = findTsconfig(tsconfigPath);
428
+ if (!tsconfig) logger.warn(`No tsconfig found in ${blue(tsconfigPath)}`);
429
+ } else {
430
+ tsconfig = findTsconfig(cwd, tsconfig);
431
+ if (!tsconfig) logger.warn(`tsconfig ${blue(original)} doesn't exist`);
432
+ }
433
+ }
434
+ if (tsconfig) logger.info(nameLabel, `tsconfig: ${color(path.relative(cwd, tsconfig))}`);
435
+ }
436
+ return tsconfig;
437
+ }
438
+
439
+ //#endregion
440
+ //#region src/utils/package.ts
441
+ const debug$1 = createDebug("tsdown:package");
442
+ async function readPackageJson(dir) {
443
+ const packageJsonPath = up$1({ cwd: dir });
444
+ if (!packageJsonPath) return;
445
+ debug$1("Reading package.json:", packageJsonPath);
446
+ const contents = await readFile(packageJsonPath, "utf8");
447
+ return {
448
+ ...JSON.parse(contents),
449
+ packageJsonPath
450
+ };
451
+ }
452
+ function getPackageType(pkg) {
453
+ if (pkg?.type) {
454
+ if (!["module", "commonjs"].includes(pkg.type)) throw new Error(`Invalid package.json type: ${pkg.type}`);
455
+ return pkg.type;
456
+ }
457
+ }
458
+ function normalizeFormat(format) {
459
+ switch (format) {
460
+ case "es":
461
+ case "esm":
462
+ case "module": return "es";
463
+ case "cjs":
464
+ case "commonjs": return "cjs";
465
+ default: return format;
466
+ }
467
+ }
468
+
469
+ //#endregion
470
+ //#region src/config/file.ts
471
+ const debug = createDebug("tsdown:config:file");
472
+ async function loadViteConfig(prefix, cwd, configLoader) {
473
+ const loader = resolveConfigLoader(configLoader);
474
+ debug("Loading Vite config via loader: ", loader);
475
+ const parser = createParser(loader);
476
+ const [result] = await createConfigCoreLoader({
477
+ sources: [{
478
+ files: [`${prefix}.config`],
479
+ extensions: [
480
+ "js",
481
+ "mjs",
482
+ "ts",
483
+ "cjs",
484
+ "mts",
485
+ "mts"
486
+ ],
487
+ parser
488
+ }],
489
+ cwd
490
+ }).load(true);
491
+ if (!result) return;
492
+ const { config, source } = result;
493
+ globalLogger.info(`Using Vite config: ${underline(source)}`);
494
+ const resolved = await config;
495
+ if (typeof resolved === "function") return resolved({
496
+ command: "build",
497
+ mode: "production"
498
+ });
499
+ return resolved;
500
+ }
501
+ const configPrefix = "tsdown.config";
502
+ async function loadConfigFile(inlineConfig, workspace) {
503
+ let cwd = inlineConfig.cwd || process.cwd();
504
+ let overrideConfig = false;
505
+ let { config: filePath } = inlineConfig;
506
+ if (filePath === false) return { configs: [{}] };
507
+ if (typeof filePath === "string") {
508
+ const stats = await fsStat(filePath);
509
+ if (stats) {
510
+ const resolved = path.resolve(filePath);
511
+ if (stats.isFile()) {
512
+ overrideConfig = true;
513
+ filePath = resolved;
514
+ cwd = path.dirname(filePath);
515
+ } else if (stats.isDirectory()) cwd = resolved;
516
+ }
517
+ }
518
+ const loader = resolveConfigLoader(inlineConfig.configLoader);
519
+ debug("Using config loader:", loader);
520
+ const parser = createParser(loader);
521
+ const [result] = await createConfigCoreLoader({
522
+ sources: overrideConfig ? [{
523
+ files: [filePath],
524
+ extensions: [],
525
+ parser
526
+ }] : [{
527
+ files: [configPrefix],
528
+ extensions: [
529
+ "ts",
530
+ "mts",
531
+ "cts",
532
+ "js",
533
+ "mjs",
534
+ "cjs",
535
+ "json"
536
+ ],
537
+ parser
538
+ }, {
539
+ files: ["package.json"],
540
+ parser
541
+ }],
542
+ cwd,
543
+ stopAt: workspace && path.dirname(workspace)
544
+ }).load(true);
545
+ let exported = [];
546
+ let file;
547
+ if (result) {
548
+ ({config: exported, source: file} = result);
549
+ globalLogger.info(`config file: ${underline(file)}`, loader === "native" ? "" : `(${loader})`);
550
+ exported = await exported;
551
+ if (typeof exported === "function") exported = await exported(inlineConfig, { ci: is_in_ci_default });
552
+ }
553
+ exported = toArray(exported);
554
+ if (exported.length === 0) exported.push({});
555
+ 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(() => [...])");
556
+ return {
557
+ configs: exported.map((config) => ({
558
+ ...config,
559
+ cwd: config.cwd ? path.resolve(cwd, config.cwd) : cwd
560
+ })),
561
+ file
562
+ };
563
+ }
564
+ const isBun = !!process.versions.bun;
565
+ const nativeTS = process.features.typescript || process.versions.deno;
566
+ const autoLoader = isBun || nativeTS && isSupported ? "native" : "unrun";
567
+ function resolveConfigLoader(configLoader = "auto") {
568
+ if (configLoader === "auto") return autoLoader;
569
+ else return configLoader === "native" ? "native" : "unrun";
570
+ }
571
+ function createParser(loader) {
572
+ return async (filepath) => {
573
+ const basename = path.basename(filepath);
574
+ const isPkgJson = basename === "package.json";
575
+ if (basename === configPrefix || isPkgJson || basename.endsWith(".json")) {
576
+ const contents = await readFile(filepath, "utf8");
577
+ const parsed = JSON.parse(contents);
578
+ if (isPkgJson) return parsed?.tsdown;
579
+ return parsed;
580
+ }
581
+ if (loader === "native") return nativeImport(filepath);
582
+ return unrunImport(filepath);
583
+ };
584
+ }
585
+ async function nativeImport(id) {
586
+ const url = pathToFileURL(id);
587
+ const importAttributes = Object.create(null);
588
+ if (isSupported) {
589
+ importAttributes.cache = "no";
590
+ init({ skipNodeModules: true });
591
+ } else if (!isBun) url.searchParams.set("no-cache", crypto.randomUUID());
592
+ const mod = await import(url.href, { with: importAttributes }).catch((error) => {
593
+ 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 });
594
+ else throw error;
595
+ });
596
+ return mod.default || mod;
597
+ }
598
+ async function unrunImport(id) {
599
+ const { unrun } = await import("unrun");
600
+ const { module } = await unrun({ path: pathToFileURL(id).href });
601
+ return module;
602
+ }
603
+
604
+ //#endregion
605
+ //#region src/config/options.ts
606
+ const debugLog = createDebug("tsdown:config:options");
607
+ async function resolveUserConfig(userConfig, inlineConfig) {
608
+ 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 = false, ignoreWatch, shims = false, skipNodeModulesBundle = false, publint = false, attw = false, fromVite, alias, tsconfig, report = true, target, env: env$1 = {}, envFile, envPrefix = "TSDOWN_", copy, 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, css, fixedExtension = platform === "node", debug: debug$3 = false, write = true } = userConfig;
609
+ const pkg = await readPackageJson(cwd);
610
+ if (workspace) name ||= pkg?.name;
611
+ const color = generateColor(name);
612
+ const nameLabel = getNameLabel(color, name);
613
+ if (!filterConfig(inlineConfig.filter, cwd, name)) {
614
+ debugLog("[filter] skipping config %s", cwd);
615
+ return [];
616
+ }
617
+ const logger = createLogger(logLevel, {
618
+ customLogger,
619
+ failOnWarn: resolveFeatureOption(failOnWarn, true)
620
+ });
621
+ if (typeof bundle === "boolean") logger.warn("`bundle` option is deprecated. Use `unbundle` instead.");
622
+ if (removeNodeProtocol) {
623
+ if (nodeProtocol) throw new TypeError("`removeNodeProtocol` is deprecated. Please only use `nodeProtocol` instead.");
624
+ logger.warn("`removeNodeProtocol` is deprecated. Use `nodeProtocol: \"strip\"` instead.");
625
+ }
626
+ nodeProtocol = nodeProtocol ?? (removeNodeProtocol ? "strip" : false);
627
+ outDir = path.resolve(cwd, outDir);
628
+ clean = resolveClean(clean, outDir, cwd);
629
+ const resolvedEntry = await resolveEntry(logger, entry, cwd, color, nameLabel);
630
+ if (dts == null) dts = !!(pkg?.types || pkg?.typings || hasExportsTypes(pkg));
631
+ target = resolveTarget(logger, target, color, pkg, nameLabel);
632
+ tsconfig = await resolveTsconfig(logger, tsconfig, cwd, color, nameLabel);
633
+ if (typeof external === "string") external = resolveRegex(external);
634
+ if (typeof noExternal === "string") noExternal = resolveRegex(noExternal);
635
+ publint = resolveFeatureOption(publint, {});
636
+ attw = resolveFeatureOption(attw, {});
637
+ exports = resolveFeatureOption(exports, {});
638
+ unused = resolveFeatureOption(unused, {});
639
+ report = resolveFeatureOption(report, {});
640
+ dts = resolveFeatureOption(dts, {});
641
+ if (!pkg) {
642
+ if (exports) throw new Error("`package.json` not found, cannot write exports");
643
+ if (publint) logger.warn(nameLabel, "publint is enabled but package.json is not found");
644
+ if (attw) logger.warn(nameLabel, "attw is enabled but package.json is not found");
645
+ }
646
+ if (publicDir) if (copy) throw new TypeError("`publicDir` is deprecated. Cannot be used with `copy`");
647
+ else logger.warn(`${blue`publicDir`} is deprecated. Use ${blue`copy`} instead.`);
648
+ envPrefix = toArray(envPrefix);
649
+ if (envPrefix.includes("")) logger.warn("`envPrefix` includes an empty string; filtering is disabled. All environment variables from the env file and process.env will be injected into the build. Ensure this is intended to avoid accidental leakage of sensitive information.");
650
+ const envFromProcess = filterEnv(process.env, envPrefix);
651
+ if (envFile) {
652
+ const resolvedPath = path.resolve(cwd, envFile);
653
+ logger.info(nameLabel, `env file: ${color(resolvedPath)}`);
654
+ env$1 = {
655
+ ...filterEnv(parseEnv(await readFile(resolvedPath, "utf8")), envPrefix),
656
+ ...envFromProcess,
657
+ ...env$1
658
+ };
659
+ } else env$1 = {
660
+ ...envFromProcess,
661
+ ...env$1
662
+ };
663
+ debugLog(`Environment variables: %O`, env$1);
664
+ if (fromVite) {
665
+ const viteUserConfig = await loadViteConfig(fromVite === true ? "vite" : fromVite, cwd, inlineConfig.configLoader);
666
+ if (viteUserConfig) {
667
+ const viteAlias = viteUserConfig.resolve?.alias;
668
+ if (Array.isArray(viteAlias)) throw new TypeError("Unsupported resolve.alias in Vite config. Use object instead of array");
669
+ if (viteAlias) alias = {
670
+ ...alias,
671
+ ...viteAlias
672
+ };
673
+ if (viteUserConfig.plugins) plugins = [viteUserConfig.plugins, plugins];
674
+ }
675
+ }
676
+ ignoreWatch = toArray(ignoreWatch).map((ignore) => {
677
+ ignore = resolveRegex(ignore);
678
+ if (typeof ignore === "string") return path.resolve(cwd, ignore);
679
+ return ignore;
680
+ });
681
+ if (noExternal != null && typeof noExternal !== "function") {
682
+ const noExternalPatterns = toArray(noExternal);
683
+ noExternal = (id) => matchPattern(id, noExternalPatterns);
684
+ }
685
+ if (inlineOnly != null) inlineOnly = toArray(inlineOnly);
686
+ debug$3 = resolveFeatureOption(debug$3, {});
687
+ if (debug$3) if (watch) {
688
+ if (debug$3.devtools) logger.warn("Devtools is not supported in watch mode, disabling it.");
689
+ debug$3.devtools = false;
690
+ } else debug$3.devtools ??= !!pkgExists("@vitejs/devtools/cli");
691
+ const config = {
692
+ ...userConfig,
693
+ alias,
694
+ attw,
695
+ cjsDefault,
696
+ clean,
697
+ copy: publicDir || copy,
698
+ css: {
699
+ splitting: true,
700
+ fileName: defaultCssBundleName,
701
+ ...css
702
+ },
703
+ cwd,
704
+ debug: debug$3,
705
+ dts,
706
+ entry: resolvedEntry,
707
+ env: env$1,
708
+ exports,
709
+ external,
710
+ fixedExtension,
711
+ globImport,
712
+ hash,
713
+ ignoreWatch,
714
+ inlineOnly,
715
+ logger,
716
+ name,
717
+ nameLabel,
718
+ nodeProtocol,
719
+ noExternal,
720
+ outDir,
721
+ pkg,
722
+ platform,
723
+ plugins,
724
+ publint,
725
+ report,
726
+ shims,
727
+ skipNodeModulesBundle,
728
+ sourcemap,
729
+ target,
730
+ treeshake,
731
+ tsconfig,
732
+ unbundle,
733
+ unused,
734
+ watch,
735
+ write
736
+ };
737
+ const objectFormat = typeof format === "object" && !Array.isArray(format);
738
+ return (objectFormat ? Object.keys(format) : resolveComma(toArray(format, "es"))).map((fmt, idx) => {
739
+ const once = idx === 0;
740
+ const overrides = objectFormat ? format[fmt] : void 0;
741
+ return {
742
+ ...config,
743
+ copy: once ? config.copy : void 0,
744
+ onSuccess: once ? config.onSuccess : void 0,
745
+ format: normalizeFormat(fmt),
746
+ ...overrides
747
+ };
748
+ });
749
+ }
750
+ /** filter env variables by prefixes */
751
+ function filterEnv(envDict, envPrefixes) {
752
+ const env$1 = {};
753
+ for (const [key, value] of Object.entries(envDict)) if (envPrefixes.some((prefix) => key.startsWith(prefix)) && value !== void 0) env$1[key] = value;
754
+ return env$1;
755
+ }
756
+ const defu = createDefu((obj, key, value) => {
757
+ if (Array.isArray(obj[key]) && Array.isArray(value)) {
758
+ obj[key] = value;
759
+ return true;
760
+ }
761
+ });
762
+ function mergeConfig(defaults, overrides) {
763
+ return defu(overrides, defaults);
764
+ }
765
+ async function mergeUserOptions(defaults, user, args) {
766
+ const userOutputOptions = typeof user === "function" ? await user(defaults, ...args) : user;
767
+ if (!userOutputOptions) return defaults;
768
+ return defu(userOutputOptions, defaults);
769
+ }
770
+ function resolveFeatureOption(value, defaults) {
771
+ if (typeof value === "object" && value !== null) return resolveCIOption(value.enabled ?? true) ? value : false;
772
+ return resolveCIOption(value) ? defaults : false;
773
+ }
774
+ function resolveCIOption(value) {
775
+ if (value === "ci-only") return is_in_ci_default ? true : false;
776
+ if (value === "local-only") return is_in_ci_default ? false : true;
777
+ return value;
778
+ }
779
+ function filterConfig(filter, configCwd, name) {
780
+ if (!filter) return true;
781
+ let cwd = path.relative(process.cwd(), configCwd);
782
+ if (cwd === "") cwd = ".";
783
+ if (filter instanceof RegExp) return name && filter.test(name) || filter.test(cwd);
784
+ return toArray(filter).some((value) => name && name === value || cwd === value);
785
+ }
786
+
787
+ //#endregion
788
+ //#region src/config.ts
789
+ function defineConfig(options) {
790
+ return options;
791
+ }
792
+
793
+ //#endregion
794
+ export { loadConfigFile as a, formatBytes as c, cleanOutDir as d, fsCopy as f, lowestCommonAncestor as h, resolveUserConfig as i, CssCodeSplitPlugin as l, fsRemove as m, mergeConfig as n, getPackageType as o, fsExists as p, mergeUserOptions as r, writeExports as s, defineConfig as t, cleanChunks as u };