@x-otto/persistence 0.0.1-alpha.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/README.md ADDED
@@ -0,0 +1,134 @@
1
+ # @x-otto/persistence
2
+
3
+ Unified snapshot persistence + append-only log abstraction. Backends: memory, file (atomic write), HTTP REST, SQLite.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add @x-otto/persistence
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```ts
14
+ import { createPersistence, createAppendLog } from '@x-otto/persistence'
15
+
16
+ // File-backed snapshot persistence (atomic .tmp → rename)
17
+ const store = createPersistence({ type: 'file', path: '/tmp/data' })
18
+ await store.save('my-key', { hello: 'world' })
19
+ const snap = await store.load('my-key')
20
+ // snap → Snapshot<{ hello: string }>
21
+
22
+ // Append-only log (memory)
23
+ const log = createAppendLog({ type: 'memory' })
24
+ const seq = log.append('stream-1', { event: 'start' })
25
+ log.append('stream-1', { event: 'end' })
26
+ const entries = log.read('stream-1', 0, 10)
27
+ ```
28
+
29
+ ## Backends
30
+
31
+ | Backend | Kind | Save | Load | List | Delete | Notes |
32
+ |-----------------|-------------|-----------------|----------|------|--------|----------------------------------|
33
+ | Memory | `memory` | `structuredClone` | `structuredClone` | ✓ | ✓ | Test / ephemeral |
34
+ | File | `file` | `.tmp` → `rename` | ✓ | ✓ | ✓ | Atomic per-file, mtime sort |
35
+ | HTTP | `http` | `PUT /:id` | `GET /:id` | ✓ | ✓ | Bearer token + ETag, fetch injected |
36
+ | SQLite | `sqlite` | `INSERT OR REPLACE` | ✓ | ✓ | ✓ | WAL mode, change_log per mutation |
37
+
38
+ All backends support `listPaginated(page, pageSize)` returning `PaginatedResult<T>`.
39
+
40
+ ## AppendLog
41
+
42
+ Orthogonal append-only primitive alongside snapshots:
43
+
44
+ | Backend | Kind | Write | Read | Notes |
45
+ |---------|---------|--------------------------------|--------------------------|--------------------------|
46
+ | Memory | `memory` | Array push + listener broadcast | Full / range (0-based seq) | Real-time tail via events |
47
+ | File | `file` | `.jsonl` per stream, write queue | Range read, crash-tail repair | Line-level truncate |
48
+ | SQLite | `sqlite` | `append_entries` table, WAL | Range read + `COUNT(*)` | Shared connection via `sqlite-db-cache` |
49
+
50
+ ## Snapshot<T> Envelope
51
+
52
+ ```ts
53
+ interface Snapshot<T> {
54
+ id: string
55
+ version: number
56
+ data: T
57
+ metadata: {
58
+ createdAt: number
59
+ updatedAt: number
60
+ tags?: string[]
61
+ [key: string]: unknown
62
+ }
63
+ }
64
+ ```
65
+
66
+ Use `saveDocument(persistence, id, data, opts)` as the single source of truth for envelope construction — consumers don't hand-roll `{version, id, data, metadata}`.
67
+
68
+ ## StorageHost
69
+
70
+ Server-side semantic layer for the `RemotePersistence` wire protocol (consumed by `@x-otto/service`):
71
+
72
+ - Namespace whitelist + lazy per-namespace Persistence instance
73
+ - Snapshot envelope wrapping/unwrapping
74
+ - `getChangesSince` — incremental sync data source
75
+ - `streamEvents` — SSE change events (SQLite-backed only, duck-type detection)
76
+
77
+ ```ts
78
+ import { createFileStorageHost } from '@x-otto/persistence'
79
+
80
+ const host = createFileStorageHost({ baseDir: './data', namespaces: ['sessions', 'knowledge'] })
81
+ ```
82
+
83
+ ## Backend Registry
84
+
85
+ `StorageBackendRegistry` — global singleton for registering custom backends (Redis, S3, etc.):
86
+
87
+ ```ts
88
+ import { storageBackendRegistry } from '@x-otto/persistence'
89
+
90
+ storageBackendRegistry.registerPersistence('redis', (opts) => new RedisPersistence(opts))
91
+ const store = createPersistence({ type: 'redis', url: 'redis://...' })
92
+ ```
93
+
94
+ Built-in backends auto-register at module load time.
95
+
96
+ ## Key Files
97
+
98
+ ```
99
+ src/
100
+ types.ts # Snapshot, Persistence<T>, Codec, pagination, StorageOptions
101
+ errors.ts # PersistenceError, RemotePersistenceError
102
+ save-document.ts # saveDocument() — envelope constructor
103
+ memory-persistence.ts # MemoryPersistenceBase<S> + MemoryPersistence<T>
104
+ disk-persistence.ts # DiskPersistence<S> — atomic write base
105
+ file-persistence.ts # FilePersistence<T> — Snapshot disk backend
106
+ remote-persistence.ts # RemotePersistence<S> — HTTP client base
107
+ http-persistence.ts # HttpPersistence<T> — Snapshot HTTP backend
108
+ sqlite-persistence.ts # SqlitePersistence — snapshots + change_log tables
109
+ sqlite-db-cache.ts # Shared SQLite connection cache (ref-counted)
110
+ change-log.ts # ChangeLogEntry type
111
+ append-log.ts # AppendLog<E> + memory/file backends + createAppendLog
112
+ sqlite-append-log.ts # SQLite append-log backend
113
+ storage-factory.ts # createPersistence + backend pre-registration
114
+ storage-host.ts # StorageHost — server-side semantic layer
115
+ atomic-write.ts # Atomic file write utility
116
+ panel-state.ts # Extension panel state persistence
117
+ index.ts # Barrel exports
118
+ ```
119
+
120
+ ## Dependencies
121
+
122
+ - Internal: `@x-otto/env`
123
+ - External: `better-sqlite3` (SQLite backends)
124
+ - Consumers: `@x-otto/session`, `@x-otto/memory`, `@x-otto/runtime`, `@x-otto/coding`, `@x-otto/service`, `@x-otto/persistence-client`
125
+
126
+ ## Testing
127
+
128
+ ```bash
129
+ pnpm --filter @x-otto/persistence typecheck
130
+ pnpm --filter @x-otto/persistence build
131
+ pnpm vitest run packages/persistence/tests/
132
+ ```
133
+
134
+ 18 test files cover all backends CRUD + pagination, AppendLog (truncate / crash-tail repair / concurrency serialization), backend registry, factory, `saveDocument`, `StorageHost`, and change tracking.