koguma 2.2.3 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/vite.ts ADDED
@@ -0,0 +1,78 @@
1
+ /**
2
+ * koguma/vite — Vite plugin for koguma projects.
3
+ *
4
+ * Usage in vite.config.ts:
5
+ *
6
+ * import { kogumaHMR } from 'koguma/vite';
7
+ *
8
+ * export default defineConfig({
9
+ * plugins: [kogumaHMR()],
10
+ * });
11
+ */
12
+
13
+ import { createHash } from 'node:crypto';
14
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
15
+ import { resolve } from 'node:path';
16
+ import type { Plugin } from 'vite';
17
+
18
+ /**
19
+ * Watches the wrangler local D1 SQLite file and triggers a full browser reload
20
+ * when content actually changes. Rather than watching the binary SQLite directly
21
+ * (which churns 3-4× per operation due to WAL writes), it writes a SHA-256 hash
22
+ * of the DB to `.koguma/dbhash` and watches that text file as the reload trigger.
23
+ *
24
+ * Also suppresses Vite HMR for the `content/` directory, since those edits sync
25
+ * through koguma's own file watcher → D1 → API, not through the Vite module graph.
26
+ *
27
+ * Pair with the `server.proxy` pointing `/api` to `http://localhost:8787` so the
28
+ * browser refetches fresh content on each reload.
29
+ */
30
+ export function kogumaHMR(): Plugin {
31
+ const HASH_FILE = '.koguma/dbhash';
32
+
33
+ return {
34
+ name: 'koguma-hmr',
35
+
36
+ configureServer(server) {
37
+ const root = server.config.root;
38
+ const hashPath = resolve(root, HASH_FILE);
39
+ const kogumaDir = resolve(root, '.koguma');
40
+
41
+ // Watch the wrangler local D1 directory for SQLite changes
42
+ server.watcher.add(resolve(root, '.wrangler/state/v3/d1/**/*.sqlite'));
43
+
44
+ server.watcher.on('change', (file: string) => {
45
+ if (
46
+ !file.includes('.wrangler/state/v3/d1') ||
47
+ !file.endsWith('.sqlite')
48
+ )
49
+ return;
50
+ try {
51
+ const hash = createHash('sha256')
52
+ .update(readFileSync(file))
53
+ .digest('hex');
54
+ if (!existsSync(kogumaDir)) mkdirSync(kogumaDir, { recursive: true });
55
+ writeFileSync(hashPath, hash);
56
+ } catch {
57
+ // SQLite may be locked mid-write — the next write will succeed
58
+ }
59
+ });
60
+
61
+ // Watch the hash file as the actual reload trigger.
62
+ // Vite's default behaviour for a watched file not in the module graph
63
+ // is a full-reload — no handleHotUpdate override needed.
64
+ server.watcher.add(hashPath);
65
+ },
66
+
67
+ config() {
68
+ return {
69
+ server: {
70
+ watch: {
71
+ // content/ changes go through koguma's sync pipeline, not Vite's module graph
72
+ ignored: ['**/content/**']
73
+ }
74
+ }
75
+ };
76
+ }
77
+ };
78
+ }