mirror of
https://github.com/JimLiu/baoyu-skills.git
synced 2026-07-09 20:51:22 +00:00
168 lines
4.6 KiB
JavaScript
168 lines
4.6 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import { spawnSync } from "node:child_process";
|
|
import fs from "node:fs/promises";
|
|
import path from "node:path";
|
|
import process from "node:process";
|
|
import { pathToFileURL } from "node:url";
|
|
|
|
async function main() {
|
|
const options = parseArgs(process.argv.slice(2));
|
|
const packageDir = path.resolve(options.packageDir);
|
|
const entryPath = path.resolve(packageDir, options.entry);
|
|
const outDir = path.resolve(packageDir, options.outDir);
|
|
|
|
await fs.rm(outDir, { recursive: true, force: true });
|
|
await fs.mkdir(outDir, { recursive: true });
|
|
|
|
const bun = resolveBunRuntime();
|
|
runBuild(bun, {
|
|
entryPath,
|
|
external: options.external,
|
|
format: "esm",
|
|
outfile: path.join(outDir, "index.js"),
|
|
});
|
|
const cjsOutfile = path.join(outDir, "index.cjs");
|
|
runBuild(bun, {
|
|
entryPath,
|
|
external: options.external,
|
|
format: "cjs",
|
|
outfile: cjsOutfile,
|
|
});
|
|
await scrubCommonJsSourceFileUrls(cjsOutfile, packageDir);
|
|
|
|
for (const asset of options.assets) {
|
|
const source = path.resolve(packageDir, asset.source);
|
|
const target = path.resolve(outDir, asset.target);
|
|
await fs.cp(source, target, { recursive: true });
|
|
}
|
|
}
|
|
|
|
function parseArgs(argv) {
|
|
const options = {
|
|
packageDir: process.cwd(),
|
|
entry: "src/index.ts",
|
|
outDir: "dist",
|
|
external: [],
|
|
assets: [],
|
|
};
|
|
|
|
for (let index = 0; index < argv.length; index += 1) {
|
|
const arg = argv[index];
|
|
if (arg === "--package-dir") {
|
|
options.packageDir = readArgValue(argv, ++index, arg);
|
|
continue;
|
|
}
|
|
if (arg === "--entry") {
|
|
options.entry = readArgValue(argv, ++index, arg);
|
|
continue;
|
|
}
|
|
if (arg === "--out-dir") {
|
|
options.outDir = readArgValue(argv, ++index, arg);
|
|
continue;
|
|
}
|
|
if (arg === "--external") {
|
|
options.external.push(readArgValue(argv, ++index, arg));
|
|
continue;
|
|
}
|
|
if (arg === "--asset") {
|
|
options.assets.push(parseAssetArg(readArgValue(argv, ++index, arg)));
|
|
continue;
|
|
}
|
|
if (arg === "-h" || arg === "--help") {
|
|
printUsage();
|
|
process.exit(0);
|
|
}
|
|
throw new Error(`Unknown argument: ${arg}`);
|
|
}
|
|
|
|
return options;
|
|
}
|
|
|
|
function readArgValue(argv, index, flag) {
|
|
const value = argv[index];
|
|
if (!value) {
|
|
throw new Error(`${flag} requires a value`);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function parseAssetArg(value) {
|
|
const [source, target = path.basename(value)] = value.split(":");
|
|
if (!source) {
|
|
throw new Error(`Invalid --asset value: ${value}`);
|
|
}
|
|
return { source, target };
|
|
}
|
|
|
|
function resolveBunRuntime() {
|
|
if (process.versions.bun) {
|
|
return { command: process.execPath, args: [] };
|
|
}
|
|
if (commandExists("bun")) {
|
|
return { command: "bun", args: [] };
|
|
}
|
|
if (commandExists("npx")) {
|
|
return { command: "npx", args: ["-y", "bun"] };
|
|
}
|
|
throw new Error(
|
|
"Neither bun nor npx is installed. Install bun with `brew install oven-sh/bun/bun` or `npm install -g bun`.",
|
|
);
|
|
}
|
|
|
|
function commandExists(command) {
|
|
const result = spawnSync("sh", ["-lc", `command -v ${command}`], {
|
|
stdio: "ignore",
|
|
});
|
|
return result.status === 0;
|
|
}
|
|
|
|
function runBuild(runtime, { entryPath, external, format, outfile }) {
|
|
const args = [
|
|
...runtime.args,
|
|
"build",
|
|
entryPath,
|
|
"--target=node",
|
|
`--format=${format}`,
|
|
...external.flatMap((name) => ["--external", name]),
|
|
"--outfile",
|
|
outfile,
|
|
];
|
|
const result = spawnSync(runtime.command, args, {
|
|
cwd: process.cwd(),
|
|
stdio: "inherit",
|
|
});
|
|
|
|
if (result.status !== 0) {
|
|
throw new Error(`Failed to build ${format.toUpperCase()} package output`);
|
|
}
|
|
}
|
|
|
|
async function scrubCommonJsSourceFileUrls(outfile, packageDir) {
|
|
const packageUrl = pathToFileURL(packageDir).href;
|
|
const packageFileUrlPattern = new RegExp(`"${escapeRegExp(packageUrl)}/[^"]+"`, "g");
|
|
const source = await fs.readFile(outfile, "utf8");
|
|
await fs.writeFile(outfile, source.replace(packageFileUrlPattern, "undefined"));
|
|
}
|
|
|
|
function escapeRegExp(value) {
|
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
}
|
|
|
|
function printUsage() {
|
|
console.log(`Usage: build-shared-package.mjs [options]
|
|
|
|
Options:
|
|
--package-dir <dir> Package root (default: current directory)
|
|
--entry <file> Entry file relative to package root (default: src/index.ts)
|
|
--out-dir <dir> Output directory relative to package root (default: dist)
|
|
--external <name> Leave a module external (can be repeated)
|
|
--asset <src[:dst]> Copy an asset directory/file into out-dir (can be repeated)
|
|
-h, --help Show help`);
|
|
}
|
|
|
|
main().catch((error) => {
|
|
console.error(error instanceof Error ? error.message : String(error));
|
|
process.exit(1);
|
|
});
|