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.
Files changed (82) hide show
  1. package/AGENTS.md +3 -3
  2. package/README.md +95 -516
  3. package/SECURITY.md +159 -33
  4. package/SUMMARY.md +59 -45
  5. package/adr/001-state-proxy-model.md +95 -0
  6. package/adr/002-observer-semantics.md +179 -0
  7. package/adr/003-deep-mutation-semantics.md +128 -0
  8. package/adr/004-array-mutation-semantics.md +127 -0
  9. package/adr/005-scheduler-contract.md +148 -0
  10. package/adr/006-context-isolation.md +91 -0
  11. package/adr/007-mutation-records.md +117 -0
  12. package/adr/008-transactions.md +105 -0
  13. package/adr/009-history-model.md +109 -0
  14. package/adr/README.md +46 -0
  15. package/adr/template.md +48 -0
  16. package/bin/cli.js +68 -0
  17. package/examples/basic.ts +115 -115
  18. package/examples/browser-vanilla.html +358 -358
  19. package/examples/cache.ts +72 -72
  20. package/examples/cross-platform-guards.ts +57 -57
  21. package/examples/history.ts +104 -0
  22. package/examples/idb.ts +109 -109
  23. package/examples/multi-tenant-context.ts +44 -44
  24. package/examples/node-server.ts +308 -308
  25. package/examples/observer.ts +60 -60
  26. package/examples/platform.ts +115 -115
  27. package/examples/react-app.tsx +362 -362
  28. package/examples/react-observer.tsx +63 -63
  29. package/examples/semantic-memory.ts +60 -60
  30. package/examples/session-advanced.ts +91 -91
  31. package/examples/sqlite-batched-writes.ts +57 -57
  32. package/examples/state-advanced.ts +89 -89
  33. package/examples/store-advanced.ts +117 -117
  34. package/examples/sync.ts +90 -0
  35. package/examples/typed-and-schema.ts +102 -100
  36. package/examples/useObserver.tsx +140 -141
  37. package/global.cjs +5733 -0
  38. package/global.d.ts +8 -0
  39. package/global.js +5667 -0
  40. package/index.cjs +2202 -1041
  41. package/index.d.ts +2 -0
  42. package/index.js +2178 -1040
  43. package/llms.txt +113 -8
  44. package/markdown/AUDIT-REPORT.md +134 -0
  45. package/markdown/CACHE.md +191 -0
  46. package/markdown/DEVTOOLS.md +128 -0
  47. package/markdown/DISPATCH.md +176 -0
  48. package/markdown/HISTORY.md +198 -0
  49. package/markdown/IDB.md +177 -0
  50. package/markdown/IMPORT.md +152 -0
  51. package/markdown/INSPECT.md +122 -0
  52. package/markdown/LOGGER.md +153 -0
  53. package/markdown/MEMORY-ATTACHMENT.md +95 -0
  54. package/markdown/MEMORY.md +161 -0
  55. package/markdown/OBSERVER.md +208 -0
  56. package/markdown/PLATFORM.md +277 -0
  57. package/markdown/REDUX.md +54 -0
  58. package/markdown/SCHEMA.md +175 -0
  59. package/markdown/SESSION.md +164 -0
  60. package/markdown/SQLITE.md +189 -0
  61. package/markdown/STATE.md +159 -0
  62. package/markdown/STORE.md +170 -0
  63. package/markdown/SYNC.md +318 -0
  64. package/markdown/TYPED.md +164 -0
  65. package/markdown/USEOBSERVER.md +256 -0
  66. package/modules/redux.cjs +701 -177
  67. package/modules/redux.cjs.map +1 -1
  68. package/modules/redux.js +701 -177
  69. package/modules/redux.js.map +1 -1
  70. package/package.json +26 -4
  71. package/types/broadcast.d.ts +61 -0
  72. package/types/computed.d.ts +96 -0
  73. package/types/encryption.d.ts +129 -0
  74. package/types/env.d.ts +19 -9
  75. package/types/exports.d.ts +29 -0
  76. package/types/history.d.ts +13 -1
  77. package/types/memorio.d.ts +25 -6
  78. package/types/mutation.d.ts +75 -0
  79. package/types/security.d.ts +67 -0
  80. package/types/session.d.ts +23 -5
  81. package/types/store.d.ts +19 -3
  82. package/vsix/memorio.vsix +0 -0
@@ -1,358 +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/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.debug('🧠 Memorio loaded!')
354
- console.debug('Platform:', memorio.getCapabilities().platform)
355
- </script>
356
- </body>
357
-
358
- </html>
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/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.debug('🧠 Memorio loaded!')
354
+ console.debug('Platform:', memorio.getCapabilities().platform)
355
+ </script>
356
+ </body>
357
+
358
+ </html>