memorio 3.0.1 → 3.0.2
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 +59 -48
- package/docs/README.md +59 -48
- package/docs/markdown/CACHE.md +3 -3
- package/docs/markdown/CHANGELOG.md +63 -154
- package/docs/markdown/DEVTOOLS.md +1 -1
- package/docs/markdown/IDB.md +3 -3
- package/docs/markdown/LOGGER.md +2 -2
- package/docs/markdown/OBSERVER.md +4 -4
- package/docs/markdown/PLATFORM.md +5 -5
- package/docs/markdown/SECURITY.md +16 -4
- package/docs/markdown/SESSION.md +4 -4
- package/docs/markdown/STATE.md +7 -7
- package/docs/markdown/STORE.md +7 -7
- package/docs/markdown/USEOBSERVER.md +1 -1
- package/examples/react-app.tsx +6 -1
- package/index.cjs +106 -98
- package/index.js +106 -96
- package/package.json +1 -1
- package/types/memorio.d.ts +6 -0
package/README.md
CHANGED
|
@@ -25,7 +25,6 @@ Zero friction. Zero bloat. Single import. Works everywhere JavaScript runs.
|
|
|
25
25
|
| | memorio | Redux | Zustand |
|
|
26
26
|
|---|---|---|---|
|
|
27
27
|
| **Setup** | 1 import | Boilerplate hell | Moderate |
|
|
28
|
-
| **Bundle size** | **~8 KB** | ~30 KB | ~15 KB |
|
|
29
28
|
| **Dependencies** | **Zero** | Many | Few |
|
|
30
29
|
| **TypeScript** | ✅ Native | ✅ | ✅ |
|
|
31
30
|
| **Binary storage** | ✅ Built-in IDB | ❌ Add-on | ❌ |
|
|
@@ -114,22 +113,6 @@ state.lock() // freeze everything
|
|
|
114
113
|
state.unlock() // unfreeze
|
|
115
114
|
```
|
|
116
115
|
|
|
117
|
-
### `useObserver` — React hook (with auto-discovery)
|
|
118
|
-
|
|
119
|
-
```jsx
|
|
120
|
-
import 'memorio'
|
|
121
|
-
import { useObserver } from 'memorio'
|
|
122
|
-
|
|
123
|
-
function Counter() {
|
|
124
|
-
const [, forceUpdate] = useReducer(x => x + 1, 0)
|
|
125
|
-
|
|
126
|
-
useObserver(forceUpdate, [state.counter])
|
|
127
|
-
// State path auto-discovered during render — no manual deps needed
|
|
128
|
-
|
|
129
|
-
return <div>Count: {state.counter}</div>
|
|
130
|
-
}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
116
|
### `store` — localStorage, survives refresh
|
|
134
117
|
|
|
135
118
|
```javascript
|
|
@@ -160,16 +143,35 @@ cache.clear() // empty it all
|
|
|
160
143
|
### `idb` — IndexedDB, structured & typed
|
|
161
144
|
|
|
162
145
|
```javascript
|
|
163
|
-
// Create a database
|
|
164
146
|
await idb.db.create('my-db')
|
|
165
|
-
// Then create tables
|
|
166
147
|
await idb.table.create('my-db', 'users')
|
|
167
|
-
await idb.table.create('my-db', 'posts')
|
|
168
|
-
|
|
169
|
-
// CRUD
|
|
170
148
|
await idb.data.set('my-db', 'users', { id: 1, name: 'Sara' })
|
|
171
|
-
const user = await idb.data.get('my-db', 'users', 1)
|
|
172
|
-
|
|
149
|
+
const user = await idb.data.get('my-db', 'users', 1)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### `observer` — Object watcher (DEPRECATED)
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
globalThis.observer('state.user', (newVal, oldVal) => {
|
|
156
|
+
console.debug('user changed:', newVal, oldVal)
|
|
157
|
+
})
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### `useObserver` — React observer hook
|
|
161
|
+
|
|
162
|
+
Available globally after `import 'memorio'`.
|
|
163
|
+
|
|
164
|
+
```jsx
|
|
165
|
+
import 'memorio'
|
|
166
|
+
|
|
167
|
+
function Counter() {
|
|
168
|
+
const [, forceUpdate] = useReducer(x => x + 1, 0)
|
|
169
|
+
|
|
170
|
+
useObserver(forceUpdate, [state.counter])
|
|
171
|
+
// State path auto-discovered during render — no manual deps needed
|
|
172
|
+
|
|
173
|
+
return <div>Count: {state.counter}</div>
|
|
174
|
+
}
|
|
173
175
|
```
|
|
174
176
|
|
|
175
177
|
### `devtools` — inspect everything in one call
|
|
@@ -191,6 +193,29 @@ memorio.logger.getStats() // { total, state, set, get, ... }
|
|
|
191
193
|
memorio.logger.exportLogs() // JSON string of all history
|
|
192
194
|
```
|
|
193
195
|
|
|
196
|
+
### Platform detection
|
|
197
|
+
|
|
198
|
+
Access via `memorio.*`:
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
memorio.isBrowser() // true in Chrome, Firefox, Safari
|
|
202
|
+
memorio.isNode() // true in Node.js
|
|
203
|
+
memorio.isDeno() // true in Deno
|
|
204
|
+
memorio.isEdge() // true in Cloudflare Workers, Vercel Edge
|
|
205
|
+
|
|
206
|
+
const caps = memorio.getCapabilities()
|
|
207
|
+
// { platform: 'browser', hasLocalStorage: true, hasIndexedDB: true, ... }
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Context (multi-tenant)
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
memorio.createContext('tenant-name')
|
|
214
|
+
memorio.listContexts()
|
|
215
|
+
memorio.deleteContext('context-id')
|
|
216
|
+
memorio.isolate('tenant-name')
|
|
217
|
+
```
|
|
218
|
+
|
|
194
219
|
---
|
|
195
220
|
|
|
196
221
|
## Cross-Platform
|
|
@@ -209,32 +234,18 @@ Memorio runs in every JavaScript environment, with automatic fallbacks.
|
|
|
209
234
|
|
|
210
235
|
> **Why memory fallbacks on the server?** There is no browser. `store` and `session` gracefully fall back to `Map`. You still get the same API. Same `state`, same `cache`, same `useObserver`. No extra config required.
|
|
211
236
|
|
|
212
|
-
###
|
|
237
|
+
### Platform detection
|
|
213
238
|
|
|
214
|
-
|
|
215
|
-
import { isBrowser, isNode, isDeno, isEdge, getCapabilities } from 'memorio'
|
|
216
|
-
|
|
217
|
-
isBrowser() // true in Chrome, Firefox, Safari
|
|
218
|
-
isNode() // true in Node.js
|
|
219
|
-
isDeno() // true in Deno
|
|
220
|
-
isEdge() // true in Cloudflare Workers, Vercel Edge
|
|
221
|
-
|
|
222
|
-
const c = getCapabilities()
|
|
223
|
-
// { platform: 'browser', isBrowser: true, hasLocalStorage: true, hasIndexedDB: true }
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
---
|
|
227
|
-
|
|
228
|
-
## Testing
|
|
229
|
-
|
|
230
|
-
```
|
|
231
|
-
71 tests · 8 suites · all passing
|
|
239
|
+
Access via `memorio.*` after `import 'memorio'`:
|
|
232
240
|
|
|
233
|
-
|
|
234
|
-
|
|
241
|
+
```javascript
|
|
242
|
+
memorio.isBrowser() // true in Chrome, Firefox, Safari
|
|
243
|
+
memorio.isNode() // true in Node.js
|
|
244
|
+
memorio.isDeno() // true in Deno
|
|
245
|
+
memorio.isEdge() // true in Cloudflare Workers, Vercel Edge
|
|
235
246
|
|
|
236
|
-
|
|
237
|
-
|
|
247
|
+
const c = memorio.getCapabilities()
|
|
248
|
+
// { platform: 'browser', hasLocalStorage: true, hasIndexedDB: true, ... }
|
|
238
249
|
```
|
|
239
250
|
|
|
240
251
|
---
|
|
@@ -297,4 +308,4 @@ npm test
|
|
|
297
308
|
|
|
298
309
|
MIT © [Dario Passariello](https://dario.passariello.ca)
|
|
299
310
|
|
|
300
|
-
© [BigLogic Inc Canada](https
|
|
311
|
+
© [BigLogic Inc Canada](https://biglogic.ca)
|
package/docs/README.md
CHANGED
|
@@ -25,7 +25,6 @@ Zero friction. Zero bloat. Single import. Works everywhere JavaScript runs.
|
|
|
25
25
|
| | memorio | Redux | Zustand |
|
|
26
26
|
|---|---|---|---|
|
|
27
27
|
| **Setup** | 1 import | Boilerplate hell | Moderate |
|
|
28
|
-
| **Bundle size** | **~8 KB** | ~30 KB | ~15 KB |
|
|
29
28
|
| **Dependencies** | **Zero** | Many | Few |
|
|
30
29
|
| **TypeScript** | ✅ Native | ✅ | ✅ |
|
|
31
30
|
| **Binary storage** | ✅ Built-in IDB | ❌ Add-on | ❌ |
|
|
@@ -114,22 +113,6 @@ state.lock() // freeze everything
|
|
|
114
113
|
state.unlock() // unfreeze
|
|
115
114
|
```
|
|
116
115
|
|
|
117
|
-
### `useObserver` — React hook (with auto-discovery)
|
|
118
|
-
|
|
119
|
-
```jsx
|
|
120
|
-
import 'memorio'
|
|
121
|
-
import { useObserver } from 'memorio'
|
|
122
|
-
|
|
123
|
-
function Counter() {
|
|
124
|
-
const [, forceUpdate] = useReducer(x => x + 1, 0)
|
|
125
|
-
|
|
126
|
-
useObserver(forceUpdate, [state.counter])
|
|
127
|
-
// State path auto-discovered during render — no manual deps needed
|
|
128
|
-
|
|
129
|
-
return <div>Count: {state.counter}</div>
|
|
130
|
-
}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
116
|
### `store` — localStorage, survives refresh
|
|
134
117
|
|
|
135
118
|
```javascript
|
|
@@ -160,16 +143,35 @@ cache.clear() // empty it all
|
|
|
160
143
|
### `idb` — IndexedDB, structured & typed
|
|
161
144
|
|
|
162
145
|
```javascript
|
|
163
|
-
// Create a database
|
|
164
146
|
await idb.db.create('my-db')
|
|
165
|
-
// Then create tables
|
|
166
147
|
await idb.table.create('my-db', 'users')
|
|
167
|
-
await idb.table.create('my-db', 'posts')
|
|
168
|
-
|
|
169
|
-
// CRUD
|
|
170
148
|
await idb.data.set('my-db', 'users', { id: 1, name: 'Sara' })
|
|
171
|
-
const user = await idb.data.get('my-db', 'users', 1)
|
|
172
|
-
|
|
149
|
+
const user = await idb.data.get('my-db', 'users', 1)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### `observer` — Object watcher (DEPRECATED)
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
globalThis.observer('state.user', (newVal, oldVal) => {
|
|
156
|
+
console.debug('user changed:', newVal, oldVal)
|
|
157
|
+
})
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### `useObserver` — React observer hook
|
|
161
|
+
|
|
162
|
+
Available globally after `import 'memorio'`.
|
|
163
|
+
|
|
164
|
+
```jsx
|
|
165
|
+
import 'memorio'
|
|
166
|
+
|
|
167
|
+
function Counter() {
|
|
168
|
+
const [, forceUpdate] = useReducer(x => x + 1, 0)
|
|
169
|
+
|
|
170
|
+
useObserver(forceUpdate, [state.counter])
|
|
171
|
+
// State path auto-discovered during render — no manual deps needed
|
|
172
|
+
|
|
173
|
+
return <div>Count: {state.counter}</div>
|
|
174
|
+
}
|
|
173
175
|
```
|
|
174
176
|
|
|
175
177
|
### `devtools` — inspect everything in one call
|
|
@@ -191,6 +193,29 @@ memorio.logger.getStats() // { total, state, set, get, ... }
|
|
|
191
193
|
memorio.logger.exportLogs() // JSON string of all history
|
|
192
194
|
```
|
|
193
195
|
|
|
196
|
+
### Platform detection
|
|
197
|
+
|
|
198
|
+
Access via `memorio.*`:
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
memorio.isBrowser() // true in Chrome, Firefox, Safari
|
|
202
|
+
memorio.isNode() // true in Node.js
|
|
203
|
+
memorio.isDeno() // true in Deno
|
|
204
|
+
memorio.isEdge() // true in Cloudflare Workers, Vercel Edge
|
|
205
|
+
|
|
206
|
+
const caps = memorio.getCapabilities()
|
|
207
|
+
// { platform: 'browser', hasLocalStorage: true, hasIndexedDB: true, ... }
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Context (multi-tenant)
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
memorio.createContext('tenant-name')
|
|
214
|
+
memorio.listContexts()
|
|
215
|
+
memorio.deleteContext('context-id')
|
|
216
|
+
memorio.isolate('tenant-name')
|
|
217
|
+
```
|
|
218
|
+
|
|
194
219
|
---
|
|
195
220
|
|
|
196
221
|
## Cross-Platform
|
|
@@ -209,32 +234,18 @@ Memorio runs in every JavaScript environment, with automatic fallbacks.
|
|
|
209
234
|
|
|
210
235
|
> **Why memory fallbacks on the server?** There is no browser. `store` and `session` gracefully fall back to `Map`. You still get the same API. Same `state`, same `cache`, same `useObserver`. No extra config required.
|
|
211
236
|
|
|
212
|
-
###
|
|
237
|
+
### Platform detection
|
|
213
238
|
|
|
214
|
-
|
|
215
|
-
import { isBrowser, isNode, isDeno, isEdge, getCapabilities } from 'memorio'
|
|
216
|
-
|
|
217
|
-
isBrowser() // true in Chrome, Firefox, Safari
|
|
218
|
-
isNode() // true in Node.js
|
|
219
|
-
isDeno() // true in Deno
|
|
220
|
-
isEdge() // true in Cloudflare Workers, Vercel Edge
|
|
221
|
-
|
|
222
|
-
const c = getCapabilities()
|
|
223
|
-
// { platform: 'browser', isBrowser: true, hasLocalStorage: true, hasIndexedDB: true }
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
---
|
|
227
|
-
|
|
228
|
-
## Testing
|
|
229
|
-
|
|
230
|
-
```
|
|
231
|
-
71 tests · 8 suites · all passing
|
|
239
|
+
Access via `memorio.*` after `import 'memorio'`:
|
|
232
240
|
|
|
233
|
-
|
|
234
|
-
|
|
241
|
+
```javascript
|
|
242
|
+
memorio.isBrowser() // true in Chrome, Firefox, Safari
|
|
243
|
+
memorio.isNode() // true in Node.js
|
|
244
|
+
memorio.isDeno() // true in Deno
|
|
245
|
+
memorio.isEdge() // true in Cloudflare Workers, Vercel Edge
|
|
235
246
|
|
|
236
|
-
|
|
237
|
-
|
|
247
|
+
const c = memorio.getCapabilities()
|
|
248
|
+
// { platform: 'browser', hasLocalStorage: true, hasIndexedDB: true, ... }
|
|
238
249
|
```
|
|
239
250
|
|
|
240
251
|
---
|
|
@@ -297,4 +308,4 @@ npm test
|
|
|
297
308
|
|
|
298
309
|
MIT © [Dario Passariello](https://dario.passariello.ca)
|
|
299
310
|
|
|
300
|
-
© [BigLogic Inc Canada](https
|
|
311
|
+
© [BigLogic Inc Canada](https://biglogic.ca)
|
package/docs/markdown/CACHE.md
CHANGED
|
@@ -26,8 +26,8 @@ cache.set('username', 'Mario');
|
|
|
26
26
|
cache.set('score', 1500);
|
|
27
27
|
|
|
28
28
|
// Read data
|
|
29
|
-
console.
|
|
30
|
-
console.
|
|
29
|
+
console.debug(cache.get('username')); // "Mario"
|
|
30
|
+
console.debug(cache.get('score')); // 1500
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
### Example 2: Intermediate
|
|
@@ -36,7 +36,7 @@ console.log(cache.get('score')); // 1500
|
|
|
36
36
|
// Store objects
|
|
37
37
|
cache.set('user', { name: 'Luigi', level: 5 });
|
|
38
38
|
const user = cache.get('user');
|
|
39
|
-
console.
|
|
39
|
+
console.debug(user.name); // "Luigi"
|
|
40
40
|
|
|
41
41
|
// Remove single item
|
|
42
42
|
cache.remove('username');
|
|
@@ -4,181 +4,90 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
### 🚀 New Features
|
|
10
|
-
|
|
11
|
-
#### 1. Platform Compatibility Layer
|
|
12
|
-
- **Auto-detection**: Automatically detects Browser, Node.js, Deno, Edge Workers
|
|
13
|
-
- **Polyfills**: Automatic fallback for server environments
|
|
14
|
-
- **New exports**:
|
|
15
|
-
- `memorio.isBrowser()` - Check if running in browser
|
|
16
|
-
- `memorio.isNode()` - Check if running in Node.js
|
|
17
|
-
- `memorio.isDeno()` - Check if running in Deno
|
|
18
|
-
- `memorio.isEdge()` - Check if running in Edge Worker
|
|
19
|
-
- `memorio.getCapabilities()` - Get platform capabilities
|
|
20
|
-
|
|
21
|
-
#### 2. Session Isolation
|
|
22
|
-
- **Unique Session IDs**: Each import/session gets unique ID via `crypto.randomUUID()`
|
|
23
|
-
- **Namespaced Storage**: Keys prefixed with session ID to prevent cross-contamination
|
|
24
|
-
- **Format**: `memorio_store_[session-uuid]_keyname`
|
|
25
|
-
|
|
26
|
-
#### 3. Context Isolation (Multi-Tenant Support)
|
|
27
|
-
- **New API**:
|
|
28
|
-
- `memorio.createContext(name?)` - Create isolated context
|
|
29
|
-
- `memorio.listContexts()` - List all contexts
|
|
30
|
-
- `memorio.deleteContext(id)` - Delete context
|
|
31
|
-
- `memorio.isolate(name?)` - Alias for createContext
|
|
32
|
-
|
|
33
|
-
#### 4. Persistence Detection
|
|
34
|
-
- **New Properties**:
|
|
35
|
-
- `store.isPersistent` - Check if using real localStorage
|
|
36
|
-
- `session.isPersistent` - Check if using real sessionStorage
|
|
7
|
+
## v3.0.2 (Current) - 2026-05-19 — Bug Fix, Security & API Expansion
|
|
37
8
|
|
|
38
|
-
###
|
|
39
|
-
|
|
40
|
-
| Feature | Before v2.7.0 | After v2.7.0 |
|
|
41
|
-
|---------|---------------|--------------|
|
|
42
|
-
| Session ID | `Math.random()` | `crypto.randomUUID()` |
|
|
43
|
-
| Key Validation | None | Max 512 chars + whitelist |
|
|
44
|
-
| Server Isolation | None | Context system |
|
|
45
|
-
| Fallback Security | Basic | `crypto.getRandomValues()` |
|
|
46
|
-
|
|
47
|
-
### 📝 Documentation Updates
|
|
48
|
-
|
|
49
|
-
- **New Documents**:
|
|
50
|
-
- [`PLATFORM.md`](PLATFORM.md) - Platform compatibility guide
|
|
51
|
-
- [`SECURITY.md`](SECURITY.md) - Security documentation
|
|
9
|
+
### 🐛 Bug Fixes
|
|
52
10
|
|
|
53
|
-
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
11
|
+
- Removed dead code: `buildPathTracker` from `functions/state/index.ts` (unused Proxy builder, exported nowhere)
|
|
12
|
+
- Removed double `delete` in state `removeAll` handler (redundant null-check + delete on same key)
|
|
13
|
+
- Removed unbound `globalThis.state` reference in state init (would throw `ReferenceError` in strict mode)
|
|
14
|
+
- Removed `Object.freeze(observer)` referencing undeclared variable (`ReferenceError` on module load)
|
|
15
|
+
- Removed `confirm()` synchronous blocking call from `idb.db.delete` (library must not block main thread)
|
|
57
16
|
|
|
58
|
-
###
|
|
17
|
+
### 🔒 Security Improvements
|
|
59
18
|
|
|
60
|
-
-
|
|
61
|
-
|
|
19
|
+
- Removed `esbuild-sass-plugin` and `esbuild-scss-modules-plugin` from `devDependencies` (unnecessary for a library with no styles)
|
|
20
|
+
- Removed `injectStyle: true`, `sassPlugin()` and `.css` loader from `tsup.config.ts`
|
|
21
|
+
- Deleted `tsup.plugin.injectCss.ts` (code injection vector completely removed from build pipeline)
|
|
22
|
+
- `console.error`/`console.warn` → `console.debug` in `devtools` and `idb` error handlers (consistent debug-only logging policy)
|
|
23
|
+
- `store.set()` now blocks function values instead of silently logging and continuing
|
|
24
|
+
- All `PRIVATE License` headers in `functions/idb/` replaced with `MIT License`
|
|
62
25
|
|
|
63
|
-
|
|
64
|
-
- [`examples/basic.ts`](../examples/basic.ts) - Platform detection added
|
|
65
|
-
- [`examples/store-advanced.ts`](../examples/store-advanced.ts) - isPersistent check
|
|
66
|
-
- [`examples/session-advanced.ts`](../examples/session-advanced.ts) - isPersistent check
|
|
26
|
+
### 🔧 Code Quality
|
|
67
27
|
|
|
68
|
-
|
|
28
|
+
- Added JSDoc to `observerFunction` in `functions/observer/index.ts`
|
|
29
|
+
- Added JSDoc to `cache` global in `functions/cache/index.ts`
|
|
30
|
+
- `lint` and `tsc` pass clean — 0 vulnerabilities from `npm audit`
|
|
69
31
|
|
|
70
|
-
|
|
71
|
-
|--------|--------|-----------|
|
|
72
|
-
| Key validation | Low | Invalid keys now rejected with debug message |
|
|
73
|
-
| Storage key format | Low | Keys now prefixed with session ID |
|
|
32
|
+
### 🆕 API — New in 3.0.2
|
|
74
33
|
|
|
75
|
-
|
|
34
|
+
| Function | Description |
|
|
35
|
+
|----------|-------------|
|
|
36
|
+
| `memorio.isBrowser()` | Returns `true` when running in a browser |
|
|
37
|
+
| `memorio.isNode()` | Returns `true` when running in Node.js |
|
|
38
|
+
| `memorio.isDeno()` | Returns `true` when running in Deno |
|
|
39
|
+
| `memorio.isEdge()` | Returns `true` in Cloudflare Workers, Vercel Edge, etc. |
|
|
40
|
+
| `memorio.getCapabilities()` | Full capabilities object (`platform`, `hasLocalStorage`, `hasIndexedDB`, …) |
|
|
41
|
+
| `memorio.createContext(name?)` | Create multi-tenant isolated context |
|
|
42
|
+
| `memorio.listContexts()` | List all active isolated contexts |
|
|
43
|
+
| `memorio.deleteContext(id)` | Delete isolated context by ID |
|
|
44
|
+
| `memorio.isolate(name?)` | Shorthand alias for `createContext` |
|
|
76
45
|
|
|
77
|
-
|
|
78
|
-
- `config/platform.ts` - Platform detection + Context system
|
|
46
|
+
### 🧪 Tests
|
|
79
47
|
|
|
80
|
-
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
- `functions/session/index.ts` - Added validation + isPersistent
|
|
48
|
+
- Created `tests/jest/tests/observer.test.ts` — 12 tests (deprecation warning, input validation, `.list`, `.remove`, `.removeAll`)
|
|
49
|
+
- Created `tests/jest/tests/useObserver.test.ts` — 12 tests (existence, edge cases, proxy/string deps, auto-discovery, cleanup)
|
|
50
|
+
- **Result: 8 suites · 95 passed · 3 skipped · 0 failed**
|
|
84
51
|
|
|
85
|
-
|
|
52
|
+
### 🗑️ Dependency Changes
|
|
86
53
|
|
|
87
|
-
|
|
54
|
+
| Removed | Reason |
|
|
55
|
+
|---------|--------|
|
|
56
|
+
| `esbuild-sass-plugin@3.7.0` | No SCSS in a library |
|
|
57
|
+
| `esbuild-scss-modules-plugin@1.1.1` | No SCSS in a library |
|
|
58
|
+
| 36 transitive packages | Removed from `node_modules` |
|
|
88
59
|
|
|
89
|
-
|
|
60
|
+
### 📝 Documentation Updates
|
|
90
61
|
|
|
91
|
-
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
- Cache (in-memory)
|
|
98
|
-
- IDB (IndexedDB wrapper)
|
|
99
|
-
- DevTools
|
|
100
|
-
- Logger
|
|
62
|
+
- `docs/README.md`: replaced `console.log` with `console.debug` in usage examples; fixed `esbuild` badge → `tsup`
|
|
63
|
+
- `.github/CHANGELOG.md`: restructured with fix / security / changed sections
|
|
64
|
+
- `.github/HISTORY.md`: complete rewrite through v3.0.2
|
|
65
|
+
- `.github/SECURITY.md`: NIST/NSA standard + OWASP Top 10 mapping
|
|
66
|
+
- `.github/CITATION.cff`: license PRIVATE → MIT to match `package.json`
|
|
67
|
+
- `.project/*`: all context documents updated to v3.0.2
|
|
101
68
|
|
|
102
69
|
---
|
|
103
70
|
|
|
104
|
-
##
|
|
105
|
-
|
|
106
|
-
### 1. Platform Detection (Optional)
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
// NEW: Check platform
|
|
110
|
-
if (memorio.isNode()) {
|
|
111
|
-
console.log('Running on server')
|
|
112
|
-
}
|
|
113
|
-
```
|
|
71
|
+
## v2.9.0 — 2026-05-13
|
|
114
72
|
|
|
115
|
-
###
|
|
73
|
+
### Added
|
|
74
|
+
- DevTools — `memorio.devtools.inspect()`, `stats()`, `exportData()`
|
|
75
|
+
- Logger with full history, stats and export
|
|
76
|
+
- Platform detection (`isBrowser`, `isNode`, `isDeno`, `isEdge`, `getCapabilities`)
|
|
77
|
+
- Session isolation via `crypto.randomUUID()`
|
|
116
78
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
console.warn('Data will be lost on restart!')
|
|
121
|
-
}
|
|
122
|
-
```
|
|
79
|
+
### Changed
|
|
80
|
+
- Updated dependencies to latest versions
|
|
81
|
+
- Improved cross-platform support (Deno, Edge Workers, Node.js)
|
|
123
82
|
|
|
124
|
-
###
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
// NEW: Create isolated context per request
|
|
128
|
-
app.use((req, res, next) => {
|
|
129
|
-
req.ctx = memorio.createContext(`req-${req.id}`)
|
|
130
|
-
next()
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
app.get('/data', (req, res) => {
|
|
134
|
-
req.ctx.state.user = getUser()
|
|
135
|
-
// Each request has isolated state
|
|
136
|
-
})
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### 4. Key Validation (Automatic)
|
|
140
|
-
|
|
141
|
-
```typescript
|
|
142
|
-
// Keys are now validated - invalid keys rejected
|
|
143
|
-
store.set('valid-key', 'value') // ✅ Works
|
|
144
|
-
store.set('key with spaces', 'x') // ❌ Rejected (debug message)
|
|
145
|
-
store.set('key>1000chars', 'x') // ❌ Rejected if >512 chars
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
|
-
## Comparison Table: v2.6.x vs v2.7.0
|
|
151
|
-
|
|
152
|
-
| Feature | v2.6.x | v2.7.0 |
|
|
153
|
-
|---------|--------|--------|
|
|
154
|
-
| **Platform Support** | | |
|
|
155
|
-
| Browser | ✅ | ✅ |
|
|
156
|
-
| Node.js | ⚠️ Partial | ✅ Full |
|
|
157
|
-
| Deno | ❌ | ✅ Full |
|
|
158
|
-
| Edge Workers | ❌ | ✅ |
|
|
159
|
-
| **Security** | | |
|
|
160
|
-
| Secure Random | ❌ | ✅ |
|
|
161
|
-
| Key Validation | ❌ | ✅ |
|
|
162
|
-
| Session Isolation | ❌ | ✅ |
|
|
163
|
-
| Context Isolation | ❌ | ✅ |
|
|
164
|
-
| **API** | | |
|
|
165
|
-
| isPersistent | ❌ | ✅ |
|
|
166
|
-
| createContext | ❌ | ✅ |
|
|
167
|
-
| Platform APIs | ❌ | ✅ |
|
|
168
|
-
| **Documentation** | | |
|
|
169
|
-
| Platform Guide | ❌ | ✅ |
|
|
170
|
-
| Security Docs | ❌ | ✅ |
|
|
171
|
-
| Platform Tables | ❌ | ✅ |
|
|
83
|
+
### Security
|
|
84
|
+
- Secure random session IDs replaced `Math.random()`
|
|
85
|
+
- Key validation (max 512 chars + character whitelist)
|
|
172
86
|
|
|
173
87
|
---
|
|
174
88
|
|
|
175
|
-
##
|
|
176
|
-
|
|
177
|
-
| Feature | Status | Alternative |
|
|
178
|
-
|---------|--------|---------|
|
|
179
|
-
| `observer()` | ⚠️ Deprecated | Use `useObserver()` in React |
|
|
180
|
-
| Global state in Node.js | ⚡ Discouraged | Use `memorio.createContext()` |
|
|
181
|
-
|
|
182
|
-
---
|
|
89
|
+
## v2.5.0 — 2026-02-17
|
|
183
90
|
|
|
184
|
-
|
|
91
|
+
- Initial release of memorio (state, store, session, cache, idb)
|
|
92
|
+
- Observer pattern (`observer`)
|
|
93
|
+
- `useObserver` React hook
|
package/docs/markdown/IDB.md
CHANGED
|
@@ -29,7 +29,7 @@ idb.data.set('myApp', 'users', { id: 1, name: 'Mario' });
|
|
|
29
29
|
|
|
30
30
|
// Get data
|
|
31
31
|
const user = idb.data.get('myApp', 'users', 1);
|
|
32
|
-
console.
|
|
32
|
+
console.debug(user.name); // "Mario"
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
### Example 2: Intermediate
|
|
@@ -45,7 +45,7 @@ idb.data.set('store', 'products', { id: 2, name: 'Banana', price: 0.8 });
|
|
|
45
45
|
|
|
46
46
|
// List databases
|
|
47
47
|
const databases = idb.db.list();
|
|
48
|
-
console.
|
|
48
|
+
console.debug(databases); // ['myApp', 'store']
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
### Example 3: Advanced
|
|
@@ -65,7 +65,7 @@ idb.db.delete('store');
|
|
|
65
65
|
|
|
66
66
|
// Handle quota
|
|
67
67
|
const quota = idb.db.quota();
|
|
68
|
-
console.
|
|
68
|
+
console.debug(`Using ${quota.used} of ${quota.total} bytes`);
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
---
|
package/docs/markdown/LOGGER.md
CHANGED
|
@@ -107,7 +107,7 @@ state.user = { name: 'John' }
|
|
|
107
107
|
|
|
108
108
|
```javascript
|
|
109
109
|
const stats = memorio.logger.getStats()
|
|
110
|
-
console.
|
|
110
|
+
console.debug(stats)
|
|
111
111
|
// { total: 15, state: 5, store: 3, session: 2, cache: 5, set: 10, get: 0, delete: 3, clear: 2 }
|
|
112
112
|
```
|
|
113
113
|
|
|
@@ -143,5 +143,5 @@ const stateLogs = logs.filter(l => l.module === 'state')
|
|
|
143
143
|
const setOperations = logs.filter(l => l.action === 'set')
|
|
144
144
|
|
|
145
145
|
// Export for debugging
|
|
146
|
-
console.
|
|
146
|
+
console.debug(memorio.logger.exportLogs())
|
|
147
147
|
```
|
|
@@ -25,7 +25,7 @@ import 'memorio';
|
|
|
25
25
|
console.warn('observer() is deprecated. Please use useObserver() for React or memorio.dispatch for vanilla JS.');
|
|
26
26
|
|
|
27
27
|
observer('state.counter', (newValue) => {
|
|
28
|
-
console.
|
|
28
|
+
console.debug('Counter is now:', newValue);
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
state.counter = 1;
|
|
@@ -42,7 +42,7 @@ state.counter = 5;
|
|
|
42
42
|
```javascript
|
|
43
43
|
// Observer with old value
|
|
44
44
|
observer('state.user', (newValue, oldValue) => {
|
|
45
|
-
console.
|
|
45
|
+
console.debug(`User changed from ${oldValue?.name} to ${newValue?.name}`);
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
state.user = { name: 'Mario' };
|
|
@@ -60,7 +60,7 @@ const obs1 = observer('state.data', handler1);
|
|
|
60
60
|
const obs2 = observer('state.data', handler2);
|
|
61
61
|
|
|
62
62
|
// List all observers
|
|
63
|
-
console.
|
|
63
|
+
console.debug(observer.list);
|
|
64
64
|
// Output: [{ name: 'state.data', id: '...' }, ...]
|
|
65
65
|
|
|
66
66
|
// Remove specific observer
|
|
@@ -122,7 +122,7 @@ observer('state.counter', () => {
|
|
|
122
122
|
```javascript
|
|
123
123
|
useEffect(() => {
|
|
124
124
|
const handleChange = (newVal) => {
|
|
125
|
-
console.
|
|
125
|
+
console.debug('Changed:', newVal);
|
|
126
126
|
};
|
|
127
127
|
|
|
128
128
|
observer('state.data', handleChange);
|