|
1 |
| -import type {WatchEventType} from "node:fs"; |
| 1 | +import type {WatchListener} from "node:fs"; |
2 | 2 | import {watch, type FSWatcher} from "node:fs";
|
3 | 3 | import {access, constants, readFile, stat} from "node:fs/promises";
|
4 | 4 | import {createServer, type IncomingMessage, type RequestListener} from "node:http";
|
@@ -135,22 +135,38 @@ function handleWatch(socket: WebSocket, root: string) {
|
135 | 135 | });
|
136 | 136 | }
|
137 | 137 |
|
138 |
| - async function refreshMarkdown(path: string) { |
| 138 | + async function refreshMarkdown(path: string): Promise<WatchListener<string>> { |
139 | 139 | let current = await readMarkdown(path, root);
|
140 | 140 | attachmentWatcher = new FileWatchers(root, current.parse.files, refreshAttachment(current.parse));
|
141 |
| - return async (event: WatchEventType) => { |
142 |
| - if (event !== "change") return; // TODO: decide how to handle a "rename" event |
143 |
| - const updated = await readMarkdown(path, root); |
144 |
| - if (current.hash !== updated.hash) { |
145 |
| - send({ |
146 |
| - type: "update", |
147 |
| - diff: diffMarkdown(current, updated), |
148 |
| - previousHash: current.hash, |
149 |
| - updatedHash: updated.hash |
150 |
| - }); |
151 |
| - attachmentWatcher?.close(); |
152 |
| - attachmentWatcher = new FileWatchers(root, updated.parse.files, refreshAttachment(updated.parse)); |
153 |
| - current = updated; |
| 141 | + return async function watcher(event) { |
| 142 | + switch (event) { |
| 143 | + case "rename": { |
| 144 | + markdownWatcher?.close(); |
| 145 | + try { |
| 146 | + markdownWatcher = watch(path, watcher); |
| 147 | + } catch (error) { |
| 148 | + if (isNodeError(error) && error.code === "ENOENT") { |
| 149 | + console.error(`file no longer exists: ${path}`); |
| 150 | + socket.terminate(); |
| 151 | + return; |
| 152 | + } |
| 153 | + throw error; |
| 154 | + } |
| 155 | + setTimeout(() => watcher("change"), 150); // delay to avoid a possibly-empty file |
| 156 | + break; |
| 157 | + } |
| 158 | + case "change": { |
| 159 | + const updated = await readMarkdown(path, root); |
| 160 | + if (current.hash === updated.hash) break; |
| 161 | + const diff = diffMarkdown(current, updated); |
| 162 | + send({type: "update", diff, previousHash: current.hash, updatedHash: updated.hash}); |
| 163 | + attachmentWatcher?.close(); |
| 164 | + attachmentWatcher = new FileWatchers(root, updated.parse.files, refreshAttachment(updated.parse)); |
| 165 | + current = updated; |
| 166 | + break; |
| 167 | + } |
| 168 | + default: |
| 169 | + throw new Error("Unrecognized event: " + event); |
154 | 170 | }
|
155 | 171 | };
|
156 | 172 | }
|
|
0 commit comments