hzl-core 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.
Files changed (177) hide show
  1. package/dist/__tests__/backup/backup-restore.test.d.ts +2 -0
  2. package/dist/__tests__/backup/backup-restore.test.d.ts.map +1 -0
  3. package/dist/__tests__/backup/backup-restore.test.js +200 -0
  4. package/dist/__tests__/backup/backup-restore.test.js.map +1 -0
  5. package/dist/__tests__/backup/import-export.test.d.ts +2 -0
  6. package/dist/__tests__/backup/import-export.test.d.ts.map +1 -0
  7. package/dist/__tests__/backup/import-export.test.js +341 -0
  8. package/dist/__tests__/backup/import-export.test.js.map +1 -0
  9. package/dist/__tests__/concurrency/stress.test.d.ts +2 -0
  10. package/dist/__tests__/concurrency/stress.test.d.ts.map +1 -0
  11. package/dist/__tests__/concurrency/stress.test.js +274 -0
  12. package/dist/__tests__/concurrency/stress.test.js.map +1 -0
  13. package/dist/__tests__/concurrency/worker.d.ts +2 -0
  14. package/dist/__tests__/concurrency/worker.d.ts.map +1 -0
  15. package/dist/__tests__/concurrency/worker.js +84 -0
  16. package/dist/__tests__/concurrency/worker.js.map +1 -0
  17. package/dist/__tests__/migrations/upgrade.test.d.ts +2 -0
  18. package/dist/__tests__/migrations/upgrade.test.d.ts.map +1 -0
  19. package/dist/__tests__/migrations/upgrade.test.js +203 -0
  20. package/dist/__tests__/migrations/upgrade.test.js.map +1 -0
  21. package/dist/__tests__/projections/rebuild-equivalence.test.d.ts +2 -0
  22. package/dist/__tests__/projections/rebuild-equivalence.test.d.ts.map +1 -0
  23. package/dist/__tests__/projections/rebuild-equivalence.test.js +276 -0
  24. package/dist/__tests__/projections/rebuild-equivalence.test.js.map +1 -0
  25. package/dist/__tests__/properties/invariants.test.d.ts +2 -0
  26. package/dist/__tests__/properties/invariants.test.d.ts.map +1 -0
  27. package/dist/__tests__/properties/invariants.test.js +314 -0
  28. package/dist/__tests__/properties/invariants.test.js.map +1 -0
  29. package/dist/db/connection.d.ts +13 -0
  30. package/dist/db/connection.d.ts.map +1 -0
  31. package/dist/db/connection.js +52 -0
  32. package/dist/db/connection.js.map +1 -0
  33. package/dist/db/connection.test.d.ts +2 -0
  34. package/dist/db/connection.test.d.ts.map +1 -0
  35. package/dist/db/connection.test.js +63 -0
  36. package/dist/db/connection.test.js.map +1 -0
  37. package/dist/db/migrations/v2.d.ts +2 -0
  38. package/dist/db/migrations/v2.d.ts.map +1 -0
  39. package/dist/db/migrations/v2.js +4 -0
  40. package/dist/db/migrations/v2.js.map +1 -0
  41. package/dist/db/migrations.d.ts +4 -0
  42. package/dist/db/migrations.d.ts.map +1 -0
  43. package/dist/db/migrations.js +45 -0
  44. package/dist/db/migrations.js.map +1 -0
  45. package/dist/db/migrations.test.d.ts +2 -0
  46. package/dist/db/migrations.test.d.ts.map +1 -0
  47. package/dist/db/migrations.test.js +75 -0
  48. package/dist/db/migrations.test.js.map +1 -0
  49. package/dist/db/schema.d.ts +3 -0
  50. package/dist/db/schema.d.ts.map +1 -0
  51. package/dist/db/schema.js +114 -0
  52. package/dist/db/schema.js.map +1 -0
  53. package/dist/events/store.d.ts +33 -0
  54. package/dist/events/store.d.ts.map +1 -0
  55. package/dist/events/store.js +81 -0
  56. package/dist/events/store.js.map +1 -0
  57. package/dist/events/store.test.d.ts +2 -0
  58. package/dist/events/store.test.d.ts.map +1 -0
  59. package/dist/events/store.test.js +138 -0
  60. package/dist/events/store.test.js.map +1 -0
  61. package/dist/events/types.d.ts +106 -0
  62. package/dist/events/types.d.ts.map +1 -0
  63. package/dist/events/types.js +87 -0
  64. package/dist/events/types.js.map +1 -0
  65. package/dist/events/validation.test.d.ts +2 -0
  66. package/dist/events/validation.test.d.ts.map +1 -0
  67. package/dist/events/validation.test.js +83 -0
  68. package/dist/events/validation.test.js.map +1 -0
  69. package/dist/fixtures/sample-data.d.ts +16 -0
  70. package/dist/fixtures/sample-data.d.ts.map +1 -0
  71. package/dist/fixtures/sample-data.js +148 -0
  72. package/dist/fixtures/sample-data.js.map +1 -0
  73. package/dist/index.d.ts +27 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +44 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/index.test.d.ts +2 -0
  78. package/dist/index.test.d.ts.map +1 -0
  79. package/dist/index.test.js +102 -0
  80. package/dist/index.test.js.map +1 -0
  81. package/dist/projections/comments-checkpoints.d.ts +11 -0
  82. package/dist/projections/comments-checkpoints.d.ts.map +1 -0
  83. package/dist/projections/comments-checkpoints.js +33 -0
  84. package/dist/projections/comments-checkpoints.js.map +1 -0
  85. package/dist/projections/comments-checkpoints.test.d.ts +2 -0
  86. package/dist/projections/comments-checkpoints.test.d.ts.map +1 -0
  87. package/dist/projections/comments-checkpoints.test.js +72 -0
  88. package/dist/projections/comments-checkpoints.test.js.map +1 -0
  89. package/dist/projections/dependencies.d.ts +12 -0
  90. package/dist/projections/dependencies.d.ts.map +1 -0
  91. package/dist/projections/dependencies.js +39 -0
  92. package/dist/projections/dependencies.js.map +1 -0
  93. package/dist/projections/dependencies.test.d.ts +2 -0
  94. package/dist/projections/dependencies.test.d.ts.map +1 -0
  95. package/dist/projections/dependencies.test.js +97 -0
  96. package/dist/projections/dependencies.test.js.map +1 -0
  97. package/dist/projections/engine.d.ts +18 -0
  98. package/dist/projections/engine.d.ts.map +1 -0
  99. package/dist/projections/engine.js +56 -0
  100. package/dist/projections/engine.js.map +1 -0
  101. package/dist/projections/engine.test.d.ts +2 -0
  102. package/dist/projections/engine.test.d.ts.map +1 -0
  103. package/dist/projections/engine.test.js +92 -0
  104. package/dist/projections/engine.test.js.map +1 -0
  105. package/dist/projections/rebuild.d.ts +4 -0
  106. package/dist/projections/rebuild.d.ts.map +1 -0
  107. package/dist/projections/rebuild.js +26 -0
  108. package/dist/projections/rebuild.js.map +1 -0
  109. package/dist/projections/rebuild.test.d.ts +2 -0
  110. package/dist/projections/rebuild.test.d.ts.map +1 -0
  111. package/dist/projections/rebuild.test.js +59 -0
  112. package/dist/projections/rebuild.test.js.map +1 -0
  113. package/dist/projections/search.d.ts +11 -0
  114. package/dist/projections/search.d.ts.map +1 -0
  115. package/dist/projections/search.js +39 -0
  116. package/dist/projections/search.js.map +1 -0
  117. package/dist/projections/search.test.d.ts +2 -0
  118. package/dist/projections/search.test.d.ts.map +1 -0
  119. package/dist/projections/search.test.js +78 -0
  120. package/dist/projections/search.test.js.map +1 -0
  121. package/dist/projections/tags.d.ts +12 -0
  122. package/dist/projections/tags.d.ts.map +1 -0
  123. package/dist/projections/tags.js +41 -0
  124. package/dist/projections/tags.js.map +1 -0
  125. package/dist/projections/tags.test.d.ts +2 -0
  126. package/dist/projections/tags.test.d.ts.map +1 -0
  127. package/dist/projections/tags.test.js +69 -0
  128. package/dist/projections/tags.test.js.map +1 -0
  129. package/dist/projections/tasks-current.d.ts +14 -0
  130. package/dist/projections/tasks-current.d.ts.map +1 -0
  131. package/dist/projections/tasks-current.js +110 -0
  132. package/dist/projections/tasks-current.js.map +1 -0
  133. package/dist/projections/tasks-current.test.d.ts +2 -0
  134. package/dist/projections/tasks-current.test.d.ts.map +1 -0
  135. package/dist/projections/tasks-current.test.js +215 -0
  136. package/dist/projections/tasks-current.test.js.map +1 -0
  137. package/dist/projections/types.d.ts +13 -0
  138. package/dist/projections/types.d.ts.map +1 -0
  139. package/dist/projections/types.js +2 -0
  140. package/dist/projections/types.js.map +1 -0
  141. package/dist/services/backup-service.d.ts +16 -0
  142. package/dist/services/backup-service.d.ts.map +1 -0
  143. package/dist/services/backup-service.js +114 -0
  144. package/dist/services/backup-service.js.map +1 -0
  145. package/dist/services/search-service.d.ts +27 -0
  146. package/dist/services/search-service.d.ts.map +1 -0
  147. package/dist/services/search-service.js +33 -0
  148. package/dist/services/search-service.js.map +1 -0
  149. package/dist/services/search-service.test.d.ts +2 -0
  150. package/dist/services/search-service.test.d.ts.map +1 -0
  151. package/dist/services/search-service.test.js +66 -0
  152. package/dist/services/search-service.test.js.map +1 -0
  153. package/dist/services/task-service.d.ts +147 -0
  154. package/dist/services/task-service.d.ts.map +1 -0
  155. package/dist/services/task-service.js +442 -0
  156. package/dist/services/task-service.js.map +1 -0
  157. package/dist/services/task-service.test.d.ts +2 -0
  158. package/dist/services/task-service.test.d.ts.map +1 -0
  159. package/dist/services/task-service.test.js +399 -0
  160. package/dist/services/task-service.test.js.map +1 -0
  161. package/dist/services/validation-service.d.ts +29 -0
  162. package/dist/services/validation-service.d.ts.map +1 -0
  163. package/dist/services/validation-service.js +74 -0
  164. package/dist/services/validation-service.js.map +1 -0
  165. package/dist/services/validation-service.test.d.ts +2 -0
  166. package/dist/services/validation-service.test.d.ts.map +1 -0
  167. package/dist/services/validation-service.test.js +67 -0
  168. package/dist/services/validation-service.test.js.map +1 -0
  169. package/dist/utils/id.d.ts +3 -0
  170. package/dist/utils/id.d.ts.map +1 -0
  171. package/dist/utils/id.js +12 -0
  172. package/dist/utils/id.js.map +1 -0
  173. package/dist/utils/id.test.d.ts +2 -0
  174. package/dist/utils/id.test.d.ts.map +1 -0
  175. package/dist/utils/id.test.js +24 -0
  176. package/dist/utils/id.test.js.map +1 -0
  177. package/package.json +83 -0
@@ -0,0 +1,13 @@
1
+ import Database from 'better-sqlite3';
2
+ export declare function getDefaultDbPath(): string;
3
+ export declare function createConnection(dbPath?: string): Database.Database;
4
+ /**
5
+ * Execute a function within a write transaction using BEGIN IMMEDIATE.
6
+ * This ensures proper locking for concurrent access from multiple agents.
7
+ * Includes retry logic for SQLITE_BUSY errors.
8
+ */
9
+ export declare function withWriteTransaction<T>(db: Database.Database, fn: () => T, opts?: {
10
+ retries?: number;
11
+ busySleepMs?: number;
12
+ }): T;
13
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/db/connection.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAMtC,wBAAgB,gBAAgB,IAAI,MAAM,CAGzC;AAED,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAcnE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,EAAE,EAAE,MAAM,CAAC,EACX,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD,CAAC,CAuBH"}
@@ -0,0 +1,52 @@
1
+ import Database from 'better-sqlite3';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ import fs from 'fs';
5
+ import { runMigrations } from './migrations.js';
6
+ export function getDefaultDbPath() {
7
+ const hzlDir = path.join(os.homedir(), '.hzl');
8
+ return path.join(hzlDir, 'data.db');
9
+ }
10
+ export function createConnection(dbPath) {
11
+ const resolvedPath = dbPath ?? process.env.HZL_DB ?? getDefaultDbPath();
12
+ // Handle in-memory databases
13
+ if (resolvedPath !== ':memory:') {
14
+ const dir = path.dirname(resolvedPath);
15
+ if (!fs.existsSync(dir)) {
16
+ fs.mkdirSync(dir, { recursive: true });
17
+ }
18
+ }
19
+ const db = new Database(resolvedPath);
20
+ runMigrations(db);
21
+ return db;
22
+ }
23
+ /**
24
+ * Execute a function within a write transaction using BEGIN IMMEDIATE.
25
+ * This ensures proper locking for concurrent access from multiple agents.
26
+ * Includes retry logic for SQLITE_BUSY errors.
27
+ */
28
+ export function withWriteTransaction(db, fn, opts) {
29
+ const retries = opts?.retries ?? 5;
30
+ const busySleepMs = opts?.busySleepMs ?? 25;
31
+ let attempt = 0;
32
+ while (true) {
33
+ try {
34
+ // Use immediate transaction for write lock
35
+ return db.transaction(fn).immediate();
36
+ }
37
+ catch (err) {
38
+ const isBusy = err?.code === 'SQLITE_BUSY' || String(err?.message).includes('SQLITE_BUSY');
39
+ if (!isBusy || attempt >= retries) {
40
+ throw err;
41
+ }
42
+ attempt += 1;
43
+ // Simple sleep with exponential backoff
44
+ const sleepTime = busySleepMs * attempt;
45
+ const start = Date.now();
46
+ while (Date.now() - start < sleepTime) {
47
+ // Busy wait (synchronous sleep for better-sqlite3)
48
+ }
49
+ }
50
+ }
51
+ }
52
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/db/connection.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,UAAU,gBAAgB;IAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;IAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAe;IAC9C,MAAM,YAAY,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,gBAAgB,EAAE,CAAC;IAExE,6BAA6B;IAC7B,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACvC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC;IACtC,aAAa,CAAC,EAAE,CAAC,CAAC;IAClB,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,EAAqB,EACrB,EAAW,EACX,IAAiD;IAEjD,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,CAAC,CAAC;IACnC,MAAM,WAAW,GAAG,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC;IAC5C,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,2CAA2C;YAC3C,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC;QACxC,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,MAAM,MAAM,GAAG,GAAG,EAAE,IAAI,KAAK,aAAa,IAAI,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;YAC3F,IAAI,CAAC,MAAM,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;gBAClC,MAAM,GAAG,CAAC;YACZ,CAAC;YACD,OAAO,IAAI,CAAC,CAAC;YACb,wCAAwC;YACxC,MAAM,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;YACxC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,SAAS,EAAE,CAAC;gBACtC,mDAAmD;YACrD,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=connection.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.test.d.ts","sourceRoot":"","sources":["../../src/db/connection.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,63 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import { createConnection, getDefaultDbPath, withWriteTransaction } from './connection.js';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import os from 'os';
6
+ describe('connection', () => {
7
+ const testDbPath = path.join(os.tmpdir(), 'hzl-test-' + Date.now() + '.db');
8
+ afterEach(() => {
9
+ try {
10
+ if (fs.existsSync(testDbPath))
11
+ fs.unlinkSync(testDbPath);
12
+ if (fs.existsSync(testDbPath + '-wal'))
13
+ fs.unlinkSync(testDbPath + '-wal');
14
+ if (fs.existsSync(testDbPath + '-shm'))
15
+ fs.unlinkSync(testDbPath + '-shm');
16
+ }
17
+ catch { }
18
+ });
19
+ it('creates database file at specified path', () => {
20
+ const db = createConnection(testDbPath);
21
+ expect(fs.existsSync(testDbPath)).toBe(true);
22
+ db.close();
23
+ });
24
+ it('runs migrations on new database', () => {
25
+ const db = createConnection(testDbPath);
26
+ const tables = db.prepare("SELECT name FROM sqlite_master WHERE type='table'").all();
27
+ const tableNames = tables.map((t) => t.name);
28
+ expect(tableNames).toContain('events');
29
+ expect(tableNames).toContain('tasks_current');
30
+ expect(tableNames).toContain('projection_state');
31
+ db.close();
32
+ });
33
+ it('returns default path in ~/.hzl/', () => {
34
+ const defaultPath = getDefaultDbPath();
35
+ expect(defaultPath).toContain('.hzl');
36
+ expect(defaultPath).toContain('data.db');
37
+ });
38
+ });
39
+ describe('withWriteTransaction', () => {
40
+ it('commits on success', () => {
41
+ const db = createConnection(':memory:');
42
+ withWriteTransaction(db, () => {
43
+ db.prepare('INSERT INTO projection_state (name, last_event_id, updated_at) VALUES (?, ?, ?)').run('test', 0, new Date().toISOString());
44
+ });
45
+ const row = db.prepare('SELECT * FROM projection_state WHERE name = ?').get('test');
46
+ expect(row).toBeDefined();
47
+ db.close();
48
+ });
49
+ it('rolls back on error', () => {
50
+ const db = createConnection(':memory:');
51
+ try {
52
+ withWriteTransaction(db, () => {
53
+ db.prepare('INSERT INTO projection_state (name, last_event_id, updated_at) VALUES (?, ?, ?)').run('test', 0, new Date().toISOString());
54
+ throw new Error('Intentional failure');
55
+ });
56
+ }
57
+ catch { }
58
+ const row = db.prepare('SELECT * FROM projection_state WHERE name = ?').get('test');
59
+ expect(row).toBeUndefined();
60
+ db.close();
61
+ });
62
+ });
63
+ //# sourceMappingURL=connection.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.test.js","sourceRoot":"","sources":["../../src/db/connection.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const MIGRATION_V2 = "\n-- Placeholder for future schema changes\n";
2
+ //# sourceMappingURL=v2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2.d.ts","sourceRoot":"","sources":["../../../src/db/migrations/v2.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,iDAExB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export const MIGRATION_V2 = `
2
+ -- Placeholder for future schema changes
3
+ `;
4
+ //# sourceMappingURL=v2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2.js","sourceRoot":"","sources":["../../../src/db/migrations/v2.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG;;CAE3B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type Database from 'better-sqlite3';
2
+ export declare function getCurrentVersion(db: Database.Database): number;
3
+ export declare function runMigrations(db: Database.Database): void;
4
+ //# sourceMappingURL=migrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/db/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAO3C,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAgB/D;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CA2BzD"}
@@ -0,0 +1,45 @@
1
+ import { SCHEMA_V1, PRAGMAS } from './schema.js';
2
+ const MIGRATIONS = {
3
+ 1: SCHEMA_V1,
4
+ };
5
+ export function getCurrentVersion(db) {
6
+ try {
7
+ const rows = db
8
+ .prepare('SELECT version FROM schema_migrations')
9
+ .all();
10
+ let maxVersion = 0;
11
+ for (const row of rows) {
12
+ const parsed = Number(row.version);
13
+ if (Number.isFinite(parsed) && parsed > maxVersion) {
14
+ maxVersion = parsed;
15
+ }
16
+ }
17
+ return maxVersion;
18
+ }
19
+ catch {
20
+ return 0;
21
+ }
22
+ }
23
+ export function runMigrations(db) {
24
+ db.exec(PRAGMAS);
25
+ db.exec(`
26
+ CREATE TABLE IF NOT EXISTS schema_migrations (
27
+ version INTEGER PRIMARY KEY,
28
+ applied_at TEXT NOT NULL
29
+ )
30
+ `);
31
+ const currentVersion = getCurrentVersion(db);
32
+ const versions = Object.keys(MIGRATIONS)
33
+ .map(Number)
34
+ .sort((a, b) => a - b);
35
+ for (const version of versions) {
36
+ if (version > currentVersion) {
37
+ db.transaction(() => {
38
+ db.exec(MIGRATIONS[version]);
39
+ db.prepare('INSERT INTO schema_migrations (version, applied_at) VALUES (?, ?)').run(version, new Date().toISOString());
40
+ })();
41
+ }
42
+ }
43
+ db.exec(SCHEMA_V1);
44
+ }
45
+ //# sourceMappingURL=migrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../src/db/migrations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,UAAU,GAA2B;IACzC,CAAC,EAAE,SAAS;CACb,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,EAAqB;IACrD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE;aACZ,OAAO,CAAC,uCAAuC,CAAC;aAChD,GAAG,EAA2C,CAAC;QAClD,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACnC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,UAAU,EAAE,CAAC;gBACnD,UAAU,GAAG,MAAM,CAAC;YACtB,CAAC;QACH,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAqB;IACjD,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAEjB,EAAE,CAAC,IAAI,CAAC;;;;;GAKP,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;SACrC,GAAG,CAAC,MAAM,CAAC;SACX,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAEzB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,OAAO,GAAG,cAAc,EAAE,CAAC;YAC7B,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;gBAClB,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;gBAC7B,EAAE,CAAC,OAAO,CACR,mEAAmE,CACpE,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;YAC3C,CAAC,CAAC,EAAE,CAAC;QACP,CAAC;IACH,CAAC;IAED,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACrB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=migrations.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.test.d.ts","sourceRoot":"","sources":["../../src/db/migrations.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,75 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import Database from 'better-sqlite3';
3
+ import { runMigrations, getCurrentVersion } from './migrations.js';
4
+ describe('migrations', () => {
5
+ let db;
6
+ beforeEach(() => {
7
+ db = new Database(':memory:');
8
+ });
9
+ afterEach(() => {
10
+ db.close();
11
+ });
12
+ it('creates schema_migrations table', () => {
13
+ runMigrations(db);
14
+ const table = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='schema_migrations'").get();
15
+ expect(table).toBeDefined();
16
+ });
17
+ it('creates events table with correct columns', () => {
18
+ runMigrations(db);
19
+ const columns = db.prepare("PRAGMA table_info(events)").all();
20
+ const columnNames = columns.map((c) => c.name);
21
+ expect(columnNames).toContain('event_id');
22
+ expect(columnNames).toContain('task_id');
23
+ expect(columnNames).toContain('type');
24
+ expect(columnNames).toContain('data');
25
+ expect(columnNames).toContain('timestamp');
26
+ });
27
+ it('creates tasks_current projection table with lease fields', () => {
28
+ runMigrations(db);
29
+ const columns = db.prepare("PRAGMA table_info(tasks_current)").all();
30
+ const columnNames = columns.map((c) => c.name);
31
+ expect(columnNames).toContain('task_id');
32
+ expect(columnNames).toContain('title');
33
+ expect(columnNames).toContain('status');
34
+ expect(columnNames).toContain('project');
35
+ expect(columnNames).toContain('claimed_at');
36
+ expect(columnNames).toContain('lease_until');
37
+ });
38
+ it('creates task_dependencies table', () => {
39
+ runMigrations(db);
40
+ const table = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='task_dependencies'").get();
41
+ expect(table).toBeDefined();
42
+ });
43
+ it('creates projection_state table', () => {
44
+ runMigrations(db);
45
+ const table = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='projection_state'").get();
46
+ expect(table).toBeDefined();
47
+ });
48
+ it('creates task_tags table for fast tag filtering', () => {
49
+ runMigrations(db);
50
+ const table = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='task_tags'").get();
51
+ expect(table).toBeDefined();
52
+ });
53
+ it('creates task_comments table', () => {
54
+ runMigrations(db);
55
+ const table = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='task_comments'").get();
56
+ expect(table).toBeDefined();
57
+ });
58
+ it('creates task_checkpoints table', () => {
59
+ runMigrations(db);
60
+ const table = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='task_checkpoints'").get();
61
+ expect(table).toBeDefined();
62
+ });
63
+ it('creates task_search FTS5 table', () => {
64
+ runMigrations(db);
65
+ const table = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='task_search'").get();
66
+ expect(table).toBeDefined();
67
+ });
68
+ it('is idempotent', () => {
69
+ runMigrations(db);
70
+ runMigrations(db);
71
+ const version = getCurrentVersion(db);
72
+ expect(version).toBe(1);
73
+ });
74
+ });
75
+ //# sourceMappingURL=migrations.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.test.js","sourceRoot":"","sources":["../../src/db/migrations.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare const SCHEMA_V1 = "\n-- Append-only event store (source of truth)\nCREATE TABLE IF NOT EXISTS events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n event_id TEXT NOT NULL UNIQUE,\n task_id TEXT NOT NULL,\n type TEXT NOT NULL,\n data TEXT NOT NULL CHECK (json_valid(data)),\n author TEXT,\n agent_id TEXT,\n session_id TEXT,\n correlation_id TEXT,\n causation_id TEXT,\n timestamp TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))\n);\n\n-- Track last applied event id per projection (enables incremental projection + doctor checks)\nCREATE TABLE IF NOT EXISTS projection_state (\n name TEXT PRIMARY KEY,\n last_event_id INTEGER NOT NULL DEFAULT 0,\n updated_at TEXT NOT NULL\n);\n\n-- Current-state projection for fast reads (rebuildable from events)\nCREATE TABLE IF NOT EXISTS tasks_current (\n task_id TEXT PRIMARY KEY,\n title TEXT NOT NULL,\n project TEXT NOT NULL,\n status TEXT NOT NULL CHECK (status IN ('backlog','ready','in_progress','done','archived')),\n parent_id TEXT,\n description TEXT,\n links TEXT NOT NULL DEFAULT '[]' CHECK (json_valid(links)),\n tags TEXT NOT NULL DEFAULT '[]' CHECK (json_valid(tags)),\n priority INTEGER NOT NULL DEFAULT 0 CHECK (priority BETWEEN 0 AND 3),\n due_at TEXT,\n metadata TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(metadata)),\n claimed_at TEXT,\n claimed_by_author TEXT,\n claimed_by_agent_id TEXT,\n lease_until TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n last_event_id INTEGER NOT NULL\n);\n\n-- Dependency edges for fast availability checks (rebuildable from events)\nCREATE TABLE IF NOT EXISTS task_dependencies (\n task_id TEXT NOT NULL,\n depends_on_id TEXT NOT NULL,\n PRIMARY KEY (task_id, depends_on_id)\n);\n\n-- Fast tag filtering (rebuildable)\nCREATE TABLE IF NOT EXISTS task_tags (\n task_id TEXT NOT NULL,\n tag TEXT NOT NULL,\n PRIMARY KEY (task_id, tag)\n);\n\n-- Fast access for steering comments (rebuildable)\nCREATE TABLE IF NOT EXISTS task_comments (\n event_rowid INTEGER PRIMARY KEY,\n task_id TEXT NOT NULL,\n author TEXT,\n agent_id TEXT,\n text TEXT NOT NULL,\n timestamp TEXT NOT NULL\n);\n\n-- Fast access for checkpoints (rebuildable)\nCREATE TABLE IF NOT EXISTS task_checkpoints (\n event_rowid INTEGER PRIMARY KEY,\n task_id TEXT NOT NULL,\n name TEXT NOT NULL,\n data TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(data)),\n timestamp TEXT NOT NULL\n);\n\n-- Full-text search over tasks (rebuildable)\nCREATE VIRTUAL TABLE IF NOT EXISTS task_search USING fts5(\n task_id UNINDEXED,\n title,\n description\n);\n\n-- Indexes for events\nCREATE INDEX IF NOT EXISTS idx_events_task_id ON events(task_id);\nCREATE INDEX IF NOT EXISTS idx_events_task_id_id ON events(task_id, id);\nCREATE INDEX IF NOT EXISTS idx_events_type ON events(type);\nCREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp);\nCREATE INDEX IF NOT EXISTS idx_events_correlation_id ON events(correlation_id);\n\n-- Indexes for tasks_current\nCREATE INDEX IF NOT EXISTS idx_tasks_current_project_status ON tasks_current(project, status);\nCREATE INDEX IF NOT EXISTS idx_tasks_current_priority ON tasks_current(project, priority, created_at);\nCREATE INDEX IF NOT EXISTS idx_tasks_current_claim_next ON tasks_current(project, status, priority DESC, created_at ASC, task_id ASC);\nCREATE INDEX IF NOT EXISTS idx_tasks_current_stuck ON tasks_current(project, status, claimed_at);\nCREATE INDEX IF NOT EXISTS idx_tasks_current_parent ON tasks_current(parent_id);\n\n-- Indexes for dependencies\nCREATE INDEX IF NOT EXISTS idx_deps_depends_on ON task_dependencies(depends_on_id);\n\n-- Indexes for tags/comments/checkpoints\nCREATE INDEX IF NOT EXISTS idx_task_tags_tag ON task_tags(tag, task_id);\nCREATE INDEX IF NOT EXISTS idx_task_comments_task ON task_comments(task_id, event_rowid);\nCREATE INDEX IF NOT EXISTS idx_task_checkpoints_task ON task_checkpoints(task_id, event_rowid);\n";
2
+ export declare const PRAGMAS = "\nPRAGMA journal_mode=WAL;\nPRAGMA synchronous=NORMAL;\nPRAGMA foreign_keys=ON;\nPRAGMA busy_timeout=5000;\n";
3
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,2uIA0GrB,CAAC;AAEF,eAAO,MAAM,OAAO,iHAKnB,CAAC"}
@@ -0,0 +1,114 @@
1
+ export const SCHEMA_V1 = `
2
+ -- Append-only event store (source of truth)
3
+ CREATE TABLE IF NOT EXISTS events (
4
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
5
+ event_id TEXT NOT NULL UNIQUE,
6
+ task_id TEXT NOT NULL,
7
+ type TEXT NOT NULL,
8
+ data TEXT NOT NULL CHECK (json_valid(data)),
9
+ author TEXT,
10
+ agent_id TEXT,
11
+ session_id TEXT,
12
+ correlation_id TEXT,
13
+ causation_id TEXT,
14
+ timestamp TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
15
+ );
16
+
17
+ -- Track last applied event id per projection (enables incremental projection + doctor checks)
18
+ CREATE TABLE IF NOT EXISTS projection_state (
19
+ name TEXT PRIMARY KEY,
20
+ last_event_id INTEGER NOT NULL DEFAULT 0,
21
+ updated_at TEXT NOT NULL
22
+ );
23
+
24
+ -- Current-state projection for fast reads (rebuildable from events)
25
+ CREATE TABLE IF NOT EXISTS tasks_current (
26
+ task_id TEXT PRIMARY KEY,
27
+ title TEXT NOT NULL,
28
+ project TEXT NOT NULL,
29
+ status TEXT NOT NULL CHECK (status IN ('backlog','ready','in_progress','done','archived')),
30
+ parent_id TEXT,
31
+ description TEXT,
32
+ links TEXT NOT NULL DEFAULT '[]' CHECK (json_valid(links)),
33
+ tags TEXT NOT NULL DEFAULT '[]' CHECK (json_valid(tags)),
34
+ priority INTEGER NOT NULL DEFAULT 0 CHECK (priority BETWEEN 0 AND 3),
35
+ due_at TEXT,
36
+ metadata TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(metadata)),
37
+ claimed_at TEXT,
38
+ claimed_by_author TEXT,
39
+ claimed_by_agent_id TEXT,
40
+ lease_until TEXT,
41
+ created_at TEXT NOT NULL,
42
+ updated_at TEXT NOT NULL,
43
+ last_event_id INTEGER NOT NULL
44
+ );
45
+
46
+ -- Dependency edges for fast availability checks (rebuildable from events)
47
+ CREATE TABLE IF NOT EXISTS task_dependencies (
48
+ task_id TEXT NOT NULL,
49
+ depends_on_id TEXT NOT NULL,
50
+ PRIMARY KEY (task_id, depends_on_id)
51
+ );
52
+
53
+ -- Fast tag filtering (rebuildable)
54
+ CREATE TABLE IF NOT EXISTS task_tags (
55
+ task_id TEXT NOT NULL,
56
+ tag TEXT NOT NULL,
57
+ PRIMARY KEY (task_id, tag)
58
+ );
59
+
60
+ -- Fast access for steering comments (rebuildable)
61
+ CREATE TABLE IF NOT EXISTS task_comments (
62
+ event_rowid INTEGER PRIMARY KEY,
63
+ task_id TEXT NOT NULL,
64
+ author TEXT,
65
+ agent_id TEXT,
66
+ text TEXT NOT NULL,
67
+ timestamp TEXT NOT NULL
68
+ );
69
+
70
+ -- Fast access for checkpoints (rebuildable)
71
+ CREATE TABLE IF NOT EXISTS task_checkpoints (
72
+ event_rowid INTEGER PRIMARY KEY,
73
+ task_id TEXT NOT NULL,
74
+ name TEXT NOT NULL,
75
+ data TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(data)),
76
+ timestamp TEXT NOT NULL
77
+ );
78
+
79
+ -- Full-text search over tasks (rebuildable)
80
+ CREATE VIRTUAL TABLE IF NOT EXISTS task_search USING fts5(
81
+ task_id UNINDEXED,
82
+ title,
83
+ description
84
+ );
85
+
86
+ -- Indexes for events
87
+ CREATE INDEX IF NOT EXISTS idx_events_task_id ON events(task_id);
88
+ CREATE INDEX IF NOT EXISTS idx_events_task_id_id ON events(task_id, id);
89
+ CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
90
+ CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp);
91
+ CREATE INDEX IF NOT EXISTS idx_events_correlation_id ON events(correlation_id);
92
+
93
+ -- Indexes for tasks_current
94
+ CREATE INDEX IF NOT EXISTS idx_tasks_current_project_status ON tasks_current(project, status);
95
+ CREATE INDEX IF NOT EXISTS idx_tasks_current_priority ON tasks_current(project, priority, created_at);
96
+ CREATE INDEX IF NOT EXISTS idx_tasks_current_claim_next ON tasks_current(project, status, priority DESC, created_at ASC, task_id ASC);
97
+ CREATE INDEX IF NOT EXISTS idx_tasks_current_stuck ON tasks_current(project, status, claimed_at);
98
+ CREATE INDEX IF NOT EXISTS idx_tasks_current_parent ON tasks_current(parent_id);
99
+
100
+ -- Indexes for dependencies
101
+ CREATE INDEX IF NOT EXISTS idx_deps_depends_on ON task_dependencies(depends_on_id);
102
+
103
+ -- Indexes for tags/comments/checkpoints
104
+ CREATE INDEX IF NOT EXISTS idx_task_tags_tag ON task_tags(tag, task_id);
105
+ CREATE INDEX IF NOT EXISTS idx_task_comments_task ON task_comments(task_id, event_rowid);
106
+ CREATE INDEX IF NOT EXISTS idx_task_checkpoints_task ON task_checkpoints(task_id, event_rowid);
107
+ `;
108
+ export const PRAGMAS = `
109
+ PRAGMA journal_mode=WAL;
110
+ PRAGMA synchronous=NORMAL;
111
+ PRAGMA foreign_keys=ON;
112
+ PRAGMA busy_timeout=5000;
113
+ `;
114
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0GxB,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG;;;;;CAKtB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type Database from 'better-sqlite3';
2
+ import { EventEnvelope, EventType } from './types.js';
3
+ export interface AppendEventInput {
4
+ event_id?: string;
5
+ task_id: string;
6
+ type: EventType;
7
+ data: Record<string, unknown>;
8
+ author?: string;
9
+ agent_id?: string;
10
+ session_id?: string;
11
+ correlation_id?: string;
12
+ causation_id?: string;
13
+ }
14
+ export interface PersistedEventEnvelope extends EventEnvelope {
15
+ rowid: number;
16
+ }
17
+ export interface GetByTaskIdOptions {
18
+ afterId?: number;
19
+ limit?: number;
20
+ }
21
+ export declare class EventStore {
22
+ private db;
23
+ private insertReturningStmt;
24
+ private insertIgnoreStmt;
25
+ private selectByTaskStmt;
26
+ private selectByEventIdStmt;
27
+ constructor(db: Database.Database);
28
+ append(input: AppendEventInput): PersistedEventEnvelope;
29
+ appendIdempotent(input: AppendEventInput): PersistedEventEnvelope | null;
30
+ getByTaskId(taskId: string, opts?: GetByTaskIdOptions): PersistedEventEnvelope[];
31
+ private rowToEnvelope;
32
+ }
33
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/events/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAqB,MAAM,YAAY,CAAC;AAEzE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,sBAAuB,SAAQ,aAAa;IAC3D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,UAAU;IAMT,OAAO,CAAC,EAAE;IALtB,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,mBAAmB,CAAqB;gBAE5B,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAyBzC,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,sBAAsB;IA+BvD,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,GAAG,sBAAsB,GAAG,IAAI;IA0BxE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,sBAAsB,EAAE;IAShF,OAAO,CAAC,aAAa;CAetB"}
@@ -0,0 +1,81 @@
1
+ import { generateId } from '../utils/id.js';
2
+ import { validateEventData } from './types.js';
3
+ export class EventStore {
4
+ db;
5
+ insertReturningStmt;
6
+ insertIgnoreStmt;
7
+ selectByTaskStmt;
8
+ selectByEventIdStmt;
9
+ constructor(db) {
10
+ this.db = db;
11
+ // Use RETURNING to get canonical DB timestamp and rowid
12
+ this.insertReturningStmt = db.prepare(`
13
+ INSERT INTO events (event_id, task_id, type, data, author, agent_id, session_id, correlation_id, causation_id)
14
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
15
+ RETURNING id, timestamp
16
+ `);
17
+ this.insertIgnoreStmt = db.prepare(`
18
+ INSERT OR IGNORE INTO events (event_id, task_id, type, data, author, agent_id, session_id, correlation_id, causation_id)
19
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
20
+ `);
21
+ this.selectByTaskStmt = db.prepare(`
22
+ SELECT * FROM events
23
+ WHERE task_id = ? AND id > COALESCE(?, 0)
24
+ ORDER BY id ASC
25
+ LIMIT COALESCE(?, 1000)
26
+ `);
27
+ this.selectByEventIdStmt = db.prepare(`
28
+ SELECT * FROM events WHERE event_id = ?
29
+ `);
30
+ }
31
+ append(input) {
32
+ validateEventData(input.type, input.data);
33
+ const eventId = input.event_id ?? generateId();
34
+ const row = this.insertReturningStmt.get(eventId, input.task_id, input.type, JSON.stringify(input.data), input.author ?? null, input.agent_id ?? null, input.session_id ?? null, input.correlation_id ?? null, input.causation_id ?? null);
35
+ return {
36
+ rowid: row.id,
37
+ event_id: eventId,
38
+ task_id: input.task_id,
39
+ type: input.type,
40
+ data: input.data,
41
+ author: input.author,
42
+ agent_id: input.agent_id,
43
+ session_id: input.session_id,
44
+ correlation_id: input.correlation_id,
45
+ causation_id: input.causation_id,
46
+ timestamp: row.timestamp,
47
+ };
48
+ }
49
+ appendIdempotent(input) {
50
+ validateEventData(input.type, input.data);
51
+ const eventId = input.event_id ?? generateId();
52
+ const result = this.insertIgnoreStmt.run(eventId, input.task_id, input.type, JSON.stringify(input.data), input.author ?? null, input.agent_id ?? null, input.session_id ?? null, input.correlation_id ?? null, input.causation_id ?? null);
53
+ // If no rows changed, the event_id already existed
54
+ if (result.changes === 0) {
55
+ return null;
56
+ }
57
+ // Fetch the inserted row to get canonical timestamp
58
+ const row = this.selectByEventIdStmt.get(eventId);
59
+ return this.rowToEnvelope(row);
60
+ }
61
+ getByTaskId(taskId, opts) {
62
+ const rows = this.selectByTaskStmt.all(taskId, opts?.afterId ?? null, opts?.limit ?? null);
63
+ return rows.map(row => this.rowToEnvelope(row));
64
+ }
65
+ rowToEnvelope(row) {
66
+ return {
67
+ rowid: row.id,
68
+ event_id: row.event_id,
69
+ task_id: row.task_id,
70
+ type: row.type,
71
+ data: JSON.parse(row.data),
72
+ author: row.author ?? undefined,
73
+ agent_id: row.agent_id ?? undefined,
74
+ session_id: row.session_id ?? undefined,
75
+ correlation_id: row.correlation_id ?? undefined,
76
+ causation_id: row.causation_id ?? undefined,
77
+ timestamp: row.timestamp,
78
+ };
79
+ }
80
+ }
81
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/events/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=store.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.test.d.ts","sourceRoot":"","sources":["../../src/events/store.test.ts"],"names":[],"mappings":""}