tsdown 0.13.2 → 0.13.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.
- package/README.md +1 -1
- package/dist/{config-CZj6NGiw.d.mts → config-CEEvti7D.d.mts} +1 -1
- package/dist/config.d.mts +2 -2
- package/dist/index.d.mts +4 -17
- package/dist/index.mjs +3 -3
- package/dist/{logger-6IV2T7t1.mjs → logger-CGMSjTLn.mjs} +51 -27
- package/dist/{migrate-mIs6mjET.mjs → migrate-BghKfLMP.mjs} +20 -20
- package/dist/package-C-PL6-Mh.mjs +5 -0
- package/dist/plugins.d.mts +2 -2
- package/dist/plugins.mjs +2 -2
- package/dist/run.mjs +11 -11
- package/dist/{src-C8dUJ_Mj.mjs → src-D6AiyRka.mjs} +634 -586
- package/dist/{types-DIH2hGTd.d.mts → types-QuuoDTDl.d.mts} +45 -8
- package/package.json +7 -7
- package/dist/package-Dg3yzWpE.mjs +0 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { debounce, generateColor,
|
|
1
|
+
import { LogLevels, createLogger, debounce, generateColor, globalLogger, noop, prettyFormat, prettyName, resolveComma, resolveRegex, slash, toArray } from "./logger-CGMSjTLn.mjs";
|
|
2
2
|
import { builtinModules } from "node:module";
|
|
3
3
|
import path, { dirname, normalize, sep } from "node:path";
|
|
4
4
|
import process from "node:process";
|
|
@@ -11,18 +11,20 @@ import child_process from "node:child_process";
|
|
|
11
11
|
import { access, chmod, cp, mkdtemp, readFile, rm, stat, writeFile } from "node:fs/promises";
|
|
12
12
|
import { tmpdir } from "node:os";
|
|
13
13
|
import { promisify } from "node:util";
|
|
14
|
-
import
|
|
14
|
+
import debug from "debug";
|
|
15
|
+
import coerce from "semver/functions/coerce.js";
|
|
16
|
+
import satisfies from "semver/functions/satisfies.js";
|
|
15
17
|
import { glob } from "tinyglobby";
|
|
16
18
|
import { RE_CSS, RE_DTS, RE_JS } from "rolldown-plugin-dts/filename";
|
|
17
19
|
import { createHooks } from "hookable";
|
|
18
|
-
import
|
|
20
|
+
import minVersion from "semver/ranges/min-version.js";
|
|
21
|
+
import { up } from "empathic/find";
|
|
22
|
+
import { up as up$1 } from "empathic/package";
|
|
23
|
+
import { loadConfig } from "unconfig";
|
|
19
24
|
import { Buffer } from "node:buffer";
|
|
20
25
|
import { brotliCompress, gzip } from "node:zlib";
|
|
21
26
|
import readline from "node:readline";
|
|
22
|
-
import minVersion from "semver/ranges/min-version.js";
|
|
23
27
|
import { globalContext, invalidateContextFile } from "rolldown-plugin-dts/tsc-context";
|
|
24
|
-
import { up as up$1 } from "empathic/find";
|
|
25
|
-
import { loadConfig } from "unconfig";
|
|
26
28
|
|
|
27
29
|
//#region src/utils/fs.ts
|
|
28
30
|
function fsExists(path$1) {
|
|
@@ -64,7 +66,7 @@ function lowestCommonAncestor(...filepaths) {
|
|
|
64
66
|
|
|
65
67
|
//#endregion
|
|
66
68
|
//#region src/features/attw.ts
|
|
67
|
-
const debug$
|
|
69
|
+
const debug$8 = debug("tsdown:attw");
|
|
68
70
|
const exec$1 = promisify(child_process.exec);
|
|
69
71
|
/**
|
|
70
72
|
* ATTW profiles.
|
|
@@ -106,18 +108,18 @@ function formatProblem(problem) {
|
|
|
106
108
|
async function attw(options) {
|
|
107
109
|
if (!options.attw) return;
|
|
108
110
|
if (!options.pkg) {
|
|
109
|
-
logger.warn("attw is enabled but package.json is not found");
|
|
111
|
+
options.logger.warn("attw is enabled but package.json is not found");
|
|
110
112
|
return;
|
|
111
113
|
}
|
|
112
114
|
const { profile = "strict", level = "warn",...attwOptions } = options.attw === true ? {} : options.attw;
|
|
113
115
|
const t = performance.now();
|
|
114
|
-
debug$
|
|
116
|
+
debug$8("Running attw check");
|
|
115
117
|
const tempDir = await mkdtemp(path.join(tmpdir(), "tsdown-attw-"));
|
|
116
118
|
let attwCore;
|
|
117
119
|
try {
|
|
118
120
|
attwCore = await import("@arethetypeswrong/core");
|
|
119
121
|
} catch {
|
|
120
|
-
logger.error(`ATTW check requires ${blue`@arethetypeswrong/core`} to be installed.`);
|
|
122
|
+
options.logger.error(`ATTW check requires ${blue`@arethetypeswrong/core`} to be installed.`);
|
|
121
123
|
return;
|
|
122
124
|
}
|
|
123
125
|
try {
|
|
@@ -140,21 +142,37 @@ async function attw(options) {
|
|
|
140
142
|
const problemList = problems.map(formatProblem).join("\n");
|
|
141
143
|
const problemMessage = `Are the types wrong problems found:\n${problemList}`;
|
|
142
144
|
if (level === "error") throw new Error(problemMessage);
|
|
143
|
-
logger.warn(problemMessage);
|
|
145
|
+
options.logger.warn(problemMessage);
|
|
144
146
|
}
|
|
145
|
-
} else logger.success(`No Are the types wrong problems found`, dim`(${Math.round(performance.now() - t)}ms)`);
|
|
147
|
+
} else options.logger.success(`No Are the types wrong problems found`, dim`(${Math.round(performance.now() - t)}ms)`);
|
|
146
148
|
} catch (error) {
|
|
147
|
-
logger.error("ATTW check failed:", error);
|
|
148
|
-
debug$
|
|
149
|
+
options.logger.error("ATTW check failed:", error);
|
|
150
|
+
debug$8("Found errors, setting exit code to 1");
|
|
149
151
|
process.exitCode = 1;
|
|
150
152
|
} finally {
|
|
151
153
|
await fsRemove(tempDir);
|
|
152
154
|
}
|
|
153
155
|
}
|
|
154
156
|
|
|
157
|
+
//#endregion
|
|
158
|
+
//#region src/features/cjs.ts
|
|
159
|
+
/**
|
|
160
|
+
* If the config includes the `cjs` format and
|
|
161
|
+
* one of its target >= node 23.0.0 / 22.12.0,
|
|
162
|
+
* warn the user about the deprecation of CommonJS.
|
|
163
|
+
*/
|
|
164
|
+
function warnLegacyCJS(config) {
|
|
165
|
+
if (!config.format.includes("cjs") || !config.target) return;
|
|
166
|
+
const legacy = config.target.some((t) => {
|
|
167
|
+
const version = coerce(t.split("node")[1]);
|
|
168
|
+
return version && satisfies(version, ">=23.0.0 || >=22.12.0");
|
|
169
|
+
});
|
|
170
|
+
if (legacy) 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");
|
|
171
|
+
}
|
|
172
|
+
|
|
155
173
|
//#endregion
|
|
156
174
|
//#region src/features/clean.ts
|
|
157
|
-
const debug$
|
|
175
|
+
const debug$7 = debug("tsdown:clean");
|
|
158
176
|
const RE_LAST_SLASH = /[/\\]$/;
|
|
159
177
|
async function cleanOutDir(configs) {
|
|
160
178
|
const removes = /* @__PURE__ */ new Set();
|
|
@@ -172,12 +190,12 @@ async function cleanOutDir(configs) {
|
|
|
172
190
|
}
|
|
173
191
|
}
|
|
174
192
|
if (!removes.size) return;
|
|
175
|
-
|
|
193
|
+
globalLogger.info(`Cleaning ${removes.size} files`);
|
|
176
194
|
await Promise.all([...removes].map(async (file) => {
|
|
177
|
-
debug$
|
|
195
|
+
debug$7("Removing", file);
|
|
178
196
|
await fsRemove(file);
|
|
179
197
|
}));
|
|
180
|
-
debug$
|
|
198
|
+
debug$7("Removed %d files", removes.size);
|
|
181
199
|
}
|
|
182
200
|
function resolveClean(clean, outDir, cwd) {
|
|
183
201
|
if (clean === true) clean = [slash(outDir)];
|
|
@@ -309,50 +327,6 @@ function exportMeta(exports, all) {
|
|
|
309
327
|
else exports["./package.json"] = "./package.json";
|
|
310
328
|
}
|
|
311
329
|
|
|
312
|
-
//#endregion
|
|
313
|
-
//#region src/features/external.ts
|
|
314
|
-
const debug$4 = Debug("tsdown:external");
|
|
315
|
-
function ExternalPlugin(options) {
|
|
316
|
-
const deps = options.pkg && Array.from(getProductionDeps(options.pkg));
|
|
317
|
-
return {
|
|
318
|
-
name: "tsdown:external",
|
|
319
|
-
async resolveId(id, importer, extraOptions) {
|
|
320
|
-
if (extraOptions.isEntry) return;
|
|
321
|
-
if (id === shimFile) return;
|
|
322
|
-
const { noExternal } = options;
|
|
323
|
-
if (typeof noExternal === "function" && noExternal(id, importer)) return;
|
|
324
|
-
if (noExternal) {
|
|
325
|
-
const noExternalPatterns = toArray(noExternal);
|
|
326
|
-
if (noExternalPatterns.some((pattern) => {
|
|
327
|
-
if (pattern instanceof RegExp) {
|
|
328
|
-
pattern.lastIndex = 0;
|
|
329
|
-
return pattern.test(id);
|
|
330
|
-
}
|
|
331
|
-
return id === pattern;
|
|
332
|
-
})) return;
|
|
333
|
-
}
|
|
334
|
-
let shouldExternal = false;
|
|
335
|
-
if (options.skipNodeModulesBundle) {
|
|
336
|
-
const resolved = await this.resolve(id, importer, extraOptions);
|
|
337
|
-
if (!resolved) return resolved;
|
|
338
|
-
shouldExternal = resolved.external || /[\\/]node_modules[\\/]/.test(resolved.id);
|
|
339
|
-
}
|
|
340
|
-
if (deps) shouldExternal ||= deps.some((dep) => id === dep || id.startsWith(`${dep}/`));
|
|
341
|
-
if (shouldExternal) {
|
|
342
|
-
debug$4("External dependency:", id);
|
|
343
|
-
return {
|
|
344
|
-
id,
|
|
345
|
-
external: shouldExternal,
|
|
346
|
-
moduleSideEffects: id.startsWith("node:") || builtinModules.includes(id) ? false : void 0
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
function getProductionDeps(pkg) {
|
|
353
|
-
return new Set([...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
330
|
//#endregion
|
|
357
331
|
//#region src/features/hooks.ts
|
|
358
332
|
async function createHooks$1(options) {
|
|
@@ -370,101 +344,146 @@ async function createHooks$1(options) {
|
|
|
370
344
|
}
|
|
371
345
|
|
|
372
346
|
//#endregion
|
|
373
|
-
//#region src/
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
const
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
347
|
+
//#region src/features/publint.ts
|
|
348
|
+
const debug$6 = debug("tsdown:publint");
|
|
349
|
+
async function publint(options) {
|
|
350
|
+
if (!options.publint) return;
|
|
351
|
+
if (!options.pkg) {
|
|
352
|
+
options.logger.warn("publint is enabled but package.json is not found");
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const t = performance.now();
|
|
356
|
+
debug$6("Running publint");
|
|
357
|
+
const { publint: publint$1 } = await import("publint");
|
|
358
|
+
const { formatMessage } = await import("publint/utils");
|
|
359
|
+
const { messages } = await publint$1(options.publint === true ? {} : options.publint);
|
|
360
|
+
debug$6("Found %d issues", messages.length);
|
|
361
|
+
if (!messages.length) options.logger.success(`No publint issues found`, dim`(${Math.round(performance.now() - t)}ms)`);
|
|
362
|
+
let hasError = false;
|
|
363
|
+
for (const message of messages) {
|
|
364
|
+
hasError ||= message.type === "error";
|
|
365
|
+
const formattedMessage = formatMessage(message, options.pkg);
|
|
366
|
+
const logType = {
|
|
367
|
+
error: "error",
|
|
368
|
+
warning: "warn",
|
|
369
|
+
suggestion: "info"
|
|
370
|
+
}[message.type];
|
|
371
|
+
options.logger[logType](formattedMessage);
|
|
372
|
+
}
|
|
373
|
+
if (hasError) {
|
|
374
|
+
debug$6("Found errors, setting exit code to 1");
|
|
375
|
+
process.exitCode = 1;
|
|
394
376
|
}
|
|
395
|
-
return targets;
|
|
396
|
-
}
|
|
397
|
-
const TARGET_REGEX = /([a-z]+)(\d+(?:\.\d+)*)/g;
|
|
398
|
-
const ESBUILD_LIGHTNINGCSS_MAPPING = {
|
|
399
|
-
chrome: "chrome",
|
|
400
|
-
edge: "edge",
|
|
401
|
-
firefox: "firefox",
|
|
402
|
-
ie: "ie",
|
|
403
|
-
ios: "ios_saf",
|
|
404
|
-
opera: "opera",
|
|
405
|
-
safari: "safari"
|
|
406
|
-
};
|
|
407
|
-
function parseVersion(version) {
|
|
408
|
-
const [major, minor = 0, patch = 0] = version.split("-")[0].split(".").map((v) => Number.parseInt(v, 10));
|
|
409
|
-
if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch)) return null;
|
|
410
|
-
return major << 16 | minor << 8 | patch;
|
|
411
377
|
}
|
|
412
378
|
|
|
413
379
|
//#endregion
|
|
414
|
-
//#region src/features/
|
|
415
|
-
async function
|
|
416
|
-
const
|
|
417
|
-
if (!
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
380
|
+
//#region src/features/entry.ts
|
|
381
|
+
async function resolveEntry(logger, entry, cwd, name) {
|
|
382
|
+
const nameLabel = name ? `[${name}] ` : "";
|
|
383
|
+
if (!entry || Object.keys(entry).length === 0) {
|
|
384
|
+
const defaultEntry = path.resolve(cwd, "src/index.ts");
|
|
385
|
+
if (await fsExists(defaultEntry)) entry = { index: defaultEntry };
|
|
386
|
+
else throw new Error(`${nameLabel}No input files, try "tsdown <your-file>" or create src/index.ts`);
|
|
387
|
+
}
|
|
388
|
+
const entryMap = await toObjectEntry(entry, cwd);
|
|
389
|
+
const entries = Object.values(entryMap);
|
|
390
|
+
if (entries.length === 0) throw new Error(`${nameLabel}Cannot find entry: ${JSON.stringify(entry)}`);
|
|
391
|
+
logger.info(prettyName(name), `entry: ${generateColor(name)(entries.map((entry$1) => path.relative(cwd, entry$1)).join(", "))}`);
|
|
392
|
+
return entryMap;
|
|
393
|
+
}
|
|
394
|
+
async function toObjectEntry(entry, cwd) {
|
|
395
|
+
if (typeof entry === "string") entry = [entry];
|
|
396
|
+
if (!Array.isArray(entry)) return entry;
|
|
397
|
+
const resolvedEntry = (await glob(entry, { cwd })).map((file) => path.resolve(cwd, file));
|
|
398
|
+
const base = lowestCommonAncestor(...resolvedEntry);
|
|
399
|
+
return Object.fromEntries(resolvedEntry.map((file) => {
|
|
400
|
+
const relative = path.relative(base, file);
|
|
401
|
+
return [relative.slice(0, relative.length - path.extname(relative).length), file];
|
|
402
|
+
}));
|
|
421
403
|
}
|
|
422
404
|
|
|
423
405
|
//#endregion
|
|
424
|
-
//#region src/features/
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
406
|
+
//#region src/features/target.ts
|
|
407
|
+
function resolveTarget(logger, target, pkg, name) {
|
|
408
|
+
if (target === false) return;
|
|
409
|
+
if (target == null) {
|
|
410
|
+
const pkgTarget = resolvePackageTarget(pkg);
|
|
411
|
+
if (pkgTarget) target = pkgTarget;
|
|
412
|
+
else return;
|
|
413
|
+
}
|
|
414
|
+
const targets = resolveComma(toArray(target));
|
|
415
|
+
if (targets.length) logger.info(prettyName(name), `target${targets.length > 1 ? "s" : ""}: ${generateColor(name)(targets.join(", "))}`);
|
|
416
|
+
return targets;
|
|
417
|
+
}
|
|
418
|
+
function resolvePackageTarget(pkg) {
|
|
419
|
+
const nodeVersion = pkg?.engines?.node;
|
|
420
|
+
if (!nodeVersion) return;
|
|
421
|
+
const nodeMinVersion = minVersion(nodeVersion);
|
|
422
|
+
if (!nodeMinVersion) return;
|
|
423
|
+
if (nodeMinVersion.version === "0.0.0") return;
|
|
424
|
+
return `node${nodeMinVersion.version}`;
|
|
425
|
+
}
|
|
426
|
+
let warned = false;
|
|
427
|
+
function RuntimeHelperCheckPlugin(logger, targets) {
|
|
428
|
+
return {
|
|
429
|
+
name: "tsdown:runtime-helper-check",
|
|
432
430
|
resolveId: {
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
external: true,
|
|
439
|
-
moduleSideEffects: false
|
|
431
|
+
filter: { id: /^@oxc-project\/runtime/ },
|
|
432
|
+
async handler(id, ...args) {
|
|
433
|
+
const EXTERNAL = {
|
|
434
|
+
id,
|
|
435
|
+
external: true
|
|
440
436
|
};
|
|
437
|
+
if (warned) return EXTERNAL;
|
|
438
|
+
const resolved = await this.resolve(id, ...args);
|
|
439
|
+
if (!resolved) {
|
|
440
|
+
if (!warned) {
|
|
441
|
+
warned = true;
|
|
442
|
+
logger.warn(`The target environment (${targets.join(", ")}) requires runtime helpers from ${blue`@oxc-project/runtime`}. Please install it to ensure all necessary polyfills are included.\nFor more information, visit: https://tsdown.dev/options/target#runtime-helpers`);
|
|
443
|
+
}
|
|
444
|
+
return EXTERNAL;
|
|
445
|
+
}
|
|
446
|
+
return resolved;
|
|
441
447
|
}
|
|
442
448
|
}
|
|
443
449
|
};
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
//#endregion
|
|
453
|
+
//#region src/features/tsconfig.ts
|
|
454
|
+
function findTsconfig(cwd, name = "tsconfig.json") {
|
|
455
|
+
return up(name, { cwd }) || false;
|
|
456
|
+
}
|
|
457
|
+
async function resolveTsconfig(logger, tsconfig, cwd, name) {
|
|
458
|
+
const original = tsconfig;
|
|
459
|
+
if (tsconfig !== false) {
|
|
460
|
+
if (tsconfig === true || tsconfig == null) {
|
|
461
|
+
tsconfig = findTsconfig(cwd);
|
|
462
|
+
if (original && !tsconfig) logger.warn(`No tsconfig found in ${blue(cwd)}`);
|
|
463
|
+
} else {
|
|
464
|
+
const tsconfigPath = path.resolve(cwd, tsconfig);
|
|
465
|
+
const stat$1 = await fsStat(tsconfigPath);
|
|
466
|
+
if (stat$1?.isFile()) tsconfig = tsconfigPath;
|
|
467
|
+
else if (stat$1?.isDirectory()) {
|
|
468
|
+
tsconfig = findTsconfig(tsconfigPath);
|
|
469
|
+
if (!tsconfig) logger.warn(`No tsconfig found in ${blue(tsconfigPath)}`);
|
|
470
|
+
} else {
|
|
471
|
+
tsconfig = findTsconfig(cwd, tsconfig);
|
|
472
|
+
if (!tsconfig) logger.warn(`tsconfig ${blue(original)} doesn't exist`);
|
|
456
473
|
}
|
|
457
474
|
}
|
|
458
|
-
|
|
475
|
+
if (tsconfig) logger.info(prettyName(name), `tsconfig: ${generateColor(name)(path.relative(cwd, tsconfig))}`);
|
|
476
|
+
}
|
|
477
|
+
return tsconfig;
|
|
459
478
|
}
|
|
460
479
|
|
|
461
480
|
//#endregion
|
|
462
481
|
//#region src/utils/package.ts
|
|
463
|
-
const debug$
|
|
482
|
+
const debug$5 = debug("tsdown:package");
|
|
464
483
|
async function readPackageJson(dir) {
|
|
465
|
-
const packageJsonPath = up({ cwd: dir });
|
|
484
|
+
const packageJsonPath = up$1({ cwd: dir });
|
|
466
485
|
if (!packageJsonPath) return;
|
|
467
|
-
debug$
|
|
486
|
+
debug$5("Reading package.json:", packageJsonPath);
|
|
468
487
|
const contents = await readFile(packageJsonPath, "utf8");
|
|
469
488
|
return {
|
|
470
489
|
...JSON.parse(contents),
|
|
@@ -490,356 +509,6 @@ function normalizeFormat(format) {
|
|
|
490
509
|
});
|
|
491
510
|
}
|
|
492
511
|
|
|
493
|
-
//#endregion
|
|
494
|
-
//#region src/features/output.ts
|
|
495
|
-
function resolveJsOutputExtension(packageType, format, fixedExtension) {
|
|
496
|
-
switch (format) {
|
|
497
|
-
case "es": return !fixedExtension && packageType === "module" ? "js" : "mjs";
|
|
498
|
-
case "cjs": return fixedExtension || packageType === "module" ? "cjs" : "js";
|
|
499
|
-
default: return "js";
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
function resolveChunkFilename({ outExtensions, fixedExtension, pkg, hash }, inputOptions, format) {
|
|
503
|
-
const packageType = getPackageType(pkg);
|
|
504
|
-
let jsExtension;
|
|
505
|
-
let dtsExtension;
|
|
506
|
-
if (outExtensions) {
|
|
507
|
-
const { js, dts } = outExtensions({
|
|
508
|
-
options: inputOptions,
|
|
509
|
-
format,
|
|
510
|
-
pkgType: packageType
|
|
511
|
-
}) || {};
|
|
512
|
-
jsExtension = js;
|
|
513
|
-
dtsExtension = dts;
|
|
514
|
-
}
|
|
515
|
-
jsExtension ||= `.${resolveJsOutputExtension(packageType, format, fixedExtension)}`;
|
|
516
|
-
const suffix = format === "iife" || format === "umd" ? `.${format}` : "";
|
|
517
|
-
return [createChunkFilename(`[name]${suffix}`, jsExtension, dtsExtension), createChunkFilename(`[name]${suffix}${hash ? "-[hash]" : ""}`, jsExtension, dtsExtension)];
|
|
518
|
-
}
|
|
519
|
-
function createChunkFilename(basename, jsExtension, dtsExtension) {
|
|
520
|
-
if (!dtsExtension) return `${basename}${jsExtension}`;
|
|
521
|
-
return (chunk) => {
|
|
522
|
-
return `${basename}${chunk.name.endsWith(".d") ? dtsExtension : jsExtension}`;
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
function resolveChunkAddon(chunkAddon, format) {
|
|
526
|
-
if (!chunkAddon) return;
|
|
527
|
-
return (chunk) => {
|
|
528
|
-
if (typeof chunkAddon === "function") chunkAddon = chunkAddon({ format });
|
|
529
|
-
switch (true) {
|
|
530
|
-
case RE_JS.test(chunk.fileName): return chunkAddon?.js || "";
|
|
531
|
-
case RE_CSS.test(chunk.fileName): return chunkAddon?.css || "";
|
|
532
|
-
case RE_DTS.test(chunk.fileName): return chunkAddon?.dts || "";
|
|
533
|
-
default: return "";
|
|
534
|
-
}
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
//#endregion
|
|
539
|
-
//#region src/features/publint.ts
|
|
540
|
-
const debug$2 = Debug("tsdown:publint");
|
|
541
|
-
async function publint(options) {
|
|
542
|
-
if (!options.publint) return;
|
|
543
|
-
if (!options.pkg) {
|
|
544
|
-
logger.warn("publint is enabled but package.json is not found");
|
|
545
|
-
return;
|
|
546
|
-
}
|
|
547
|
-
const t = performance.now();
|
|
548
|
-
debug$2("Running publint");
|
|
549
|
-
const { publint: publint$1 } = await import("publint");
|
|
550
|
-
const { formatMessage } = await import("publint/utils");
|
|
551
|
-
const { messages } = await publint$1(options.publint === true ? {} : options.publint);
|
|
552
|
-
debug$2("Found %d issues", messages.length);
|
|
553
|
-
if (!messages.length) logger.success(`No publint issues found`, dim`(${Math.round(performance.now() - t)}ms)`);
|
|
554
|
-
let hasError = false;
|
|
555
|
-
for (const message of messages) {
|
|
556
|
-
hasError ||= message.type === "error";
|
|
557
|
-
const formattedMessage = formatMessage(message, options.pkg);
|
|
558
|
-
const logType = {
|
|
559
|
-
error: "error",
|
|
560
|
-
warning: "warn",
|
|
561
|
-
suggestion: "info"
|
|
562
|
-
}[message.type];
|
|
563
|
-
logger[logType](formattedMessage);
|
|
564
|
-
}
|
|
565
|
-
if (hasError) {
|
|
566
|
-
debug$2("Found errors, setting exit code to 1");
|
|
567
|
-
process.exitCode = 1;
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
//#endregion
|
|
572
|
-
//#region src/utils/format.ts
|
|
573
|
-
function formatBytes(bytes) {
|
|
574
|
-
if (bytes === Infinity) return void 0;
|
|
575
|
-
return `${(bytes / 1e3).toFixed(2)} kB`;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
//#endregion
|
|
579
|
-
//#region src/features/report.ts
|
|
580
|
-
const debug$1 = Debug("tsdown:report");
|
|
581
|
-
const brotliCompressAsync = promisify(brotliCompress);
|
|
582
|
-
const gzipAsync = promisify(gzip);
|
|
583
|
-
function ReportPlugin(options, cwd, cjsDts, name, isMultiFormat) {
|
|
584
|
-
return {
|
|
585
|
-
name: "tsdown:report",
|
|
586
|
-
async writeBundle(outputOptions, bundle) {
|
|
587
|
-
const outDir = path.relative(cwd, outputOptions.file ? path.resolve(cwd, outputOptions.file, "..") : path.resolve(cwd, outputOptions.dir));
|
|
588
|
-
const sizes = [];
|
|
589
|
-
for (const chunk of Object.values(bundle)) {
|
|
590
|
-
const size = await calcSize(options, chunk);
|
|
591
|
-
sizes.push(size);
|
|
592
|
-
}
|
|
593
|
-
const filenameLength = Math.max(...sizes.map((size) => size.filename.length));
|
|
594
|
-
const rawTextLength = Math.max(...sizes.map((size) => size.rawText.length));
|
|
595
|
-
const gzipTextLength = Math.max(...sizes.map((size) => size.gzipText == null ? 0 : size.gzipText.length));
|
|
596
|
-
const brotliTextLength = Math.max(...sizes.map((size) => size.brotliText == null ? 0 : size.brotliText.length));
|
|
597
|
-
let totalRaw = 0;
|
|
598
|
-
for (const size of sizes) {
|
|
599
|
-
size.rawText = size.rawText.padStart(rawTextLength);
|
|
600
|
-
size.gzipText = size.gzipText?.padStart(gzipTextLength);
|
|
601
|
-
size.brotliText = size.brotliText?.padStart(brotliTextLength);
|
|
602
|
-
totalRaw += size.raw;
|
|
603
|
-
}
|
|
604
|
-
sizes.sort((a, b) => {
|
|
605
|
-
if (a.dts !== b.dts) return a.dts ? 1 : -1;
|
|
606
|
-
if (a.isEntry !== b.isEntry) return a.isEntry ? -1 : 1;
|
|
607
|
-
return b.raw - a.raw;
|
|
608
|
-
});
|
|
609
|
-
const nameLabel = prettyName(name);
|
|
610
|
-
const formatLabel = isMultiFormat && prettyFormat(cjsDts ? "cjs" : outputOptions.format);
|
|
611
|
-
for (const size of sizes) {
|
|
612
|
-
const filenameColor = size.dts ? green : noop;
|
|
613
|
-
logger.info(nameLabel, formatLabel, dim(outDir + path.sep) + filenameColor((size.isEntry ? bold : noop)(size.filename)), ` `.repeat(filenameLength - size.filename.length), dim(size.rawText), size.gzipText && dim`│ gzip: ${size.gzipText}`, options.brotli && size.brotliText && dim`│ brotli: ${size.brotliText}`);
|
|
614
|
-
}
|
|
615
|
-
const totalSizeText = formatBytes(totalRaw);
|
|
616
|
-
logger.info(nameLabel, formatLabel, `${sizes.length} files, total: ${totalSizeText}`);
|
|
617
|
-
}
|
|
618
|
-
};
|
|
619
|
-
}
|
|
620
|
-
async function calcSize(options, chunk) {
|
|
621
|
-
debug$1(`Calculating size for`, chunk.fileName);
|
|
622
|
-
const content = chunk.type === "chunk" ? chunk.code : chunk.source;
|
|
623
|
-
const raw = Buffer.byteLength(content, "utf8");
|
|
624
|
-
debug$1("[size]", chunk.fileName, raw);
|
|
625
|
-
let gzip$1 = Infinity;
|
|
626
|
-
let brotli = Infinity;
|
|
627
|
-
if (raw > (options.maxCompressSize ?? 1e6)) debug$1(chunk.fileName, "file size exceeds limit, skip gzip/brotli");
|
|
628
|
-
else {
|
|
629
|
-
gzip$1 = (await gzipAsync(content)).length;
|
|
630
|
-
debug$1("[gzip]", chunk.fileName, gzip$1);
|
|
631
|
-
if (options.brotli) {
|
|
632
|
-
brotli = (await brotliCompressAsync(content)).length;
|
|
633
|
-
debug$1("[brotli]", chunk.fileName, brotli);
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
return {
|
|
637
|
-
filename: chunk.fileName,
|
|
638
|
-
dts: RE_DTS.test(chunk.fileName),
|
|
639
|
-
isEntry: chunk.type === "chunk" && chunk.isEntry,
|
|
640
|
-
raw,
|
|
641
|
-
rawText: formatBytes(raw),
|
|
642
|
-
gzip: gzip$1,
|
|
643
|
-
gzipText: formatBytes(gzip$1),
|
|
644
|
-
brotli,
|
|
645
|
-
brotliText: formatBytes(brotli)
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
//#endregion
|
|
650
|
-
//#region src/features/shims.ts
|
|
651
|
-
function getShimsInject(format, platform) {
|
|
652
|
-
if (format === "es" && platform === "node") return {
|
|
653
|
-
__dirname: [shimFile, "__dirname"],
|
|
654
|
-
__filename: [shimFile, "__filename"]
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
//#endregion
|
|
659
|
-
//#region src/features/shortcuts.ts
|
|
660
|
-
function shortcuts(restart) {
|
|
661
|
-
let actionRunning = false;
|
|
662
|
-
async function onInput(input) {
|
|
663
|
-
if (actionRunning) return;
|
|
664
|
-
const SHORTCUTS = [
|
|
665
|
-
{
|
|
666
|
-
key: "r",
|
|
667
|
-
description: "reload config and rebuild",
|
|
668
|
-
action() {
|
|
669
|
-
rl.close();
|
|
670
|
-
restart();
|
|
671
|
-
}
|
|
672
|
-
},
|
|
673
|
-
{
|
|
674
|
-
key: "c",
|
|
675
|
-
description: "clear console",
|
|
676
|
-
action() {
|
|
677
|
-
console.clear();
|
|
678
|
-
}
|
|
679
|
-
},
|
|
680
|
-
{
|
|
681
|
-
key: "q",
|
|
682
|
-
description: "quit",
|
|
683
|
-
action() {
|
|
684
|
-
process.exit(0);
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
];
|
|
688
|
-
if (input === "h") {
|
|
689
|
-
const loggedKeys = /* @__PURE__ */ new Set();
|
|
690
|
-
logger.info(" Shortcuts");
|
|
691
|
-
for (const shortcut$1 of SHORTCUTS) {
|
|
692
|
-
if (loggedKeys.has(shortcut$1.key)) continue;
|
|
693
|
-
loggedKeys.add(shortcut$1.key);
|
|
694
|
-
if (shortcut$1.action == null) continue;
|
|
695
|
-
logger.info(dim` press ` + bold`${shortcut$1.key} + enter` + dim` to ${shortcut$1.description}`);
|
|
696
|
-
}
|
|
697
|
-
return;
|
|
698
|
-
}
|
|
699
|
-
const shortcut = SHORTCUTS.find((shortcut$1) => shortcut$1.key === input);
|
|
700
|
-
if (!shortcut) return;
|
|
701
|
-
actionRunning = true;
|
|
702
|
-
await shortcut.action();
|
|
703
|
-
actionRunning = false;
|
|
704
|
-
}
|
|
705
|
-
const rl = readline.createInterface({ input: process.stdin });
|
|
706
|
-
rl.on("line", onInput);
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
//#endregion
|
|
710
|
-
//#region src/features/target.ts
|
|
711
|
-
function resolveTarget(target, pkg, name) {
|
|
712
|
-
if (target === false) return;
|
|
713
|
-
if (target == null) {
|
|
714
|
-
const pkgTarget = resolvePackageTarget(pkg);
|
|
715
|
-
if (pkgTarget) target = pkgTarget;
|
|
716
|
-
else return;
|
|
717
|
-
}
|
|
718
|
-
const targets = resolveComma(toArray(target));
|
|
719
|
-
if (targets.length) logger.info(prettyName(name), `target${targets.length > 1 ? "s" : ""}: ${generateColor(name)(targets.join(", "))}`);
|
|
720
|
-
return targets;
|
|
721
|
-
}
|
|
722
|
-
function resolvePackageTarget(pkg) {
|
|
723
|
-
const nodeVersion = pkg?.engines?.node;
|
|
724
|
-
if (!nodeVersion) return;
|
|
725
|
-
const nodeMinVersion = minVersion(nodeVersion);
|
|
726
|
-
if (!nodeMinVersion) return;
|
|
727
|
-
if (nodeMinVersion.version === "0.0.0") return;
|
|
728
|
-
return `node${nodeMinVersion.version}`;
|
|
729
|
-
}
|
|
730
|
-
let warned = false;
|
|
731
|
-
function RuntimeHelperCheckPlugin(targets) {
|
|
732
|
-
return {
|
|
733
|
-
name: "tsdown:runtime-helper-check",
|
|
734
|
-
resolveId: {
|
|
735
|
-
filter: { id: /^@oxc-project\/runtime/ },
|
|
736
|
-
async handler(id, ...args) {
|
|
737
|
-
const EXTERNAL = {
|
|
738
|
-
id,
|
|
739
|
-
external: true
|
|
740
|
-
};
|
|
741
|
-
if (warned) return EXTERNAL;
|
|
742
|
-
const resolved = await this.resolve(id, ...args);
|
|
743
|
-
if (!resolved) {
|
|
744
|
-
if (!warned) {
|
|
745
|
-
warned = true;
|
|
746
|
-
logger.warn(`The target environment (${targets.join(", ")}) requires runtime helpers from ${blue`@oxc-project/runtime`}. Please install it to ensure all necessary polyfills are included.\nFor more information, visit: https://tsdown.dev/options/target#runtime-helpers`);
|
|
747
|
-
}
|
|
748
|
-
return EXTERNAL;
|
|
749
|
-
}
|
|
750
|
-
return resolved;
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
};
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
//#endregion
|
|
757
|
-
//#region src/features/watch.ts
|
|
758
|
-
const endsWithConfig = /[\\/](?:package\.json|tsdown\.config.*)$/;
|
|
759
|
-
async function watchBuild(options, configFiles, rebuild, restart) {
|
|
760
|
-
if (typeof options.watch === "boolean" && options.outDir === options.cwd) throw new Error(`Watch is enabled, but output directory is the same as the current working directory.Please specify a different watch directory using ${blue`watch`} option,or set ${blue`outDir`} to a different directory.`);
|
|
761
|
-
const files = toArray(typeof options.watch === "boolean" ? options.cwd : options.watch);
|
|
762
|
-
logger.info(`Watching for changes in ${files.join(", ")}`);
|
|
763
|
-
files.push(...configFiles);
|
|
764
|
-
const { watch } = await import("chokidar");
|
|
765
|
-
const debouncedRebuild = debounce(rebuild, 100);
|
|
766
|
-
const watcher = watch(files, {
|
|
767
|
-
ignoreInitial: true,
|
|
768
|
-
ignorePermissionErrors: true,
|
|
769
|
-
ignored: [
|
|
770
|
-
/[\\/]\.git[\\/]/,
|
|
771
|
-
/[\\/]node_modules[\\/]/,
|
|
772
|
-
options.outDir,
|
|
773
|
-
...toArray(options.ignoreWatch)
|
|
774
|
-
]
|
|
775
|
-
});
|
|
776
|
-
watcher.on("all", (type, file) => {
|
|
777
|
-
if (configFiles.includes(file) || endsWithConfig.test(file)) {
|
|
778
|
-
logger.info(`Reload config: ${file}`);
|
|
779
|
-
restart();
|
|
780
|
-
return;
|
|
781
|
-
}
|
|
782
|
-
logger.info(`Change detected: ${type} ${file}`);
|
|
783
|
-
invalidateContextFile(globalContext, file);
|
|
784
|
-
debouncedRebuild();
|
|
785
|
-
});
|
|
786
|
-
return watcher;
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
//#endregion
|
|
790
|
-
//#region src/features/entry.ts
|
|
791
|
-
async function resolveEntry(entry, cwd, name) {
|
|
792
|
-
const nameLabel = name ? `[${name}] ` : "";
|
|
793
|
-
if (!entry || Object.keys(entry).length === 0) {
|
|
794
|
-
const defaultEntry = path.resolve(cwd, "src/index.ts");
|
|
795
|
-
if (await fsExists(defaultEntry)) entry = { index: defaultEntry };
|
|
796
|
-
else throw new Error(`${nameLabel}No input files, try "tsdown <your-file>" or create src/index.ts`);
|
|
797
|
-
}
|
|
798
|
-
const entryMap = await toObjectEntry(entry, cwd);
|
|
799
|
-
const entries = Object.values(entryMap);
|
|
800
|
-
if (entries.length === 0) throw new Error(`${nameLabel}Cannot find entry: ${JSON.stringify(entry)}`);
|
|
801
|
-
logger.info(prettyName(name), `entry: ${generateColor(name)(entries.map((entry$1) => path.relative(cwd, entry$1)).join(", "))}`);
|
|
802
|
-
return entryMap;
|
|
803
|
-
}
|
|
804
|
-
async function toObjectEntry(entry, cwd) {
|
|
805
|
-
if (typeof entry === "string") entry = [entry];
|
|
806
|
-
if (!Array.isArray(entry)) return entry;
|
|
807
|
-
const resolvedEntry = (await glob(entry, { cwd })).map((file) => path.resolve(cwd, file));
|
|
808
|
-
const base = lowestCommonAncestor(...resolvedEntry);
|
|
809
|
-
return Object.fromEntries(resolvedEntry.map((file) => {
|
|
810
|
-
const relative = path.relative(base, file);
|
|
811
|
-
return [relative.slice(0, relative.length - path.extname(relative).length), file];
|
|
812
|
-
}));
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
//#endregion
|
|
816
|
-
//#region src/features/tsconfig.ts
|
|
817
|
-
function findTsconfig(cwd, name = "tsconfig.json") {
|
|
818
|
-
return up$1(name, { cwd }) || false;
|
|
819
|
-
}
|
|
820
|
-
async function resolveTsconfig(tsconfig, cwd, name) {
|
|
821
|
-
const original = tsconfig;
|
|
822
|
-
if (tsconfig !== false) {
|
|
823
|
-
if (tsconfig === true || tsconfig == null) {
|
|
824
|
-
tsconfig = findTsconfig(cwd);
|
|
825
|
-
if (original && !tsconfig) logger.warn(`No tsconfig found in ${blue(cwd)}`);
|
|
826
|
-
} else {
|
|
827
|
-
const tsconfigPath = path.resolve(cwd, tsconfig);
|
|
828
|
-
const stat$1 = await fsStat(tsconfigPath);
|
|
829
|
-
if (stat$1?.isFile()) tsconfig = tsconfigPath;
|
|
830
|
-
else if (stat$1?.isDirectory()) {
|
|
831
|
-
tsconfig = findTsconfig(tsconfigPath);
|
|
832
|
-
if (!tsconfig) logger.warn(`No tsconfig found in ${blue(tsconfigPath)}`);
|
|
833
|
-
} else {
|
|
834
|
-
tsconfig = findTsconfig(cwd, tsconfig);
|
|
835
|
-
if (!tsconfig) logger.warn(`tsconfig ${blue(original)} doesn't exist`);
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
if (tsconfig) logger.info(prettyName(name), `tsconfig: ${generateColor(name)(path.relative(cwd, tsconfig))}`);
|
|
839
|
-
}
|
|
840
|
-
return tsconfig;
|
|
841
|
-
}
|
|
842
|
-
|
|
843
512
|
//#endregion
|
|
844
513
|
//#region src/options/config.ts
|
|
845
514
|
async function loadViteConfig(prefix, cwd) {
|
|
@@ -861,7 +530,7 @@ async function loadViteConfig(prefix, cwd) {
|
|
|
861
530
|
defaults: {}
|
|
862
531
|
});
|
|
863
532
|
if (!source) return;
|
|
864
|
-
|
|
533
|
+
globalLogger.info(`Using Vite config: ${underline(source)}`);
|
|
865
534
|
const resolved = await config;
|
|
866
535
|
if (typeof resolved === "function") return resolved({
|
|
867
536
|
command: "build",
|
|
@@ -921,7 +590,7 @@ async function loadConfigFile(options, workspace) {
|
|
|
921
590
|
config = toArray(config);
|
|
922
591
|
if (config.length === 0) config.push({});
|
|
923
592
|
const file = sources[0];
|
|
924
|
-
if (file)
|
|
593
|
+
if (file) globalLogger.info(`Using tsdown config: ${underline(file)}`);
|
|
925
594
|
return {
|
|
926
595
|
configs: config,
|
|
927
596
|
file
|
|
@@ -930,7 +599,7 @@ async function loadConfigFile(options, workspace) {
|
|
|
930
599
|
|
|
931
600
|
//#endregion
|
|
932
601
|
//#region src/options/index.ts
|
|
933
|
-
const debug =
|
|
602
|
+
const debug$4 = debug("tsdown:options");
|
|
934
603
|
const DEFAULT_EXCLUDE_WORKSPACE = [
|
|
935
604
|
"**/node_modules/**",
|
|
936
605
|
"**/dist/**",
|
|
@@ -938,21 +607,20 @@ const DEFAULT_EXCLUDE_WORKSPACE = [
|
|
|
938
607
|
"**/t?(e)mp/**"
|
|
939
608
|
];
|
|
940
609
|
async function resolveOptions(options) {
|
|
941
|
-
|
|
942
|
-
debug("options %O", options);
|
|
943
|
-
debug("loading config file: %s", options.config);
|
|
610
|
+
debug$4("options %O", options);
|
|
944
611
|
const { configs: rootConfigs, file } = await loadConfigFile(options);
|
|
612
|
+
const files = [];
|
|
945
613
|
if (file) {
|
|
946
614
|
files.push(file);
|
|
947
|
-
debug("loaded root config file %s", file);
|
|
948
|
-
debug("root configs %
|
|
949
|
-
} else debug("no root config file found");
|
|
615
|
+
debug$4("loaded root config file %s", file);
|
|
616
|
+
debug$4("root configs %O", rootConfigs);
|
|
617
|
+
} else debug$4("no root config file found");
|
|
950
618
|
const configs = (await Promise.all(rootConfigs.map(async (rootConfig) => {
|
|
951
619
|
const { configs: workspaceConfigs, files: workspaceFiles } = await resolveWorkspace(rootConfig, options);
|
|
952
620
|
if (workspaceFiles) files.push(...workspaceFiles);
|
|
953
621
|
return Promise.all(workspaceConfigs.filter((config) => !config.workspace || config.entry).map((config) => resolveConfig(config)));
|
|
954
622
|
}))).flat();
|
|
955
|
-
debug("resolved configs %O", configs);
|
|
623
|
+
debug$4("resolved configs %O", configs);
|
|
956
624
|
return {
|
|
957
625
|
configs,
|
|
958
626
|
files
|
|
@@ -994,16 +662,16 @@ async function resolveWorkspace(config, options) {
|
|
|
994
662
|
}
|
|
995
663
|
const files = [];
|
|
996
664
|
const configs = (await Promise.all(packages.map(async (cwd) => {
|
|
997
|
-
debug("loading workspace config %s", cwd);
|
|
665
|
+
debug$4("loading workspace config %s", cwd);
|
|
998
666
|
const { configs: configs$1, file } = await loadConfigFile({
|
|
999
667
|
...options,
|
|
1000
668
|
config: workspaceConfig,
|
|
1001
669
|
cwd
|
|
1002
670
|
}, cwd);
|
|
1003
671
|
if (file) {
|
|
1004
|
-
debug("loaded workspace config file %s", file);
|
|
672
|
+
debug$4("loaded workspace config file %s", file);
|
|
1005
673
|
files.push(file);
|
|
1006
|
-
} else debug("no workspace config file found in %s", cwd);
|
|
674
|
+
} else debug$4("no workspace config file found in %s", cwd);
|
|
1007
675
|
return configs$1.map((config$1) => ({
|
|
1008
676
|
...normalized,
|
|
1009
677
|
cwd,
|
|
@@ -1016,18 +684,21 @@ async function resolveWorkspace(config, options) {
|
|
|
1016
684
|
};
|
|
1017
685
|
}
|
|
1018
686
|
async function resolveConfig(userConfig) {
|
|
1019
|
-
let { entry, format = ["es"], plugins = [], clean = true, silent = false, treeshake = true, platform = "node", outDir = "dist", sourcemap = false, dts, unused = false, watch = false, ignoreWatch = [], shims = false, skipNodeModulesBundle = false, publint: publint$1 = false, attw: attw$1 = false, fromVite, alias, tsconfig, report = true, target, env = {}, copy: copy$1, publicDir, hash, cwd = process.cwd(), name, workspace, external, noExternal, exports = false, bundle, unbundle = typeof bundle === "boolean" ? !bundle : false, removeNodeProtocol, nodeProtocol } = userConfig;
|
|
1020
|
-
|
|
687
|
+
let { entry, format = ["es"], plugins = [], clean = true, silent = false, logLevel = silent ? "silent" : "info", failOnWarn = false, customLogger, treeshake = true, platform = "node", outDir = "dist", sourcemap = false, dts, unused = false, watch = false, ignoreWatch = [], shims = false, skipNodeModulesBundle = false, publint: publint$1 = false, attw: attw$1 = false, fromVite, alias, tsconfig, report = true, target, env = {}, copy: copy$1, publicDir, hash, cwd = process.cwd(), name, workspace, external, noExternal, exports = false, bundle, unbundle = typeof bundle === "boolean" ? !bundle : false, removeNodeProtocol, nodeProtocol, cjsDefault = true } = userConfig;
|
|
688
|
+
const logger = createLogger(logLevel, {
|
|
689
|
+
customLogger,
|
|
690
|
+
failOnWarn
|
|
691
|
+
});
|
|
1021
692
|
if (typeof bundle === "boolean") logger.warn("`bundle` option is deprecated. Use `unbundle` instead.");
|
|
1022
693
|
nodeProtocol = nodeProtocol ?? (removeNodeProtocol ? "strip" : false);
|
|
1023
694
|
outDir = path.resolve(cwd, outDir);
|
|
1024
695
|
clean = resolveClean(clean, outDir, cwd);
|
|
1025
696
|
const pkg = await readPackageJson(cwd);
|
|
1026
697
|
if (workspace) name ||= pkg?.name;
|
|
1027
|
-
entry = await resolveEntry(entry, cwd, name);
|
|
698
|
+
entry = await resolveEntry(logger, entry, cwd, name);
|
|
1028
699
|
if (dts == null) dts = !!(pkg?.types || pkg?.typings);
|
|
1029
|
-
target = resolveTarget(target, pkg, name);
|
|
1030
|
-
tsconfig = await resolveTsconfig(tsconfig, cwd, name);
|
|
700
|
+
target = resolveTarget(logger, target, pkg, name);
|
|
701
|
+
tsconfig = await resolveTsconfig(logger, tsconfig, cwd, name);
|
|
1031
702
|
if (typeof external === "string") external = resolveRegex(external);
|
|
1032
703
|
if (typeof noExternal === "string") noExternal = resolveRegex(noExternal);
|
|
1033
704
|
if (publint$1 === true) publint$1 = {};
|
|
@@ -1044,6 +715,11 @@ async function resolveConfig(userConfig) {
|
|
|
1044
715
|
if (viteAlias && !Array.isArray(viteAlias)) alias = viteAlias;
|
|
1045
716
|
}
|
|
1046
717
|
}
|
|
718
|
+
ignoreWatch = toArray(ignoreWatch).map((ignore) => {
|
|
719
|
+
ignore = resolveRegex(ignore);
|
|
720
|
+
if (typeof ignore === "string") return path.resolve(cwd, ignore);
|
|
721
|
+
return ignore;
|
|
722
|
+
});
|
|
1047
723
|
const config = {
|
|
1048
724
|
...userConfig,
|
|
1049
725
|
entry,
|
|
@@ -1052,7 +728,7 @@ async function resolveConfig(userConfig) {
|
|
|
1052
728
|
target,
|
|
1053
729
|
outDir,
|
|
1054
730
|
clean,
|
|
1055
|
-
|
|
731
|
+
logger,
|
|
1056
732
|
treeshake,
|
|
1057
733
|
platform,
|
|
1058
734
|
sourcemap,
|
|
@@ -1077,22 +753,279 @@ async function resolveConfig(userConfig) {
|
|
|
1077
753
|
noExternal,
|
|
1078
754
|
exports,
|
|
1079
755
|
unbundle,
|
|
1080
|
-
nodeProtocol
|
|
756
|
+
nodeProtocol,
|
|
757
|
+
cjsDefault
|
|
758
|
+
};
|
|
759
|
+
return config;
|
|
760
|
+
}
|
|
761
|
+
async function mergeUserOptions(defaults, user, args) {
|
|
762
|
+
const userOutputOptions = typeof user === "function" ? await user(defaults, ...args) : user;
|
|
763
|
+
return {
|
|
764
|
+
...defaults,
|
|
765
|
+
...userOutputOptions
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
//#endregion
|
|
770
|
+
//#region src/features/external.ts
|
|
771
|
+
const debug$3 = debug("tsdown:external");
|
|
772
|
+
function ExternalPlugin(options) {
|
|
773
|
+
const deps = options.pkg && Array.from(getProductionDeps(options.pkg));
|
|
774
|
+
return {
|
|
775
|
+
name: "tsdown:external",
|
|
776
|
+
async resolveId(id, importer, extraOptions) {
|
|
777
|
+
if (extraOptions.isEntry) return;
|
|
778
|
+
if (id === shimFile) return;
|
|
779
|
+
const { noExternal } = options;
|
|
780
|
+
if (typeof noExternal === "function" && noExternal(id, importer)) return;
|
|
781
|
+
if (noExternal) {
|
|
782
|
+
const noExternalPatterns = toArray(noExternal);
|
|
783
|
+
if (noExternalPatterns.some((pattern) => {
|
|
784
|
+
if (pattern instanceof RegExp) {
|
|
785
|
+
pattern.lastIndex = 0;
|
|
786
|
+
return pattern.test(id);
|
|
787
|
+
}
|
|
788
|
+
return id === pattern;
|
|
789
|
+
})) return;
|
|
790
|
+
}
|
|
791
|
+
let shouldExternal = false;
|
|
792
|
+
if (options.skipNodeModulesBundle) {
|
|
793
|
+
const resolved = await this.resolve(id, importer, extraOptions);
|
|
794
|
+
if (!resolved) return resolved;
|
|
795
|
+
shouldExternal = resolved.external || /[\\/]node_modules[\\/]/.test(resolved.id);
|
|
796
|
+
}
|
|
797
|
+
if (deps) shouldExternal ||= deps.some((dep) => id === dep || id.startsWith(`${dep}/`));
|
|
798
|
+
if (shouldExternal) {
|
|
799
|
+
debug$3("External dependency:", id);
|
|
800
|
+
return {
|
|
801
|
+
id,
|
|
802
|
+
external: shouldExternal,
|
|
803
|
+
moduleSideEffects: id.startsWith("node:") || builtinModules.includes(id) ? false : void 0
|
|
804
|
+
};
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
function getProductionDeps(pkg) {
|
|
810
|
+
return new Set([...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
//#endregion
|
|
814
|
+
//#region src/utils/lightningcss.ts
|
|
815
|
+
/**
|
|
816
|
+
* Converts esbuild target [^1] (which is also used by Rolldown [^2]) to Lightning CSS targets [^3].
|
|
817
|
+
*
|
|
818
|
+
* [^1]: https://esbuild.github.io/api/#target
|
|
819
|
+
* [^2]: https://github.com/rolldown/rolldown/blob/v1.0.0-beta.8/packages/rolldown/src/binding.d.ts#L1429-L1431
|
|
820
|
+
* [^3]: https://lightningcss.dev/transpilation.html
|
|
821
|
+
*/
|
|
822
|
+
function esbuildTargetToLightningCSS(target) {
|
|
823
|
+
let targets;
|
|
824
|
+
const targetString = target.join(" ").toLowerCase();
|
|
825
|
+
const matches = [...targetString.matchAll(TARGET_REGEX)];
|
|
826
|
+
for (const match of matches) {
|
|
827
|
+
const name = match[1];
|
|
828
|
+
const browser = ESBUILD_LIGHTNINGCSS_MAPPING[name];
|
|
829
|
+
if (!browser) continue;
|
|
830
|
+
const version = match[2];
|
|
831
|
+
const versionInt = parseVersion(version);
|
|
832
|
+
if (versionInt == null) continue;
|
|
833
|
+
targets = targets || {};
|
|
834
|
+
targets[browser] = versionInt;
|
|
835
|
+
}
|
|
836
|
+
return targets;
|
|
837
|
+
}
|
|
838
|
+
const TARGET_REGEX = /([a-z]+)(\d+(?:\.\d+)*)/g;
|
|
839
|
+
const ESBUILD_LIGHTNINGCSS_MAPPING = {
|
|
840
|
+
chrome: "chrome",
|
|
841
|
+
edge: "edge",
|
|
842
|
+
firefox: "firefox",
|
|
843
|
+
ie: "ie",
|
|
844
|
+
ios: "ios_saf",
|
|
845
|
+
opera: "opera",
|
|
846
|
+
safari: "safari"
|
|
847
|
+
};
|
|
848
|
+
function parseVersion(version) {
|
|
849
|
+
const [major, minor = 0, patch = 0] = version.split("-")[0].split(".").map((v) => Number.parseInt(v, 10));
|
|
850
|
+
if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch)) return null;
|
|
851
|
+
return major << 16 | minor << 8 | patch;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
//#endregion
|
|
855
|
+
//#region src/features/lightningcss.ts
|
|
856
|
+
async function LightningCSSPlugin(options) {
|
|
857
|
+
const LightningCSS = await import("unplugin-lightningcss/rolldown").catch(() => void 0);
|
|
858
|
+
if (!LightningCSS) return;
|
|
859
|
+
const targets = options.target && esbuildTargetToLightningCSS(options.target);
|
|
860
|
+
if (!targets) return;
|
|
861
|
+
return LightningCSS.default({ options: { targets } });
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
//#endregion
|
|
865
|
+
//#region src/features/node-protocol.ts
|
|
866
|
+
/**
|
|
867
|
+
* The `node:` protocol was added in Node.js v14.18.0.
|
|
868
|
+
* @see https://nodejs.org/api/esm.html#node-imports
|
|
869
|
+
*/
|
|
870
|
+
function NodeProtocolPlugin(nodeProtocolOption) {
|
|
871
|
+
if (nodeProtocolOption === "strip") return {
|
|
872
|
+
name: "tsdown:node-protocol:strip",
|
|
873
|
+
resolveId: {
|
|
874
|
+
order: "pre",
|
|
875
|
+
filter: { id: /^node:/ },
|
|
876
|
+
handler(id) {
|
|
877
|
+
return {
|
|
878
|
+
id: id.slice(5),
|
|
879
|
+
external: true,
|
|
880
|
+
moduleSideEffects: false
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
const builtinModulesRegex = /* @__PURE__ */ new RegExp(`^(${builtinModules.join("|")})$`);
|
|
886
|
+
return {
|
|
887
|
+
name: "tsdown:node-protocol:add",
|
|
888
|
+
resolveId: {
|
|
889
|
+
order: "pre",
|
|
890
|
+
filter: { id: builtinModulesRegex },
|
|
891
|
+
handler(id) {
|
|
892
|
+
return {
|
|
893
|
+
id: `node:${id}`,
|
|
894
|
+
external: true,
|
|
895
|
+
moduleSideEffects: false
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
//#endregion
|
|
903
|
+
//#region src/features/output.ts
|
|
904
|
+
function resolveJsOutputExtension(packageType, format, fixedExtension) {
|
|
905
|
+
switch (format) {
|
|
906
|
+
case "es": return !fixedExtension && packageType === "module" ? "js" : "mjs";
|
|
907
|
+
case "cjs": return fixedExtension || packageType === "module" ? "cjs" : "js";
|
|
908
|
+
default: return "js";
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
function resolveChunkFilename({ outExtensions, fixedExtension, pkg, hash }, inputOptions, format) {
|
|
912
|
+
const packageType = getPackageType(pkg);
|
|
913
|
+
let jsExtension;
|
|
914
|
+
let dtsExtension;
|
|
915
|
+
if (outExtensions) {
|
|
916
|
+
const { js, dts } = outExtensions({
|
|
917
|
+
options: inputOptions,
|
|
918
|
+
format,
|
|
919
|
+
pkgType: packageType
|
|
920
|
+
}) || {};
|
|
921
|
+
jsExtension = js;
|
|
922
|
+
dtsExtension = dts;
|
|
923
|
+
}
|
|
924
|
+
jsExtension ||= `.${resolveJsOutputExtension(packageType, format, fixedExtension)}`;
|
|
925
|
+
const suffix = format === "iife" || format === "umd" ? `.${format}` : "";
|
|
926
|
+
return [createChunkFilename(`[name]${suffix}`, jsExtension, dtsExtension), createChunkFilename(`[name]${suffix}${hash ? "-[hash]" : ""}`, jsExtension, dtsExtension)];
|
|
927
|
+
}
|
|
928
|
+
function createChunkFilename(basename, jsExtension, dtsExtension) {
|
|
929
|
+
if (!dtsExtension) return `${basename}${jsExtension}`;
|
|
930
|
+
return (chunk) => {
|
|
931
|
+
return `${basename}${chunk.name.endsWith(".d") ? dtsExtension : jsExtension}`;
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
function resolveChunkAddon(chunkAddon, format) {
|
|
935
|
+
if (!chunkAddon) return;
|
|
936
|
+
return (chunk) => {
|
|
937
|
+
if (typeof chunkAddon === "function") chunkAddon = chunkAddon({ format });
|
|
938
|
+
switch (true) {
|
|
939
|
+
case RE_JS.test(chunk.fileName): return chunkAddon?.js || "";
|
|
940
|
+
case RE_CSS.test(chunk.fileName): return chunkAddon?.css || "";
|
|
941
|
+
case RE_DTS.test(chunk.fileName): return chunkAddon?.dts || "";
|
|
942
|
+
default: return "";
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
//#endregion
|
|
948
|
+
//#region src/utils/format.ts
|
|
949
|
+
function formatBytes(bytes) {
|
|
950
|
+
if (bytes === Infinity) return void 0;
|
|
951
|
+
return `${(bytes / 1e3).toFixed(2)} kB`;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
//#endregion
|
|
955
|
+
//#region src/features/report.ts
|
|
956
|
+
const debug$2 = debug("tsdown:report");
|
|
957
|
+
const brotliCompressAsync = promisify(brotliCompress);
|
|
958
|
+
const gzipAsync = promisify(gzip);
|
|
959
|
+
function ReportPlugin(options, logger, cwd, cjsDts, name, isMultiFormat) {
|
|
960
|
+
return {
|
|
961
|
+
name: "tsdown:report",
|
|
962
|
+
async writeBundle(outputOptions, bundle) {
|
|
963
|
+
const outDir = path.relative(cwd, outputOptions.file ? path.resolve(cwd, outputOptions.file, "..") : path.resolve(cwd, outputOptions.dir));
|
|
964
|
+
const sizes = [];
|
|
965
|
+
for (const chunk of Object.values(bundle)) {
|
|
966
|
+
const size = await calcSize(options, chunk);
|
|
967
|
+
sizes.push(size);
|
|
968
|
+
}
|
|
969
|
+
const filenameLength = Math.max(...sizes.map((size) => size.filename.length));
|
|
970
|
+
const rawTextLength = Math.max(...sizes.map((size) => size.rawText.length));
|
|
971
|
+
const gzipTextLength = Math.max(...sizes.map((size) => size.gzipText == null ? 0 : size.gzipText.length));
|
|
972
|
+
const brotliTextLength = Math.max(...sizes.map((size) => size.brotliText == null ? 0 : size.brotliText.length));
|
|
973
|
+
let totalRaw = 0;
|
|
974
|
+
for (const size of sizes) {
|
|
975
|
+
size.rawText = size.rawText.padStart(rawTextLength);
|
|
976
|
+
size.gzipText = size.gzipText?.padStart(gzipTextLength);
|
|
977
|
+
size.brotliText = size.brotliText?.padStart(brotliTextLength);
|
|
978
|
+
totalRaw += size.raw;
|
|
979
|
+
}
|
|
980
|
+
sizes.sort((a, b) => {
|
|
981
|
+
if (a.dts !== b.dts) return a.dts ? 1 : -1;
|
|
982
|
+
if (a.isEntry !== b.isEntry) return a.isEntry ? -1 : 1;
|
|
983
|
+
return b.raw - a.raw;
|
|
984
|
+
});
|
|
985
|
+
const nameLabel = prettyName(name);
|
|
986
|
+
const formatLabel = isMultiFormat && prettyFormat(cjsDts ? "cjs" : outputOptions.format);
|
|
987
|
+
for (const size of sizes) {
|
|
988
|
+
const filenameColor = size.dts ? green : noop;
|
|
989
|
+
logger.info(nameLabel, formatLabel, dim(outDir + path.sep) + filenameColor((size.isEntry ? bold : noop)(size.filename)), ` `.repeat(filenameLength - size.filename.length), dim(size.rawText), size.gzipText && dim`│ gzip: ${size.gzipText}`, options.brotli && size.brotliText && dim`│ brotli: ${size.brotliText}`);
|
|
990
|
+
}
|
|
991
|
+
const totalSizeText = formatBytes(totalRaw);
|
|
992
|
+
logger.info(nameLabel, formatLabel, `${sizes.length} files, total: ${totalSizeText}`);
|
|
993
|
+
}
|
|
1081
994
|
};
|
|
1082
|
-
return config;
|
|
1083
995
|
}
|
|
1084
|
-
async function
|
|
1085
|
-
|
|
996
|
+
async function calcSize(options, chunk) {
|
|
997
|
+
debug$2(`Calculating size for`, chunk.fileName);
|
|
998
|
+
const content = chunk.type === "chunk" ? chunk.code : chunk.source;
|
|
999
|
+
const raw = Buffer.byteLength(content, "utf8");
|
|
1000
|
+
debug$2("[size]", chunk.fileName, raw);
|
|
1001
|
+
let gzip$1 = Infinity;
|
|
1002
|
+
let brotli = Infinity;
|
|
1003
|
+
if (raw > (options.maxCompressSize ?? 1e6)) debug$2(chunk.fileName, "file size exceeds limit, skip gzip/brotli");
|
|
1004
|
+
else {
|
|
1005
|
+
gzip$1 = (await gzipAsync(content)).length;
|
|
1006
|
+
debug$2("[gzip]", chunk.fileName, gzip$1);
|
|
1007
|
+
if (options.brotli) {
|
|
1008
|
+
brotli = (await brotliCompressAsync(content)).length;
|
|
1009
|
+
debug$2("[brotli]", chunk.fileName, brotli);
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1086
1012
|
return {
|
|
1087
|
-
|
|
1088
|
-
|
|
1013
|
+
filename: chunk.fileName,
|
|
1014
|
+
dts: RE_DTS.test(chunk.fileName),
|
|
1015
|
+
isEntry: chunk.type === "chunk" && chunk.isEntry,
|
|
1016
|
+
raw,
|
|
1017
|
+
rawText: formatBytes(raw),
|
|
1018
|
+
gzip: gzip$1,
|
|
1019
|
+
gzipText: formatBytes(gzip$1),
|
|
1020
|
+
brotli,
|
|
1021
|
+
brotliText: formatBytes(brotli)
|
|
1089
1022
|
};
|
|
1090
1023
|
}
|
|
1091
1024
|
|
|
1092
1025
|
//#endregion
|
|
1093
1026
|
//#region src/features/shebang.ts
|
|
1094
1027
|
const RE_SHEBANG = /^#!.*/;
|
|
1095
|
-
function ShebangPlugin(cwd, name, isMultiFormat) {
|
|
1028
|
+
function ShebangPlugin(logger, cwd, name, isMultiFormat) {
|
|
1096
1029
|
return {
|
|
1097
1030
|
name: "tsdown:shebang",
|
|
1098
1031
|
async writeBundle(options, bundle) {
|
|
@@ -1109,19 +1042,204 @@ function ShebangPlugin(cwd, name, isMultiFormat) {
|
|
|
1109
1042
|
};
|
|
1110
1043
|
}
|
|
1111
1044
|
|
|
1045
|
+
//#endregion
|
|
1046
|
+
//#region src/features/shims.ts
|
|
1047
|
+
function getShimsInject(format, platform) {
|
|
1048
|
+
if (format === "es" && platform === "node") return {
|
|
1049
|
+
__dirname: [shimFile, "__dirname"],
|
|
1050
|
+
__filename: [shimFile, "__filename"]
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
//#endregion
|
|
1055
|
+
//#region src/features/rolldown.ts
|
|
1056
|
+
const debug$1 = debug("tsdown:rolldown");
|
|
1057
|
+
async function getBuildOptions(config, format, isMultiFormat, cjsDts = false) {
|
|
1058
|
+
const inputOptions = await resolveInputOptions(config, format, cjsDts, isMultiFormat);
|
|
1059
|
+
const outputOptions = await resolveOutputOptions(inputOptions, config, format, cjsDts);
|
|
1060
|
+
const rolldownConfig = {
|
|
1061
|
+
...inputOptions,
|
|
1062
|
+
output: outputOptions
|
|
1063
|
+
};
|
|
1064
|
+
debug$1("rolldown config with format \"%s\" %O", cjsDts ? "cjs dts" : format, rolldownConfig);
|
|
1065
|
+
return rolldownConfig;
|
|
1066
|
+
}
|
|
1067
|
+
async function resolveInputOptions(config, format, cjsDts, isMultiFormat) {
|
|
1068
|
+
const { entry, external, plugins: userPlugins, platform, alias, treeshake, dts, unused, target, define, shims, tsconfig, cwd, report, env, nodeProtocol, loader, name, logger, cjsDefault } = config;
|
|
1069
|
+
const plugins = [];
|
|
1070
|
+
if (nodeProtocol) plugins.push(NodeProtocolPlugin(nodeProtocol));
|
|
1071
|
+
if (config.pkg || config.skipNodeModulesBundle) plugins.push(ExternalPlugin(config));
|
|
1072
|
+
if (dts) {
|
|
1073
|
+
const { dts: dtsPlugin } = await import("rolldown-plugin-dts");
|
|
1074
|
+
const options = {
|
|
1075
|
+
tsconfig,
|
|
1076
|
+
...dts
|
|
1077
|
+
};
|
|
1078
|
+
if (format === "es") plugins.push(dtsPlugin(options));
|
|
1079
|
+
else if (cjsDts) plugins.push(dtsPlugin({
|
|
1080
|
+
...options,
|
|
1081
|
+
emitDtsOnly: true,
|
|
1082
|
+
cjsDefault
|
|
1083
|
+
}));
|
|
1084
|
+
}
|
|
1085
|
+
if (!cjsDts) {
|
|
1086
|
+
if (unused) {
|
|
1087
|
+
const { Unused } = await import("unplugin-unused");
|
|
1088
|
+
plugins.push(Unused.rolldown(unused === true ? {} : unused));
|
|
1089
|
+
}
|
|
1090
|
+
if (target) plugins.push(RuntimeHelperCheckPlugin(logger, target), await LightningCSSPlugin({ target }));
|
|
1091
|
+
plugins.push(ShebangPlugin(logger, cwd, name, isMultiFormat));
|
|
1092
|
+
}
|
|
1093
|
+
if (report && LogLevels[logger.level] >= 3) plugins.push(ReportPlugin(report, logger, cwd, cjsDts, name, isMultiFormat));
|
|
1094
|
+
if (!cjsDts) plugins.push(userPlugins);
|
|
1095
|
+
const inputOptions = await mergeUserOptions({
|
|
1096
|
+
input: entry,
|
|
1097
|
+
cwd,
|
|
1098
|
+
external,
|
|
1099
|
+
resolve: {
|
|
1100
|
+
alias,
|
|
1101
|
+
tsconfigFilename: tsconfig || void 0
|
|
1102
|
+
},
|
|
1103
|
+
treeshake,
|
|
1104
|
+
platform: cjsDts || format === "cjs" ? "node" : platform,
|
|
1105
|
+
define: {
|
|
1106
|
+
...define,
|
|
1107
|
+
...Object.keys(env).reduce((acc, key) => {
|
|
1108
|
+
const value = JSON.stringify(env[key]);
|
|
1109
|
+
acc[`process.env.${key}`] = value;
|
|
1110
|
+
acc[`import.meta.env.${key}`] = value;
|
|
1111
|
+
return acc;
|
|
1112
|
+
}, Object.create(null))
|
|
1113
|
+
},
|
|
1114
|
+
transform: { target },
|
|
1115
|
+
plugins,
|
|
1116
|
+
inject: { ...shims && !cjsDts && getShimsInject(format, platform) },
|
|
1117
|
+
moduleTypes: loader,
|
|
1118
|
+
onLog: cjsDefault ? (level, log, defaultHandler) => {
|
|
1119
|
+
if (log.code === "MIXED_EXPORT") return;
|
|
1120
|
+
defaultHandler(level, log);
|
|
1121
|
+
} : void 0
|
|
1122
|
+
}, config.inputOptions, [format, { cjsDts }]);
|
|
1123
|
+
return inputOptions;
|
|
1124
|
+
}
|
|
1125
|
+
async function resolveOutputOptions(inputOptions, config, format, cjsDts) {
|
|
1126
|
+
const { entry, outDir, sourcemap, minify, unbundle, banner, footer, cjsDefault } = config;
|
|
1127
|
+
const [entryFileNames, chunkFileNames] = resolveChunkFilename(config, inputOptions, format);
|
|
1128
|
+
const outputOptions = await mergeUserOptions({
|
|
1129
|
+
format: cjsDts ? "es" : format,
|
|
1130
|
+
name: config.globalName,
|
|
1131
|
+
sourcemap,
|
|
1132
|
+
dir: outDir,
|
|
1133
|
+
exports: cjsDefault ? "auto" : "named",
|
|
1134
|
+
minify: !cjsDts && minify,
|
|
1135
|
+
entryFileNames,
|
|
1136
|
+
chunkFileNames,
|
|
1137
|
+
preserveModules: unbundle,
|
|
1138
|
+
preserveModulesRoot: unbundle ? lowestCommonAncestor(...Object.values(entry)) : void 0,
|
|
1139
|
+
banner: resolveChunkAddon(banner, format),
|
|
1140
|
+
footer: resolveChunkAddon(footer, format)
|
|
1141
|
+
}, config.outputOptions, [format, { cjsDts }]);
|
|
1142
|
+
return outputOptions;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
//#endregion
|
|
1146
|
+
//#region src/features/shortcuts.ts
|
|
1147
|
+
function shortcuts(restart) {
|
|
1148
|
+
let actionRunning = false;
|
|
1149
|
+
async function onInput(input) {
|
|
1150
|
+
if (actionRunning) return;
|
|
1151
|
+
const SHORTCUTS = [
|
|
1152
|
+
{
|
|
1153
|
+
key: "r",
|
|
1154
|
+
description: "reload config and rebuild",
|
|
1155
|
+
action() {
|
|
1156
|
+
rl.close();
|
|
1157
|
+
restart();
|
|
1158
|
+
}
|
|
1159
|
+
},
|
|
1160
|
+
{
|
|
1161
|
+
key: "c",
|
|
1162
|
+
description: "clear console",
|
|
1163
|
+
action() {
|
|
1164
|
+
console.clear();
|
|
1165
|
+
}
|
|
1166
|
+
},
|
|
1167
|
+
{
|
|
1168
|
+
key: "q",
|
|
1169
|
+
description: "quit",
|
|
1170
|
+
action() {
|
|
1171
|
+
process.exit(0);
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
];
|
|
1175
|
+
if (input === "h") {
|
|
1176
|
+
const loggedKeys = /* @__PURE__ */ new Set();
|
|
1177
|
+
globalLogger.info(" Shortcuts");
|
|
1178
|
+
for (const shortcut$1 of SHORTCUTS) {
|
|
1179
|
+
if (loggedKeys.has(shortcut$1.key)) continue;
|
|
1180
|
+
loggedKeys.add(shortcut$1.key);
|
|
1181
|
+
if (shortcut$1.action == null) continue;
|
|
1182
|
+
globalLogger.info(dim` press ` + bold`${shortcut$1.key} + enter` + dim` to ${shortcut$1.description}`);
|
|
1183
|
+
}
|
|
1184
|
+
return;
|
|
1185
|
+
}
|
|
1186
|
+
const shortcut = SHORTCUTS.find((shortcut$1) => shortcut$1.key === input);
|
|
1187
|
+
if (!shortcut) return;
|
|
1188
|
+
actionRunning = true;
|
|
1189
|
+
await shortcut.action();
|
|
1190
|
+
actionRunning = false;
|
|
1191
|
+
}
|
|
1192
|
+
const rl = readline.createInterface({ input: process.stdin });
|
|
1193
|
+
rl.on("line", onInput);
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
//#endregion
|
|
1197
|
+
//#region src/features/watch.ts
|
|
1198
|
+
const endsWithConfig = /[\\/](?:package\.json|tsdown\.config.*)$/;
|
|
1199
|
+
async function watchBuild(options, configFiles, rebuild, restart) {
|
|
1200
|
+
if (typeof options.watch === "boolean" && options.outDir === options.cwd) throw new Error(`Watch is enabled, but output directory is the same as the current working directory.Please specify a different watch directory using ${blue`watch`} option,or set ${blue`outDir`} to a different directory.`);
|
|
1201
|
+
const files = toArray(typeof options.watch === "boolean" ? options.cwd : options.watch);
|
|
1202
|
+
options.logger.info(`Watching for changes in ${files.join(", ")}`);
|
|
1203
|
+
files.push(...configFiles);
|
|
1204
|
+
const { watch } = await import("chokidar");
|
|
1205
|
+
const debouncedRebuild = debounce(rebuild, 100);
|
|
1206
|
+
const watcher = watch(files, {
|
|
1207
|
+
ignoreInitial: true,
|
|
1208
|
+
ignorePermissionErrors: true,
|
|
1209
|
+
ignored: [
|
|
1210
|
+
/[\\/]\.git[\\/]/,
|
|
1211
|
+
/[\\/]node_modules[\\/]/,
|
|
1212
|
+
options.outDir,
|
|
1213
|
+
...options.ignoreWatch
|
|
1214
|
+
]
|
|
1215
|
+
});
|
|
1216
|
+
watcher.on("all", (type, file) => {
|
|
1217
|
+
if (configFiles.includes(file) || endsWithConfig.test(file)) {
|
|
1218
|
+
options.logger.info(`Reload config: ${file}`);
|
|
1219
|
+
restart();
|
|
1220
|
+
return;
|
|
1221
|
+
}
|
|
1222
|
+
options.logger.info(`Change detected: ${type} ${file}`);
|
|
1223
|
+
invalidateContextFile(globalContext, file);
|
|
1224
|
+
debouncedRebuild();
|
|
1225
|
+
});
|
|
1226
|
+
return watcher;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1112
1229
|
//#endregion
|
|
1113
1230
|
//#region src/index.ts
|
|
1114
1231
|
/**
|
|
1115
1232
|
* Build with tsdown.
|
|
1116
1233
|
*/
|
|
1117
1234
|
async function build$1(userOptions = {}) {
|
|
1235
|
+
globalLogger.level = userOptions.logLevel || (userOptions.silent ? "silent" : "info");
|
|
1118
1236
|
const { configs, files: configFiles } = await resolveOptions(userOptions);
|
|
1119
1237
|
let cleanPromise;
|
|
1120
1238
|
const clean = () => {
|
|
1121
1239
|
if (cleanPromise) return cleanPromise;
|
|
1122
1240
|
return cleanPromise = cleanOutDir(configs);
|
|
1123
1241
|
};
|
|
1124
|
-
|
|
1242
|
+
globalLogger.info("Build start");
|
|
1125
1243
|
const rebuilds = await Promise.all(configs.map((options) => buildSingle(options, clean)));
|
|
1126
1244
|
const disposeCbs = [];
|
|
1127
1245
|
for (const [i, config] of configs.entries()) {
|
|
@@ -1149,9 +1267,10 @@ const shimFile = path.resolve(pkgRoot, "esm-shims.js");
|
|
|
1149
1267
|
* @param config Resolved options
|
|
1150
1268
|
*/
|
|
1151
1269
|
async function buildSingle(config, clean) {
|
|
1152
|
-
const { format: formats, dts, watch, onSuccess } = config;
|
|
1270
|
+
const { format: formats, dts, watch, onSuccess, logger } = config;
|
|
1153
1271
|
let ab;
|
|
1154
1272
|
const { hooks, context } = await createHooks$1(config);
|
|
1273
|
+
warnLegacyCJS(config);
|
|
1155
1274
|
await rebuild(true);
|
|
1156
1275
|
if (watch) return () => rebuild();
|
|
1157
1276
|
async function rebuild(first) {
|
|
@@ -1205,77 +1324,6 @@ async function buildSingle(config, clean) {
|
|
|
1205
1324
|
} else await onSuccess?.(config, ab.signal);
|
|
1206
1325
|
}
|
|
1207
1326
|
}
|
|
1208
|
-
async function getBuildOptions(config, format, isMultiFormat, cjsDts) {
|
|
1209
|
-
const { entry, external, plugins: userPlugins, outDir, platform, alias, treeshake, sourcemap, dts, minify, unused, target, define, shims, tsconfig, cwd, report, env, nodeProtocol, loader, name, unbundle, banner, footer } = config;
|
|
1210
|
-
const plugins = [];
|
|
1211
|
-
if (nodeProtocol) plugins.push(NodeProtocolPlugin(nodeProtocol));
|
|
1212
|
-
if (config.pkg || config.skipNodeModulesBundle) plugins.push(ExternalPlugin(config));
|
|
1213
|
-
if (dts) {
|
|
1214
|
-
const { dts: dtsPlugin } = await import("rolldown-plugin-dts");
|
|
1215
|
-
const options = {
|
|
1216
|
-
tsconfig,
|
|
1217
|
-
...dts
|
|
1218
|
-
};
|
|
1219
|
-
if (format === "es") plugins.push(dtsPlugin(options));
|
|
1220
|
-
else if (cjsDts) plugins.push(dtsPlugin({
|
|
1221
|
-
...options,
|
|
1222
|
-
emitDtsOnly: true
|
|
1223
|
-
}));
|
|
1224
|
-
}
|
|
1225
|
-
if (!cjsDts) {
|
|
1226
|
-
if (unused) {
|
|
1227
|
-
const { Unused } = await import("unplugin-unused");
|
|
1228
|
-
plugins.push(Unused.rolldown(unused === true ? {} : unused));
|
|
1229
|
-
}
|
|
1230
|
-
if (target) plugins.push(RuntimeHelperCheckPlugin(target), await LightningCSSPlugin({ target }));
|
|
1231
|
-
plugins.push(ShebangPlugin(cwd, name, isMultiFormat));
|
|
1232
|
-
}
|
|
1233
|
-
if (report && !logger.silent) plugins.push(ReportPlugin(report, cwd, cjsDts, name, isMultiFormat));
|
|
1234
|
-
if (!cjsDts) plugins.push(userPlugins);
|
|
1235
|
-
cjsDts = !!cjsDts;
|
|
1236
|
-
const inputOptions = await mergeUserOptions({
|
|
1237
|
-
input: entry,
|
|
1238
|
-
cwd,
|
|
1239
|
-
external,
|
|
1240
|
-
resolve: {
|
|
1241
|
-
alias,
|
|
1242
|
-
tsconfigFilename: tsconfig || void 0
|
|
1243
|
-
},
|
|
1244
|
-
treeshake,
|
|
1245
|
-
platform: cjsDts || format === "cjs" ? "node" : platform,
|
|
1246
|
-
define: {
|
|
1247
|
-
...define,
|
|
1248
|
-
...Object.keys(env).reduce((acc, key) => {
|
|
1249
|
-
const value = JSON.stringify(env[key]);
|
|
1250
|
-
acc[`process.env.${key}`] = value;
|
|
1251
|
-
acc[`import.meta.env.${key}`] = value;
|
|
1252
|
-
return acc;
|
|
1253
|
-
}, Object.create(null))
|
|
1254
|
-
},
|
|
1255
|
-
transform: { target },
|
|
1256
|
-
plugins,
|
|
1257
|
-
inject: { ...shims && !cjsDts && getShimsInject(format, platform) },
|
|
1258
|
-
moduleTypes: loader
|
|
1259
|
-
}, config.inputOptions, [format, { cjsDts }]);
|
|
1260
|
-
const [entryFileNames, chunkFileNames] = resolveChunkFilename(config, inputOptions, format);
|
|
1261
|
-
const outputOptions = await mergeUserOptions({
|
|
1262
|
-
format: cjsDts ? "es" : format,
|
|
1263
|
-
name: config.globalName,
|
|
1264
|
-
sourcemap,
|
|
1265
|
-
dir: outDir,
|
|
1266
|
-
minify: !cjsDts && minify,
|
|
1267
|
-
entryFileNames,
|
|
1268
|
-
chunkFileNames,
|
|
1269
|
-
preserveModules: unbundle,
|
|
1270
|
-
preserveModulesRoot: unbundle ? lowestCommonAncestor(...Object.values(entry)) : void 0,
|
|
1271
|
-
banner: resolveChunkAddon(banner, format),
|
|
1272
|
-
footer: resolveChunkAddon(footer, format)
|
|
1273
|
-
}, config.outputOptions, [format, { cjsDts }]);
|
|
1274
|
-
return {
|
|
1275
|
-
...inputOptions,
|
|
1276
|
-
output: outputOptions
|
|
1277
|
-
};
|
|
1278
|
-
}
|
|
1279
1327
|
|
|
1280
1328
|
//#endregion
|
|
1281
1329
|
export { ExternalPlugin, NodeProtocolPlugin, ReportPlugin, ShebangPlugin, build$1 as build, buildSingle, shimFile };
|