aboutsummaryrefslogtreecommitdiff
path: root/bin/build.js
diff options
context:
space:
mode:
authorLouis Pilfold <louis@lpil.uk>2021-09-12 12:44:15 +0100
committerLouis Pilfold <louis@lpil.uk>2021-09-12 12:44:15 +0100
commit7669f75f4ee16d692b1171c3329bf5e3485c1a7c (patch)
tree3a3686993ee3e6da5b968851fc7009104abb2430 /bin/build.js
parent6529e7ebcd8681f2d1687d2aa8e44838c25ed279 (diff)
downloadjavascript-7669f75f4ee16d692b1171c3329bf5e3485c1a7c.tar.gz
javascript-7669f75f4ee16d692b1171c3329bf5e3485c1a7c.zip
Build script
Diffstat (limited to 'bin/build.js')
-rw-r--r--bin/build.js156
1 files changed, 156 insertions, 0 deletions
diff --git a/bin/build.js b/bin/build.js
new file mode 100644
index 0000000..3937705
--- /dev/null
+++ b/bin/build.js
@@ -0,0 +1,156 @@
+import { stat, copyFile, readFile, mkdir, access, readdir } from "fs/promises";
+import { resolve, relative, join } from "path";
+import { promisify } from "util";
+import { exec as callbackExec } from "child_process";
+
+let exec = promisify(callbackExec);
+
+export async function build() {
+ let { name, gleamDependencies } = JSON.parse(
+ await readFile("./package.json")
+ );
+
+ await Promise.all(gleamDependencies.map(clone));
+ for (let dep of gleamDependencies) await cachedBuildProject(dep);
+
+ await buildProject({
+ name,
+ root: ".",
+ includeTests: true,
+ dependencies: gleamDependencies.map((d) => d.name),
+ });
+
+ return {
+ name,
+ };
+}
+
+async function copyJs(name, dir) {
+ let inDir = join(dir, "src");
+ let out = outDir(name);
+ let files = await readdir(inDir);
+ files.map(async (file) => {
+ if (file.endsWith(".js")) {
+ await copyFile(join(inDir, file), join(out, file));
+ }
+ });
+}
+
+async function cachedBuildProject(info) {
+ if (await fileExists(outDir(info.name))) return;
+ await buildProject(info);
+}
+
+async function buildProject({ name, root, dependencies, includeTests }) {
+ console.log(`Building ${name}`);
+ let dir = root || libraryDir(name);
+ let src = join(dir, "src");
+ let test = join(dir, "test");
+ let out = outDir(name);
+ try {
+ await exec(
+ [
+ "gleam compile-package",
+ `--name ${name}`,
+ "--target javascript",
+ `--src ${src}`,
+ includeTests ? `--test ${test}` : "",
+ `--out ${out}`,
+ (dependencies || []).map((dep) => `--lib=${outDir(dep)}`).join(" "),
+ ].join(" ")
+ );
+ } catch (error) {
+ console.error(error.stderr);
+ process.exit(1);
+ }
+ await copyJs(name, dir);
+}
+
+async function clone({ name, ref, url }) {
+ let dir = libraryDir(name);
+ if (await fileExists(dir)) return;
+ await mkdir(dir, { recursive: true });
+ await exec(`git clone --depth=1 --branch="${ref}" "${url}" "${dir}"`);
+}
+
+function libraryDir(name) {
+ return join("target", "deps", name);
+}
+
+function outDir(name) {
+ return join("target", "lib", name);
+}
+
+async function fileExists(path) {
+ try {
+ await access(path);
+ return true;
+ } catch {
+ return false;
+ }
+}
+
+async function test() {
+ let gleamPackage = await build();
+
+ console.log("Running tests...");
+
+ let dir = `target/lib/${gleamPackage.name}`;
+ let passes = 0;
+ let failures = 0;
+
+ for await (let path of await getFiles(dir)) {
+ if (!path.endsWith("_test.js")) continue;
+ let module = await import(path);
+
+ for await (let fnName of Object.keys(module)) {
+ if (!fnName.endsWith("_test")) continue;
+ try {
+ await module[fnName]();
+ process.stdout.write(`\u001b[32m.\u001b[0m`);
+ passes++;
+ } catch (error) {
+ let moduleName = "\n" + relative(dir, path).slice(0, -3);
+ process.stdout.write(`\n❌ ${moduleName}.${fnName}: ${error}\n`);
+ failures++;
+ }
+ }
+ }
+
+ console.log(`
+
+${passes + failures} tests
+${failures} failures`);
+ process.exit(failures ? 1 : 0);
+}
+
+async function getFiles(dir) {
+ const subdirs = await readdir(dir);
+ const files = await Promise.all(
+ subdirs.map(async (subdir) => {
+ const res = resolve(dir, subdir);
+ return (await stat(res)).isDirectory() ? getFiles(res) : res;
+ })
+ );
+ return files.reduce((a, f) => a.concat(f), []);
+}
+
+async function main() {
+ switch (process.argv[process.argv.length - 1]) {
+ case "build":
+ return await build();
+
+ case "test":
+ return await test();
+
+ default:
+ console.error(`
+Usage:
+ node bin/build.js test
+ node bin/build.js build
+`);
+ process.exit(1);
+ }
+}
+
+main();