@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.
- package/package.json +1 -1
- package/AGENTS.md +0 -28
- package/dist/src/db/checkpoint-storage.d.ts +0 -19
- package/dist/src/db/checkpoint-storage.d.ts.map +0 -1
- package/dist/src/db/checkpoint-storage.js +0 -355
- package/dist/src/db/checkpoint-storage.js.map +0 -1
- package/dist/src/db/index.d.ts +0 -30
- package/dist/src/db/index.d.ts.map +0 -1
- package/dist/src/db/index.js +0 -329
- package/dist/src/db/index.js.map +0 -1
- package/dist/src/db/sqlite.d.ts +0 -31
- package/dist/src/db/sqlite.d.ts.map +0 -1
- package/dist/src/db/sqlite.js +0 -558
- package/dist/src/db/sqlite.js.map +0 -1
- package/dist/src/db/types.d.ts +0 -611
- package/dist/src/db/types.d.ts.map +0 -1
- package/dist/src/db/types.js +0 -4
- package/dist/src/db/types.js.map +0 -1
- package/dist/src/index.d.ts +0 -2
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -285
- package/dist/src/index.js.map +0 -1
- package/dist/src/recovery/checkpointing.d.ts +0 -244
- package/dist/src/recovery/checkpointing.d.ts.map +0 -1
- package/dist/src/recovery/checkpointing.js +0 -511
- package/dist/src/recovery/checkpointing.js.map +0 -1
- package/dist/src/recovery/detection.d.ts +0 -137
- package/dist/src/recovery/detection.d.ts.map +0 -1
- package/dist/src/recovery/detection.js +0 -240
- package/dist/src/recovery/detection.js.map +0 -1
- package/dist/src/recovery/detector.d.ts +0 -34
- package/dist/src/recovery/detector.d.ts.map +0 -1
- package/dist/src/recovery/detector.js +0 -42
- package/dist/src/recovery/detector.js.map +0 -1
- package/dist/src/recovery/index.d.ts +0 -3
- package/dist/src/recovery/index.d.ts.map +0 -1
- package/dist/src/recovery/index.js +0 -3
- package/dist/src/recovery/index.js.map +0 -1
- package/dist/src/recovery/restorer.d.ts +0 -51
- package/dist/src/recovery/restorer.d.ts.map +0 -1
- package/dist/src/recovery/restorer.js +0 -266
- package/dist/src/recovery/restorer.js.map +0 -1
- package/dist/src/schemas.d.ts +0 -142
- package/dist/src/schemas.d.ts.map +0 -1
- package/dist/src/schemas.js +0 -110
- package/dist/src/schemas.js.map +0 -1
- package/src/db/checkpoint-storage.ts +0 -443
- package/src/db/index.d.ts +0 -30
- package/src/db/index.d.ts.map +0 -1
- package/src/db/index.js.map +0 -1
- package/src/db/index.ts +0 -417
- package/src/db/schema.sql +0 -112
- package/src/db/sqlite.d.ts +0 -31
- package/src/db/sqlite.d.ts.map +0 -1
- package/src/db/sqlite.js +0 -667
- package/src/db/sqlite.js.map +0 -1
- package/src/db/sqlite.ts +0 -677
- package/src/db/types.d.ts +0 -612
- package/src/db/types.d.ts.map +0 -1
- package/src/db/types.js +0 -4
- package/src/db/types.js.map +0 -1
- package/src/db/types.ts +0 -771
- package/src/index.ts +0 -332
- package/src/recovery/detector.ts +0 -82
- package/src/recovery/index.ts +0 -3
- package/src/recovery/restorer.ts +0 -377
package/src/db/index.ts
DELETED
|
@@ -1,417 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import { randomUUID } from 'crypto';
|
|
5
|
-
import { SQLiteAdapter } from './sqlite.js';
|
|
6
|
-
import type { Event, Mailbox, Cursor, Lock } from './types.js';
|
|
7
|
-
|
|
8
|
-
// CONFIGURATION
|
|
9
|
-
|
|
10
|
-
function getLegacyDbPath(): string {
|
|
11
|
-
return path.join(
|
|
12
|
-
process.env.HOME || '',
|
|
13
|
-
'.local',
|
|
14
|
-
'share',
|
|
15
|
-
'fleet',
|
|
16
|
-
'squawk.json'
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function getSqliteDbPath(): string {
|
|
21
|
-
return path.join(
|
|
22
|
-
process.env.HOME || '',
|
|
23
|
-
'.local',
|
|
24
|
-
'share',
|
|
25
|
-
'fleet',
|
|
26
|
-
'squawk.db'
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// PRIVATE STATE
|
|
31
|
-
|
|
32
|
-
let adapter: SQLiteAdapter | null = null;
|
|
33
|
-
|
|
34
|
-
// INITIALIZATION
|
|
35
|
-
|
|
36
|
-
export async function initializeDatabase(dbPath?: string): Promise<void> {
|
|
37
|
-
const targetPath = dbPath || getSqliteDbPath();
|
|
38
|
-
|
|
39
|
-
const dbDir = path.dirname(targetPath);
|
|
40
|
-
if (!fs.existsSync(dbDir)) {
|
|
41
|
-
fs.mkdirSync(dbDir, { recursive: true });
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const schemaPath = path.join(process.cwd(), 'squawk', 'src', 'db', 'schema.sql');
|
|
45
|
-
adapter = new SQLiteAdapter(targetPath, schemaPath);
|
|
46
|
-
await adapter.initialize();
|
|
47
|
-
|
|
48
|
-
const legacyDbPath = getLegacyDbPath();
|
|
49
|
-
if (fs.existsSync(legacyDbPath)) {
|
|
50
|
-
await migrateFromJson(legacyDbPath);
|
|
51
|
-
const backupPath = legacyDbPath + '.backup';
|
|
52
|
-
fs.renameSync(legacyDbPath, backupPath);
|
|
53
|
-
console.log(`[Migration] Legacy data migrated to SQLite`);
|
|
54
|
-
console.log(`[Migration] Backup saved to: ${backupPath}`);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function getAdapter(): SQLiteAdapter {
|
|
59
|
-
if (!adapter) {
|
|
60
|
-
throw new Error(
|
|
61
|
-
'Database not initialized. Call initializeDatabase() first.'
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
return adapter;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export async function closeDatabase(): Promise<void> {
|
|
68
|
-
if (adapter) {
|
|
69
|
-
await adapter.close();
|
|
70
|
-
adapter = null;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// JSON MIGRATION
|
|
75
|
-
|
|
76
|
-
interface LegacyJsonData {
|
|
77
|
-
mailboxes: Record<string, any>;
|
|
78
|
-
events: Record<string, any[]>;
|
|
79
|
-
cursors: Record<string, any>;
|
|
80
|
-
locks: Record<string, any>;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async function migrateFromJson(jsonPath: string): Promise<void> {
|
|
84
|
-
console.log(`[Migration] Starting migration from: ${jsonPath}`);
|
|
85
|
-
|
|
86
|
-
try {
|
|
87
|
-
const content = fs.readFileSync(jsonPath, 'utf-8');
|
|
88
|
-
const legacyData: LegacyJsonData = JSON.parse(content);
|
|
89
|
-
|
|
90
|
-
const stats = {
|
|
91
|
-
mailboxes: 0,
|
|
92
|
-
events: 0,
|
|
93
|
-
cursors: 0,
|
|
94
|
-
locks: 0,
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
for (const [id, mailbox] of Object.entries(legacyData.mailboxes || {})) {
|
|
98
|
-
try {
|
|
99
|
-
if (!mailbox.created_at || !mailbox.updated_at) {
|
|
100
|
-
console.warn(`[Migration] Skipping mailbox ${id} due to missing required fields`);
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
await (adapter as any).mailboxes.create({
|
|
105
|
-
id,
|
|
106
|
-
created_at: mailbox.created_at,
|
|
107
|
-
updated_at: mailbox.updated_at,
|
|
108
|
-
});
|
|
109
|
-
stats.mailboxes++;
|
|
110
|
-
} catch (error) {
|
|
111
|
-
console.warn(`[Migration] Failed to migrate mailbox ${id}:`, error);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
for (const [mailboxId, events] of Object.entries(
|
|
116
|
-
legacyData.events || {}
|
|
117
|
-
)) {
|
|
118
|
-
if (!(await (adapter as any).mailboxes.getById(mailboxId))) {
|
|
119
|
-
await (adapter as any).mailboxes.create({
|
|
120
|
-
id: mailboxId,
|
|
121
|
-
created_at: new Date().toISOString(),
|
|
122
|
-
updated_at: new Date().toISOString(),
|
|
123
|
-
});
|
|
124
|
-
stats.mailboxes++;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
for (const event of events) {
|
|
128
|
-
try {
|
|
129
|
-
if (!event.type) {
|
|
130
|
-
console.warn(`[Migration] Skipping event without type field in mailbox ${mailboxId}`);
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
await (adapter as any).events.append({
|
|
135
|
-
event_type: event.type,
|
|
136
|
-
stream_type: 'squawk',
|
|
137
|
-
stream_id: mailboxId,
|
|
138
|
-
data:
|
|
139
|
-
typeof event.data === 'string'
|
|
140
|
-
? JSON.parse(event.data)
|
|
141
|
-
: event.data,
|
|
142
|
-
occurred_at: event.occurred_at,
|
|
143
|
-
causation_id: event.causation_id,
|
|
144
|
-
correlation_id: event.correlation_id,
|
|
145
|
-
metadata: event.metadata
|
|
146
|
-
? typeof event.metadata === 'string'
|
|
147
|
-
? JSON.parse(event.metadata)
|
|
148
|
-
: event.metadata
|
|
149
|
-
: undefined,
|
|
150
|
-
});
|
|
151
|
-
stats.events++;
|
|
152
|
-
} catch (error) {
|
|
153
|
-
console.warn(`[Migration] Failed to migrate event:`, error);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
for (const [id, cursor] of Object.entries(legacyData.cursors || {})) {
|
|
159
|
-
try {
|
|
160
|
-
await (adapter as any).cursors.create({
|
|
161
|
-
id,
|
|
162
|
-
stream_type: 'squawk',
|
|
163
|
-
stream_id: cursor.stream_id,
|
|
164
|
-
position: cursor.position,
|
|
165
|
-
consumer_id: cursor.consumer_id || 'migrated',
|
|
166
|
-
});
|
|
167
|
-
stats.cursors++;
|
|
168
|
-
} catch (error) {
|
|
169
|
-
console.warn(`[Migration] Failed to migrate cursor ${id}:`, error);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
for (const [id, lock] of Object.entries(legacyData.locks || {})) {
|
|
174
|
-
const lockData = lock as any;
|
|
175
|
-
if (!lockData.released_at) {
|
|
176
|
-
try {
|
|
177
|
-
await (adapter as any).locks.acquire({
|
|
178
|
-
file: lockData.file,
|
|
179
|
-
specialist_id: lockData.reserved_by,
|
|
180
|
-
timeout_ms: lockData.timeout_ms || 30000,
|
|
181
|
-
purpose:
|
|
182
|
-
lockData.purpose === 'delete'
|
|
183
|
-
? 'delete'
|
|
184
|
-
: lockData.purpose === 'read'
|
|
185
|
-
? 'read'
|
|
186
|
-
: 'edit',
|
|
187
|
-
checksum: lockData.checksum,
|
|
188
|
-
});
|
|
189
|
-
stats.locks++;
|
|
190
|
-
} catch (error) {
|
|
191
|
-
console.warn(`[Migration] Failed to migrate lock ${id}:`, error);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
console.log(`[Migration] Complete:`);
|
|
197
|
-
console.log(` - Mailboxes: ${stats.mailboxes}`);
|
|
198
|
-
console.log(` - Events: ${stats.events}`);
|
|
199
|
-
console.log(` - Cursors: ${stats.cursors}`);
|
|
200
|
-
console.log(` - Locks: ${stats.locks}`);
|
|
201
|
-
} catch (error) {
|
|
202
|
-
console.error('[Migration] Failed:', error);
|
|
203
|
-
throw error;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
export const mailboxOps = {
|
|
210
|
-
getAll: async () => {
|
|
211
|
-
const adapter = getAdapter() as any;
|
|
212
|
-
const mailboxes = await adapter.mailboxes.getAll();
|
|
213
|
-
return mailboxes.sort(
|
|
214
|
-
(a: any, b: any) =>
|
|
215
|
-
new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
|
|
216
|
-
);
|
|
217
|
-
},
|
|
218
|
-
|
|
219
|
-
getById: async (id: string) => {
|
|
220
|
-
const adapter = getAdapter() as any;
|
|
221
|
-
return adapter.mailboxes.getById(id);
|
|
222
|
-
},
|
|
223
|
-
|
|
224
|
-
create: async (id: string) => {
|
|
225
|
-
const adapter = getAdapter() as any;
|
|
226
|
-
const now = new Date().toISOString();
|
|
227
|
-
return adapter.mailboxes.create({
|
|
228
|
-
id,
|
|
229
|
-
created_at: now,
|
|
230
|
-
updated_at: now,
|
|
231
|
-
});
|
|
232
|
-
},
|
|
233
|
-
|
|
234
|
-
exists: async (id: string) => {
|
|
235
|
-
const adapter = getAdapter() as any;
|
|
236
|
-
const mailbox = await adapter.mailboxes.getById(id);
|
|
237
|
-
return mailbox !== null;
|
|
238
|
-
},
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
export const eventOps = {
|
|
242
|
-
getByMailbox: async (mailboxId: string) => {
|
|
243
|
-
const adapter = getAdapter() as any;
|
|
244
|
-
const events = await adapter.events.queryByStream('squawk', mailboxId);
|
|
245
|
-
return events.sort(
|
|
246
|
-
(a: any, b: any) =>
|
|
247
|
-
new Date(a.occurred_at).getTime() -
|
|
248
|
-
new Date(b.occurred_at).getTime()
|
|
249
|
-
);
|
|
250
|
-
},
|
|
251
|
-
|
|
252
|
-
append: async (mailboxId: string, events: any[]) => {
|
|
253
|
-
const adapter = getAdapter() as any;
|
|
254
|
-
|
|
255
|
-
if (!(await adapter.mailboxes.getById(mailboxId))) {
|
|
256
|
-
await adapter.mailboxes.create({
|
|
257
|
-
id: mailboxId,
|
|
258
|
-
created_at: new Date().toISOString(),
|
|
259
|
-
updated_at: new Date().toISOString(),
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const inserted: Event[] = [];
|
|
264
|
-
for (const event of events) {
|
|
265
|
-
const appended = await adapter.events.append({
|
|
266
|
-
event_type: event.type,
|
|
267
|
-
stream_type: 'squawk',
|
|
268
|
-
stream_id: mailboxId,
|
|
269
|
-
data:
|
|
270
|
-
typeof event.data === 'string'
|
|
271
|
-
? JSON.parse(event.data)
|
|
272
|
-
: event.data,
|
|
273
|
-
occurred_at: event.occurred_at,
|
|
274
|
-
causation_id: event.causation_id,
|
|
275
|
-
correlation_id: event.correlation_id,
|
|
276
|
-
metadata: event.metadata
|
|
277
|
-
? typeof event.metadata === 'string'
|
|
278
|
-
? JSON.parse(event.metadata)
|
|
279
|
-
: event.metadata
|
|
280
|
-
: undefined,
|
|
281
|
-
});
|
|
282
|
-
inserted.push(appended);
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
return inserted;
|
|
286
|
-
},
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
export const cursorOps = {
|
|
290
|
-
getById: async (id: string) => {
|
|
291
|
-
const adapter = getAdapter() as any;
|
|
292
|
-
return adapter.cursors.getById(id);
|
|
293
|
-
},
|
|
294
|
-
|
|
295
|
-
getByStream: async (streamId: string) => {
|
|
296
|
-
const adapter = getAdapter() as any;
|
|
297
|
-
const cursors = await adapter.cursors.getAll();
|
|
298
|
-
return (
|
|
299
|
-
cursors.find((c: Cursor) => c.stream_id === streamId) ||
|
|
300
|
-
null
|
|
301
|
-
);
|
|
302
|
-
},
|
|
303
|
-
|
|
304
|
-
upsert: async (cursor: any) => {
|
|
305
|
-
const adapter = getAdapter() as any;
|
|
306
|
-
const id = cursor.id || `${cursor.stream_id}_cursor`;
|
|
307
|
-
const now = new Date().toISOString();
|
|
308
|
-
|
|
309
|
-
const existing = await adapter.cursors.getById(id);
|
|
310
|
-
|
|
311
|
-
if (existing) {
|
|
312
|
-
await adapter.cursors.update(id, {
|
|
313
|
-
position: cursor.position,
|
|
314
|
-
updated_at: now,
|
|
315
|
-
});
|
|
316
|
-
return existing;
|
|
317
|
-
} else {
|
|
318
|
-
return adapter.cursors.create({
|
|
319
|
-
id,
|
|
320
|
-
stream_type: 'squawk',
|
|
321
|
-
stream_id: cursor.stream_id,
|
|
322
|
-
position: cursor.position,
|
|
323
|
-
consumer_id: cursor.consumer_id || 'default',
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
},
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
export const lockOps = {
|
|
330
|
-
getAll: async () => {
|
|
331
|
-
const adapter = getAdapter() as any;
|
|
332
|
-
const allLocks = await adapter.locks.getAll();
|
|
333
|
-
const now = new Date().toISOString();
|
|
334
|
-
|
|
335
|
-
return allLocks.filter((lock: any) => {
|
|
336
|
-
if (lock.status === 'released') return false;
|
|
337
|
-
|
|
338
|
-
const expiresAt = lock.expires_at;
|
|
339
|
-
return expiresAt > now;
|
|
340
|
-
});
|
|
341
|
-
},
|
|
342
|
-
|
|
343
|
-
getById: async (id: string) => {
|
|
344
|
-
const adapter = getAdapter() as any;
|
|
345
|
-
return adapter.locks.getById(id);
|
|
346
|
-
},
|
|
347
|
-
|
|
348
|
-
acquire: async (lock: any) => {
|
|
349
|
-
const adapter = getAdapter() as any;
|
|
350
|
-
|
|
351
|
-
const result = await adapter.locks.acquire({
|
|
352
|
-
file: lock.file,
|
|
353
|
-
specialist_id: lock.reserved_by || lock.specialist_id,
|
|
354
|
-
timeout_ms: lock.timeout_ms || 30000,
|
|
355
|
-
purpose:
|
|
356
|
-
lock.purpose === 'delete'
|
|
357
|
-
? 'delete'
|
|
358
|
-
: lock.purpose === 'read'
|
|
359
|
-
? 'read'
|
|
360
|
-
: 'edit',
|
|
361
|
-
checksum: lock.checksum,
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
if (result.conflict) {
|
|
365
|
-
// (legacy behavior: acquire always returns a lock object)
|
|
366
|
-
return result.existing_lock || {
|
|
367
|
-
id: result.lock?.id || '',
|
|
368
|
-
file: lock.file,
|
|
369
|
-
reserved_by: result.lock?.reserved_by || '',
|
|
370
|
-
reserved_at: result.lock?.reserved_at || '',
|
|
371
|
-
released_at: null,
|
|
372
|
-
purpose: lock.purpose || 'edit',
|
|
373
|
-
checksum: lock.checksum,
|
|
374
|
-
timeout_ms: lock.timeout_ms || 30000,
|
|
375
|
-
metadata: lock.metadata,
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
return result.lock;
|
|
380
|
-
},
|
|
381
|
-
|
|
382
|
-
release: async (id: string) => {
|
|
383
|
-
const adapter = getAdapter() as any;
|
|
384
|
-
const lock = await adapter.locks.getById(id);
|
|
385
|
-
if (lock) {
|
|
386
|
-
await adapter.locks.release(id);
|
|
387
|
-
return lock;
|
|
388
|
-
}
|
|
389
|
-
return null;
|
|
390
|
-
},
|
|
391
|
-
|
|
392
|
-
getExpired: async () => {
|
|
393
|
-
const adapter = getAdapter() as any;
|
|
394
|
-
const allLocks = await adapter.locks.getAll();
|
|
395
|
-
const now = new Date().toISOString();
|
|
396
|
-
|
|
397
|
-
return allLocks.filter((lock: any) => {
|
|
398
|
-
if (lock.status === 'released') return false;
|
|
399
|
-
|
|
400
|
-
const expiresAt = lock.expires_at;
|
|
401
|
-
return expiresAt <= now;
|
|
402
|
-
});
|
|
403
|
-
},
|
|
404
|
-
|
|
405
|
-
releaseExpired: async () => {
|
|
406
|
-
const expired = await lockOps.getExpired();
|
|
407
|
-
for (const lock of expired) {
|
|
408
|
-
await lockOps.release(lock.id);
|
|
409
|
-
}
|
|
410
|
-
return expired.length;
|
|
411
|
-
},
|
|
412
|
-
};
|
|
413
|
-
|
|
414
|
-
// TYPE EXPORTS (Backward Compatibility)
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
export type { Mailbox, Event, Cursor, Lock };
|
package/src/db/schema.sql
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
-- FleetTools Squawk Database Schema
|
|
2
|
-
-- Uses SQLite with WAL mode for better concurrency
|
|
3
|
-
|
|
4
|
-
-- Missions table
|
|
5
|
-
CREATE TABLE IF NOT EXISTS missions (
|
|
6
|
-
id TEXT PRIMARY KEY,
|
|
7
|
-
title TEXT NOT NULL,
|
|
8
|
-
description TEXT,
|
|
9
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
10
|
-
priority TEXT NOT NULL DEFAULT 'medium',
|
|
11
|
-
created_at TEXT NOT NULL,
|
|
12
|
-
started_at TEXT,
|
|
13
|
-
completed_at TEXT,
|
|
14
|
-
total_sorties INTEGER NOT NULL DEFAULT 0,
|
|
15
|
-
completed_sorties INTEGER NOT NULL DEFAULT 0,
|
|
16
|
-
result TEXT,
|
|
17
|
-
metadata TEXT
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
-- Sorties table
|
|
21
|
-
CREATE TABLE IF NOT EXISTS sorties (
|
|
22
|
-
id TEXT PRIMARY KEY,
|
|
23
|
-
mission_id TEXT,
|
|
24
|
-
title TEXT NOT NULL,
|
|
25
|
-
description TEXT,
|
|
26
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
27
|
-
priority TEXT NOT NULL DEFAULT 'medium',
|
|
28
|
-
assigned_to TEXT,
|
|
29
|
-
files TEXT,
|
|
30
|
-
progress INTEGER NOT NULL DEFAULT 0,
|
|
31
|
-
progress_notes TEXT,
|
|
32
|
-
started_at TEXT,
|
|
33
|
-
completed_at TEXT,
|
|
34
|
-
blocked_by TEXT,
|
|
35
|
-
blocked_reason TEXT,
|
|
36
|
-
result TEXT,
|
|
37
|
-
metadata TEXT,
|
|
38
|
-
FOREIGN KEY (mission_id) REFERENCES missions(id) ON DELETE CASCADE
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
-- Mailboxes table
|
|
42
|
-
CREATE TABLE IF NOT EXISTS mailboxes (
|
|
43
|
-
id TEXT PRIMARY KEY,
|
|
44
|
-
created_at TEXT NOT NULL,
|
|
45
|
-
updated_at TEXT NOT NULL
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
-- Events table - stores mailbox events
|
|
49
|
-
CREATE TABLE IF NOT EXISTS events (
|
|
50
|
-
id TEXT PRIMARY KEY,
|
|
51
|
-
mailbox_id TEXT NOT NULL,
|
|
52
|
-
type TEXT NOT NULL,
|
|
53
|
-
stream_type TEXT NOT NULL,
|
|
54
|
-
stream_id TEXT NOT NULL,
|
|
55
|
-
sequence_number INTEGER NOT NULL,
|
|
56
|
-
data TEXT NOT NULL,
|
|
57
|
-
occurred_at TEXT NOT NULL,
|
|
58
|
-
causation_id TEXT,
|
|
59
|
-
correlation_id TEXT,
|
|
60
|
-
metadata TEXT,
|
|
61
|
-
FOREIGN KEY (mailbox_id) REFERENCES mailboxes(id) ON DELETE CASCADE
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
-- Cursors table - tracks read positions
|
|
65
|
-
CREATE TABLE IF NOT EXISTS cursors (
|
|
66
|
-
id TEXT PRIMARY KEY,
|
|
67
|
-
stream_id TEXT NOT NULL,
|
|
68
|
-
position INTEGER NOT NULL,
|
|
69
|
-
consumer_id TEXT,
|
|
70
|
-
updated_at TEXT NOT NULL,
|
|
71
|
-
UNIQUE(stream_id)
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
-- Locks table - CTK file locks
|
|
75
|
-
CREATE TABLE IF NOT EXISTS locks (
|
|
76
|
-
id TEXT PRIMARY KEY,
|
|
77
|
-
file TEXT NOT NULL,
|
|
78
|
-
reserved_by TEXT NOT NULL,
|
|
79
|
-
reserved_at TEXT NOT NULL,
|
|
80
|
-
released_at TEXT,
|
|
81
|
-
purpose TEXT DEFAULT 'edit',
|
|
82
|
-
checksum TEXT,
|
|
83
|
-
timeout_ms INTEGER DEFAULT 30000,
|
|
84
|
-
expires_at TEXT,
|
|
85
|
-
status TEXT DEFAULT 'active',
|
|
86
|
-
metadata TEXT
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
-- Specialists table - tracks active specialists
|
|
90
|
-
CREATE TABLE IF NOT EXISTS specialists (
|
|
91
|
-
id TEXT PRIMARY KEY,
|
|
92
|
-
name TEXT NOT NULL,
|
|
93
|
-
status TEXT DEFAULT 'active',
|
|
94
|
-
last_seen TEXT NOT NULL,
|
|
95
|
-
metadata TEXT
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
-- Indexes for performance (created AFTER all tables)
|
|
99
|
-
CREATE INDEX IF NOT EXISTS idx_events_mailbox ON events(mailbox_id);
|
|
100
|
-
CREATE INDEX IF NOT EXISTS idx_events_stream ON events(stream_type, stream_id, occurred_at);
|
|
101
|
-
CREATE INDEX IF NOT EXISTS idx_events_sequence ON events(stream_type, stream_id, sequence_number);
|
|
102
|
-
CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
|
|
103
|
-
CREATE INDEX IF NOT EXISTS idx_locks_file ON locks(file);
|
|
104
|
-
CREATE INDEX IF NOT EXISTS idx_locks_reserved_by ON locks(reserved_by);
|
|
105
|
-
CREATE INDEX IF NOT EXISTS idx_specialists_status ON specialists(status);
|
|
106
|
-
|
|
107
|
-
-- Triggers for updated_at
|
|
108
|
-
CREATE TRIGGER IF NOT EXISTS update_mailbox_timestamp
|
|
109
|
-
AFTER UPDATE ON mailboxes
|
|
110
|
-
BEGIN
|
|
111
|
-
UPDATE mailboxes SET updated_at = datetime('now') WHERE id = NEW.id;
|
|
112
|
-
END;
|
package/src/db/sqlite.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import Database from 'bun:sqlite';
|
|
2
|
-
import type { DatabaseAdapter, DatabaseStats, MissionOps, SortieOps, LockOps, EventOps, CheckpointOps, SpecialistOps, MessageOps, CursorOps } from './types.js';
|
|
3
|
-
export declare class SQLiteAdapter implements DatabaseAdapter {
|
|
4
|
-
version: "1.0.0";
|
|
5
|
-
private db;
|
|
6
|
-
private dbPath;
|
|
7
|
-
private schemaPath;
|
|
8
|
-
missions: MissionOps;
|
|
9
|
-
sorties: SortieOps;
|
|
10
|
-
locks: LockOps;
|
|
11
|
-
events: EventOps;
|
|
12
|
-
checkpoints: CheckpointOps;
|
|
13
|
-
specialists: SpecialistOps;
|
|
14
|
-
messages: MessageOps;
|
|
15
|
-
cursors: CursorOps;
|
|
16
|
-
constructor(dbPath?: string, schemaPath?: string);
|
|
17
|
-
private resolveSchemaPath;
|
|
18
|
-
initialize(): Promise<void>;
|
|
19
|
-
private initializeOperations;
|
|
20
|
-
close(): Promise<void>;
|
|
21
|
-
isHealthy(): Promise<boolean>;
|
|
22
|
-
getStats(): Promise<DatabaseStats>;
|
|
23
|
-
maintenance(): Promise<void>;
|
|
24
|
-
beginTransaction(): Promise<void>;
|
|
25
|
-
commitTransaction(): Promise<void>;
|
|
26
|
-
rollbackTransaction(): Promise<void>;
|
|
27
|
-
getDatabase(): Database | null;
|
|
28
|
-
}
|
|
29
|
-
export declare function createSQLiteAdapter(dbPath?: string): Promise<SQLiteAdapter>;
|
|
30
|
-
export declare function createInMemoryAdapter(): Promise<SQLiteAdapter>;
|
|
31
|
-
//# sourceMappingURL=sqlite.d.ts.map
|
package/src/db/sqlite.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["sqlite.ts"],"names":[],"mappings":"AAEA,OAAO,QAAQ,MAAM,YAAY,CAAC;AAGlC,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EAEb,UAAU,EACV,SAAS,EACT,OAAO,EACP,QAAQ,EACR,aAAa,EACb,aAAa,EACb,UAAU,EACV,SAAS,EAQV,MAAM,YAAY,CAAC;AAEpB,qBAAa,aAAc,YAAW,eAAe;IACnD,OAAO,EAAG,OAAO,CAAU;IAE3B,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;IAEpB,QAAQ,EAAE,UAAU,CAAoB;IACxC,OAAO,EAAE,SAAS,CAAmB;IACrC,KAAK,EAAE,OAAO,CAAiB;IAC/B,MAAM,EAAE,QAAQ,CAAkB;IAClC,WAAW,EAAE,aAAa,CAAuB;IACjD,WAAW,EAAE,aAAa,CAAuB;IACjD,QAAQ,EAAE,UAAU,CAAoB;IACxC,OAAO,EAAE,SAAS,CAAmB;gBAEhC,MAAM,GAAE,MAAmB,EAAE,UAAU,CAAC,EAAE,MAAM;IAW5D,OAAO,CAAC,iBAAiB;IA0CnB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BjC,OAAO,CAAC,oBAAoB;IAmjBtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAatB,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAa7B,QAAQ,IAAI,OAAO,CAAC,aAAa,CAAC;IAuClC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAc5B,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAajC,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAalC,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAa1C,WAAW,IAAI,QAAQ,GAAG,IAAI;CAG/B;AAED,wBAAsB,mBAAmB,CAAC,MAAM,GAAE,MAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAI7F;AAED,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,aAAa,CAAC,CAEpE"}
|