1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
import chokidar, { FSWatcher } from 'chokidar';
import { logger } from '../logger.js';
import { PageDirectory } from '../builder/pageDirectory.js';
import { rebuildSinglePage } from '../builder/buildProject.js';
import path from 'path';
import fs from 'fs';
function attachPageEvents(watcher: FSWatcher, pages: PageDirectory) {
const onPageChange = async (file: string) => {
logger.info(`File ${file} has been modified, rebuilding...`);
if (await rebuildSinglePage(file, pages)) {
logger.info(`...done`);
}
logger.info(``);
}
const onPageRemoval = (file: string) => {
logger.info(`File ${file} has been removed, deleting...`);
const page = pages.get(file.replace(/\.[^.]*$/,''));
if (!page) {
logger.error(`Failed to find page for ${file}`);
return;
}
const joinedPath = path.join(process.env.OUTPUT_DIR, `${page.route}.html`);
try {
fs.rmSync(joinedPath)
} catch (e) {
logger.error(`Failed to remove ${joinedPath}: ${e.message}`);
}
logger.info(`...done`);
logger.info(``);
}
watcher.on('add', onPageChange);
watcher.on('change', onPageChange);
watcher.on('unlink', onPageRemoval);
}
function attachStaticEvents(watcher: FSWatcher) {
const onStaticChange = async (file: string) => {
logger.info(`Static file ${file} has been modified, copying...`);
const joinedPath = path.join(process.env.STATIC_DIR, file);
const joinedOutputPath = path.join(process.env.OUTPUT_DIR, 'static', file);
try {
fs.copyFileSync(joinedPath, joinedOutputPath);
logger.info(`...done`);
} catch (e) {
logger.error(`Failed to copy ${joinedPath} to ${joinedOutputPath}: ${e.message}`);
}
logger.info(``);
}
const onStaticRemoval = (file: string) => {
logger.info(`Static file ${file} has been removed, deleting...`);
const joinedOutputPath = path.join(process.env.OUTPUT_DIR, 'static', file);
try {
fs.rmSync(joinedOutputPath)
logger.info(`...done`);
} catch (e) {
logger.error(`Failed to remove ${joinedOutputPath}: ${e.message}`);
}
logger.info(``);
}
watcher.on('add', onStaticChange);
watcher.on('change', onStaticChange);
watcher.on('unlink', onStaticRemoval);
}
function attachViewEvents(watcher: FSWatcher, pages: PageDirectory) {
const onViewChange = async (file: string) => {
logger.info(`View ${file} has been modified, rebuilding pages with view...`);
let pagesWithView = pages.getPages().filter(page => `${page.view}.ejs` === file);
logger.info(`Found ${pagesWithView.length} pages with view ${file}`);
for (const page of pagesWithView) {
logger.info(`Rebuilding page ${page.route}...`);
if (await rebuildSinglePage(page.originalPath, pages)) {
logger.info(`...done`);
}
}
logger.info(``);
}
const onViewRemoval = (file: string) => {
logger.info(``);
logger.info(`View ${file} has been removed`);
logger.info(``);
}
watcher.on('add', onViewChange);
watcher.on('change', onViewChange);
watcher.on('unlink', onViewRemoval);
}
export const start = (pages: PageDirectory) => {
const pagesWatcher = chokidar.watch('.', {
persistent: true,
cwd: process.env.PAGES_DIR,
ignoreInitial: true,
});
const staticWatcher = chokidar.watch('.', {
persistent: true,
cwd: process.env.STATIC_DIR,
ignoreInitial: true,
});
const viewsWatcher = chokidar.watch('.', {
persistent: true,
cwd: process.env.VIEWS_DIR,
ignoreInitial: true,
});
attachPageEvents(pagesWatcher, pages);
attachStaticEvents(staticWatcher);
attachViewEvents(viewsWatcher, pages);
const exitHandler = () => {
logger.info(`Stopping file watcher...`);
viewsWatcher.close();
staticWatcher.close();
pagesWatcher.close();
}
process.on('SIGINT', exitHandler);
process.on('SIGTERM', exitHandler);
}
|