@spool-lab/core 0.4.1 → 0.4.12
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/dist/db/db.d.ts +19 -0
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db.js +210 -15
- package/dist/db/db.js.map +1 -1
- package/dist/db/queries.d.ts +36 -10
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +96 -75
- package/dist/db/queries.js.map +1 -1
- package/dist/db/share-drafts.d.ts +51 -0
- package/dist/db/share-drafts.d.ts.map +1 -0
- package/dist/db/share-drafts.js +47 -0
- package/dist/db/share-drafts.js.map +1 -0
- package/dist/doctor/checks/config.d.ts +3 -0
- package/dist/doctor/checks/config.d.ts.map +1 -0
- package/dist/doctor/checks/config.js +123 -0
- package/dist/doctor/checks/config.js.map +1 -0
- package/dist/doctor/checks/db.d.ts +3 -0
- package/dist/doctor/checks/db.d.ts.map +1 -0
- package/dist/doctor/checks/db.js +225 -0
- package/dist/doctor/checks/db.js.map +1 -0
- package/dist/doctor/checks/env.d.ts +3 -0
- package/dist/doctor/checks/env.d.ts.map +1 -0
- package/dist/doctor/checks/env.js +70 -0
- package/dist/doctor/checks/env.js.map +1 -0
- package/dist/doctor/checks/index.d.ts +3 -0
- package/dist/doctor/checks/index.d.ts.map +1 -0
- package/dist/doctor/checks/index.js +13 -0
- package/dist/doctor/checks/index.js.map +1 -0
- package/dist/doctor/checks/native.d.ts +3 -0
- package/dist/doctor/checks/native.d.ts.map +1 -0
- package/dist/doctor/checks/native.js +42 -0
- package/dist/doctor/checks/native.js.map +1 -0
- package/dist/doctor/checks/versions.d.ts +3 -0
- package/dist/doctor/checks/versions.d.ts.map +1 -0
- package/dist/doctor/checks/versions.js +79 -0
- package/dist/doctor/checks/versions.js.map +1 -0
- package/dist/doctor/index.d.ts +3 -0
- package/dist/doctor/index.d.ts.map +1 -0
- package/dist/doctor/index.js +3 -0
- package/dist/doctor/index.js.map +1 -0
- package/dist/doctor/preflight.d.ts +18 -0
- package/dist/doctor/preflight.d.ts.map +1 -0
- package/dist/doctor/preflight.js +27 -0
- package/dist/doctor/preflight.js.map +1 -0
- package/dist/doctor/runner.d.ts +12 -0
- package/dist/doctor/runner.d.ts.map +1 -0
- package/dist/doctor/runner.js +37 -0
- package/dist/doctor/runner.js.map +1 -0
- package/dist/doctor/types.d.ts +27 -0
- package/dist/doctor/types.d.ts.map +1 -0
- package/dist/doctor/types.js +2 -0
- package/dist/doctor/types.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/migrations/agent-search-cleanup.d.ts +36 -0
- package/dist/migrations/agent-search-cleanup.d.ts.map +1 -0
- package/dist/migrations/agent-search-cleanup.js +182 -0
- package/dist/migrations/agent-search-cleanup.js.map +1 -0
- package/dist/migrations/worktree-identity-upgrade.d.ts +31 -0
- package/dist/migrations/worktree-identity-upgrade.d.ts.map +1 -0
- package/dist/migrations/worktree-identity-upgrade.js +22 -0
- package/dist/migrations/worktree-identity-upgrade.js.map +1 -0
- package/dist/parsers/claude.d.ts.map +1 -1
- package/dist/parsers/claude.js +25 -12
- package/dist/parsers/claude.js.map +1 -1
- package/dist/parsers/codex.d.ts.map +1 -1
- package/dist/parsers/codex.js +32 -5
- package/dist/parsers/codex.js.map +1 -1
- package/dist/parsers/gemini.d.ts.map +1 -1
- package/dist/parsers/gemini.js +5 -5
- package/dist/parsers/gemini.js.map +1 -1
- package/dist/parsers/spool-prelude.d.ts +16 -0
- package/dist/parsers/spool-prelude.d.ts.map +1 -0
- package/dist/parsers/spool-prelude.js +21 -0
- package/dist/parsers/spool-prelude.js.map +1 -0
- package/dist/projects/display-name.d.ts +2 -0
- package/dist/projects/display-name.d.ts.map +1 -0
- package/dist/projects/display-name.js +8 -0
- package/dist/projects/display-name.js.map +1 -0
- package/dist/projects/fs.d.ts +3 -0
- package/dist/projects/fs.d.ts.map +1 -0
- package/dist/projects/fs.js +20 -0
- package/dist/projects/fs.js.map +1 -0
- package/dist/projects/groups.d.ts +4 -0
- package/dist/projects/groups.d.ts.map +1 -0
- package/dist/projects/groups.js +20 -0
- package/dist/projects/groups.js.map +1 -0
- package/dist/projects/identity-synthesizers.d.ts +22 -0
- package/dist/projects/identity-synthesizers.d.ts.map +1 -0
- package/dist/projects/identity-synthesizers.js +29 -0
- package/dist/projects/identity-synthesizers.js.map +1 -0
- package/dist/projects/identity.d.ts +16 -0
- package/dist/projects/identity.d.ts.map +1 -0
- package/dist/projects/identity.js +172 -0
- package/dist/projects/identity.js.map +1 -0
- package/dist/projects/sessions.d.ts +12 -0
- package/dist/projects/sessions.d.ts.map +1 -0
- package/dist/projects/sessions.js +47 -0
- package/dist/projects/sessions.js.map +1 -0
- package/dist/projects/worktree-resolvers.d.ts +19 -0
- package/dist/projects/worktree-resolvers.d.ts.map +1 -0
- package/dist/projects/worktree-resolvers.js +65 -0
- package/dist/projects/worktree-resolvers.js.map +1 -0
- package/dist/sync/syncer.d.ts.map +1 -1
- package/dist/sync/syncer.js +11 -3
- package/dist/sync/syncer.js.map +1 -1
- package/dist/types.d.ts +15 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/doctor/checks/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAU1C,MAAM,KAAK,GAAiB;IAC1B;QACE,EAAE,EAAE,eAAe;QACnB,QAAQ,EAAE,aAAa;QACvB,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,MAAM,CAAC,EAAE;YACjB,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,OAAO,sBAAsB,CAAA;YAChF,OAAO,IAAI,CAAA;QACb,CAAC;KACF;IACD;QACE,EAAE,EAAE,WAAW;QACf,QAAQ,EAAE,SAAS;QACnB,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,MAAM,CAAC,EAAE;YACjB,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,OAAO,sBAAsB,CAAA;YAChF,OAAO,IAAI,CAAA;QACb,CAAC;KACF;IACD;QACE,EAAE,EAAE,uBAAuB;QAC3B,QAAQ,EAAE,qBAAqB;QAC/B,QAAQ,EAAE,KAAK;KAChB;CACF,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAY,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtD,EAAE,EAAE,IAAI,CAAC,EAAE;IACX,QAAQ,EAAE,QAAoB;IAC9B,KAAK,EAAE,IAAI,CAAC,QAAQ;IACpB,GAAG,EAAE,GAAgB,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;CAC9C,CAAC,CAAC,CAAA;AAEH,SAAS,eAAe,CAAC,IAAgB;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC3C,MAAM,IAAI,GAAG;QACX,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,QAAQ,EAAE,QAAoB;QAC9B,KAAK,EAAE,IAAI,CAAC,QAAQ;KACrB,CAAA;IAED,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO;YACL,GAAG,IAAI;YACP,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;YACxC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,CAAC,wBAAwB;YACxE,OAAO,EAAE,EAAE,IAAI,EAAE;SAClB,CAAA;IACH,CAAC;IAED,IAAI,GAAW,CAAA;IACf,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,GAAG,IAAI;YACP,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,gBAAiB,GAAa,CAAC,OAAO,EAAE;YACjD,OAAO,EAAE,EAAE,IAAI,EAAE;SAClB,CAAA;IACH,CAAC;IAED,IAAI,MAAe,CAAA;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,GAAG,IAAI;YACP,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,iBAAkB,GAAa,CAAC,OAAO,EAAE;YAClD,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;YACpC,GAAG,EAAE;gBACH,WAAW,EAAE,mBAAmB,IAAI,CAAC,QAAQ,kBAAkB;gBAC/D,WAAW,EAAE,IAAI;gBACjB,KAAK,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;aACnC;SACF,CAAA;IACH,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;QACjC,IAAI,GAAG,EAAE,CAAC;YACR,OAAO;gBACL,GAAG,IAAI;gBACP,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,iBAAiB,GAAG,EAAE;gBAC/B,OAAO,EAAE,EAAE,IAAI,EAAE;gBACjB,GAAG,EAAE;oBACH,WAAW,EAAE,qBAAqB,IAAI,CAAC,QAAQ,kBAAkB;oBACjE,WAAW,EAAE,IAAI;oBACjB,KAAK,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;iBACnC;aACF,CAAA;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,GAAG,IAAI;QACP,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,UAAU,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG;QAC5C,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;KACrC,CAAA;AACH,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;IACzD,MAAM,MAAM,GAAG,GAAG,IAAI,QAAQ,EAAE,EAAE,CAAA;IAClC,IAAI,CAAC;QACH,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,sBAAuB,GAAa,CAAC,OAAO,EAAE,EAAE,CAAA;IAC/E,CAAC;IACD,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,+BAA+B,MAAM,EAAE,EAAE,CAAA;AACvE,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,IAAI,CAAC,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,IAAI,CAAA;IAC7B,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;IACzD,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;AAC7C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../../src/doctor/checks/db.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAA8B,MAAM,aAAa,CAAA;AAOpE,eAAO,MAAM,QAAQ,EAAE,KAAK,EAmI3B,CAAA"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { existsSync, statSync } from 'node:fs';
|
|
3
|
+
import { DB_PATH } from '../../db/db.js';
|
|
4
|
+
import { probeSqlite } from '../preflight.js';
|
|
5
|
+
const WAL_PATH = `${DB_PATH}-wal`;
|
|
6
|
+
const WAL_WARN_RATIO = 0.5;
|
|
7
|
+
const WAL_WARN_MIN_BYTES = 16 * 1024 * 1024;
|
|
8
|
+
const VACUUM_HINT_RATIO = 0.25;
|
|
9
|
+
export const dbChecks = [
|
|
10
|
+
{
|
|
11
|
+
id: 'db.exists',
|
|
12
|
+
category: 'db',
|
|
13
|
+
title: 'Database file',
|
|
14
|
+
run: () => {
|
|
15
|
+
if (!existsSync(DB_PATH)) {
|
|
16
|
+
return {
|
|
17
|
+
id: 'db.exists', category: 'db', title: 'Database file',
|
|
18
|
+
severity: 'warn',
|
|
19
|
+
message: `Not found at ${DB_PATH} — run \`spool sync\` to create it`,
|
|
20
|
+
details: { path: DB_PATH },
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const size = statSync(DB_PATH).size;
|
|
24
|
+
return {
|
|
25
|
+
id: 'db.exists', category: 'db', title: 'Database file',
|
|
26
|
+
severity: 'ok',
|
|
27
|
+
message: `${humanBytes(size)} at ${DB_PATH}`,
|
|
28
|
+
details: { path: DB_PATH, sizeBytes: size },
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: 'db.integrity',
|
|
34
|
+
category: 'db',
|
|
35
|
+
title: 'Database integrity',
|
|
36
|
+
run: () => withReadonlyDb('db.integrity', 'Database integrity', db => {
|
|
37
|
+
const rows = db.pragma('integrity_check');
|
|
38
|
+
const messages = rows.map(r => r.integrity_check);
|
|
39
|
+
if (messages.length === 1 && messages[0] === 'ok') {
|
|
40
|
+
return { severity: 'ok', message: 'integrity_check passed' };
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
severity: 'error',
|
|
44
|
+
message: `integrity_check reported ${messages.length} problem(s)`,
|
|
45
|
+
details: { problems: messages.slice(0, 20) },
|
|
46
|
+
};
|
|
47
|
+
}),
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: 'db.foreign-keys',
|
|
51
|
+
category: 'db',
|
|
52
|
+
title: 'Foreign key consistency',
|
|
53
|
+
run: () => withReadonlyDb('db.foreign-keys', 'Foreign key consistency', db => {
|
|
54
|
+
const rows = db.pragma('foreign_key_check');
|
|
55
|
+
if (rows.length === 0) {
|
|
56
|
+
return { severity: 'ok', message: 'foreign_key_check passed' };
|
|
57
|
+
}
|
|
58
|
+
const byTable = new Map();
|
|
59
|
+
for (const r of rows)
|
|
60
|
+
byTable.set(r.table, (byTable.get(r.table) ?? 0) + 1);
|
|
61
|
+
const summary = Array.from(byTable.entries())
|
|
62
|
+
.map(([t, n]) => `${t}: ${n}`).join(', ');
|
|
63
|
+
const fix = {
|
|
64
|
+
description: `Delete ${rows.length} orphaned row(s) (${summary})`,
|
|
65
|
+
destructive: false,
|
|
66
|
+
apply: () => applyForeignKeyCleanup(rows),
|
|
67
|
+
};
|
|
68
|
+
return {
|
|
69
|
+
severity: 'error',
|
|
70
|
+
message: `${rows.length} orphan row(s) — ${summary}`,
|
|
71
|
+
details: { violations: rows.slice(0, 50) },
|
|
72
|
+
fix,
|
|
73
|
+
};
|
|
74
|
+
}),
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: 'db.wal-size',
|
|
78
|
+
category: 'db',
|
|
79
|
+
title: 'WAL size',
|
|
80
|
+
run: () => {
|
|
81
|
+
if (!existsSync(DB_PATH)) {
|
|
82
|
+
return skipped('db.wal-size', 'WAL size');
|
|
83
|
+
}
|
|
84
|
+
const dbSize = statSync(DB_PATH).size;
|
|
85
|
+
let walSize = 0;
|
|
86
|
+
try {
|
|
87
|
+
walSize = statSync(WAL_PATH).size;
|
|
88
|
+
}
|
|
89
|
+
catch { /* WAL file optional */ }
|
|
90
|
+
const ratio = dbSize > 0 ? walSize / dbSize : 0;
|
|
91
|
+
const oversized = walSize >= WAL_WARN_MIN_BYTES && ratio >= WAL_WARN_RATIO;
|
|
92
|
+
if (!oversized) {
|
|
93
|
+
return {
|
|
94
|
+
id: 'db.wal-size', category: 'db', title: 'WAL size',
|
|
95
|
+
severity: 'ok',
|
|
96
|
+
message: walSize === 0 ? 'WAL empty' : `${humanBytes(walSize)} (${(ratio * 100).toFixed(0)}% of db)`,
|
|
97
|
+
details: { walBytes: walSize, dbBytes: dbSize },
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
id: 'db.wal-size', category: 'db', title: 'WAL size',
|
|
102
|
+
severity: 'warn',
|
|
103
|
+
message: `WAL is ${humanBytes(walSize)} (${(ratio * 100).toFixed(0)}% of db)`,
|
|
104
|
+
details: { walBytes: walSize, dbBytes: dbSize },
|
|
105
|
+
fix: {
|
|
106
|
+
description: 'Checkpoint the WAL into the main database',
|
|
107
|
+
destructive: false,
|
|
108
|
+
apply: () => applyWalCheckpoint(),
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: 'db.vacuum-hint',
|
|
115
|
+
category: 'db',
|
|
116
|
+
title: 'Free-page ratio',
|
|
117
|
+
run: () => withReadonlyDb('db.vacuum-hint', 'Free-page ratio', db => {
|
|
118
|
+
const free = db.pragma('freelist_count')[0]?.freelist_count ?? 0;
|
|
119
|
+
const total = db.pragma('page_count')[0]?.page_count ?? 0;
|
|
120
|
+
const ratio = total > 0 ? free / total : 0;
|
|
121
|
+
const hint = total > 0 && ratio >= VACUUM_HINT_RATIO;
|
|
122
|
+
if (!hint) {
|
|
123
|
+
return {
|
|
124
|
+
severity: 'ok',
|
|
125
|
+
message: total === 0 ? 'empty db' : `${(ratio * 100).toFixed(1)}% free pages`,
|
|
126
|
+
details: { freePages: free, totalPages: total },
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
severity: 'warn',
|
|
131
|
+
message: `${(ratio * 100).toFixed(1)}% of pages are free — vacuum will reclaim space`,
|
|
132
|
+
details: { freePages: free, totalPages: total },
|
|
133
|
+
fix: {
|
|
134
|
+
description: 'Run VACUUM to compact the database',
|
|
135
|
+
destructive: false,
|
|
136
|
+
apply: () => applyVacuum(),
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}),
|
|
140
|
+
},
|
|
141
|
+
];
|
|
142
|
+
function withReadonlyDb(id, title, fn) {
|
|
143
|
+
const sqlite = probeSqlite();
|
|
144
|
+
if (!sqlite.ok) {
|
|
145
|
+
return { id, category: 'db', title, severity: 'warn', message: 'skipped — see `native.sqlite`' };
|
|
146
|
+
}
|
|
147
|
+
if (!existsSync(DB_PATH))
|
|
148
|
+
return skipped(id, title);
|
|
149
|
+
const db = new Database(DB_PATH, { readonly: true, fileMustExist: true });
|
|
150
|
+
try {
|
|
151
|
+
const out = fn(db);
|
|
152
|
+
return { id, category: 'db', title, ...out };
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
db.close();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function skipped(id, title) {
|
|
159
|
+
return {
|
|
160
|
+
id, category: 'db', title,
|
|
161
|
+
severity: 'ok',
|
|
162
|
+
message: 'skipped — no database',
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function applyForeignKeyCleanup(violations) {
|
|
166
|
+
const db = new Database(DB_PATH);
|
|
167
|
+
try {
|
|
168
|
+
db.pragma('foreign_keys = OFF');
|
|
169
|
+
const grouped = new Map();
|
|
170
|
+
for (const v of violations) {
|
|
171
|
+
const arr = grouped.get(v.table) ?? [];
|
|
172
|
+
arr.push(v.rowid);
|
|
173
|
+
grouped.set(v.table, arr);
|
|
174
|
+
}
|
|
175
|
+
const tx = db.transaction(() => {
|
|
176
|
+
for (const [table, rowids] of grouped) {
|
|
177
|
+
const stmt = db.prepare(`DELETE FROM "${table.replace(/"/g, '""')}" WHERE rowid = ?`);
|
|
178
|
+
for (const rid of rowids)
|
|
179
|
+
stmt.run(rid);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
tx();
|
|
183
|
+
return { ok: true, message: `Removed ${violations.length} orphan row(s)` };
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
db.close();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function applyWalCheckpoint() {
|
|
190
|
+
const db = new Database(DB_PATH);
|
|
191
|
+
try {
|
|
192
|
+
const result = db.pragma('wal_checkpoint(TRUNCATE)');
|
|
193
|
+
const r = result[0];
|
|
194
|
+
if (!r)
|
|
195
|
+
return { ok: true, message: 'WAL checkpointed' };
|
|
196
|
+
if (r.busy)
|
|
197
|
+
return { ok: false, message: 'WAL checkpoint reported busy — close other Spool processes and retry' };
|
|
198
|
+
return { ok: true, message: `Checkpointed ${r.checkpointed}/${r.log} frames` };
|
|
199
|
+
}
|
|
200
|
+
finally {
|
|
201
|
+
db.close();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function applyVacuum() {
|
|
205
|
+
const db = new Database(DB_PATH);
|
|
206
|
+
try {
|
|
207
|
+
const before = statSync(DB_PATH).size;
|
|
208
|
+
db.exec('VACUUM');
|
|
209
|
+
const after = statSync(DB_PATH).size;
|
|
210
|
+
return { ok: true, message: `Reclaimed ${humanBytes(Math.max(before - after, 0))}` };
|
|
211
|
+
}
|
|
212
|
+
finally {
|
|
213
|
+
db.close();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function humanBytes(n) {
|
|
217
|
+
if (n < 1024)
|
|
218
|
+
return `${n} B`;
|
|
219
|
+
if (n < 1024 * 1024)
|
|
220
|
+
return `${(n / 1024).toFixed(1)} KB`;
|
|
221
|
+
if (n < 1024 * 1024 * 1024)
|
|
222
|
+
return `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
223
|
+
return `${(n / 1024 / 1024 / 1024).toFixed(1)} GB`;
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../../src/doctor/checks/db.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/doctor/checks/env.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAe,MAAM,aAAa,CAAA;AAKrD,eAAO,MAAM,SAAS,EAAE,KAAK,EA0D5B,CAAA"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { accessSync, constants, mkdirSync, statfsSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { SPOOL_DIR } from '../../db/db.js';
|
|
4
|
+
const MIN_NODE_MAJOR = 20;
|
|
5
|
+
const MIN_FREE_BYTES = 1 * 1024 * 1024 * 1024; // 1 GB
|
|
6
|
+
export const envChecks = [
|
|
7
|
+
{
|
|
8
|
+
id: 'env.node-version',
|
|
9
|
+
category: 'env',
|
|
10
|
+
title: 'Node.js version',
|
|
11
|
+
run: () => {
|
|
12
|
+
const v = process.versions.node;
|
|
13
|
+
const major = Number(v.split('.')[0]);
|
|
14
|
+
if (Number.isNaN(major)) {
|
|
15
|
+
return mk('env.node-version', 'Node.js version', 'warn', `Could not parse Node version (${v})`, { version: v });
|
|
16
|
+
}
|
|
17
|
+
if (major < MIN_NODE_MAJOR) {
|
|
18
|
+
return mk('env.node-version', 'Node.js version', 'error', `Node ${v} is below the minimum supported (≥${MIN_NODE_MAJOR})`, { version: v, minMajor: MIN_NODE_MAJOR });
|
|
19
|
+
}
|
|
20
|
+
return mk('env.node-version', 'Node.js version', 'ok', v, { version: v });
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 'env.spool-dir',
|
|
25
|
+
category: 'env',
|
|
26
|
+
title: 'Spool home directory',
|
|
27
|
+
run: () => {
|
|
28
|
+
const dir = SPOOL_DIR;
|
|
29
|
+
const overrideActive = process.env['SPOOL_DATA_DIR'] !== undefined;
|
|
30
|
+
const defaultDir = `${homedir()}/.spool`;
|
|
31
|
+
try {
|
|
32
|
+
mkdirSync(dir, { recursive: true });
|
|
33
|
+
accessSync(dir, constants.W_OK);
|
|
34
|
+
return mk('env.spool-dir', 'Spool home directory', 'ok', dir, { path: dir, overrideActive, defaultDir });
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
return mk('env.spool-dir', 'Spool home directory', 'error', `Cannot write to ${dir}: ${err.message}`, { path: dir, overrideActive, defaultDir });
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: 'env.disk-space',
|
|
43
|
+
category: 'env',
|
|
44
|
+
title: 'Disk space',
|
|
45
|
+
run: () => {
|
|
46
|
+
try {
|
|
47
|
+
const stat = statfsSync(SPOOL_DIR);
|
|
48
|
+
const free = Number(stat.bavail) * Number(stat.bsize);
|
|
49
|
+
const ok = free >= MIN_FREE_BYTES;
|
|
50
|
+
return mk('env.disk-space', 'Disk space', ok ? 'ok' : 'warn', `${humanBytes(free)} free on ${SPOOL_DIR}`, { freeBytes: free, minFreeBytes: MIN_FREE_BYTES });
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
return mk('env.disk-space', 'Disk space', 'warn', `Could not stat filesystem: ${err.message}`);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
function mk(id, title, severity, message, details) {
|
|
59
|
+
return { id, category: 'env', title, severity, message, ...(details ? { details } : {}) };
|
|
60
|
+
}
|
|
61
|
+
function humanBytes(n) {
|
|
62
|
+
if (n < 1024)
|
|
63
|
+
return `${n} B`;
|
|
64
|
+
if (n < 1024 * 1024)
|
|
65
|
+
return `${(n / 1024).toFixed(1)} KB`;
|
|
66
|
+
if (n < 1024 * 1024 * 1024)
|
|
67
|
+
return `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
68
|
+
return `${(n / 1024 / 1024 / 1024).toFixed(1)} GB`;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../../src/doctor/checks/env.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/doctor/checks/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAOxC,eAAO,MAAM,SAAS,EAAE,KAAK,EAM5B,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { envChecks } from './env.js';
|
|
2
|
+
import { nativeChecks } from './native.js';
|
|
3
|
+
import { versionChecks } from './versions.js';
|
|
4
|
+
import { dbChecks } from './db.js';
|
|
5
|
+
import { configChecks } from './config.js';
|
|
6
|
+
export const allChecks = [
|
|
7
|
+
...envChecks,
|
|
8
|
+
...nativeChecks,
|
|
9
|
+
...versionChecks,
|
|
10
|
+
...dbChecks,
|
|
11
|
+
...configChecks,
|
|
12
|
+
];
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/doctor/checks/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,MAAM,CAAC,MAAM,SAAS,GAAY;IAChC,GAAG,SAAS;IACZ,GAAG,YAAY;IACf,GAAG,aAAa;IAChB,GAAG,QAAQ;IACX,GAAG,YAAY;CAChB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../../src/doctor/checks/native.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAe,MAAM,aAAa,CAAA;AAGrD,eAAO,MAAM,YAAY,EAAE,KAAK,EA2B/B,CAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { probeSqlite } from '../preflight.js';
|
|
2
|
+
export const nativeChecks = [
|
|
3
|
+
{
|
|
4
|
+
id: 'native.sqlite',
|
|
5
|
+
category: 'native',
|
|
6
|
+
title: 'better-sqlite3 native module',
|
|
7
|
+
run: () => {
|
|
8
|
+
const status = probeSqlite();
|
|
9
|
+
if (status.ok) {
|
|
10
|
+
return {
|
|
11
|
+
id: 'native.sqlite',
|
|
12
|
+
category: 'native',
|
|
13
|
+
title: 'better-sqlite3 native module',
|
|
14
|
+
severity: 'ok',
|
|
15
|
+
message: `loaded (Node ${process.version})`,
|
|
16
|
+
details: { node: process.version },
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
id: 'native.sqlite',
|
|
21
|
+
category: 'native',
|
|
22
|
+
title: 'better-sqlite3 native module',
|
|
23
|
+
severity: 'error',
|
|
24
|
+
message: summarizeAbiError(status.error),
|
|
25
|
+
details: { error: status.error.message, node: process.version },
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
function summarizeAbiError(err) {
|
|
31
|
+
const msg = err.message;
|
|
32
|
+
const abiMatch = msg.match(/NODE_MODULE_VERSION (\d+)[\s\S]*?NODE_MODULE_VERSION (\d+)/);
|
|
33
|
+
if (abiMatch) {
|
|
34
|
+
const compiled = abiMatch[1];
|
|
35
|
+
const wanted = abiMatch[2];
|
|
36
|
+
return (`Node ABI mismatch (compiled for v${compiled}, this Node wants v${wanted}). ` +
|
|
37
|
+
`Reinstall the CLI: \`npm i -g @spool-lab/cli\``);
|
|
38
|
+
}
|
|
39
|
+
const oneLine = msg.split('\n')[0] ?? msg;
|
|
40
|
+
return `Failed to load: ${oneLine}`;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native.js","sourceRoot":"","sources":["../../../src/doctor/checks/native.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAE7C,MAAM,CAAC,MAAM,YAAY,GAAY;IACnC;QACE,EAAE,EAAE,eAAe;QACnB,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,8BAA8B;QACrC,GAAG,EAAE,GAAgB,EAAE;YACrB,MAAM,MAAM,GAAG,WAAW,EAAE,CAAA;YAC5B,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;gBACd,OAAO;oBACL,EAAE,EAAE,eAAe;oBACnB,QAAQ,EAAE,QAAQ;oBAClB,KAAK,EAAE,8BAA8B;oBACrC,QAAQ,EAAE,IAAI;oBACd,OAAO,EAAE,gBAAgB,OAAO,CAAC,OAAO,GAAG;oBAC3C,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE;iBACnC,CAAA;YACH,CAAC;YACD,OAAO;gBACL,EAAE,EAAE,eAAe;gBACnB,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,8BAA8B;gBACrC,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC;gBACxC,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE;aAChE,CAAA;QACH,CAAC;KACF;CACF,CAAA;AAED,SAAS,iBAAiB,CAAC,GAAU;IACnC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAA;IACvB,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAA;IACxF,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;QAC5B,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;QAC1B,OAAO,CACL,oCAAoC,QAAQ,sBAAsB,MAAM,KAAK;YAC7E,gDAAgD,CACjD,CAAA;IACH,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAA;IACzC,OAAO,mBAAmB,OAAO,EAAE,CAAA;AACrC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["../../../src/doctor/checks/versions.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAe,MAAM,aAAa,CAAA;AAErD,eAAO,MAAM,aAAa,EAAE,KAAK,EA6EhC,CAAA"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { DB_PATH, LATEST_SCHEMA_VERSION, getDB } from '../../db/db.js';
|
|
4
|
+
import { probeSqlite } from '../preflight.js';
|
|
5
|
+
export const versionChecks = [
|
|
6
|
+
{
|
|
7
|
+
id: 'versions.schema-compat',
|
|
8
|
+
category: 'versions',
|
|
9
|
+
title: 'Database schema compatibility',
|
|
10
|
+
run: () => {
|
|
11
|
+
const sqlite = probeSqlite();
|
|
12
|
+
if (!sqlite.ok) {
|
|
13
|
+
return {
|
|
14
|
+
id: 'versions.schema-compat',
|
|
15
|
+
category: 'versions',
|
|
16
|
+
title: 'Database schema compatibility',
|
|
17
|
+
severity: 'warn',
|
|
18
|
+
message: 'skipped — see `native.sqlite`',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
if (!existsSync(DB_PATH)) {
|
|
22
|
+
return {
|
|
23
|
+
id: 'versions.schema-compat',
|
|
24
|
+
category: 'versions',
|
|
25
|
+
title: 'Database schema compatibility',
|
|
26
|
+
severity: 'ok',
|
|
27
|
+
message: `No database yet — schema will be created at v${LATEST_SCHEMA_VERSION} on first sync`,
|
|
28
|
+
details: { expected: LATEST_SCHEMA_VERSION },
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const db = new Database(DB_PATH, { readonly: true, fileMustExist: true });
|
|
32
|
+
try {
|
|
33
|
+
const row = db.pragma('user_version');
|
|
34
|
+
const current = row[0]?.user_version ?? 0;
|
|
35
|
+
if (current === LATEST_SCHEMA_VERSION) {
|
|
36
|
+
return {
|
|
37
|
+
id: 'versions.schema-compat',
|
|
38
|
+
category: 'versions',
|
|
39
|
+
title: 'Database schema compatibility',
|
|
40
|
+
severity: 'ok',
|
|
41
|
+
message: `v${current}`,
|
|
42
|
+
details: { current, expected: LATEST_SCHEMA_VERSION },
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (current < LATEST_SCHEMA_VERSION) {
|
|
46
|
+
return {
|
|
47
|
+
id: 'versions.schema-compat',
|
|
48
|
+
category: 'versions',
|
|
49
|
+
title: 'Database schema compatibility',
|
|
50
|
+
severity: 'error',
|
|
51
|
+
message: `DB is at v${current}, CLI expects v${LATEST_SCHEMA_VERSION}`,
|
|
52
|
+
details: { current, expected: LATEST_SCHEMA_VERSION },
|
|
53
|
+
fix: {
|
|
54
|
+
description: `Migrate database from v${current} to v${LATEST_SCHEMA_VERSION}`,
|
|
55
|
+
destructive: false,
|
|
56
|
+
apply: () => {
|
|
57
|
+
getDB();
|
|
58
|
+
return { ok: true, message: `Migrated to v${LATEST_SCHEMA_VERSION}` };
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
id: 'versions.schema-compat',
|
|
65
|
+
category: 'versions',
|
|
66
|
+
title: 'Database schema compatibility',
|
|
67
|
+
severity: 'error',
|
|
68
|
+
message: `DB is at v${current} but this CLI only knows up to v${LATEST_SCHEMA_VERSION}. ` +
|
|
69
|
+
`Upgrade the CLI (npm i -g @spool-lab/cli).`,
|
|
70
|
+
details: { current, expected: LATEST_SCHEMA_VERSION },
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
db.close();
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
//# sourceMappingURL=versions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"versions.js","sourceRoot":"","sources":["../../../src/doctor/checks/versions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/doctor/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/doctor/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type SqliteStatus = {
|
|
2
|
+
ok: true;
|
|
3
|
+
} | {
|
|
4
|
+
ok: false;
|
|
5
|
+
error: Error;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Confirms the bundled better-sqlite3 binary can actually load and open a
|
|
9
|
+
* database. The most common failure is a Node ABI mismatch (NODE_MODULE_VERSION)
|
|
10
|
+
* after upgrading Node without rebuilding native modules — that error message
|
|
11
|
+
* is verbose, so we capture it once here and let downstream checks short-circuit
|
|
12
|
+
* with a short pointer to `native.sqlite`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function probeSqlite(): SqliteStatus;
|
|
15
|
+
/** Test hook — reset the cache between runs. */
|
|
16
|
+
export declare function _resetProbeForTest(): void;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=preflight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../../src/doctor/preflight.ts"],"names":[],"mappings":"AAEA,KAAK,YAAY,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAA;AAI9D;;;;;;GAMG;AACH,wBAAgB,WAAW,IAAI,YAAY,CAU1C;AAED,gDAAgD;AAChD,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
let cached = null;
|
|
3
|
+
/**
|
|
4
|
+
* Confirms the bundled better-sqlite3 binary can actually load and open a
|
|
5
|
+
* database. The most common failure is a Node ABI mismatch (NODE_MODULE_VERSION)
|
|
6
|
+
* after upgrading Node without rebuilding native modules — that error message
|
|
7
|
+
* is verbose, so we capture it once here and let downstream checks short-circuit
|
|
8
|
+
* with a short pointer to `native.sqlite`.
|
|
9
|
+
*/
|
|
10
|
+
export function probeSqlite() {
|
|
11
|
+
if (cached)
|
|
12
|
+
return cached;
|
|
13
|
+
try {
|
|
14
|
+
const db = new Database(':memory:');
|
|
15
|
+
db.close();
|
|
16
|
+
cached = { ok: true };
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
cached = { ok: false, error: err instanceof Error ? err : new Error(String(err)) };
|
|
20
|
+
}
|
|
21
|
+
return cached;
|
|
22
|
+
}
|
|
23
|
+
/** Test hook — reset the cache between runs. */
|
|
24
|
+
export function _resetProbeForTest() {
|
|
25
|
+
cached = null;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=preflight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../src/doctor/preflight.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAA;AAIrC,IAAI,MAAM,GAAwB,IAAI,CAAA;AAEtC;;;;;;GAMG;AACH,MAAM,UAAU,WAAW;IACzB,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IACzB,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAA;QACnC,EAAE,CAAC,KAAK,EAAE,CAAA;QACV,MAAM,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;IACvB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAA;IACpF,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,kBAAkB;IAChC,MAAM,GAAG,IAAI,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Check, CheckResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Run every check (or a filtered subset by id). Each check is isolated:
|
|
4
|
+
* a thrown error is converted into an `error` result so one bad check
|
|
5
|
+
* cannot mask the rest of the report.
|
|
6
|
+
*
|
|
7
|
+
* Checks are run sequentially — they share filesystem state and a few
|
|
8
|
+
* (read-only) sqlite connections, and parallelism would buy almost nothing.
|
|
9
|
+
*/
|
|
10
|
+
export declare function runChecks(filterIds?: readonly string[]): Promise<CheckResult[]>;
|
|
11
|
+
export declare function listChecks(): Array<Pick<Check, 'id' | 'category' | 'title'>>;
|
|
12
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/doctor/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAGpD;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CASrF;AAgBD,wBAAgB,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,UAAU,GAAG,OAAO,CAAC,CAAC,CAE5E"}
|