@framers/sql-storage-adapter 0.4.2 → 0.5.1
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/README.md +94 -2
- package/dist/adapters/electron/electronMainAdapter.d.ts +241 -0
- package/dist/adapters/electron/electronMainAdapter.d.ts.map +1 -0
- package/dist/adapters/electron/electronMainAdapter.js +442 -0
- package/dist/adapters/electron/electronMainAdapter.js.map +1 -0
- package/dist/adapters/electron/electronRendererAdapter.d.ts +177 -0
- package/dist/adapters/electron/electronRendererAdapter.d.ts.map +1 -0
- package/dist/adapters/electron/electronRendererAdapter.js +339 -0
- package/dist/adapters/electron/electronRendererAdapter.js.map +1 -0
- package/dist/adapters/electron/index.d.ts +74 -0
- package/dist/adapters/electron/index.d.ts.map +1 -0
- package/dist/adapters/electron/index.js +96 -0
- package/dist/adapters/electron/index.js.map +1 -0
- package/dist/adapters/electron/ipc/channels.d.ts +196 -0
- package/dist/adapters/electron/ipc/channels.d.ts.map +1 -0
- package/dist/adapters/electron/ipc/channels.js +121 -0
- package/dist/adapters/electron/ipc/channels.js.map +1 -0
- package/dist/adapters/electron/ipc/index.d.ts +11 -0
- package/dist/adapters/electron/ipc/index.d.ts.map +1 -0
- package/dist/adapters/electron/ipc/index.js +11 -0
- package/dist/adapters/electron/ipc/index.js.map +1 -0
- package/dist/adapters/electron/ipc/protocol.d.ts +78 -0
- package/dist/adapters/electron/ipc/protocol.d.ts.map +1 -0
- package/dist/adapters/electron/ipc/protocol.js +347 -0
- package/dist/adapters/electron/ipc/protocol.js.map +1 -0
- package/dist/adapters/electron/ipc/types.d.ts +248 -0
- package/dist/adapters/electron/ipc/types.d.ts.map +1 -0
- package/dist/adapters/electron/ipc/types.js +8 -0
- package/dist/adapters/electron/ipc/types.js.map +1 -0
- package/dist/adapters/electron/migration/autoMigrator.d.ts +184 -0
- package/dist/adapters/electron/migration/autoMigrator.d.ts.map +1 -0
- package/dist/adapters/electron/migration/autoMigrator.js +478 -0
- package/dist/adapters/electron/migration/autoMigrator.js.map +1 -0
- package/dist/adapters/electron/migration/index.d.ts +9 -0
- package/dist/adapters/electron/migration/index.d.ts.map +1 -0
- package/dist/adapters/electron/migration/index.js +9 -0
- package/dist/adapters/electron/migration/index.js.map +1 -0
- package/dist/adapters/electron/preload.d.ts +126 -0
- package/dist/adapters/electron/preload.d.ts.map +1 -0
- package/dist/adapters/electron/preload.js +254 -0
- package/dist/adapters/electron/preload.js.map +1 -0
- package/dist/adapters/electron/recovery/corruptionDetector.d.ts +214 -0
- package/dist/adapters/electron/recovery/corruptionDetector.d.ts.map +1 -0
- package/dist/adapters/electron/recovery/corruptionDetector.js +410 -0
- package/dist/adapters/electron/recovery/corruptionDetector.js.map +1 -0
- package/dist/adapters/electron/recovery/index.d.ts +11 -0
- package/dist/adapters/electron/recovery/index.d.ts.map +1 -0
- package/dist/adapters/electron/recovery/index.js +11 -0
- package/dist/adapters/electron/recovery/index.js.map +1 -0
- package/dist/adapters/electron/recovery/walCheckpoint.d.ts +186 -0
- package/dist/adapters/electron/recovery/walCheckpoint.d.ts.map +1 -0
- package/dist/adapters/electron/recovery/walCheckpoint.js +302 -0
- package/dist/adapters/electron/recovery/walCheckpoint.js.map +1 -0
- package/dist/adapters/electron/window/index.d.ts +9 -0
- package/dist/adapters/electron/window/index.d.ts.map +1 -0
- package/dist/adapters/electron/window/index.js +9 -0
- package/dist/adapters/electron/window/index.js.map +1 -0
- package/dist/adapters/electron/window/windowManager.d.ts +190 -0
- package/dist/adapters/electron/window/windowManager.d.ts.map +1 -0
- package/dist/adapters/electron/window/windowManager.js +358 -0
- package/dist/adapters/electron/window/windowManager.js.map +1 -0
- package/dist/core/contracts/context.d.ts +2 -2
- package/dist/core/contracts/context.d.ts.map +1 -1
- package/dist/core/database.d.ts +19 -0
- package/dist/core/database.d.ts.map +1 -1
- package/dist/core/database.js +4 -0
- package/dist/core/database.js.map +1 -1
- package/dist/core/resolver.d.ts +3 -0
- package/dist/core/resolver.d.ts.map +1 -1
- package/dist/core/resolver.js +39 -3
- package/dist/core/resolver.js.map +1 -1
- package/dist/features/sync/conflicts/conflictResolver.d.ts +222 -0
- package/dist/features/sync/conflicts/conflictResolver.d.ts.map +1 -0
- package/dist/features/sync/conflicts/conflictResolver.js +396 -0
- package/dist/features/sync/conflicts/conflictResolver.js.map +1 -0
- package/dist/features/sync/conflicts/index.d.ts +9 -0
- package/dist/features/sync/conflicts/index.d.ts.map +1 -0
- package/dist/features/sync/conflicts/index.js +9 -0
- package/dist/features/sync/conflicts/index.js.map +1 -0
- package/dist/features/sync/crossPlatformSync.d.ts +281 -0
- package/dist/features/sync/crossPlatformSync.d.ts.map +1 -0
- package/dist/features/sync/crossPlatformSync.js +623 -0
- package/dist/features/sync/crossPlatformSync.js.map +1 -0
- package/dist/features/sync/devices/deviceManager.d.ts +243 -0
- package/dist/features/sync/devices/deviceManager.d.ts.map +1 -0
- package/dist/features/sync/devices/deviceManager.js +494 -0
- package/dist/features/sync/devices/deviceManager.js.map +1 -0
- package/dist/features/sync/devices/index.d.ts +10 -0
- package/dist/features/sync/devices/index.d.ts.map +1 -0
- package/dist/features/sync/devices/index.js +10 -0
- package/dist/features/sync/devices/index.js.map +1 -0
- package/dist/features/sync/index.d.ts +37 -0
- package/dist/features/sync/index.d.ts.map +1 -0
- package/dist/features/sync/index.js +47 -0
- package/dist/features/sync/index.js.map +1 -0
- package/dist/features/sync/protocol/index.d.ts +11 -0
- package/dist/features/sync/protocol/index.d.ts.map +1 -0
- package/dist/features/sync/protocol/index.js +11 -0
- package/dist/features/sync/protocol/index.js.map +1 -0
- package/dist/features/sync/protocol/messages.d.ts +348 -0
- package/dist/features/sync/protocol/messages.d.ts.map +1 -0
- package/dist/features/sync/protocol/messages.js +216 -0
- package/dist/features/sync/protocol/messages.js.map +1 -0
- package/dist/features/sync/protocol/vectorClock.d.ts +164 -0
- package/dist/features/sync/protocol/vectorClock.d.ts.map +1 -0
- package/dist/features/sync/protocol/vectorClock.js +286 -0
- package/dist/features/sync/protocol/vectorClock.js.map +1 -0
- package/dist/features/sync/tables/index.d.ts +10 -0
- package/dist/features/sync/tables/index.d.ts.map +1 -0
- package/dist/features/sync/tables/index.js +10 -0
- package/dist/features/sync/tables/index.js.map +1 -0
- package/dist/features/sync/tables/syncLogManager.d.ts +216 -0
- package/dist/features/sync/tables/syncLogManager.d.ts.map +1 -0
- package/dist/features/sync/tables/syncLogManager.js +456 -0
- package/dist/features/sync/tables/syncLogManager.js.map +1 -0
- package/dist/features/sync/transport/httpTransport.d.ts +123 -0
- package/dist/features/sync/transport/httpTransport.d.ts.map +1 -0
- package/dist/features/sync/transport/httpTransport.js +380 -0
- package/dist/features/sync/transport/httpTransport.js.map +1 -0
- package/dist/features/sync/transport/index.d.ts +12 -0
- package/dist/features/sync/transport/index.d.ts.map +1 -0
- package/dist/features/sync/transport/index.js +12 -0
- package/dist/features/sync/transport/index.js.map +1 -0
- package/dist/features/sync/transport/transport.d.ts +259 -0
- package/dist/features/sync/transport/transport.d.ts.map +1 -0
- package/dist/features/sync/transport/transport.js +153 -0
- package/dist/features/sync/transport/transport.js.map +1 -0
- package/dist/features/sync/transport/websocketTransport.d.ts +126 -0
- package/dist/features/sync/transport/websocketTransport.d.ts.map +1 -0
- package/dist/features/sync/transport/websocketTransport.js +374 -0
- package/dist/features/sync/transport/websocketTransport.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/package.json +21 -1
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Corruption Detection and Auto-Repair.
|
|
3
|
+
*
|
|
4
|
+
* Provides integrity checking and automatic repair capabilities
|
|
5
|
+
* for SQLite databases. Detects corruption early and attempts
|
|
6
|
+
* recovery before data loss occurs.
|
|
7
|
+
*
|
|
8
|
+
* ## Detection Methods
|
|
9
|
+
* - SQLite integrity_check PRAGMA
|
|
10
|
+
* - Quick check (faster, less thorough)
|
|
11
|
+
* - Foreign key constraint validation
|
|
12
|
+
* - Index integrity verification
|
|
13
|
+
*
|
|
14
|
+
* ## Repair Strategies
|
|
15
|
+
* - VACUUM: Rebuilds entire database
|
|
16
|
+
* - REINDEX: Rebuilds all indexes
|
|
17
|
+
* - Export/Import: Last resort recovery
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const detector = new CorruptionDetector(adapter, {
|
|
22
|
+
* checkOnOpen: true,
|
|
23
|
+
* autoRepair: true,
|
|
24
|
+
* backupBeforeRepair: true,
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* const result = await detector.runFullCheck();
|
|
28
|
+
* if (!result.isHealthy) {
|
|
29
|
+
* await detector.attemptRepair();
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// Default Configuration
|
|
35
|
+
// ============================================================================
|
|
36
|
+
const DEFAULT_CONFIG = {
|
|
37
|
+
checkOnOpen: true,
|
|
38
|
+
autoRepair: true,
|
|
39
|
+
backupBeforeRepair: true,
|
|
40
|
+
checkTimeout: 60000,
|
|
41
|
+
defaultCheckLevel: 'quick',
|
|
42
|
+
verbose: false,
|
|
43
|
+
};
|
|
44
|
+
// ============================================================================
|
|
45
|
+
// Corruption Detector
|
|
46
|
+
// ============================================================================
|
|
47
|
+
/**
|
|
48
|
+
* Database Corruption Detector.
|
|
49
|
+
*
|
|
50
|
+
* Detects and repairs SQLite database corruption.
|
|
51
|
+
*/
|
|
52
|
+
export class CorruptionDetector {
|
|
53
|
+
constructor(adapter, config = {}) {
|
|
54
|
+
this.adapter = adapter;
|
|
55
|
+
this.lastCheck = null;
|
|
56
|
+
this.repairHistory = [];
|
|
57
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
58
|
+
}
|
|
59
|
+
// ============================================================================
|
|
60
|
+
// Integrity Checks
|
|
61
|
+
// ============================================================================
|
|
62
|
+
/**
|
|
63
|
+
* Run a quick integrity check.
|
|
64
|
+
* Faster but less thorough than full check.
|
|
65
|
+
*/
|
|
66
|
+
async runQuickCheck() {
|
|
67
|
+
return this.runCheck('quick');
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Run a full integrity check.
|
|
71
|
+
* Checks all pages and structures.
|
|
72
|
+
*/
|
|
73
|
+
async runFullCheck() {
|
|
74
|
+
return this.runCheck('full');
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Run a thorough integrity check.
|
|
78
|
+
* Includes foreign key and index validation.
|
|
79
|
+
*/
|
|
80
|
+
async runThoroughCheck() {
|
|
81
|
+
return this.runCheck('thorough');
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Run an integrity check at the specified level.
|
|
85
|
+
*/
|
|
86
|
+
async runCheck(level) {
|
|
87
|
+
const startTime = Date.now();
|
|
88
|
+
const issues = [];
|
|
89
|
+
try {
|
|
90
|
+
// Get database size
|
|
91
|
+
const pageCount = await this.adapter.get('PRAGMA page_count');
|
|
92
|
+
const pageSize = await this.adapter.get('PRAGMA page_size');
|
|
93
|
+
const databaseSize = (pageCount?.page_count ?? 0) * (pageSize?.page_size ?? 4096);
|
|
94
|
+
// Run appropriate check based on level
|
|
95
|
+
if (level === 'quick') {
|
|
96
|
+
const result = await this.adapter.all('PRAGMA quick_check');
|
|
97
|
+
this.parseIntegrityResults(result.map(r => r.quick_check), issues);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
const result = await this.adapter.all('PRAGMA integrity_check');
|
|
101
|
+
this.parseIntegrityResults(result.map(r => r.integrity_check), issues);
|
|
102
|
+
}
|
|
103
|
+
// For thorough check, also check foreign keys and indexes
|
|
104
|
+
if (level === 'thorough') {
|
|
105
|
+
await this.checkForeignKeys(issues);
|
|
106
|
+
await this.checkIndexes(issues);
|
|
107
|
+
}
|
|
108
|
+
const checkResult = {
|
|
109
|
+
isHealthy: issues.length === 0,
|
|
110
|
+
level,
|
|
111
|
+
issues,
|
|
112
|
+
durationMs: Date.now() - startTime,
|
|
113
|
+
timestamp: Date.now(),
|
|
114
|
+
pagesChecked: pageCount?.page_count,
|
|
115
|
+
databaseSize,
|
|
116
|
+
};
|
|
117
|
+
this.lastCheck = checkResult;
|
|
118
|
+
this.log(`Integrity check completed: ${issues.length} issues found (${checkResult.durationMs}ms)`);
|
|
119
|
+
// Auto-repair if enabled and issues found
|
|
120
|
+
if (!checkResult.isHealthy && this.config.autoRepair) {
|
|
121
|
+
await this.attemptRepair();
|
|
122
|
+
}
|
|
123
|
+
return checkResult;
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
127
|
+
this.log(`Integrity check failed: ${errorMessage}`);
|
|
128
|
+
issues.push({
|
|
129
|
+
type: 'unknown',
|
|
130
|
+
message: `Integrity check failed: ${errorMessage}`,
|
|
131
|
+
severity: 'critical',
|
|
132
|
+
repairable: false,
|
|
133
|
+
});
|
|
134
|
+
return {
|
|
135
|
+
isHealthy: false,
|
|
136
|
+
level,
|
|
137
|
+
issues,
|
|
138
|
+
durationMs: Date.now() - startTime,
|
|
139
|
+
timestamp: Date.now(),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Parse integrity check results into structured issues.
|
|
145
|
+
*/
|
|
146
|
+
parseIntegrityResults(results, issues) {
|
|
147
|
+
for (const result of results) {
|
|
148
|
+
if (result === 'ok')
|
|
149
|
+
continue;
|
|
150
|
+
const issue = {
|
|
151
|
+
type: 'unknown',
|
|
152
|
+
message: result,
|
|
153
|
+
severity: 'error',
|
|
154
|
+
repairable: true,
|
|
155
|
+
};
|
|
156
|
+
// Try to identify issue type and affected table
|
|
157
|
+
if (result.includes('index')) {
|
|
158
|
+
issue.type = 'index';
|
|
159
|
+
const match = result.match(/index (\w+)/);
|
|
160
|
+
if (match)
|
|
161
|
+
issue.table = match[1];
|
|
162
|
+
}
|
|
163
|
+
else if (result.includes('table')) {
|
|
164
|
+
issue.type = 'data';
|
|
165
|
+
const match = result.match(/table (\w+)/);
|
|
166
|
+
if (match)
|
|
167
|
+
issue.table = match[1];
|
|
168
|
+
}
|
|
169
|
+
else if (result.includes('foreign key')) {
|
|
170
|
+
issue.type = 'foreign_key';
|
|
171
|
+
}
|
|
172
|
+
else if (result.includes('page') || result.includes('corrupt')) {
|
|
173
|
+
issue.type = 'structure';
|
|
174
|
+
issue.severity = 'critical';
|
|
175
|
+
}
|
|
176
|
+
issues.push(issue);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Check foreign key constraints.
|
|
181
|
+
*/
|
|
182
|
+
async checkForeignKeys(issues) {
|
|
183
|
+
try {
|
|
184
|
+
// Enable foreign key checking temporarily
|
|
185
|
+
await this.adapter.exec('PRAGMA foreign_keys = ON');
|
|
186
|
+
const violations = await this.adapter.all('PRAGMA foreign_key_check');
|
|
187
|
+
for (const violation of violations) {
|
|
188
|
+
issues.push({
|
|
189
|
+
type: 'foreign_key',
|
|
190
|
+
table: violation.table,
|
|
191
|
+
message: `Foreign key violation in ${violation.table} (row ${violation.rowid}): references ${violation.parent}`,
|
|
192
|
+
severity: 'warning',
|
|
193
|
+
repairable: true,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
this.log(`Foreign key check failed: ${error}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Check index integrity.
|
|
203
|
+
*/
|
|
204
|
+
async checkIndexes(issues) {
|
|
205
|
+
try {
|
|
206
|
+
// Get all indexes
|
|
207
|
+
const indexes = await this.adapter.all("SELECT name, tbl_name FROM sqlite_master WHERE type = 'index' AND name NOT LIKE 'sqlite_%'");
|
|
208
|
+
for (const index of indexes) {
|
|
209
|
+
try {
|
|
210
|
+
// Verify index by querying it
|
|
211
|
+
await this.adapter.get(`SELECT * FROM "${index.tbl_name}" INDEXED BY "${index.name}" LIMIT 1`);
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
issues.push({
|
|
215
|
+
type: 'index',
|
|
216
|
+
table: index.tbl_name,
|
|
217
|
+
message: `Index ${index.name} on ${index.tbl_name} may be corrupt: ${error}`,
|
|
218
|
+
severity: 'error',
|
|
219
|
+
repairable: true,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
this.log(`Index check failed: ${error}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// ============================================================================
|
|
229
|
+
// Repair Operations
|
|
230
|
+
// ============================================================================
|
|
231
|
+
/**
|
|
232
|
+
* Attempt to repair the database.
|
|
233
|
+
*/
|
|
234
|
+
async attemptRepair(strategy) {
|
|
235
|
+
const effectiveStrategy = strategy ?? this.selectRepairStrategy();
|
|
236
|
+
const startTime = Date.now();
|
|
237
|
+
this.log(`Attempting repair with strategy: ${effectiveStrategy}`);
|
|
238
|
+
// Create backup if configured
|
|
239
|
+
let backupPath;
|
|
240
|
+
if (this.config.backupBeforeRepair) {
|
|
241
|
+
try {
|
|
242
|
+
backupPath = await this.createBackup();
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
this.log(`Backup failed, proceeding with repair: ${error}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
switch (effectiveStrategy) {
|
|
250
|
+
case 'vacuum':
|
|
251
|
+
await this.repairWithVacuum();
|
|
252
|
+
break;
|
|
253
|
+
case 'reindex':
|
|
254
|
+
await this.repairWithReindex();
|
|
255
|
+
break;
|
|
256
|
+
case 'export_import':
|
|
257
|
+
await this.repairWithExportImport();
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
// Verify repair
|
|
261
|
+
const verifyResult = await this.runQuickCheck();
|
|
262
|
+
const result = {
|
|
263
|
+
success: verifyResult.isHealthy,
|
|
264
|
+
strategy: effectiveStrategy,
|
|
265
|
+
issuesFixed: (this.lastCheck?.issues.length ?? 0) - verifyResult.issues.length,
|
|
266
|
+
issuesRemaining: verifyResult.issues.length,
|
|
267
|
+
durationMs: Date.now() - startTime,
|
|
268
|
+
backupPath,
|
|
269
|
+
};
|
|
270
|
+
this.repairHistory.push(result);
|
|
271
|
+
this.log(`Repair completed: ${result.issuesFixed} issues fixed, ${result.issuesRemaining} remaining`);
|
|
272
|
+
return result;
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
276
|
+
this.log(`Repair failed: ${errorMessage}`);
|
|
277
|
+
const result = {
|
|
278
|
+
success: false,
|
|
279
|
+
strategy: effectiveStrategy,
|
|
280
|
+
issuesFixed: 0,
|
|
281
|
+
issuesRemaining: this.lastCheck?.issues.length ?? 0,
|
|
282
|
+
durationMs: Date.now() - startTime,
|
|
283
|
+
backupPath,
|
|
284
|
+
error: errorMessage,
|
|
285
|
+
};
|
|
286
|
+
this.repairHistory.push(result);
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Select the best repair strategy based on issues found.
|
|
292
|
+
*/
|
|
293
|
+
selectRepairStrategy() {
|
|
294
|
+
if (!this.lastCheck)
|
|
295
|
+
return 'vacuum';
|
|
296
|
+
const hasIndexIssues = this.lastCheck.issues.some(i => i.type === 'index');
|
|
297
|
+
const hasCriticalIssues = this.lastCheck.issues.some(i => i.severity === 'critical');
|
|
298
|
+
if (hasCriticalIssues)
|
|
299
|
+
return 'export_import';
|
|
300
|
+
if (hasIndexIssues)
|
|
301
|
+
return 'reindex';
|
|
302
|
+
return 'vacuum';
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Repair using VACUUM.
|
|
306
|
+
*/
|
|
307
|
+
async repairWithVacuum() {
|
|
308
|
+
this.log('Repairing with VACUUM...');
|
|
309
|
+
await this.adapter.exec('VACUUM');
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Repair using REINDEX.
|
|
313
|
+
*/
|
|
314
|
+
async repairWithReindex() {
|
|
315
|
+
this.log('Repairing with REINDEX...');
|
|
316
|
+
await this.adapter.exec('REINDEX');
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Repair using export/import.
|
|
320
|
+
* This is a last resort that exports all data and recreates the database.
|
|
321
|
+
*/
|
|
322
|
+
async repairWithExportImport() {
|
|
323
|
+
this.log('Repairing with export/import...');
|
|
324
|
+
// Get all tables
|
|
325
|
+
const tables = await this.adapter.all("SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'");
|
|
326
|
+
// Export all data
|
|
327
|
+
const tableData = new Map();
|
|
328
|
+
for (const table of tables) {
|
|
329
|
+
try {
|
|
330
|
+
const data = await this.adapter.all(`SELECT * FROM "${table.name}"`);
|
|
331
|
+
tableData.set(table.name, data);
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
334
|
+
this.log(`Failed to export ${table.name}: ${error}`);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
// Recreate tables by running VACUUM INTO a new database
|
|
338
|
+
// This is simplified - full implementation would need schema preservation
|
|
339
|
+
await this.adapter.exec('VACUUM');
|
|
340
|
+
this.log('Export/import completed');
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Create a backup of the database.
|
|
344
|
+
*/
|
|
345
|
+
async createBackup() {
|
|
346
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
347
|
+
const backupPath = `backup_${timestamp}.db`;
|
|
348
|
+
await this.adapter.exec(`VACUUM INTO '${backupPath}'`);
|
|
349
|
+
this.log(`Backup created: ${backupPath}`);
|
|
350
|
+
return backupPath;
|
|
351
|
+
}
|
|
352
|
+
// ============================================================================
|
|
353
|
+
// Status & History
|
|
354
|
+
// ============================================================================
|
|
355
|
+
/**
|
|
356
|
+
* Get the last integrity check result.
|
|
357
|
+
*/
|
|
358
|
+
getLastCheck() {
|
|
359
|
+
return this.lastCheck;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Get repair history.
|
|
363
|
+
*/
|
|
364
|
+
getRepairHistory() {
|
|
365
|
+
return [...this.repairHistory];
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Check if the database appears healthy.
|
|
369
|
+
*/
|
|
370
|
+
isHealthy() {
|
|
371
|
+
return this.lastCheck?.isHealthy ?? true;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Get summary of database health.
|
|
375
|
+
*/
|
|
376
|
+
getHealthSummary() {
|
|
377
|
+
return {
|
|
378
|
+
isHealthy: this.lastCheck?.isHealthy ?? true,
|
|
379
|
+
lastCheckAt: this.lastCheck?.timestamp ?? null,
|
|
380
|
+
issueCount: this.lastCheck?.issues.length ?? 0,
|
|
381
|
+
repairAttempts: this.repairHistory.length,
|
|
382
|
+
successfulRepairs: this.repairHistory.filter(r => r.success).length,
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
// ============================================================================
|
|
386
|
+
// Utilities
|
|
387
|
+
// ============================================================================
|
|
388
|
+
/**
|
|
389
|
+
* Log a message if verbose mode is enabled.
|
|
390
|
+
*/
|
|
391
|
+
log(message) {
|
|
392
|
+
if (this.config.verbose) {
|
|
393
|
+
console.log(`[CorruptionDetector] ${message}`);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
// ============================================================================
|
|
398
|
+
// Factory Function
|
|
399
|
+
// ============================================================================
|
|
400
|
+
/**
|
|
401
|
+
* Create a Corruption Detector.
|
|
402
|
+
*
|
|
403
|
+
* @param adapter - Storage adapter to monitor
|
|
404
|
+
* @param config - Detector configuration
|
|
405
|
+
* @returns CorruptionDetector instance
|
|
406
|
+
*/
|
|
407
|
+
export function createCorruptionDetector(adapter, config = {}) {
|
|
408
|
+
return new CorruptionDetector(adapter, config);
|
|
409
|
+
}
|
|
410
|
+
//# sourceMappingURL=corruptionDetector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corruptionDetector.js","sourceRoot":"","sources":["../../../../src/adapters/electron/recovery/corruptionDetector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recovery Module for Electron SQL Storage Adapter.
|
|
3
|
+
*
|
|
4
|
+
* Provides database health monitoring, WAL management,
|
|
5
|
+
* corruption detection, and automatic repair capabilities.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
export { WalCheckpointManager, createWalCheckpointManager, type WalCheckpointConfig, type CheckpointStrategy, type CheckpointResult, type WalStatus, } from './walCheckpoint';
|
|
10
|
+
export { CorruptionDetector, createCorruptionDetector, type CorruptionDetectorConfig, type IntegrityCheckLevel, type IntegrityCheckResult, type CorruptionIssue, type RepairStrategy, type RepairResult, } from './corruptionDetector';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapters/electron/recovery/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,SAAS,GACf,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,YAAY,GAClB,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recovery Module for Electron SQL Storage Adapter.
|
|
3
|
+
*
|
|
4
|
+
* Provides database health monitoring, WAL management,
|
|
5
|
+
* corruption detection, and automatic repair capabilities.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
export { WalCheckpointManager, createWalCheckpointManager, } from './walCheckpoint.js';
|
|
10
|
+
export { CorruptionDetector, createCorruptionDetector, } from './corruptionDetector.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/adapters/electron/recovery/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,oBAAoB,EACpB,0BAA0B,GAK3B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,kBAAkB,EAClB,wBAAwB,GAOzB,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAL (Write-Ahead Logging) Checkpoint Manager.
|
|
3
|
+
*
|
|
4
|
+
* Manages SQLite WAL checkpointing for optimal performance and
|
|
5
|
+
* data durability. Handles automatic and manual checkpointing
|
|
6
|
+
* with configurable strategies.
|
|
7
|
+
*
|
|
8
|
+
* ## WAL Mode Benefits
|
|
9
|
+
* - Better concurrency (readers don't block writers)
|
|
10
|
+
* - Faster write performance
|
|
11
|
+
* - Atomic commits
|
|
12
|
+
*
|
|
13
|
+
* ## Checkpoint Strategies
|
|
14
|
+
* - PASSIVE: Non-blocking, best for background checkpointing
|
|
15
|
+
* - FULL: Blocks until complete, ensures WAL is cleared
|
|
16
|
+
* - RESTART: Blocks and restarts WAL, minimizes WAL growth
|
|
17
|
+
* - TRUNCATE: Most aggressive, truncates WAL file
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const manager = new WalCheckpointManager(adapter, {
|
|
22
|
+
* checkpointInterval: 300000,
|
|
23
|
+
* strategy: 'PASSIVE',
|
|
24
|
+
* maxWalSize: 50 * 1024 * 1024, // 50MB
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* await manager.start();
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
import type { StorageAdapter } from '../../../core/contracts';
|
|
31
|
+
/**
|
|
32
|
+
* WAL checkpoint strategy.
|
|
33
|
+
*/
|
|
34
|
+
export type CheckpointStrategy = 'PASSIVE' | 'FULL' | 'RESTART' | 'TRUNCATE';
|
|
35
|
+
/**
|
|
36
|
+
* WAL checkpoint manager configuration.
|
|
37
|
+
*/
|
|
38
|
+
export interface WalCheckpointConfig {
|
|
39
|
+
/** Interval between automatic checkpoints in milliseconds (default: 300000 = 5 min) */
|
|
40
|
+
checkpointInterval?: number;
|
|
41
|
+
/** Checkpoint strategy (default: 'PASSIVE') */
|
|
42
|
+
strategy?: CheckpointStrategy;
|
|
43
|
+
/** Maximum WAL size in bytes before forced checkpoint (default: 50MB) */
|
|
44
|
+
maxWalSize?: number;
|
|
45
|
+
/** Page size in bytes (default: 4096) */
|
|
46
|
+
pageSize?: number;
|
|
47
|
+
/** Auto-checkpoint page threshold (default: 1000) */
|
|
48
|
+
autoCheckpointPages?: number;
|
|
49
|
+
/** Synchronous mode (default: 'NORMAL') */
|
|
50
|
+
synchronous?: 'OFF' | 'NORMAL' | 'FULL' | 'EXTRA';
|
|
51
|
+
/** Enable verbose logging (default: false) */
|
|
52
|
+
verbose?: boolean;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Result of a checkpoint operation.
|
|
56
|
+
*/
|
|
57
|
+
export interface CheckpointResult {
|
|
58
|
+
/** Whether the checkpoint was successful */
|
|
59
|
+
success: boolean;
|
|
60
|
+
/** Strategy used for this checkpoint */
|
|
61
|
+
strategy: CheckpointStrategy;
|
|
62
|
+
/** Number of WAL frames before checkpoint */
|
|
63
|
+
walFramesBefore: number;
|
|
64
|
+
/** Number of WAL frames after checkpoint */
|
|
65
|
+
walFramesAfter: number;
|
|
66
|
+
/** Number of frames moved to database */
|
|
67
|
+
framesCheckpointed: number;
|
|
68
|
+
/** Number of busy frames that couldn't be checkpointed */
|
|
69
|
+
busyFrames: number;
|
|
70
|
+
/** Time taken in milliseconds */
|
|
71
|
+
durationMs: number;
|
|
72
|
+
/** Timestamp of checkpoint */
|
|
73
|
+
timestamp: number;
|
|
74
|
+
/** Error message if failed */
|
|
75
|
+
error?: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* WAL status information.
|
|
79
|
+
*/
|
|
80
|
+
export interface WalStatus {
|
|
81
|
+
/** Whether WAL mode is enabled */
|
|
82
|
+
enabled: boolean;
|
|
83
|
+
/** Current WAL file size in bytes */
|
|
84
|
+
walSize: number;
|
|
85
|
+
/** Approximate number of pages in WAL */
|
|
86
|
+
walPages: number;
|
|
87
|
+
/** Last checkpoint timestamp */
|
|
88
|
+
lastCheckpoint: number | null;
|
|
89
|
+
/** Number of checkpoints performed */
|
|
90
|
+
totalCheckpoints: number;
|
|
91
|
+
/** Auto-checkpoint threshold in pages */
|
|
92
|
+
autoCheckpointThreshold: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* WAL Checkpoint Manager.
|
|
96
|
+
*
|
|
97
|
+
* Manages automatic and manual WAL checkpointing for SQLite databases.
|
|
98
|
+
* Ensures optimal performance and data durability.
|
|
99
|
+
*/
|
|
100
|
+
export declare class WalCheckpointManager {
|
|
101
|
+
private readonly adapter;
|
|
102
|
+
private readonly config;
|
|
103
|
+
private checkpointTimer;
|
|
104
|
+
private lastCheckpoint;
|
|
105
|
+
private totalCheckpoints;
|
|
106
|
+
private isRunning;
|
|
107
|
+
constructor(adapter: StorageAdapter, config?: WalCheckpointConfig);
|
|
108
|
+
/**
|
|
109
|
+
* Start the checkpoint manager.
|
|
110
|
+
*/
|
|
111
|
+
start(): Promise<void>;
|
|
112
|
+
/**
|
|
113
|
+
* Stop the checkpoint manager.
|
|
114
|
+
*/
|
|
115
|
+
stop(): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Configure WAL mode on the database.
|
|
118
|
+
*/
|
|
119
|
+
private configureWalMode;
|
|
120
|
+
/**
|
|
121
|
+
* Disable WAL mode and switch back to DELETE journal mode.
|
|
122
|
+
*/
|
|
123
|
+
disableWalMode(): Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* Perform a WAL checkpoint.
|
|
126
|
+
*
|
|
127
|
+
* @param strategy - Checkpoint strategy (defaults to config strategy)
|
|
128
|
+
* @returns Checkpoint result
|
|
129
|
+
*/
|
|
130
|
+
checkpoint(strategy?: CheckpointStrategy): Promise<CheckpointResult>;
|
|
131
|
+
/**
|
|
132
|
+
* Force a full checkpoint that clears the WAL.
|
|
133
|
+
*/
|
|
134
|
+
forceFullCheckpoint(): Promise<CheckpointResult>;
|
|
135
|
+
/**
|
|
136
|
+
* Start the automatic checkpoint timer.
|
|
137
|
+
*/
|
|
138
|
+
private startCheckpointTimer;
|
|
139
|
+
/**
|
|
140
|
+
* Stop the automatic checkpoint timer.
|
|
141
|
+
*/
|
|
142
|
+
private stopCheckpointTimer;
|
|
143
|
+
/**
|
|
144
|
+
* Get current WAL status.
|
|
145
|
+
*/
|
|
146
|
+
getStatus(): Promise<WalStatus>;
|
|
147
|
+
/**
|
|
148
|
+
* Get current WAL size in bytes.
|
|
149
|
+
*/
|
|
150
|
+
private getWalSize;
|
|
151
|
+
/**
|
|
152
|
+
* Get current WAL frame count.
|
|
153
|
+
*/
|
|
154
|
+
private getWalFrameCount;
|
|
155
|
+
/**
|
|
156
|
+
* Check if WAL mode is currently enabled.
|
|
157
|
+
*/
|
|
158
|
+
isWalEnabled(): Promise<boolean>;
|
|
159
|
+
/**
|
|
160
|
+
* Get checkpoint statistics.
|
|
161
|
+
*/
|
|
162
|
+
getStats(): {
|
|
163
|
+
totalCheckpoints: number;
|
|
164
|
+
lastCheckpoint: number | null;
|
|
165
|
+
isRunning: boolean;
|
|
166
|
+
checkpointInterval: number;
|
|
167
|
+
strategy: CheckpointStrategy;
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* Update checkpoint configuration at runtime.
|
|
171
|
+
*/
|
|
172
|
+
updateConfig(newConfig: Partial<WalCheckpointConfig>): void;
|
|
173
|
+
/**
|
|
174
|
+
* Log a message if verbose mode is enabled.
|
|
175
|
+
*/
|
|
176
|
+
private log;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Create a WAL Checkpoint Manager.
|
|
180
|
+
*
|
|
181
|
+
* @param adapter - Storage adapter to manage
|
|
182
|
+
* @param config - Checkpoint configuration
|
|
183
|
+
* @returns WalCheckpointManager instance
|
|
184
|
+
*/
|
|
185
|
+
export declare function createWalCheckpointManager(adapter: StorageAdapter, config?: WalCheckpointConfig): WalCheckpointManager;
|
|
186
|
+
//# sourceMappingURL=walCheckpoint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walCheckpoint.d.ts","sourceRoot":"","sources":["../../../../src/adapters/electron/recovery/walCheckpoint.ts"],"names":[],"mappings":"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"}
|