@cyanheads/mcp-ts-core 0.9.16 → 0.9.17

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 (36) hide show
  1. package/AGENTS.md +2 -1
  2. package/CLAUDE.md +2 -1
  3. package/README.md +1 -1
  4. package/changelog/0.9.x/0.9.17.md +23 -0
  5. package/dist/logs/combined.log +8 -4
  6. package/dist/logs/error.log +4 -2
  7. package/dist/services/mirror/core/defineMirror.d.ts +62 -0
  8. package/dist/services/mirror/core/defineMirror.d.ts.map +1 -0
  9. package/dist/services/mirror/core/defineMirror.js +99 -0
  10. package/dist/services/mirror/core/defineMirror.js.map +1 -0
  11. package/dist/services/mirror/core/runner.d.ts +29 -0
  12. package/dist/services/mirror/core/runner.d.ts.map +1 -0
  13. package/dist/services/mirror/core/runner.js +95 -0
  14. package/dist/services/mirror/core/runner.js.map +1 -0
  15. package/dist/services/mirror/index.d.ts +18 -0
  16. package/dist/services/mirror/index.d.ts.map +1 -0
  17. package/dist/services/mirror/index.js +17 -0
  18. package/dist/services/mirror/index.js.map +1 -0
  19. package/dist/services/mirror/sqlite/handle.d.ts +48 -0
  20. package/dist/services/mirror/sqlite/handle.d.ts.map +1 -0
  21. package/dist/services/mirror/sqlite/handle.js +105 -0
  22. package/dist/services/mirror/sqlite/handle.js.map +1 -0
  23. package/dist/services/mirror/sqlite/schema.d.ts +38 -0
  24. package/dist/services/mirror/sqlite/schema.d.ts.map +1 -0
  25. package/dist/services/mirror/sqlite/schema.js +124 -0
  26. package/dist/services/mirror/sqlite/schema.js.map +1 -0
  27. package/dist/services/mirror/sqlite/sqliteMirrorStore.d.ts +27 -0
  28. package/dist/services/mirror/sqlite/sqliteMirrorStore.d.ts.map +1 -0
  29. package/dist/services/mirror/sqlite/sqliteMirrorStore.js +286 -0
  30. package/dist/services/mirror/sqlite/sqliteMirrorStore.js.map +1 -0
  31. package/dist/services/mirror/types.d.ts +211 -0
  32. package/dist/services/mirror/types.d.ts.map +1 -0
  33. package/dist/services/mirror/types.js +9 -0
  34. package/dist/services/mirror/types.js.map +1 -0
  35. package/package.json +11 -2
  36. package/skills/api-mirror/SKILL.md +103 -0
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @fileoverview Runtime-agnostic SQLite handle for the mirror store. Uses the
3
+ * built-in `bun:sqlite` driver under Bun and the `better-sqlite3` optional peer
4
+ * dependency on Node — both exposed through one synchronous handle interface
5
+ * (the intersection of the two driver APIs).
6
+ *
7
+ * The drivers are loaded via variable-specifier dynamic imports so the
8
+ * framework typechecks and builds without `bun-types` in scope or
9
+ * `better-sqlite3` installed; both resolve at runtime on the matching runtime.
10
+ * @module services/mirror/sqlite/handle
11
+ */
12
+ import { mkdir } from 'node:fs/promises';
13
+ import { dirname, resolve as resolvePath } from 'node:path';
14
+ import { configurationError, databaseError, McpError } from '../../../types-global/errors.js';
15
+ import { runtimeCaps } from '../../../utils/internal/runtime.js';
16
+ /**
17
+ * Variable-specifier module IDs. Annotating as `string` (not the string
18
+ * literal) stops `tsc` from statically resolving the module, so the framework
19
+ * compiles without `bun-types` or `better-sqlite3` present. Each resolves at
20
+ * runtime only on the runtime that ships it.
21
+ */
22
+ const BUN_SQLITE_SPECIFIER = 'bun:sqlite';
23
+ const BETTER_SQLITE3_SPECIFIER = 'better-sqlite3';
24
+ /**
25
+ * Open (or create) a SQLite database at `path`, picking the driver for the
26
+ * current runtime. Creates the parent directory, enables WAL, and sets
27
+ * `busy_timeout` so a refresh writer and reader processes coexist without
28
+ * spurious `database is locked` errors.
29
+ *
30
+ * Throws `ConfigurationError` on Node when `better-sqlite3` is not installed,
31
+ * and `DatabaseError` for any other open failure.
32
+ */
33
+ export async function openSqliteHandle(path, options = {}) {
34
+ await mkdir(dirname(resolvePath(path)), { recursive: true });
35
+ const busyTimeoutMs = options.busyTimeoutMs ?? 5000;
36
+ let handle;
37
+ try {
38
+ handle = runtimeCaps.isBun
39
+ ? /* istanbul ignore next -- Bun branch; the test suite runs Vitest workers under Node */
40
+ await openBunHandle(path)
41
+ : await openBetterSqlite3Handle(path);
42
+ }
43
+ catch (err) {
44
+ // The Node path throws a ConfigurationError when better-sqlite3 is absent —
45
+ // preserve it rather than masking it as a generic open failure.
46
+ if (err instanceof McpError)
47
+ throw err;
48
+ throw databaseError(`Failed to open mirror store at ${path}`, { path }, { cause: err });
49
+ }
50
+ // Connection pragmas. WAL allows one writer + concurrent readers; NORMAL
51
+ // synchronous is the WAL-recommended durability/throughput balance.
52
+ handle.exec(`PRAGMA journal_mode = WAL; PRAGMA synchronous = NORMAL; PRAGMA foreign_keys = ON; PRAGMA busy_timeout = ${busyTimeoutMs};`);
53
+ return handle;
54
+ }
55
+ /* istanbul ignore next -- Bun-only driver; the test suite runs Vitest workers under Node */
56
+ async function openBunHandle(path) {
57
+ const mod = (await import(BUN_SQLITE_SPECIFIER));
58
+ const db = new mod.Database(path, { create: true });
59
+ return {
60
+ close: () => {
61
+ db.close();
62
+ },
63
+ exec: (sql) => {
64
+ db.exec(sql);
65
+ },
66
+ prepare: (sql) => {
67
+ const stmt = db.prepare(sql);
68
+ return {
69
+ all: (...params) => stmt.all(...params),
70
+ get: (...params) => stmt.get(...params),
71
+ run: (...params) => stmt.run(...params),
72
+ };
73
+ },
74
+ transaction: (fn) => db.transaction(fn)(),
75
+ };
76
+ }
77
+ async function openBetterSqlite3Handle(path) {
78
+ let mod;
79
+ try {
80
+ mod = (await import(BETTER_SQLITE3_SPECIFIER));
81
+ }
82
+ catch (err) {
83
+ /* istanbul ignore next -- missing-dep path; better-sqlite3 is installed in the test env */
84
+ throw configurationError('Install "better-sqlite3" to use the SQLite mirror store on Node: bun add better-sqlite3', { path }, { cause: err });
85
+ }
86
+ const db = new mod.default(path);
87
+ return {
88
+ close: () => {
89
+ db.close();
90
+ },
91
+ exec: (sql) => {
92
+ db.exec(sql);
93
+ },
94
+ prepare: (sql) => {
95
+ const stmt = db.prepare(sql);
96
+ return {
97
+ all: (...params) => stmt.all(...params),
98
+ get: (...params) => stmt.get(...params),
99
+ run: (...params) => stmt.run(...params),
100
+ };
101
+ },
102
+ transaction: (fn) => db.transaction(fn)(),
103
+ };
104
+ }
105
+ //# sourceMappingURL=handle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handle.js","sourceRoot":"","sources":["../../../../src/services/mirror/sqlite/handle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @fileoverview DDL generation for the SQLite mirror store. Builds the primary
3
+ * table, secondary indexes, an optional FTS5 external-content index with sync
4
+ * triggers, the single-row `mirror_sync_state` table, and the `schema_version`
5
+ * table — all from a declarative column/FTS spec.
6
+ * @module services/mirror/sqlite/schema
7
+ */
8
+ /** Default FTS5 tokenizer — Unicode-aware, diacritic-stripping, no stemming. */
9
+ export declare const DEFAULT_FTS_TOKENIZER = "unicode61 remove_diacritics 2";
10
+ /** Declarative schema spec consumed by {@link buildSchemaSql}. */
11
+ export interface SchemaSpec {
12
+ /** Column name → SQLite type/declaration (e.g. `'TEXT'`, `'INTEGER NOT NULL'`). */
13
+ columns: Record<string, string>;
14
+ /** Columns to index in FTS5 (subset of `columns`). Omit/empty to skip FTS. */
15
+ fts?: string[];
16
+ /** FTS5 tokenizer directive. Defaults to {@link DEFAULT_FTS_TOKENIZER}. */
17
+ ftsTokenizer?: string;
18
+ /** Secondary indexes over declared columns. */
19
+ indexes?: Array<{
20
+ name?: string;
21
+ columns: string[];
22
+ }>;
23
+ /** Primary-key column — receives `PRIMARY KEY NOT NULL` and drives upsert/tombstone. */
24
+ primaryKey: string;
25
+ /** Primary table name. */
26
+ table: string;
27
+ }
28
+ /** Validate a {@link SchemaSpec} and return its FTS column set (validated). */
29
+ export declare function validateSchemaSpec(spec: SchemaSpec): {
30
+ ftsColumns: string[];
31
+ tokenizer: string;
32
+ };
33
+ /**
34
+ * Build the full idempotent DDL for a mirror store. Safe to run on every open
35
+ * (`CREATE … IF NOT EXISTS` throughout). Returns one SQL string.
36
+ */
37
+ export declare function buildSchemaSql(spec: SchemaSpec): string;
38
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../src/services/mirror/sqlite/schema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,gFAAgF;AAChF,eAAO,MAAM,qBAAqB,kCAAkC,CAAC;AAErE,kEAAkE;AAClE,MAAM,WAAW,UAAU;IACzB,mFAAmF;IACnF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,8EAA8E;IAC9E,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACtD,wFAAwF;IACxF,UAAU,EAAE,MAAM,CAAC;IACnB,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;CACf;AAaD,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CA4ChG;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAuCvD"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * @fileoverview DDL generation for the SQLite mirror store. Builds the primary
3
+ * table, secondary indexes, an optional FTS5 external-content index with sync
4
+ * triggers, the single-row `mirror_sync_state` table, and the `schema_version`
5
+ * table — all from a declarative column/FTS spec.
6
+ * @module services/mirror/sqlite/schema
7
+ */
8
+ import { configurationError } from '../../../types-global/errors.js';
9
+ /** Default FTS5 tokenizer — Unicode-aware, diacritic-stripping, no stemming. */
10
+ export const DEFAULT_FTS_TOKENIZER = 'unicode61 remove_diacritics 2';
11
+ const IDENTIFIER_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
12
+ function assertIdentifier(value, role) {
13
+ if (!IDENTIFIER_RE.test(value)) {
14
+ throw configurationError(`Invalid mirror ${role} identifier "${value}" — must match ${IDENTIFIER_RE.source}.`, { value, role });
15
+ }
16
+ }
17
+ /** Validate a {@link SchemaSpec} and return its FTS column set (validated). */
18
+ export function validateSchemaSpec(spec) {
19
+ assertIdentifier(spec.table, 'table');
20
+ const columnNames = Object.keys(spec.columns);
21
+ if (columnNames.length === 0) {
22
+ throw configurationError('Mirror schema must declare at least one column.', {
23
+ table: spec.table,
24
+ });
25
+ }
26
+ for (const col of columnNames)
27
+ assertIdentifier(col, 'column');
28
+ if (!(spec.primaryKey in spec.columns)) {
29
+ throw configurationError(`Mirror primaryKey "${spec.primaryKey}" is not among the declared columns.`, { primaryKey: spec.primaryKey, columns: columnNames });
30
+ }
31
+ const ftsColumns = spec.fts ?? [];
32
+ for (const col of ftsColumns) {
33
+ if (!(col in spec.columns)) {
34
+ throw configurationError(`Mirror FTS column "${col}" is not a declared column.`, {
35
+ column: col,
36
+ columns: columnNames,
37
+ });
38
+ }
39
+ }
40
+ const tokenizer = spec.ftsTokenizer ?? DEFAULT_FTS_TOKENIZER;
41
+ if (tokenizer.includes('"')) {
42
+ throw configurationError('Mirror ftsTokenizer must not contain a double-quote character.', {
43
+ tokenizer,
44
+ });
45
+ }
46
+ for (const idx of spec.indexes ?? []) {
47
+ for (const col of idx.columns) {
48
+ if (!(col in spec.columns)) {
49
+ throw configurationError(`Mirror index column "${col}" is not a declared column.`, {
50
+ column: col,
51
+ });
52
+ }
53
+ }
54
+ }
55
+ return { ftsColumns, tokenizer };
56
+ }
57
+ /**
58
+ * Build the full idempotent DDL for a mirror store. Safe to run on every open
59
+ * (`CREATE … IF NOT EXISTS` throughout). Returns one SQL string.
60
+ */
61
+ export function buildSchemaSql(spec) {
62
+ const { ftsColumns, tokenizer } = validateSchemaSpec(spec);
63
+ const t = spec.table;
64
+ const columnDefs = Object.entries(spec.columns).map(([name, decl]) => {
65
+ const base = `${name} ${decl}`.trim();
66
+ return name === spec.primaryKey ? `${name} ${decl} PRIMARY KEY NOT NULL`.trim() : base;
67
+ });
68
+ const parts = [
69
+ `CREATE TABLE IF NOT EXISTS schema_version (version INTEGER PRIMARY KEY, applied_at TEXT NOT NULL);`,
70
+ `CREATE TABLE IF NOT EXISTS ${t} (\n ${columnDefs.join(',\n ')}\n);`,
71
+ ];
72
+ for (const idx of spec.indexes ?? []) {
73
+ const name = idx.name ?? `${t}_${idx.columns.join('_')}_idx`;
74
+ assertIdentifier(name, 'index');
75
+ parts.push(`CREATE INDEX IF NOT EXISTS ${name} ON ${t}(${idx.columns.join(', ')});`);
76
+ }
77
+ if (ftsColumns.length > 0) {
78
+ parts.push(buildFtsSql(t, ftsColumns, tokenizer));
79
+ }
80
+ parts.push(`CREATE TABLE IF NOT EXISTS mirror_sync_state (
81
+ id INTEGER PRIMARY KEY CHECK (id = 1),
82
+ status TEXT NOT NULL,
83
+ cursor TEXT,
84
+ checkpoint TEXT,
85
+ started_at TEXT,
86
+ completed_at TEXT,
87
+ total INTEGER,
88
+ error TEXT
89
+ );`, `INSERT OR IGNORE INTO mirror_sync_state(id, status) VALUES (1, 'pending');`);
90
+ return parts.join('\n\n');
91
+ }
92
+ /**
93
+ * Build the FTS5 external-content virtual table and its insert/delete/update
94
+ * sync triggers. External content (`content=<table>`) stores only the index, not
95
+ * a copy of the text; the triggers keep it in lock-step with the base table,
96
+ * using the `('delete', …)` command-row form required for external-content
97
+ * deletes.
98
+ */
99
+ function buildFtsSql(table, ftsColumns, tokenizer) {
100
+ const cols = ftsColumns.join(', ');
101
+ const newCols = ftsColumns.map((c) => `new.${c}`).join(', ');
102
+ const oldCols = ftsColumns.map((c) => `old.${c}`).join(', ');
103
+ const fts = `${table}_fts`;
104
+ return `CREATE VIRTUAL TABLE IF NOT EXISTS ${fts} USING fts5(
105
+ ${ftsColumns.join(',\n ')},
106
+ content='${table}',
107
+ content_rowid='rowid',
108
+ tokenize="${tokenizer}"
109
+ );
110
+
111
+ CREATE TRIGGER IF NOT EXISTS ${table}_ai AFTER INSERT ON ${table} BEGIN
112
+ INSERT INTO ${fts}(rowid, ${cols}) VALUES (new.rowid, ${newCols});
113
+ END;
114
+
115
+ CREATE TRIGGER IF NOT EXISTS ${table}_ad AFTER DELETE ON ${table} BEGIN
116
+ INSERT INTO ${fts}(${fts}, rowid, ${cols}) VALUES ('delete', old.rowid, ${oldCols});
117
+ END;
118
+
119
+ CREATE TRIGGER IF NOT EXISTS ${table}_au AFTER UPDATE ON ${table} BEGIN
120
+ INSERT INTO ${fts}(${fts}, rowid, ${cols}) VALUES ('delete', old.rowid, ${oldCols});
121
+ INSERT INTO ${fts}(rowid, ${cols}) VALUES (new.rowid, ${newCols});
122
+ END;`;
123
+ }
124
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/services/mirror/sqlite/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @fileoverview Embedded-SQLite implementation of {@link MirrorStore}. Owns the
3
+ * primary table, optional FTS5 index, the `mirror_sync_state` row, schema
4
+ * versioning + migration runner, generic flat queries, and the raw-handle
5
+ * escape hatch. Lazy-opens on first use (memoized) and is then backed by
6
+ * synchronous driver calls.
7
+ * @module services/mirror/sqlite/sqliteMirrorStore
8
+ */
9
+ import type { Migration, MirrorStore } from '../types.js';
10
+ import { type SchemaSpec } from './schema.js';
11
+ /** Configuration for {@link sqliteMirrorStore}. */
12
+ export interface SqliteMirrorStoreSpec extends SchemaSpec {
13
+ /** `PRAGMA busy_timeout` in ms. Default 5000. */
14
+ busyTimeoutMs?: number;
15
+ /** Migrations applied in order when the stored version is lower than `version`. */
16
+ migrations?: Migration[];
17
+ /** Filesystem path to the SQLite database (created if absent). */
18
+ path: string;
19
+ /** Current schema version. Default 1. */
20
+ version?: number;
21
+ }
22
+ /**
23
+ * Create a SQLite-backed {@link MirrorStore} from a declarative spec. The store
24
+ * is not opened until the first method call.
25
+ */
26
+ export declare function sqliteMirrorStore(spec: SqliteMirrorStoreSpec): MirrorStore;
27
+ //# sourceMappingURL=sqliteMirrorStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqliteMirrorStore.d.ts","sourceRoot":"","sources":["../../../../src/services/mirror/sqlite/sqliteMirrorStore.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAEV,SAAS,EAET,WAAW,EAMZ,MAAM,aAAa,CAAC;AAErB,OAAO,EAAkB,KAAK,UAAU,EAAsB,MAAM,aAAa,CAAC;AAElF,mDAAmD;AACnD,MAAM,WAAW,qBAAsB,SAAQ,UAAU;IACvD,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mFAAmF;IACnF,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAkBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,GAAG,WAAW,CA0L1E"}
@@ -0,0 +1,286 @@
1
+ /**
2
+ * @fileoverview Embedded-SQLite implementation of {@link MirrorStore}. Owns the
3
+ * primary table, optional FTS5 index, the `mirror_sync_state` row, schema
4
+ * versioning + migration runner, generic flat queries, and the raw-handle
5
+ * escape hatch. Lazy-opens on first use (memoized) and is then backed by
6
+ * synchronous driver calls.
7
+ * @module services/mirror/sqlite/sqliteMirrorStore
8
+ */
9
+ import { databaseError, validationError } from '../../../types-global/errors.js';
10
+ import { openSqliteHandle } from './handle.js';
11
+ import { buildSchemaSql, validateSchemaSpec } from './schema.js';
12
+ const SQL_OP = {
13
+ eq: '=',
14
+ ne: '!=',
15
+ gt: '>',
16
+ gte: '>=',
17
+ lt: '<',
18
+ lte: '<=',
19
+ };
20
+ /**
21
+ * Create a SQLite-backed {@link MirrorStore} from a declarative spec. The store
22
+ * is not opened until the first method call.
23
+ */
24
+ export function sqliteMirrorStore(spec) {
25
+ // Fail fast on a malformed spec at construction time, not first query.
26
+ const { ftsColumns } = validateSchemaSpec(spec);
27
+ const allColumns = Object.keys(spec.columns);
28
+ const ftsTable = `${spec.table}_fts`;
29
+ let opened;
30
+ let opening;
31
+ function open() {
32
+ if (opened)
33
+ return Promise.resolve(opened);
34
+ opening ??= (async () => {
35
+ const handleOptions = {
36
+ ...(spec.busyTimeoutMs !== undefined && { busyTimeoutMs: spec.busyTimeoutMs }),
37
+ };
38
+ const handle = await openSqliteHandle(spec.path, handleOptions);
39
+ try {
40
+ handle.exec(buildSchemaSql(spec));
41
+ runMigrations(handle, spec.version ?? 1, spec.migrations ?? []);
42
+ }
43
+ catch (err) {
44
+ handle.close();
45
+ throw databaseError(`Failed to initialize mirror store at ${spec.path}`, { path: spec.path }, { cause: err });
46
+ }
47
+ opened = { handle, allColumns, hasFts: ftsColumns.length > 0 };
48
+ return opened;
49
+ })();
50
+ return opening;
51
+ }
52
+ function assertColumn(column, role) {
53
+ if (!allColumns.includes(column)) {
54
+ throw validationError(`Unknown mirror ${role} column "${column}".`, {
55
+ column,
56
+ columns: allColumns,
57
+ });
58
+ }
59
+ }
60
+ return {
61
+ async applyBatch(records, tombstones) {
62
+ if (records.length === 0 && tombstones.length === 0)
63
+ return;
64
+ const { handle } = await open();
65
+ const cols = allColumns;
66
+ const placeholders = cols.map(() => '?').join(', ');
67
+ const updates = cols
68
+ .filter((c) => c !== spec.primaryKey)
69
+ .map((c) => `${c} = excluded.${c}`)
70
+ .join(', ');
71
+ // No non-PK columns → a bare PK table; ON CONFLICT DO NOTHING keeps upsert idempotent.
72
+ const conflict = updates
73
+ ? `ON CONFLICT(${spec.primaryKey}) DO UPDATE SET ${updates}`
74
+ : `ON CONFLICT(${spec.primaryKey}) DO NOTHING`;
75
+ const upsert = handle.prepare(`INSERT INTO ${spec.table}(${cols.join(', ')}) VALUES (${placeholders}) ${conflict}`);
76
+ const remove = handle.prepare(`DELETE FROM ${spec.table} WHERE ${spec.primaryKey} = ?`);
77
+ handle.transaction(() => {
78
+ for (const record of records) {
79
+ upsert.run(...cols.map((c) => record[c] ?? null));
80
+ }
81
+ for (const id of tombstones)
82
+ remove.run(id);
83
+ });
84
+ },
85
+ async query(options) {
86
+ const store = await open();
87
+ if (options.match && !store.hasFts) {
88
+ throw validationError('This mirror has no FTS index; `match` is not supported.', {
89
+ table: spec.table,
90
+ });
91
+ }
92
+ for (const f of options.filters ?? [])
93
+ assertColumn(f.column, 'filter');
94
+ if (options.sort && options.sort !== 'relevance')
95
+ assertColumn(options.sort.column, 'sort');
96
+ const { handle } = store;
97
+ const { clauses: filterClauses, params: filterParams } = buildFilterClauses(options.filters ?? []);
98
+ const relevance = options.sort === 'relevance' && Boolean(options.match);
99
+ // COUNT never needs bm25, so the FTS predicate is always the rowid
100
+ // subquery form — no join, no ordering.
101
+ const countClauses = [...filterClauses];
102
+ const countParams = [...filterParams];
103
+ if (options.match) {
104
+ countClauses.unshift(`${spec.table}.rowid IN (SELECT rowid FROM ${ftsTable} WHERE ${ftsTable} MATCH ?)`);
105
+ countParams.unshift(options.match);
106
+ }
107
+ const countWhere = countClauses.length > 0 ? `WHERE ${countClauses.join(' AND ')}` : '';
108
+ const total = handle
109
+ .prepare(`SELECT COUNT(*) AS n FROM ${spec.table} ${countWhere}`)
110
+ .get(...countParams)?.n ?? 0;
111
+ // Row fetch. For relevance sort, apply MATCH on the JOINed FTS table so
112
+ // `bm25()` is scored in that MATCH's context; the subquery form leaves
113
+ // bm25 with no query to score against. Other sorts keep the subquery form
114
+ // (no join needed). `ORDER BY` columns are table-qualified to avoid a
115
+ // `rowid` ambiguity once the FTS table is joined in.
116
+ const rowClauses = [...filterClauses];
117
+ const rowParams = [...filterParams];
118
+ let join = '';
119
+ if (options.match) {
120
+ if (relevance) {
121
+ join = `JOIN ${ftsTable} ON ${spec.table}.rowid = ${ftsTable}.rowid`;
122
+ rowClauses.unshift(`${ftsTable} MATCH ?`);
123
+ }
124
+ else {
125
+ rowClauses.unshift(`${spec.table}.rowid IN (SELECT rowid FROM ${ftsTable} WHERE ${ftsTable} MATCH ?)`);
126
+ }
127
+ rowParams.unshift(options.match);
128
+ }
129
+ const rowWhere = rowClauses.length > 0 ? `WHERE ${rowClauses.join(' AND ')}` : '';
130
+ const selectCols = store.allColumns.map((c) => `${spec.table}.${c}`).join(', ');
131
+ const orderBy = relevance
132
+ ? `ORDER BY bm25(${ftsTable}) ASC`
133
+ : buildOrderBy(options.sort, spec.table);
134
+ const rows = handle
135
+ .prepare(`SELECT ${selectCols} FROM ${spec.table} ${join} ${rowWhere} ${orderBy} LIMIT ? OFFSET ?`)
136
+ .all(...rowParams, options.limit, options.offset);
137
+ return { rows, total };
138
+ },
139
+ async getByIds(ids) {
140
+ if (ids.length === 0)
141
+ return [];
142
+ const { handle } = await open();
143
+ const placeholders = ids.map(() => '?').join(', ');
144
+ const rows = handle
145
+ .prepare(`SELECT ${allColumns.join(', ')} FROM ${spec.table} WHERE ${spec.primaryKey} IN (${placeholders})`)
146
+ .all(...ids);
147
+ const byId = new Map(rows.map((r) => [r[spec.primaryKey], r]));
148
+ return ids.map((id) => byId.get(id)).filter((r) => r !== undefined);
149
+ },
150
+ async count() {
151
+ const { handle } = await open();
152
+ const row = handle.prepare(`SELECT COUNT(*) AS n FROM ${spec.table}`).get();
153
+ return row?.n ?? 0;
154
+ },
155
+ async readState() {
156
+ const { handle } = await open();
157
+ return readSyncState(handle);
158
+ },
159
+ async writeState(state) {
160
+ const { handle } = await open();
161
+ writeSyncState(handle, state);
162
+ },
163
+ async raw() {
164
+ return (await open()).handle;
165
+ },
166
+ async integrityCheck() {
167
+ const { handle } = await open();
168
+ const integrity = handle.prepare(`PRAGMA integrity_check`).all();
169
+ const quick = handle.prepare(`PRAGMA quick_check`).all();
170
+ const results = [
171
+ ...integrity.map((r) => `integrity_check: ${r.integrity_check}`),
172
+ ...quick.map((r) => `quick_check: ${r.quick_check}`),
173
+ ];
174
+ return { ok: results.every((r) => r.endsWith('ok')), results };
175
+ },
176
+ close() {
177
+ if (opened) {
178
+ opened.handle.close();
179
+ opened = undefined;
180
+ opening = undefined;
181
+ }
182
+ return Promise.resolve();
183
+ },
184
+ };
185
+ }
186
+ // ---------------------------------------------------------------------------
187
+ // Query building
188
+ // ---------------------------------------------------------------------------
189
+ function buildFilterClauses(filters) {
190
+ const clauses = [];
191
+ const params = [];
192
+ for (const f of filters) {
193
+ if (f.op === 'in') {
194
+ const values = Array.isArray(f.value) ? f.value : [f.value];
195
+ if (values.length === 0) {
196
+ clauses.push('0'); // empty IN matches nothing
197
+ continue;
198
+ }
199
+ clauses.push(`${f.column} IN (${values.map(() => '?').join(', ')})`);
200
+ params.push(...values);
201
+ continue;
202
+ }
203
+ clauses.push(`${f.column} ${SQL_OP[f.op]} ?`);
204
+ params.push(Array.isArray(f.value) ? (f.value[0] ?? null) : f.value);
205
+ }
206
+ return { clauses, params };
207
+ }
208
+ function buildOrderBy(sort, table) {
209
+ if (sort && sort !== 'relevance') {
210
+ return `ORDER BY ${table}.${sort.column} ${sort.direction === 'asc' ? 'ASC' : 'DESC'}`;
211
+ }
212
+ return `ORDER BY ${table}.rowid ASC`;
213
+ }
214
+ function readSyncState(handle) {
215
+ const row = handle
216
+ .prepare(`SELECT status, cursor, checkpoint, started_at, completed_at, total, error
217
+ FROM mirror_sync_state WHERE id = 1`)
218
+ .get();
219
+ if (!row)
220
+ return { status: 'pending' };
221
+ return {
222
+ status: row.status,
223
+ ...(row.cursor != null && { cursor: row.cursor }),
224
+ ...(row.checkpoint != null && { checkpoint: row.checkpoint }),
225
+ ...(row.started_at != null && { startedAt: row.started_at }),
226
+ ...(row.completed_at != null && { completedAt: row.completed_at }),
227
+ ...(row.total != null && { total: row.total }),
228
+ ...(row.error != null && { error: row.error }),
229
+ };
230
+ }
231
+ /**
232
+ * Persist sync state. `completed_at` and `total` are durable "last successful
233
+ * sync" markers — preserved via COALESCE when a write omits them — so an
234
+ * in-progress or failed refresh on top of a complete mirror keeps the
235
+ * completion marker that readiness keys off. Every other column is
236
+ * current-run progress, overwritten on each write.
237
+ */
238
+ function writeSyncState(handle, state) {
239
+ handle
240
+ .prepare(`UPDATE mirror_sync_state
241
+ SET status = ?, cursor = ?, checkpoint = ?, started_at = ?,
242
+ completed_at = COALESCE(?, completed_at),
243
+ total = COALESCE(?, total),
244
+ error = ?
245
+ WHERE id = 1`)
246
+ .run(state.status, state.cursor ?? null, state.checkpoint ?? null, state.startedAt ?? null, state.completedAt ?? null, state.total ?? null, state.error ?? null);
247
+ }
248
+ // ---------------------------------------------------------------------------
249
+ // Schema versioning
250
+ // ---------------------------------------------------------------------------
251
+ /**
252
+ * Apply pending migrations. A brand-new database (no `schema_version` row) was
253
+ * just built at the current schema by the DDL, so it is stamped to `target`
254
+ * without running migrations (there is no older data to transform). An existing
255
+ * database at a lower version runs each migration with `stored < version <=
256
+ * target`, in order, stamping the version after each.
257
+ */
258
+ function runMigrations(handle, target, migrations) {
259
+ const stored = handle.prepare(`SELECT MAX(version) AS version FROM schema_version`).get()
260
+ ?.version ?? 0;
261
+ if (stored === 0) {
262
+ stampVersion(handle, target);
263
+ return;
264
+ }
265
+ if (stored >= target)
266
+ return;
267
+ const pending = migrations
268
+ .filter((m) => m.version > stored && m.version <= target)
269
+ .sort((a, b) => a.version - b.version);
270
+ for (const m of pending) {
271
+ handle.transaction(() => {
272
+ m.up(handle);
273
+ });
274
+ stampVersion(handle, m.version);
275
+ }
276
+ stampVersion(handle, target);
277
+ }
278
+ function stampVersion(handle, version) {
279
+ handle.transaction(() => {
280
+ handle.prepare(`DELETE FROM schema_version`).run();
281
+ handle
282
+ .prepare(`INSERT INTO schema_version(version, applied_at) VALUES (?, ?)`)
283
+ .run(version, new Date().toISOString());
284
+ });
285
+ }
286
+ //# sourceMappingURL=sqliteMirrorStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqliteMirrorStore.js","sourceRoot":"","sources":["../../../../src/services/mirror/sqlite/sqliteMirrorStore.ts"],"names":[],"mappings":"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"}