@spool-lab/core 0.4.1 → 0.4.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/db/db.d.ts +28 -1
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db.js +320 -17
- package/dist/db/db.js.map +1 -1
- package/dist/db/queries.d.ts +36 -11
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +118 -83
- package/dist/db/queries.js.map +1 -1
- package/dist/db/share-drafts.d.ts +51 -0
- package/dist/db/share-drafts.d.ts.map +1 -0
- package/dist/db/share-drafts.js +47 -0
- package/dist/db/share-drafts.js.map +1 -0
- package/dist/doctor/checks/config.d.ts +3 -0
- package/dist/doctor/checks/config.d.ts.map +1 -0
- package/dist/doctor/checks/config.js +123 -0
- package/dist/doctor/checks/config.js.map +1 -0
- package/dist/doctor/checks/db.d.ts +3 -0
- package/dist/doctor/checks/db.d.ts.map +1 -0
- package/dist/doctor/checks/db.js +225 -0
- package/dist/doctor/checks/db.js.map +1 -0
- package/dist/doctor/checks/env.d.ts +3 -0
- package/dist/doctor/checks/env.d.ts.map +1 -0
- package/dist/doctor/checks/env.js +70 -0
- package/dist/doctor/checks/env.js.map +1 -0
- package/dist/doctor/checks/index.d.ts +3 -0
- package/dist/doctor/checks/index.d.ts.map +1 -0
- package/dist/doctor/checks/index.js +13 -0
- package/dist/doctor/checks/index.js.map +1 -0
- package/dist/doctor/checks/native.d.ts +3 -0
- package/dist/doctor/checks/native.d.ts.map +1 -0
- package/dist/doctor/checks/native.js +42 -0
- package/dist/doctor/checks/native.js.map +1 -0
- package/dist/doctor/checks/versions.d.ts +3 -0
- package/dist/doctor/checks/versions.d.ts.map +1 -0
- package/dist/doctor/checks/versions.js +79 -0
- package/dist/doctor/checks/versions.js.map +1 -0
- package/dist/doctor/index.d.ts +3 -0
- package/dist/doctor/index.d.ts.map +1 -0
- package/dist/doctor/index.js +3 -0
- package/dist/doctor/index.js.map +1 -0
- package/dist/doctor/preflight.d.ts +18 -0
- package/dist/doctor/preflight.d.ts.map +1 -0
- package/dist/doctor/preflight.js +27 -0
- package/dist/doctor/preflight.js.map +1 -0
- package/dist/doctor/runner.d.ts +12 -0
- package/dist/doctor/runner.d.ts.map +1 -0
- package/dist/doctor/runner.js +37 -0
- package/dist/doctor/runner.js.map +1 -0
- package/dist/doctor/types.d.ts +27 -0
- package/dist/doctor/types.d.ts.map +1 -0
- package/dist/doctor/types.js +2 -0
- package/dist/doctor/types.js.map +1 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/migrations/agent-search-cleanup.d.ts +36 -0
- package/dist/migrations/agent-search-cleanup.d.ts.map +1 -0
- package/dist/migrations/agent-search-cleanup.js +182 -0
- package/dist/migrations/agent-search-cleanup.js.map +1 -0
- package/dist/migrations/worktree-identity-upgrade.d.ts +31 -0
- package/dist/migrations/worktree-identity-upgrade.d.ts.map +1 -0
- package/dist/migrations/worktree-identity-upgrade.js +22 -0
- package/dist/migrations/worktree-identity-upgrade.js.map +1 -0
- package/dist/parsers/claude.d.ts.map +1 -1
- package/dist/parsers/claude.js +25 -12
- package/dist/parsers/claude.js.map +1 -1
- package/dist/parsers/codex.d.ts.map +1 -1
- package/dist/parsers/codex.js +32 -5
- package/dist/parsers/codex.js.map +1 -1
- package/dist/parsers/gemini.d.ts.map +1 -1
- package/dist/parsers/gemini.js +5 -5
- package/dist/parsers/gemini.js.map +1 -1
- package/dist/parsers/spool-prelude.d.ts +16 -0
- package/dist/parsers/spool-prelude.d.ts.map +1 -0
- package/dist/parsers/spool-prelude.js +21 -0
- package/dist/parsers/spool-prelude.js.map +1 -0
- package/dist/projects/display-name.d.ts +2 -0
- package/dist/projects/display-name.d.ts.map +1 -0
- package/dist/projects/display-name.js +8 -0
- package/dist/projects/display-name.js.map +1 -0
- package/dist/projects/fs.d.ts +3 -0
- package/dist/projects/fs.d.ts.map +1 -0
- package/dist/projects/fs.js +20 -0
- package/dist/projects/fs.js.map +1 -0
- package/dist/projects/groups.d.ts +4 -0
- package/dist/projects/groups.d.ts.map +1 -0
- package/dist/projects/groups.js +20 -0
- package/dist/projects/groups.js.map +1 -0
- package/dist/projects/identity-synthesizers.d.ts +22 -0
- package/dist/projects/identity-synthesizers.d.ts.map +1 -0
- package/dist/projects/identity-synthesizers.js +29 -0
- package/dist/projects/identity-synthesizers.js.map +1 -0
- package/dist/projects/identity.d.ts +16 -0
- package/dist/projects/identity.d.ts.map +1 -0
- package/dist/projects/identity.js +172 -0
- package/dist/projects/identity.js.map +1 -0
- package/dist/projects/sessions.d.ts +40 -0
- package/dist/projects/sessions.d.ts.map +1 -0
- package/dist/projects/sessions.js +151 -0
- package/dist/projects/sessions.js.map +1 -0
- package/dist/projects/worktree-resolvers.d.ts +19 -0
- package/dist/projects/worktree-resolvers.d.ts.map +1 -0
- package/dist/projects/worktree-resolvers.js +65 -0
- package/dist/projects/worktree-resolvers.js.map +1 -0
- package/dist/security/index.d.ts +14 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +7 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/maintenance.d.ts +15 -0
- package/dist/security/maintenance.d.ts.map +1 -0
- package/dist/security/maintenance.js +68 -0
- package/dist/security/maintenance.js.map +1 -0
- package/dist/security/profile.d.ts +47 -0
- package/dist/security/profile.d.ts.map +1 -0
- package/dist/security/profile.js +122 -0
- package/dist/security/profile.js.map +1 -0
- package/dist/security/purge.d.ts +49 -0
- package/dist/security/purge.d.ts.map +1 -0
- package/dist/security/purge.js +159 -0
- package/dist/security/purge.js.map +1 -0
- package/dist/security/repo.d.ts +141 -0
- package/dist/security/repo.d.ts.map +1 -0
- package/dist/security/repo.js +469 -0
- package/dist/security/repo.js.map +1 -0
- package/dist/security/scan.d.ts +50 -0
- package/dist/security/scan.d.ts.map +1 -0
- package/dist/security/scan.js +120 -0
- package/dist/security/scan.js.map +1 -0
- package/dist/security/types.d.ts +128 -0
- package/dist/security/types.d.ts.map +1 -0
- package/dist/security/types.js +10 -0
- package/dist/security/types.js.map +1 -0
- package/dist/security/worker.d.ts +53 -0
- package/dist/security/worker.d.ts.map +1 -0
- package/dist/security/worker.js +180 -0
- package/dist/security/worker.js.map +1 -0
- package/dist/sync/source-paths.d.ts +1 -0
- package/dist/sync/source-paths.d.ts.map +1 -1
- package/dist/sync/source-paths.js +13 -3
- package/dist/sync/source-paths.js.map +1 -1
- package/dist/sync/syncer.d.ts +8 -1
- package/dist/sync/syncer.d.ts.map +1 -1
- package/dist/sync/syncer.js +37 -17
- package/dist/sync/syncer.js.map +1 -1
- package/dist/types.d.ts +28 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/util/resolve-bin.d.ts +34 -0
- package/dist/util/resolve-bin.d.ts.map +1 -1
- package/dist/util/resolve-bin.js +175 -20
- package/dist/util/resolve-bin.js.map +1 -1
- package/package.json +5 -2
package/dist/db/db.d.ts
CHANGED
|
@@ -1,10 +1,37 @@
|
|
|
1
1
|
import Database from 'better-sqlite3';
|
|
2
|
+
import { type IdentityFs } from '../projects/identity.js';
|
|
2
3
|
export declare const SPOOL_DIR: string;
|
|
3
4
|
export declare const DB_PATH: string;
|
|
4
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Latest schema version the running build knows how to migrate to.
|
|
7
|
+
* Bump in lockstep with the last `db.pragma('user_version = N')` in runMigrations.
|
|
8
|
+
*/
|
|
9
|
+
export declare const LATEST_SCHEMA_VERSION = 13;
|
|
10
|
+
export interface OpenOptions {
|
|
11
|
+
/** Worker-thread callers should pass `false` — the main process has
|
|
12
|
+
* already run migrations on the shared DB file before spawning, and
|
|
13
|
+
* two threads racing through the migration script trip over each
|
|
14
|
+
* other on the `CREATE TRIGGER` / index steps (DROP IF EXISTS +
|
|
15
|
+
* CREATE is not atomic across connections). Default `true`. */
|
|
16
|
+
runMigrations?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function getDB(arg?: boolean | OpenOptions): Database.Database;
|
|
5
19
|
/** True if the DB file did not exist before this process opened it. */
|
|
6
20
|
export declare function wasNewDb(): boolean;
|
|
7
21
|
/** user_version of the DB before any migrations ran this process. Null if getDB() hasn't been called. */
|
|
8
22
|
export declare function getInitialUserVersion(): number | null;
|
|
9
23
|
export declare function getDBSize(): number;
|
|
24
|
+
export declare function runMigrations(db: Database.Database): void;
|
|
25
|
+
export declare function backfillProjectIdentities(db: Database.Database, fs: IdentityFs): void;
|
|
26
|
+
/**
|
|
27
|
+
* Snapshot the DB to `<dbDir>/backups/spool-pre-v{fromVersion+1}-<ts>.db`
|
|
28
|
+
* via VACUUM INTO, before a destructive migration runs.
|
|
29
|
+
*
|
|
30
|
+
* Returns the backup file path on success, or null when a backup is skipped:
|
|
31
|
+
* - in-memory DBs (db.memory)
|
|
32
|
+
* - fresh-install / no-data DBs (sessions table empty or missing)
|
|
33
|
+
*
|
|
34
|
+
* Each call writes to a distinct path; v5 and v7 produce separate files.
|
|
35
|
+
*/
|
|
36
|
+
export declare function backupBeforeDestructive(db: Database.Database, fromVersion: number): string | null;
|
|
10
37
|
//# sourceMappingURL=db.d.ts.map
|
package/dist/db/db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAA;AAIrC,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAK1E,eAAO,MAAM,SAAS,QAA6D,CAAA;AACnF,eAAO,MAAM,OAAO,QAA8B,CAAA;AAElD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,KAAK,CAAA;AAMvC,MAAM,WAAW,WAAW;IAC1B;;;;oEAIgE;IAChE,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,wBAAgB,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAqBpE;AAED,uEAAuE;AACvE,wBAAgB,QAAQ,IAAI,OAAO,CAAqB;AAExD,yGAAyG;AACzG,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAA+B;AAErF,wBAAgB,SAAS,IAAI,MAAM,CAMlC;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAohBzD;AAED,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,UAAU,QAgB9E;AA0BD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,IAAI,CAef"}
|
package/dist/db/db.js
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
import Database from 'better-sqlite3';
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
4
|
import { existsSync, mkdirSync, statSync } from 'node:fs';
|
|
5
|
+
import { computeIdentity } from '../projects/identity.js';
|
|
6
|
+
import { realFs } from '../projects/fs.js';
|
|
7
|
+
import { runAgentSearchCleanup } from '../migrations/agent-search-cleanup.js';
|
|
8
|
+
import { upgradeWorktreeIdentities } from '../migrations/worktree-identity-upgrade.js';
|
|
5
9
|
export const SPOOL_DIR = process.env['SPOOL_DATA_DIR'] ?? join(homedir(), '.spool');
|
|
6
10
|
export const DB_PATH = join(SPOOL_DIR, 'spool.db');
|
|
11
|
+
/**
|
|
12
|
+
* Latest schema version the running build knows how to migrate to.
|
|
13
|
+
* Bump in lockstep with the last `db.pragma('user_version = N')` in runMigrations.
|
|
14
|
+
*/
|
|
15
|
+
export const LATEST_SCHEMA_VERSION = 13;
|
|
7
16
|
let _db = null;
|
|
8
17
|
let _wasNewDb = false;
|
|
9
18
|
let _initialUserVersion = null;
|
|
10
|
-
export function getDB(
|
|
19
|
+
export function getDB(arg) {
|
|
11
20
|
if (_db)
|
|
12
21
|
return _db;
|
|
22
|
+
const opts = typeof arg === 'object' && arg !== null ? arg : {};
|
|
23
|
+
const shouldRunMigrations = opts.runMigrations !== false;
|
|
13
24
|
mkdirSync(SPOOL_DIR, { recursive: true });
|
|
14
25
|
// Capture pre-open state before better-sqlite3 creates the file. These two
|
|
15
26
|
// signals together let callers tell apart "fresh install" from "upgrade":
|
|
@@ -21,7 +32,9 @@ export function getDB(_readonly = false) {
|
|
|
21
32
|
db.pragma('foreign_keys = ON');
|
|
22
33
|
db.pragma('busy_timeout = 5000');
|
|
23
34
|
_initialUserVersion = db.pragma('user_version')[0]?.user_version ?? 0;
|
|
24
|
-
|
|
35
|
+
if (shouldRunMigrations) {
|
|
36
|
+
runMigrations(db);
|
|
37
|
+
}
|
|
25
38
|
_db = db;
|
|
26
39
|
return db;
|
|
27
40
|
}
|
|
@@ -37,7 +50,7 @@ export function getDBSize() {
|
|
|
37
50
|
return 0;
|
|
38
51
|
}
|
|
39
52
|
}
|
|
40
|
-
function runMigrations(db) {
|
|
53
|
+
export function runMigrations(db) {
|
|
41
54
|
db.exec(`
|
|
42
55
|
CREATE TABLE IF NOT EXISTS sources (
|
|
43
56
|
id INTEGER PRIMARY KEY,
|
|
@@ -68,6 +81,7 @@ function runMigrations(db) {
|
|
|
68
81
|
session_uuid TEXT NOT NULL UNIQUE,
|
|
69
82
|
file_path TEXT NOT NULL UNIQUE,
|
|
70
83
|
title TEXT,
|
|
84
|
+
title_source TEXT NOT NULL DEFAULT 'derived',
|
|
71
85
|
started_at TEXT NOT NULL,
|
|
72
86
|
ended_at TEXT NOT NULL,
|
|
73
87
|
message_count INTEGER NOT NULL DEFAULT 0,
|
|
@@ -164,6 +178,7 @@ function runMigrations(db) {
|
|
|
164
178
|
`);
|
|
165
179
|
db.exec(`
|
|
166
180
|
DROP TRIGGER IF EXISTS messages_fts_insert;
|
|
181
|
+
DROP TRIGGER IF EXISTS messages_fts_update;
|
|
167
182
|
DROP TRIGGER IF EXISTS messages_fts_delete;
|
|
168
183
|
DROP TRIGGER IF EXISTS session_search_fts_insert;
|
|
169
184
|
DROP TRIGGER IF EXISTS session_search_fts_update;
|
|
@@ -177,6 +192,23 @@ function runMigrations(db) {
|
|
|
177
192
|
VALUES(NEW.id, NEW.content_text);
|
|
178
193
|
END;
|
|
179
194
|
|
|
195
|
+
-- Security Scan's Purge action UPDATEs messages.content_text in
|
|
196
|
+
-- place. FTS external-content tables don't auto-sync on UPDATE —
|
|
197
|
+
-- we issue the 'delete' command for the old text and re-insert
|
|
198
|
+
-- the new. Without this trigger the FTS index keeps matching the
|
|
199
|
+
-- raw value after Purge, defeating the threat-model goal.
|
|
200
|
+
CREATE TRIGGER messages_fts_update
|
|
201
|
+
AFTER UPDATE OF content_text ON messages BEGIN
|
|
202
|
+
INSERT INTO messages_fts(messages_fts, rowid, content_text)
|
|
203
|
+
VALUES('delete', OLD.id, OLD.content_text);
|
|
204
|
+
INSERT INTO messages_fts(rowid, content_text)
|
|
205
|
+
VALUES(NEW.id, NEW.content_text);
|
|
206
|
+
INSERT INTO messages_fts_trigram(messages_fts_trigram, rowid, content_text)
|
|
207
|
+
VALUES('delete', OLD.id, OLD.content_text);
|
|
208
|
+
INSERT INTO messages_fts_trigram(rowid, content_text)
|
|
209
|
+
VALUES(NEW.id, NEW.content_text);
|
|
210
|
+
END;
|
|
211
|
+
|
|
180
212
|
CREATE TRIGGER messages_fts_delete
|
|
181
213
|
AFTER DELETE ON messages BEGIN
|
|
182
214
|
INSERT INTO messages_fts(messages_fts, rowid, content_text)
|
|
@@ -218,29 +250,27 @@ function runMigrations(db) {
|
|
|
218
250
|
// Each migration runs exactly once. Add new migrations at the end with
|
|
219
251
|
// the next sequential version number.
|
|
220
252
|
const version = db.pragma('user_version')[0].user_version;
|
|
221
|
-
// Historical connector migrations (v1-v3): all operate on
|
|
222
|
-
//
|
|
223
|
-
//
|
|
253
|
+
// Historical connector migrations (v1-v3): all operate on tables that v5
|
|
254
|
+
// dropped (connector_sync_state, captures, capture_connectors,
|
|
255
|
+
// captures_fts*). Guard each on the relevant table existing — fresh
|
|
256
|
+
// installs (post-v5 schema) skip these without ever touching the SQL.
|
|
224
257
|
if (version < 1) {
|
|
225
|
-
|
|
258
|
+
if (tableExists(db, 'connector_sync_state')) {
|
|
226
259
|
db.exec('ALTER TABLE connector_sync_state ADD COLUMN last_error_at TEXT');
|
|
227
260
|
}
|
|
228
|
-
catch { }
|
|
229
261
|
db.pragma('user_version = 1');
|
|
230
262
|
}
|
|
231
263
|
if (version < 2) {
|
|
232
|
-
|
|
264
|
+
if (tableExists(db, 'captures_fts')) {
|
|
233
265
|
db.exec("INSERT INTO captures_fts(captures_fts) VALUES('rebuild')");
|
|
234
266
|
}
|
|
235
|
-
|
|
236
|
-
try {
|
|
267
|
+
if (tableExists(db, 'captures_fts_trigram')) {
|
|
237
268
|
db.exec("INSERT INTO captures_fts_trigram(captures_fts_trigram) VALUES('rebuild')");
|
|
238
269
|
}
|
|
239
|
-
catch { }
|
|
240
270
|
db.pragma('user_version = 2');
|
|
241
271
|
}
|
|
242
272
|
if (version < 3) {
|
|
243
|
-
|
|
273
|
+
if (tableExists(db, 'captures') && tableExists(db, 'capture_connectors')) {
|
|
244
274
|
db.transaction(() => {
|
|
245
275
|
db.exec(`
|
|
246
276
|
INSERT OR IGNORE INTO capture_connectors (capture_id, connector_id)
|
|
@@ -261,7 +291,6 @@ function runMigrations(db) {
|
|
|
261
291
|
db.exec(`DROP INDEX IF EXISTS idx_captures_source`);
|
|
262
292
|
})();
|
|
263
293
|
}
|
|
264
|
-
catch { }
|
|
265
294
|
db.pragma('user_version = 3');
|
|
266
295
|
}
|
|
267
296
|
if (version < 4) {
|
|
@@ -285,8 +314,9 @@ function runMigrations(db) {
|
|
|
285
314
|
// SQLite can't ALTER a CHECK constraint, so we rebuild the stars table.
|
|
286
315
|
// For users who never had the wide CHECK (fresh install on post-v5
|
|
287
316
|
// schema), the rebuild is a no-op rename round-trip — safe and cheap.
|
|
288
|
-
// Captures data is dropped
|
|
289
|
-
//
|
|
317
|
+
// Captures data is dropped here; users were directed to Spool Daemon for
|
|
318
|
+
// connector functionality. We snapshot first so the data is recoverable.
|
|
319
|
+
backupBeforeDestructive(db, 4);
|
|
290
320
|
db.transaction(() => {
|
|
291
321
|
db.exec(`DROP TRIGGER IF EXISTS captures_fts_insert`);
|
|
292
322
|
db.exec(`DROP TRIGGER IF EXISTS captures_fts_delete`);
|
|
@@ -313,10 +343,283 @@ function runMigrations(db) {
|
|
|
313
343
|
})();
|
|
314
344
|
db.pragma('user_version = 5');
|
|
315
345
|
}
|
|
346
|
+
if (version < 6) {
|
|
347
|
+
db.transaction(() => {
|
|
348
|
+
db.exec(`
|
|
349
|
+
ALTER TABLE projects ADD COLUMN identity_kind TEXT;
|
|
350
|
+
ALTER TABLE projects ADD COLUMN identity_key TEXT;
|
|
351
|
+
CREATE INDEX IF NOT EXISTS idx_projects_identity
|
|
352
|
+
ON projects (identity_kind, identity_key);
|
|
353
|
+
|
|
354
|
+
CREATE VIEW IF NOT EXISTS project_groups_v AS
|
|
355
|
+
SELECT
|
|
356
|
+
p.identity_kind,
|
|
357
|
+
p.identity_key,
|
|
358
|
+
MIN(p.display_name) AS display_name,
|
|
359
|
+
GROUP_CONCAT(DISTINCT s.name) AS sources_csv,
|
|
360
|
+
COALESCE(SUM(c.session_count),0) AS session_count,
|
|
361
|
+
MAX(c.last_session_at) AS last_session_at
|
|
362
|
+
FROM projects p
|
|
363
|
+
JOIN sources s ON s.id = p.source_id
|
|
364
|
+
LEFT JOIN (
|
|
365
|
+
SELECT project_id,
|
|
366
|
+
COUNT(*) AS session_count,
|
|
367
|
+
MAX(started_at) AS last_session_at
|
|
368
|
+
FROM sessions
|
|
369
|
+
WHERE message_count > 0
|
|
370
|
+
GROUP BY project_id
|
|
371
|
+
) c ON c.project_id = p.id
|
|
372
|
+
WHERE p.identity_kind IS NOT NULL
|
|
373
|
+
GROUP BY p.identity_kind, p.identity_key;
|
|
374
|
+
`);
|
|
375
|
+
})();
|
|
376
|
+
db.pragma('user_version = 6');
|
|
377
|
+
backfillProjectIdentities(db, realFs);
|
|
378
|
+
}
|
|
379
|
+
if (version < 7) {
|
|
380
|
+
backupBeforeDestructive(db, 6);
|
|
381
|
+
db.transaction(() => {
|
|
382
|
+
db.exec(`
|
|
383
|
+
CREATE TABLE pins (
|
|
384
|
+
session_uuid TEXT PRIMARY KEY,
|
|
385
|
+
pinned_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
386
|
+
);
|
|
387
|
+
CREATE INDEX IF NOT EXISTS idx_pins_pinned_at ON pins (pinned_at DESC);
|
|
388
|
+
INSERT OR IGNORE INTO pins (session_uuid, pinned_at)
|
|
389
|
+
SELECT item_uuid, starred_at FROM stars WHERE item_type = 'session';
|
|
390
|
+
DROP TABLE stars;
|
|
391
|
+
`);
|
|
392
|
+
})();
|
|
393
|
+
db.pragma('user_version = 7');
|
|
394
|
+
}
|
|
395
|
+
if (version < 8) {
|
|
396
|
+
// v8: title_source column distinguishes title authority. 'derived' = parsed
|
|
397
|
+
// from source JSONL (default; sync may overwrite). 'spool' = written by
|
|
398
|
+
// Spool itself (e.g. agent-search session created in-app). 'user' = user
|
|
399
|
+
// edited in Spool. Sync only overwrites 'derived' rows.
|
|
400
|
+
if (!columnExists(db, 'sessions', 'title_source')) {
|
|
401
|
+
db.exec(`ALTER TABLE sessions ADD COLUMN title_source TEXT NOT NULL DEFAULT 'derived'`);
|
|
402
|
+
}
|
|
403
|
+
db.pragma('user_version = 8');
|
|
404
|
+
}
|
|
405
|
+
// Schema sanity runs BEFORE any data migration that depends on these
|
|
406
|
+
// columns. Repairs DBs where a version pragma was bumped (by experimental
|
|
407
|
+
// code, a manual upgrade, or a half-finished migration) without the
|
|
408
|
+
// corresponding column being added. Each check is a fast no-op when the
|
|
409
|
+
// column already exists.
|
|
410
|
+
ensureSchemaSanity(db);
|
|
411
|
+
if (version < 9) {
|
|
412
|
+
// v9: one-time data cleanup of historical agent-search sessions indexed
|
|
413
|
+
// before #150-#153. Detection is gated on the Spool buildPrompt blob in
|
|
414
|
+
// a user message (Spool-unique signal) so it can never sweep up real
|
|
415
|
+
// coding sessions whose first message happened to be Claude Code's
|
|
416
|
+
// injected <local-command-caveat>. See migrations/agent-search-cleanup.ts
|
|
417
|
+
// for the full rationale.
|
|
418
|
+
backupBeforeDestructive(db, 8);
|
|
419
|
+
db.transaction(() => {
|
|
420
|
+
runAgentSearchCleanup(db);
|
|
421
|
+
})();
|
|
422
|
+
db.pragma('user_version = 9');
|
|
423
|
+
}
|
|
424
|
+
if (version < 10) {
|
|
425
|
+
// v10: re-classify path-kind projects that are stranded worktree cwds.
|
|
426
|
+
// Before the worktree resolvers landed, a session synced after its
|
|
427
|
+
// worktree was deleted couldn't reach the upstream git remote and was
|
|
428
|
+
// bucketed as its own path-kind project. The resolver now reads the
|
|
429
|
+
// worktree tool's persistent registry (e.g. ~/.superset/local.db) and
|
|
430
|
+
// recovers the real identity. See migrations/worktree-identity-upgrade.ts.
|
|
431
|
+
db.transaction(() => {
|
|
432
|
+
upgradeWorktreeIdentities(db, realFs);
|
|
433
|
+
})();
|
|
434
|
+
db.pragma('user_version = 10');
|
|
435
|
+
}
|
|
436
|
+
if (version < 11) {
|
|
437
|
+
// v11: share_drafts table — locally-persisted in-progress shares
|
|
438
|
+
// managed by Spool Share's editor. Independent of the sessions index;
|
|
439
|
+
// a draft can survive its source session being deleted because the
|
|
440
|
+
// full snapshot is captured at compose time and stored as JSON.
|
|
441
|
+
//
|
|
442
|
+
// Two JSON payloads per row:
|
|
443
|
+
// - snapshot_json: the complete SpoolDocument (full conversation +
|
|
444
|
+
// opts). Used when opening the editor. Can be hundreds of KB on
|
|
445
|
+
// long sessions.
|
|
446
|
+
// - preview_json: a slim subset used by the Shares grid card —
|
|
447
|
+
// opts + title + source + word count + the first handful of
|
|
448
|
+
// turns. Kept under a few KB so listShareDrafts can SELECT it
|
|
449
|
+
// across hundreds of rows without shipping multi-MB IPC payloads
|
|
450
|
+
// to the renderer.
|
|
451
|
+
db.exec(`
|
|
452
|
+
CREATE TABLE IF NOT EXISTS share_drafts (
|
|
453
|
+
draft_id TEXT PRIMARY KEY,
|
|
454
|
+
source_kind TEXT NOT NULL CHECK (source_kind IN (
|
|
455
|
+
'spool-session', 'pasted-url', 'imported-file', 'imported-jsonl'
|
|
456
|
+
)),
|
|
457
|
+
source_origin TEXT,
|
|
458
|
+
title TEXT NOT NULL DEFAULT '',
|
|
459
|
+
snapshot_json TEXT NOT NULL,
|
|
460
|
+
preview_json TEXT NOT NULL DEFAULT '{}',
|
|
461
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
462
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
463
|
+
);
|
|
464
|
+
CREATE INDEX IF NOT EXISTS idx_share_drafts_updated_at
|
|
465
|
+
ON share_drafts(updated_at DESC);
|
|
466
|
+
CREATE INDEX IF NOT EXISTS idx_share_drafts_source_origin
|
|
467
|
+
ON share_drafts(source_origin);
|
|
468
|
+
`);
|
|
469
|
+
db.pragma('user_version = 11');
|
|
470
|
+
}
|
|
471
|
+
if (version < 12) {
|
|
472
|
+
// v12: Security Scan — sidecar findings + allowlists. The five
|
|
473
|
+
// scan_* columns on sessions are denormalised counters
|
|
474
|
+
// maintained by the scan worker; findings stores (kind,
|
|
475
|
+
// value_hash, offsets) only — never the raw value. Purge mutates
|
|
476
|
+
// messages.content_text and flips the row to state='purged'; the
|
|
477
|
+
// row remains as an audit record. scan_purged_count is the
|
|
478
|
+
// lifetime tally of purged findings per session, used by the
|
|
479
|
+
// Library row's "all-resolved ✓" badge to distinguish "never
|
|
480
|
+
// had findings" from "was clean after I cleaned it up".
|
|
481
|
+
//
|
|
482
|
+
// Wrapped in a transaction so a mid-migration failure (process
|
|
483
|
+
// killed, disk full, etc.) doesn't leave the DB half-altered.
|
|
484
|
+
// Without this, a partial v12 — say two ALTER TABLEs landed
|
|
485
|
+
// but the third failed — would auto-commit the first two and
|
|
486
|
+
// leave user_version at 11; the next launch would retry from
|
|
487
|
+
// the first ALTER and trip a "duplicate column" error,
|
|
488
|
+
// bricking the app on every subsequent startup.
|
|
489
|
+
db.transaction(() => {
|
|
490
|
+
db.exec(`
|
|
491
|
+
ALTER TABLE sessions ADD COLUMN scan_profile TEXT;
|
|
492
|
+
ALTER TABLE sessions ADD COLUMN scan_completed_at TEXT;
|
|
493
|
+
ALTER TABLE sessions ADD COLUMN scan_finding_count INTEGER NOT NULL DEFAULT 0;
|
|
494
|
+
ALTER TABLE sessions ADD COLUMN scan_high_count INTEGER NOT NULL DEFAULT 0;
|
|
495
|
+
ALTER TABLE sessions ADD COLUMN scan_purged_count INTEGER NOT NULL DEFAULT 0;
|
|
496
|
+
|
|
497
|
+
CREATE TABLE IF NOT EXISTS findings (
|
|
498
|
+
id INTEGER PRIMARY KEY,
|
|
499
|
+
session_id INTEGER NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
500
|
+
message_id INTEGER REFERENCES messages(id) ON DELETE CASCADE,
|
|
501
|
+
kind TEXT NOT NULL,
|
|
502
|
+
value_hash TEXT NOT NULL,
|
|
503
|
+
confidence REAL NOT NULL,
|
|
504
|
+
provider TEXT NOT NULL,
|
|
505
|
+
start_offset INTEGER NOT NULL,
|
|
506
|
+
end_offset INTEGER NOT NULL,
|
|
507
|
+
state TEXT NOT NULL DEFAULT 'active'
|
|
508
|
+
CHECK (state IN ('active','dismissed','purged')),
|
|
509
|
+
detected_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
510
|
+
state_changed_at TEXT
|
|
511
|
+
);
|
|
512
|
+
CREATE INDEX IF NOT EXISTS idx_findings_session ON findings(session_id);
|
|
513
|
+
CREATE INDEX IF NOT EXISTS idx_findings_state ON findings(state);
|
|
514
|
+
CREATE INDEX IF NOT EXISTS idx_findings_kind_hash ON findings(kind, value_hash);
|
|
515
|
+
|
|
516
|
+
CREATE TABLE IF NOT EXISTS allowlist_session (
|
|
517
|
+
session_id INTEGER NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
518
|
+
kind TEXT NOT NULL,
|
|
519
|
+
value_hash TEXT NOT NULL,
|
|
520
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
521
|
+
PRIMARY KEY (session_id, kind, value_hash)
|
|
522
|
+
);
|
|
523
|
+
|
|
524
|
+
CREATE TABLE IF NOT EXISTS allowlist_global (
|
|
525
|
+
kind TEXT NOT NULL,
|
|
526
|
+
value_hash TEXT NOT NULL,
|
|
527
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
528
|
+
PRIMARY KEY (kind, value_hash)
|
|
529
|
+
);
|
|
530
|
+
`);
|
|
531
|
+
db.pragma('user_version = 12');
|
|
532
|
+
})();
|
|
533
|
+
}
|
|
534
|
+
if (version < 13) {
|
|
535
|
+
// v13: purge subagent jsonl rows that hijacked their parent's session_uuid.
|
|
536
|
+
// Claude code writes subagent transcripts to <slug>/<uuid>/subagents/agent-*.jsonl;
|
|
537
|
+
// every record inside carries sessionId = parent uuid, so the indexer used to
|
|
538
|
+
// upsert these on top of the parent row via UNIQUE(session_uuid) — clobbering
|
|
539
|
+
// file_path and zeroing message_count (all messages are isSidechain). The
|
|
540
|
+
// matching read-side fix in source-paths.ts excludes the files going forward;
|
|
541
|
+
// here we delete the orphan rows so the next sync re-indexes the real parent.
|
|
542
|
+
// Cascades cover messages / session_search / findings / allowlist_session;
|
|
543
|
+
// pins survives (keyed by session_uuid TEXT, no FK) and re-attaches on re-sync.
|
|
544
|
+
db.transaction(() => {
|
|
545
|
+
const claudeSourceId = db.prepare("SELECT id FROM sources WHERE name = 'claude'").get()?.id;
|
|
546
|
+
if (claudeSourceId !== undefined) {
|
|
547
|
+
db.prepare(`DELETE FROM sessions
|
|
548
|
+
WHERE source_id = ?
|
|
549
|
+
AND file_path LIKE '%/subagents/agent-%'`).run(claudeSourceId);
|
|
550
|
+
db.prepare(`DELETE FROM sync_log
|
|
551
|
+
WHERE source_id = ?
|
|
552
|
+
AND file_path LIKE '%/subagents/agent-%'`).run(claudeSourceId);
|
|
553
|
+
}
|
|
554
|
+
db.pragma('user_version = 13');
|
|
555
|
+
})();
|
|
556
|
+
}
|
|
316
557
|
rebuildFtsTableIfEmpty(db, 'messages', 'messages_fts_trigram');
|
|
317
558
|
rebuildFtsTableIfEmpty(db, 'session_search', 'session_search_fts');
|
|
318
559
|
rebuildFtsTableIfEmpty(db, 'session_search', 'session_search_fts_trigram');
|
|
319
560
|
}
|
|
561
|
+
export function backfillProjectIdentities(db, fs) {
|
|
562
|
+
const rows = db.prepare(`SELECT id, display_path FROM projects WHERE identity_kind IS NULL`).all();
|
|
563
|
+
if (rows.length === 0)
|
|
564
|
+
return;
|
|
565
|
+
const update = db.prepare(`UPDATE projects
|
|
566
|
+
SET identity_kind = ?, identity_key = ?, display_name = COALESCE(?, display_name)
|
|
567
|
+
WHERE id = ?`);
|
|
568
|
+
db.transaction(() => {
|
|
569
|
+
for (const r of rows) {
|
|
570
|
+
const id = computeIdentity(r.display_path, fs);
|
|
571
|
+
update.run(id.kind, id.key, id.displayName, r.id);
|
|
572
|
+
}
|
|
573
|
+
})();
|
|
574
|
+
}
|
|
575
|
+
function tableExists(db, name) {
|
|
576
|
+
const row = db.prepare(`SELECT name FROM sqlite_master WHERE type IN ('table','virtual') AND name = ?`).get(name);
|
|
577
|
+
return row !== undefined;
|
|
578
|
+
}
|
|
579
|
+
function columnExists(db, table, column) {
|
|
580
|
+
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
581
|
+
return rows.some(r => r.name === column);
|
|
582
|
+
}
|
|
583
|
+
function ensureSchemaSanity(db) {
|
|
584
|
+
// Backfill columns the head schema requires but historical DBs (or test
|
|
585
|
+
// fixtures that seed an intentionally-minimal table) may be missing.
|
|
586
|
+
// Each ALTER is a fast no-op when the column already exists.
|
|
587
|
+
const ensureCol = (col, ddl) => {
|
|
588
|
+
if (!columnExists(db, 'sessions', col))
|
|
589
|
+
db.exec(`ALTER TABLE sessions ADD COLUMN ${col} ${ddl}`);
|
|
590
|
+
};
|
|
591
|
+
ensureCol('title', 'TEXT');
|
|
592
|
+
ensureCol('title_source', `TEXT NOT NULL DEFAULT 'derived'`);
|
|
593
|
+
ensureCol('message_count', 'INTEGER NOT NULL DEFAULT 0');
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Snapshot the DB to `<dbDir>/backups/spool-pre-v{fromVersion+1}-<ts>.db`
|
|
597
|
+
* via VACUUM INTO, before a destructive migration runs.
|
|
598
|
+
*
|
|
599
|
+
* Returns the backup file path on success, or null when a backup is skipped:
|
|
600
|
+
* - in-memory DBs (db.memory)
|
|
601
|
+
* - fresh-install / no-data DBs (sessions table empty or missing)
|
|
602
|
+
*
|
|
603
|
+
* Each call writes to a distinct path; v5 and v7 produce separate files.
|
|
604
|
+
*/
|
|
605
|
+
export function backupBeforeDestructive(db, fromVersion) {
|
|
606
|
+
if (db.memory)
|
|
607
|
+
return null;
|
|
608
|
+
const dbPath = db.name;
|
|
609
|
+
if (!dbPath)
|
|
610
|
+
return null;
|
|
611
|
+
if (!tableExists(db, 'sessions'))
|
|
612
|
+
return null;
|
|
613
|
+
const sessions = db.prepare(`SELECT COUNT(*) AS c FROM sessions`).get();
|
|
614
|
+
if (sessions.c === 0)
|
|
615
|
+
return null;
|
|
616
|
+
const backupDir = join(dirname(dbPath), 'backups');
|
|
617
|
+
mkdirSync(backupDir, { recursive: true });
|
|
618
|
+
const ts = new Date().toISOString().replace(/[:.]/g, '-');
|
|
619
|
+
const backupPath = join(backupDir, `spool-pre-v${fromVersion + 1}-${ts}.db`);
|
|
620
|
+
db.exec(`VACUUM INTO '${backupPath.replace(/'/g, "''")}'`);
|
|
621
|
+
return backupPath;
|
|
622
|
+
}
|
|
320
623
|
function rebuildFtsTableIfEmpty(db, contentTable, ftsTable) {
|
|
321
624
|
const sourceCount = db.prepare(`SELECT COUNT(*) AS count FROM ${contentTable}`).get().count;
|
|
322
625
|
if (sourceCount === 0)
|
package/dist/db/db.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAA;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"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"}
|
package/dist/db/queries.d.ts
CHANGED
|
@@ -1,7 +1,32 @@
|
|
|
1
1
|
import type Database from 'better-sqlite3';
|
|
2
|
-
import type { Session, Message, FragmentResult, StatusInfo, SessionSource,
|
|
3
|
-
export declare function getOrCreateProject(db: Database.Database, sourceId: number, slug: string, displayPath: string, displayName: string
|
|
2
|
+
import type { Session, Message, FragmentResult, StatusInfo, SessionSource, ProjectIdentityKind } from '../types.js';
|
|
3
|
+
export declare function getOrCreateProject(db: Database.Database, sourceId: number, slug: string, displayPath: string, displayName: string, identity: {
|
|
4
|
+
identityKind: ProjectIdentityKind;
|
|
5
|
+
identityKey: string;
|
|
6
|
+
}): number;
|
|
4
7
|
export declare function getSourceId(db: Database.Database, name: SessionSource): number;
|
|
8
|
+
/**
|
|
9
|
+
* Get/create the virtual "Asks" project that holds Spool-authored agent-search
|
|
10
|
+
* sessions. One per source so each agent's sessions stay grouped under their
|
|
11
|
+
* own row in project_groups_v (joined by identity for cross-source grouping).
|
|
12
|
+
*/
|
|
13
|
+
export declare function getOrCreateAskProject(db: Database.Database, source: SessionSource): number;
|
|
14
|
+
/**
|
|
15
|
+
* Insert a session row authored by Spool itself (e.g. agent search). Title is
|
|
16
|
+
* locked via title_source='spool' so subsequent sync of the source-side JSONL
|
|
17
|
+
* won't overwrite it. file_path uses a sentinel ('spool:pending:<uuid>') that
|
|
18
|
+
* upsertSession rebinds to the real path when sync first sees the JSONL.
|
|
19
|
+
*
|
|
20
|
+
* Idempotent: if a row with the same session_uuid already exists, returns its
|
|
21
|
+
* id without modifying anything.
|
|
22
|
+
*/
|
|
23
|
+
export declare function insertSpoolAuthoredSession(db: Database.Database, opts: {
|
|
24
|
+
projectId: number;
|
|
25
|
+
sourceId: number;
|
|
26
|
+
sessionUuid: string;
|
|
27
|
+
title: string;
|
|
28
|
+
cwd: string;
|
|
29
|
+
}): number;
|
|
5
30
|
export declare function getSessionMtime(db: Database.Database, filePath: string): string | null;
|
|
6
31
|
export declare function deleteSessionByFilePath(db: Database.Database, filePath: string): boolean;
|
|
7
32
|
export declare function getAllSessionMtimes(db: Database.Database): Map<string, string>;
|
|
@@ -35,7 +60,7 @@ export declare function insertMessages(db: Database.Database, sessionId: number,
|
|
|
35
60
|
toolNames: string[];
|
|
36
61
|
seq: number;
|
|
37
62
|
}>): void;
|
|
38
|
-
export declare
|
|
63
|
+
export declare const SESSION_SELECT = "\n SELECT\n s.id, s.project_id AS projectId, s.source_id AS sourceId,\n s.session_uuid AS sessionUuid, s.file_path AS filePath,\n s.title, s.started_at AS startedAt, s.ended_at AS endedAt,\n s.message_count AS messageCount, s.has_tool_use AS hasToolUse,\n s.cwd, s.model,\n s.scan_finding_count AS scanFindingCount,\n s.scan_high_count AS scanHighCount,\n s.scan_purged_count AS scanPurgedCount,\n s.scan_completed_at AS scanCompletedAt,\n src.name AS source,\n p.display_path AS projectDisplayPath,\n p.display_name AS projectDisplayName\n FROM sessions s\n JOIN sources src ON src.id = s.source_id\n JOIN projects p ON p.id = s.project_id";
|
|
39
64
|
export declare function getSessionWithMessages(db: Database.Database, sessionUuid: string): {
|
|
40
65
|
session: Session;
|
|
41
66
|
messages: Message[];
|
|
@@ -44,7 +69,8 @@ export declare function searchFragments(db: Database.Database, query: string, op
|
|
|
44
69
|
limit?: number;
|
|
45
70
|
source?: SessionSource;
|
|
46
71
|
since?: string;
|
|
47
|
-
|
|
72
|
+
onlyPinned?: boolean;
|
|
73
|
+
identityKey?: string;
|
|
48
74
|
}): FragmentResult[];
|
|
49
75
|
export declare function searchSessionPreview(db: Database.Database, query: string, opts?: {
|
|
50
76
|
limit?: number;
|
|
@@ -52,12 +78,11 @@ export declare function searchSessionPreview(db: Database.Database, query: strin
|
|
|
52
78
|
since?: string;
|
|
53
79
|
}): FragmentResult[];
|
|
54
80
|
export declare function buildLikeSnippet(text: string, terms: string[]): string;
|
|
55
|
-
export declare function
|
|
56
|
-
export declare function
|
|
57
|
-
export declare function
|
|
58
|
-
export declare function
|
|
59
|
-
|
|
60
|
-
};
|
|
61
|
-
export declare function listStarredItems(db: Database.Database, limit?: number): StarredItem[];
|
|
81
|
+
export declare function pinSession(db: Database.Database, sessionUuid: string): void;
|
|
82
|
+
export declare function unpinSession(db: Database.Database, sessionUuid: string): void;
|
|
83
|
+
export declare function isPinned(db: Database.Database, sessionUuid: string): boolean;
|
|
84
|
+
export declare function getPinnedUuids(db: Database.Database): string[];
|
|
85
|
+
export declare function listPinnedSessions(db: Database.Database): Session[];
|
|
62
86
|
export declare function getStatus(db: Database.Database): StatusInfo;
|
|
87
|
+
export declare function rowToSession(r: Record<string, unknown>): Session;
|
|
63
88
|
//# sourceMappingURL=queries.d.ts.map
|
package/dist/db/queries.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/db/queries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAmB,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/db/queries.ts"],"names":[],"mappings":"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"}
|