memorio 5.1.1 → 5.1.3
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/AGENTS.md +1 -3
- package/CHANGELOG.md +80 -0
- package/README.md +15 -2
- package/SUMMARY.md +2 -2
- package/examples/sqlite-batched-writes.ts +10 -7
- package/global.cjs +382 -210
- package/global.js +359 -186
- package/index.cjs +382 -210
- package/index.js +359 -186
- package/llms.txt +4 -2
- package/markdown/SQLITE.md +46 -20
- package/markdown/STORE.md +12 -12
- package/markdown/SYNC.md +18 -15
- package/modules/redux.cjs +0 -6
- package/modules/redux.cjs.map +1 -1
- package/modules/redux.js +0 -6
- package/modules/redux.js.map +1 -1
- package/package.json +7 -2
- package/types/bun-sqlite.d.ts +14 -0
- package/types/encryption.d.ts +2 -2
- package/types/sqlite.d.ts +58 -35
- package/vsix/memorio.vsix +0 -0
package/llms.txt
CHANGED
|
@@ -21,8 +21,8 @@ Memorio provides 6 storage modules plus utilities:
|
|
|
21
21
|
| `session` | sessionStorage | Dies with browser tab; falls back to non-durable in-memory `Map` in Node.js/Deno |
|
|
22
22
|
| `cache` | In-memory cache | Fastest read, no persistence |
|
|
23
23
|
| `idb` | IndexedDB | Structured, async, persistent (browser-only - disabled in Node.js/Deno) |
|
|
24
|
-
| `sqlite` | SQLite via sql.js (WebAssembly) | Browser-only relational SQL |
|
|
25
|
-
| `observer` | Object watcher |
|
|
24
|
+
| `sqlite` | SQLite via sql.js (WebAssembly) / `bun:sqlite` (native) | Browser-only relational SQL; optional journal + checkpoint persistence to `store` |
|
|
25
|
+
| `observer` | Object watcher | String-based path observer; use `typed<T>()` + `registerSchema()` for statically checked alternatives |
|
|
26
26
|
| `useObserver` | React hook | Auto-discovery of state paths |
|
|
27
27
|
| `encryption` | AES-GCM + PBKDF2 | Encrypt/decrypt values, store/session integration |
|
|
28
28
|
|
|
@@ -51,6 +51,8 @@ To opt in to global access (state, store, session, cache, idb, sqlite, observer,
|
|
|
51
51
|
import 'memorio/global'
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
**Upgrading from 4.x:** in v5, `import 'memorio'` no longer installs globals on `globalThis`. If your code uses bare globals (e.g. `state.counter = 1` without importing `state`), change the import to `import 'memorio/global'`. Named imports (`import { state } from 'memorio'`) are unaffected. After upgrading, restart your dev server and clear `node_modules/.vite` / `.next/cache` to avoid stale pre-bundles masking the change.
|
|
55
|
+
|
|
54
56
|
This is independent of bundler environment detection (no `import.meta.env.DEV`, no `process.env.NODE_ENV` checks).
|
|
55
57
|
|
|
56
58
|
## API Reference
|
package/markdown/SQLITE.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
> **Status:** Published
|
|
2
|
-
> **Date:** 2026-09-12
|
|
3
|
-
> **Scope**: API Reference
|
|
4
|
-
> **Standard**: Memorio API Specification v5
|
|
5
|
-
>
|
|
6
|
-
---
|
|
7
|
-
# SQLite - Memorio
|
|
1
|
+
> **Status:** Published
|
|
2
|
+
> **Date:** 2026-09-12
|
|
3
|
+
> **Scope**: API Reference
|
|
4
|
+
> **Standard**: Memorio API Specification v5
|
|
5
|
+
>
|
|
6
|
+
---
|
|
7
|
+
# SQLite - Memorio
|
|
8
8
|
|
|
9
9
|
> The `sql.js` package is **optional** - if it is not installed, Memorio loads `sql.js` on first use by injecting the `sql-wasm-browser.js` UMD build from the jsDelivr CDN as a classic `<script>` (which exposes the `initSqlJs` factory on `globalThis`). No bare `import('sql.js')` is ever emitted, so bundlers never resolve the optional dependency at build time. Not available in Node.js/Deno.
|
|
10
10
|
|
|
@@ -97,16 +97,16 @@ console.debug('SQLite version:', sqlite.db.version());
|
|
|
97
97
|
### Example 5: Persistence & dev download
|
|
98
98
|
|
|
99
99
|
> **Important:** sql.js databases live in **WebAssembly memory** - they are
|
|
100
|
-
> in-memory and **volatile** (lost on page refresh) unless you
|
|
100
|
+
> in-memory and **volatile** (lost on page refresh) unless you opt into persistence.
|
|
101
101
|
|
|
102
102
|
```javascript
|
|
103
|
-
// Opt into
|
|
103
|
+
// Opt into persistence at create time (global config or per-create)
|
|
104
104
|
await sqlite.db.create('app', { persistence: true });
|
|
105
105
|
|
|
106
106
|
await sqlite.query.run('app', 'CREATE TABLE notes (id INTEGER PRIMARY KEY, body TEXT)');
|
|
107
|
-
// writes are
|
|
107
|
+
// writes are journaled incrementally; checkpoints are saved automatically
|
|
108
108
|
|
|
109
|
-
await sqlite.db.persist('app'); // force an immediate snapshot
|
|
109
|
+
await sqlite.db.persist('app'); // force an immediate checkpoint (full snapshot + clear journal)
|
|
110
110
|
// After a refresh, reopening restores the data:
|
|
111
111
|
await sqlite.db.create('app', { persistence: true });
|
|
112
112
|
|
|
@@ -117,10 +117,33 @@ await sqlite.db.download('app', 'app.sqlite');
|
|
|
117
117
|
await sqlite.db.close('app');
|
|
118
118
|
```
|
|
119
119
|
|
|
120
|
+
Persistence uses a **journal + checkpoint** strategy for incremental durability:
|
|
121
|
+
|
|
122
|
+
1. **Journal**: every `db.run(sql, params)` write is recorded as a journal entry
|
|
123
|
+
(with an HLC timestamp for causal ordering) in `store` (localStorage). The
|
|
124
|
+
journal is append-only and incremental - only the changed statement is stored.
|
|
125
|
+
2. **Checkpoint**: every 50 operations (configurable), or after 250 ms of write
|
|
126
|
+
idle, a full database snapshot is taken and written to `store`. The journal is
|
|
127
|
+
then cleared up to that point.
|
|
128
|
+
3. **Recovery**: on `create(name, { persistence: true })`, the latest checkpoint
|
|
129
|
+
is loaded first, then any journal entries that were written after the
|
|
130
|
+
checkpoint are replayed on top - so no writes are lost even if the page closes
|
|
131
|
+
between checkpoints.
|
|
132
|
+
|
|
120
133
|
Persistence is stored on `store` (localStorage, namespaced per
|
|
121
|
-
`sqlite.config({ namespace })` / memorio context) as
|
|
122
|
-
`memorio:sqlite:db:<ns>:<name
|
|
123
|
-
|
|
134
|
+
`sqlite.config({ namespace })` / memorio context) as:
|
|
135
|
+
- Checkpoint: `memorio:sqlite:db:<ns>:<name>` (base64 binary snapshot)
|
|
136
|
+
- Journal entries: `memorio:sqlite:journal:<ns>:<name>:<seq>` (individual SQL ops)
|
|
137
|
+
|
|
138
|
+
It is best-effort: if `store` is unavailable the database simply behaves as
|
|
139
|
+
in-memory. The journal is also available directly:
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
sqlite.db.persist('app'); // force checkpoint (alias: flush)
|
|
143
|
+
sqlite.db.flush('app'); // force checkpoint
|
|
144
|
+
const entries = sqlite.db.journal.entries('app'); // inspect pending ops
|
|
145
|
+
await sqlite.db.journal.checkpoint('app'); // manual checkpoint
|
|
146
|
+
```
|
|
124
147
|
|
|
125
148
|
---
|
|
126
149
|
|
|
@@ -132,9 +155,11 @@ the database simply behaves as in-memory.
|
|
|
132
155
|
|--------|------------|---------|-------------|
|
|
133
156
|
| `sqlite.config(opts)` | `opts: { loader?, locateFile?, wasmUrl?, persistence?, namespace? }` | `sqlite` | Configure the engine. `loader` fully replaces the initializer (default = CDN `<script>`); `locateFile` customizes wasm resolution; `wasmUrl` sets the wasm base directory; `persistence` toggles automatic db snapshots; `namespace` partitions persisted snapshots. Chainable. |
|
|
134
157
|
| `sqlite.db.create(name, opts)` | `name: string, opts?: { data?, persistence? }` | `Database` | Opens/creates a named in-memory db. With `persistence: true` (or global config), a snapshot is restored if present and writes are auto-saved. |
|
|
135
|
-
| `sqlite.db.persist(name)` | `name: string` | `Promise<boolean>` | Force an immediate snapshot of a persisted database to `store`. |
|
|
158
|
+
| `sqlite.db.persist(name)` | `name: string` | `Promise<boolean>` | Force an immediate checkpoint (full snapshot + journal clear) of a persisted database to `store`. Alias of `flush`. |
|
|
159
|
+
| `sqlite.db.flush(name)` | `name: string` | `Promise<boolean>` | Force an immediate checkpoint (alias of `persist`). |
|
|
136
160
|
| `sqlite.db.download(name, filename?)` | `name: string, filename?: string` | `Promise<boolean>` | Dev-only: trigger a browser download of the db as a `.sqlite` file. |
|
|
137
|
-
| `sqlite.db.close(name)` | `name: string` | `Promise<void>` |
|
|
161
|
+
| `sqlite.db.close(name)` | `name: string` | `Promise<void>` | Checkpoint (if enabled), close, and release the handle. |
|
|
162
|
+
| `sqlite.db.journal` | `name: string` | Object | Journal namespace: `append`, `entries`, `count`, `clear`, `replay`, `checkpoint`. |
|
|
138
163
|
| `sqlite.ready` | none | `Promise<void>` | Resolves once `sql.js` has been initialized. Rejects (and sets `_disabled`) if the engine can't load. |
|
|
139
164
|
| `sqlite.db.version()` | none | `string \| null` | Engine version, available after initialization. |
|
|
140
165
|
| `sqlite._disabled` | none | `boolean` | `true` when the module is disabled (non-browser env / load failure). |
|
|
@@ -147,7 +172,7 @@ the database simply behaves as in-memory.
|
|
|
147
172
|
| `sqlite.db.support()` | none | `boolean` | Check whether SQLite can run in this environment. |
|
|
148
173
|
| `sqlite.db.create(name, opts?)` | `name: string`, `opts?: { data }` | `Promise<Database>` | Create an in-memory database (or reopen one from a binary dump). |
|
|
149
174
|
| `sqlite.db.get(name)` | `name: string` | `Database` | Retrieve an open database handle. |
|
|
150
|
-
| `sqlite.db.delete(name)` | `name: string` | `boolean
|
|
175
|
+
| `sqlite.db.delete(name)` | `name: string` | `Promise<boolean>` | Checkpoint (if enabled), close, and remove a database handle. |
|
|
151
176
|
| `sqlite.db.list()` | none | `string[]` | List open database names. |
|
|
152
177
|
| `sqlite.db.size(name?)` | `name?: string` | `Promise<number>` | Size in bytes of one or all databases. |
|
|
153
178
|
| `sqlite.db.export(name)` | `name: string` | `Promise<Uint8Array>` | Export a database to a binary dump. |
|
|
@@ -184,6 +209,7 @@ the database simply behaves as in-memory.
|
|
|
184
209
|
|
|
185
210
|
1. Configure the wasm path for production: `sqlite.config({ wasmUrl })` or `sqlite.config({ loader })`.
|
|
186
211
|
2. Create one named database per feature and reuse the handle: `const db = await sqlite.db.create('app')`.
|
|
187
|
-
3.
|
|
188
|
-
4. Use
|
|
189
|
-
5.
|
|
212
|
+
3. Use `await sqlite.ready` before running statements to ensure the engine is loaded.
|
|
213
|
+
4. Use `?` placeholders and `params` to avoid SQL injection.
|
|
214
|
+
5. Batch writes and call `sqlite.db.persist()` / `sqlite.db.flush()` once after the batch, not inside a loop. The journal captures each write incrementally, but the checkpoint (full snapshot) is the expensive operation.
|
|
215
|
+
6. Always release databases you no longer need: `await sqlite.db.delete('temp')`.
|
package/markdown/STORE.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
> **Status:** Published
|
|
2
|
-
> **Date:** 2026-09-12
|
|
3
|
-
> **Scope**: API Reference
|
|
4
|
-
> **Standard**: Memorio API Specification v5
|
|
5
|
-
>
|
|
6
|
-
---
|
|
7
|
-
# Store - Memorio
|
|
1
|
+
> **Status:** Published
|
|
2
|
+
> **Date:** 2026-09-12
|
|
3
|
+
> **Scope**: API Reference
|
|
4
|
+
> **Standard**: Memorio API Specification v5
|
|
5
|
+
>
|
|
6
|
+
---
|
|
7
|
+
# Store - Memorio
|
|
8
8
|
|
|
9
9
|
> 🖥️ **Browser & Edge**: Uses localStorage for persistence
|
|
10
10
|
> ⚙️ **Node.js/Deno**: Falls back to in-memory storage (not persistent)
|
|
@@ -56,7 +56,7 @@ store.remove('username');
|
|
|
56
56
|
|
|
57
57
|
// Check size
|
|
58
58
|
const totalSize = store.size();
|
|
59
|
-
console.debug(`${totalSize}
|
|
59
|
+
console.debug(`${totalSize} KB`);
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
### Example 3: Advanced
|
|
@@ -66,9 +66,9 @@ console.debug(`${totalSize} bytes`);
|
|
|
66
66
|
const [used, total] = await store.quota();
|
|
67
67
|
console.debug(`Using ${used} out of ${total} KB`);
|
|
68
68
|
|
|
69
|
-
// Get total size in
|
|
69
|
+
// Get total size in kilobytes
|
|
70
70
|
const size = store.size();
|
|
71
|
-
console.debug(`${size}
|
|
71
|
+
console.debug(`${size} KB`);
|
|
72
72
|
|
|
73
73
|
// Clear all data
|
|
74
74
|
store.removeAll();
|
|
@@ -97,7 +97,7 @@ try {
|
|
|
97
97
|
| `store.delete(name)` | `name: string` | `boolean` | Alias for remove |
|
|
98
98
|
| `store.removeAll()` | none | `boolean` | Clear all storage |
|
|
99
99
|
| `store.clearAll()` | none | `boolean` | Alias for removeAll |
|
|
100
|
-
| `store.size()` | none | `number` | Get total size in
|
|
100
|
+
| `store.size()` | none | `number` | Get total size in kilobytes (KB) |
|
|
101
101
|
| `store.quota()` | none | `Promise<[number, number]>` | Get storage usage/quota in KB |
|
|
102
102
|
|
|
103
103
|
### Properties
|
|
@@ -167,4 +167,4 @@ Use `store.quota()` to monitor usage.
|
|
|
167
167
|
1. Prefix keys: `store.set('app_username', '...')`
|
|
168
168
|
2. Check before set: `if (store.get('key')) { ... }`
|
|
169
169
|
3. Handle quota: Try/catch around large data
|
|
170
|
-
4. Clean up: `store.removeAll()` on logout
|
|
170
|
+
4. Clean up: `store.removeAll()` on logout
|
package/markdown/SYNC.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
> **Status:** Published
|
|
2
|
-
> **Date:** 2026-09-12
|
|
3
|
-
> **Scope**: API Reference
|
|
4
|
-
> **Standard**: Memorio API Specification v5
|
|
5
|
-
>
|
|
6
|
-
---
|
|
7
|
-
# Synchronization & Cloud (optional)
|
|
1
|
+
> **Status:** Published
|
|
2
|
+
> **Date:** 2026-09-12
|
|
3
|
+
> **Scope**: API Reference
|
|
4
|
+
> **Standard**: Memorio API Specification v5
|
|
5
|
+
>
|
|
6
|
+
---
|
|
7
|
+
# Synchronization & Cloud (optional)
|
|
8
8
|
|
|
9
9
|
`memorio.memory` is **local-first**. Data is created and served from the device;
|
|
10
10
|
the cloud is only ever a **transport/persistence provider**, never the source of
|
|
@@ -67,12 +67,15 @@ memorio.memory.configure({ sync: { provider: myCloudProvider, namespace: '…' }
|
|
|
67
67
|
SQLite (`sql.js`) is **in-memory by default** (volatie per page load). It becomes
|
|
68
68
|
the durable journal/value store when you opt in:
|
|
69
69
|
|
|
70
|
-
- `sqlite.config({ persistence: true })` / `sqlite.db.create('app', { persistence: true })`
|
|
71
|
-
|
|
72
|
-
- Writes are
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
- `sqlite.config({ persistence: true })` / `sqlite.db.create('app', { persistence: true })`
|
|
71
|
+
snapshot the database to `store` (localStorage) and restore it on reopen.
|
|
72
|
+
- Writes are journaled incrementally (append-only, HLC-timestamped) and
|
|
73
|
+
checkpointed periodically (every 50 ops or 250 ms of idle). On reopen, the
|
|
74
|
+
last checkpoint is loaded and the journal is replayed — no writes are lost.
|
|
75
|
+
- `sqlite.db.persist(name)` / `sqlite.db.flush(name)` forces an immediate
|
|
76
|
+
checkpoint; `sqlite.db.close(name)` checkpoints + closes;
|
|
77
|
+
`sqlite.db.download(name, file?)` triggers a browser `.sqlite` download
|
|
78
|
+
(dev convenience).
|
|
76
79
|
|
|
77
80
|
See `docs/markdown/SQLITE.md` for the full SQLite reference.
|
|
78
81
|
|
|
@@ -172,7 +175,7 @@ interface SyncProvider {
|
|
|
172
175
|
| `localStorage` / Map | `store` | no | yes (browser) |
|
|
173
176
|
| `sessionStorage` / Map | `session` | no | per-tab (browser) |
|
|
174
177
|
| IndexedDB | `idb`, `memory` durable | no | yes |
|
|
175
|
-
| sql.js (WASM heap) | `sqlite` | **yes** |
|
|
178
|
+
| sql.js (WASM heap) | `sqlite` | **yes** | with `persistence: true` (journal + checkpoint → `store`) |
|
|
176
179
|
| sync journal | `memory.journal` | no | yes (`store`) |
|
|
177
180
|
|
|
178
181
|
---
|
|
@@ -315,4 +318,4 @@ entity-level entries. Mitigate with:
|
|
|
315
318
|
Applying granular path-level patches, HLC for causality, fractional indexing
|
|
316
319
|
for ordered collections, explicit tombstones for deletions, and a convergence
|
|
317
320
|
test suite lets memorio handle high-frequency concurrent offline edits across
|
|
318
|
-
devices without the overhead of a full CRDT stack.
|
|
321
|
+
devices without the overhead of a full CRDT stack.
|
package/modules/redux.cjs
CHANGED
|
@@ -471,8 +471,6 @@ var CONTEXTS_KEY, _contexts;
|
|
|
471
471
|
var init_platform = __esm({
|
|
472
472
|
"core/platform.ts"() {
|
|
473
473
|
init_cjs_shims();
|
|
474
|
-
init_internal();
|
|
475
|
-
init_encryption();
|
|
476
474
|
__name(getSessionStorage, "getSessionStorage");
|
|
477
475
|
__name(getLocalStorage, "getLocalStorage");
|
|
478
476
|
__name(hasIndexedDB, "hasIndexedDB");
|
|
@@ -1675,12 +1673,8 @@ function encodeHLC(hlcValue) {
|
|
|
1675
1673
|
}
|
|
1676
1674
|
__name(encodeHLC, "encodeHLC");
|
|
1677
1675
|
|
|
1678
|
-
// core/mutation/patch.ts
|
|
1679
|
-
init_cjs_shims();
|
|
1680
|
-
|
|
1681
1676
|
// core/mutation/transaction.ts
|
|
1682
1677
|
init_cjs_shims();
|
|
1683
|
-
init_internal();
|
|
1684
1678
|
var TX_REGISTRY_KEY = "__memorio_transaction_registry__";
|
|
1685
1679
|
var registry = globalThis[TX_REGISTRY_KEY] || /* @__PURE__ */ new Map();
|
|
1686
1680
|
if (!globalThis[TX_REGISTRY_KEY]) {
|