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
package/llms.txt
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
**Memorio** is
|
|
5
|
+
**Memorio** is the memory layer for AI agents and apps - owned by the user, not the vendor. It manages application state, remembers how it changed, understands causal relationships, enables deterministic replay, and can simulate the impact of future changes. It provides reactive state, persistence, observation, and optional AES-GCM encryption capabilities with zero production dependencies. It works in Node.js, Deno, browsers, and edge environments.
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
npm i memorio
|
|
@@ -21,13 +21,17 @@ 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 |
|
|
24
25
|
| `observer` | Object watcher | Legacy; string-based paths, not statically checked against `state`'s shape |
|
|
25
26
|
| `useObserver` | React hook | Auto-discovery of state paths |
|
|
27
|
+
| `encryption` | AES-GCM + PBKDF2 | Encrypt/decrypt values, store/session integration |
|
|
26
28
|
|
|
27
29
|
## Quick Start
|
|
28
30
|
|
|
31
|
+
Memorio does not expose APIs on `globalThis` by default. Use explicit named imports for normal application code:
|
|
32
|
+
|
|
29
33
|
```javascript
|
|
30
|
-
import 'memorio'
|
|
34
|
+
import { state, useObserver } from 'memorio'
|
|
31
35
|
|
|
32
36
|
// Set reactive state
|
|
33
37
|
state.user = { name: 'Sara', role: 'admin' }
|
|
@@ -40,6 +44,15 @@ useObserver(
|
|
|
40
44
|
)
|
|
41
45
|
```
|
|
42
46
|
|
|
47
|
+
```note
|
|
48
|
+
To opt in to global access (state, store, session, cache, idb, sqlite, observer, useObserver on `globalThis`), use the explicit global entrypoint:
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
import 'memorio/global'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
This is independent of bundler environment detection (no `import.meta.env.DEV`, no `process.env.NODE_ENV` checks).
|
|
55
|
+
|
|
43
56
|
## API Reference
|
|
44
57
|
|
|
45
58
|
### `state` - Reactive State
|
|
@@ -238,7 +251,7 @@ observer.removeAll()
|
|
|
238
251
|
Primary way to observe state changes in React components.
|
|
239
252
|
|
|
240
253
|
```jsx
|
|
241
|
-
import 'memorio'
|
|
254
|
+
import { useObserver, state } from 'memorio'
|
|
242
255
|
import { useReducer } from 'react'
|
|
243
256
|
|
|
244
257
|
function Counter() {
|
|
@@ -305,7 +318,7 @@ memorio.logger.exportLogs() // JSON string of all history
|
|
|
305
318
|
|
|
306
319
|
## Platform Detection
|
|
307
320
|
|
|
308
|
-
Access via `memorio.*` after `
|
|
321
|
+
Access via `memorio.*` after importing from `memorio`:
|
|
309
322
|
|
|
310
323
|
```javascript
|
|
311
324
|
memorio.isBrowser() // true in Chrome, Firefox, Safari
|
|
@@ -338,23 +351,58 @@ By default, `state` is a **shared global namespace** - a value set in one place
|
|
|
338
351
|
To isolate a slice of state (e.g. per tenant, per request), create an explicit context:
|
|
339
352
|
|
|
340
353
|
```javascript
|
|
354
|
+
// Basic context: namespace isolation via key prefixes
|
|
341
355
|
const ctx = memorio.createContext('tenant-name')
|
|
342
356
|
ctx.state.user = { name: 'Isolated' }
|
|
343
357
|
|
|
344
358
|
console.debug(state.user) // undefined - separate namespace from ctx.state
|
|
345
359
|
|
|
346
|
-
|
|
347
|
-
memorio.
|
|
348
|
-
memorio.
|
|
360
|
+
// Encrypted context: namespace + cryptographic isolation
|
|
361
|
+
const key = await memorio.encryption.deriveKey('tenant-password', 'tenant-salt')
|
|
362
|
+
const ctx = memorio.createContext('tenant-name', { encryptionKey: key })
|
|
363
|
+
await ctx.store.set('secrets', { apiKey: 'sk-12345' }) // encrypted at rest
|
|
364
|
+
const secrets = await ctx.store.get('secrets') // decrypted on read
|
|
349
365
|
```
|
|
350
366
|
|
|
351
367
|
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
368
|
|
|
353
369
|
- generate context IDs from trusted server-side data, never directly from client-controlled input, to prevent collisions or spoofing;
|
|
354
370
|
- 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.
|
|
371
|
+
- when encryption is enabled on a context, encrypted values provide a cryptographic wall on top of the namespace prefix, but key management is your responsibility.
|
|
355
372
|
|
|
356
373
|
`getCapabilities().sessionId` provides a per-session identifier for browser contexts but is not itself an isolation mechanism - use `createContext` for that.
|
|
357
374
|
|
|
375
|
+
### `memorio.encryption` - Encryption (opt-in)
|
|
376
|
+
|
|
377
|
+
Built on the Web Crypto API (`crypto.subtle`). AES-GCM for authenticated encryption, PBKDF2 for password-based key derivation. Works in browsers, Node.js 18+, Deno 1.13+, and modern edge runtimes.
|
|
378
|
+
|
|
379
|
+
```javascript
|
|
380
|
+
// Derive a key from a password (PBKDF2, 600k iterations - NIST SP 800-132)
|
|
381
|
+
const key = await memorio.encryption.deriveKey('password', 'salt')
|
|
382
|
+
|
|
383
|
+
// Or generate a random key
|
|
384
|
+
const key = await memorio.encryption.generateKey()
|
|
385
|
+
|
|
386
|
+
// Encrypt/decrypt
|
|
387
|
+
const envelope = await memorio.encryption.encrypt({ secret: 'value' }, key)
|
|
388
|
+
const original = await memorio.encryption.decrypt(envelope, key)
|
|
389
|
+
|
|
390
|
+
// Password-based convenience (returns JSON string, for direct persistence)
|
|
391
|
+
const json = await memorio.encryption.encryptWithPassword(value, 'password', 'salt')
|
|
392
|
+
const decrypted = await memorio.encryption.decryptWithPassword(json, 'password', 'salt')
|
|
393
|
+
|
|
394
|
+
// Store-level encryption
|
|
395
|
+
await store.set('api_token', secret, { encrypt: key })
|
|
396
|
+
await store.get('api_token', { decrypt: key })
|
|
397
|
+
|
|
398
|
+
// Or configure a default key for transparent encryption
|
|
399
|
+
store.config({ encryptionKey: key })
|
|
400
|
+
await store.set('api_token', secret) // encrypted automatically
|
|
401
|
+
const token = store.get('api_token') // decrypted automatically (returns a Promise)
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
> Encryption is **opt-in** - no layer encrypts by default. Key management is the application's responsibility. Never hardcode keys in client bundles.
|
|
405
|
+
|
|
358
406
|
### `memorio.typed<T>()` - Typed Store (compile-time safety)
|
|
359
407
|
|
|
360
408
|
Returns the global `state` proxy cast to type `T`. The same Proxy instance - no overhead. Use for TypeScript autocomplete and static type checking.
|
|
@@ -429,6 +477,63 @@ memorio.canRedo() // true
|
|
|
429
477
|
|
|
430
478
|
### `memorio.trace()` - Mutation Log
|
|
431
479
|
|
|
480
|
+
Every mutation is recorded as a structured `Mutation` with a unique ID, HLC timestamp, operation, before/after values, source attribution, and optional transaction ID:
|
|
481
|
+
|
|
482
|
+
```javascript
|
|
483
|
+
memorio.enableHistory(true)
|
|
484
|
+
state.user.name = 'Sara'
|
|
485
|
+
|
|
486
|
+
const log = memorio.trace()
|
|
487
|
+
// [{
|
|
488
|
+
// id: 'm_01h...', path: 'user.name', operation: 'set',
|
|
489
|
+
// before: undefined, after: 'Sara',
|
|
490
|
+
// timestamp: 1780000000, hlc: 'hlc:1780000000:00:abc1',
|
|
491
|
+
// action: 'set', newValue: 'Sara', previousValue: undefined,
|
|
492
|
+
// source: undefined, transactionId: undefined
|
|
493
|
+
// }]
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### Mutation Engine (Memorio 5)
|
|
497
|
+
|
|
498
|
+
`memorio.mutate()` records a mutation with source attribution:
|
|
499
|
+
|
|
500
|
+
```javascript
|
|
501
|
+
import { memorio } from 'memorio'
|
|
502
|
+
|
|
503
|
+
memorio.enableHistory(true)
|
|
504
|
+
|
|
505
|
+
const m = memorio.mutate('state.user.role', 'admin', {
|
|
506
|
+
source: 'permissions.enableAdmin'
|
|
507
|
+
})
|
|
508
|
+
console.log(m.id) // "m_01h4f2k7..."
|
|
509
|
+
console.log(m.operation) // "set"
|
|
510
|
+
console.log(m.before) // undefined
|
|
511
|
+
console.log(m.after) // "admin"
|
|
512
|
+
console.log(m.source) // "permissions.enableAdmin"
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
Transactions group related mutations atomically:
|
|
516
|
+
|
|
517
|
+
```javascript
|
|
518
|
+
const tx = memorio.transaction('user.migration', 'Migrate to v2')
|
|
519
|
+
|
|
520
|
+
state.user.role = 'admin'
|
|
521
|
+
state.user.v2 = true
|
|
522
|
+
|
|
523
|
+
memorio.commitTransaction() // or memorio.abortTransaction() to roll back
|
|
524
|
+
|
|
525
|
+
// Named imports for fine-grained control:
|
|
526
|
+
import { beginTransaction, commitTransaction, abortTransaction, currentTransaction } from 'memorio'
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
Patch utilities convert mutations to RFC 6902-style patches for replay, sync, and simulation:
|
|
530
|
+
|
|
531
|
+
```javascript
|
|
532
|
+
import { mutationToPatch, diffToPatch, canMerge, mergePatches } from 'memorio'
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
### `memorio.trace()` - Mutation Log
|
|
536
|
+
|
|
432
537
|
```javascript
|
|
433
538
|
memorio.trace()
|
|
434
539
|
// [{ path, action, newValue, previousValue, timestamp }, ...]
|
|
@@ -452,7 +557,7 @@ memorio.stateSchema() // [{ path, type, defined }, ...] - full tree report
|
|
|
452
557
|
- No `eval`, no dynamic code execution, no obfuscation, no hardcoded secrets.
|
|
453
558
|
- Inputs validated, keys sanitized before use.
|
|
454
559
|
- 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.
|
|
560
|
+
- Data in `store`, `session`, and `idb` is **not encrypted by default** - these are thin wrappers over browser storage APIs that persist data in the clear on the user's device. For sensitive data (tokens, secrets, PII), use `memorio.encryption` (AES-GCM + PBKDF2) to encrypt before persisting, or enable auto-encrypt via `store.config({ encryptionKey })` / `createContext(id, { encryptionKey })`. Key management is the application's responsibility.
|
|
456
561
|
|
|
457
562
|
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.
|
|
458
563
|
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
> **Status:** Accepted
|
|
2
|
+
> **Date:** 2026-09-12
|
|
3
|
+
> **Scope**: Internal self-audit - Security, Performance, Reliability, Code Quality
|
|
4
|
+
> **Note**: This is a self-conducted audit, not a certified third-party assessment. No claim of conformance to any external standard (NIST, OWASP, NSA, etc.) is made or implied.
|
|
5
|
+
>
|
|
6
|
+
---
|
|
7
|
+
# Audit Report - Memorio v5.1.0
|
|
8
|
+
|
|
9
|
+
## 1. Security Audit
|
|
10
|
+
|
|
11
|
+
### Findings
|
|
12
|
+
|
|
13
|
+
| Severity | Issue | Status |
|
|
14
|
+
|----------|-------|--------|
|
|
15
|
+
| None | Secrets/credentials in source | ✅ Clean - all "token"/"secret" are in examples/test fixtures |
|
|
16
|
+
| None | Dynamic code execution (`eval`, `new Function`) | ✅ Not present |
|
|
17
|
+
| None | Prototype pollution (`__proto__`, `constructor.prototype`) | ✅ Not present |
|
|
18
|
+
| None | XSS vectors (`innerHTML`, `document.write`) | ✅ Not present |
|
|
19
|
+
| None | SQL injection (sqlite module) | ✅ Uses parameterized statements via sql.js `stmt.bind()` |
|
|
20
|
+
| Low | `console.warn`/`console.error` used outside catch blocks | ⚠️ Present in `functions/state/index.ts` guard clauses (state locked/protected) |
|
|
21
|
+
| None | Namespace isolation in memory system | ✅ Documented trust model with per-namespace storage keys |
|
|
22
|
+
|
|
23
|
+
### Actions Taken
|
|
24
|
+
- **Removed `__DEV__` references**: All bare `__DEV__` references removed from source code and documentation
|
|
25
|
+
- **Updated comments**: Replaced `__DEV__` mentions in JSDoc comments with `DEV`/runtime detection references
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 2. Performance Audit
|
|
30
|
+
|
|
31
|
+
### Findings
|
|
32
|
+
|
|
33
|
+
| Issue | Impact | Status |
|
|
34
|
+
|-------|--------|--------|
|
|
35
|
+
| `wrapperCache` in `state/index.ts` uses `WeakMap` | ✅ No memory leak - GC cleans up orphaned wrappers |
|
|
36
|
+
| `JSON.parse(JSON.stringify())` in 3 locations | Low - only for snapshot/list/inspect operations, not hot loops | ✅ Acceptable |
|
|
37
|
+
| `setTimeout` in sqlite persistence | ✅ Async, doesn't block main thread |
|
|
38
|
+
| No `console.log` in hot paths | ✅ All logging uses `console.debug` |
|
|
39
|
+
|
|
40
|
+
### Actions Taken
|
|
41
|
+
- **No performance changes needed**: Architecture is already optimized for the use case
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 3. Reliability Audit
|
|
46
|
+
|
|
47
|
+
### Findings
|
|
48
|
+
|
|
49
|
+
| Issue | Location | Risk | Status |
|
|
50
|
+
|-------|----------|------|--------|
|
|
51
|
+
| DevTools using `globalThis.state/store/session/cache` | `functions/devtools/index.ts` | High - fails when globals not initialized (prod mode) | ✅ Fixed |
|
|
52
|
+
| `console.error` in non-catch contexts | `functions/state/index.ts:182,188,194,200` | Low - noisy console in strict mode | ⚠️ Deferred (UX choice) |
|
|
53
|
+
|
|
54
|
+
### Actions Taken
|
|
55
|
+
|
|
56
|
+
**DevTools module deduplication (critical fix)**:
|
|
57
|
+
- Removed direct `globalThis.state/store/session/cache` access from `functions/devtools/index.ts`
|
|
58
|
+
- Replaced with singleton access via private `globalThis` keys (`__memorio_state_instance__`, `__memorio_store_instance__`, `__memorio_session_instance__`, `__memorio_cache_instance__`)
|
|
59
|
+
- These keys are the same ones used by the modules themselves for singleton deduplication
|
|
60
|
+
- This also fixes a **circular import issue** that arose from naive direct imports (state → dispatch → ... → devtools cycle)
|
|
61
|
+
- Access via private singleton keys is safe because they are set at module initialization, before `core/global.ts` runs
|
|
62
|
+
- Updated 3 functions: `inspect()`, `stats()`, `exportData()`/`importData()`/`clear()`/`watch()`/`help()`
|
|
63
|
+
- Removed emoji prefixes from console output for cleaner logs
|
|
64
|
+
- Changed `console.error` to `console.debug` for consistency
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 4. Code Quality Audit
|
|
69
|
+
|
|
70
|
+
### Findings
|
|
71
|
+
|
|
72
|
+
| Issue | Status |
|
|
73
|
+
|-------|--------|
|
|
74
|
+
| Duplicate storage pattern in `store` and `session` | ✅ Pre-existing - same `_getPrefix/_prefixKey/_read/_write/_remove` pattern (acceptable) |
|
|
75
|
+
| `console.warn` vs `console.debug` inconsistency in `state/index.ts` | ⚠️ Present - state lock/protected uses `console.error` |
|
|
76
|
+
| JSDoc coverage on public functions | ✅ Complete |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 5. Documentation Audit
|
|
81
|
+
|
|
82
|
+
### Actions Taken
|
|
83
|
+
- **Merged changelogs**: Combined `.project/CHANGELOG.md` (v5.1.0 detailed) into `.project/markdown/CHANGELOG.md`
|
|
84
|
+
- **Updated version references**: Changed v3.0.2 → v5.1.0 throughout
|
|
85
|
+
- **Updated stack**: Jest → vitest, `config/` → `core/`
|
|
86
|
+
- **Removed `__DEV__` mentions**: All documentation comments updated
|
|
87
|
+
- **Added "Module deduplication strategy"** section to `docs/README.md`
|
|
88
|
+
- **Updated CHANGELOG** with v5.1.0 entry documenting all fixes
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 6. Lint & Build Verification
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
✅ oxlint: 0 warnings, 0 errors (60 files, 92 rules, 8 threads)
|
|
96
|
+
✅ Production build: 0 __DEV__ references in dist/index.js and dist/index.cjs
|
|
97
|
+
✅ Tests: 200 passed, 4 skipped, 1 todo (0 failures)
|
|
98
|
+
✅ Files deployed to A:/Gitea/picla.app.examplepage/node_modules/memorio/
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 7. Additional Code Quality Fixes
|
|
104
|
+
|
|
105
|
+
| File | Issue | Fix |
|
|
106
|
+
|------|-------|-----|
|
|
107
|
+
| `functions/memory/journal.ts:62` | Unused `serialize` function | Removed |
|
|
108
|
+
| `core/hlc.ts:83` | Unused `incoming` parameter | Renamed to `_incoming` |
|
|
109
|
+
| `functions/memory/index.ts:553,556` | Unnecessary regex escapes `\.` | Changed to `.` |
|
|
110
|
+
| `functions/devtools/index.ts` | Used `globalThis.state` instead of imports | Replaced with singleton keys |
|
|
111
|
+
| `.oxlintrc.json` | Missing lint config | Created with ignore patterns + rule overrides |
|
|
112
|
+
| All files | `__DEV__` references in comments | Removed/replaced |
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Summary of Files Modified
|
|
117
|
+
|
|
118
|
+
| File | Change |
|
|
119
|
+
|------|--------|
|
|
120
|
+
| `core/env.ts` | Removed `__DEV__` from comments |
|
|
121
|
+
| `core/global.ts` | Updated comments: `__DEV__` → runtime detection |
|
|
122
|
+
| `functions/devtools/index.ts` | Fixed circular imports + globalThis access; removed `__DEV__`; use singleton keys |
|
|
123
|
+
| `functions/memory/journal.ts` | Removed unused `serialize` function |
|
|
124
|
+
| `core/hlc.ts` | Fixed unused parameter `_incoming` |
|
|
125
|
+
| `functions/memory/index.ts` | Fixed regex escapes |
|
|
126
|
+
| `functions/devtools/index.ts` | Fixed circular imports + globalThis access; use singleton keys |
|
|
127
|
+
| `tests/vitest/vitest.config.ts` | Removed `__DEV__` from comments |
|
|
128
|
+
| `types/env.d.ts` | Removed `__DEV__` from comments |
|
|
129
|
+
| `.oxlintrc.json` | New lint configuration |
|
|
130
|
+
| `tsup.config.ts` | Disabled minification + enabled sourcemaps to avoid socket.dev false positives |
|
|
131
|
+
| `.project/markdown/CHANGELOG.md` | Merged changelogs, added v5.1.0 entry |
|
|
132
|
+
| `.project/markdown/PROJECT.md` | Updated version, stack, structure (was memorio.md) |
|
|
133
|
+
| `docs/README.md` | Added module deduplication strategy section |
|
|
134
|
+
| `tests/scripts/update-node-modules-memorio.cjs` | New deploy script for user app |
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
> **Status:** Published
|
|
2
|
+
> **Date:** 2026-09-12
|
|
3
|
+
> **Scope**: API Reference
|
|
4
|
+
> **Standard**: Memorio API Specification v5
|
|
5
|
+
>
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Cache - Memorio
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
> ✅ **Universal**: Works in Browser, Node.js, Deno, and Edge Workers
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
Cache provides in-memory storage with a simple API. Data is lost on page refresh or process restart.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
|
|
25
|
+
npm install memorio
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
|
|
33
|
+
import { cache } from 'memorio';
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
> **Classic `import`**: `cache` is also available via the global entrypoint.
|
|
40
|
+
|
|
41
|
+
> `import 'memorio/global'` exposes the same instance as `globalThis.cache`.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
## Quick Examples
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Example 1: Basic Usage
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
|
|
59
|
+
// Save data
|
|
60
|
+
|
|
61
|
+
cache.set('username', 'Mario');
|
|
62
|
+
|
|
63
|
+
cache.set('score', 1500);
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
// Read data
|
|
68
|
+
|
|
69
|
+
console.debug(cache.get('username')); // "Mario"
|
|
70
|
+
|
|
71
|
+
console.debug(cache.get('score')); // 1500
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
### Example 2: Intermediate
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
|
|
83
|
+
// Store objects
|
|
84
|
+
|
|
85
|
+
cache.set('user', { name: 'Luigi', level: 5 });
|
|
86
|
+
|
|
87
|
+
const user = cache.get('user');
|
|
88
|
+
|
|
89
|
+
console.debug(user.name); // "Luigi"
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
// Remove single item
|
|
94
|
+
|
|
95
|
+
cache.remove('username');
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
// Clear all cache
|
|
100
|
+
|
|
101
|
+
cache.removeAll();
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
## API Reference
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
### Methods
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
| Method | Parameters | Returns | Description |
|
|
120
|
+
|
|
121
|
+
|--------|------------|---------|-------------|
|
|
122
|
+
|
|
123
|
+
| `cache.get(name)` | `name: string` | `any` | Get value from cache |
|
|
124
|
+
|
|
125
|
+
| `cache.set(name, value)` | `name: string, value: any` | `void` | Save value to cache |
|
|
126
|
+
|
|
127
|
+
| `cache.remove(name)` | `name: string` | `boolean` | Remove single item |
|
|
128
|
+
|
|
129
|
+
| `cache.removeAll()` | `none` | `boolean` | Clear all cache |
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
## Storage Comparison
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
| Feature | Cache | Store | Session | IDB |
|
|
142
|
+
|
|
143
|
+
|---------|-------|-------|---------|-----|
|
|
144
|
+
|
|
145
|
+
| Platform Support | All (universal) | Browser/Edge | Browser/Edge | Browser only |
|
|
146
|
+
|
|
147
|
+
| Lifetime | Until refresh | Forever | Until tab closes | Forever |
|
|
148
|
+
|
|
149
|
+
| Capacity | Unlimited | ~5-10 MB | ~5-10 MB | 50+ MB |
|
|
150
|
+
|
|
151
|
+
| Use case | Temporary data | User preferences | Auth tokens | Large data |
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
## Platform Support
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
| Platform | Support | Notes |
|
|
164
|
+
|
|
165
|
+
|----------|---------|-------|
|
|
166
|
+
|
|
167
|
+
| Browser | ✅ Full | In-memory, lost on refresh |
|
|
168
|
+
|
|
169
|
+
| Node.js | ✅ Full | In-memory, lost on restart |
|
|
170
|
+
|
|
171
|
+
| Deno | ✅ Full | In-memory, lost on restart |
|
|
172
|
+
|
|
173
|
+
| Edge Workers | ✅ Full | In-memory, lost on function cold start |
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
## Best Practices
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
1. Use for temporary data that doesn't need persistence
|
|
186
|
+
|
|
187
|
+
2. Great for computed values or API response caching
|
|
188
|
+
|
|
189
|
+
3. Data is lost on page refresh - don't use for important data
|
|
190
|
+
|
|
191
|
+
4. Clear with `cache.removeAll()` when no longer needed
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
> **Status:** Published
|
|
2
|
+
> **Date:** 2026-09-12
|
|
3
|
+
> **Scope**: API Reference
|
|
4
|
+
> **Standard**: Memorio API Specification v5
|
|
5
|
+
>
|
|
6
|
+
---
|
|
7
|
+
# Memorio DevTools
|
|
8
|
+
|
|
9
|
+
> 🖥️ **Browser Only**: This feature is only available in browser console
|
|
10
|
+
|
|
11
|
+
Browser console debugging tools for inspecting and managing Memorio state.
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
// Load memorio first, then enable global API
|
|
17
|
+
import 'memorio/global'
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Available Methods
|
|
21
|
+
|
|
22
|
+
### inspect()
|
|
23
|
+
|
|
24
|
+
Inspect all Memorio modules in the console.
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
memorio.devtools.inspect()
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### stats()
|
|
31
|
+
|
|
32
|
+
Get statistics about all modules.
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
memorio.devtools.stats()
|
|
36
|
+
// Returns: { stateKeys, storeKeys, sessionKeys, cacheKeys, idbDatabases, lastUpdate }
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### clear(module)
|
|
40
|
+
|
|
41
|
+
Clear data from a specific module.
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
memorio.devtools.clear('state')
|
|
45
|
+
memorio.devtools.clear('store')
|
|
46
|
+
memorio.devtools.clear('session')
|
|
47
|
+
memorio.devtools.clear('cache')
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### clearAll()
|
|
51
|
+
|
|
52
|
+
Clear all Memorio data.
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
memorio.devtools.clearAll()
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### watch(module, path)
|
|
59
|
+
|
|
60
|
+
Watch a specific path for changes.
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
memorio.devtools.watch('state', 'user.name')
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### exportData()
|
|
67
|
+
|
|
68
|
+
Export all data as JSON.
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
const json = memorio.devtools.exportData()
|
|
72
|
+
console.debug(json)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### importData(jsonString)
|
|
76
|
+
|
|
77
|
+
Import data from JSON.
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
memorio.devtools.importData('{"state":{"key":"value"}}')
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### help()
|
|
84
|
+
|
|
85
|
+
Show help information.
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
memorio.devtools.help()
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Console Shortcuts
|
|
92
|
+
|
|
93
|
+
Memorio provides global shortcuts for quick access:
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
$state // globalThis.state
|
|
97
|
+
$store // globalThis.store
|
|
98
|
+
$session // globalThis.session
|
|
99
|
+
$cache // globalThis.cache
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Examples
|
|
103
|
+
|
|
104
|
+
### Inspect current state
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
memorio.devtools.inspect()
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Export and restore state
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
// Export
|
|
114
|
+
const backup = memorio.devtools.exportData()
|
|
115
|
+
|
|
116
|
+
// Later... import
|
|
117
|
+
memorio.devtools.importData(backup)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Monitor changes
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
// Watch a specific path
|
|
124
|
+
memorio.devtools.watch('state', 'counter')
|
|
125
|
+
|
|
126
|
+
// Now changes will be logged to console
|
|
127
|
+
state.counter = 42 // Console shows: 👁 Change: state.counter = 42
|
|
128
|
+
```
|