memorio 4.6.8 → 4.7.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/llms.txt ADDED
@@ -0,0 +1,405 @@
1
+ # Memorio - LLM Documentation
2
+
3
+ ## Overview
4
+
5
+ **Memorio** is a cross-platform state management library that provides reactive state, persistence, and observation capabilities with zero dependencies. It works in Node.js, Deno, browsers, and edge environments.
6
+
7
+ ```
8
+ npm i memorio
9
+ ```
10
+
11
+ ## Core Concepts
12
+
13
+ Memorio provides 6 storage modules plus utilities:
14
+
15
+ | Module | Purpose | Persistence |
16
+ |--------|---------|-------------|
17
+ | `state` | Reactive, volatile state | In-memory (resets on refresh) |
18
+ | `store` | localStorage persistence | Survives browser refresh |
19
+ | `session` | sessionStorage | Dies with browser tab |
20
+ | `cache` | In-memory cache | Fastest read, no persistence |
21
+ | `idb` | IndexedDB | Structured, async, persistent (browser-only) |
22
+ | `observer` | Object watcher | Legacy |
23
+ | `useObserver` | React hook | Auto-discovery of state paths |
24
+
25
+ ## Quick Start
26
+
27
+ ```javascript
28
+ import 'memorio'
29
+
30
+ // Set reactive state
31
+ state.user = { name: 'Sara', role: 'admin' }
32
+ state.counter = 0
33
+
34
+ // Observe changes (React hook)
35
+ useObserver(
36
+ () => { console.debug('counter:', state.counter) },
37
+ [state.counter]
38
+ )
39
+ ```
40
+
41
+ ## API Reference
42
+
43
+ ### `state` — Reactive State
44
+
45
+ Global, Proxy-based, reactive state management.
46
+
47
+ ```javascript
48
+ // Set values
49
+ state.user = { name: 'Sara', role: 'admin' }
50
+ state.items = [1, 2, 3]
51
+ state.counter = 0
52
+
53
+ // Get values
54
+ const name = state.user.name // 'Sara'
55
+
56
+ // List all keys
57
+ console.debug(state.list) // ['user', 'items', 'counter']
58
+
59
+ // Remove one key
60
+ state.remove('items')
61
+
62
+ // Clear all
63
+ state.removeAll()
64
+
65
+ // Lock/unlock for frozen objects
66
+ state.lock() // freeze everything
67
+ state.unlock() // unfreeze
68
+ ```
69
+
70
+ **Features:**
71
+ - Automatic path tracking via `__path` property
72
+ - Nested proxy support
73
+ - Lock/unlock per-key or globally
74
+ - Auto-dispatches events on changes
75
+
76
+ ### `store` — localStorage Persistence
77
+
78
+ Persistent storage that survives browser refresh.
79
+
80
+ ```javascript
81
+ // Set
82
+ store.set('preferences', { theme: 'dark' })
83
+
84
+ // Get
85
+ const prefs = store.get('preferences') // { theme: 'dark' } or null
86
+
87
+ // List all keys
88
+ store.list() // { preferences: { theme: 'dark' } }
89
+
90
+ // Remove
91
+ store.remove('preferences')
92
+
93
+ // Delete (alias for remove)
94
+ store.delete('preferences')
95
+
96
+ // Clear all memorio items
97
+ store.removeAll()
98
+
99
+ // Clear all (alias for removeAll)
100
+ store.clearAll()
101
+
102
+ // Check size
103
+ console.debug(store.size(), 'chars stored')
104
+
105
+ // Check if persistent (real localStorage vs memory fallback)
106
+ console.debug(store.isPersistent) // true → real localStorage
107
+
108
+ // Estimate quota usage (returns [0, 0] for localStorage)
109
+ await store.quota() // [usage, quota] in KB
110
+ ```
111
+
112
+ ### `session` — sessionStorage
113
+
114
+ Storage that dies when browser tab closes.
115
+
116
+ ```javascript
117
+ // Set
118
+ session.set('token', 'user-abc-123')
119
+
120
+ // Get
121
+ const token = session.get('token') // 'user-abc-123' or null
122
+
123
+ // List all keys
124
+ session.list() // { token: 'user-abc-123' }
125
+
126
+ // Remove
127
+ session.remove('token')
128
+
129
+ // Delete (alias for remove)
130
+ session.delete('token')
131
+
132
+ // Clear all
133
+ session.removeAll()
134
+
135
+ // Clear all (alias for removeAll)
136
+ session.clearAll()
137
+
138
+ // Check size
139
+ console.debug(session.size(), 'chars stored')
140
+
141
+ // Check if persistent
142
+ console.debug(session.isPersistent)
143
+ ```
144
+
145
+ ### `cache` — In-Memory Cache
146
+
147
+ Fastest possible read, data lost on refresh.
148
+
149
+ ```javascript
150
+ // Set
151
+ cache.set('temp', computeExpensiveResult())
152
+
153
+ // Get
154
+ const result = cache.get('temp') // undefined or the value
155
+
156
+ // List all keys
157
+ cache.list() // { temp: <value> }
158
+
159
+ // Remove
160
+ cache.remove('temp')
161
+
162
+ // Clear all
163
+ cache.clear()
164
+
165
+ // Remove all (alias for clear)
166
+ cache.removeAll()
167
+
168
+ // Direct access (also works)
169
+ cache['myKey'] = value
170
+ const value = cache['myKey']
171
+ delete cache['myKey']
172
+ ```
173
+
174
+ ### `idb` — IndexedDB
175
+
176
+ Structured, persistent, async database (browser-only).
177
+
178
+ ```javascript
179
+ // Create database
180
+ await idb.db.create('my-db', 1) // version defaults to 1
181
+
182
+ // Create table (object store)
183
+ await idb.table.create('my-db', 'users')
184
+
185
+ // Set data
186
+ await idb.data.set('my-db', 'users', { id: 1, name: 'Sara' })
187
+
188
+ // Get data by key
189
+ const user = await idb.data.get('my-db', 'users', 1)
190
+
191
+ // Delete data
192
+ await idb.data.delete('my-db', 'users', 1)
193
+
194
+ // List databases
195
+ const dbs = await idb.db.list()
196
+
197
+ // Check if database exists
198
+ const exists = await idb.db.exist('my-db')
199
+
200
+ // Delete database
201
+ await idb.db.delete('my-db')
202
+
203
+ // Get database size
204
+ const size = await idb.db.size('my-db')
205
+
206
+ // Get table size
207
+ const tableSize = await idb.table.size('my-db', 'users')
208
+
209
+ // Check support
210
+ idb.db.support() // true if IndexedDB available
211
+
212
+ // Check quota
213
+ const [usage, quota] = await idb.db.quota()
214
+ ```
215
+
216
+ **Note:** In Node.js/Deno, `idb` is disabled with a warning. Use `store` or `session` instead.
217
+
218
+ ### `observer` — Object Watcher
219
+
220
+ Legacy observer API. Use `useObserver` instead.
221
+
222
+ ```javascript
223
+ // Listen to state changes
224
+ observer('state.user', (newVal, oldVal) => {
225
+ console.debug('user changed:', newVal, oldVal)
226
+ })
227
+
228
+ // Toggle listening (no callback)
229
+ observer('state.counter')
230
+
231
+ // Remove observer
232
+ observer.remove('state.user')
233
+
234
+ // List all observers
235
+ console.debug(observer.list)
236
+
237
+ // Remove all observers
238
+ observer.removeAll()
239
+ ```
240
+
241
+ ### `useObserver` — React Hook
242
+
243
+ Primary way to observe state changes in React components.
244
+
245
+ ```jsx
246
+ import 'memorio'
247
+ import { useReducer } from 'react'
248
+
249
+ function Counter() {
250
+ const [, forceUpdate] = useReducer(x => x + 1, 0)
251
+
252
+ // Auto-discovery mode (no deps)
253
+ useObserver(() => {
254
+ console.debug('counter:', state.counter)
255
+ }, state.counter)
256
+
257
+ // Explicit deps mode
258
+ useObserver(
259
+ () => { console.debug('user:', state.user) },
260
+ [state.user]
261
+ )
262
+
263
+ return <div>Count: {state.counter}</div>
264
+ }
265
+ ```
266
+
267
+ **Features:**
268
+ - Auto-discovery of state paths during render
269
+ - Returns cleanup function to stop monitoring
270
+ - Supports both Proxy objects and string paths
271
+
272
+ ### `devtools` — Inspection Tools
273
+
274
+ Inspect all memorio data in console.
275
+
276
+ ```javascript
277
+ // Pretty-print state, store, session, cache
278
+ memorio.devtools.inspect()
279
+
280
+ // Get stats
281
+ memorio.devtools.stats() // { stateKeys, storeKeys, sessionKeys, ... }
282
+
283
+ // Clear specific module
284
+ memorio.devtools.clear('state')
285
+
286
+ // Clear all modules
287
+ memorio.devtools.clearAll()
288
+
289
+ // Export all data as JSON
290
+ memorio.devtools.exportData()
291
+
292
+ // Import data from JSON
293
+ memorio.devtools.importData(jsonString)
294
+
295
+ // Show help
296
+ memorio.devtools.help()
297
+
298
+ // Console shortcuts
299
+ $state // same as globalThis.state
300
+ $store // same as globalThis.store
301
+ $session // same as globalThis.session
302
+ $cache // same as globalThis.cache
303
+ ```
304
+
305
+ ### `logger` — Change Tracking
306
+
307
+ Track every state change with timestamps.
308
+
309
+ ```javascript
310
+ // Configure logger
311
+ memorio.logger.configure({
312
+ enabled: true,
313
+ logToConsole: true,
314
+ modules: ['state', 'store', 'session', 'cache', 'idb']
315
+ })
316
+
317
+ // Get history
318
+ memorio.logger.getHistory() // [{ timestamp, module, action, path, value }, ...]
319
+
320
+ // Get stats
321
+ memorio.logger.getStats() // { total, state, store, session, cache, idb, set, get, ... }
322
+
323
+ // Clear history
324
+ memorio.logger.clearHistory()
325
+
326
+ // Export logs
327
+ memorio.logger.exportLogs() // JSON string of all history
328
+ ```
329
+
330
+ ## Platform Detection
331
+
332
+ Access via `memorio.*` after `import 'memorio'`:
333
+
334
+ ```javascript
335
+ memorio.isBrowser() // true in Chrome, Firefox, Safari
336
+ memorio.isNode() // true in Node.js
337
+ memorio.isDeno() // true in Deno
338
+ memorio.isEdge() // true in Cloudflare Workers, Vercel Edge
339
+
340
+ const caps = memorio.getCapabilities()
341
+ // { 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
+ ```
349
+
350
+ ## Cross-Platform Support
351
+
352
+ | Module | Browser | Node.js | Deno | Edge/Workers |
353
+ |--------|---------|---------|------|--------------|
354
+ | `state` | ✅ | ✅ | ✅ | ✅ |
355
+ | `observer` / `useObserver` | ✅ | ✅ | ✅ | ✅ |
356
+ | `cache` | ✅ | ✅ | ✅ | ✅ |
357
+ | `store` | ✅ localStorage | ⚠️ memory | ⚠️ memory | ✅ localStorage |
358
+ | `session` | ✅ sessionStorage | ⚠️ memory | ⚠️ memory | ✅ sessionStorage |
359
+ | `idb` | ✅ IndexedDB | ❌ | ❌ | ⚠️ |
360
+ | `devtools` | ✅ | ❌ | ❌ | ⚠️ |
361
+
362
+ **Note:** `store` and `session` fall back to in-memory `Map` in Node.js/Deno.
363
+
364
+ ## Session Isolation
365
+
366
+ Each browser tab and server request gets an isolated namespace automatically via session IDs.
367
+
368
+ ```javascript
369
+ // Create isolated context
370
+ memorio.createContext('tenant-name')
371
+ memorio.listContexts()
372
+ memorio.deleteContext('context-id')
373
+ memorio.isolate('tenant-name') // alias for createContext
374
+ ```
375
+
376
+ ## Security
377
+
378
+ - Zero production dependencies
379
+ - NIST & NSA aligned security standards
380
+ - No `eval`, no obfuscation, no hardcoded secrets
381
+ - All inputs validated, keys sanitized
382
+ - Secure random session IDs via `crypto.randomUUID`
383
+
384
+ ## License
385
+
386
+ MIT © Dario Passariello (BigLogic Inc Canada)
387
+
388
+ ## Utilities
389
+
390
+ ### `memorio.dispatch` — Event Dispatch System
391
+
392
+ Internal event system used by state changes.
393
+
394
+ ```javascript
395
+ // Dispatch a custom event
396
+ memorio.dispatch.set('custom:event', { detail: { data: 'value' } })
397
+
398
+ // Listen for an event
399
+ memorio.dispatch.listen('custom:event', (e) => {
400
+ console.debug('Event triggered:', e.detail)
401
+ })
402
+
403
+ // Remove listener
404
+ memorio.dispatch.remove('custom:event')
405
+ ```
@@ -0,0 +1,90 @@
1
+ # Cache - Memorio
2
+
3
+ > ✅ **Universal**: Works in Browser, Node.js, Deno, and Edge Workers
4
+
5
+ Cache provides in-memory storage with a simple API. Data is lost on page refresh or process restart.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install memorio
11
+ ```
12
+
13
+ ```javascript
14
+ import 'memorio';
15
+ ```
16
+
17
+ ---
18
+
19
+ ## Quick Examples
20
+
21
+ ### Example 1: Basic Usage
22
+
23
+ ```javascript
24
+ // Save data
25
+ cache.set('username', 'Mario');
26
+ cache.set('score', 1500);
27
+
28
+ // Read data
29
+ console.debug(cache.get('username')); // "Mario"
30
+ console.debug(cache.get('score')); // 1500
31
+ ```
32
+
33
+ ### Example 2: Intermediate
34
+
35
+ ```javascript
36
+ // Store objects
37
+ cache.set('user', { name: 'Luigi', level: 5 });
38
+ const user = cache.get('user');
39
+ console.debug(user.name); // "Luigi"
40
+
41
+ // Remove single item
42
+ cache.remove('username');
43
+
44
+ // Clear all cache
45
+ cache.removeAll();
46
+ ```
47
+
48
+ ---
49
+
50
+ ## API Reference
51
+
52
+ ### Methods
53
+
54
+ | Method | Parameters | Returns | Description |
55
+ |--------|------------|---------|-------------|
56
+ | `cache.get(name)` | `name: string` | `any` | Get value from cache |
57
+ | `cache.set(name, value)` | `name: string, value: any` | `void` | Save value to cache |
58
+ | `cache.remove(name)` | `name: string` | `boolean` | Remove single item |
59
+ | `cache.removeAll()` | `none` | `boolean` | Clear all cache |
60
+
61
+ ---
62
+
63
+ ## Storage Comparison
64
+
65
+ | Feature | Cache | Store | Session | IDB |
66
+ |---------|-------|-------|---------|-----|
67
+ | Platform Support | All (universal) | Browser/Edge | Browser/Edge | Browser only |
68
+ | Lifetime | Until refresh | Forever | Until tab closes | Forever |
69
+ | Capacity | Unlimited | ~5-10 MB | ~5-10 MB | 50+ MB |
70
+ | Use case | Temporary data | User preferences | Auth tokens | Large data |
71
+
72
+ ---
73
+
74
+ ## Platform Support
75
+
76
+ | Platform | Support | Notes |
77
+ |----------|---------|-------|
78
+ | Browser | ✅ Full | In-memory, lost on refresh |
79
+ | Node.js | ✅ Full | In-memory, lost on restart |
80
+ | Deno | ✅ Full | In-memory, lost on restart |
81
+ | Edge Workers | ✅ Full | In-memory, lost on function cold start |
82
+
83
+ ---
84
+
85
+ ## Best Practices
86
+
87
+ 1. Use for temporary data that doesn't need persistence
88
+ 2. Great for computed values or API response caching
89
+ 3. Data is lost on page refresh - don't use for important data
90
+ 4. Clear with `cache.removeAll()` when no longer needed
@@ -0,0 +1,161 @@
1
+ # Changelog - Memorio
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ---
6
+
7
+ ## v4.6.1 (Security Patch) - 2026-08-14 — CRITICAL Security Fix
8
+
9
+ ### 🔐 Security NOTICE (v4.6.0)
10
+
11
+ **CRITICAL**: A Gitea Personal Access Token was accidentally committed to `.npmrc` in v4.6.0
12
+
13
+ **Affected**: `v4.6.0` tag and all builds from that version
14
+
15
+ **Action Required**:
16
+ - **IMMEDIATE**: Revoke ALL tokens on Gitea Packages by admin access
17
+ - **GENERATE**: Create new PAT with scope `write:package` only
18
+ - **CONFIGURE**: Add as secret `PAT` in GitHub Actions or Gitea Actions
19
+ - **UPGRADE**: Use v4.6.1 where the token is replaced with `${PAT}` environment variable
20
+
21
+ The hardcoded token `2f398d5d7a734781e96108fdd0dbbabad41ef77a` has been removed in v4.6.1.
22
+
23
+ ### 🐛 Bug Fixes
24
+
25
+ - **SECURITY**: Removed hardcoded Gitea PAT from `.npmrc` (exposed token remediated)
26
+ - Replaced with environment variable `${PAT}` for secure authentication
27
+
28
+ ### 📝 Documentation Updates
29
+
30
+ - `.npmrc`: Token replaced with environment variable reference
31
+ - `.gitea/workflows/npm.yml`: Configured to use secrets `GITEA_USER` and `PAT`
32
+
33
+ ---
34
+
35
+ ## v4.6.0 (Previous - SECURITY ISSUE) - 2026-08-13 — Refactoring & Documentation
36
+
37
+ **⚠️ WARNING**: This version had a hardcoded PAT token that was later remediated in v4.6.1**
38
+
39
+ ### 🐛 Bug Fixes
40
+
41
+ - Fixed circular import in `idb/index.ts` → `core/global`
42
+ - Fixed dead `globalThis._propertyAccessLog` reference in `observer`
43
+ - Fixed `dispatch.remove(f)` tuple bug in `functions/dispatch.ts`
44
+ - Fixed `logger.isDebugEnabled` using wrong module reference
45
+ - Removed dead `propertyAccessLog` / `pushPropertyAccess` from `core/internal.ts`
46
+ - Removed duplicate path-tracking block in `state` get handler
47
+ - Removed redundant `?? key` fallback in `state` set handler
48
+
49
+ ### 🔧 Code Refactoring
50
+
51
+ - **Self-contained modules**: All modules now work independently without internal `globalThis.memorio.*` reads/writes
52
+ - **Module-local state**: Created `core/internal.ts` for module-local singletons
53
+ - **Bootstrap-only global**: `core/global.ts` now only publishes to `globalThis.memorio` at initialization
54
+ - **Removed dead code**: `core/constructor.ts` deleted (unused)
55
+ - **Extracted helpers**: `_read`/`_write`/`_remove` in `store` and `session` to eliminate duplication
56
+ - **Fixed circular imports**: `dispatch` → `observer` via `globalThis.events`
57
+
58
+ ### 📝 Documentation Updates
59
+
60
+ - `docs/README.md`: Added Classic `import { state } from 'memorio'` section, improved badges layout, enhanced "Why memorio?" comparison table
61
+ - `docs/markdown/STORE.md`: Added classic import note
62
+ - `docs/markdown/IMPORT.md`: New file for named export guide
63
+ - `docs/SUMMARY.md`: Updated to include `IMPORT.md`
64
+ - `README.md`: Badge corrections, header cleanup, removed unverified bundle size claims
65
+
66
+ ### 🆕 GitHub Actions / Gitea Workflows
67
+
68
+ - Added `.gitea/workflows/npm.yml` for automatic npm package publishing to Gitea Packages on `v*` tags
69
+ - Requires `GITEA_USER` and `PAT` secrets
70
+
71
+ ### 🧪 Tests
72
+
73
+ - **Result: 9 suites · 101 passed · 4 skipped · 1 todo**
74
+ - All lint and typecheck clean
75
+
76
+ ---
77
+
78
+ ## v3.0.2 (Current) - 2026-05-19 — Bug Fix, Security & API Expansion
79
+
80
+ ### 🐛 Bug Fixes
81
+
82
+ - Removed dead code: `buildPathTracker` from `functions/state/index.ts` (unused Proxy builder, exported nowhere)
83
+ - Removed double `delete` in state `removeAll` handler (redundant null-check + delete on same key)
84
+ - Removed unbound `globalThis.state` reference in state init (would throw `ReferenceError` in strict mode)
85
+ - Removed `Object.freeze(observer)` referencing undeclared variable (`ReferenceError` on module load)
86
+ - Removed `confirm()` synchronous blocking call from `idb.db.delete` (library must not block main thread)
87
+
88
+ ### 🔒 Security Improvements
89
+
90
+ - Removed `esbuild-sass-plugin` and `esbuild-scss-modules-plugin` from `devDependencies` (unnecessary for a library with no styles)
91
+ - Removed `injectStyle: true`, `sassPlugin()` and `.css` loader from `tsup.config.ts`
92
+ - Deleted `tsup.plugin.injectCss.ts` (code injection vector completely removed from build pipeline)
93
+ - `console.error`/`console.warn` → `console.debug` in `devtools` and `idb` error handlers (consistent debug-only logging policy)
94
+ - `store.set()` now blocks function values instead of silently logging and continuing
95
+ - All `PRIVATE License` headers in `functions/idb/` replaced with `MIT License`
96
+
97
+ ### 🔧 Code Quality
98
+
99
+ - Added JSDoc to `observerFunction` in `functions/observer/index.ts`
100
+ - Added JSDoc to `cache` global in `functions/cache/index.ts`
101
+ - `lint` and `tsc` pass clean — 0 vulnerabilities from `npm audit`
102
+
103
+ ### 🆕 API — New in 3.0.2
104
+
105
+ | Function | Description |
106
+ |----------|-------------|
107
+ | `memorio.isBrowser()` | Returns `true` when running in a browser |
108
+ | `memorio.isNode()` | Returns `true` when running in Node.js |
109
+ | `memorio.isDeno()` | Returns `true` when running in Deno |
110
+ | `memorio.isEdge()` | Returns `true` in Cloudflare Workers, Vercel Edge, etc. |
111
+ | `memorio.getCapabilities()` | Full capabilities object (`platform`, `hasLocalStorage`, `hasIndexedDB`, …) |
112
+ | `memorio.createContext(name?)` | Create multi-tenant isolated context |
113
+ | `memorio.listContexts()` | List all active isolated contexts |
114
+ | `memorio.deleteContext(id)` | Delete isolated context by ID |
115
+ | `memorio.isolate(name?)` | Shorthand alias for `createContext` |
116
+
117
+ ### 🧪 Tests
118
+ - **Result: 8 suites · 95 passed · 3 skipped · 0 failed**
119
+
120
+ ### 🗑️ Dependency Changes
121
+
122
+ | Removed | Reason |
123
+ |---------|--------|
124
+ | `esbuild-sass-plugin@3.7.0` | No SCSS in a library |
125
+ | `esbuild-scss-modules-plugin@1.1.1` | No SCSS in a library |
126
+ | 36 transitive packages | Removed from `node_modules` |
127
+
128
+ ### 📝 Documentation Updates
129
+
130
+ - `docs/README.md`: replaced `console.debug` with `console.debug` in usage examples; fixed `esbuild` badge → `tsup`
131
+ - `.github/CHANGELOG.md`: restructured with fix / security / changed sections
132
+ - `.github/HISTORY.md`: complete rewrite through v3.0.2
133
+ - `.github/SECURITY.md`: NIST/NSA standard + OWASP Top 10 mapping
134
+ - `.github/CITATION.cff`: license PRIVATE → MIT to match `package.json`
135
+ - `.project/*`: all context documents updated to v3.0.2
136
+
137
+ ---
138
+
139
+ ## v2.9.0 — 2026-05-13
140
+
141
+ ### Added
142
+ - DevTools — `memorio.devtools.inspect()`, `stats()`, `exportData()`
143
+ - Logger with full history, stats and export
144
+ - Platform detection (`isBrowser`, `isNode`, `isDeno`, `isEdge`, `getCapabilities`)
145
+ - Session isolation via `crypto.randomUUID()`
146
+
147
+ ### Changed
148
+ - Updated dependencies to latest versions
149
+ - Improved cross-platform support (Deno, Edge Workers, Node.js)
150
+
151
+ ### Security
152
+ - Secure random session IDs replaced `Math.random()`
153
+ - Key validation (max 512 chars + character whitelist)
154
+
155
+ ---
156
+
157
+ ## v2.5.0 — 2026-02-17
158
+
159
+ - Initial release of memorio (state, store, session, cache, idb)
160
+ - Observer pattern (`observer`)
161
+ - `useObserver` React hook