memorio 2.6.6 → 2.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/README.md +102 -0
- package/examples/basic.ts +41 -1
- package/examples/browser-vanilla.html +358 -0
- package/examples/node-server.ts +308 -0
- package/examples/platform.ts +115 -0
- package/examples/react-app.tsx +357 -0
- package/examples/session-advanced.ts +13 -0
- package/examples/store-advanced.ts +13 -0
- package/index.cjs +331 -119
- package/index.js +331 -119
- package/package.json +17 -12
- package/types/memorio.d.ts +22 -0
- package/types/session.d.ts +7 -6
- package/types/state.d.ts +1 -6
- package/types/store.d.ts +6 -7
package/README.md
CHANGED
|
@@ -39,6 +39,8 @@
|
|
|
39
39
|
- [Testing](#testing)
|
|
40
40
|
- [Security](#security)
|
|
41
41
|
- [License](#license)
|
|
42
|
+
- [Cross-Platform Support](#cross-platform-support)
|
|
43
|
+
- [Platform & Context Isolation](docs/markdown/PLATFORM.md)
|
|
42
44
|
|
|
43
45
|
## Features
|
|
44
46
|
|
|
@@ -48,6 +50,9 @@
|
|
|
48
50
|
- Type-safe with full TypeScript support
|
|
49
51
|
- Comprehensive test coverage
|
|
50
52
|
- Easy debugging with proxy-based state
|
|
53
|
+
- **Cross-platform**: Works in Browser, Node.js, Deno, and Edge Workers
|
|
54
|
+
- **Session Isolation**: Each session/request gets isolated state namespace
|
|
55
|
+
- **Context System**: Multi-tenant server-side isolation with `memorio.createContext()`
|
|
51
56
|
|
|
52
57
|
## ⚠️ Enterprise Use
|
|
53
58
|
|
|
@@ -311,3 +316,100 @@ Security scans and reports are available at:
|
|
|
311
316
|
MIT License
|
|
312
317
|
|
|
313
318
|
Copyrigth (c) [Dario Passariello](https://dario.passariello.ca/)
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## Cross-Platform Support
|
|
323
|
+
|
|
324
|
+
Memorio is designed to work across multiple JavaScript environments:
|
|
325
|
+
|
|
326
|
+
### Platform Compatibility
|
|
327
|
+
|
|
328
|
+
| Feature | Browser | Node.js | Deno | Edge Workers |
|
|
329
|
+
|---------|---------|---------|------|---------------|
|
|
330
|
+
| `state` | ✅ | ✅ | ✅ | ✅ |
|
|
331
|
+
| `observer` | ✅ | ✅ | ✅ | ✅ |
|
|
332
|
+
| `useObserver` | ✅ | ⚠️ | ⚠️ | ✅ |
|
|
333
|
+
| `cache` | ✅ | ✅ | ✅ | ✅ |
|
|
334
|
+
| `store` | ✅ (localStorage) | ⚠️ (memory) | ⚠️ (memory) | ✅ (localStorage) |
|
|
335
|
+
| `session` | ✅ (sessionStorage) | ⚠️ (memory) | ⚠️ (memory) | ✅ (sessionStorage) |
|
|
336
|
+
| `idb` | ✅ | ❌ | ❌ | ⚠️ |
|
|
337
|
+
|
|
338
|
+
- ✅ Full support
|
|
339
|
+
- ⚠️ Partial support (fallback to in-memory)
|
|
340
|
+
- ❌ Not available
|
|
341
|
+
|
|
342
|
+
### Session Isolation
|
|
343
|
+
|
|
344
|
+
Memorio provides automatic session isolation to prevent state leakage between different requests or contexts:
|
|
345
|
+
|
|
346
|
+
- **Unique Session IDs**: Each import gets a unique session identifier
|
|
347
|
+
- **Namespaced Storage**: `store` and `session` keys are prefixed with session ID
|
|
348
|
+
- **State Isolation**: `state` is isolated per-instance
|
|
349
|
+
|
|
350
|
+
This ensures that in server-side environments (Node.js/Deno), different requests don't share state data.
|
|
351
|
+
|
|
352
|
+
### Best Practices
|
|
353
|
+
|
|
354
|
+
1. **For Client-Side**: Use all features freely - store, session, idb work with real browser storage
|
|
355
|
+
2. **For Server-Side**: Use `state` and `cache` for in-memory data; store/session fall back to memory
|
|
356
|
+
3. **For Edge Workers**: Same as browser; localStorage/sessionStorage available
|
|
357
|
+
|
|
358
|
+
### Checking Platform
|
|
359
|
+
|
|
360
|
+
```javascript
|
|
361
|
+
// Platform detection is available via the internal module
|
|
362
|
+
// Note: Public API coming in future versions
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Cross-Platform Support
|
|
368
|
+
|
|
369
|
+
Memorio is designed to work across multiple JavaScript environments:
|
|
370
|
+
|
|
371
|
+
### Platform Compatibility
|
|
372
|
+
|
|
373
|
+
| Feature | Browser | Node.js | Deno | Edge Workers |
|
|
374
|
+
|---------|---------|---------|------|---------------|
|
|
375
|
+
| `state` | ✅ | ✅ | ✅ | ✅ |
|
|
376
|
+
| `observer` | ✅ | ✅ | ✅ | ✅ |
|
|
377
|
+
| `useObserver` | ✅ | ⚠️ | ⚠️ | ✅ |
|
|
378
|
+
| `cache` | ✅ | ✅ | ✅ | ✅ |
|
|
379
|
+
| `store` | ✅ (localStorage) | ⚠️ (memory) | ⚠️ (memory) | ✅ (localStorage) |
|
|
380
|
+
| `session` | ✅ (sessionStorage) | ⚠️ (memory) | ⚠️ (memory) | ✅ (sessionStorage) |
|
|
381
|
+
| `idb` | ✅ | ❌ | ❌ | ⚠️ |
|
|
382
|
+
|
|
383
|
+
- ✅ Full support
|
|
384
|
+
- ⚠️ Partial support (fallback to in-memory)
|
|
385
|
+
- ❌ Not available
|
|
386
|
+
|
|
387
|
+
### Session Isolation
|
|
388
|
+
|
|
389
|
+
Memorio provides automatic session isolation to prevent state leakage between different requests or contexts:
|
|
390
|
+
|
|
391
|
+
- **Unique Session IDs**: Each import gets a unique session identifier
|
|
392
|
+
- **Namespaced Storage**: `store` and `session` keys are prefixed with session ID
|
|
393
|
+
- **State Isolation**: `state` is isolated per-instance
|
|
394
|
+
|
|
395
|
+
This ensures that in server-side environments (Node.js/Deno), different requests don't share state data.
|
|
396
|
+
|
|
397
|
+
### Best Practices
|
|
398
|
+
|
|
399
|
+
1. **For Client-Side**: Use all features freely - store, session, idb work with real browser storage
|
|
400
|
+
2. **For Server-Side**: Use `state` and `cache` for in-memory data; store/session fall back to memory
|
|
401
|
+
3. **For Edge Workers**: Same as browser; localStorage/sessionStorage available
|
|
402
|
+
|
|
403
|
+
### Checking Platform
|
|
404
|
+
|
|
405
|
+
```javascript
|
|
406
|
+
import { isBrowser, isNode, isDeno, getCapabilities } from 'memorio';
|
|
407
|
+
|
|
408
|
+
console.log('Browser:', isBrowser()); // true in browser
|
|
409
|
+
console.log('Node.js:', isNode()); // true in Node.js
|
|
410
|
+
console.log('Deno:', isDeno()); // true in Deno
|
|
411
|
+
|
|
412
|
+
const caps = getCapabilities();
|
|
413
|
+
console.log('Platform:', caps.platform); // 'browser' | 'node' | 'deno' | 'edge'
|
|
414
|
+
console.log('Persistent:', store.isPersistent); // true if using real storage
|
|
415
|
+
```
|
package/examples/basic.ts
CHANGED
|
@@ -5,16 +5,46 @@
|
|
|
5
5
|
* - State management
|
|
6
6
|
* - Store (localStorage)
|
|
7
7
|
* - Session storage
|
|
8
|
+
* - Platform detection
|
|
8
9
|
*
|
|
9
10
|
* Run: npx ts-node examples/basic.ts
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
13
|
import '../index'
|
|
13
14
|
|
|
15
|
+
// ============================================
|
|
16
|
+
// PLATFORM DETECTION
|
|
17
|
+
// ============================================
|
|
18
|
+
|
|
19
|
+
console.log('=== Platform Detection ===')
|
|
20
|
+
console.log('Memorio version:', memorio.version)
|
|
21
|
+
|
|
22
|
+
// Check platform
|
|
23
|
+
if (memorio.isBrowser()) {
|
|
24
|
+
console.log('Platform: Browser')
|
|
25
|
+
} else if (memorio.isNode()) {
|
|
26
|
+
console.log('Platform: Node.js')
|
|
27
|
+
} else if (memorio.isDeno()) {
|
|
28
|
+
console.log('Platform: Deno')
|
|
29
|
+
} else if (memorio.isEdge()) {
|
|
30
|
+
console.log('Platform: Edge Worker')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Get capabilities
|
|
34
|
+
const caps = memorio.getCapabilities()
|
|
35
|
+
console.log('Capabilities:', {
|
|
36
|
+
platform: caps.platform,
|
|
37
|
+
hasLocalStorage: caps.hasLocalStorage,
|
|
38
|
+
hasSessionStorage: caps.hasSessionStorage,
|
|
39
|
+
hasIndexedDB: caps.hasIndexedDB
|
|
40
|
+
})
|
|
41
|
+
|
|
14
42
|
// ============================================
|
|
15
43
|
// STATE - In-memory reactive state
|
|
16
44
|
// ============================================
|
|
17
45
|
|
|
46
|
+
console.log('\n=== State Management ===')
|
|
47
|
+
|
|
18
48
|
// Set some state values
|
|
19
49
|
state.name = 'Mario'
|
|
20
50
|
state.age = 30
|
|
@@ -36,6 +66,11 @@ console.log('All states:', state.list)
|
|
|
36
66
|
// STORE - Persistent localStorage
|
|
37
67
|
// ============================================
|
|
38
68
|
|
|
69
|
+
console.log('\n=== Store (Persistent Storage) ===')
|
|
70
|
+
|
|
71
|
+
// Check persistence
|
|
72
|
+
console.log('Is persistent:', store.isPersistent) // true in browser, false in Node.js/Deno
|
|
73
|
+
|
|
39
74
|
// Save to localStorage
|
|
40
75
|
store.set('username', 'mario')
|
|
41
76
|
store.set('preferences', { theme: 'dark', language: 'en' })
|
|
@@ -52,6 +87,11 @@ console.log('Storage size:', store.size(), 'bytes')
|
|
|
52
87
|
// SESSION - Temporary session storage
|
|
53
88
|
// ============================================
|
|
54
89
|
|
|
90
|
+
console.log('\n=== Session (Temporary Storage) ===')
|
|
91
|
+
|
|
92
|
+
// Check persistence
|
|
93
|
+
console.log('Is persistent:', session.isPersistent) // true in browser, false in Node.js/Deno
|
|
94
|
+
|
|
55
95
|
// Save session data (cleared when tab closes)
|
|
56
96
|
session.set('token', 'abc123xyz')
|
|
57
97
|
session.set('userId', 42)
|
|
@@ -72,4 +112,4 @@ session.remove('token')
|
|
|
72
112
|
store.removeAll()
|
|
73
113
|
session.removeAll()
|
|
74
114
|
|
|
75
|
-
console.log('
|
|
115
|
+
console.log('\nExample complete!')
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<title>Memorio Vanilla JS Example</title>
|
|
8
|
+
<style>
|
|
9
|
+
/* Simple CSS */
|
|
10
|
+
body {
|
|
11
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
12
|
+
max-width: 800px;
|
|
13
|
+
margin: 0 auto;
|
|
14
|
+
padding: 20px;
|
|
15
|
+
background: #f5f5f5;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.card {
|
|
19
|
+
background: white;
|
|
20
|
+
border-radius: 8px;
|
|
21
|
+
padding: 20px;
|
|
22
|
+
margin-bottom: 20px;
|
|
23
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
h1 {
|
|
27
|
+
color: #333;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
h2 {
|
|
31
|
+
color: #666;
|
|
32
|
+
margin-top: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
button {
|
|
36
|
+
background: #007bff;
|
|
37
|
+
color: white;
|
|
38
|
+
border: none;
|
|
39
|
+
padding: 10px 20px;
|
|
40
|
+
border-radius: 4px;
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
margin: 5px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
button:hover {
|
|
46
|
+
background: #0056b3;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
button.danger {
|
|
50
|
+
background: #dc3545;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
button.danger:hover {
|
|
54
|
+
background: #c82333;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
button.success {
|
|
58
|
+
background: #28a745;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
button.success:hover {
|
|
62
|
+
background: #218838;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
input,
|
|
66
|
+
select {
|
|
67
|
+
padding: 8px;
|
|
68
|
+
border: 1px solid #ddd;
|
|
69
|
+
border-radius: 4px;
|
|
70
|
+
margin: 5px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
pre {
|
|
74
|
+
background: #f8f9fa;
|
|
75
|
+
padding: 10px;
|
|
76
|
+
border-radius: 4px;
|
|
77
|
+
overflow-x: auto;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.output {
|
|
81
|
+
background: #e9ecef;
|
|
82
|
+
padding: 10px;
|
|
83
|
+
border-radius: 4px;
|
|
84
|
+
font-family: monospace;
|
|
85
|
+
white-space: pre-wrap;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.grid {
|
|
89
|
+
display: grid;
|
|
90
|
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
91
|
+
gap: 10px;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.stat {
|
|
95
|
+
background: #e7f3ff;
|
|
96
|
+
padding: 10px;
|
|
97
|
+
border-radius: 4px;
|
|
98
|
+
text-align: center;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.stat-value {
|
|
102
|
+
font-size: 24px;
|
|
103
|
+
font-weight: bold;
|
|
104
|
+
color: #007bff;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.stat-label {
|
|
108
|
+
font-size: 12px;
|
|
109
|
+
color: #666;
|
|
110
|
+
}
|
|
111
|
+
</style>
|
|
112
|
+
</head>
|
|
113
|
+
|
|
114
|
+
<body>
|
|
115
|
+
<h1>🧠 Memorio Vanilla JS Demo</h1>
|
|
116
|
+
|
|
117
|
+
<!-- State Section -->
|
|
118
|
+
<div class="card">
|
|
119
|
+
<h2>1. State (Reactive)</h2>
|
|
120
|
+
<p>Global reactive state - changes trigger UI updates automatically</p>
|
|
121
|
+
|
|
122
|
+
<div class="grid">
|
|
123
|
+
<div class="stat">
|
|
124
|
+
<div class="stat-value" id="counter">0</div>
|
|
125
|
+
<div class="stat-label">Counter</div>
|
|
126
|
+
</div>
|
|
127
|
+
<div class="stat">
|
|
128
|
+
<div class="stat-value" id="username">-</div>
|
|
129
|
+
<div class="stat-label">Username</div>
|
|
130
|
+
</div>
|
|
131
|
+
<div class="stat">
|
|
132
|
+
<div class="stat-value" id="theme">light</div>
|
|
133
|
+
<div class="stat-label">Theme</div>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
<br>
|
|
138
|
+
<button onclick="state.counter++">Increment Counter</button>
|
|
139
|
+
<button onclick="state.counter--">Decrement</button>
|
|
140
|
+
<button onclick="state.counter = 0">Reset</button>
|
|
141
|
+
|
|
142
|
+
<h3>Set Username:</h3>
|
|
143
|
+
<input type="text" id="nameInput" placeholder="Enter name">
|
|
144
|
+
<button onclick="state.username = document.getElementById('nameInput').value">Set</button>
|
|
145
|
+
|
|
146
|
+
<h3>Theme:</h3>
|
|
147
|
+
<button onclick="state.theme = 'light'">Light</button>
|
|
148
|
+
<button onclick="state.theme = 'dark'">Dark</button>
|
|
149
|
+
|
|
150
|
+
<h3>All State:</h3>
|
|
151
|
+
<pre id="stateOutput" class="output"></pre>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<!-- Store Section -->
|
|
155
|
+
<div class="card">
|
|
156
|
+
<h2>2. Store (localStorage)</h2>
|
|
157
|
+
<p>Permanent storage - survives page refresh</p>
|
|
158
|
+
<p>Persistent: <span id="storePersistent">checking...</span></p>
|
|
159
|
+
|
|
160
|
+
<input type="text" id="storeKey" placeholder="Key">
|
|
161
|
+
<input type="text" id="storeValue" placeholder="Value">
|
|
162
|
+
<button
|
|
163
|
+
onclick="store.set(document.getElementById('storeKey').value, document.getElementById('storeValue').value)">Save</button>
|
|
164
|
+
<button
|
|
165
|
+
onclick="document.getElementById('storeOutput').textContent = JSON.stringify(store.get(document.getElementById('storeKey').value), null, 2)">Get</button>
|
|
166
|
+
<button class="danger" onclick="store.remove(document.getElementById('storeKey').value)">Delete</button>
|
|
167
|
+
|
|
168
|
+
<h3>All Store Data:</h3>
|
|
169
|
+
<pre id="storeOutput" class="output"></pre>
|
|
170
|
+
</div>
|
|
171
|
+
|
|
172
|
+
<!-- Session Section -->
|
|
173
|
+
<div class="card">
|
|
174
|
+
<h2>3. Session (sessionStorage)</h2>
|
|
175
|
+
<p>Temporary storage - cleared when tab closes</p>
|
|
176
|
+
<p>Persistent: <span id="sessionPersistent">checking...</span></p>
|
|
177
|
+
|
|
178
|
+
<input type="text" id="sessionKey" placeholder="Key">
|
|
179
|
+
<input type="text" id="sessionValue" placeholder="Value">
|
|
180
|
+
<button
|
|
181
|
+
onclick="session.set(document.getElementById('sessionKey').value, document.getElementById('sessionValue').value)">Save</button>
|
|
182
|
+
<button
|
|
183
|
+
onclick="document.getElementById('sessionOutput').textContent = JSON.stringify(session.get(document.getElementById('sessionKey').value), null, 2)">Get</button>
|
|
184
|
+
<button class="danger" onclick="session.remove(document.getElementById('sessionKey').value)">Delete</button>
|
|
185
|
+
|
|
186
|
+
<h3>All Session Data:</h3>
|
|
187
|
+
<pre id="sessionOutput" class="output"></pre>
|
|
188
|
+
</div>
|
|
189
|
+
|
|
190
|
+
<!-- Cache Section -->
|
|
191
|
+
<div class="card">
|
|
192
|
+
<h2>4. Cache (In-Memory)</h2>
|
|
193
|
+
<p>Temporary cache - cleared on refresh</p>
|
|
194
|
+
|
|
195
|
+
<input type="text" id="cacheKey" placeholder="Key">
|
|
196
|
+
<input type="text" id="cacheValue" placeholder="Value">
|
|
197
|
+
<button
|
|
198
|
+
onclick="cache.set(document.getElementById('cacheKey').value, document.getElementById('cacheValue').value)">Save</button>
|
|
199
|
+
<button
|
|
200
|
+
onclick="document.getElementById('cacheOutput').textContent = JSON.stringify(cache.get(document.getElementById('cacheKey').value), null, 2)">Get</button>
|
|
201
|
+
<button class="danger" onclick="cache.remove(document.getElementById('cacheKey').value)">Delete</button>
|
|
202
|
+
|
|
203
|
+
<h3>All Cache Data:</h3>
|
|
204
|
+
<pre id="cacheOutput" class="output"></pre>
|
|
205
|
+
</div>
|
|
206
|
+
|
|
207
|
+
<!-- Observer Section -->
|
|
208
|
+
<div class="card">
|
|
209
|
+
<h2>5. Observer (Auto-Reactive)</h2>
|
|
210
|
+
<p>Watch for state changes automatically</p>
|
|
211
|
+
|
|
212
|
+
<button class="success" id="startObserver">Start Observer</button>
|
|
213
|
+
<button class="danger" id="stopObserver">Stop Observer</button>
|
|
214
|
+
<button onclick="state.testValue = Math.random()">Trigger Change</button>
|
|
215
|
+
|
|
216
|
+
<h3>Observer Log:</h3>
|
|
217
|
+
<pre id="observerLog" class="output"></pre>
|
|
218
|
+
</div>
|
|
219
|
+
|
|
220
|
+
<!-- Platform Info -->
|
|
221
|
+
<div class="card">
|
|
222
|
+
<h2>6. Platform Info</h2>
|
|
223
|
+
<div id="platformInfo" class="output"></div>
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
<!-- Load Memorio -->
|
|
227
|
+
<script src="https://cdn.jsdelivr.net/npm/memorio/dist/index.cjs"></script>
|
|
228
|
+
|
|
229
|
+
<script>
|
|
230
|
+
// ============================================
|
|
231
|
+
// MEMORIO VANILLA JS EXAMPLE
|
|
232
|
+
// ============================================
|
|
233
|
+
|
|
234
|
+
// 1. REACTIVE STATE
|
|
235
|
+
// -----------------
|
|
236
|
+
|
|
237
|
+
// Initialize state
|
|
238
|
+
state.counter = 0
|
|
239
|
+
state.username = 'Guest'
|
|
240
|
+
state.theme = 'light'
|
|
241
|
+
state.testValue = 0
|
|
242
|
+
|
|
243
|
+
// Update UI when state changes
|
|
244
|
+
function updateStateUI() {
|
|
245
|
+
document.getElementById('counter').textContent = state.counter
|
|
246
|
+
document.getElementById('username').textContent = state.username
|
|
247
|
+
document.getElementById('theme').textContent = state.theme
|
|
248
|
+
document.getElementById('stateOutput').textContent = JSON.stringify({
|
|
249
|
+
counter: state.counter,
|
|
250
|
+
username: state.username,
|
|
251
|
+
theme: state.theme,
|
|
252
|
+
testValue: state.testValue
|
|
253
|
+
}, null, 2)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Use observer to react to changes
|
|
257
|
+
useObserver(() => {
|
|
258
|
+
updateStateUI()
|
|
259
|
+
document.body.className = state.theme
|
|
260
|
+
}, [state.counter, state.username, state.theme, state.testValue])
|
|
261
|
+
|
|
262
|
+
// 2. PERSISTENT STORE
|
|
263
|
+
// -------------------
|
|
264
|
+
|
|
265
|
+
// Check persistence
|
|
266
|
+
document.getElementById('storePersistent').textContent = store.isPersistent ? '✅ Yes (localStorage)' : '❌ No (memory)'
|
|
267
|
+
|
|
268
|
+
// Save sample data
|
|
269
|
+
store.set('visits', '0')
|
|
270
|
+
store.set('lastVisit', new Date().toISOString())
|
|
271
|
+
|
|
272
|
+
function updateStoreUI() {
|
|
273
|
+
document.getElementById('storeOutput').textContent = 'Visits: ' + store.get('visits') + '\nLast Visit: ' + store.get('lastVisit')
|
|
274
|
+
}
|
|
275
|
+
updateStoreUI()
|
|
276
|
+
|
|
277
|
+
// Increment visits
|
|
278
|
+
let visits = parseInt(store.get('visits') || '0')
|
|
279
|
+
store.set('visits', (visits + 1).toString())
|
|
280
|
+
|
|
281
|
+
// 3. SESSION STORAGE
|
|
282
|
+
// ------------------
|
|
283
|
+
|
|
284
|
+
document.getElementById('sessionPersistent').textContent = session.isPersistent ? '✅ Yes (sessionStorage)' : '❌ No (memory)'
|
|
285
|
+
|
|
286
|
+
session.set('pageViews', '0')
|
|
287
|
+
|
|
288
|
+
function updateSessionUI() {
|
|
289
|
+
document.getElementById('sessionOutput').textContent = 'Page Views: ' + session.get('pageViews')
|
|
290
|
+
}
|
|
291
|
+
updateSessionUI()
|
|
292
|
+
|
|
293
|
+
// Increment page views
|
|
294
|
+
let pageViews = parseInt(session.get('pageViews') || '0')
|
|
295
|
+
session.set('pageViews', (pageViews + 1).toString())
|
|
296
|
+
|
|
297
|
+
// 4. CACHE (In-Memory)
|
|
298
|
+
// --------------------
|
|
299
|
+
|
|
300
|
+
cache.set('tempData', { computed: true, timestamp: Date.now() })
|
|
301
|
+
|
|
302
|
+
function updateCacheUI() {
|
|
303
|
+
document.getElementById('cacheOutput').textContent = JSON.stringify(cache.get('tempData'), null, 2)
|
|
304
|
+
}
|
|
305
|
+
updateCacheUI()
|
|
306
|
+
|
|
307
|
+
// 5. OBSERVER
|
|
308
|
+
// -----------
|
|
309
|
+
|
|
310
|
+
let observerActive = false
|
|
311
|
+
const logEl = document.getElementById('observerLog')
|
|
312
|
+
|
|
313
|
+
document.getElementById('startObserver').onclick = () => {
|
|
314
|
+
observerActive = true
|
|
315
|
+
logEl.textContent += 'Observer started!\n'
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
document.getElementById('stopObserver').onclick = () => {
|
|
319
|
+
observerActive = false
|
|
320
|
+
logEl.textContent += 'Observer stopped!\n'
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// This creates a persistent observer
|
|
324
|
+
useObserver((newVal, oldVal) => {
|
|
325
|
+
if (observerActive) {
|
|
326
|
+
logEl.textContent += `Changed: ${oldVal} → ${newVal}\n`
|
|
327
|
+
logEl.scrollTop = logEl.scrollHeight
|
|
328
|
+
}
|
|
329
|
+
}, [state.testValue])
|
|
330
|
+
|
|
331
|
+
// 6. PLATFORM INFO
|
|
332
|
+
// ----------------
|
|
333
|
+
|
|
334
|
+
const platformInfo = document.getElementById('platformInfo')
|
|
335
|
+
platformInfo.textContent = `
|
|
336
|
+
Platform Detection:
|
|
337
|
+
-----------------
|
|
338
|
+
Browser: ${memorio.isBrowser() ? '✅' : '❌'}
|
|
339
|
+
Node.js: ${memorio.isNode() ? '✅' : '❌'}
|
|
340
|
+
Deno: ${memorio.isDeno() ? '✅' : '❌'}
|
|
341
|
+
Edge: ${memorio.isEdge() ? '✅' : '❌'}
|
|
342
|
+
|
|
343
|
+
Capabilities:
|
|
344
|
+
-------------
|
|
345
|
+
localStorage: ${memorio.getCapabilities().hasLocalStorage ? '✅' : '❌'}
|
|
346
|
+
sessionStorage: ${memorio.getCapabilities().hasSessionStorage ? '✅' : '❌'}
|
|
347
|
+
IndexedDB: ${memorio.getCapabilities().hasIndexedDB ? '✅' : '❌'}
|
|
348
|
+
|
|
349
|
+
Session ID: ${memorio.getCapabilities().sessionId.substring(0, 8)}...
|
|
350
|
+
`.trim()
|
|
351
|
+
|
|
352
|
+
// Log welcome
|
|
353
|
+
console.log('🧠 Memorio loaded!')
|
|
354
|
+
console.log('Platform:', memorio.getCapabilities().platform)
|
|
355
|
+
</script>
|
|
356
|
+
</body>
|
|
357
|
+
|
|
358
|
+
</html>
|