@fleettools/squawk 0.1.0 → 0.1.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.
Files changed (66) hide show
  1. package/package.json +1 -1
  2. package/AGENTS.md +0 -28
  3. package/dist/src/db/checkpoint-storage.d.ts +0 -19
  4. package/dist/src/db/checkpoint-storage.d.ts.map +0 -1
  5. package/dist/src/db/checkpoint-storage.js +0 -355
  6. package/dist/src/db/checkpoint-storage.js.map +0 -1
  7. package/dist/src/db/index.d.ts +0 -30
  8. package/dist/src/db/index.d.ts.map +0 -1
  9. package/dist/src/db/index.js +0 -329
  10. package/dist/src/db/index.js.map +0 -1
  11. package/dist/src/db/sqlite.d.ts +0 -31
  12. package/dist/src/db/sqlite.d.ts.map +0 -1
  13. package/dist/src/db/sqlite.js +0 -558
  14. package/dist/src/db/sqlite.js.map +0 -1
  15. package/dist/src/db/types.d.ts +0 -611
  16. package/dist/src/db/types.d.ts.map +0 -1
  17. package/dist/src/db/types.js +0 -4
  18. package/dist/src/db/types.js.map +0 -1
  19. package/dist/src/index.d.ts +0 -2
  20. package/dist/src/index.d.ts.map +0 -1
  21. package/dist/src/index.js +0 -285
  22. package/dist/src/index.js.map +0 -1
  23. package/dist/src/recovery/checkpointing.d.ts +0 -244
  24. package/dist/src/recovery/checkpointing.d.ts.map +0 -1
  25. package/dist/src/recovery/checkpointing.js +0 -511
  26. package/dist/src/recovery/checkpointing.js.map +0 -1
  27. package/dist/src/recovery/detection.d.ts +0 -137
  28. package/dist/src/recovery/detection.d.ts.map +0 -1
  29. package/dist/src/recovery/detection.js +0 -240
  30. package/dist/src/recovery/detection.js.map +0 -1
  31. package/dist/src/recovery/detector.d.ts +0 -34
  32. package/dist/src/recovery/detector.d.ts.map +0 -1
  33. package/dist/src/recovery/detector.js +0 -42
  34. package/dist/src/recovery/detector.js.map +0 -1
  35. package/dist/src/recovery/index.d.ts +0 -3
  36. package/dist/src/recovery/index.d.ts.map +0 -1
  37. package/dist/src/recovery/index.js +0 -3
  38. package/dist/src/recovery/index.js.map +0 -1
  39. package/dist/src/recovery/restorer.d.ts +0 -51
  40. package/dist/src/recovery/restorer.d.ts.map +0 -1
  41. package/dist/src/recovery/restorer.js +0 -266
  42. package/dist/src/recovery/restorer.js.map +0 -1
  43. package/dist/src/schemas.d.ts +0 -142
  44. package/dist/src/schemas.d.ts.map +0 -1
  45. package/dist/src/schemas.js +0 -110
  46. package/dist/src/schemas.js.map +0 -1
  47. package/src/db/checkpoint-storage.ts +0 -443
  48. package/src/db/index.d.ts +0 -30
  49. package/src/db/index.d.ts.map +0 -1
  50. package/src/db/index.js.map +0 -1
  51. package/src/db/index.ts +0 -417
  52. package/src/db/schema.sql +0 -112
  53. package/src/db/sqlite.d.ts +0 -31
  54. package/src/db/sqlite.d.ts.map +0 -1
  55. package/src/db/sqlite.js +0 -667
  56. package/src/db/sqlite.js.map +0 -1
  57. package/src/db/sqlite.ts +0 -677
  58. package/src/db/types.d.ts +0 -612
  59. package/src/db/types.d.ts.map +0 -1
  60. package/src/db/types.js +0 -4
  61. package/src/db/types.js.map +0 -1
  62. package/src/db/types.ts +0 -771
  63. package/src/index.ts +0 -332
  64. package/src/recovery/detector.ts +0 -82
  65. package/src/recovery/index.ts +0 -3
  66. package/src/recovery/restorer.ts +0 -377
package/src/db/sqlite.js DELETED
@@ -1,667 +0,0 @@
1
- import Database from 'bun:sqlite';
2
- import fs from 'fs';
3
- import path from 'path';
4
- export class SQLiteAdapter {
5
- version = '1.0.0';
6
- db = null;
7
- dbPath;
8
- schemaPath;
9
- missions = {};
10
- sorties = {};
11
- locks = {};
12
- events = {};
13
- checkpoints = {};
14
- specialists = {};
15
- messages = {};
16
- cursors = {};
17
- constructor(dbPath = ':memory:', schemaPath) {
18
- this.dbPath = dbPath;
19
- if (schemaPath) {
20
- this.schemaPath = schemaPath;
21
- return;
22
- }
23
- this.schemaPath = this.resolveSchemaPath();
24
- }
25
- resolveSchemaPath() {
26
- const possiblePaths = [];
27
- try {
28
- const __filename = new URL('', import.meta.url).pathname;
29
- const __dirname = path.dirname(__filename);
30
- possiblePaths.push(path.join(__dirname, 'schema.sql'));
31
- }
32
- catch {
33
- }
34
- possiblePaths.push(path.join(process.cwd(), 'squawk', 'src', 'db', 'schema.sql'));
35
- const projectRoot = process.cwd();
36
- const modulePaths = [
37
- path.join(projectRoot, 'src', 'db', 'schema.sql'),
38
- path.join(projectRoot, 'db', 'schema.sql'),
39
- path.join(projectRoot, 'lib', 'db', 'schema.sql'),
40
- ];
41
- possiblePaths.push(...modulePaths);
42
- try {
43
- const stack = new Error().stack;
44
- if (stack) {
45
- const match = stack.match(/at.*\((.*):.*\)/);
46
- if (match && match[1]) {
47
- const callerDir = path.dirname(match[1]);
48
- possiblePaths.push(path.join(callerDir, 'schema.sql'));
49
- possiblePaths.push(path.join(callerDir, '..', 'src', 'db', 'schema.sql'));
50
- }
51
- }
52
- }
53
- catch {
54
- }
55
- for (const candidatePath of possiblePaths) {
56
- if (fs.existsSync(candidatePath)) {
57
- return candidatePath;
58
- }
59
- }
60
- return possiblePaths[0] || path.join(process.cwd(), 'squawk', 'src', 'db', 'schema.sql');
61
- }
62
- async initialize() {
63
- try {
64
- this.db = new Database(this.dbPath);
65
- if (this.dbPath !== ':memory:') {
66
- this.db.exec('PRAGMA journal_mode = WAL');
67
- }
68
- this.db.exec('PRAGMA foreign_keys = ON');
69
- if (fs.existsSync(this.schemaPath)) {
70
- const schema = fs.readFileSync(this.schemaPath, 'utf-8');
71
- this.db.exec(schema);
72
- }
73
- else {
74
- throw new Error(`Schema file not found: ${this.schemaPath}`);
75
- }
76
- this.initializeOperations();
77
- console.log(`SQLite database initialized: ${this.dbPath}`);
78
- }
79
- catch (error) {
80
- console.error('Failed to initialize database:', error);
81
- throw error;
82
- }
83
- }
84
- initializeOperations() {
85
- if (!this.db) {
86
- throw new Error('Database not initialized');
87
- }
88
- // TypeScript workaround for property access
89
- const adapter = this;
90
- adapter.mailboxes = {
91
- version: '1.0.0',
92
- create: async (input) => {
93
- const now = new Date().toISOString();
94
- const createdAt = input.created_at || now;
95
- const updatedAt = input.updated_at || now;
96
- this.db.prepare(`
97
- INSERT INTO mailboxes (id, created_at, updated_at)
98
- VALUES (?, ?, ?)
99
- `).run(input.id, createdAt, updatedAt);
100
- return { id: input.id, created_at: createdAt, updated_at: updatedAt };
101
- },
102
- getById: async (id) => {
103
- const row = this.db.prepare(`
104
- SELECT * FROM mailboxes WHERE id = ?
105
- `).get(id);
106
- return row || null;
107
- },
108
- getAll: async () => {
109
- const rows = this.db.prepare(`
110
- SELECT * FROM mailboxes ORDER BY created_at DESC
111
- `).all();
112
- return rows;
113
- },
114
- update: async (id, data) => {
115
- const now = new Date().toISOString();
116
- const result = this.db.prepare(`
117
- UPDATE mailboxes
118
- SET updated_at = COALESCE(?, updated_at)
119
- WHERE id = ?
120
- `).run(now, id);
121
- if (result.changes === 0)
122
- return null;
123
- return await this.mailboxes.getById(id);
124
- },
125
- delete: async (id) => {
126
- const result = this.db.prepare(`
127
- DELETE FROM mailboxes WHERE id = ?
128
- `).run(id);
129
- return result.changes > 0;
130
- }
131
- };
132
- this.cursors = {
133
- version: '1.0.0',
134
- create: async (input) => {
135
- const now = new Date().toISOString();
136
- this.db.prepare(`
137
- INSERT INTO cursors (id, stream_id, position, consumer_id, updated_at)
138
- VALUES (?, ?, ?, ?, ?)
139
- `).run(input.id, input.stream_id, input.position, input.consumer_id, now);
140
- return { id: input.id, stream_id: input.stream_id, position: input.position, consumer_id: input.consumer_id, updated_at: now };
141
- },
142
- getById: async (id) => {
143
- const row = this.db.prepare(`
144
- SELECT * FROM cursors WHERE id = ?
145
- `).get(id);
146
- return row || null;
147
- },
148
- getByStream: async (streamId) => {
149
- const row = this.db.prepare(`
150
- SELECT * FROM cursors WHERE stream_id = ?
151
- `).get(streamId);
152
- return row || null;
153
- },
154
- advance: async (streamId, position) => {
155
- const now = new Date().toISOString();
156
- this.db.prepare(`
157
- INSERT INTO cursors (id, stream_id, position, updated_at)
158
- VALUES (?, ?, ?, ?)
159
- ON CONFLICT(stream_id) DO UPDATE SET
160
- position = excluded.position,
161
- updated_at = excluded.updated_at
162
- `).run(`${streamId}_cursor`, streamId, position, now);
163
- return await adapter.cursors.getByStream(streamId);
164
- },
165
- update: async (id, data) => {
166
- const now = new Date().toISOString();
167
- this.db.prepare(`
168
- UPDATE cursors
169
- SET position = COALESCE(?, position),
170
- updated_at = COALESCE(?, updated_at)
171
- WHERE id = ?
172
- `).run(data.position, now, id);
173
- return await adapter.cursors.getById(id);
174
- },
175
- getAll: async (filter) => {
176
- let query = 'SELECT * FROM cursors';
177
- const params = [];
178
- if (filter?.stream_type) {
179
- query += ' WHERE stream_id LIKE ?';
180
- params.push(`${filter.stream_type}_%`);
181
- }
182
- query += ' ORDER BY updated_at DESC';
183
- const rows = this.db.prepare(query).all(...params);
184
- return rows;
185
- }
186
- };
187
- this.locks = {
188
- version: '1.0.0',
189
- acquire: async (input) => {
190
- const id = `lock_${Math.random().toString(36).substring(2, 10)}`;
191
- const now = new Date().toISOString();
192
- const expiresAt = new Date(Date.now() + input.timeout_ms).toISOString();
193
- const existing = this.db.prepare(`
194
- SELECT * FROM locks
195
- WHERE file = ? AND released_at IS NULL AND expires_at > datetime('now')
196
- `).get(input.file);
197
- if (existing) {
198
- return {
199
- conflict: true,
200
- existing_lock: existing
201
- };
202
- }
203
- this.db.prepare(`
204
- INSERT INTO locks (id, file, reserved_by, reserved_at, purpose, timeout_ms, checksum, expires_at, metadata)
205
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
206
- `).run(id, input.file, input.specialist_id, now, input.purpose || 'edit', input.timeout_ms, input.checksum, expiresAt, JSON.stringify(input.metadata || {}));
207
- const lock = await adapter.locks.getById(id);
208
- return {
209
- conflict: false,
210
- lock: {
211
- ...lock,
212
- status: 'active',
213
- expires_at: expiresAt,
214
- normalized_path: input.file
215
- }
216
- };
217
- },
218
- release: async (id) => {
219
- const result = this.db.prepare(`
220
- UPDATE locks
221
- SET released_at = datetime('now'),
222
- status = 'released'
223
- WHERE id = ?
224
- `).run(id);
225
- return result.changes > 0;
226
- },
227
- getById: async (id) => {
228
- const row = this.db.prepare(`
229
- SELECT * FROM locks WHERE id = ?
230
- `).get(id);
231
- return row || null;
232
- },
233
- getByFile: async (file) => {
234
- const row = this.db.prepare(`
235
- SELECT * FROM locks
236
- WHERE file = ? AND released_at IS NULL AND expires_at > datetime('now')
237
- `).get(file);
238
- return row || null;
239
- },
240
- getActive: async () => {
241
- const rows = this.db.prepare(`
242
- SELECT * FROM locks
243
- WHERE released_at IS NULL AND expires_at > datetime('now')
244
- `).all();
245
- return rows.map((row) => ({
246
- ...row,
247
- status: 'active',
248
- normalized_path: row.file
249
- }));
250
- },
251
- getAll: async () => {
252
- const rows = this.db.prepare(`
253
- SELECT * FROM locks ORDER BY reserved_at DESC
254
- `).all();
255
- return rows;
256
- },
257
- forceRelease: async (id) => {
258
- const result = this.db.prepare(`
259
- UPDATE locks
260
- SET released_at = datetime('now'),
261
- status = 'force_released'
262
- WHERE id = ?
263
- `).run(id);
264
- return result.changes > 0;
265
- },
266
- getExpired: async () => {
267
- const now = new Date().toISOString();
268
- const rows = this.db.prepare(`
269
- SELECT * FROM locks
270
- WHERE released_at IS NULL
271
- AND timeout_ms IS NOT NULL
272
- AND expires_at IS NOT NULL
273
- AND expires_at < datetime('now')
274
- `).all();
275
- return rows;
276
- },
277
- releaseExpired: async () => {
278
- const result = this.db.prepare(`
279
- UPDATE locks
280
- SET released_at = datetime('now'),
281
- status = 'expired'
282
- WHERE released_at IS NULL
283
- AND timeout_ms IS NOT NULL
284
- AND expires_at IS NOT NULL
285
- AND expires_at < datetime('now')
286
- `).run();
287
- return result.changes;
288
- }
289
- };
290
- this.events = {
291
- version: '1.0.0',
292
- append: async (input) => {
293
- const eventId = `evt_${Math.random().toString(36).substring(2, 10)}`;
294
- const lastSeq = this.db.prepare(`
295
- SELECT MAX(sequence_number) as last_seq
296
- FROM events
297
- WHERE stream_type = ? AND stream_id = ?
298
- `).get(input.stream_type, input.stream_id);
299
- const sequenceNumber = (lastSeq?.last_seq || 0) + 1;
300
- const now = new Date().toISOString();
301
- let mailboxId = input.stream_id;
302
- const existingMailbox = this.db.prepare(`
303
- SELECT id FROM mailboxes WHERE id = ?
304
- `).get(input.stream_id);
305
- if (!existingMailbox) {
306
- mailboxId = `mbx_${input.stream_type}_${input.stream_id}`;
307
- this.db.prepare(`
308
- INSERT OR IGNORE INTO mailboxes (id, created_at, updated_at)
309
- VALUES (?, ?, ?)
310
- `).run(mailboxId, now, now);
311
- }
312
- this.db.prepare(`
313
- INSERT INTO events (
314
- id, mailbox_id, type, stream_type, stream_id, sequence_number,
315
- data, occurred_at, causation_id, correlation_id, metadata
316
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
317
- `).run(eventId, mailboxId, input.event_type, input.stream_type, input.stream_id, sequenceNumber, JSON.stringify(input.data), input.occurred_at || now, input.causation_id || null, input.correlation_id || null, JSON.stringify(input.metadata || {}));
318
- return {
319
- sequence_number: sequenceNumber,
320
- event_id: eventId,
321
- event_type: input.event_type,
322
- stream_type: input.stream_type,
323
- stream_id: input.stream_id,
324
- data: input.data,
325
- causation_id: input.causation_id,
326
- correlation_id: input.correlation_id,
327
- metadata: input.metadata,
328
- occurred_at: input.occurred_at || now,
329
- recorded_at: now,
330
- schema_version: input.schema_version || 1
331
- };
332
- },
333
- queryByStream: async (streamType, streamId, afterSequence) => {
334
- const query = `
335
- SELECT * FROM events
336
- WHERE stream_type = ? AND stream_id = ?
337
- ${afterSequence ? 'AND sequence_number > ?' : ''}
338
- ORDER BY sequence_number ASC
339
- `;
340
- const params = [streamType, streamId];
341
- if (afterSequence !== undefined)
342
- params.push(afterSequence);
343
- const rows = this.db.prepare(query).all(...params);
344
- return rows.map(row => ({
345
- sequence_number: row.sequence_number,
346
- event_id: row.id,
347
- event_type: row.type,
348
- stream_type: row.stream_type,
349
- stream_id: row.stream_id,
350
- data: JSON.parse(row.data),
351
- causation_id: row.causation_id,
352
- correlation_id: row.correlation_id,
353
- metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
354
- occurred_at: row.occurred_at,
355
- recorded_at: row.occurred_at,
356
- schema_version: 1
357
- }));
358
- },
359
- queryByType: async (eventType) => {
360
- const rows = this.db.prepare(`
361
- SELECT * FROM events WHERE type = ? ORDER BY occurred_at ASC
362
- `).all(eventType);
363
- return rows.map(row => ({
364
- sequence_number: row.sequence_number,
365
- event_id: row.id,
366
- event_type: row.type,
367
- stream_type: row.stream_type,
368
- stream_id: row.stream_id,
369
- data: JSON.parse(row.data),
370
- causation_id: row.causation_id,
371
- correlation_id: row.correlation_id,
372
- metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
373
- occurred_at: row.occurred_at,
374
- recorded_at: row.occurred_at,
375
- schema_version: 1
376
- }));
377
- },
378
- getEvents: async (filter) => {
379
- let query = 'SELECT * FROM events WHERE 1=1';
380
- const params = [];
381
- if (filter.event_type) {
382
- if (Array.isArray(filter.event_type)) {
383
- query += ` AND type IN (${filter.event_type.map(() => '?').join(',')})`;
384
- params.push(...filter.event_type);
385
- }
386
- else {
387
- query += ' AND type = ?';
388
- params.push(filter.event_type);
389
- }
390
- }
391
- if (filter.stream_type) {
392
- if (Array.isArray(filter.stream_type)) {
393
- query += ` AND stream_type IN (${filter.stream_type.map(() => '?').join(',')})`;
394
- params.push(...filter.stream_type);
395
- }
396
- else {
397
- query += ' AND stream_type = ?';
398
- params.push(filter.stream_type);
399
- }
400
- }
401
- if (filter.stream_id) {
402
- query += ' AND stream_id = ?';
403
- params.push(filter.stream_id);
404
- }
405
- if (filter.after_sequence !== undefined) {
406
- query += ' AND sequence_number > ?';
407
- params.push(filter.after_sequence);
408
- }
409
- query += ' ORDER BY occurred_at ASC';
410
- const rows = this.db.prepare(query).all(...params);
411
- return rows.map(row => ({
412
- sequence_number: row.sequence_number,
413
- event_id: row.id,
414
- event_type: row.type,
415
- stream_type: row.stream_type,
416
- stream_id: row.stream_id,
417
- data: JSON.parse(row.data),
418
- causation_id: row.causation_id,
419
- correlation_id: row.correlation_id,
420
- metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
421
- occurred_at: row.occurred_at,
422
- recorded_at: row.occurred_at,
423
- schema_version: 1
424
- }));
425
- },
426
- getLatestByStream: async (streamType, streamId) => {
427
- const row = this.db.prepare(`
428
- SELECT * FROM events
429
- WHERE stream_type = ? AND stream_id = ?
430
- ORDER BY sequence_number DESC
431
- LIMIT 1
432
- `).get(streamType, streamId);
433
- return row ? {
434
- sequence_number: row.sequence_number,
435
- event_id: row.id,
436
- event_type: row.type,
437
- stream_type: row.stream_type,
438
- stream_id: row.stream_id,
439
- data: JSON.parse(row.data),
440
- causation_id: row.causation_id,
441
- correlation_id: row.correlation_id,
442
- metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
443
- occurred_at: row.occurred_at,
444
- recorded_at: row.occurred_at,
445
- schema_version: 1
446
- } : null;
447
- }
448
- };
449
- this.missions = {};
450
- this.sorties = {};
451
- this.checkpoints = {};
452
- this.specialists = {};
453
- this.messages = {};
454
- adapter.checkpoints = {
455
- version: '1.0.0',
456
- create: async (input) => {
457
- const id = input.id || `chk_${Math.random().toString(36).substring(2, 10)}`;
458
- const now = new Date().toISOString();
459
- this.db.prepare(`
460
- INSERT INTO checkpoints (
461
- id, mission_id, mission_title, timestamp, trigger, trigger_details,
462
- progress_percent, sorties, active_locks, pending_messages,
463
- recovery_context, created_by, expires_at, version, metadata
464
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
465
- `).run(id, input.mission_id, input.mission_title || null, input.timestamp || now, input.trigger, input.trigger_details || null, input.progress_percent || 0, JSON.stringify(input.sorties || []), JSON.stringify(input.active_locks || []), JSON.stringify(input.pending_messages || []), JSON.stringify(input.recovery_context || {}), input.created_by, input.expires_at || null, input.version || '1.0.0', JSON.stringify(input.metadata || {}));
466
- const checkpoint = await adapter.checkpoints.getById(id);
467
- return checkpoint;
468
- },
469
- getById: async (id) => {
470
- const row = this.db.prepare(`
471
- SELECT * FROM checkpoints WHERE id = ?
472
- `).get(id);
473
- if (!row)
474
- return null;
475
- return {
476
- id: row.id,
477
- mission_id: row.mission_id,
478
- mission_title: row.mission_title,
479
- timestamp: row.timestamp,
480
- trigger: row.trigger,
481
- trigger_details: row.trigger_details,
482
- progress_percent: row.progress_percent,
483
- sorties: row.sorties ? JSON.parse(row.sorties) : [],
484
- active_locks: row.active_locks ? JSON.parse(row.active_locks) : [],
485
- pending_messages: row.pending_messages ? JSON.parse(row.pending_messages) : [],
486
- recovery_context: row.recovery_context ? JSON.parse(row.recovery_context) : {},
487
- created_by: row.created_by,
488
- expires_at: row.expires_at,
489
- consumed_at: row.consumed_at,
490
- version: row.version,
491
- metadata: row.metadata ? JSON.parse(row.metadata) : {}
492
- };
493
- },
494
- getLatest: async (missionId) => {
495
- const row = this.db.prepare(`
496
- SELECT * FROM checkpoints
497
- WHERE mission_id = ? AND consumed_at IS NULL
498
- ORDER BY timestamp DESC
499
- LIMIT 1
500
- `).get(missionId);
501
- if (!row)
502
- return null;
503
- return await adapter.checkpoints.getById(row.id);
504
- },
505
- list: async (missionId) => {
506
- let query = 'SELECT * FROM checkpoints';
507
- const params = [];
508
- if (missionId) {
509
- query += ' WHERE mission_id = ?';
510
- params.push(missionId);
511
- }
512
- query += ' ORDER BY timestamp DESC';
513
- const rows = this.db.prepare(query).all(...params);
514
- return rows.map((row) => ({
515
- id: row.id,
516
- mission_id: row.mission_id,
517
- mission_title: row.mission_title,
518
- timestamp: row.timestamp,
519
- trigger: row.trigger,
520
- trigger_details: row.trigger_details,
521
- progress_percent: row.progress_percent,
522
- sorties: row.sorties ? JSON.parse(row.sorties) : [],
523
- active_locks: row.active_locks ? JSON.parse(row.active_locks) : [],
524
- pending_messages: row.pending_messages ? JSON.parse(row.pending_messages) : [],
525
- recovery_context: row.recovery_context ? JSON.parse(row.recovery_context) : {},
526
- created_by: row.created_by,
527
- expires_at: row.expires_at,
528
- consumed_at: row.consumed_at,
529
- version: row.version,
530
- metadata: row.metadata ? JSON.parse(row.metadata) : {}
531
- }));
532
- },
533
- delete: async (id) => {
534
- const result = this.db.prepare(`
535
- DELETE FROM checkpoints WHERE id = ?
536
- `).run(id);
537
- return result.changes > 0;
538
- },
539
- markConsumed: async (id) => {
540
- const now = new Date().toISOString();
541
- const result = this.db.prepare(`
542
- UPDATE checkpoints
543
- SET consumed_at = ?
544
- WHERE id = ?
545
- `).run(now, id);
546
- if (result.changes > 0) {
547
- return await adapter.checkpoints.getById(id);
548
- }
549
- return null;
550
- }
551
- };
552
- }
553
- async close() {
554
- try {
555
- if (this.db) {
556
- this.db.close();
557
- this.db = null;
558
- console.log(`SQLite database closed: ${this.dbPath}`);
559
- }
560
- }
561
- catch (error) {
562
- console.error('Error closing database:', error);
563
- throw error;
564
- }
565
- }
566
- async isHealthy() {
567
- try {
568
- if (!this.db) {
569
- return false;
570
- }
571
- this.db.prepare('SELECT 1').get();
572
- return true;
573
- }
574
- catch {
575
- return false;
576
- }
577
- }
578
- async getStats() {
579
- if (!this.db) {
580
- throw new Error('Database not initialized');
581
- }
582
- const eventCount = this.db.prepare('SELECT COUNT(*) as count FROM events').get();
583
- const missionCount = 0; // TODO: Implement when mission table exists
584
- const activeMissionCount = 0; // TODO: Implement
585
- const activeLockCount = this.db.prepare("SELECT COUNT(*) as count FROM locks WHERE released_at IS NULL AND expires_at > datetime('now')").get();
586
- const checkpointCount = 0; // TODO: Implement
587
- let dbSize = 0;
588
- let walSize = 0;
589
- if (this.dbPath !== ':memory:' && fs.existsSync(this.dbPath)) {
590
- dbSize = fs.statSync(this.dbPath).size;
591
- const walPath = `${this.dbPath}-wal`;
592
- if (fs.existsSync(walPath)) {
593
- walSize = fs.statSync(walPath).size;
594
- }
595
- }
596
- return {
597
- total_events: eventCount.count,
598
- total_missions: missionCount,
599
- active_missions: activeMissionCount,
600
- active_locks: activeLockCount.count,
601
- total_checkpoints: checkpointCount,
602
- database_size_bytes: dbSize,
603
- wal_size_bytes: walSize
604
- };
605
- }
606
- async maintenance() {
607
- if (!this.db) {
608
- throw new Error('Database not initialized');
609
- }
610
- try {
611
- this.db.exec('VACUUM');
612
- console.log('Database maintenance completed');
613
- }
614
- catch (error) {
615
- console.error('Error running database maintenance:', error);
616
- throw error;
617
- }
618
- }
619
- async beginTransaction() {
620
- if (!this.db) {
621
- throw new Error('Database not initialized');
622
- }
623
- try {
624
- this.db.exec('BEGIN TRANSACTION');
625
- }
626
- catch (error) {
627
- console.error('Error beginning transaction:', error);
628
- throw error;
629
- }
630
- }
631
- async commitTransaction() {
632
- if (!this.db) {
633
- throw new Error('Database not initialized');
634
- }
635
- try {
636
- this.db.exec('COMMIT');
637
- }
638
- catch (error) {
639
- console.error('Error committing transaction:', error);
640
- throw error;
641
- }
642
- }
643
- async rollbackTransaction() {
644
- if (!this.db) {
645
- throw new Error('Database not initialized');
646
- }
647
- try {
648
- this.db.exec('ROLLBACK');
649
- }
650
- catch (error) {
651
- console.error('Error rolling back transaction:', error);
652
- throw error;
653
- }
654
- }
655
- getDatabase() {
656
- return this.db;
657
- }
658
- }
659
- export async function createSQLiteAdapter(dbPath = ':memory:') {
660
- const adapter = new SQLiteAdapter(dbPath);
661
- await adapter.initialize();
662
- return adapter;
663
- }
664
- export async function createInMemoryAdapter() {
665
- return createSQLiteAdapter(':memory:');
666
- }
667
- //# sourceMappingURL=sqlite.js.map