koguma 2.3.2 → 2.3.4
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/cli/log.ts +12 -5
- package/cli/wrangler.ts +3 -68
- package/package.json +1 -1
- package/src/admin/_bundle.ts +1 -1
- package/src/vite.js +17 -20
- package/src/vite.ts +42 -41
package/src/vite.js
CHANGED
|
@@ -2,35 +2,32 @@
|
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
-
function kogumaHMR() {
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const HASH_SUBPATH = `${HASH_DIR}/${
|
|
9
|
-
const SQLITE_GLOB = "**/.koguma/.wrangler/state/v3/d1/**/*.sqlite";
|
|
5
|
+
function kogumaHMR(options = {}) {
|
|
6
|
+
const HASH_DIR = options.kogumaDir ?? ".koguma";
|
|
7
|
+
const HASH_FILE = "dbhash";
|
|
8
|
+
const HASH_SUBPATH = `${HASH_DIR}/${HASH_FILE}`;
|
|
10
9
|
return {
|
|
11
10
|
name: "koguma-hmr",
|
|
12
11
|
configureServer(server) {
|
|
13
12
|
const root = server.config.root;
|
|
14
13
|
const hashDir = join(root, HASH_DIR);
|
|
15
14
|
const hashPath = join(root, HASH_SUBPATH);
|
|
16
|
-
|
|
15
|
+
const wranglerDir = join(root, HASH_DIR, ".wrangler");
|
|
16
|
+
if (!existsSync(hashDir))
|
|
17
|
+
mkdirSync(hashDir, { recursive: true });
|
|
18
|
+
server.watcher.add(hashDir);
|
|
17
19
|
server.watcher.on("change", (file) => {
|
|
18
|
-
if (
|
|
20
|
+
if (file.startsWith(wranglerDir) && file.endsWith(".sqlite")) {
|
|
21
|
+
try {
|
|
22
|
+
const hash = createHash("sha256").update(readFileSync(file)).digest("hex");
|
|
23
|
+
writeFileSync(hashPath, hash);
|
|
24
|
+
} catch {}
|
|
19
25
|
return;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
writeFileSync(hashPath, hash);
|
|
25
|
-
} catch {}
|
|
26
|
+
}
|
|
27
|
+
if (file === hashPath) {
|
|
28
|
+
server.ws.send({ type: "full-reload" });
|
|
29
|
+
}
|
|
26
30
|
});
|
|
27
|
-
server.watcher.add(hashPath);
|
|
28
|
-
},
|
|
29
|
-
handleHotUpdate({ file, server }) {
|
|
30
|
-
if (file.endsWith(HASH_FILENAME) && file.includes(HASH_DIR)) {
|
|
31
|
-
server.ws.send({ type: "full-reload" });
|
|
32
|
-
return [];
|
|
33
|
-
}
|
|
34
31
|
},
|
|
35
32
|
config() {
|
|
36
33
|
return {
|
package/src/vite.ts
CHANGED
|
@@ -15,25 +15,27 @@ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
|
15
15
|
import { join } from 'node:path';
|
|
16
16
|
import type { Plugin } from 'vite';
|
|
17
17
|
|
|
18
|
+
export interface KogumaHMROptions {
|
|
19
|
+
/**
|
|
20
|
+
* Path to the .koguma directory, relative to the Vite project root.
|
|
21
|
+
* Defaults to '.koguma'. Set this if your Vite config lives in a
|
|
22
|
+
* subdirectory of the repo (e.g. '../../.koguma').
|
|
23
|
+
*/
|
|
24
|
+
kogumaDir?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
18
27
|
/**
|
|
19
28
|
* Watches the wrangler local D1 SQLite file and triggers a full browser reload
|
|
20
|
-
* when content
|
|
21
|
-
*
|
|
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.
|
|
29
|
+
* when content changes. Uses a SHA-256 hash file in .koguma/dbhash to debounce
|
|
30
|
+
* the multiple WAL writes that SQLite generates per D1 operation.
|
|
26
31
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
32
|
+
* Also suppresses Vite HMR for content/ since those changes sync through
|
|
33
|
+
* koguma's own pipeline → D1 → API, not through the Vite module graph.
|
|
29
34
|
*/
|
|
30
|
-
export function kogumaHMR(): Plugin {
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const HASH_SUBPATH = `${HASH_DIR}/${
|
|
34
|
-
|
|
35
|
-
// Glob passed to chokidar — must NOT go through path.resolve or the ** breaks
|
|
36
|
-
const SQLITE_GLOB = '**/.koguma/.wrangler/state/v3/d1/**/*.sqlite';
|
|
35
|
+
export function kogumaHMR(options: KogumaHMROptions = {}): Plugin {
|
|
36
|
+
const HASH_DIR = options.kogumaDir ?? '.koguma';
|
|
37
|
+
const HASH_FILE = 'dbhash';
|
|
38
|
+
const HASH_SUBPATH = `${HASH_DIR}/${HASH_FILE}`;
|
|
37
39
|
|
|
38
40
|
return {
|
|
39
41
|
name: 'koguma-hmr',
|
|
@@ -42,38 +44,37 @@ export function kogumaHMR(): Plugin {
|
|
|
42
44
|
const root = server.config.root;
|
|
43
45
|
const hashDir = join(root, HASH_DIR);
|
|
44
46
|
const hashPath = join(root, HASH_SUBPATH);
|
|
47
|
+
const wranglerDir = join(root, HASH_DIR, '.wrangler');
|
|
48
|
+
|
|
49
|
+
// Ensure .koguma exists so chokidar can watch it
|
|
50
|
+
if (!existsSync(hashDir)) mkdirSync(hashDir, { recursive: true });
|
|
45
51
|
|
|
46
|
-
//
|
|
47
|
-
|
|
52
|
+
// Watch .koguma/ directory — covers both the SQLite files inside
|
|
53
|
+
// .wrangler/ and the dbhash file we write ourselves.
|
|
54
|
+
server.watcher.add(hashDir);
|
|
48
55
|
|
|
49
56
|
server.watcher.on('change', (file: string) => {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
// SQLite changed → compute hash and write dbhash file.
|
|
58
|
+
// The next change event for dbhash will trigger the reload.
|
|
59
|
+
if (file.startsWith(wranglerDir) && file.endsWith('.sqlite')) {
|
|
60
|
+
try {
|
|
61
|
+
const hash = createHash('sha256')
|
|
62
|
+
.update(readFileSync(file))
|
|
63
|
+
.digest('hex');
|
|
64
|
+
writeFileSync(hashPath, hash);
|
|
65
|
+
} catch {
|
|
66
|
+
// SQLite may be locked mid-write — next write will succeed
|
|
67
|
+
}
|
|
54
68
|
return;
|
|
55
|
-
try {
|
|
56
|
-
const hash = createHash('sha256')
|
|
57
|
-
.update(readFileSync(file))
|
|
58
|
-
.digest('hex');
|
|
59
|
-
if (!existsSync(hashDir)) mkdirSync(hashDir, { recursive: true });
|
|
60
|
-
writeFileSync(hashPath, hash);
|
|
61
|
-
} catch {
|
|
62
|
-
// SQLite may be locked mid-write — the next write will succeed
|
|
63
69
|
}
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Watch the hash file — Vite does NOT auto-reload non-module files,
|
|
67
|
-
// so handleHotUpdate below is required to send the full-reload signal.
|
|
68
|
-
server.watcher.add(hashPath);
|
|
69
|
-
},
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
// dbhash changed → new content is in D1 → reload the page.
|
|
72
|
+
// We send directly from here rather than via handleHotUpdate because
|
|
73
|
+
// handleHotUpdate only fires for files in Vite's module graph.
|
|
74
|
+
if (file === hashPath) {
|
|
75
|
+
server.ws.send({ type: 'full-reload' });
|
|
76
|
+
}
|
|
77
|
+
});
|
|
77
78
|
},
|
|
78
79
|
|
|
79
80
|
config() {
|