Skip to content

Commit 0dc43cc

Browse files
committed
chore(watch): optimize watch script
1 parent 2571fb6 commit 0dc43cc

File tree

5 files changed

+122
-165
lines changed

5 files changed

+122
-165
lines changed

docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"preview": "rspress preview"
1111
},
1212
"dependencies": {
13-
"@matechat/react": "link:..",
13+
"@matechat/react": "workspace:*",
1414
"rspress": "^1.40.2"
1515
},
1616
"devDependencies": {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"build": "vite build",
3737
"dev": "tsx scripts/watch.ts",
3838
"docs:build": "pnpm --filter @matechat/react-docs build",
39-
"docs:dev": "tsx scripts/docs-watch.ts",
39+
"docs:dev": "tsx scripts/watch.ts --project docs",
4040
"playground:build": "vite build --config playground/vite.config.ts",
4141
"preview": "vite --config playground/vite.config.ts",
4242
"test": "vitest",

pnpm-lock.yaml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/docs-watch.ts

Lines changed: 0 additions & 98 deletions
This file was deleted.

scripts/watch.ts

Lines changed: 119 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,49 @@ import { execSync, spawn } from "node:child_process";
22
import fs, { type WatchEventType } from "node:fs";
33
import path from "node:path";
44
import { fileURLToPath } from "node:url";
5-
import { createSpinner, type ProgressBar } from "archons";
5+
import { createSpinner, defineCommand, type ProgressBar, run } from "archons";
66
import chalk from "chalk";
77

8-
function isIgnored(filename: string) {
8+
export interface WatchConfig {
9+
paths: { path: string; cmd: string }[];
10+
dev: {
11+
exec: string;
12+
options: string[];
13+
};
14+
}
15+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
16+
const watchMap: Record<string, WatchConfig> = {
17+
core: {
18+
paths: [{ path: path.join(__dirname, "../src"), cmd: "pnpm build" }],
19+
dev: {
20+
exec: "pnpm",
21+
options: ["run", "--silent", "preview", "--clearScreen", "false"],
22+
},
23+
},
24+
docs: {
25+
paths: [{ path: path.join(__dirname, "../src"), cmd: "pnpm build" }],
26+
dev: {
27+
exec: "pnpm",
28+
options: ["run", "--silent", "--filter", "@matechat/react-docs", "dev"],
29+
},
30+
},
31+
};
32+
const ignored = [
33+
"node_modules",
34+
".git",
35+
".github",
36+
".vscode",
37+
"dist",
38+
"build",
39+
"bin",
40+
".md",
41+
".d.ts",
42+
"target",
43+
".cjs",
44+
"doc_build",
45+
];
46+
47+
function isIgnored(filename: string, ignored: string[]) {
948
for (const pattern of ignored) {
1049
if (filename.includes(pattern)) {
1150
return true;
@@ -31,68 +70,36 @@ function createArchonsSpinner() {
3170
return spinner;
3271
}
3372

34-
const cwd = process.cwd();
35-
const watchMap = new Map<string, string>([
36-
[
37-
path.join(path.dirname(fileURLToPath(import.meta.url)), "../src"),
38-
"pnpm build",
39-
],
40-
]);
41-
const displayPaths = Array.from(watchMap.keys())
42-
.map((dirPath) => chalk.cyan(path.relative(cwd, dirPath)))
43-
.join(", ");
44-
45-
const ignored = [
46-
"node_modules",
47-
".git",
48-
".github",
49-
".vscode",
50-
"dist",
51-
"build",
52-
"bin",
53-
".md",
54-
".d.ts",
55-
"target",
56-
".cjs",
57-
];
58-
const greenPrefix = chalk.green("[MateChat]");
59-
60-
const spinner = createArchonsSpinner();
61-
spinner.enableSteadyTick(100);
62-
spinner.setMessage("Initial building...");
63-
for (const cmd of watchMap.values()) {
64-
tryBuild(cmd, "Building...", spinner);
73+
export interface WatchOptions {
74+
coloredPrefix: string;
75+
options: WatchConfig;
76+
displayPaths: string;
77+
ignoredPaths: string[];
6578
}
66-
spinner.finishAndClear();
67-
console.clear();
68-
console.log(`${greenPrefix} Build complete.\n`);
69-
console.log(`${greenPrefix} Watching on ${displayPaths} for changes...`);
79+
function watch({
80+
coloredPrefix,
81+
options,
82+
displayPaths,
83+
ignoredPaths,
84+
}: WatchOptions) {
85+
let lastBuild = Date.now();
7086

71-
function watch() {
7287
function createDevProcess() {
73-
let devProcess = spawn(
74-
"pnpm",
75-
["run", "--silent", "preview", "--clearScreen", "false"],
76-
{
77-
stdio: "inherit",
78-
shell: true,
79-
},
80-
);
88+
let devProcess = spawn(options.dev.exec, options.dev.options, {
89+
stdio: "inherit",
90+
shell: true,
91+
});
8192
return () => {
8293
const spinner = createArchonsSpinner();
83-
spinner.println(`${greenPrefix} Restarting Vite dev server...`);
94+
spinner.println(`${coloredPrefix} Restarting dev server...`);
8495
while (!devProcess.kill("SIGINT"));
8596
devProcess.on("close", () => {
86-
devProcess = spawn(
87-
"pnpm",
88-
["run", "--silent", "preview", "--clearScreen", "false"],
89-
{
90-
stdio: "inherit",
91-
shell: true,
92-
},
93-
);
97+
devProcess = spawn(options.dev.exec, options.dev.options, {
98+
stdio: "inherit",
99+
shell: true,
100+
});
94101
devProcess.on("error", (err) => {
95-
console.error(`${greenPrefix} Error restarting dev process:`, err);
102+
console.error(`${coloredPrefix} Error restarting dev process:`, err);
96103
});
97104
spinner.finishAndClear();
98105
});
@@ -111,29 +118,77 @@ function watch() {
111118

112119
restartServer();
113120

114-
if (filename && !isIgnored(filename)) {
121+
if (filename && !isIgnored(filename, ignoredPaths)) {
115122
const spinner = createArchonsSpinner();
116123
spinner.println(
117-
`${greenPrefix} File ${chalk.cyan(filename)} was ${eventType}d, rebuilding...`,
124+
`${coloredPrefix} File ${chalk.cyan(
125+
filename,
126+
)} was ${eventType}d, rebuilding...`,
118127
);
119128
spinner.enableSteadyTick(100);
120129
if ([".ts", ".tsx", ".css"].some((ext) => filename.endsWith(ext))) {
121130
tryBuild(command, "Rebuilding...", spinner);
122131
}
123132
console.clear();
124-
spinner.println(`${greenPrefix} Build complete.\n\n`);
133+
spinner.println(`${coloredPrefix} Build complete.\n\n`);
125134
spinner.println(
126-
`${greenPrefix} Watching on ${displayPaths} for changes...`,
135+
`${coloredPrefix} Watching on ${displayPaths} for changes...`,
127136
);
128137
spinner.finishAndClear();
129138
lastBuild = Date.now();
130139
}
131140
}
132141

133-
for (const [dirPath, cmd] of watchMap) {
134-
fs.watch(dirPath, { recursive: true }, rebuild.bind(null, cmd));
142+
for (const { cmd, path } of options.paths) {
143+
fs.watch(path, { recursive: true }, rebuild.bind(null, cmd));
135144
}
136145
}
137146

138-
let lastBuild = Date.now();
139-
watch();
147+
const main = defineCommand({
148+
meta: {
149+
name: "watch",
150+
about: "Watch files and rebuild when changed",
151+
styled: true,
152+
},
153+
options: {
154+
project: {
155+
type: "option",
156+
default: "core",
157+
short: "p",
158+
help: "Project to watch",
159+
},
160+
},
161+
callback: async (ctx) => {
162+
const cwd = process.cwd();
163+
const project = ctx.args.project as string;
164+
if (!watchMap[project]) {
165+
throw new Error(`Project ${project} not found`);
166+
}
167+
168+
const displayPaths = watchMap[project].paths
169+
.map((opts) => chalk.cyan(path.relative(cwd, opts.path)))
170+
.join(", ");
171+
172+
const coloredPrefix = chalk.green("[MateChat]");
173+
174+
const spinner = createArchonsSpinner();
175+
spinner.enableSteadyTick(100);
176+
spinner.setMessage("Initial building...");
177+
for (const { cmd } of watchMap[project].paths) {
178+
tryBuild(cmd, "Building...", spinner);
179+
}
180+
spinner.finishAndClear();
181+
console.clear();
182+
console.log(`${coloredPrefix} Build complete.\n`);
183+
console.log(`${coloredPrefix} Watching on ${displayPaths} for changes...`);
184+
185+
watch({
186+
coloredPrefix,
187+
options: watchMap[project],
188+
displayPaths,
189+
ignoredPaths: ignored,
190+
});
191+
},
192+
});
193+
194+
run(main);

0 commit comments

Comments
 (0)