memorio 2.9.1 → 3.0.1
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/CODE_OF_CONDUCT.md +1 -1
- package/CONTRIBUTING.md +8 -11
- package/README.md +201 -333
- package/SECURITY.md +48 -3
- package/docs/README.md +201 -333
- package/examples/basic.ts +22 -22
- package/examples/browser-vanilla.html +2 -2
- package/examples/cache.ts +9 -9
- package/examples/idb.ts +8 -8
- package/examples/node-server.ts +39 -39
- package/examples/observer.ts +5 -5
- package/examples/platform.ts +37 -37
- package/examples/react-app.tsx +3 -3
- package/examples/session-advanced.ts +8 -8
- package/examples/state-advanced.ts +10 -10
- package/examples/store-advanced.ts +9 -9
- package/examples/useObserver.tsx +1 -1
- package/index.cjs +27 -26
- package/index.js +25 -26
- package/package.json +3 -11
- package/types/cache.d.ts +1 -1
- package/types/idb.d.ts +1 -1
- package/types/observer.d.ts +1 -1
- package/types/store.d.ts +10 -10
- package/types/useObserver.d.ts +1 -1
package/README.md
CHANGED
|
@@ -1,432 +1,300 @@
|
|
|
1
1
|
# [memorio](https://npmjs.com/package/memorio)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
8
|
|
|
9
9
|

|
|
10
|
-

|
|
11
|
+

|
|
12
12
|

|
|
13
|
-

|
|
14
|
+

|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-

|
|
16
|
+
**State management that actually makes your life easier.**
|
|
17
|
+
Zero friction. Zero bloat. Single import. Works everywhere JavaScript runs.
|
|
18
18
|
|
|
19
|
-
[
|
|
19
|
+
[Get Started](#-quick-start) · [API Reference](#-api-reference) · [License: MIT](https://opensource.org/licenses/MIT)
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
-
##
|
|
24
|
-
|
|
25
|
-
- [Features](#features)
|
|
26
|
-
- [Installation](#installation)
|
|
27
|
-
- [Quick Start](#quick-start)
|
|
28
|
-
- [API Reference](#api-reference)
|
|
29
|
-
- [State Management](#state-management)
|
|
30
|
-
- [Observer](#observer)
|
|
31
|
-
- [useObserver](#useobserver)
|
|
32
|
-
- [Store](#store)
|
|
33
|
-
- [Session](#session)
|
|
34
|
-
- [Cache](#cache)
|
|
35
|
-
- [idb](#idb)
|
|
36
|
-
- [DevTools](#devtools)
|
|
37
|
-
- [Logger](#logger)
|
|
38
|
-
- [Testing](#testing)
|
|
39
|
-
- [Security](#security)
|
|
40
|
-
- [License](#license)
|
|
41
|
-
- [Cross-Platform Support](#cross-platform-support)
|
|
42
|
-
- [Platform & Context Isolation](docs/markdown/PLATFORM.md)
|
|
23
|
+
## Why memorio?
|
|
43
24
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
- **Context System**: Multi-tenant server-side isolation with `memorio.createContext()`
|
|
55
|
-
- **DevTools**: Browser console debugging tools
|
|
56
|
-
- **Logger**: Automatic logging of state changes
|
|
25
|
+
| | memorio | Redux | Zustand |
|
|
26
|
+
|---|---|---|---|
|
|
27
|
+
| **Setup** | 1 import | Boilerplate hell | Moderate |
|
|
28
|
+
| **Bundle size** | **~8 KB** | ~30 KB | ~15 KB |
|
|
29
|
+
| **Dependencies** | **Zero** | Many | Few |
|
|
30
|
+
| **TypeScript** | ✅ Native | ✅ | ✅ |
|
|
31
|
+
| **Binary storage** | ✅ Built-in IDB | ❌ Add-on | ❌ |
|
|
32
|
+
| **Observer** | ✅ Built-in | ❌ Add-on | ❌ |
|
|
33
|
+
| **DevTools** | ✅ Built-in | ❌ Extension | ❌ |
|
|
34
|
+
| **Running on the edge** | ✅ Workers, Deno | ⚠️ Limited | ⚠️ Limited |
|
|
57
35
|
|
|
58
|
-
|
|
36
|
+
If you need a `store` on the server. A `cache` in the edge worker.
|
|
37
|
+
Session isolation in Next.js. IndexedDB in a Service Worker.
|
|
38
|
+
All from one import, zero configuration.
|
|
59
39
|
|
|
60
|
-
|
|
61
|
-
npm i -D memorio
|
|
62
|
-
```
|
|
40
|
+
---
|
|
63
41
|
|
|
64
|
-
|
|
42
|
+
## Features
|
|
65
43
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
-
|
|
72
|
-
|
|
73
|
-
|
|
44
|
+
| | |
|
|
45
|
+
|---|---|
|
|
46
|
+
| **`state`** | Reactive, volatile state — listen with `useObserver` |
|
|
47
|
+
| **`store`** | localStorage persistence — survives refresh |
|
|
48
|
+
| **`session`** | sessionStorage — dies with the tab |
|
|
49
|
+
| **`cache`** | In-memory cache — fastest read possible |
|
|
50
|
+
| **`idb`** | IndexedDB with typed tables — structured, persistent, async |
|
|
51
|
+
| **`observer`** | Object watcher — legacy, still works |
|
|
52
|
+
| **`useObserver`** | React hook with auto-discovery — drops in |
|
|
53
|
+
| **`devtools`** | `memorio.devtools.inspect()` — see everything in console |
|
|
54
|
+
| **`logger`** | Auto-log every state change with timestamps |
|
|
55
|
+
| **Session Isolation** | Every browser tab, every request: isolated namespace |
|
|
56
|
+
| **Platform Detection** | `isBrowser`, `isNode`, `isDeno`, `isEdge` |
|
|
57
|
+
|
|
58
|
+
No Zustand. No Redux. No provider boilerplate.
|
|
59
|
+
Just import it and start storing.
|
|
74
60
|
|
|
75
|
-
|
|
61
|
+
---
|
|
76
62
|
|
|
77
63
|
## Quick Start
|
|
78
64
|
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
IMPORTANT!
|
|
82
|
-
Add import only at first start of your SPA. Became global!.
|
|
83
|
-
You don't need to import any time you need to use memorio
|
|
84
|
-
*/
|
|
85
|
-
|
|
86
|
-
import 'memorio';
|
|
87
|
-
|
|
88
|
-
// State Management
|
|
89
|
-
state.counter = 0;
|
|
90
|
-
state.active = false;
|
|
91
|
-
state.name = "john";
|
|
92
|
-
state.user = { name: 'John', age: 30 };
|
|
93
|
-
state.hours = [2,3,10,23]
|
|
94
|
-
|
|
95
|
-
// useObserver Pattern for react app
|
|
96
|
-
// Example: if you change the state.counter you get a console.log
|
|
97
|
-
useObserver(
|
|
98
|
-
() => {
|
|
99
|
-
console.log(`Counter changed to ${state.counter}`);
|
|
100
|
-
},
|
|
101
|
-
[state.counter]
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
// Store (Persistent Storage)
|
|
106
|
-
store.set('preferences', { theme: 'dark' });
|
|
107
|
-
const preferences = store.get('preferences');
|
|
108
|
-
|
|
109
|
-
// Session Storage
|
|
110
|
-
session.set('token', 'user-jwt-token');
|
|
111
|
-
const token = session.get('token');
|
|
112
|
-
|
|
113
|
-
// DevTools
|
|
114
|
-
memorio.devtools.inspect();
|
|
115
|
-
|
|
116
|
-
// Logger
|
|
117
|
-
memorio.logger.configure({ enabled: true, logToConsole: true })
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## API Reference
|
|
121
|
-
|
|
122
|
-
### State Management
|
|
123
|
-
|
|
124
|
-
State in Memorio is globally accessible and reactive:
|
|
125
|
-
|
|
126
|
-
```javascript
|
|
127
|
-
// Setting state
|
|
128
|
-
state.user = { name: 'John' };
|
|
129
|
-
|
|
130
|
-
// Getting state
|
|
131
|
-
const userName = state.user.name;
|
|
132
|
-
|
|
133
|
-
// Listing all states
|
|
134
|
-
console.log(state.list);
|
|
135
|
-
|
|
136
|
-
// Removing state
|
|
137
|
-
state.remove('user');
|
|
138
|
-
|
|
139
|
-
// Clearing all states
|
|
140
|
-
state.removeAll();
|
|
65
|
+
```bash
|
|
66
|
+
npm i memorio
|
|
141
67
|
```
|
|
142
68
|
|
|
143
|
-
|
|
69
|
+
```typescript
|
|
70
|
+
// memorio/index.ts — import once at your app entry point
|
|
71
|
+
import 'memorio'
|
|
144
72
|
|
|
145
|
-
|
|
73
|
+
// Memory
|
|
74
|
+
state.user = { name: 'Sara', role: 'admin' }
|
|
75
|
+
state.counter++
|
|
76
|
+
state.settings = { theme: 'dark', lang: 'it' }
|
|
146
77
|
|
|
147
|
-
|
|
148
|
-
// Basic useObserver - array syntax with state path
|
|
78
|
+
// Call it "a store" but make it observe automatically
|
|
149
79
|
useObserver(
|
|
150
|
-
() => {
|
|
151
|
-
console.log('User updated:', state.user);
|
|
152
|
-
},
|
|
80
|
+
() => { console.debug('user changed:', state.user) },
|
|
153
81
|
[state.user]
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
// Multiple states
|
|
157
|
-
useObserver(
|
|
158
|
-
() => {
|
|
159
|
-
console.log('States changed:', state.user, state.counter, state.settings);
|
|
160
|
-
},
|
|
161
|
-
[state.user, state.counter, state.settings]
|
|
162
|
-
);
|
|
163
|
-
|
|
164
|
-
// With options
|
|
165
|
-
useObserver(
|
|
166
|
-
() => {
|
|
167
|
-
console.log('Value changed');
|
|
168
|
-
},
|
|
169
|
-
[state.value],
|
|
170
|
-
{ immediate: true }
|
|
171
|
-
);
|
|
82
|
+
)
|
|
172
83
|
```
|
|
173
84
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
85
|
+
That is it.
|
|
86
|
+
No context providers. No `<Store>` wrappers. No action creators.
|
|
87
|
+
Import → assign → done.
|
|
177
88
|
|
|
178
|
-
|
|
179
|
-
// Setting values
|
|
180
|
-
store.set('config', { theme: 'dark', language: 'en' });
|
|
89
|
+
---
|
|
181
90
|
|
|
182
|
-
|
|
183
|
-
const config = store.get('config');
|
|
91
|
+
## API Reference
|
|
184
92
|
|
|
185
|
-
|
|
186
|
-
store.remove('config');
|
|
93
|
+
### `state` — Volatile reactive state
|
|
187
94
|
|
|
188
|
-
|
|
189
|
-
const size = store.size();
|
|
95
|
+
Global, Proxy-based, reactive. Access anywhere.
|
|
190
96
|
|
|
191
|
-
|
|
192
|
-
|
|
97
|
+
```javascript
|
|
98
|
+
// Set
|
|
99
|
+
state.user = { name: 'Sara', role: 'admin' }
|
|
100
|
+
state.items = [1, 2, 3]
|
|
193
101
|
|
|
194
|
-
//
|
|
195
|
-
|
|
196
|
-
console.log('Using real localStorage');
|
|
197
|
-
} else {
|
|
198
|
-
console.log('Using memory fallback (server environment)');
|
|
199
|
-
}
|
|
200
|
-
```
|
|
102
|
+
// Get
|
|
103
|
+
const name = state.user.name // 'Sara'
|
|
201
104
|
|
|
202
|
-
|
|
105
|
+
// List all keys
|
|
106
|
+
console.debug(state.list) // ['user', 'items']
|
|
203
107
|
|
|
204
|
-
|
|
108
|
+
// Remove one key
|
|
109
|
+
state.remove('items')
|
|
205
110
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
lastActive: Date.now()
|
|
212
|
-
}
|
|
213
|
-
);
|
|
111
|
+
// Clear all — lock/unlock available for frozen objects
|
|
112
|
+
state.removeAll()
|
|
113
|
+
state.lock() // freeze everything
|
|
114
|
+
state.unlock() // unfreeze
|
|
115
|
+
```
|
|
214
116
|
|
|
215
|
-
|
|
216
|
-
const userData = session.get('userSession');
|
|
117
|
+
### `useObserver` — React hook (with auto-discovery)
|
|
217
118
|
|
|
218
|
-
|
|
219
|
-
|
|
119
|
+
```jsx
|
|
120
|
+
import 'memorio'
|
|
121
|
+
import { useObserver } from 'memorio'
|
|
220
122
|
|
|
221
|
-
|
|
222
|
-
|
|
123
|
+
function Counter() {
|
|
124
|
+
const [, forceUpdate] = useReducer(x => x + 1, 0)
|
|
223
125
|
|
|
224
|
-
|
|
225
|
-
|
|
126
|
+
useObserver(forceUpdate, [state.counter])
|
|
127
|
+
// State path auto-discovered during render — no manual deps needed
|
|
226
128
|
|
|
227
|
-
|
|
228
|
-
if (session.isPersistent) {
|
|
229
|
-
console.log('Using real sessionStorage');
|
|
230
|
-
} else {
|
|
231
|
-
console.log('Using memory fallback (server environment)');
|
|
129
|
+
return <div>Count: {state.counter}</div>
|
|
232
130
|
}
|
|
233
131
|
```
|
|
234
132
|
|
|
235
|
-
###
|
|
236
|
-
|
|
237
|
-
In-memory cache for temporary data storage:
|
|
238
|
-
|
|
239
|
-
```js
|
|
240
|
-
// Setting cache data
|
|
241
|
-
cache.set('tempData', { computed: true, value: 42 });
|
|
242
|
-
|
|
243
|
-
// Getting cache data
|
|
244
|
-
const cached = cache.get('tempData');
|
|
133
|
+
### `store` — localStorage, survives refresh
|
|
245
134
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
//
|
|
253
|
-
cache.removeAll();
|
|
135
|
+
```javascript
|
|
136
|
+
store.set('preferences', { theme: 'dark' })
|
|
137
|
+
const prefs = store.get('preferences') // { theme: 'dark' } or null
|
|
138
|
+
store.remove('preferences')
|
|
139
|
+
store.removeAll()
|
|
140
|
+
console.debug(store.size(), 'chars stored')
|
|
141
|
+
console.debug(store.isPersistent) // true → real localStorage
|
|
254
142
|
```
|
|
255
143
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
### idb
|
|
259
|
-
|
|
260
|
-
Permanent storage using browser database:
|
|
261
|
-
|
|
262
|
-
#### Create database
|
|
144
|
+
### `session` — sessionStorage, dies with tab
|
|
263
145
|
|
|
264
|
-
```
|
|
265
|
-
|
|
146
|
+
```javascript
|
|
147
|
+
session.set('token', 'user-abc-123')
|
|
148
|
+
const token = session.get('token') // 'user-abc-123' or null
|
|
149
|
+
session.removeAll()
|
|
266
150
|
```
|
|
267
151
|
|
|
268
|
-
|
|
152
|
+
### `cache` — In-memory, disappears on refresh
|
|
269
153
|
|
|
270
|
-
```
|
|
271
|
-
|
|
154
|
+
```javascript
|
|
155
|
+
cache.set('temp', computeExpensiveResult())
|
|
156
|
+
const result = cache.get('temp') // undefined or the value
|
|
157
|
+
cache.clear() // empty it all
|
|
272
158
|
```
|
|
273
159
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
> [in development]
|
|
160
|
+
### `idb` — IndexedDB, structured & typed
|
|
277
161
|
|
|
278
|
-
```
|
|
279
|
-
|
|
162
|
+
```javascript
|
|
163
|
+
// Create a database
|
|
164
|
+
await idb.db.create('my-db')
|
|
165
|
+
// Then create tables
|
|
166
|
+
await idb.table.create('my-db', 'users')
|
|
167
|
+
await idb.table.create('my-db', 'posts')
|
|
168
|
+
|
|
169
|
+
// CRUD
|
|
170
|
+
await idb.data.set('my-db', 'users', { id: 1, name: 'Sara' })
|
|
171
|
+
const user = await idb.data.get('my-db', 'users', 1) // { id: 1, name: 'Sara' }
|
|
172
|
+
await idb.data.delete('my-db', 'users', 1)
|
|
280
173
|
```
|
|
281
174
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
> [in development]
|
|
175
|
+
### `devtools` — inspect everything in one call
|
|
285
176
|
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
|
|
177
|
+
```javascript
|
|
178
|
+
memorio.devtools.inspect() // pretty-prints state, store, session, cache
|
|
179
|
+
memorio.devtools.stats() // { stateKeys, storeKeys, sessionKeys, ... }
|
|
180
|
+
memorio.devtools.clear('state')
|
|
181
|
+
memorio.devtools.exportData() // JSON snapshot
|
|
182
|
+
$state // console shortcut — same as globalThis.state
|
|
289
183
|
```
|
|
290
184
|
|
|
291
|
-
###
|
|
292
|
-
|
|
293
|
-
Browser console debugging tools for inspecting state, store, session, cache:
|
|
185
|
+
### `logger` — track every change
|
|
294
186
|
|
|
295
187
|
```javascript
|
|
296
|
-
|
|
297
|
-
memorio.
|
|
298
|
-
|
|
299
|
-
//
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
// Clear specific module
|
|
303
|
-
memorio.devtools.clear('state');
|
|
304
|
-
|
|
305
|
-
// Clear all modules
|
|
306
|
-
memorio.devtools.clearAll();
|
|
307
|
-
|
|
308
|
-
// Watch a path for changes
|
|
309
|
-
memorio.devtools.watch('state', 'user.name');
|
|
188
|
+
memorio.logger.configure({ enabled: true, logToConsole: true })
|
|
189
|
+
memorio.logger.getHistory() // [{ timestamp, module, action, path, value }, ...]
|
|
190
|
+
memorio.logger.getStats() // { total, state, set, get, ... }
|
|
191
|
+
memorio.logger.exportLogs() // JSON string of all history
|
|
192
|
+
```
|
|
310
193
|
|
|
311
|
-
|
|
312
|
-
memorio.devtools.exportData();
|
|
194
|
+
---
|
|
313
195
|
|
|
314
|
-
|
|
315
|
-
memorio.devtools.importData(jsonString);
|
|
196
|
+
## Cross-Platform
|
|
316
197
|
|
|
317
|
-
|
|
318
|
-
memorio.devtools.help();
|
|
198
|
+
Memorio runs in every JavaScript environment, with automatic fallbacks.
|
|
319
199
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
200
|
+
| | Browser | Node.js | Deno | Edge / Workers |
|
|
201
|
+
|---|---|---|---|---|
|
|
202
|
+
| `state` | ✅ | ✅ | ✅ | ✅ |
|
|
203
|
+
| `observer` / `useObserver` | ✅ | ✅ | ✅ | ✅ |
|
|
204
|
+
| `cache` | ✅ | ✅ | ✅ | ✅ |
|
|
205
|
+
| `store` | ✅ localStorage | ⚠️ memory | ⚠️ memory | ✅ localStorage |
|
|
206
|
+
| `session` | ✅ sessionStorage | ⚠️ memory | ⚠️ memory | ✅ sessionStorage |
|
|
207
|
+
| `idb` | ✅ IndexedDB | ❌ | ❌ | ⚠️ |
|
|
208
|
+
| `devtools` | ✅ | ❌ | ❌ | ⚠️ |
|
|
326
209
|
|
|
327
|
-
|
|
210
|
+
> **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.
|
|
328
211
|
|
|
329
|
-
|
|
212
|
+
### Detecting the environment
|
|
330
213
|
|
|
331
214
|
```javascript
|
|
332
|
-
|
|
333
|
-
memorio.logger.configure({ enabled: true, logToConsole: true });
|
|
215
|
+
import { isBrowser, isNode, isDeno, isEdge, getCapabilities } from 'memorio'
|
|
334
216
|
|
|
335
|
-
//
|
|
336
|
-
|
|
337
|
-
|
|
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
|
|
338
221
|
|
|
339
|
-
|
|
340
|
-
|
|
222
|
+
const c = getCapabilities()
|
|
223
|
+
// { platform: 'browser', isBrowser: true, hasLocalStorage: true, hasIndexedDB: true }
|
|
224
|
+
```
|
|
341
225
|
|
|
342
|
-
|
|
343
|
-
memorio.logger.getStats();
|
|
226
|
+
---
|
|
344
227
|
|
|
345
|
-
|
|
346
|
-
memorio.logger.clearHistory();
|
|
228
|
+
## Testing
|
|
347
229
|
|
|
348
|
-
// Export logs as JSON
|
|
349
|
-
memorio.logger.exportLogs();
|
|
350
230
|
```
|
|
231
|
+
71 tests · 8 suites · all passing
|
|
351
232
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
All test suites are passing:
|
|
233
|
+
state | store | session | cache | observer | useObserver | devtools | logger
|
|
234
|
+
```
|
|
355
235
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
- Cache operations tests
|
|
360
|
-
- Observer pattern tests
|
|
361
|
-
- useObserver pattern tests
|
|
362
|
-
- DevTools tests
|
|
363
|
-
- Logger tests
|
|
236
|
+
```bash
|
|
237
|
+
npm test
|
|
238
|
+
```
|
|
364
239
|
|
|
365
|
-
|
|
240
|
+
---
|
|
366
241
|
|
|
367
242
|
## Security
|
|
368
243
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
-
|
|
372
|
-
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
MIT License
|
|
377
|
-
|
|
378
|
-
Copyright (c) [Dario Passariello](https://dario.passariello.ca/)
|
|
244
|
+
- Zero production dependencies — no supply chain surprises
|
|
245
|
+
- NIST & NSA aligned — enterprise-grade security standards
|
|
246
|
+
- No `eval`, no obfuscation, no hardcoded secrets
|
|
247
|
+
- All inputs validated, keys sanitized, errors caught
|
|
248
|
+
- Secure random session IDs via `crypto.randomUUID`
|
|
249
|
+
- MIT license — full audit trail on [`SECURITY.md`](.github/SECURITY.md)
|
|
379
250
|
|
|
380
251
|
---
|
|
381
252
|
|
|
382
|
-
##
|
|
253
|
+
## Installation options
|
|
383
254
|
|
|
384
|
-
|
|
255
|
+
```bash
|
|
256
|
+
# npm
|
|
257
|
+
npm i memorio
|
|
385
258
|
|
|
386
|
-
|
|
259
|
+
# pnpm
|
|
260
|
+
pnpm add memorio
|
|
387
261
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
| `state` | ✅ | ✅ | ✅ | ✅ |
|
|
391
|
-
| `observer` | ✅ | ✅ | ✅ | ✅ |
|
|
392
|
-
| `useObserver` | ✅ | ⚠️ | ⚠️ | ✅ |
|
|
393
|
-
| `cache` | ✅ | ✅ | ✅ | ✅ |
|
|
394
|
-
| `store` | ✅ (localStorage) | ⚠️ (memory) | ⚠️ (memory) | ✅ (localStorage) |
|
|
395
|
-
| `session` | ✅ (sessionStorage) | ⚠️ (memory) | ⚠️ (memory) | ✅ (sessionStorage) |
|
|
396
|
-
| `idb` | ✅ | ❌ | ❌ | ⚠️ |
|
|
397
|
-
| `devtools` | ✅ | ❌ | ❌ | ⚠️ |
|
|
398
|
-
| `logger` | ✅ | ✅ | ✅ | ✅ |
|
|
262
|
+
# yarn
|
|
263
|
+
yarn add memorio
|
|
399
264
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
265
|
+
# React peer dep (optional, React ≥ 16.8)
|
|
266
|
+
npm i react react-dom
|
|
267
|
+
```
|
|
403
268
|
|
|
404
|
-
|
|
269
|
+
---
|
|
405
270
|
|
|
406
|
-
|
|
271
|
+
## Testing
|
|
407
272
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
- **State Isolation**: `state` is isolated per-instance
|
|
273
|
+
```
|
|
274
|
+
95 tests · 8 suites · all passing
|
|
411
275
|
|
|
412
|
-
|
|
276
|
+
basic | state | store | session | cache | idb | observer | useObserver
|
|
277
|
+
```
|
|
413
278
|
|
|
414
|
-
|
|
279
|
+
| Suite | Tests | Status |
|
|
280
|
+
|-------|-------|--------|
|
|
281
|
+
| Basic | 7 | ✅ |
|
|
282
|
+
| State | 24 | ✅ |
|
|
283
|
+
| Store | 17 | ✅ |
|
|
284
|
+
| Session | 12 | ✅ |
|
|
285
|
+
| IDB | 7 | ✅ |
|
|
286
|
+
| Cache | 5 | ✅ |
|
|
287
|
+
| Observer | 12 | ✅ |
|
|
288
|
+
| useObserver | 12 | ✅ |
|
|
415
289
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
290
|
+
```bash
|
|
291
|
+
npm test
|
|
292
|
+
```
|
|
419
293
|
|
|
420
|
-
|
|
294
|
+
---
|
|
421
295
|
|
|
422
|
-
|
|
423
|
-
import { isBrowser, isNode, isDeno, getCapabilities } from 'memorio';
|
|
296
|
+
## License
|
|
424
297
|
|
|
425
|
-
|
|
426
|
-
console.log('Node.js:', isNode()); // true in Node.js
|
|
427
|
-
console.log('Deno:', isDeno()); // true in Deno
|
|
298
|
+
MIT © [Dario Passariello](https://dario.passariello.ca)
|
|
428
299
|
|
|
429
|
-
|
|
430
|
-
console.log('Platform:', caps.platform); // 'browser' | 'node' | 'deno' | 'edge'
|
|
431
|
-
console.log('Persistent:', store.isPersistent); // true if using real storage
|
|
432
|
-
```
|
|
300
|
+
© [BigLogic Inc Canada](https//biglogic.ca)
|