memorio 4.7.0 → 4.7.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/README.md +302 -188
- package/SECURITY.md +10 -10
- package/SUMMARY.md +14 -0
- package/index.cjs +166 -6
- package/index.d.ts +3 -0
- package/index.js +119 -6
- package/llms.txt +176 -101
- package/markdown/CHANGELOG.md +8 -8
- package/markdown/HISTORY.md +192 -0
- package/markdown/INSPECT.md +116 -0
- package/markdown/MEMORY.md +155 -0
- package/markdown/SCHEMA.md +169 -0
- package/markdown/SECURITY.md +1 -1
- package/markdown/TYPED.md +158 -0
- package/package.json +7 -7
- package/types/exports.d.ts +25 -0
- package/types/history.d.ts +27 -0
- package/types/inspect.d.ts +14 -0
- package/types/memorio.d.ts +48 -2
- package/types/memory.d.ts +70 -0
- package/types/schema.d.ts +53 -0
package/llms.txt
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
npm i memorio
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
> **For AI agents generating code against this library:** default `state` is a shared, global namespace unless a context is explicitly created with `memorio.createContext(id)`. Do not assume per-request or per-tab isolation is automatic - see [Session & Context Isolation](#session--context-isolation) before generating server-side code that handles more than one user/request.
|
|
12
|
+
|
|
11
13
|
## Core Concepts
|
|
12
14
|
|
|
13
15
|
Memorio provides 6 storage modules plus utilities:
|
|
@@ -15,11 +17,11 @@ Memorio provides 6 storage modules plus utilities:
|
|
|
15
17
|
| Module | Purpose | Persistence |
|
|
16
18
|
|--------|---------|-------------|
|
|
17
19
|
| `state` | Reactive, volatile state | In-memory (resets on refresh) |
|
|
18
|
-
| `store` | localStorage persistence | Survives browser refresh |
|
|
19
|
-
| `session` | sessionStorage | Dies with browser tab |
|
|
20
|
+
| `store` | localStorage persistence | Survives browser refresh; falls back to non-durable in-memory `Map` in Node.js/Deno |
|
|
21
|
+
| `session` | sessionStorage | Dies with browser tab; falls back to non-durable in-memory `Map` in Node.js/Deno |
|
|
20
22
|
| `cache` | In-memory cache | Fastest read, no persistence |
|
|
21
|
-
| `idb` | IndexedDB | Structured, async, persistent (browser-only) |
|
|
22
|
-
| `observer` | Object watcher | Legacy |
|
|
23
|
+
| `idb` | IndexedDB | Structured, async, persistent (browser-only - disabled in Node.js/Deno) |
|
|
24
|
+
| `observer` | Object watcher | Legacy; string-based paths, not statically checked against `state`'s shape |
|
|
23
25
|
| `useObserver` | React hook | Auto-discovery of state paths |
|
|
24
26
|
|
|
25
27
|
## Quick Start
|
|
@@ -40,7 +42,7 @@ useObserver(
|
|
|
40
42
|
|
|
41
43
|
## API Reference
|
|
42
44
|
|
|
43
|
-
### `state`
|
|
45
|
+
### `state` - Reactive State
|
|
44
46
|
|
|
45
47
|
Global, Proxy-based, reactive state management.
|
|
46
48
|
|
|
@@ -61,21 +63,23 @@ state.remove('items')
|
|
|
61
63
|
|
|
62
64
|
// Clear all
|
|
63
65
|
state.removeAll()
|
|
64
|
-
|
|
65
|
-
// Lock/unlock for frozen objects
|
|
66
|
-
state.lock() // freeze everything
|
|
67
|
-
state.unlock() // unfreeze
|
|
68
66
|
```
|
|
69
67
|
|
|
68
|
+
**Locking - VERIFY BEFORE PUBLISHING:** this library's own documents currently disagree on scope.
|
|
69
|
+
|
|
70
|
+
- One source describes **per-key** locking: `state.config.lock()` freezes only the `config` key; other keys remain writable.
|
|
71
|
+
- Another source describes **global** locking: `state.lock()` / `state.unlock()` freezing the entire `state` object at once.
|
|
72
|
+
|
|
73
|
+
These are materially different behaviors - confirm against the actual source which one (or both, with distinct method names) is implemented, then replace this note with the real signature(s). Do not ship a docs update, or generate code against this section, until this is resolved.
|
|
74
|
+
|
|
70
75
|
**Features:**
|
|
71
76
|
- Automatic path tracking via `__path` property
|
|
72
77
|
- Nested proxy support
|
|
73
|
-
- Lock/unlock per-key or globally
|
|
74
78
|
- Auto-dispatches events on changes
|
|
75
79
|
|
|
76
|
-
### `store`
|
|
80
|
+
### `store` - localStorage Persistence
|
|
77
81
|
|
|
78
|
-
Persistent storage that survives browser refresh.
|
|
82
|
+
Persistent storage that survives browser refresh. On Node.js/Deno this falls back to an in-memory `Map` that does **not** survive a process restart - treat it as a same-shape cache there, not durable storage.
|
|
79
83
|
|
|
80
84
|
```javascript
|
|
81
85
|
// Set
|
|
@@ -89,15 +93,11 @@ store.list() // { preferences: { theme: 'dark' } }
|
|
|
89
93
|
|
|
90
94
|
// Remove
|
|
91
95
|
store.remove('preferences')
|
|
92
|
-
|
|
93
|
-
// Delete (alias for remove)
|
|
94
|
-
store.delete('preferences')
|
|
96
|
+
store.delete('preferences') // alias
|
|
95
97
|
|
|
96
98
|
// Clear all memorio items
|
|
97
99
|
store.removeAll()
|
|
98
|
-
|
|
99
|
-
// Clear all (alias for removeAll)
|
|
100
|
-
store.clearAll()
|
|
100
|
+
store.clearAll() // alias
|
|
101
101
|
|
|
102
102
|
// Check size
|
|
103
103
|
console.debug(store.size(), 'chars stored')
|
|
@@ -105,13 +105,15 @@ console.debug(store.size(), 'chars stored')
|
|
|
105
105
|
// Check if persistent (real localStorage vs memory fallback)
|
|
106
106
|
console.debug(store.isPersistent) // true → real localStorage
|
|
107
107
|
|
|
108
|
-
// Estimate quota usage
|
|
108
|
+
// Estimate quota usage
|
|
109
109
|
await store.quota() // [usage, quota] in KB
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
> **`store.quota()` currently returns `[0, 0]` for the `localStorage` backend** - it is not a real usage reading for that backend, it's a placeholder. Don't use it to make capacity decisions until it's implemented for `localStorage`; it may be meaningful for other backends (e.g. `idb`), but confirm before relying on it there too.
|
|
113
|
+
|
|
114
|
+
### `session` - sessionStorage
|
|
113
115
|
|
|
114
|
-
Storage that dies when browser tab closes.
|
|
116
|
+
Storage that dies when browser tab closes. Same Node.js/Deno `Map` fallback caveat as `store` applies here.
|
|
115
117
|
|
|
116
118
|
```javascript
|
|
117
119
|
// Set
|
|
@@ -125,15 +127,11 @@ session.list() // { token: 'user-abc-123' }
|
|
|
125
127
|
|
|
126
128
|
// Remove
|
|
127
129
|
session.remove('token')
|
|
128
|
-
|
|
129
|
-
// Delete (alias for remove)
|
|
130
|
-
session.delete('token')
|
|
130
|
+
session.delete('token') // alias
|
|
131
131
|
|
|
132
132
|
// Clear all
|
|
133
133
|
session.removeAll()
|
|
134
|
-
|
|
135
|
-
// Clear all (alias for removeAll)
|
|
136
|
-
session.clearAll()
|
|
134
|
+
session.clearAll() // alias
|
|
137
135
|
|
|
138
136
|
// Check size
|
|
139
137
|
console.debug(session.size(), 'chars stored')
|
|
@@ -142,7 +140,7 @@ console.debug(session.size(), 'chars stored')
|
|
|
142
140
|
console.debug(session.isPersistent)
|
|
143
141
|
```
|
|
144
142
|
|
|
145
|
-
### `cache`
|
|
143
|
+
### `cache` - In-Memory Cache
|
|
146
144
|
|
|
147
145
|
Fastest possible read, data lost on refresh.
|
|
148
146
|
|
|
@@ -161,9 +159,7 @@ cache.remove('temp')
|
|
|
161
159
|
|
|
162
160
|
// Clear all
|
|
163
161
|
cache.clear()
|
|
164
|
-
|
|
165
|
-
// Remove all (alias for clear)
|
|
166
|
-
cache.removeAll()
|
|
162
|
+
cache.removeAll() // alias
|
|
167
163
|
|
|
168
164
|
// Direct access (also works)
|
|
169
165
|
cache['myKey'] = value
|
|
@@ -171,9 +167,9 @@ const value = cache['myKey']
|
|
|
171
167
|
delete cache['myKey']
|
|
172
168
|
```
|
|
173
169
|
|
|
174
|
-
### `idb`
|
|
170
|
+
### `idb` - IndexedDB
|
|
175
171
|
|
|
176
|
-
Structured, persistent, async database (browser-only).
|
|
172
|
+
Structured, persistent, async database (browser-only). **Disabled in Node.js/Deno** - calls will warn and no-op; use `store` or `session` there instead.
|
|
177
173
|
|
|
178
174
|
```javascript
|
|
179
175
|
// Create database
|
|
@@ -200,24 +196,21 @@ const exists = await idb.db.exist('my-db')
|
|
|
200
196
|
// Delete database
|
|
201
197
|
await idb.db.delete('my-db')
|
|
202
198
|
|
|
203
|
-
// Get database size
|
|
199
|
+
// Get database / table size
|
|
204
200
|
const size = await idb.db.size('my-db')
|
|
205
|
-
|
|
206
|
-
// Get table size
|
|
207
201
|
const tableSize = await idb.table.size('my-db', 'users')
|
|
208
202
|
|
|
209
|
-
// Check support
|
|
210
|
-
idb.db.support()
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const [usage, quota] = await idb.db.quota()
|
|
203
|
+
// Check support before calling anything else
|
|
204
|
+
if (idb.db.support()) {
|
|
205
|
+
const [usage, quota] = await idb.db.quota()
|
|
206
|
+
}
|
|
214
207
|
```
|
|
215
208
|
|
|
216
|
-
|
|
209
|
+
Always guard `idb` calls with `idb.db.support()` (or `memorio.getCapabilities().hasIndexedDB`) in code that might run outside a browser - don't rely on the no-op warning alone.
|
|
217
210
|
|
|
218
|
-
### `observer`
|
|
211
|
+
### `observer` - Object Watcher
|
|
219
212
|
|
|
220
|
-
Legacy observer API.
|
|
213
|
+
Legacy observer API. Prefer `useObserver` in React code.
|
|
221
214
|
|
|
222
215
|
```javascript
|
|
223
216
|
// Listen to state changes
|
|
@@ -238,7 +231,9 @@ console.debug(observer.list)
|
|
|
238
231
|
observer.removeAll()
|
|
239
232
|
```
|
|
240
233
|
|
|
241
|
-
|
|
234
|
+
> Paths are plain strings and are not checked against `state`'s actual shape at compile time or at registration time. A typo or a later rename of the corresponding `state` key will fail silently - the observer simply never fires again.
|
|
235
|
+
|
|
236
|
+
### `useObserver` - React Hook
|
|
242
237
|
|
|
243
238
|
Primary way to observe state changes in React components.
|
|
244
239
|
|
|
@@ -266,67 +261,48 @@ function Counter() {
|
|
|
266
261
|
|
|
267
262
|
**Features:**
|
|
268
263
|
- Auto-discovery of state paths during render
|
|
269
|
-
- Returns cleanup function to stop monitoring
|
|
264
|
+
- Returns a cleanup function to stop monitoring
|
|
270
265
|
- Supports both Proxy objects and string paths
|
|
271
266
|
|
|
272
|
-
### `devtools`
|
|
267
|
+
### `devtools` - Inspection Tools
|
|
273
268
|
|
|
274
|
-
|
|
269
|
+
Browser-only (see [Cross-Platform Support](#cross-platform-support)); no-ops or unavailable in Node.js/Deno.
|
|
275
270
|
|
|
276
271
|
```javascript
|
|
277
|
-
//
|
|
278
|
-
memorio.devtools.
|
|
279
|
-
|
|
280
|
-
// Get stats
|
|
281
|
-
memorio.devtools.stats() // { stateKeys, storeKeys, sessionKeys, ... }
|
|
282
|
-
|
|
283
|
-
// Clear specific module
|
|
272
|
+
memorio.devtools.inspect() // pretty-print state, store, session, cache
|
|
273
|
+
memorio.devtools.stats() // { stateKeys, storeKeys, sessionKeys, ... }
|
|
284
274
|
memorio.devtools.clear('state')
|
|
285
|
-
|
|
286
|
-
// Clear all modules
|
|
287
275
|
memorio.devtools.clearAll()
|
|
288
|
-
|
|
289
|
-
// Export all data as JSON
|
|
290
276
|
memorio.devtools.exportData()
|
|
291
|
-
|
|
292
|
-
// Import data from JSON
|
|
293
277
|
memorio.devtools.importData(jsonString)
|
|
294
|
-
|
|
295
|
-
// Show help
|
|
296
278
|
memorio.devtools.help()
|
|
297
279
|
|
|
298
280
|
// Console shortcuts
|
|
299
|
-
$state //
|
|
300
|
-
$store //
|
|
301
|
-
$session //
|
|
302
|
-
$cache //
|
|
281
|
+
$state // globalThis.state
|
|
282
|
+
$store // globalThis.store
|
|
283
|
+
$session // globalThis.session
|
|
284
|
+
$cache // globalThis.cache
|
|
303
285
|
```
|
|
304
286
|
|
|
305
|
-
### `logger`
|
|
287
|
+
### `logger` - Change Tracking
|
|
306
288
|
|
|
307
|
-
|
|
289
|
+
Records every write it's configured to track, with timestamps - including whatever values you pass in.
|
|
308
290
|
|
|
309
291
|
```javascript
|
|
310
|
-
// Configure logger
|
|
311
292
|
memorio.logger.configure({
|
|
312
293
|
enabled: true,
|
|
313
294
|
logToConsole: true,
|
|
314
295
|
modules: ['state', 'store', 'session', 'cache', 'idb']
|
|
315
296
|
})
|
|
316
297
|
|
|
317
|
-
//
|
|
318
|
-
memorio.logger.
|
|
319
|
-
|
|
320
|
-
// Get stats
|
|
321
|
-
memorio.logger.getStats() // { total, state, store, session, cache, idb, set, get, ... }
|
|
322
|
-
|
|
323
|
-
// Clear history
|
|
298
|
+
memorio.logger.getHistory() // [{ timestamp, module, action, path, value }, ...]
|
|
299
|
+
memorio.logger.getStats() // { total, state, store, session, cache, idb, set, get, ... }
|
|
324
300
|
memorio.logger.clearHistory()
|
|
325
|
-
|
|
326
|
-
// Export logs
|
|
327
|
-
memorio.logger.exportLogs() // JSON string of all history
|
|
301
|
+
memorio.logger.exportLogs() // JSON string of all history
|
|
328
302
|
```
|
|
329
303
|
|
|
304
|
+
> The `value` field in each history entry is whatever was written - tokens, PII, anything. Don't enable `logger` unconditionally in production paths that handle sensitive data, and don't wire `exportLogs()` output anywhere it could leak (analytics, error reporters, support tooling) without redaction.
|
|
305
|
+
|
|
330
306
|
## Platform Detection
|
|
331
307
|
|
|
332
308
|
Access via `memorio.*` after `import 'memorio'`:
|
|
@@ -339,14 +315,10 @@ memorio.isEdge() // true in Cloudflare Workers, Vercel Edge
|
|
|
339
315
|
|
|
340
316
|
const caps = memorio.getCapabilities()
|
|
341
317
|
// { platform: 'browser', hasLocalStorage: true, hasIndexedDB: true, sessionId: 'uuid', ... }
|
|
342
|
-
|
|
343
|
-
// Create isolated context
|
|
344
|
-
memorio.createContext('tenant-name')
|
|
345
|
-
memorio.listContexts()
|
|
346
|
-
memorio.deleteContext('context-id')
|
|
347
|
-
memorio.isolate('tenant-name') // alias for createContext
|
|
348
318
|
```
|
|
349
319
|
|
|
320
|
+
Prefer checking `getCapabilities()` over assuming a platform from context - especially before calling `idb` or relying on `store`/`session` durability.
|
|
321
|
+
|
|
350
322
|
## Cross-Platform Support
|
|
351
323
|
|
|
352
324
|
| Module | Browser | Node.js | Deno | Edge/Workers |
|
|
@@ -354,32 +326,135 @@ memorio.isolate('tenant-name') // alias for createContext
|
|
|
354
326
|
| `state` | ✅ | ✅ | ✅ | ✅ |
|
|
355
327
|
| `observer` / `useObserver` | ✅ | ✅ | ✅ | ✅ |
|
|
356
328
|
| `cache` | ✅ | ✅ | ✅ | ✅ |
|
|
357
|
-
| `store` | ✅ localStorage | ⚠️
|
|
358
|
-
| `session` | ✅ sessionStorage | ⚠️
|
|
359
|
-
| `idb` | ✅ IndexedDB | ❌ | ❌ | ⚠️ |
|
|
329
|
+
| `store` | ✅ `localStorage` | ⚠️ `Map`, not durable | ⚠️ `Map`, not durable | ✅ `localStorage` where available, else `Map` |
|
|
330
|
+
| `session` | ✅ `sessionStorage` | ⚠️ `Map`, not durable | ⚠️ `Map`, not durable | ✅ `sessionStorage` where available, else `Map` |
|
|
331
|
+
| `idb` | ✅ `IndexedDB` | ❌ disabled | ❌ disabled | ⚠️ check `getCapabilities()` |
|
|
360
332
|
| `devtools` | ✅ | ❌ | ❌ | ⚠️ |
|
|
361
333
|
|
|
362
|
-
|
|
334
|
+
## Session & Context Isolation
|
|
363
335
|
|
|
364
|
-
|
|
336
|
+
By default, `state` is a **shared global namespace** - a value set in one place is visible everywhere else that reads `state` in the same process. There is no automatic per-tab or per-request isolation of `state` itself.
|
|
365
337
|
|
|
366
|
-
|
|
338
|
+
To isolate a slice of state (e.g. per tenant, per request), create an explicit context:
|
|
367
339
|
|
|
368
340
|
```javascript
|
|
369
|
-
|
|
370
|
-
|
|
341
|
+
const ctx = memorio.createContext('tenant-name')
|
|
342
|
+
ctx.state.user = { name: 'Isolated' }
|
|
343
|
+
|
|
344
|
+
console.debug(state.user) // undefined - separate namespace from ctx.state
|
|
345
|
+
|
|
371
346
|
memorio.listContexts()
|
|
372
347
|
memorio.deleteContext('context-id')
|
|
373
348
|
memorio.isolate('tenant-name') // alias for createContext
|
|
374
349
|
```
|
|
375
350
|
|
|
351
|
+
Isolation is implemented as a **key-prefix convention** inside the same underlying storage, not a hard memory or process boundary. In a shared Node.js process or an edge isolate that may be reused across requests:
|
|
352
|
+
|
|
353
|
+
- generate context IDs from trusted server-side data, never directly from client-controlled input, to prevent collisions or spoofing;
|
|
354
|
+
- don't treat this as your only isolation layer for data that must not cross tenants - enforce that at the process/request level as well.
|
|
355
|
+
|
|
356
|
+
`getCapabilities().sessionId` provides a per-session identifier for browser contexts but is not itself an isolation mechanism - use `createContext` for that.
|
|
357
|
+
|
|
358
|
+
### `memorio.typed<T>()` - Typed Store (compile-time safety)
|
|
359
|
+
|
|
360
|
+
Returns the global `state` proxy cast to type `T`. The same Proxy instance — no overhead. Use for TypeScript autocomplete and static type checking.
|
|
361
|
+
|
|
362
|
+
```javascript
|
|
363
|
+
const app = memorio.typed<AppState>()
|
|
364
|
+
app.user = { name: 'Sara', age: 30 } // type-checked
|
|
365
|
+
app.user = { name: 42 } // ❌ compile error
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### `memorio.registerSchema()` - Schema Validation (runtime safety)
|
|
369
|
+
|
|
370
|
+
Register validators for state paths. Writes that violate a schema are rejected before being stored.
|
|
371
|
+
|
|
372
|
+
```javascript
|
|
373
|
+
memorio.registerSchema('user', {
|
|
374
|
+
type: 'object',
|
|
375
|
+
required: ['name', 'email'],
|
|
376
|
+
properties: {
|
|
377
|
+
name: { type: 'string', min: 1 },
|
|
378
|
+
email: { type: 'string', pattern: /^[^@]+@[^@]+$/ }
|
|
379
|
+
}
|
|
380
|
+
})
|
|
381
|
+
|
|
382
|
+
state.user = { name: 'Sara' } // rejected: missing 'email'
|
|
383
|
+
state.user = { name: 'Sara', email: 'sara@test.com' } // accepted
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
Custom validators:
|
|
387
|
+
|
|
388
|
+
```javascript
|
|
389
|
+
memorio.registerSchema('theme', (val) =>
|
|
390
|
+
val === 'light' || val === 'dark' ? true : 'must be light or dark'
|
|
391
|
+
)
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
Manual validation and management:
|
|
395
|
+
|
|
396
|
+
```javascript
|
|
397
|
+
memorio.validate('user', value) // { valid: true } or { valid: false, errors: [...] }
|
|
398
|
+
memorio.listSchemas() // ['user', 'theme']
|
|
399
|
+
memorio.unregisterSchema('theme') // removes validator
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Combine `typed<T>()` + `registerSchema()` for both compile-time and runtime safety.
|
|
403
|
+
|
|
404
|
+
### `memorio.snapshot()` / `memorio.diff()` - Time Travel
|
|
405
|
+
|
|
406
|
+
```javascript
|
|
407
|
+
memorio.enableHistory()
|
|
408
|
+
|
|
409
|
+
const snap = memorio.snapshot()
|
|
410
|
+
state.user.name = 'Luigi'
|
|
411
|
+
state.counter = 100
|
|
412
|
+
|
|
413
|
+
const changes = memorio.diff(snap)
|
|
414
|
+
// [{ path: 'user.name', oldValue: 'Sara', newValue: 'Luigi' }, ...]
|
|
415
|
+
|
|
416
|
+
memorio.rollback(snap) // restore to snapshot
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### `memorio.undo()` / `memorio.redo()` - Undo/Redo
|
|
420
|
+
|
|
421
|
+
```javascript
|
|
422
|
+
state.a = 1; state.b = 2; state.c = 3
|
|
423
|
+
memorio.undo() // removes state.c
|
|
424
|
+
memorio.undo() // removes state.b
|
|
425
|
+
memorio.redo() // restores state.b
|
|
426
|
+
memorio.canUndo() // true
|
|
427
|
+
memorio.canRedo() // true
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### `memorio.trace()` - Mutation Log
|
|
431
|
+
|
|
432
|
+
```javascript
|
|
433
|
+
memorio.trace()
|
|
434
|
+
// [{ path, action, newValue, previousValue, timestamp }, ...]
|
|
435
|
+
memorio.clearHistory()
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### `memorio.stateKeys()` / `memorio.pathExists()` / `memorio.stateSchema()` - Introspection
|
|
439
|
+
|
|
440
|
+
```javascript
|
|
441
|
+
memorio.stateKeys() // ['user', 'counter']
|
|
442
|
+
memorio.pathExists('user.name') // true or false
|
|
443
|
+
memorio.stateType('user.name') // 'string'
|
|
444
|
+
memorio.stateSchema() // [{ path, type, defined }, ...] - full tree report
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
376
449
|
## Security
|
|
377
450
|
|
|
378
|
-
- Zero production dependencies
|
|
379
|
-
-
|
|
380
|
-
-
|
|
381
|
-
-
|
|
382
|
-
-
|
|
451
|
+
- Zero production dependencies.
|
|
452
|
+
- No `eval`, no dynamic code execution, no obfuscation, no hardcoded secrets.
|
|
453
|
+
- Inputs validated, keys sanitized before use.
|
|
454
|
+
- Secure random session IDs via `crypto.randomUUID`.
|
|
455
|
+
- Data in `store`, `session`, and `idb` is **not encrypted** - these are thin wrappers over browser storage APIs that persist data in the clear on the user's device. Add your own encryption layer before storing tokens, secrets, or regulated personal data there.
|
|
456
|
+
|
|
457
|
+
Engineering practices are informed by recognized guidance (e.g. NIST SP 800-53 practices) as a design input - this is a statement about how the library is built, not a compliance certification, and no third-party audit has been performed. Report security issues privately (see `SECURITY.md`) rather than in a public issue.
|
|
383
458
|
|
|
384
459
|
## License
|
|
385
460
|
|
|
@@ -387,9 +462,9 @@ MIT © Dario Passariello (BigLogic Inc Canada)
|
|
|
387
462
|
|
|
388
463
|
## Utilities
|
|
389
464
|
|
|
390
|
-
### `memorio.dispatch`
|
|
465
|
+
### `memorio.dispatch` - Event Dispatch System
|
|
391
466
|
|
|
392
|
-
Internal event system used by state changes.
|
|
467
|
+
Internal event system used by state changes; also usable directly for custom events.
|
|
393
468
|
|
|
394
469
|
```javascript
|
|
395
470
|
// Dispatch a custom event
|
package/markdown/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## v4.6.1 (Security Patch) - 2026-08-14
|
|
7
|
+
## v4.6.1 (Security Patch) - 2026-08-14 - CRITICAL Security Fix
|
|
8
8
|
|
|
9
9
|
### 🔐 Security NOTICE (v4.6.0)
|
|
10
10
|
|
|
@@ -32,7 +32,7 @@ The hardcoded token `2f398d5d7a734781e96108fdd0dbbabad41ef77a` has been removed
|
|
|
32
32
|
|
|
33
33
|
---
|
|
34
34
|
|
|
35
|
-
## v4.6.0 (Previous - SECURITY ISSUE) - 2026-08-13
|
|
35
|
+
## v4.6.0 (Previous - SECURITY ISSUE) - 2026-08-13 - Refactoring & Documentation
|
|
36
36
|
|
|
37
37
|
**⚠️ WARNING**: This version had a hardcoded PAT token that was later remediated in v4.6.1**
|
|
38
38
|
|
|
@@ -75,7 +75,7 @@ The hardcoded token `2f398d5d7a734781e96108fdd0dbbabad41ef77a` has been removed
|
|
|
75
75
|
|
|
76
76
|
---
|
|
77
77
|
|
|
78
|
-
## v3.0.2 (Current) - 2026-05-19
|
|
78
|
+
## v3.0.2 (Current) - 2026-05-19 - Bug Fix, Security & API Expansion
|
|
79
79
|
|
|
80
80
|
### 🐛 Bug Fixes
|
|
81
81
|
|
|
@@ -98,9 +98,9 @@ The hardcoded token `2f398d5d7a734781e96108fdd0dbbabad41ef77a` has been removed
|
|
|
98
98
|
|
|
99
99
|
- Added JSDoc to `observerFunction` in `functions/observer/index.ts`
|
|
100
100
|
- Added JSDoc to `cache` global in `functions/cache/index.ts`
|
|
101
|
-
- `lint` and `tsc` pass clean
|
|
101
|
+
- `lint` and `tsc` pass clean - 0 vulnerabilities from `npm audit`
|
|
102
102
|
|
|
103
|
-
### 🆕 API
|
|
103
|
+
### 🆕 API - New in 3.0.2
|
|
104
104
|
|
|
105
105
|
| Function | Description |
|
|
106
106
|
|----------|-------------|
|
|
@@ -136,10 +136,10 @@ The hardcoded token `2f398d5d7a734781e96108fdd0dbbabad41ef77a` has been removed
|
|
|
136
136
|
|
|
137
137
|
---
|
|
138
138
|
|
|
139
|
-
## v2.9.0
|
|
139
|
+
## v2.9.0 - 2026-05-13
|
|
140
140
|
|
|
141
141
|
### Added
|
|
142
|
-
- DevTools
|
|
142
|
+
- DevTools - `memorio.devtools.inspect()`, `stats()`, `exportData()`
|
|
143
143
|
- Logger with full history, stats and export
|
|
144
144
|
- Platform detection (`isBrowser`, `isNode`, `isDeno`, `isEdge`, `getCapabilities`)
|
|
145
145
|
- Session isolation via `crypto.randomUUID()`
|
|
@@ -154,7 +154,7 @@ The hardcoded token `2f398d5d7a734781e96108fdd0dbbabad41ef77a` has been removed
|
|
|
154
154
|
|
|
155
155
|
---
|
|
156
156
|
|
|
157
|
-
## v2.5.0
|
|
157
|
+
## v2.5.0 - 2026-02-17
|
|
158
158
|
|
|
159
159
|
- Initial release of memorio (state, store, session, cache, idb)
|
|
160
160
|
- Observer pattern (`observer`)
|