TypeScript/scripts/build/projects.mjs

70 lines
2.4 KiB
JavaScript

import { exec, Debouncer } from "./utils.mjs";
import { resolve } from "path";
import { findUpRoot } from "./findUpDir.mjs";
import assert from "assert";
class ProjectQueue {
/**
* @param {(projects: string[], lkg: boolean, force: boolean) => Promise<any>} action
*/
constructor(action) {
/** @type {{ lkg: boolean, force: boolean, projects?: string[], debouncer: Debouncer }[]} */
this._debouncers = [];
this._action = action;
}
/**
* @param {string} project
* @param {{ lkg?: boolean; force?: boolean; }} options
*/
enqueue(project, { lkg = true, force = false } = {}) {
let entry = this._debouncers.find(entry => entry.lkg === lkg && entry.force === force);
if (!entry) {
const debouncer = new Debouncer(100, async () => {
assert(entry);
const projects = entry.projects;
if (projects) {
entry.projects = undefined;
await this._action(projects, lkg, force);
}
});
this._debouncers.push(entry = { lkg, force, debouncer });
}
if (!entry.projects) entry.projects = [];
entry.projects.push(project);
return entry.debouncer.enqueue();
}
}
const execTsc = (/** @type {boolean} */ lkg, /** @type {string[]} */ ...args) =>
exec(process.execPath,
[resolve(findUpRoot(), lkg ? "./lib/tsc" : "./built/local/tsc"),
"-b", ...args],
{ hidePrompt: true });
const projectBuilder = new ProjectQueue((projects, lkg, force) => execTsc(lkg, ...(force ? ["--force"] : []), ...projects));
/**
* @param {string} project
* @param {object} options
* @param {boolean} [options.lkg=true]
* @param {boolean} [options.force=false]
*/
export const buildProject = (project, { lkg, force } = {}) => projectBuilder.enqueue(project, { lkg, force });
const projectCleaner = new ProjectQueue((projects, lkg) => execTsc(lkg, "--clean", ...projects));
/**
* @param {string} project
*/
export const cleanProject = (project) => projectCleaner.enqueue(project);
const projectWatcher = new ProjectQueue((projects) => execTsc(/*lkg*/ true, "--watch", ...projects));
/**
* @param {string} project
* @param {object} options
* @param {boolean} [options.lkg=true]
*/
export const watchProject = (project, { lkg } = {}) => projectWatcher.enqueue(project, { lkg });