@proletariat/cli 0.3.87 → 0.3.89
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/commands/db/repair.d.ts +14 -0
- package/dist/commands/db/repair.js +186 -0
- package/dist/commands/db/repair.js.map +1 -0
- package/dist/commands/init.d.ts +6 -1
- package/dist/commands/init.js +44 -89
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/new.d.ts +30 -2
- package/dist/commands/new.js +141 -9
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/session/list.js +42 -0
- package/dist/commands/session/list.js.map +1 -1
- package/dist/commands/session/poke.d.ts +6 -0
- package/dist/commands/session/poke.js +40 -0
- package/dist/commands/session/poke.js.map +1 -1
- package/dist/commands/work/start.d.ts +1 -0
- package/dist/commands/work/start.js +20 -1
- package/dist/commands/work/start.js.map +1 -1
- package/dist/hooks/init.js +3 -6
- package/dist/hooks/init.js.map +1 -1
- package/dist/lib/asana/config.d.ts +1 -1
- package/dist/lib/asana/config.js +18 -30
- package/dist/lib/asana/config.js.map +1 -1
- package/dist/lib/asana/mapper.d.ts +4 -3
- package/dist/lib/asana/mapper.js +17 -10
- package/dist/lib/asana/mapper.js.map +1 -1
- package/dist/lib/dashboard/data.js +2 -2
- package/dist/lib/dashboard/data.js.map +1 -1
- package/dist/lib/database/agents.d.ts +73 -0
- package/dist/lib/database/agents.js +341 -0
- package/dist/lib/database/agents.js.map +1 -0
- package/dist/lib/database/db-safety.d.ts +59 -0
- package/dist/lib/database/db-safety.js +295 -0
- package/dist/lib/database/db-safety.js.map +1 -0
- package/dist/lib/database/driver.d.ts +115 -0
- package/dist/lib/database/driver.js +110 -0
- package/dist/lib/database/driver.js.map +1 -0
- package/dist/lib/database/index.d.ts +26 -287
- package/dist/lib/database/index.js +37 -1067
- package/dist/lib/database/index.js.map +1 -1
- package/dist/lib/database/media.d.ts +53 -0
- package/dist/lib/database/media.js +118 -0
- package/dist/lib/database/media.js.map +1 -0
- package/dist/lib/database/migrations/0012_add_action_network_allowlist.d.ts +9 -0
- package/dist/lib/database/migrations/0012_add_action_network_allowlist.js +22 -0
- package/dist/lib/database/migrations/0012_add_action_network_allowlist.js.map +1 -0
- package/dist/lib/database/migrations/index.js +2 -0
- package/dist/lib/database/migrations/index.js.map +1 -1
- package/dist/lib/database/pmo-bootstrap.d.ts +30 -0
- package/dist/lib/database/pmo-bootstrap.js +105 -0
- package/dist/lib/database/pmo-bootstrap.js.map +1 -0
- package/dist/lib/database/repositories.d.ts +26 -0
- package/dist/lib/database/repositories.js +56 -0
- package/dist/lib/database/repositories.js.map +1 -0
- package/dist/lib/database/settings-store.d.ts +60 -0
- package/dist/lib/database/settings-store.js +87 -0
- package/dist/lib/database/settings-store.js.map +1 -0
- package/dist/lib/database/themes.d.ts +59 -0
- package/dist/lib/database/themes.js +212 -0
- package/dist/lib/database/themes.js.map +1 -0
- package/dist/lib/database/workspace.d.ts +51 -0
- package/dist/lib/database/workspace.js +194 -0
- package/dist/lib/database/workspace.js.map +1 -0
- package/dist/lib/database/worktrees.d.ts +33 -0
- package/dist/lib/database/worktrees.js +60 -0
- package/dist/lib/database/worktrees.js.map +1 -0
- package/dist/lib/execution/config.d.ts +14 -1
- package/dist/lib/execution/config.js +67 -17
- package/dist/lib/execution/config.js.map +1 -1
- package/dist/lib/execution/devcontainer.d.ts +2 -0
- package/dist/lib/execution/devcontainer.js +6 -1
- package/dist/lib/execution/devcontainer.js.map +1 -1
- package/dist/lib/execution/runners/docker-management.d.ts +6 -0
- package/dist/lib/execution/runners/docker-management.js +28 -12
- package/dist/lib/execution/runners/docker-management.js.map +1 -1
- package/dist/lib/execution/runners/sandbox.js +2 -1
- package/dist/lib/execution/runners/sandbox.js.map +1 -1
- package/dist/lib/execution/spawner.d.ts +3 -1
- package/dist/lib/execution/spawner.js +1 -0
- package/dist/lib/execution/spawner.js.map +1 -1
- package/dist/lib/execution/storage.d.ts +47 -12
- package/dist/lib/execution/storage.js +69 -47
- package/dist/lib/execution/storage.js.map +1 -1
- package/dist/lib/execution/types.d.ts +1 -0
- package/dist/lib/execution/types.js.map +1 -1
- package/dist/lib/external-issues/mapping-store.d.ts +4 -3
- package/dist/lib/external-issues/mapping-store.js +21 -13
- package/dist/lib/external-issues/mapping-store.js.map +1 -1
- package/dist/lib/external-issues/outbound-sync.d.ts +1 -1
- package/dist/lib/jira/config.d.ts +1 -6
- package/dist/lib/jira/config.js +16 -33
- package/dist/lib/jira/config.js.map +1 -1
- package/dist/lib/linear/config.d.ts +1 -1
- package/dist/lib/linear/config.js +16 -38
- package/dist/lib/linear/config.js.map +1 -1
- package/dist/lib/linear/mapper.d.ts +4 -3
- package/dist/lib/linear/mapper.js +20 -13
- package/dist/lib/linear/mapper.js.map +1 -1
- package/dist/lib/monday/config.d.ts +1 -1
- package/dist/lib/monday/config.js +16 -32
- package/dist/lib/monday/config.js.map +1 -1
- package/dist/lib/monday/mapper.d.ts +4 -3
- package/dist/lib/monday/mapper.js +19 -12
- package/dist/lib/monday/mapper.js.map +1 -1
- package/dist/lib/onboarding/wizard.d.ts +2 -2
- package/dist/lib/onboarding/wizard.js +32 -24
- package/dist/lib/onboarding/wizard.js.map +1 -1
- package/dist/lib/pmo/diet.d.ts +1 -1
- package/dist/lib/pmo/find-pmo.js +10 -10
- package/dist/lib/pmo/find-pmo.js.map +1 -1
- package/dist/lib/pmo/schema.d.ts +1 -1
- package/dist/lib/pmo/schema.js +1 -0
- package/dist/lib/pmo/schema.js.map +1 -1
- package/dist/lib/pmo/storage/actions.js +9 -3
- package/dist/lib/pmo/storage/actions.js.map +1 -1
- package/dist/lib/pmo/storage/index.d.ts +8 -0
- package/dist/lib/pmo/storage/index.js +13 -1
- package/dist/lib/pmo/storage/index.js.map +1 -1
- package/dist/lib/pmo/storage/types.d.ts +5 -1
- package/dist/lib/pmo/types.d.ts +1 -0
- package/dist/lib/pmo/types.js.map +1 -1
- package/dist/lib/registry/index.d.ts +2 -2
- package/dist/lib/registry/index.js +5 -6
- package/dist/lib/registry/index.js.map +1 -1
- package/dist/lib/session-store.js +2 -2
- package/dist/lib/session-store.js.map +1 -1
- package/dist/lib/shortcut/config.d.ts +1 -7
- package/dist/lib/shortcut/config.js +13 -32
- package/dist/lib/shortcut/config.js.map +1 -1
- package/dist/lib/trello/config.d.ts +1 -26
- package/dist/lib/trello/config.js +23 -64
- package/dist/lib/trello/config.js.map +1 -1
- package/dist/lib/trello/mapper.d.ts +4 -3
- package/dist/lib/trello/mapper.js +17 -10
- package/dist/lib/trello/mapper.js.map +1 -1
- package/dist/lib/work-lifecycle/action-chaining.js +4 -0
- package/dist/lib/work-lifecycle/action-chaining.js.map +1 -1
- package/dist/lib/work-lifecycle/post-execution.d.ts +1 -1
- package/dist/lib/work-source/config.d.ts +1 -1
- package/dist/lib/work-source/config.js +14 -24
- package/dist/lib/work-source/config.js.map +1 -1
- package/dist/lib/work-source/provider-sources.d.ts +1 -1
- package/dist/lib/work-source/provider-sources.js +8 -20
- package/dist/lib/work-source/provider-sources.js.map +1 -1
- package/oclif.manifest.json +1111 -1001
- package/package.json +1 -1
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Safety — WAL mode, auto-backup, corruption recovery.
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - WAL journal mode configuration
|
|
6
|
+
* - Rotating backup (keeps last 5 copies)
|
|
7
|
+
* - Integrity check on open with auto-recovery
|
|
8
|
+
* - Manual repair via dump/reimport
|
|
9
|
+
*
|
|
10
|
+
* See: PRLT-1081
|
|
11
|
+
*/
|
|
12
|
+
import Database from 'better-sqlite3';
|
|
13
|
+
import * as fs from 'node:fs';
|
|
14
|
+
import * as path from 'node:path';
|
|
15
|
+
const MAX_BACKUPS = 5;
|
|
16
|
+
/**
|
|
17
|
+
* Enable WAL journal mode on a database connection.
|
|
18
|
+
* WAL allows concurrent readers with one writer and is significantly
|
|
19
|
+
* more resistant to corruption than the default journal_mode=delete.
|
|
20
|
+
*/
|
|
21
|
+
export function enableWALMode(db) {
|
|
22
|
+
db.pragma('journal_mode = WAL');
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get the backup path for a given database path and backup number.
|
|
26
|
+
*/
|
|
27
|
+
export function getBackupPath(dbPath, n) {
|
|
28
|
+
return `${dbPath}.backup.${n}`;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Create a rotating backup of the database file.
|
|
32
|
+
* Keeps the last MAX_BACKUPS copies, numbered 1 (newest) through MAX_BACKUPS (oldest).
|
|
33
|
+
* Rotates existing backups before copying the current database.
|
|
34
|
+
*
|
|
35
|
+
* Returns true if backup was created, false if source didn't exist.
|
|
36
|
+
*/
|
|
37
|
+
export function createRotatingBackup(dbPath) {
|
|
38
|
+
if (!fs.existsSync(dbPath)) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
// Rotate existing backups: delete oldest, shift others up
|
|
42
|
+
const oldest = getBackupPath(dbPath, MAX_BACKUPS);
|
|
43
|
+
if (fs.existsSync(oldest)) {
|
|
44
|
+
fs.unlinkSync(oldest);
|
|
45
|
+
}
|
|
46
|
+
for (let i = MAX_BACKUPS - 1; i >= 1; i--) {
|
|
47
|
+
const src = getBackupPath(dbPath, i);
|
|
48
|
+
const dst = getBackupPath(dbPath, i + 1);
|
|
49
|
+
if (fs.existsSync(src)) {
|
|
50
|
+
fs.renameSync(src, dst);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Copy current database as backup.1 (newest)
|
|
54
|
+
try {
|
|
55
|
+
fs.copyFileSync(dbPath, getBackupPath(dbPath, 1));
|
|
56
|
+
// Also copy WAL and SHM files if they exist (for WAL-mode databases)
|
|
57
|
+
const walPath = `${dbPath}-wal`;
|
|
58
|
+
const shmPath = `${dbPath}-shm`;
|
|
59
|
+
if (fs.existsSync(walPath)) {
|
|
60
|
+
fs.copyFileSync(walPath, `${getBackupPath(dbPath, 1)}-wal`);
|
|
61
|
+
}
|
|
62
|
+
if (fs.existsSync(shmPath)) {
|
|
63
|
+
fs.copyFileSync(shmPath, `${getBackupPath(dbPath, 1)}-shm`);
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Backup failure is not fatal — log and continue
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Run PRAGMA integrity_check on a database.
|
|
74
|
+
* Returns { ok: true } if the database is healthy, or { ok: false, errors } with details.
|
|
75
|
+
*/
|
|
76
|
+
export function checkIntegrity(db) {
|
|
77
|
+
try {
|
|
78
|
+
const rows = db.pragma('integrity_check');
|
|
79
|
+
const errors = rows
|
|
80
|
+
.map(r => r.integrity_check)
|
|
81
|
+
.filter(msg => msg !== 'ok');
|
|
82
|
+
return { ok: errors.length === 0, errors };
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
return {
|
|
86
|
+
ok: false,
|
|
87
|
+
errors: [error instanceof Error ? error.message : String(error)],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Quick integrity check using PRAGMA quick_check (faster than full integrity_check).
|
|
93
|
+
* Skips checking that the contents of table rows match the indexes.
|
|
94
|
+
*/
|
|
95
|
+
export function quickCheckIntegrity(db) {
|
|
96
|
+
try {
|
|
97
|
+
const rows = db.pragma('quick_check');
|
|
98
|
+
const errors = rows
|
|
99
|
+
.map(r => r.quick_check)
|
|
100
|
+
.filter(msg => msg !== 'ok');
|
|
101
|
+
return { ok: errors.length === 0, errors };
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
return {
|
|
105
|
+
ok: false,
|
|
106
|
+
errors: [error instanceof Error ? error.message : String(error)],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Attempt to repair a corrupted database.
|
|
112
|
+
*
|
|
113
|
+
* Strategy:
|
|
114
|
+
* 1. Try dump/reimport — opens the corrupt DB, dumps all SQL, creates a new DB
|
|
115
|
+
* 2. If dump fails, fall back to the most recent backup
|
|
116
|
+
*
|
|
117
|
+
* The original corrupt file is preserved as dbPath.corrupt for forensics.
|
|
118
|
+
*/
|
|
119
|
+
export function repairDatabase(dbPath) {
|
|
120
|
+
// Try dump/reimport first
|
|
121
|
+
const dumpResult = attemptDumpReimport(dbPath);
|
|
122
|
+
if (dumpResult.success) {
|
|
123
|
+
return dumpResult;
|
|
124
|
+
}
|
|
125
|
+
// Fall back to backup restore
|
|
126
|
+
const backupResult = attemptBackupRestore(dbPath);
|
|
127
|
+
if (backupResult.success) {
|
|
128
|
+
return backupResult;
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
success: false,
|
|
132
|
+
method: 'none',
|
|
133
|
+
message: `Could not repair database. Dump failed: ${dumpResult.message}. No usable backups found.`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Attempt recovery via .dump and reimport.
|
|
138
|
+
* Opens the corrupt database, extracts as much SQL as possible,
|
|
139
|
+
* then creates a fresh database from that SQL.
|
|
140
|
+
*/
|
|
141
|
+
function attemptDumpReimport(dbPath) {
|
|
142
|
+
let corruptDb = null;
|
|
143
|
+
let newDb = null;
|
|
144
|
+
const tempPath = `${dbPath}.repair-temp`;
|
|
145
|
+
try {
|
|
146
|
+
// Open corrupt database — may partially work
|
|
147
|
+
corruptDb = new Database(dbPath, { readonly: true });
|
|
148
|
+
// Dump all recoverable SQL
|
|
149
|
+
const tables = corruptDb.prepare("SELECT sql FROM sqlite_master WHERE sql IS NOT NULL ORDER BY CASE type WHEN 'table' THEN 1 WHEN 'index' THEN 2 ELSE 3 END").all();
|
|
150
|
+
if (tables.length === 0) {
|
|
151
|
+
return { success: false, method: 'dump-reimport', message: 'No tables found in corrupt database' };
|
|
152
|
+
}
|
|
153
|
+
// Create new database with recovered schema
|
|
154
|
+
newDb = new Database(tempPath);
|
|
155
|
+
newDb.pragma('journal_mode = WAL');
|
|
156
|
+
for (const { sql } of tables) {
|
|
157
|
+
try {
|
|
158
|
+
newDb.exec(sql);
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// Skip objects that fail to recreate (e.g., references to missing tables)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Copy data table by table
|
|
165
|
+
const tableNames = corruptDb.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'").all();
|
|
166
|
+
let rowsRecovered = 0;
|
|
167
|
+
for (const { name } of tableNames) {
|
|
168
|
+
try {
|
|
169
|
+
const rows = corruptDb.prepare(`SELECT * FROM "${name}"`).all();
|
|
170
|
+
if (rows.length === 0)
|
|
171
|
+
continue;
|
|
172
|
+
const columns = Object.keys(rows[0]);
|
|
173
|
+
const placeholders = columns.map(() => '?').join(', ');
|
|
174
|
+
const insertSql = `INSERT OR IGNORE INTO "${name}" (${columns.map(c => `"${c}"`).join(', ')}) VALUES (${placeholders})`;
|
|
175
|
+
const insertStmt = newDb.prepare(insertSql);
|
|
176
|
+
const insertAll = newDb.transaction((data) => {
|
|
177
|
+
for (const row of data) {
|
|
178
|
+
insertStmt.run(...columns.map(c => row[c]));
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
insertAll(rows);
|
|
182
|
+
rowsRecovered += rows.length;
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// Skip tables that can't be read
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
corruptDb.close();
|
|
189
|
+
corruptDb = null;
|
|
190
|
+
newDb.close();
|
|
191
|
+
newDb = null;
|
|
192
|
+
// Swap files: corrupt → .corrupt, repaired → original
|
|
193
|
+
const corruptBackupPath = `${dbPath}.corrupt`;
|
|
194
|
+
if (fs.existsSync(corruptBackupPath)) {
|
|
195
|
+
fs.unlinkSync(corruptBackupPath);
|
|
196
|
+
}
|
|
197
|
+
fs.renameSync(dbPath, corruptBackupPath);
|
|
198
|
+
fs.renameSync(tempPath, dbPath);
|
|
199
|
+
// Clean up old WAL/SHM files from the corrupt database
|
|
200
|
+
for (const suffix of ['-wal', '-shm']) {
|
|
201
|
+
const f = `${dbPath}${suffix}`;
|
|
202
|
+
if (fs.existsSync(f)) {
|
|
203
|
+
fs.unlinkSync(f);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
success: true,
|
|
208
|
+
method: 'dump-reimport',
|
|
209
|
+
message: `Recovered ${rowsRecovered} rows from ${tableNames.length} tables. Corrupt file saved as ${path.basename(corruptBackupPath)}.`,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
// Clean up on failure
|
|
214
|
+
if (corruptDb) {
|
|
215
|
+
try {
|
|
216
|
+
corruptDb.close();
|
|
217
|
+
}
|
|
218
|
+
catch { /* ignore */ }
|
|
219
|
+
}
|
|
220
|
+
if (newDb) {
|
|
221
|
+
try {
|
|
222
|
+
newDb.close();
|
|
223
|
+
}
|
|
224
|
+
catch { /* ignore */ }
|
|
225
|
+
}
|
|
226
|
+
if (fs.existsSync(tempPath)) {
|
|
227
|
+
try {
|
|
228
|
+
fs.unlinkSync(tempPath);
|
|
229
|
+
}
|
|
230
|
+
catch { /* ignore */ }
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
success: false,
|
|
234
|
+
method: 'dump-reimport',
|
|
235
|
+
message: error instanceof Error ? error.message : String(error),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Attempt recovery by restoring from the most recent valid backup.
|
|
241
|
+
* Tries backups 1 through MAX_BACKUPS, validates each with integrity_check.
|
|
242
|
+
*/
|
|
243
|
+
function attemptBackupRestore(dbPath) {
|
|
244
|
+
for (let i = 1; i <= MAX_BACKUPS; i++) {
|
|
245
|
+
const backupPath = getBackupPath(dbPath, i);
|
|
246
|
+
if (!fs.existsSync(backupPath)) {
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
// Validate the backup
|
|
250
|
+
let backupDb = null;
|
|
251
|
+
try {
|
|
252
|
+
backupDb = new Database(backupPath, { readonly: true });
|
|
253
|
+
const check = checkIntegrity(backupDb);
|
|
254
|
+
backupDb.close();
|
|
255
|
+
backupDb = null;
|
|
256
|
+
if (!check.ok) {
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
// Backup is valid — swap it in
|
|
260
|
+
const corruptBackupPath = `${dbPath}.corrupt`;
|
|
261
|
+
if (fs.existsSync(corruptBackupPath)) {
|
|
262
|
+
fs.unlinkSync(corruptBackupPath);
|
|
263
|
+
}
|
|
264
|
+
fs.renameSync(dbPath, corruptBackupPath);
|
|
265
|
+
fs.copyFileSync(backupPath, dbPath);
|
|
266
|
+
// Clean up old WAL/SHM files
|
|
267
|
+
for (const suffix of ['-wal', '-shm']) {
|
|
268
|
+
const f = `${dbPath}${suffix}`;
|
|
269
|
+
if (fs.existsSync(f)) {
|
|
270
|
+
fs.unlinkSync(f);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
success: true,
|
|
275
|
+
method: 'backup-restore',
|
|
276
|
+
message: `Restored from backup.${i}. Corrupt file saved as ${path.basename(corruptBackupPath)}.`,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
if (backupDb) {
|
|
281
|
+
try {
|
|
282
|
+
backupDb.close();
|
|
283
|
+
}
|
|
284
|
+
catch { /* ignore */ }
|
|
285
|
+
}
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
success: false,
|
|
291
|
+
method: 'backup-restore',
|
|
292
|
+
message: 'No valid backups found',
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=db-safety.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-safety.js","sourceRoot":"","sources":["../../../src/lib/database/db-safety.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Driver Abstraction Layer
|
|
3
|
+
*
|
|
4
|
+
* Defines a driver-agnostic interface for SQLite database access.
|
|
5
|
+
* This allows swapping the underlying implementation (better-sqlite3, sql.js, etc.)
|
|
6
|
+
* without changing consumer code.
|
|
7
|
+
*
|
|
8
|
+
* All database access in the codebase should go through this interface
|
|
9
|
+
* rather than importing better-sqlite3 directly.
|
|
10
|
+
*/
|
|
11
|
+
import Database from 'better-sqlite3';
|
|
12
|
+
/**
|
|
13
|
+
* Result of executing a statement that modifies data.
|
|
14
|
+
*/
|
|
15
|
+
export interface RunResult {
|
|
16
|
+
/** Number of rows changed by the statement */
|
|
17
|
+
changes: number;
|
|
18
|
+
/** Row ID of the last inserted row */
|
|
19
|
+
lastInsertRowid: number | bigint;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A prepared SQL statement that can be executed with parameters.
|
|
23
|
+
*/
|
|
24
|
+
export interface PreparedStatement<T = Record<string, unknown>> {
|
|
25
|
+
/** Execute the statement and return change info (INSERT/UPDATE/DELETE) */
|
|
26
|
+
run(...params: unknown[]): RunResult;
|
|
27
|
+
/** Execute the statement and return the first matching row */
|
|
28
|
+
get(...params: unknown[]): T | undefined;
|
|
29
|
+
/** Execute the statement and return all matching rows */
|
|
30
|
+
all(...params: unknown[]): T[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Database driver interface that abstracts over the underlying SQLite implementation.
|
|
34
|
+
*
|
|
35
|
+
* This is the single interface through which all database access should flow.
|
|
36
|
+
* Implementations exist for better-sqlite3 (current) with sql.js planned.
|
|
37
|
+
*
|
|
38
|
+
* Usage:
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const driver = createDriver(dbPath)
|
|
41
|
+
* const row = driver.prepare<{ count: number }>('SELECT COUNT(*) as count FROM users').get()
|
|
42
|
+
* driver.close()
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export interface DatabaseDriver {
|
|
46
|
+
/** Prepare a SQL statement for execution */
|
|
47
|
+
prepare<T = Record<string, unknown>>(sql: string): PreparedStatement<T>;
|
|
48
|
+
/** Execute raw SQL (DDL, multi-statement, no return value) */
|
|
49
|
+
exec(sql: string): void;
|
|
50
|
+
/** Get or set SQLite pragmas */
|
|
51
|
+
pragma(source: string, options?: {
|
|
52
|
+
simple?: boolean;
|
|
53
|
+
}): unknown;
|
|
54
|
+
/**
|
|
55
|
+
* Create a transaction function.
|
|
56
|
+
* Returns a new function that, when called, runs the wrapped function
|
|
57
|
+
* inside a SQLite transaction.
|
|
58
|
+
*/
|
|
59
|
+
transaction<F extends (...args: unknown[]) => unknown>(fn: F): F;
|
|
60
|
+
/** Close the database connection */
|
|
61
|
+
close(): void;
|
|
62
|
+
/** Whether the connection is open */
|
|
63
|
+
readonly open: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Access the underlying raw database connection.
|
|
66
|
+
* Use this ONLY for interop with libraries that need the raw connection
|
|
67
|
+
* (e.g., Drizzle ORM). New code should use the driver interface instead.
|
|
68
|
+
* @internal
|
|
69
|
+
*/
|
|
70
|
+
readonly raw: unknown;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* DatabaseDriver implementation backed by better-sqlite3.
|
|
74
|
+
*
|
|
75
|
+
* This is the primary driver used in production. It wraps a better-sqlite3
|
|
76
|
+
* Database instance behind the DatabaseDriver interface.
|
|
77
|
+
*/
|
|
78
|
+
export declare class BetterSqlite3Driver implements DatabaseDriver {
|
|
79
|
+
private db;
|
|
80
|
+
constructor(db: Database.Database);
|
|
81
|
+
prepare<T = Record<string, unknown>>(sql: string): PreparedStatement<T>;
|
|
82
|
+
exec(sql: string): void;
|
|
83
|
+
pragma(source: string, options?: {
|
|
84
|
+
simple?: boolean;
|
|
85
|
+
}): unknown;
|
|
86
|
+
transaction<F extends (...args: unknown[]) => unknown>(fn: F): F;
|
|
87
|
+
close(): void;
|
|
88
|
+
get open(): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Access the underlying better-sqlite3 Database instance.
|
|
91
|
+
* @internal Use for Drizzle ORM interop only.
|
|
92
|
+
*/
|
|
93
|
+
get raw(): Database.Database;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Create a DatabaseDriver from an existing better-sqlite3 Database instance.
|
|
97
|
+
* Useful when migrating existing code that already has a Database object.
|
|
98
|
+
*/
|
|
99
|
+
export declare function wrapDatabase(db: Database.Database): DatabaseDriver;
|
|
100
|
+
/**
|
|
101
|
+
* Create a DatabaseDriver by opening a new better-sqlite3 connection.
|
|
102
|
+
* Configures standard pragmas (WAL mode, foreign keys, busy timeout).
|
|
103
|
+
*/
|
|
104
|
+
export declare function openDriver(dbPath: string, options?: {
|
|
105
|
+
foreignKeys?: boolean;
|
|
106
|
+
busyTimeout?: number;
|
|
107
|
+
}): DatabaseDriver;
|
|
108
|
+
/**
|
|
109
|
+
* Extract the raw better-sqlite3 Database from a driver.
|
|
110
|
+
* Throws if the driver is not a BetterSqlite3Driver.
|
|
111
|
+
*
|
|
112
|
+
* Use this for interop with code that still requires the raw connection
|
|
113
|
+
* (e.g., Drizzle ORM, legacy code being migrated).
|
|
114
|
+
*/
|
|
115
|
+
export declare function getRawDatabase(driver: DatabaseDriver): Database.Database;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Driver Abstraction Layer
|
|
3
|
+
*
|
|
4
|
+
* Defines a driver-agnostic interface for SQLite database access.
|
|
5
|
+
* This allows swapping the underlying implementation (better-sqlite3, sql.js, etc.)
|
|
6
|
+
* without changing consumer code.
|
|
7
|
+
*
|
|
8
|
+
* All database access in the codebase should go through this interface
|
|
9
|
+
* rather than importing better-sqlite3 directly.
|
|
10
|
+
*/
|
|
11
|
+
import Database from 'better-sqlite3';
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// BetterSqlite3 Driver Implementation
|
|
14
|
+
// =============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* DatabaseDriver implementation backed by better-sqlite3.
|
|
17
|
+
*
|
|
18
|
+
* This is the primary driver used in production. It wraps a better-sqlite3
|
|
19
|
+
* Database instance behind the DatabaseDriver interface.
|
|
20
|
+
*/
|
|
21
|
+
export class BetterSqlite3Driver {
|
|
22
|
+
db;
|
|
23
|
+
constructor(db) {
|
|
24
|
+
this.db = db;
|
|
25
|
+
}
|
|
26
|
+
prepare(sql) {
|
|
27
|
+
const stmt = this.db.prepare(sql);
|
|
28
|
+
return {
|
|
29
|
+
run: (...params) => {
|
|
30
|
+
const result = stmt.run(...params);
|
|
31
|
+
return { changes: result.changes, lastInsertRowid: result.lastInsertRowid };
|
|
32
|
+
},
|
|
33
|
+
get: (...params) => {
|
|
34
|
+
return stmt.get(...params);
|
|
35
|
+
},
|
|
36
|
+
all: (...params) => {
|
|
37
|
+
return stmt.all(...params);
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
exec(sql) {
|
|
42
|
+
this.db.exec(sql);
|
|
43
|
+
}
|
|
44
|
+
pragma(source, options) {
|
|
45
|
+
return this.db.pragma(source, options);
|
|
46
|
+
}
|
|
47
|
+
transaction(fn) {
|
|
48
|
+
return this.db.transaction(fn);
|
|
49
|
+
}
|
|
50
|
+
close() {
|
|
51
|
+
this.db.close();
|
|
52
|
+
}
|
|
53
|
+
get open() {
|
|
54
|
+
return this.db.open;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Access the underlying better-sqlite3 Database instance.
|
|
58
|
+
* @internal Use for Drizzle ORM interop only.
|
|
59
|
+
*/
|
|
60
|
+
get raw() {
|
|
61
|
+
return this.db;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// =============================================================================
|
|
65
|
+
// Factory Functions
|
|
66
|
+
// =============================================================================
|
|
67
|
+
/**
|
|
68
|
+
* Create a DatabaseDriver from an existing better-sqlite3 Database instance.
|
|
69
|
+
* Useful when migrating existing code that already has a Database object.
|
|
70
|
+
*/
|
|
71
|
+
export function wrapDatabase(db) {
|
|
72
|
+
return new BetterSqlite3Driver(db);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Create a DatabaseDriver by opening a new better-sqlite3 connection.
|
|
76
|
+
* Configures standard pragmas (WAL mode, foreign keys, busy timeout).
|
|
77
|
+
*/
|
|
78
|
+
export function openDriver(dbPath, options) {
|
|
79
|
+
const db = new Database(dbPath);
|
|
80
|
+
db.pragma('journal_mode = WAL');
|
|
81
|
+
if (options?.foreignKeys !== false) {
|
|
82
|
+
db.pragma('foreign_keys = ON');
|
|
83
|
+
}
|
|
84
|
+
if (options?.busyTimeout !== undefined) {
|
|
85
|
+
db.pragma(`busy_timeout = ${options.busyTimeout}`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
db.pragma('busy_timeout = 5000');
|
|
89
|
+
}
|
|
90
|
+
return new BetterSqlite3Driver(db);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Extract the raw better-sqlite3 Database from a driver.
|
|
94
|
+
* Throws if the driver is not a BetterSqlite3Driver.
|
|
95
|
+
*
|
|
96
|
+
* Use this for interop with code that still requires the raw connection
|
|
97
|
+
* (e.g., Drizzle ORM, legacy code being migrated).
|
|
98
|
+
*/
|
|
99
|
+
export function getRawDatabase(driver) {
|
|
100
|
+
if (driver instanceof BetterSqlite3Driver) {
|
|
101
|
+
return driver.raw;
|
|
102
|
+
}
|
|
103
|
+
// For other driver implementations, check the raw property
|
|
104
|
+
const raw = driver.raw;
|
|
105
|
+
if (raw && typeof raw === 'object' && 'prepare' in raw) {
|
|
106
|
+
return raw;
|
|
107
|
+
}
|
|
108
|
+
throw new Error('Cannot extract raw database from this driver implementation');
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=driver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.js","sourceRoot":"","sources":["../../../src/lib/database/driver.ts"],"names":[],"mappings":"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"}
|