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.
Files changed (82) hide show
  1. package/AGENTS.md +3 -3
  2. package/README.md +95 -516
  3. package/SECURITY.md +159 -33
  4. package/SUMMARY.md +59 -45
  5. package/adr/001-state-proxy-model.md +95 -0
  6. package/adr/002-observer-semantics.md +179 -0
  7. package/adr/003-deep-mutation-semantics.md +128 -0
  8. package/adr/004-array-mutation-semantics.md +127 -0
  9. package/adr/005-scheduler-contract.md +148 -0
  10. package/adr/006-context-isolation.md +91 -0
  11. package/adr/007-mutation-records.md +117 -0
  12. package/adr/008-transactions.md +105 -0
  13. package/adr/009-history-model.md +109 -0
  14. package/adr/README.md +46 -0
  15. package/adr/template.md +48 -0
  16. package/bin/cli.js +68 -0
  17. package/examples/basic.ts +115 -115
  18. package/examples/browser-vanilla.html +358 -358
  19. package/examples/cache.ts +72 -72
  20. package/examples/cross-platform-guards.ts +57 -57
  21. package/examples/history.ts +104 -0
  22. package/examples/idb.ts +109 -109
  23. package/examples/multi-tenant-context.ts +44 -44
  24. package/examples/node-server.ts +308 -308
  25. package/examples/observer.ts +60 -60
  26. package/examples/platform.ts +115 -115
  27. package/examples/react-app.tsx +362 -362
  28. package/examples/react-observer.tsx +63 -63
  29. package/examples/semantic-memory.ts +60 -60
  30. package/examples/session-advanced.ts +91 -91
  31. package/examples/sqlite-batched-writes.ts +57 -57
  32. package/examples/state-advanced.ts +89 -89
  33. package/examples/store-advanced.ts +117 -117
  34. package/examples/sync.ts +90 -0
  35. package/examples/typed-and-schema.ts +102 -100
  36. package/examples/useObserver.tsx +140 -141
  37. package/global.cjs +5733 -0
  38. package/global.d.ts +8 -0
  39. package/global.js +5667 -0
  40. package/index.cjs +2202 -1041
  41. package/index.d.ts +2 -0
  42. package/index.js +2178 -1040
  43. package/llms.txt +113 -8
  44. package/markdown/AUDIT-REPORT.md +134 -0
  45. package/markdown/CACHE.md +191 -0
  46. package/markdown/DEVTOOLS.md +128 -0
  47. package/markdown/DISPATCH.md +176 -0
  48. package/markdown/HISTORY.md +198 -0
  49. package/markdown/IDB.md +177 -0
  50. package/markdown/IMPORT.md +152 -0
  51. package/markdown/INSPECT.md +122 -0
  52. package/markdown/LOGGER.md +153 -0
  53. package/markdown/MEMORY-ATTACHMENT.md +95 -0
  54. package/markdown/MEMORY.md +161 -0
  55. package/markdown/OBSERVER.md +208 -0
  56. package/markdown/PLATFORM.md +277 -0
  57. package/markdown/REDUX.md +54 -0
  58. package/markdown/SCHEMA.md +175 -0
  59. package/markdown/SESSION.md +164 -0
  60. package/markdown/SQLITE.md +189 -0
  61. package/markdown/STATE.md +159 -0
  62. package/markdown/STORE.md +170 -0
  63. package/markdown/SYNC.md +318 -0
  64. package/markdown/TYPED.md +164 -0
  65. package/markdown/USEOBSERVER.md +256 -0
  66. package/modules/redux.cjs +701 -177
  67. package/modules/redux.cjs.map +1 -1
  68. package/modules/redux.js +701 -177
  69. package/modules/redux.js.map +1 -1
  70. package/package.json +26 -4
  71. package/types/broadcast.d.ts +61 -0
  72. package/types/computed.d.ts +96 -0
  73. package/types/encryption.d.ts +129 -0
  74. package/types/env.d.ts +19 -9
  75. package/types/exports.d.ts +29 -0
  76. package/types/history.d.ts +13 -1
  77. package/types/memorio.d.ts +25 -6
  78. package/types/mutation.d.ts +75 -0
  79. package/types/security.d.ts +67 -0
  80. package/types/session.d.ts +23 -5
  81. package/types/store.d.ts +19 -3
  82. 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