rsnext/packages/next-swc/crates/next-core/js/build.mjs
2022-12-13 00:38:21 +01:00

162 lines
4.1 KiB
JavaScript

/**
* Build npm package to be able to embed them in the binary
*/
import { mkdir, writeFile, rm, readFile } from "node:fs/promises";
import { existsSync } from "node:fs";
import { createRequire } from "node:module";
import { join, dirname, basename, extname } from "node:path";
import { fileURLToPath } from "node:url";
import ncc from "@vercel/ncc";
import { findUp } from "find-up";
const __dirname = dirname(fileURLToPath(import.meta.url));
const require = createRequire(import.meta.url);
/**
* @type {{
* name: string;
* type: "cjs" | "module" | "module-default";
* types?: string;
* }[]}
*/
const packages = [
{
name: "anser",
type: "cjs",
},
{
name: "css.escape",
type: "cjs",
types: "export = CSS.escape;",
},
{
name: "platform",
type: "cjs",
},
{
name: "source-map",
type: "module",
},
{
name: "stacktrace-parser",
type: "module",
},
{
name: "strip-ansi",
type: "module-default",
},
];
const externals = Object.fromEntries(
packages.map((pkg) => [
pkg.name,
`@vercel/turbopack-next/compiled/${pkg.name}`,
])
);
// adapted from https://github.com/vercel/next.js/blob/8fb5ef18e7958a19874e11b8037ac0f71c48baef/packages/next/taskfile-ncc.js
async function writePackageManifest(packageName, main) {
// some newer packages fail to include package.json in the exports
// so we can't reliably use require.resolve here
let packagePath;
try {
packagePath = require.resolve(packageName + "/package.json");
} catch (_) {
packagePath = await findUp("package.json", {
cwd: dirname(require.resolve(packageName)),
});
}
const { name, author, license } = require(packagePath);
const compiledPackagePath = join(__dirname, `src/compiled/${packageName}`);
const potentialLicensePath = join(dirname(packagePath), "./LICENSE");
if (existsSync(potentialLicensePath)) {
await writeFile(
join(compiledPackagePath, "LICENSE"),
await readFile(potentialLicensePath, "utf8")
);
} else {
// license might be lower case and not able to be found on case-sensitive
// file systems (ubuntu)
const otherPotentialLicensePath = join(dirname(packagePath), "./license");
if (existsSync(otherPotentialLicensePath)) {
await writeFile(
join(compiledPackagePath, "LICENSE"),
await readFile(otherPotentialLicensePath, "utf8")
);
}
}
await writeFile(
join(compiledPackagePath, "package.json"),
JSON.stringify(
Object.assign(
{},
{ name, main: `${basename(main, "." + extname(main))}` },
author ? { author } : undefined,
license ? { license } : undefined
)
) + "\n"
);
}
async function main() {
const baseDir = join(__dirname, "src/compiled");
await rm(baseDir, {
force: true,
recursive: true,
});
let types = "/* GENERATED FILE, DO NOT EDIT */\n";
for (const pkg of packages) {
const input = require.resolve(pkg.name);
const outputDir = join(baseDir, pkg.name);
await mkdir(outputDir, { recursive: true });
const { code, assets } = await ncc(input, {
minify: true,
assetBuilds: true,
quiet: true,
externals,
});
await writeFile(join(outputDir, "index.js"), code);
for (const key in assets) {
await writeFile(join(outputDir, key), assets[key].source);
}
await writePackageManifest(pkg.name, "index.js");
types += `\ndeclare module "@vercel/turbopack-next/compiled/${pkg.name}" {\n`;
if (pkg.types) {
types += ` ${pkg.types}\n`;
} else if (pkg.type === "module-default") {
types += ` import m from "${pkg.name}";\n`;
types += ` export default m;\n`;
} else if (pkg.type === "module") {
types += ` export * from "${pkg.name}";\n`;
} else if (pkg.type === "cjs") {
types += ` import m from "${pkg.name}";\n`;
types += ` export = m;\n`;
} else {
throw new Error(`unknown package type ${pkg.type} for ${pkg.name}`);
}
types += `}\n`;
console.log(`built ${pkg.name}`);
}
await writeFile(join(__dirname, "types", "compiled.d.ts"), types);
}
main().catch((e) => {
console.dir(e);
process.exit(1);
});