1import { exec, Debouncer } from "./utils.mjs"; 2import { resolve } from "path"; 3import { findUpRoot } from "./findUpDir.mjs"; 4import assert from "assert"; 5 6class ProjectQueue { 7 /** 8 * @param {(projects: string[], lkg: boolean, force: boolean) => Promise<any>} action 9 */ 10 constructor(action) { 11 /** @type {{ lkg: boolean, force: boolean, projects?: string[], debouncer: Debouncer }[]} */ 12 this._debouncers = []; 13 this._action = action; 14 } 15 16 /** 17 * @param {string} project 18 * @param {{ lkg?: boolean; force?: boolean; }} options 19 */ 20 enqueue(project, { lkg = true, force = false } = {}) { 21 let entry = this._debouncers.find(entry => entry.lkg === lkg && entry.force === force); 22 if (!entry) { 23 const debouncer = new Debouncer(100, async () => { 24 assert(entry); 25 const projects = entry.projects; 26 if (projects) { 27 entry.projects = undefined; 28 await this._action(projects, lkg, force); 29 } 30 }); 31 this._debouncers.push(entry = { lkg, force, debouncer }); 32 } 33 if (!entry.projects) entry.projects = []; 34 entry.projects.push(project); 35 return entry.debouncer.enqueue(); 36 } 37} 38 39const execTsc = (/** @type {boolean} */ lkg, /** @type {string[]} */ ...args) => 40 exec(process.execPath, 41 [resolve(findUpRoot(), lkg ? "./lib/tsc" : "./built/local/tsc"), 42 "-b", ...args], 43 { hidePrompt: true }); 44 45const projectBuilder = new ProjectQueue((projects, lkg, force) => execTsc(lkg, ...(force ? ["--force"] : []), ...projects)); 46 47/** 48 * @param {string} project 49 * @param {object} options 50 * @param {boolean} [options.lkg=true] 51 * @param {boolean} [options.force=false] 52 */ 53export const buildProject = (project, { lkg, force } = {}) => projectBuilder.enqueue(project, { lkg, force }); 54 55const projectCleaner = new ProjectQueue((projects, lkg) => execTsc(lkg, "--clean", ...projects)); 56 57/** 58 * @param {string} project 59 */ 60 export const cleanProject = (project) => projectCleaner.enqueue(project); 61 62const projectWatcher = new ProjectQueue((projects) => execTsc(/*lkg*/ true, "--watch", ...projects)); 63 64/** 65 * @param {string} project 66 * @param {object} options 67 * @param {boolean} [options.lkg=true] 68 */ 69export const watchProject = (project, { lkg } = {}) => projectWatcher.enqueue(project, { lkg }); 70