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} 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 });