#!/usr/bin/env -S node -r esbin import { promises as fs } from "fs" import { resolve } from "path" import { kebabCase } from "lodash" import { sync as glob } from "fast-glob" import { ensureArray as arr } from "~/shared/ensureArray" // import _ from "dedent"; interface Task { deps: string | string[] target: string | string[] command: string | string[] } // Variables for Makefile // $@: The file name of the target of the rule. // $<: The name of the first prerequisite. // $?: The names of all the prerequisites that are newer than the target, with spaces between them. // $^: The names of all the prerequisites, with spaces between them. const tasks: { [name: string]: () => Task } = { Makefile: (script = "scripts/build-makefile.ts") => ({ command: script, target: "Makefile", deps: [script], }), theme: (script = "scripts/build-theme.tsx") => ({ command: `${script} -o $(@D)`, target: [ "src/shared/theme/tokens.generated.ts", "src/shared/theme/tokens.generated.css", ], deps: ["src/shared/theme/tokens.tsx", script], }), models: ( models = "src/shared/models", source = `${models}/models.yml`, script = "./scripts/build-models.ts", ) => ({ command: `${script}`, target: glob(`${models}/*.generated.ts`), deps: [source, script], }), WebExtensionPolyfill: (base = "src/vendor/webextension-polyfill") => ({ target: `${base}/api-metadata.generated.json`, deps: glob(`${base}/**/*`), command: `./${base}/scripts/compress.ts`, }), HTML: (script = "scripts/build-htmls.tsx") => ({ target: glob("dist/*.html"), deps: script, command: script, }), locales: (script = "scripts/build-locales.ts") => ({ target: [ ...glob(["dist/_locales/**/*.json", "src/shared/i18n/resources"]), "src/shared/i18n/data.generated.ts", ], deps: script, command: script, }), // monaco: ( // script = "./scripts/build-monaco.ts", // dist = "dist/vendor/monaco-editor/index.js", // ) => ({ // target: dist, // deps: ["package.json", script], // command: [script, `touch ${dist}`], // }), sass: (script = "./scripts/build-sass.ts") => ({ target: "dist/vendor/sass/index.js", deps: ["package.json", script], command: script, }), } async function main() { const sep = " \\\n " function* generate() { yield "# This file is generated by `make Makefile`" const instances = Object.entries(tasks).map(([name, t]) => [name, t()] as const) for (const [name, task] of instances) { const { target } = task yield arr(target).join(" ") + ": " + arr(task.deps) .filter(d => !glob(d).some(file => target.includes(file))) .join(sep) yield `\t@echo "✨ Building ${name}..."` for (const cmd of arr(task.command)) { yield `\t@${cmd}` } yield "" yield `${kebabCase(name)}: ${arr(target)[0]}` yield "" } yield "all: " + instances.map(task => kebabCase(task[0])).join(sep) yield "" } const makefile = [...generate()].join("\n") await fs.writeFile(resolve(__dirname, "../Makefile"), makefile) } main()