Skip to content

Commit 2058f77

Browse files
committed
refactor: abstract watcher
1 parent 02fae86 commit 2058f77

2 files changed

Lines changed: 69 additions & 43 deletions

File tree

packages/scaffold/src/core/server.ts

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ import type { Context } from "../types/index.js";
22
import { existsSync } from "node:fs";
33
import { join } from "node:path";
44
import process from "node:process";
5-
import chokidar from "chokidar";
6-
import { debounce } from "es-toolkit";
5+
import { watch } from "../utils/watcher.js";
76
import { ZoteroRunner } from "../utils/zotero-runner.js";
87
import { Base } from "./base.js";
98
import Build from "./builder.js";
@@ -69,47 +68,32 @@ export default class Serve extends Base {
6968
async watch() {
7069
const { source } = this.ctx;
7170

72-
const watcher = chokidar.watch(source, {
73-
ignored: /(^|[/\\])\../, // ignore dotfiles
74-
persistent: true,
75-
});
76-
77-
const onChangeDebounced = debounce(async (path: string) => {
78-
await this.onChange(path).catch((err) => {
79-
// Do not abort the watcher when errors occur
80-
// in builds triggered by the watcher.
81-
this.logger.error(err);
82-
});
83-
}, 500);
84-
85-
watcher
86-
.on("ready", async () => {
87-
await this.ctx.hooks.callHook("serve:ready", this.ctx);
88-
this.logger.clear();
89-
this.logger.ready("Server Ready!");
90-
})
91-
.on("change", async (path) => {
92-
this.logger.clear();
93-
this.logger.info(`${path} changed`);
94-
await onChangeDebounced(path);
95-
})
96-
.on("error", (err) => {
97-
this.logger.fail("Server start failed!");
98-
this.logger.error(err);
99-
});
100-
}
101-
102-
async onChange(path: string) {
103-
await this.ctx.hooks.callHook("serve:onChanged", this.ctx, path);
104-
105-
if (path.endsWith(".ts") || path.endsWith(".tsx")) {
106-
await this.builder.esbuild();
107-
}
108-
else {
109-
await this.builder.run();
110-
}
111-
112-
await this.reload();
71+
watch(
72+
source,
73+
{
74+
onReady: async () => {
75+
await this.ctx.hooks.callHook("serve:ready", this.ctx);
76+
this.logger.clear();
77+
this.logger.ready("Server Ready!");
78+
},
79+
onChange: async (path) => {
80+
await this.ctx.hooks.callHook("serve:onChanged", this.ctx, path);
81+
82+
if (path.endsWith(".ts") || path.endsWith(".tsx")) {
83+
await this.builder.esbuild();
84+
}
85+
else {
86+
await this.builder.run();
87+
}
88+
89+
await this.reload();
90+
},
91+
onError: (err) => {
92+
this.logger.fail("Server start failed!");
93+
this.logger.error(err);
94+
},
95+
},
96+
);
11397
}
11498

11599
async reload() {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import chokidar from "chokidar";
2+
import { debounce } from "es-toolkit";
3+
import { logger } from "./logger.js";
4+
5+
export function watch(
6+
source: string | string[],
7+
event: {
8+
onReady: () => any;
9+
onChange: (path: string) => any | Promise<any>;
10+
onError?: (err: unknown) => any;
11+
},
12+
) {
13+
const watcher = chokidar.watch(source, {
14+
ignored: /(^|[/\\])\../, // ignore dotfiles
15+
persistent: true,
16+
});
17+
18+
const onChangeDebounced = debounce(event.onChange, 500);
19+
20+
watcher
21+
.on("ready", async () => {
22+
await event.onReady();
23+
})
24+
.on("change", async (path) => {
25+
try {
26+
await onChangeDebounced(path);
27+
}
28+
catch (err) {
29+
// Do not abort the watcher when errors occur
30+
// in builds triggered by the watcher.
31+
logger.error(err);
32+
}
33+
})
34+
.on("error", async (err) => {
35+
if (event.onError)
36+
await event.onError(err);
37+
logger.fail("Server start failed!");
38+
logger.error(err);
39+
});
40+
41+
// return watcher;
42+
}

0 commit comments

Comments
 (0)