memorio 4.9.35 → 5.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/AGENTS.md +3 -3
- package/README.md +95 -516
- package/SECURITY.md +159 -33
- package/SUMMARY.md +59 -45
- package/adr/001-state-proxy-model.md +95 -0
- package/adr/002-observer-semantics.md +179 -0
- package/adr/003-deep-mutation-semantics.md +128 -0
- package/adr/004-array-mutation-semantics.md +127 -0
- package/adr/005-scheduler-contract.md +148 -0
- package/adr/006-context-isolation.md +91 -0
- package/adr/007-mutation-records.md +117 -0
- package/adr/008-transactions.md +105 -0
- package/adr/009-history-model.md +109 -0
- package/adr/README.md +46 -0
- package/adr/template.md +48 -0
- package/bin/cli.js +68 -0
- package/examples/basic.ts +115 -115
- package/examples/browser-vanilla.html +358 -358
- package/examples/cache.ts +72 -72
- package/examples/cross-platform-guards.ts +57 -57
- package/examples/history.ts +104 -0
- package/examples/idb.ts +109 -109
- package/examples/multi-tenant-context.ts +44 -44
- package/examples/node-server.ts +308 -308
- package/examples/observer.ts +60 -60
- package/examples/platform.ts +115 -115
- package/examples/react-app.tsx +362 -362
- package/examples/react-observer.tsx +63 -63
- package/examples/semantic-memory.ts +60 -60
- package/examples/session-advanced.ts +91 -91
- package/examples/sqlite-batched-writes.ts +57 -57
- package/examples/state-advanced.ts +89 -89
- package/examples/store-advanced.ts +117 -117
- package/examples/sync.ts +90 -0
- package/examples/typed-and-schema.ts +102 -100
- package/examples/useObserver.tsx +140 -141
- package/global.cjs +5733 -0
- package/global.d.ts +8 -0
- package/global.js +5667 -0
- package/index.cjs +2202 -1041
- package/index.d.ts +2 -0
- package/index.js +2178 -1040
- package/llms.txt +113 -8
- package/markdown/AUDIT-REPORT.md +134 -0
- package/markdown/CACHE.md +191 -0
- package/markdown/DEVTOOLS.md +128 -0
- package/markdown/DISPATCH.md +176 -0
- package/markdown/HISTORY.md +198 -0
- package/markdown/IDB.md +177 -0
- package/markdown/IMPORT.md +152 -0
- package/markdown/INSPECT.md +122 -0
- package/markdown/LOGGER.md +153 -0
- package/markdown/MEMORY-ATTACHMENT.md +95 -0
- package/markdown/MEMORY.md +161 -0
- package/markdown/OBSERVER.md +208 -0
- package/markdown/PLATFORM.md +277 -0
- package/markdown/REDUX.md +54 -0
- package/markdown/SCHEMA.md +175 -0
- package/markdown/SESSION.md +164 -0
- package/markdown/SQLITE.md +189 -0
- package/markdown/STATE.md +159 -0
- package/markdown/STORE.md +170 -0
- package/markdown/SYNC.md +318 -0
- package/markdown/TYPED.md +164 -0
- package/markdown/USEOBSERVER.md +256 -0
- package/modules/redux.cjs +701 -177
- package/modules/redux.cjs.map +1 -1
- package/modules/redux.js +701 -177
- package/modules/redux.js.map +1 -1
- package/package.json +26 -4
- package/types/broadcast.d.ts +61 -0
- package/types/computed.d.ts +96 -0
- package/types/encryption.d.ts +129 -0
- package/types/env.d.ts +19 -9
- package/types/exports.d.ts +29 -0
- package/types/history.d.ts +13 -1
- package/types/memorio.d.ts +25 -6
- package/types/mutation.d.ts +75 -0
- package/types/security.d.ts +67 -0
- package/types/session.d.ts +23 -5
- package/types/store.d.ts +19 -3
- package/vsix/memorio.vsix +0 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
> **Status:** Published
|
|
2
|
+
> **Date:** 2026-09-12
|
|
3
|
+
> **Scope**: API Reference
|
|
4
|
+
> **Standard**: Memorio API Specification v5
|
|
5
|
+
>
|
|
6
|
+
---
|
|
7
|
+
# Session - Memorio
|
|
8
|
+
|
|
9
|
+
> 🖥️ **Browser & Edge**: Uses sessionStorage for persistence
|
|
10
|
+
> ⚙️ **Node.js/Deno**: Falls back to in-memory storage (not persistent)
|
|
11
|
+
|
|
12
|
+
Session provides temporary storage using browser sessionStorage. Data persists until the tab or window is closed.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install memorio
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```javascript
|
|
21
|
+
import { session } from 'memorio';
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
> **Classic `import`**: `session` is also available via the global entrypoint.
|
|
25
|
+
> `import 'memorio/global'` exposes the same instance as `globalThis.session`.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Quick Examples
|
|
30
|
+
|
|
31
|
+
### Example 1: Basic Usage
|
|
32
|
+
|
|
33
|
+
```javascript
|
|
34
|
+
// Save session data
|
|
35
|
+
session.set('token', 'abc123');
|
|
36
|
+
session.set('userId', 42);
|
|
37
|
+
|
|
38
|
+
// Read session data
|
|
39
|
+
console.debug(session.get('token')); // "abc123"
|
|
40
|
+
|
|
41
|
+
// Check persistence
|
|
42
|
+
console.debug(session.isPersistent); // true in browser, false in Node.js/Deno
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Example 2: Intermediate
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
// Store objects
|
|
49
|
+
session.set('user', { name: 'Mario', role: 'admin' });
|
|
50
|
+
|
|
51
|
+
// Remove specific item
|
|
52
|
+
session.remove('token');
|
|
53
|
+
|
|
54
|
+
// Clear all session data
|
|
55
|
+
session.removeAll();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Example 3: Advanced
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
// Check if session has data
|
|
62
|
+
if (session.get('authToken')) {
|
|
63
|
+
// User is logged in
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Get storage quota (returns Promise<[usage, quota]> in KB)
|
|
67
|
+
const [used, total] = await session.quota();
|
|
68
|
+
console.debug(`Using ${used} out of ${total} KB`);
|
|
69
|
+
|
|
70
|
+
// Get total size in characters
|
|
71
|
+
const size = session.size();
|
|
72
|
+
console.debug(`${size} bytes`);
|
|
73
|
+
|
|
74
|
+
// Handle session expiry
|
|
75
|
+
window.addEventListener('storage', (e) => {
|
|
76
|
+
if (e.key === 'session' && !e.newValue) {
|
|
77
|
+
// Session cleared
|
|
78
|
+
redirectToLogin();
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## API Reference
|
|
86
|
+
|
|
87
|
+
### Methods
|
|
88
|
+
|
|
89
|
+
| Method | Parameters | Returns | Description |
|
|
90
|
+
|--------|------------|---------|-------------|
|
|
91
|
+
| `session.get(name)` | `name: string` | `any` | Get value from session |
|
|
92
|
+
| `session.set(name, value)` | `name: string, value: any` | `void` | Save value to session |
|
|
93
|
+
| `session.remove(name)` | `name: string` | `boolean` | Remove single item |
|
|
94
|
+
| `session.delete(name)` | `name: string` | `boolean` | Alias for remove |
|
|
95
|
+
| `session.removeAll()` | `none` | `boolean` | Clear all session data |
|
|
96
|
+
| `session.clearAll()` | `none` | `boolean` | Alias for removeAll |
|
|
97
|
+
| `session.size()` | `none` | `number` | Get total size in characters |
|
|
98
|
+
| `session.quota()` | `none` | `Promise<[number, number]>` | Get storage usage/quota in KB |
|
|
99
|
+
|
|
100
|
+
### Properties
|
|
101
|
+
|
|
102
|
+
| Property | Type | Description |
|
|
103
|
+
|----------|------|-------------|
|
|
104
|
+
| `session.isPersistent` | `boolean` | `true` if using real sessionStorage, `false` if in-memory fallback |
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Store vs Session
|
|
109
|
+
|
|
110
|
+
| Feature | Store | Session |
|
|
111
|
+
|---------|-------|---------|
|
|
112
|
+
| Storage | localStorage | sessionStorage |
|
|
113
|
+
| Lifetime | Forever | Until tab closes |
|
|
114
|
+
| Use case | User preferences | Temporary auth |
|
|
115
|
+
| Shared across tabs | Yes | No |
|
|
116
|
+
| Platform | Browser/Edge | Browser/Edge |
|
|
117
|
+
| Persistence | ✅ Always | ✅ Browser only |
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Platform Notes
|
|
122
|
+
|
|
123
|
+
| Platform | Behavior |
|
|
124
|
+
|----------|----------|
|
|
125
|
+
| Browser | Uses real sessionStorage - data persists until tab closes |
|
|
126
|
+
| Edge Worker | Uses real sessionStorage |
|
|
127
|
+
| Node.js | In-memory fallback - data lost on process restart |
|
|
128
|
+
| Deno | In-memory fallback - data lost on process restart |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Best Practices
|
|
133
|
+
|
|
134
|
+
1. Use for auth tokens: `session.set('token', jwt)`
|
|
135
|
+
2. Clear on logout: `session.removeAll()`
|
|
136
|
+
3. Don't use for persistent data
|
|
137
|
+
4. Check for null: `session.get('key') || defaultValue`
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Common Use Cases
|
|
142
|
+
|
|
143
|
+
### Authentication
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
// Login
|
|
147
|
+
session.set('authToken', response.token);
|
|
148
|
+
session.set('user', response.user);
|
|
149
|
+
|
|
150
|
+
// Logout
|
|
151
|
+
session.removeAll();
|
|
152
|
+
router.push('/login');
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Form Progress
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
// Save form draft
|
|
159
|
+
session.set('formDraft', formData);
|
|
160
|
+
|
|
161
|
+
// Restore on page refresh
|
|
162
|
+
const draft = session.get('formDraft');
|
|
163
|
+
if (draft) restoreForm(draft);
|
|
164
|
+
```
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
> **Status:** Published
|
|
2
|
+
> **Date:** 2026-09-12
|
|
3
|
+
> **Scope**: API Reference
|
|
4
|
+
> **Standard**: Memorio API Specification v5
|
|
5
|
+
>
|
|
6
|
+
---
|
|
7
|
+
# SQLite - Memorio
|
|
8
|
+
|
|
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
|
+
|
|
11
|
+
SQLite brings a full SQL engine into the browser through [`sql.js`](https://sql.js.org), a port of SQLite to JavaScript via WebAssembly. Memorio loads it **lazily** on first use, so it only affects bundles that actually use the `sqlite` module.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install memorio
|
|
17
|
+
# Optional: install the SQLite engine locally (the default loader fetches it from the CDN)
|
|
18
|
+
npm install sql.js
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
import { sqlite } from 'memorio';
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
> **Global API**: `import 'memorio/global'` is the opt-in entrypoint that also exposes `state`, `store`, `session`, `cache`, `idb`, `sqlite`, `observer`, and `useObserver` on `globalThis`.
|
|
26
|
+
|
|
27
|
+
> The default loader injects the sql.js UMD build (`sql-wasm-browser.js`) from the jsDelivr CDN as a classic `<script>`, exposing the `initSqlJs` factory on `globalThis`. This keeps `sql.js` (and its WASM) out of your build graph entirely - it's only fetched when `sqlite` is first used. For production/self-hosted setups, install `sql.js` and configure a custom `loader` (e.g. `sqlite.config({ loader: () => import('sql.js') })` under a bundler), or set the wasm base with `sqlite.config({ wasmUrl })` / `sqlite.config({ locateFile })`.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Quick Examples
|
|
32
|
+
|
|
33
|
+
### Example 1: Basic Usage
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
// Create an in-memory database and a table
|
|
37
|
+
await sqlite.db.create('myApp');
|
|
38
|
+
await sqlite.query.run('myApp', 'CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
|
|
39
|
+
|
|
40
|
+
// Insert data
|
|
41
|
+
await sqlite.query.run('myApp', 'INSERT INTO users (name) VALUES (?)', ['Mario']);
|
|
42
|
+
|
|
43
|
+
// Select data
|
|
44
|
+
const rows = await sqlite.query.select('myApp', 'SELECT * FROM users');
|
|
45
|
+
console.debug(rows); // [{ id: 1, name: 'Mario' }]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Example 2: CRUD shortcuts
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
const db = 'store';
|
|
52
|
+
|
|
53
|
+
await sqlite.db.create(db);
|
|
54
|
+
await sqlite.query.run(db, 'CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, price REAL)');
|
|
55
|
+
await sqlite.data.set(db, 'INSERT INTO products (name, price) VALUES (?, ?)', ['Apple', 1.5]);
|
|
56
|
+
await sqlite.data.set(db, 'INSERT INTO products (name, price) VALUES (?, ?)', ['Banana', 0.8]);
|
|
57
|
+
|
|
58
|
+
// First matching row
|
|
59
|
+
const apple = await sqlite.data.get(db, 'SELECT * FROM products WHERE name = ?', ['Apple']);
|
|
60
|
+
console.debug(apple); // { id: 1, name: 'Apple', price: 1.5 }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Example 3: Export / Import
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
await sqlite.db.create('myApp');
|
|
67
|
+
await sqlite.query.run('myApp', 'CREATE TABLE todos (id INTEGER PRIMARY KEY, task TEXT)');
|
|
68
|
+
await sqlite.data.set('myApp', 'INSERT INTO todos (task) VALUES (?)', ['Write docs']);
|
|
69
|
+
|
|
70
|
+
// Export the in-memory database to a portable binary dump
|
|
71
|
+
const dump = await sqlite.db.export('myApp');
|
|
72
|
+
|
|
73
|
+
// Later... import it back
|
|
74
|
+
await sqlite.db.import('restored', dump);
|
|
75
|
+
const rows = await sqlite.query.select('restored', 'SELECT * FROM todos');
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Example 4: Engine control
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
// Configure the wasm location BEFORE first use (sets the locateFile base)
|
|
82
|
+
sqlite.config({ wasmUrl: '/static/sql.js/' });
|
|
83
|
+
|
|
84
|
+
// Or provide a fully custom loader (e.g. a local/npm build of sql.js)
|
|
85
|
+
sqlite.config({ loader: async () => {
|
|
86
|
+
return await import('sql.js'); // local install - resolves at runtime
|
|
87
|
+
}});
|
|
88
|
+
|
|
89
|
+
// Enable automatic persistence of one or more databases (see Example 5)
|
|
90
|
+
sqlite.config({ persistence: true });
|
|
91
|
+
|
|
92
|
+
// Wait until the engine is ready
|
|
93
|
+
await sqlite.ready;
|
|
94
|
+
console.debug('SQLite version:', sqlite.db.version());
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Example 5: Persistence & dev download
|
|
98
|
+
|
|
99
|
+
> **Important:** sql.js databases live in **WebAssembly memory** - they are
|
|
100
|
+
> in-memory and **volatile** (lost on page refresh) unless you persist them.
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
// Opt into auto-persistence at create time (global config or per-create)
|
|
104
|
+
await sqlite.db.create('app', { persistence: true });
|
|
105
|
+
|
|
106
|
+
await sqlite.query.run('app', 'CREATE TABLE notes (id INTEGER PRIMARY KEY, body TEXT)');
|
|
107
|
+
// writes are snapshotted to localStorage automatically (debounced via updateHook)
|
|
108
|
+
|
|
109
|
+
await sqlite.db.persist('app'); // force an immediate snapshot
|
|
110
|
+
// After a refresh, reopening restores the data:
|
|
111
|
+
await sqlite.db.create('app', { persistence: true });
|
|
112
|
+
|
|
113
|
+
// Dev convenience: download the current db as a .sqlite file from the browser
|
|
114
|
+
await sqlite.db.download('app', 'app.sqlite');
|
|
115
|
+
|
|
116
|
+
// Flush + persist + release the handle
|
|
117
|
+
await sqlite.db.close('app');
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Persistence is stored on `store` (localStorage, namespaced per
|
|
121
|
+
`sqlite.config({ namespace })` / memorio context) as a base64 snapshot under
|
|
122
|
+
`memorio:sqlite:db:<ns>:<name>`. It is best-effort: if `store` is unavailable
|
|
123
|
+
the database simply behaves as in-memory.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## API Reference
|
|
128
|
+
|
|
129
|
+
### Engine Control
|
|
130
|
+
|
|
131
|
+
| Method | Parameters | Returns | Description |
|
|
132
|
+
|--------|------------|---------|-------------|
|
|
133
|
+
| `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
|
+
| `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`. |
|
|
136
|
+
| `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>` | Persist (if enabled), close, and release the handle. |
|
|
138
|
+
| `sqlite.ready` | none | `Promise<void>` | Resolves once `sql.js` has been initialized. Rejects (and sets `_disabled`) if the engine can't load. |
|
|
139
|
+
| `sqlite.db.version()` | none | `string \| null` | Engine version, available after initialization. |
|
|
140
|
+
| `sqlite._disabled` | none | `boolean` | `true` when the module is disabled (non-browser env / load failure). |
|
|
141
|
+
| `sqlite._warning` | none | `string \| undefined` | Reason text when disabled, if applicable. |
|
|
142
|
+
|
|
143
|
+
### Database Methods
|
|
144
|
+
|
|
145
|
+
| Method | Parameters | Returns | Description |
|
|
146
|
+
|--------|------------|---------|-------------|
|
|
147
|
+
| `sqlite.db.support()` | none | `boolean` | Check whether SQLite can run in this environment. |
|
|
148
|
+
| `sqlite.db.create(name, opts?)` | `name: string`, `opts?: { data }` | `Promise<Database>` | Create an in-memory database (or reopen one from a binary dump). |
|
|
149
|
+
| `sqlite.db.get(name)` | `name: string` | `Database` | Retrieve an open database handle. |
|
|
150
|
+
| `sqlite.db.delete(name)` | `name: string` | `boolean` | Close and remove a database handle. |
|
|
151
|
+
| `sqlite.db.list()` | none | `string[]` | List open database names. |
|
|
152
|
+
| `sqlite.db.size(name?)` | `name?: string` | `Promise<number>` | Size in bytes of one or all databases. |
|
|
153
|
+
| `sqlite.db.export(name)` | `name: string` | `Promise<Uint8Array>` | Export a database to a binary dump. |
|
|
154
|
+
| `sqlite.db.import(name, data)` | `name: string`, `data` | `Promise<Database>` | Create/replace a database from a binary dump. |
|
|
155
|
+
|
|
156
|
+
### Query Methods
|
|
157
|
+
|
|
158
|
+
| Method | Parameters | Returns | Description |
|
|
159
|
+
|--------|------------|---------|-------------|
|
|
160
|
+
| `sqlite.query.run(name, sql, params?)` | `name: string`, `sql: string`, `params?: any[]` | `Promise<number>` | Run a statement that does not return rows (INSERT / UPDATE / DELETE / CREATE). Returns modified-row count. |
|
|
161
|
+
| `sqlite.query.select(name, sql, params?)` | `name: string`, `sql: string`, `params?: any[]` | `Promise<object[]>` | Run a query and return the rows as plain objects. |
|
|
162
|
+
|
|
163
|
+
### Data Methods (CRUD shortcuts)
|
|
164
|
+
|
|
165
|
+
| Method | Parameters | Returns | Description |
|
|
166
|
+
|--------|------------|---------|-------------|
|
|
167
|
+
| `sqlite.data.set(name, sql, params?)` | `name: string`, `sql: string`, `params?: any[]` | `Promise<number>` | Alias of `sqlite.query.run`. |
|
|
168
|
+
| `sqlite.data.get(name, sql, params?)` | `name: string`, `sql: string`, `params?: any[]` | `Promise<object \| null>` | Alias of `sqlite.query.select` returning the first row (or `null`). |
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Platform Support
|
|
173
|
+
|
|
174
|
+
| Platform | Support | Notes |
|
|
175
|
+
|----------|---------|-------|
|
|
176
|
+
| Browser | ✅ Full | Requires WebAssembly + the `sql.js` package (or CDN fallback) |
|
|
177
|
+
| Edge Worker | ⚠️ Limited | WebAssembly may be available; configure a `loader` manually |
|
|
178
|
+
| Node.js | ❌ Not available | Use `store` or `session` instead |
|
|
179
|
+
| Deno | ❌ Not available | Use `store` or `session` instead |
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Best Practices
|
|
184
|
+
|
|
185
|
+
1. Configure the wasm path for production: `sqlite.config({ wasmUrl })` or `sqlite.config({ loader })`.
|
|
186
|
+
2. Create one named database per feature and reuse the handle: `const db = await sqlite.db.create('app')`.
|
|
187
|
+
3. Always release databases you no longer need: `sqlite.db.delete('temp')`.
|
|
188
|
+
4. Use `await sqlite.ready` before running statements to ensure the engine is loaded.
|
|
189
|
+
5. Use `?` placeholders and `params` to avoid SQL injection.
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
> **Status:** Published
|
|
2
|
+
> **Date:** 2026-09-12
|
|
3
|
+
> **Scope**: API Reference
|
|
4
|
+
> **Standard**: Memorio API Specification v5
|
|
5
|
+
>
|
|
6
|
+
---
|
|
7
|
+
# State - Memorio
|
|
8
|
+
|
|
9
|
+
> ✅ **Universal**: Works in Browser, Node.js, Deno, and Edge Workers
|
|
10
|
+
|
|
11
|
+
State is a reactive global state manager using JavaScript Proxies. It's simple, powerful, and requires no setup. Data persists only in memory during the session.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install memorio
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
import { state } from 'memorio';
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
That's it. `state` is ready to use.
|
|
24
|
+
|
|
25
|
+
> **Classic `import`**: `state` is also available as a named export from the global entrypoint.
|
|
26
|
+
> `import 'memorio/global'` exposes the same proxy as `globalThis.state`.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Quick Examples
|
|
31
|
+
|
|
32
|
+
### Example 1: Basic Usage
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
// Set a value
|
|
36
|
+
state.name = 'Mario';
|
|
37
|
+
state.age = 25;
|
|
38
|
+
|
|
39
|
+
// Get a value
|
|
40
|
+
console.debug(state.name); // "Mario"
|
|
41
|
+
|
|
42
|
+
// Simple object
|
|
43
|
+
state.user = { name: 'Luigi', level: 1 };
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Example 2: Intermediate
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
// Array operations
|
|
50
|
+
state.items = [1, 2, 3];
|
|
51
|
+
state.items.push(4);
|
|
52
|
+
console.debug(state.items); // [1, 2, 3, 4]
|
|
53
|
+
|
|
54
|
+
// Nested objects
|
|
55
|
+
state.config = { theme: 'dark', lang: 'en' };
|
|
56
|
+
state.config.theme = 'light';
|
|
57
|
+
|
|
58
|
+
// List all states
|
|
59
|
+
console.debug(state.list);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Example 3: Advanced
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
// Lock state to prevent modifications
|
|
66
|
+
state.frozenConfig = { maxUsers: 100 };
|
|
67
|
+
state.frozenConfig.lock();
|
|
68
|
+
// Now state.frozenConfig cannot be modified
|
|
69
|
+
|
|
70
|
+
// Path tracking
|
|
71
|
+
const path = state.user.path;
|
|
72
|
+
console.debug(path.name); // "user"
|
|
73
|
+
console.debug(path.profile.name); // "user.profile"
|
|
74
|
+
|
|
75
|
+
// Get full path as string
|
|
76
|
+
console.debug(state.user.__path); // "state.user"
|
|
77
|
+
|
|
78
|
+
// Protected keys (internal use)
|
|
79
|
+
console.debug(protect); // Array of protected keys
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## API Reference
|
|
85
|
+
|
|
86
|
+
### Properties
|
|
87
|
+
|
|
88
|
+
| Property | Type | Description |
|
|
89
|
+
|----------|------|-------------|
|
|
90
|
+
| `state.list` | Array | Get all current state keys (deep copy) |
|
|
91
|
+
| `state.path` | Object | Get path tracker for current location |
|
|
92
|
+
| `state.__path` | string | Get full path as string |
|
|
93
|
+
|
|
94
|
+
### Methods
|
|
95
|
+
|
|
96
|
+
| Method | Parameters | Description |
|
|
97
|
+
|--------|------------|-------------|
|
|
98
|
+
| `state.remove(key)` | `key: string` | Remove a specific state |
|
|
99
|
+
| `state.removeAll()` | none | Clear all states |
|
|
100
|
+
|
|
101
|
+
### Lock
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
// Lock an object or array
|
|
105
|
+
state.myArray = [1, 2, 3];
|
|
106
|
+
state.myArray.lock();
|
|
107
|
+
|
|
108
|
+
// Now any modification will fail
|
|
109
|
+
state.myArray.push(4); // Error: state 'myArray' is locked
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## How It Works
|
|
115
|
+
|
|
116
|
+
Memorio uses JavaScript `Proxy` to intercept get/set operations on the global `state` object. This allows:
|
|
117
|
+
|
|
118
|
+
1. **Reactivity** - Any change can trigger observers
|
|
119
|
+
2. **Nested objects** - Deep path tracking
|
|
120
|
+
3. **Type safety** - Full TypeScript support
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Platform Notes
|
|
125
|
+
|
|
126
|
+
| Platform | Support | Notes |
|
|
127
|
+
|----------|---------|-------|
|
|
128
|
+
| Browser | ✅ Full | In-memory, lost on refresh |
|
|
129
|
+
| Node.js | ✅ Full | In-memory, lost on restart |
|
|
130
|
+
| Deno | ✅ Full | In-memory, lost on restart |
|
|
131
|
+
| Edge Workers | ✅ Full | In-memory, lost on function cold start |
|
|
132
|
+
|
|
133
|
+
**Note**: In server environments (Node.js/Deno), use `memorio.createContext()` for request isolation.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Best Practices
|
|
138
|
+
|
|
139
|
+
1. Use descriptive keys: `state.userProfile` not `state.up`
|
|
140
|
+
2. Group related data: `state.cart.items` not `state.cartItems`
|
|
141
|
+
3. Lock static config: `state.appConfig.lock()`
|
|
142
|
+
4. Clean up on logout: `state.removeAll()`
|
|
143
|
+
5. Use path tracking for debugging: `state.myData.__path`
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Common Errors
|
|
148
|
+
|
|
149
|
+
```javascript
|
|
150
|
+
// Error: protected key
|
|
151
|
+
state._internal = 'value';
|
|
152
|
+
// Output: "key _internal is protected"
|
|
153
|
+
|
|
154
|
+
// Error: locked state
|
|
155
|
+
state.locked = { x: 1 };
|
|
156
|
+
state.locked.lock();
|
|
157
|
+
state.locked.x = 2;
|
|
158
|
+
// Output: "Error: state 'locked' is locked"
|
|
159
|
+
```
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
> **Status:** Published
|
|
2
|
+
> **Date:** 2026-09-12
|
|
3
|
+
> **Scope**: API Reference
|
|
4
|
+
> **Standard**: Memorio API Specification v5
|
|
5
|
+
>
|
|
6
|
+
---
|
|
7
|
+
# Store - Memorio
|
|
8
|
+
|
|
9
|
+
> 🖥️ **Browser & Edge**: Uses localStorage for persistence
|
|
10
|
+
> ⚙️ **Node.js/Deno**: Falls back to in-memory storage (not persistent)
|
|
11
|
+
|
|
12
|
+
Store provides persistent localStorage management with a simple API. Data survives page refreshes and browser restarts.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install memorio
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```javascript
|
|
21
|
+
import { store } from 'memorio';
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
> **Classic `import`**: `store` is also available via the global entrypoint.
|
|
25
|
+
> `import 'memorio/global'` exposes the same instance as `globalThis.store`.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Quick Examples
|
|
30
|
+
|
|
31
|
+
### Example 1: Basic Usage
|
|
32
|
+
|
|
33
|
+
```javascript
|
|
34
|
+
// Save data
|
|
35
|
+
store.set('username', 'Mario');
|
|
36
|
+
store.set('score', 1500);
|
|
37
|
+
|
|
38
|
+
// Read data
|
|
39
|
+
console.debug(store.get('username')); // "Mario"
|
|
40
|
+
console.debug(store.get('score')); // 1500
|
|
41
|
+
|
|
42
|
+
// Check if using real persistence
|
|
43
|
+
console.debug(store.isPersistent); // true in browser, false in Node.js/Deno
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Example 2: Intermediate
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
// Store objects
|
|
50
|
+
store.set('user', { name: 'Luigi', level: 5 });
|
|
51
|
+
const user = store.get('user');
|
|
52
|
+
console.debug(user.name); // "Luigi"
|
|
53
|
+
|
|
54
|
+
// Remove single item
|
|
55
|
+
store.remove('username');
|
|
56
|
+
|
|
57
|
+
// Check size
|
|
58
|
+
const totalSize = store.size();
|
|
59
|
+
console.debug(`${totalSize} bytes`);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Example 3: Advanced
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
// Get storage quota (returns Promise<[usage, quota]> in KB)
|
|
66
|
+
const [used, total] = await store.quota();
|
|
67
|
+
console.debug(`Using ${used} out of ${total} KB`);
|
|
68
|
+
|
|
69
|
+
// Get total size in characters
|
|
70
|
+
const size = store.size();
|
|
71
|
+
console.debug(`${size} bytes`);
|
|
72
|
+
|
|
73
|
+
// Clear all data
|
|
74
|
+
store.removeAll();
|
|
75
|
+
// or use alias
|
|
76
|
+
store.clearAll();
|
|
77
|
+
|
|
78
|
+
// Handle errors gracefully
|
|
79
|
+
try {
|
|
80
|
+
store.set('largeData', hugeObject);
|
|
81
|
+
} catch (err) {
|
|
82
|
+
console.error('Storage full:', err);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## API Reference
|
|
89
|
+
|
|
90
|
+
### Methods
|
|
91
|
+
|
|
92
|
+
| Method | Parameters | Returns | Description |
|
|
93
|
+
|--------|------------|---------|-------------|
|
|
94
|
+
| `store.get(name)` | `name: string` | `any` | Get value from storage |
|
|
95
|
+
| `store.set(name, value)` | `name: string, value: any` | `void` | Save value to storage |
|
|
96
|
+
| `store.remove(name)` | `name: string` | `boolean` | Remove single item |
|
|
97
|
+
| `store.delete(name)` | `name: string` | `boolean` | Alias for remove |
|
|
98
|
+
| `store.removeAll()` | none | `boolean` | Clear all storage |
|
|
99
|
+
| `store.clearAll()` | none | `boolean` | Alias for removeAll |
|
|
100
|
+
| `store.size()` | none | `number` | Get total size in characters |
|
|
101
|
+
| `store.quota()` | none | `Promise<[number, number]>` | Get storage usage/quota in KB |
|
|
102
|
+
|
|
103
|
+
### Properties
|
|
104
|
+
|
|
105
|
+
| Property | Type | Description |
|
|
106
|
+
|----------|------|-------------|
|
|
107
|
+
| `store.isPersistent` | `boolean` | `true` if using real localStorage, `false` if in-memory fallback |
|
|
108
|
+
|
|
109
|
+
### Supported Types
|
|
110
|
+
|
|
111
|
+
```javascript
|
|
112
|
+
// All JSON-serializable types work
|
|
113
|
+
store.set('string', 'hello');
|
|
114
|
+
store.set('number', 42);
|
|
115
|
+
store.set('boolean', true);
|
|
116
|
+
store.set('array', [1, 2, 3]);
|
|
117
|
+
store.set('object', { key: 'value' });
|
|
118
|
+
store.set('null', null);
|
|
119
|
+
store.set('undefined', null); // converted to null
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Not Supported
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
// Functions will log an error
|
|
126
|
+
store.set('myFunc', () => {});
|
|
127
|
+
// Output: "It's not secure to store functions."
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Platform Comparison
|
|
133
|
+
|
|
134
|
+
| Feature | Store | Session | Cache | IDB |
|
|
135
|
+
|---------|-------|---------|-------|-----|
|
|
136
|
+
| **Storage** | localStorage | sessionStorage | Memory | IndexedDB |
|
|
137
|
+
| **Lifetime** | Forever | Until tab closes | Until refresh | Forever |
|
|
138
|
+
| **Capacity** | ~5-10 MB | ~5-10 MB | Unlimited | 50+ MB |
|
|
139
|
+
| **Platform** | Browser/Edge | Browser/Edge | All | Browser |
|
|
140
|
+
| **Persistence** | ✅ true | N/A | ❌ false | ✅ true |
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## How It Works
|
|
145
|
+
|
|
146
|
+
Store wraps the browser's `localStorage` API with:
|
|
147
|
+
|
|
148
|
+
- Automatic JSON serialization/deserialization
|
|
149
|
+
- Error handling for parse failures
|
|
150
|
+
- Size calculation
|
|
151
|
+
- Quota monitoring
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Storage Limits
|
|
156
|
+
|
|
157
|
+
- **Chrome/Safari**: ~5-10 MB
|
|
158
|
+
- **Firefox**: ~10 MB
|
|
159
|
+
- **Edge**: ~5-10 MB
|
|
160
|
+
|
|
161
|
+
Use `store.quota()` to monitor usage.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Best Practices
|
|
166
|
+
|
|
167
|
+
1. Prefix keys: `store.set('app_username', '...')`
|
|
168
|
+
2. Check before set: `if (store.get('key')) { ... }`
|
|
169
|
+
3. Handle quota: Try/catch around large data
|
|
170
|
+
4. Clean up: `store.removeAll()` on logout
|