@haverstack/adapter-sqlite 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
2
+
3
+ To the extent possible under law, the Haverstack contributors have waived all
4
+ copyright and related or neighboring rights to Haverstack. This work is
5
+ published from the United States.
6
+
7
+ https://creativecommons.org/publicdomain/zero/1.0/
package/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # @haverstack/adapter-sqlite
2
+
3
+ SQLite storage adapter for [Haverstack](https://www.npmjs.com/package/@haverstack/core).
4
+
5
+ Implements the `StackAdapter` interface using [sql.js](https://github.com/sql-js/sql.js). Runs in Node.js without native compilation. The database is held in memory and flushed to disk after every write.
6
+
7
+ > **Status:** Early development. APIs are unstable.
8
+
9
+ ## Installation
10
+
11
+ ```sh
12
+ npm install @haverstack/adapter-sqlite @haverstack/core
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```ts
18
+ import { Stack } from '@haverstack/core';
19
+ import { SQLiteAdapter } from '@haverstack/adapter-sqlite';
20
+
21
+ // First run — create a new database
22
+ const adapter = await SQLiteAdapter.initialize({
23
+ path: './my-stack.db',
24
+ entityId: 'my-entity-id',
25
+ timezone: 'America/New_York',
26
+ });
27
+
28
+ // Subsequent runs — open the existing database
29
+ // const adapter = await SQLiteAdapter.open({ path: './my-stack.db' });
30
+
31
+ const stack = await Stack.create(adapter);
32
+
33
+ // ... use the stack (see @haverstack/core for the full API)
34
+
35
+ await stack.flush();
36
+ await stack.close();
37
+ ```
38
+
39
+ ## API
40
+
41
+ ### `SQLiteAdapter.initialize(opts)`
42
+
43
+ Creates a new database at `opts.path`. Throws if the file already exists.
44
+
45
+ | Option | Type | Description |
46
+ | ---------- | -------- | -------------------------------------- |
47
+ | `path` | `string` | Absolute path to the `.db` file |
48
+ | `entityId` | `string` | Entity ID of the stack owner |
49
+ | `timezone` | `string` | IANA timezone string (e.g. `America/New_York`) |
50
+
51
+ ### `SQLiteAdapter.open(opts)`
52
+
53
+ Opens an existing database at `opts.path`. Throws if the file does not exist.
54
+
55
+ | Option | Type | Description |
56
+ | ------ | -------- | --------------------------------------- |
57
+ | `path` | `string` | Absolute path to an existing `.db` file |
58
+
59
+ ## Storage layout
60
+
61
+ Given a database at `./my-stack.db`, attachments are stored in `./attachments/`.
62
+
63
+ ## Capabilities
64
+
65
+ | Feature | Supported |
66
+ | ------------------ | --------- |
67
+ | Full-text search | Yes (FTS4) |
68
+ | Content field query | Yes |
69
+ | Sortable fields | `createdAt`, `updatedAt`, `version` |
70
+
71
+ ## License
72
+
73
+ [CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/) — public domain.
74
+
75
+ ## Monorepo
76
+
77
+ Part of [haverstack/core](https://github.com/haverstack/core).
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Stack — SQLite Adapter
3
+ * -------------------------------------------------------
4
+ * Implements StackAdapter using sql.js (SQLite compiled to
5
+ * WebAssembly). Runs in Node, browsers, and other runtimes
6
+ * without native compilation.
7
+ *
8
+ * The database is held in memory and flushed to disk on every
9
+ * write. Attachments are stored as files in an `attachments/`
10
+ * subdirectory next to the database file.
11
+ *
12
+ * Stack config (timezone, entity_id, etc.) is stored in a
13
+ * `stack_config` key/value table.
14
+ */
15
+ import type { StackAdapter, StackRecord, StackType, TypeId, RecordVersion, StackQuery, QueryResult, Association, AdapterCapabilities } from '@haverstack/core';
16
+ export type SQLiteInitializeOptions = {
17
+ /** Absolute path to the .db file. Must not already exist. */
18
+ path: string;
19
+ /** IANA timezone string e.g. "America/New_York". */
20
+ timezone: string;
21
+ /** Entity ID of the stack owner. */
22
+ entityId: string;
23
+ };
24
+ export type SQLiteOpenOptions = {
25
+ /** Absolute path to an existing .db file. */
26
+ path: string;
27
+ };
28
+ export declare class SQLiteAdapter implements StackAdapter {
29
+ private readonly SQL;
30
+ private readonly path;
31
+ readonly capabilities: AdapterCapabilities;
32
+ private db;
33
+ private readonly attachmentsDir;
34
+ private constructor();
35
+ /**
36
+ * Initialize a new stack database. Fails if the file already exists —
37
+ * use open() for existing databases.
38
+ */
39
+ static initialize(opts: SQLiteInitializeOptions): Promise<SQLiteAdapter>;
40
+ /**
41
+ * Open an existing stack database. Fails if the file does not exist —
42
+ * use initialize() for new databases.
43
+ */
44
+ static open(opts: SQLiteOpenOptions): Promise<SQLiteAdapter>;
45
+ getConfig(key: string): Promise<string | null>;
46
+ setConfig(key: string, value: string): Promise<void>;
47
+ /** Flush the in-memory database to disk. Called after every write. */
48
+ private persist;
49
+ createRecord(record: StackRecord): Promise<StackRecord>;
50
+ getRecord(id: string): Promise<StackRecord | null>;
51
+ updateRecord(id: string, changes: Partial<StackRecord>): Promise<StackRecord>;
52
+ deleteRecord(id: string, opts?: {
53
+ hard?: boolean;
54
+ }): Promise<void>;
55
+ queryRecords(query: StackQuery): Promise<QueryResult>;
56
+ getVersions(id: string): Promise<RecordVersion[]>;
57
+ getVersion(id: string, version: number): Promise<RecordVersion | null>;
58
+ saveVersion(id: string, version: RecordVersion): Promise<void>;
59
+ saveType(type: StackType): Promise<void>;
60
+ getType(id: TypeId): Promise<StackType | null>;
61
+ listTypes(): Promise<StackType[]>;
62
+ putAttachment(data: Uint8Array, mimeType: string): Promise<string>;
63
+ getAttachment(fileId: string): Promise<Uint8Array>;
64
+ deleteAttachment(fileId: string): Promise<void>;
65
+ associate(recordId: string, association: Association): Promise<void>;
66
+ dissociate(recordId: string, association: Association): Promise<void>;
67
+ private insertAssociations;
68
+ private getAssociationsForRecord;
69
+ private updateFts;
70
+ private execQuery;
71
+ }
72
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,601 @@
1
+ /**
2
+ * Stack — SQLite Adapter
3
+ * -------------------------------------------------------
4
+ * Implements StackAdapter using sql.js (SQLite compiled to
5
+ * WebAssembly). Runs in Node, browsers, and other runtimes
6
+ * without native compilation.
7
+ *
8
+ * The database is held in memory and flushed to disk on every
9
+ * write. Attachments are stored as files in an `attachments/`
10
+ * subdirectory next to the database file.
11
+ *
12
+ * Stack config (timezone, entity_id, etc.) is stored in a
13
+ * `stack_config` key/value table.
14
+ */
15
+ import initSqlJs from 'sql.js';
16
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
17
+ import { readFile, writeFile } from 'fs/promises';
18
+ import { join, dirname } from 'path';
19
+ import { generateId } from '@haverstack/core';
20
+ // -------------------------------------------------------
21
+ // SQL — schema
22
+ // -------------------------------------------------------
23
+ const SCHEMA_SQL = `
24
+ CREATE TABLE IF NOT EXISTS stack_config (
25
+ key TEXT PRIMARY KEY,
26
+ value TEXT NOT NULL
27
+ ) STRICT;
28
+
29
+ CREATE TABLE IF NOT EXISTS records (
30
+ id TEXT PRIMARY KEY,
31
+ type_id TEXT NOT NULL,
32
+ created_at INTEGER NOT NULL,
33
+ updated_at INTEGER NOT NULL,
34
+ content TEXT NOT NULL CHECK (json_valid(content)),
35
+ version INTEGER NOT NULL DEFAULT 1,
36
+ parent_id TEXT,
37
+ entity_id TEXT,
38
+ app_id TEXT,
39
+ deleted_at INTEGER,
40
+ permissions TEXT CHECK (permissions IS NULL OR json_valid(permissions))
41
+ ) STRICT;
42
+
43
+ CREATE TABLE IF NOT EXISTS associations (
44
+ record_id TEXT NOT NULL REFERENCES records(id),
45
+ kind TEXT NOT NULL CHECK (kind IN ('tag', 'attachment', 'relationship')),
46
+ label TEXT NOT NULL,
47
+ file_id TEXT NOT NULL DEFAULT '',
48
+ mime_type TEXT,
49
+ related_id TEXT NOT NULL DEFAULT '',
50
+ PRIMARY KEY (record_id, kind, label, file_id, related_id)
51
+ ) STRICT;
52
+
53
+ CREATE TABLE IF NOT EXISTS versions (
54
+ record_id TEXT NOT NULL REFERENCES records(id),
55
+ version INTEGER NOT NULL,
56
+ content TEXT NOT NULL CHECK (json_valid(content)),
57
+ updated_at INTEGER NOT NULL,
58
+ entity_id TEXT,
59
+ PRIMARY KEY (record_id, version)
60
+ ) STRICT;
61
+
62
+ CREATE TABLE IF NOT EXISTS types (
63
+ id TEXT PRIMARY KEY,
64
+ base_id TEXT NOT NULL,
65
+ version INTEGER NOT NULL,
66
+ name TEXT NOT NULL,
67
+ schema TEXT NOT NULL CHECK (json_valid(schema)),
68
+ schema_hash TEXT NOT NULL,
69
+ migrates_from TEXT,
70
+ created_at INTEGER NOT NULL
71
+ ) STRICT;
72
+
73
+ CREATE TABLE IF NOT EXISTS attachments (
74
+ file_id TEXT PRIMARY KEY,
75
+ mime_type TEXT NOT NULL,
76
+ created_at INTEGER NOT NULL,
77
+ path TEXT NOT NULL
78
+ ) STRICT;
79
+
80
+ -- Indexes
81
+ CREATE INDEX IF NOT EXISTS idx_records_type_id ON records(type_id);
82
+ CREATE INDEX IF NOT EXISTS idx_records_parent_id ON records(parent_id);
83
+ CREATE INDEX IF NOT EXISTS idx_records_entity_id ON records(entity_id);
84
+ CREATE INDEX IF NOT EXISTS idx_records_app_id ON records(app_id);
85
+ CREATE INDEX IF NOT EXISTS idx_records_deleted_at ON records(deleted_at);
86
+ CREATE INDEX IF NOT EXISTS idx_records_created_at ON records(created_at);
87
+ CREATE INDEX IF NOT EXISTS idx_records_updated_at ON records(updated_at);
88
+ CREATE INDEX IF NOT EXISTS idx_assoc_record_id ON associations(record_id);
89
+ CREATE INDEX IF NOT EXISTS idx_assoc_kind_label ON associations(kind, label);
90
+ CREATE INDEX IF NOT EXISTS idx_types_base_id ON types(base_id);
91
+
92
+ -- Full-text search (FTS4 — compatible with sql.js)
93
+ CREATE VIRTUAL TABLE IF NOT EXISTS records_fts USING fts4(
94
+ content,
95
+ content='records'
96
+ );
97
+ `;
98
+ // -------------------------------------------------------
99
+ // Row <-> domain object mapping
100
+ // -------------------------------------------------------
101
+ const toMs = (d) => d.getTime();
102
+ const fromMs = (ms) => new Date(ms);
103
+ const rowToRecord = (row, associations) => {
104
+ const record = {
105
+ id: row.id,
106
+ typeId: row.type_id,
107
+ createdAt: fromMs(row.created_at),
108
+ updatedAt: fromMs(row.updated_at),
109
+ content: JSON.parse(row.content),
110
+ version: row.version,
111
+ };
112
+ if (row.parent_id)
113
+ record.parentId = row.parent_id;
114
+ if (row.entity_id)
115
+ record.entityId = row.entity_id;
116
+ if (row.app_id)
117
+ record.appId = row.app_id;
118
+ if (row.deleted_at)
119
+ record.deletedAt = fromMs(row.deleted_at);
120
+ if (row.permissions)
121
+ record.permissions = JSON.parse(row.permissions);
122
+ if (associations.length)
123
+ record.associations = associations;
124
+ return record;
125
+ };
126
+ const rowToAssociation = (row) => {
127
+ if (row.kind === 'tag') {
128
+ return { kind: 'tag', label: row.label };
129
+ }
130
+ if (row.kind === 'attachment') {
131
+ return {
132
+ kind: 'attachment',
133
+ label: row.label,
134
+ fileId: row.file_id,
135
+ mimeType: row.mime_type,
136
+ };
137
+ }
138
+ // relationship
139
+ return {
140
+ kind: 'relationship',
141
+ label: row.label,
142
+ recordId: row.related_id,
143
+ };
144
+ };
145
+ const rowToType = (row) => {
146
+ const t = {
147
+ id: row.id,
148
+ baseId: row.base_id,
149
+ version: row.version,
150
+ name: row.name,
151
+ schema: JSON.parse(row.schema),
152
+ schemaHash: row.schema_hash,
153
+ createdAt: fromMs(row.created_at),
154
+ };
155
+ if (row.migrates_from)
156
+ t.migratesFrom = row.migrates_from;
157
+ return t;
158
+ };
159
+ const rowToVersion = (row) => {
160
+ const v = {
161
+ version: row.version,
162
+ content: JSON.parse(row.content),
163
+ updatedAt: fromMs(row.updated_at),
164
+ };
165
+ if (row.entity_id)
166
+ v.entityId = row.entity_id;
167
+ return v;
168
+ };
169
+ // -------------------------------------------------------
170
+ // Query building
171
+ // -------------------------------------------------------
172
+ const buildWhereClause = (query) => {
173
+ const conditions = [];
174
+ const params = [];
175
+ const f = query.filter ?? {};
176
+ if (!f.includeDeleted) {
177
+ conditions.push('r.deleted_at IS NULL');
178
+ }
179
+ if (f.typeId !== undefined) {
180
+ const ids = Array.isArray(f.typeId) ? f.typeId : [f.typeId];
181
+ conditions.push(`r.type_id IN (${ids.map(() => '?').join(',')})`);
182
+ params.push(...ids);
183
+ }
184
+ if (f.parentId !== undefined) {
185
+ if (f.parentId === null) {
186
+ conditions.push('r.parent_id IS NULL');
187
+ }
188
+ else {
189
+ conditions.push('r.parent_id = ?');
190
+ params.push(f.parentId);
191
+ }
192
+ }
193
+ if (f.appId !== undefined) {
194
+ const ids = Array.isArray(f.appId) ? f.appId : [f.appId];
195
+ conditions.push(`r.app_id IN (${ids.map(() => '?').join(',')})`);
196
+ params.push(...ids);
197
+ }
198
+ if (f.entityId !== undefined) {
199
+ const ids = Array.isArray(f.entityId) ? f.entityId : [f.entityId];
200
+ conditions.push(`r.entity_id IN (${ids.map(() => '?').join(',')})`);
201
+ params.push(...ids);
202
+ }
203
+ if (f.createdAt?.after) {
204
+ conditions.push('r.created_at > ?');
205
+ params.push(toMs(f.createdAt.after));
206
+ }
207
+ if (f.createdAt?.before) {
208
+ conditions.push('r.created_at < ?');
209
+ params.push(toMs(f.createdAt.before));
210
+ }
211
+ if (f.updatedAt?.after) {
212
+ conditions.push('r.updated_at > ?');
213
+ params.push(toMs(f.updatedAt.after));
214
+ }
215
+ if (f.updatedAt?.before) {
216
+ conditions.push('r.updated_at < ?');
217
+ params.push(toMs(f.updatedAt.before));
218
+ }
219
+ // Tag filter — record must have ALL specified tags
220
+ if (f.tags?.length) {
221
+ for (const tag of f.tags) {
222
+ conditions.push(`EXISTS (SELECT 1 FROM associations a WHERE a.record_id = r.id AND a.kind = 'tag' AND a.label = ?)`);
223
+ params.push(tag);
224
+ }
225
+ }
226
+ // Attachment label filter
227
+ if (f.hasAttachment) {
228
+ conditions.push(`EXISTS (SELECT 1 FROM associations a WHERE a.record_id = r.id AND a.kind = 'attachment' AND a.label = ?)`);
229
+ params.push(f.hasAttachment);
230
+ }
231
+ // Relationship filter
232
+ if (f.relatedTo) {
233
+ conditions.push(`EXISTS (SELECT 1 FROM associations a WHERE a.record_id = r.id AND a.kind = 'relationship' AND a.related_id = ?` +
234
+ (f.relatedTo.label ? ` AND a.label = ?` : '') +
235
+ `)`);
236
+ params.push(f.relatedTo.recordId);
237
+ if (f.relatedTo.label)
238
+ params.push(f.relatedTo.label);
239
+ }
240
+ // Content field filters (top-level scalar exact match)
241
+ if (f.content) {
242
+ for (const [key, value] of Object.entries(f.content)) {
243
+ conditions.push(`json_extract(r.content, ?) = ?`);
244
+ params.push(`$.${key}`, value);
245
+ }
246
+ }
247
+ // Full-text search
248
+ if (f.search) {
249
+ conditions.push(`r.rowid IN (SELECT rowid FROM records_fts WHERE records_fts MATCH ?)`);
250
+ params.push(f.search);
251
+ }
252
+ // Cursor (created_at + id for stable pagination)
253
+ if (query.cursor) {
254
+ const [cursorTs, cursorId] = Buffer.from(query.cursor, 'base64').toString().split('|');
255
+ const sortDir = query.sort?.direction ?? 'desc';
256
+ const op = sortDir === 'asc' ? '>' : '<';
257
+ conditions.push(`(r.created_at ${op} ? OR (r.created_at = ? AND r.id ${op} ?))`);
258
+ params.push(Number(cursorTs), Number(cursorTs), cursorId);
259
+ }
260
+ return {
261
+ sql: conditions.length ? `WHERE ${conditions.join(' AND ')}` : '',
262
+ params,
263
+ };
264
+ };
265
+ const buildOrderClause = (query) => {
266
+ const field = query.sort?.field ?? 'created_at';
267
+ const dir = (query.sort?.direction ?? 'desc').toUpperCase();
268
+ const col = field === 'createdAt' ? 'created_at' : field === 'updatedAt' ? 'updated_at' : field;
269
+ return `ORDER BY r.${col} ${dir}, r.id ${dir}`;
270
+ };
271
+ const makeCursor = (record) => Buffer.from(`${toMs(record.createdAt)}|${record.id}`).toString('base64');
272
+ // -------------------------------------------------------
273
+ // SQLite adapter
274
+ // -------------------------------------------------------
275
+ export class SQLiteAdapter {
276
+ SQL;
277
+ path;
278
+ capabilities = {
279
+ fullTextSearch: true,
280
+ contentFieldQuery: true,
281
+ sortableFields: ['createdAt', 'updatedAt', 'version'],
282
+ };
283
+ db;
284
+ attachmentsDir;
285
+ constructor(SQL, path) {
286
+ this.SQL = SQL;
287
+ this.path = path;
288
+ this.attachmentsDir = join(dirname(path), 'attachments');
289
+ }
290
+ /**
291
+ * Initialize a new stack database. Fails if the file already exists —
292
+ * use open() for existing databases.
293
+ */
294
+ static async initialize(opts) {
295
+ if (existsSync(opts.path)) {
296
+ throw new Error(`Cannot initialize: database already exists at "${opts.path}". ` +
297
+ `Use SQLiteAdapter.open() instead.`);
298
+ }
299
+ const SQL = await initSqlJs();
300
+ const adapter = new SQLiteAdapter(SQL, opts.path);
301
+ adapter.db = new SQL.Database();
302
+ adapter.db.run(SCHEMA_SQL);
303
+ mkdirSync(adapter.attachmentsDir, { recursive: true });
304
+ adapter.db.run(`INSERT INTO stack_config (key, value) VALUES
305
+ ('entity_id', ?), ('timezone', ?), ('version', '1')`, [opts.entityId, opts.timezone]);
306
+ adapter.persist();
307
+ return adapter;
308
+ }
309
+ /**
310
+ * Open an existing stack database. Fails if the file does not exist —
311
+ * use initialize() for new databases.
312
+ */
313
+ static async open(opts) {
314
+ if (!existsSync(opts.path)) {
315
+ throw new Error(`Cannot open: no database found at "${opts.path}". ` +
316
+ `Use SQLiteAdapter.initialize() to create one.`);
317
+ }
318
+ const SQL = await initSqlJs();
319
+ const adapter = new SQLiteAdapter(SQL, opts.path);
320
+ const fileBuffer = readFileSync(opts.path);
321
+ adapter.db = new SQL.Database(fileBuffer);
322
+ adapter.db.run(SCHEMA_SQL); // safe — all statements use CREATE IF NOT EXISTS
323
+ mkdirSync(adapter.attachmentsDir, { recursive: true });
324
+ return adapter;
325
+ }
326
+ // -------------------------------------------------------
327
+ // Config
328
+ // -------------------------------------------------------
329
+ async getConfig(key) {
330
+ const stmt = this.db.prepare('SELECT value FROM stack_config WHERE key = ?');
331
+ stmt.bind([key]);
332
+ if (stmt.step()) {
333
+ const row = stmt.getAsObject();
334
+ stmt.free();
335
+ return row.value;
336
+ }
337
+ stmt.free();
338
+ return null;
339
+ }
340
+ async setConfig(key, value) {
341
+ this.db.run('INSERT OR REPLACE INTO stack_config (key, value) VALUES (?, ?)', [key, value]);
342
+ this.persist();
343
+ }
344
+ // -------------------------------------------------------
345
+ // Persistence
346
+ // -------------------------------------------------------
347
+ /** Flush the in-memory database to disk. Called after every write. */
348
+ persist() {
349
+ const data = this.db.export();
350
+ writeFileSync(this.path, Buffer.from(data));
351
+ }
352
+ // -------------------------------------------------------
353
+ // Records
354
+ // -------------------------------------------------------
355
+ async createRecord(record) {
356
+ this.db.run(`INSERT INTO records
357
+ (id, type_id, created_at, updated_at, content, version,
358
+ parent_id, entity_id, app_id, deleted_at, permissions)
359
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
360
+ record.id,
361
+ record.typeId,
362
+ toMs(record.createdAt),
363
+ toMs(record.updatedAt),
364
+ JSON.stringify(record.content),
365
+ record.version,
366
+ record.parentId ?? null,
367
+ record.entityId ?? null,
368
+ record.appId ?? null,
369
+ record.deletedAt ? toMs(record.deletedAt) : null,
370
+ record.permissions ? JSON.stringify(record.permissions) : null,
371
+ ]);
372
+ if (record.associations?.length) {
373
+ this.insertAssociations(record.id, record.associations);
374
+ }
375
+ this.updateFts(record.id, JSON.stringify(record.content));
376
+ this.persist();
377
+ return record;
378
+ }
379
+ async getRecord(id) {
380
+ const stmt = this.db.prepare('SELECT * FROM records r WHERE r.id = ?');
381
+ stmt.bind([id]);
382
+ if (!stmt.step()) {
383
+ stmt.free();
384
+ return null;
385
+ }
386
+ const row = stmt.getAsObject();
387
+ stmt.free();
388
+ const associations = this.getAssociationsForRecord(id);
389
+ return rowToRecord(row, associations);
390
+ }
391
+ async updateRecord(id, changes) {
392
+ const setClauses = [];
393
+ const params = [];
394
+ if (changes.content !== undefined) {
395
+ setClauses.push('content = ?');
396
+ params.push(JSON.stringify(changes.content));
397
+ }
398
+ if (changes.typeId !== undefined) {
399
+ setClauses.push('type_id = ?');
400
+ params.push(changes.typeId);
401
+ }
402
+ if (changes.updatedAt !== undefined) {
403
+ setClauses.push('updated_at = ?');
404
+ params.push(toMs(changes.updatedAt));
405
+ }
406
+ if (changes.version !== undefined) {
407
+ setClauses.push('version = ?');
408
+ params.push(changes.version);
409
+ }
410
+ if (changes.deletedAt !== undefined) {
411
+ setClauses.push('deleted_at = ?');
412
+ params.push(toMs(changes.deletedAt));
413
+ }
414
+ if (changes.permissions !== undefined) {
415
+ setClauses.push('permissions = ?');
416
+ params.push(changes.permissions.length ? JSON.stringify(changes.permissions) : null);
417
+ }
418
+ if (setClauses.length) {
419
+ params.push(id);
420
+ this.db.run(`UPDATE records SET ${setClauses.join(', ')} WHERE id = ?`, params);
421
+ }
422
+ // Replace associations if provided
423
+ if (changes.associations !== undefined) {
424
+ this.db.run('DELETE FROM associations WHERE record_id = ?', [id]);
425
+ if (changes.associations.length) {
426
+ this.insertAssociations(id, changes.associations);
427
+ }
428
+ }
429
+ if (changes.content !== undefined) {
430
+ this.updateFts(id, JSON.stringify(changes.content));
431
+ }
432
+ this.persist();
433
+ const updated = await this.getRecord(id);
434
+ if (!updated)
435
+ throw new Error(`Record not found after update: "${id}"`);
436
+ return updated;
437
+ }
438
+ async deleteRecord(id, opts = {}) {
439
+ if (opts.hard) {
440
+ this.db.run('DELETE FROM associations WHERE record_id = ?', [id]);
441
+ this.db.run('DELETE FROM versions WHERE record_id = ?', [id]);
442
+ this.db.run(`DELETE FROM records_fts WHERE docid = (SELECT rowid FROM records WHERE id = ?)`, [id]);
443
+ this.db.run('DELETE FROM records WHERE id = ?', [id]);
444
+ }
445
+ else {
446
+ this.db.run('UPDATE records SET deleted_at = ? WHERE id = ?', [toMs(new Date()), id]);
447
+ }
448
+ this.persist();
449
+ }
450
+ async queryRecords(query) {
451
+ const { sql: where, params } = buildWhereClause(query);
452
+ const order = buildOrderClause(query);
453
+ const limit = query.limit ?? 50;
454
+ // Fetch one extra to determine if there's a next page
455
+ const rows = this.execQuery(`SELECT r.* FROM records r ${where} ${order} LIMIT ?`, [...params, limit + 1]);
456
+ const hasMore = rows.length > limit;
457
+ const page = hasMore ? rows.slice(0, limit) : rows;
458
+ const records = page.map((row) => {
459
+ const associations = this.getAssociationsForRecord(row.id);
460
+ return rowToRecord(row, associations);
461
+ });
462
+ // Total count (without pagination)
463
+ const countRows = this.execQuery(`SELECT COUNT(*) as total FROM records r ${where}`, params);
464
+ const total = countRows[0]?.total ?? 0;
465
+ const lastRecord = records[records.length - 1];
466
+ const cursor = hasMore && lastRecord ? makeCursor(lastRecord) : null;
467
+ return { records, cursor, total };
468
+ }
469
+ // -------------------------------------------------------
470
+ // Versions
471
+ // -------------------------------------------------------
472
+ async getVersions(id) {
473
+ const rows = this.execQuery('SELECT * FROM versions WHERE record_id = ? ORDER BY version DESC', [id]);
474
+ return rows.map(rowToVersion);
475
+ }
476
+ async getVersion(id, version) {
477
+ const rows = this.execQuery('SELECT * FROM versions WHERE record_id = ? AND version = ?', [id, version]);
478
+ return rows.length ? rowToVersion(rows[0]) : null;
479
+ }
480
+ async saveVersion(id, version) {
481
+ this.db.run(`INSERT OR IGNORE INTO versions (record_id, version, content, updated_at, entity_id)
482
+ VALUES (?, ?, ?, ?, ?)`, [
483
+ id,
484
+ version.version,
485
+ JSON.stringify(version.content),
486
+ toMs(version.updatedAt),
487
+ version.entityId ?? null,
488
+ ]);
489
+ this.persist();
490
+ }
491
+ // -------------------------------------------------------
492
+ // Types
493
+ // -------------------------------------------------------
494
+ async saveType(type) {
495
+ this.db.run(`INSERT OR REPLACE INTO types
496
+ (id, base_id, version, name, schema, schema_hash, migrates_from, created_at)
497
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
498
+ type.id,
499
+ type.baseId,
500
+ type.version,
501
+ type.name,
502
+ JSON.stringify(type.schema),
503
+ type.schemaHash,
504
+ type.migratesFrom ?? null,
505
+ toMs(type.createdAt),
506
+ ]);
507
+ this.persist();
508
+ }
509
+ async getType(id) {
510
+ const rows = this.execQuery('SELECT * FROM types WHERE id = ?', [id]);
511
+ return rows.length ? rowToType(rows[0]) : null;
512
+ }
513
+ async listTypes() {
514
+ const rows = this.execQuery('SELECT * FROM types ORDER BY base_id, version');
515
+ return rows.map(rowToType);
516
+ }
517
+ // -------------------------------------------------------
518
+ // Attachments
519
+ // -------------------------------------------------------
520
+ async putAttachment(data, mimeType) {
521
+ const fileId = generateId();
522
+ const ext = mimeType.split('/')[1] ?? 'bin';
523
+ const filename = `${fileId}.${ext}`;
524
+ const filePath = join(this.attachmentsDir, filename);
525
+ await writeFile(filePath, data);
526
+ this.db.run('INSERT INTO attachments (file_id, mime_type, created_at, path) VALUES (?, ?, ?, ?)', [fileId, mimeType, toMs(new Date()), filename]);
527
+ this.persist();
528
+ return fileId;
529
+ }
530
+ async getAttachment(fileId) {
531
+ const rows = this.execQuery('SELECT path FROM attachments WHERE file_id = ?', [fileId]);
532
+ if (!rows.length) {
533
+ throw new Error(`Attachment not found: "${fileId}"`);
534
+ }
535
+ const filePath = join(this.attachmentsDir, rows[0].path);
536
+ return readFile(filePath);
537
+ }
538
+ async deleteAttachment(fileId) {
539
+ this.db.run('DELETE FROM attachments WHERE file_id = ?', [fileId]);
540
+ this.persist();
541
+ }
542
+ // -------------------------------------------------------
543
+ // Private helpers
544
+ // -------------------------------------------------------
545
+ async associate(recordId, association) {
546
+ this.insertAssociations(recordId, [association]);
547
+ this.persist();
548
+ }
549
+ async dissociate(recordId, association) {
550
+ this.db.run(`DELETE FROM associations
551
+ WHERE record_id = ?
552
+ AND kind = ?
553
+ AND label = ?
554
+ AND file_id = ?
555
+ AND related_id = ?`, [
556
+ recordId,
557
+ association.kind,
558
+ association.label,
559
+ association.kind === 'attachment' ? association.fileId : '',
560
+ association.kind === 'relationship' ? association.recordId : '',
561
+ ]);
562
+ this.persist();
563
+ }
564
+ insertAssociations(recordId, associations) {
565
+ for (const assoc of associations) {
566
+ this.db.run(`INSERT OR IGNORE INTO associations
567
+ (record_id, kind, label, file_id, mime_type, related_id)
568
+ VALUES (?, ?, ?, ?, ?, ?)`, [
569
+ recordId,
570
+ assoc.kind,
571
+ assoc.label,
572
+ assoc.kind === 'attachment' ? assoc.fileId : '',
573
+ assoc.kind === 'attachment' ? assoc.mimeType : null,
574
+ assoc.kind === 'relationship' ? assoc.recordId : '',
575
+ ]);
576
+ }
577
+ }
578
+ getAssociationsForRecord(recordId) {
579
+ const rows = this.execQuery('SELECT * FROM associations WHERE record_id = ?', [recordId]);
580
+ return rows.map(rowToAssociation);
581
+ }
582
+ updateFts(recordId, content) {
583
+ // FTS4 content table — delete old entry then insert new one
584
+ this.db.run(`DELETE FROM records_fts WHERE docid = (SELECT rowid FROM records WHERE id = ?)`, [
585
+ recordId,
586
+ ]);
587
+ this.db.run(`INSERT INTO records_fts(docid, content)
588
+ SELECT rowid, ? FROM records WHERE id = ?`, [content, recordId]);
589
+ }
590
+ execQuery(sql, params = []) {
591
+ const stmt = this.db.prepare(sql);
592
+ stmt.bind(params);
593
+ const results = [];
594
+ while (stmt.step()) {
595
+ results.push(stmt.getAsObject());
596
+ }
597
+ stmt.free();
598
+ return results;
599
+ }
600
+ }
601
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@haverstack/adapter-sqlite",
3
+ "version": "0.1.0",
4
+ "description": "SQLite storage adapter for Haverstack",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "import": "./dist/index.js",
9
+ "types": "./dist/index.d.ts"
10
+ }
11
+ },
12
+ "main": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/haverstack/core",
20
+ "directory": "packages/adapter-sqlite"
21
+ },
22
+ "license": "CC0-1.0",
23
+ "keywords": [
24
+ "haverstack",
25
+ "sqlite",
26
+ "adapter",
27
+ "personal data",
28
+ "storage"
29
+ ],
30
+ "dependencies": {
31
+ "sql.js": "^1.14.0",
32
+ "@haverstack/core": "0.1.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^22.0.0",
36
+ "@types/sql.js": "^1.4.9",
37
+ "typescript": "^5.5.0",
38
+ "vitest": "^2.0.0"
39
+ },
40
+ "scripts": {
41
+ "build": "tsc -p tsconfig.build.json",
42
+ "test": "vitest run",
43
+ "typecheck": "tsc --noEmit",
44
+ "lint": "eslint src tests"
45
+ }
46
+ }