2021-05-15 20:09:52 +08:00
|
|
|
#!/usr/bin/env node
|
2017-06-28 22:34:59 +02:00
|
|
|
|
2021-05-15 20:09:52 +08:00
|
|
|
import fs from "node:fs/promises";
|
2023-12-17 19:34:12 +00:00
|
|
|
import path from "node:path";
|
2021-05-15 20:09:52 +08:00
|
|
|
import readline from "node:readline";
|
2022-02-07 12:00:43 +08:00
|
|
|
import createEsmUtils from "esm-utils";
|
2025-01-23 14:26:54 +08:00
|
|
|
import styleText from "node-style-text";
|
2023-12-17 19:34:12 +00:00
|
|
|
import prettyBytes from "pretty-bytes";
|
2025-05-27 09:35:31 +08:00
|
|
|
import prettyMilliseconds from "pretty-ms";
|
2023-03-28 16:18:53 +08:00
|
|
|
import { DIST_DIR } from "../utils/index.js";
|
2025-05-27 09:35:31 +08:00
|
|
|
import packageConfigs from "./config.js";
|
2023-08-23 15:15:25 +08:00
|
|
|
import parseArguments from "./parse-arguments.js";
|
2017-06-28 22:34:59 +02:00
|
|
|
|
2022-02-07 12:00:43 +08:00
|
|
|
const { require } = createEsmUtils(import.meta);
|
|
|
|
|
|
2020-10-26 09:44:09 +08:00
|
|
|
const statusConfig = [
|
|
|
|
|
{ color: "bgGreen", text: "DONE" },
|
|
|
|
|
{ color: "bgRed", text: "FAIL" },
|
|
|
|
|
{ color: "bgGray", text: "SKIPPED" },
|
|
|
|
|
];
|
|
|
|
|
const maxLength = Math.max(...statusConfig.map(({ text }) => text.length)) + 2;
|
|
|
|
|
const padStatusText = (text) => {
|
|
|
|
|
while (text.length < maxLength) {
|
|
|
|
|
text = text.length % 2 ? `${text} ` : ` ${text}`;
|
|
|
|
|
}
|
|
|
|
|
return text;
|
|
|
|
|
};
|
|
|
|
|
const status = {};
|
|
|
|
|
for (const { color, text } of statusConfig) {
|
2025-01-23 14:26:54 +08:00
|
|
|
status[text] = styleText[color].black(padStatusText(text));
|
2020-10-26 09:44:09 +08:00
|
|
|
}
|
2018-05-29 14:59:57 -03:00
|
|
|
|
2020-12-16 08:45:29 +09:00
|
|
|
function fitTerminal(input, suffix = "") {
|
2018-06-14 11:15:04 -03:00
|
|
|
const columns = Math.min(process.stdout.columns || 40, 80);
|
2020-10-26 09:44:09 +08:00
|
|
|
const WIDTH = columns - maxLength + 1;
|
2018-05-29 14:59:57 -03:00
|
|
|
if (input.length < WIDTH) {
|
2022-02-07 12:00:43 +08:00
|
|
|
const repeatCount = Math.max(WIDTH - input.length - 1 - suffix.length, 0);
|
2025-01-23 14:26:54 +08:00
|
|
|
input += styleText.dim(".").repeat(repeatCount) + suffix;
|
2018-05-24 15:30:45 -03:00
|
|
|
}
|
2018-05-29 14:59:57 -03:00
|
|
|
return input;
|
2017-06-28 22:34:59 +02:00
|
|
|
}
|
|
|
|
|
|
2022-01-27 09:37:55 +08:00
|
|
|
const clear = () => {
|
|
|
|
|
readline.clearLine(process.stdout, 0);
|
|
|
|
|
readline.cursorTo(process.stdout, 0, null);
|
|
|
|
|
};
|
|
|
|
|
|
2025-04-09 08:38:46 +08:00
|
|
|
async function buildFile({ packageConfig, file, cliOptions, results }) {
|
|
|
|
|
const { distDirectory } = packageConfig;
|
2022-09-25 11:50:59 +08:00
|
|
|
let displayName = file.output.file;
|
|
|
|
|
if (
|
|
|
|
|
(file.platform === "universal" && file.output.format !== "esm") ||
|
2023-02-23 22:15:18 +09:00
|
|
|
(file.output.file.startsWith("index.") && file.output.format !== "esm") ||
|
2025-11-25 02:13:03 +08:00
|
|
|
file.output.file.endsWith(".browser.mjs") ||
|
2023-02-23 22:15:18 +09:00
|
|
|
file.kind === "types"
|
2022-09-25 11:50:59 +08:00
|
|
|
) {
|
|
|
|
|
displayName = ` ${displayName}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
process.stdout.write(fitTerminal(displayName));
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
(cliOptions.files && !cliOptions.files.has(file.output.file)) ||
|
2025-05-29 15:30:45 +08:00
|
|
|
(cliOptions.playground && !file.playground)
|
2022-09-25 11:50:59 +08:00
|
|
|
) {
|
|
|
|
|
console.log(status.SKIPPED);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let result;
|
2020-06-12 06:42:42 +05:30
|
|
|
try {
|
2025-04-09 08:38:46 +08:00
|
|
|
result = await file.build({ packageConfig, file, cliOptions, results });
|
2020-06-12 06:42:42 +05:30
|
|
|
} catch (error) {
|
2020-10-26 09:44:09 +08:00
|
|
|
console.log(status.FAIL + "\n");
|
2022-04-03 01:42:20 +08:00
|
|
|
console.error(error);
|
|
|
|
|
throw error;
|
2020-06-12 06:42:42 +05:30
|
|
|
}
|
2022-09-25 11:50:59 +08:00
|
|
|
|
2024-07-02 10:01:15 +08:00
|
|
|
result ??= {};
|
2022-10-06 15:20:19 +08:00
|
|
|
|
2022-09-25 11:50:59 +08:00
|
|
|
if (result.skipped) {
|
|
|
|
|
console.log(status.SKIPPED);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-02 10:01:15 +08:00
|
|
|
const outputFile = cliOptions.saveAs ?? file.output.file;
|
|
|
|
|
|
2022-09-25 11:50:59 +08:00
|
|
|
const sizeMessages = [];
|
|
|
|
|
if (cliOptions.printSize) {
|
2025-04-09 08:38:46 +08:00
|
|
|
const { size } = await fs.stat(path.join(distDirectory, outputFile));
|
2022-09-25 11:50:59 +08:00
|
|
|
sizeMessages.push(prettyBytes(size));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cliOptions.compareSize) {
|
|
|
|
|
// TODO: Use `import.meta.resolve` when Node.js support
|
|
|
|
|
const stablePrettierDirectory = path.dirname(require.resolve("prettier"));
|
2024-07-02 10:01:15 +08:00
|
|
|
const stableVersionFile = path.join(stablePrettierDirectory, outputFile);
|
2022-09-25 11:50:59 +08:00
|
|
|
let stableSize;
|
|
|
|
|
try {
|
|
|
|
|
({ size: stableSize } = await fs.stat(stableVersionFile));
|
|
|
|
|
} catch {
|
|
|
|
|
// No op
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (stableSize) {
|
2025-04-09 08:38:46 +08:00
|
|
|
const { size } = await fs.stat(path.join(distDirectory, outputFile));
|
2022-09-25 11:50:59 +08:00
|
|
|
const sizeDiff = size - stableSize;
|
2025-01-23 14:26:54 +08:00
|
|
|
const message = styleText[sizeDiff > 0 ? "yellow" : "green"](
|
2022-09-25 11:50:59 +08:00
|
|
|
prettyBytes(sizeDiff),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
sizeMessages.push(`${message}`);
|
|
|
|
|
} else {
|
2025-01-23 14:26:54 +08:00
|
|
|
sizeMessages.push(styleText.blue("[NEW FILE]"));
|
2022-09-25 11:50:59 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sizeMessages.length > 0) {
|
|
|
|
|
// Clear previous line
|
|
|
|
|
clear();
|
|
|
|
|
process.stdout.write(
|
|
|
|
|
fitTerminal(displayName, `${sizeMessages.join(", ")} `),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log(status.DONE);
|
2024-07-02 10:01:15 +08:00
|
|
|
|
|
|
|
|
return result;
|
2018-05-24 15:30:45 -03:00
|
|
|
}
|
|
|
|
|
|
2023-08-23 15:15:25 +08:00
|
|
|
async function run() {
|
|
|
|
|
const cliOptions = parseArguments();
|
2022-01-27 09:37:55 +08:00
|
|
|
|
2025-05-27 09:35:31 +08:00
|
|
|
let packagesToBuild = [];
|
|
|
|
|
if (cliOptions.packages) {
|
|
|
|
|
for (const packageName of cliOptions.packages) {
|
|
|
|
|
const packageConfig = packageConfigs.find(
|
|
|
|
|
(packageConfig) => packageConfig.packageName === packageName,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!packageConfig) {
|
|
|
|
|
throw new Error(`Unknown package "${packageName}"`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
packagesToBuild.push(packageConfig);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
packagesToBuild = packageConfigs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Clear package dist directory instead
|
2022-09-25 11:50:59 +08:00
|
|
|
if (cliOptions.clean) {
|
2022-02-02 10:23:51 +08:00
|
|
|
let stat;
|
|
|
|
|
try {
|
|
|
|
|
stat = await fs.stat(DIST_DIR);
|
|
|
|
|
} catch {
|
|
|
|
|
// No op
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (stat) {
|
|
|
|
|
if (stat.isDirectory()) {
|
|
|
|
|
await fs.rm(DIST_DIR, { recursive: true, force: true });
|
|
|
|
|
} else {
|
|
|
|
|
throw new Error(`"${DIST_DIR}" is not a directory`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-27 09:35:31 +08:00
|
|
|
for (const [index, packageConfig] of packagesToBuild.entries()) {
|
|
|
|
|
if (index > 0) {
|
|
|
|
|
console.log();
|
|
|
|
|
}
|
2021-09-09 12:23:53 +08:00
|
|
|
|
2025-05-27 09:35:31 +08:00
|
|
|
console.log(
|
2025-10-14 19:30:07 +08:00
|
|
|
styleText.inverse`[${index + 1}/${packagesToBuild.length}] Building package '${packageConfig.packageName}'`,
|
2025-05-27 09:35:31 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const startTime = performance.now();
|
|
|
|
|
const results = [];
|
|
|
|
|
for (const file of packageConfig.files) {
|
|
|
|
|
const result = await buildFile({
|
|
|
|
|
packageConfig,
|
|
|
|
|
file,
|
|
|
|
|
cliOptions,
|
|
|
|
|
results,
|
|
|
|
|
});
|
|
|
|
|
results.push(result);
|
|
|
|
|
}
|
|
|
|
|
console.log(
|
|
|
|
|
`Build package '${packageConfig.packageName}' success in ${prettyMilliseconds(performance.now() - startTime)}`,
|
|
|
|
|
);
|
2021-12-02 19:47:14 +08:00
|
|
|
}
|
2018-05-24 15:30:45 -03:00
|
|
|
}
|
|
|
|
|
|
2023-08-23 15:15:25 +08:00
|
|
|
await run();
|