swaf/src/frontend/AssetCompiler.ts

78 lines
2.7 KiB
TypeScript

import child_process from "child_process";
import config from "config";
import fs from "fs";
import path from "path";
import {logger} from "../Logger.js";
import {doesFileExist, listFilesRecursively} from "../Utils.js";
const ROLLUP_CONFIG_FILE_NAME = 'rollup.config.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<void> {
// 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<boolean>('view.dev');
if (!this.rollup) {
const rollupConfigPath = await doesFileExist(ROLLUP_CONFIG_FILE_NAME) ?
ROLLUP_CONFIG_FILE_NAME :
path.resolve('node_modules/swaf/' + ROLLUP_CONFIG_FILE_NAME);
const args = [
'rollup',
'-c', rollupConfigPath,
'--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<void> {
if (this.rollup) {
logger.info(`Stopping rollup (${this.rollup.pid})...`);
await new Promise<void>((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);
}
}
}