diff --git a/src/frontend/AssetPreCompiler.ts b/src/frontend/AssetPreCompiler.ts index b9d1597..6f9b9e0 100644 --- a/src/frontend/AssetPreCompiler.ts +++ b/src/frontend/AssetPreCompiler.ts @@ -1,5 +1,5 @@ import chokidar, {FSWatcher} from "chokidar"; -import {existsSync, mkdirSync} from "fs"; +import {existsSync, mkdirSync, promises as fs} from "fs"; import path from "path"; import {logger} from "../Logger.js"; @@ -121,19 +121,11 @@ export default abstract class AssetPreCompiler { this.watcher.on('add', (file) => { this.onNewFile(file) - .then(() => this.preCompile(this.toCanonicalName(file), true)) - .then(() => { - return this.afterPreCompile(true); - }) .catch(err => logger.error(err)); }); this.watcher.on('change', (file) => { - (this.onFileChange ? this.onFileChange(file) : Promise.resolve()) - .then(() => this.preCompile(this.toCanonicalName(file), true)) - .then(() => { - return this.afterPreCompile(true); - }) + this.onFileChange(file) .catch(err => logger.error(err)); }); @@ -144,13 +136,34 @@ export default abstract class AssetPreCompiler { }); } - public async onNewFile(_file: string): Promise { + public async onNewFile(file: string): Promise { + logger.silly('a', file); + const canonicalName = this.toCanonicalName(file); + await this.preCompile(canonicalName, true); + await this.afterPreCompile(true); + await this.inputChangeHandler?.(false); } - public onFileChange?(file: string): Promise; + public async onFileChange(file: string): Promise { + logger.silly('c', file); + const canonicalName = this.toCanonicalName(file); + await this.preCompile(canonicalName, true); + await this.afterPreCompile(true); + } + + public async onFileRemove(file: string): Promise { + logger.silly('r', file); + const canonicalName = this.toCanonicalName(file); + const replacementSourceFile = await this.resolveFileFromCanonicalName(canonicalName); + if (replacementSourceFile) { + await this.preCompile(canonicalName, true); + await this.afterPreCompile(true); + } else { + const targetFile = path.resolve(this.targetDir, canonicalName); + await fs.rm(targetFile); + } - public async onFileRemove(_file: string): Promise { await this.inputChangeHandler?.(true); } @@ -172,7 +185,7 @@ export default abstract class AssetPreCompiler { return canonicalViewName; } - protected async resolveFileFromCanonicalName(canonicalName: string): Promise { + protected async resolveFileFromCanonicalName(canonicalName: string): Promise { for (const viewPath of this.assetPaths) { const tryPath = path.join(viewPath, canonicalName); if (await doesFileExist(tryPath)) { @@ -180,6 +193,12 @@ export default abstract class AssetPreCompiler { } } - throw new Error('View not found from canonical name ' + canonicalName); + return null; + } + + protected async resolveFileFromCanonicalNameOrFail(canonicalName: string): Promise { + const file = await this.resolveFileFromCanonicalName(canonicalName); + if (file) return file; + else throw new Error('View not found from canonical name ' + canonicalName); } } diff --git a/src/frontend/CopyAssetPreCompiler.ts b/src/frontend/CopyAssetPreCompiler.ts index 060f54a..ce3fc46 100644 --- a/src/frontend/CopyAssetPreCompiler.ts +++ b/src/frontend/CopyAssetPreCompiler.ts @@ -22,7 +22,7 @@ export default class CopyAssetPreCompiler extends AssetPreCompiler { } public async preCompile(canonicalName: string): Promise { - const inputFile = await this.resolveFileFromCanonicalName(canonicalName); + const inputFile = await this.resolveFileFromCanonicalNameOrFail(canonicalName); const outputFile = path.join(this.actualTargetDir, canonicalName); logger.info('Copying', inputFile, '->', outputFile); await fs.mkdir(path.dirname(outputFile), {recursive: true}); diff --git a/src/frontend/SvelteViewEngine.ts b/src/frontend/SvelteViewEngine.ts index 3ab930b..8b10bc5 100644 --- a/src/frontend/SvelteViewEngine.ts +++ b/src/frontend/SvelteViewEngine.ts @@ -41,6 +41,7 @@ export default class SvelteViewEngine extends ViewEngine { public async onFileChange(file: string): Promise { delete this.preprocessingCache[this.toCanonicalName(file)]; + await super.onFileChange(file); } public async onFileRemove(file: string): Promise { @@ -62,7 +63,7 @@ export default class SvelteViewEngine extends ViewEngine { const view = await this.fileCache.get(actualFile, !config.get('view.cache')); // Root template - const templateFile = await this.resolveFileFromCanonicalName('layouts/svelte_layout.html'); + const templateFile = await this.resolveFileFromCanonicalNameOrFail('layouts/svelte_layout.html'); const rawOutput = await this.fileCache.get(templateFile, !config.get('view.cache')); // Pre-compiled parts @@ -95,10 +96,9 @@ export default class SvelteViewEngine extends ViewEngine { } public async preCompile(canonicalName: string, alsoCompileDependents: boolean): Promise { - const file = await this.resolveFileFromCanonicalName(canonicalName); const intermediateFile = path.join(this.targetDir, canonicalName); - logger.info(canonicalName + ' > ', 'Pre-compiling', file, '->', intermediateFile); + logger.info(canonicalName + ' > ', 'Pre-compiling', canonicalName, '->', intermediateFile); const allBackendCalls: string[] = []; @@ -157,7 +157,7 @@ export default class SvelteViewEngine extends ViewEngine { return this.preprocessingCache[canonicalName]; } - const file = await this.resolveFileFromCanonicalName(canonicalName); + const file = await this.resolveFileFromCanonicalNameOrFail(canonicalName); logger.info(canonicalName + ' > ', `Preprocessing ${file}`); // mkdir output file dir