import child_process from "child_process"; import config from "config"; import fs from "fs"; import {logger} from "../Logger.js"; import {listFilesRecursively} from "../Utils.js"; export default class AssetCompiler { private rollup?: child_process.ChildProcess; private extensions: string[] = []; /** * @param sourceDir The source assets directory. * @param targetDir The output directory that should contain all final and public assets. */ public constructor( public readonly sourceDir: string, public readonly targetDir: string, ) { if (!fs.existsSync(this.targetDir)) { fs.mkdirSync(this.targetDir, {recursive: true}); } } public addExtension(extension: string): void { this.extensions.push(extension); } public async compile(watch: boolean): Promise { // Prepare input list const input = (await listFilesRecursively(this.sourceDir)) .filter(f => this.extensions.find(ext => f.endsWith('.' + ext))); logger.info('Input list:', input); const production = !config.get('view.dev'); if (!this.rollup) { const args = [ 'rollup', '-c', 'rollup.config.js', '--environment', `ENV:${production ? 'production' : 'dev'},BUILD_DIR:${this.sourceDir},PUBLIC_DIR:${this.targetDir},INPUT:${input.join(':')}`, ]; if (watch) args.push('--watch'); this.rollup = child_process.spawn('yarn', args, {stdio: [process.stdin, process.stdout, process.stderr]}); logger.info('Rollup started'); this.rollup.once('exit', (code: number) => { logger.info('Rollup stopped (' + code + ')'); this.rollup = undefined; if (!watch && code !== 0) process.exit(code); }); } } public async stopWatching(restart: boolean): Promise { if (this.rollup) { logger.info(`Stopping rollup (${this.rollup.pid})...`); await new Promise((resolve, reject) => { if (!this.rollup) return resolve(); this.rollup.once('exit', () => { resolve(); }); if (!this.rollup.kill("SIGTERM")) reject('Could not stop rollup.'); }); } if (restart) { await this.compile(true); } } }