Files
qinglong/scripts/ql3-build-package-closure.cjs
T

111 lines
3.0 KiB
JavaScript

#!/usr/bin/env node
const fs = require('node:fs');
const path = require('node:path');
const { spawnSync } = require('node:child_process');
const QL3_PACKAGE_NAME = /^@qinglong\/[a-z0-9]+(?:-[a-z0-9]+)*$/;
class QingLong3PackageClosureBuildError extends Error {
constructor(message) {
super(`QingLong 3.0 package closure build failed: ${message}`);
this.name = 'QingLong3PackageClosureBuildError';
}
}
function resolveQingLong3Package(root, packageDirectory) {
const packagesDirectory = path.join(root, 'packages');
const relative = path.relative(packagesDirectory, packageDirectory);
if (
relative.length === 0 ||
relative === '..' ||
relative.startsWith(`..${path.sep}`) ||
relative.includes(path.sep) ||
!relative.startsWith('ql3-')
) {
throw new QingLong3PackageClosureBuildError(
'cwd must be one direct packages/ql3-* directory',
);
}
const manifestPath = path.join(packageDirectory, 'package.json');
let manifest;
try {
manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
} catch (error) {
throw new QingLong3PackageClosureBuildError(
`cannot read package manifest: ${
error instanceof Error ? error.message : String(error)
}`,
);
}
if (!QL3_PACKAGE_NAME.test(manifest.name ?? '')) {
throw new QingLong3PackageClosureBuildError(
'manifest name must be one bounded @qinglong/* package name',
);
}
if (manifest.scripts?.build !== 'tsc -p tsconfig.json') {
throw new QingLong3PackageClosureBuildError(
`${manifest.name} build must compile only itself`,
);
}
return Object.freeze({
name: manifest.name,
packageDirectory,
});
}
function createQingLong3PackageClosureBuildPlan(root, packageDirectory) {
const packageRecord = resolveQingLong3Package(root, packageDirectory);
return Object.freeze({
command: process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm',
args: Object.freeze([
'-r',
'--workspace-concurrency=1',
'--filter',
`${packageRecord.name}...`,
'run',
'build',
]),
cwd: root,
});
}
function main() {
if (process.env.npm_lifecycle_event === 'build') {
throw new QingLong3PackageClosureBuildError(
'closure helper cannot run from a package build script',
);
}
const root = path.resolve(__dirname, '..');
const plan = createQingLong3PackageClosureBuildPlan(root, process.cwd());
const result = spawnSync(plan.command, plan.args, {
cwd: plan.cwd,
env: process.env,
stdio: 'inherit',
});
if (result.error) throw result.error;
if (result.signal) {
throw new QingLong3PackageClosureBuildError(
`pnpm terminated by ${result.signal}`,
);
}
if (result.status !== 0) process.exitCode = result.status ?? 1;
}
module.exports = {
QingLong3PackageClosureBuildError,
createQingLong3PackageClosureBuildPlan,
resolveQingLong3Package,
};
if (require.main === module) {
try {
main();
} catch (error) {
process.stderr.write(
`${error instanceof Error ? error.message : String(error)}\n`,
);
process.exitCode = 1;
}
}