memorio 4.9.31 → 5.0.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/AGENTS.md +3 -3
- package/README.md +327 -330
- package/SECURITY.md +17 -1
- package/SUMMARY.md +59 -45
- package/adr/001-state-proxy-model.md +96 -0
- package/adr/002-observer-semantics.md +180 -0
- package/adr/003-deep-mutation-semantics.md +129 -0
- package/adr/004-array-mutation-semantics.md +128 -0
- package/adr/005-scheduler-contract.md +149 -0
- package/adr/006-context-isolation.md +92 -0
- package/adr/007-mutation-records.md +118 -0
- package/adr/008-transactions.md +106 -0
- package/adr/009-history-model.md +110 -0
- package/adr/README.md +46 -0
- package/adr/template.md +49 -0
- package/examples/basic.ts +115 -115
- package/examples/browser-vanilla.html +358 -358
- package/examples/cache.ts +72 -72
- package/examples/cross-platform-guards.ts +57 -57
- package/examples/history.ts +104 -0
- package/examples/idb.ts +109 -109
- package/examples/multi-tenant-context.ts +44 -44
- package/examples/node-server.ts +308 -308
- package/examples/observer.ts +60 -60
- package/examples/platform.ts +115 -115
- package/examples/react-app.tsx +362 -362
- package/examples/react-observer.tsx +63 -63
- package/examples/semantic-memory.ts +60 -60
- package/examples/session-advanced.ts +91 -91
- package/examples/sqlite-batched-writes.ts +57 -57
- package/examples/state-advanced.ts +89 -89
- package/examples/store-advanced.ts +117 -117
- package/examples/sync.ts +90 -0
- package/examples/typed-and-schema.ts +102 -100
- package/examples/useObserver.tsx +140 -141
- package/global.cjs +4594 -0
- package/global.d.ts +8 -0
- package/global.js +4532 -0
- package/index.cjs +706 -649
- package/index.d.ts +1 -0
- package/index.js +686 -648
- package/llms.txt +72 -4
- package/markdown/AUDIT-REPORT.md +135 -0
- package/markdown/CACHE.md +100 -0
- package/markdown/CHANGELOG.md +243 -0
- package/markdown/DEVTOOLS.md +129 -0
- package/markdown/DISPATCH.md +177 -0
- package/markdown/HISTORY.md +199 -0
- package/markdown/IDB.md +178 -0
- package/markdown/IMPORT.md +153 -0
- package/markdown/INSPECT.md +123 -0
- package/markdown/LOGGER.md +154 -0
- package/markdown/MEMORY-ATTACHMENT.md +96 -0
- package/markdown/MEMORY.md +162 -0
- package/markdown/OBSERVER.md +209 -0
- package/markdown/PLATFORM.md +271 -0
- package/markdown/PROJECT.md +311 -0
- package/markdown/SCHEMA.md +176 -0
- package/markdown/SECURITY.md +330 -0
- package/markdown/SESSION.md +165 -0
- package/markdown/SQLITE.md +190 -0
- package/markdown/STATE.md +160 -0
- package/markdown/STORE.md +171 -0
- package/markdown/SYNC.md +319 -0
- package/markdown/TYPED.md +165 -0
- package/markdown/USEOBSERVER.md +257 -0
- package/modules/redux.cjs +561 -374
- package/modules/redux.cjs.map +1 -1
- package/modules/redux.js +561 -374
- package/modules/redux.js.map +1 -1
- package/package.json +13 -3
- package/types/env.d.ts +19 -9
- package/types/exports.d.ts +20 -0
- package/types/history.d.ts +13 -1
- package/types/memorio.d.ts +17 -5
- package/types/mutation.d.ts +75 -0
package/examples/node-server.ts
CHANGED
|
@@ -1,308 +1,308 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Memorio Node.js Server Example
|
|
3
|
-
*
|
|
4
|
-
* This example shows how to use Memorio in a Node.js server environment.
|
|
5
|
-
* Includes context isolation for multi-tenant applications.
|
|
6
|
-
*
|
|
7
|
-
* Run: npx ts-node examples/node-server.ts
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import 'memorio'
|
|
11
|
-
|
|
12
|
-
// ============================================
|
|
13
|
-
// 1. BASIC USAGE
|
|
14
|
-
// ============================================
|
|
15
|
-
|
|
16
|
-
console.debug('=== 1. Basic Node.js Usage ===')
|
|
17
|
-
|
|
18
|
-
// Check platform
|
|
19
|
-
console.debug('Platform:', memorio.isNode() ? 'Node.js ✅' : 'Other')
|
|
20
|
-
|
|
21
|
-
// Check persistence (false in Node.js - uses memory fallback)
|
|
22
|
-
console.debug('Store persistent:', store.isPersistent) // false
|
|
23
|
-
console.debug('Session persistent:', session.isPersistent) // false
|
|
24
|
-
|
|
25
|
-
// State works exactly like in browser
|
|
26
|
-
state.appName = 'My Server App'
|
|
27
|
-
state.startTime = Date.now()
|
|
28
|
-
state.config = {
|
|
29
|
-
port: 3000,
|
|
30
|
-
env: 'production'
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
console.debug('App name:', state.appName)
|
|
34
|
-
console.debug('Config:', state.config)
|
|
35
|
-
|
|
36
|
-
// ============================================
|
|
37
|
-
// 2. CACHE (In-Memory - Perfect for Server)
|
|
38
|
-
// ============================================
|
|
39
|
-
|
|
40
|
-
console.debug('\n=== 2. Cache (In-Memory) ===')
|
|
41
|
-
|
|
42
|
-
// Cache is perfect for temporary server data
|
|
43
|
-
cache.set('apiResponse', { data: 'cached value' })
|
|
44
|
-
cache.set('userCount', 42)
|
|
45
|
-
|
|
46
|
-
console.debug('Cached API response:', cache.get('apiResponse'))
|
|
47
|
-
console.debug('User count:', cache.get('userCount'))
|
|
48
|
-
|
|
49
|
-
// Clear cache when needed
|
|
50
|
-
cache.remove('apiResponse')
|
|
51
|
-
// cache.clearAll() - clear all
|
|
52
|
-
|
|
53
|
-
// ============================================
|
|
54
|
-
// 3. STORE & SESSION (Memory Fallback in Node.js)
|
|
55
|
-
// ============================================
|
|
56
|
-
|
|
57
|
-
console.debug('\n=== 3. Store & Session (Memory Fallback) ===')
|
|
58
|
-
|
|
59
|
-
// Store and session work but don't persist (no localStorage in Node.js)
|
|
60
|
-
store.set('serverConfig', { debug: true })
|
|
61
|
-
session.set('requestData', { path: '/api/users' })
|
|
62
|
-
|
|
63
|
-
console.debug('Server config:', store.get('serverConfig'))
|
|
64
|
-
console.debug('Request data:', session.get('requestData'))
|
|
65
|
-
|
|
66
|
-
// ⚠️ Data is lost on process restart!
|
|
67
|
-
// For persistence in Node.js, use a database
|
|
68
|
-
|
|
69
|
-
// ============================================
|
|
70
|
-
// 4. CONTEXT ISOLATION (Multi-Tenant)
|
|
71
|
-
// ============================================
|
|
72
|
-
|
|
73
|
-
console.debug('\n=== 4. Context Isolation (Multi-Tenant) ===')
|
|
74
|
-
|
|
75
|
-
// Create isolated contexts for different tenants/requests
|
|
76
|
-
const userAContext = memorio.createContext('tenant-A')
|
|
77
|
-
const userBContext = memorio.createContext('tenant-B')
|
|
78
|
-
|
|
79
|
-
// Each context has completely separate data
|
|
80
|
-
userAContext.state.user = { name: 'Alice', id: 1 }
|
|
81
|
-
userAContext.state.secret = 'Alice secret data'
|
|
82
|
-
userAContext.cache.set('temp', 'A temp data')
|
|
83
|
-
|
|
84
|
-
userBContext.state.user = { name: 'Bob', id: 2 }
|
|
85
|
-
userBContext.state.secret = 'Bob secret data'
|
|
86
|
-
userBContext.cache.set('temp', 'B temp data')
|
|
87
|
-
|
|
88
|
-
// Verify isolation
|
|
89
|
-
console.debug('User A name:', userAContext.state.user.name) // Alice
|
|
90
|
-
console.debug('User B name:', userBContext.state.user.name) // Bob
|
|
91
|
-
|
|
92
|
-
// Global state is separate
|
|
93
|
-
console.debug('Global state:', state.appName) // 'My Server App'
|
|
94
|
-
console.debug('User A global secret:', userAContext.state.secret) // 'Alice secret data'
|
|
95
|
-
console.debug('User B global secret:', userBContext.state.secret) // 'Bob secret data'
|
|
96
|
-
|
|
97
|
-
// ============================================
|
|
98
|
-
// 5. EXPRESS.JS MIDDLEWARE EXAMPLE
|
|
99
|
-
// ============================================
|
|
100
|
-
|
|
101
|
-
console.debug('\n=== 5. Express.js Middleware Example ===')
|
|
102
|
-
|
|
103
|
-
/*
|
|
104
|
-
// In a real Express app:
|
|
105
|
-
|
|
106
|
-
import express from 'express'
|
|
107
|
-
const app = express()
|
|
108
|
-
|
|
109
|
-
// Middleware to create isolated context per request
|
|
110
|
-
app.use((req, res, next) => {
|
|
111
|
-
// Create unique context for this request
|
|
112
|
-
const ctx = memorio.createContext(`req-${req.id}`)
|
|
113
|
-
|
|
114
|
-
// Attach to request for use in handlers
|
|
115
|
-
req.memorio = ctx
|
|
116
|
-
|
|
117
|
-
// Clean up on response finish
|
|
118
|
-
res.on('finish', () => {
|
|
119
|
-
memorio.deleteContext(ctx.id)
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
next()
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
// Route handler using isolated context
|
|
126
|
-
app.get('/api/user', (req, res) => {
|
|
127
|
-
const ctx = req.memorio
|
|
128
|
-
|
|
129
|
-
// Set request-specific state
|
|
130
|
-
ctx.state.requestId = req.id
|
|
131
|
-
ctx.state.startTime = Date.now()
|
|
132
|
-
|
|
133
|
-
// Cache data for this request
|
|
134
|
-
ctx.cache.set('query', req.query)
|
|
135
|
-
|
|
136
|
-
// Get user data
|
|
137
|
-
const user = getUserFromDB(req.params.id)
|
|
138
|
-
|
|
139
|
-
// Return response
|
|
140
|
-
res.json({
|
|
141
|
-
user,
|
|
142
|
-
requestId: ctx.state.requestId
|
|
143
|
-
})
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
app.listen(3000)
|
|
147
|
-
*/
|
|
148
|
-
|
|
149
|
-
console.debug('See code comments for Express.js integration')
|
|
150
|
-
|
|
151
|
-
// ============================================
|
|
152
|
-
// 6. WEBSOCKET EXAMPLE
|
|
153
|
-
// ============================================
|
|
154
|
-
|
|
155
|
-
console.debug('\n=== 6. WebSocket Example ===')
|
|
156
|
-
|
|
157
|
-
/*
|
|
158
|
-
// For WebSocket connections:
|
|
159
|
-
|
|
160
|
-
const activeConnections = new Map()
|
|
161
|
-
|
|
162
|
-
function handleConnection(ws, userId) {
|
|
163
|
-
// Create isolated context for this user
|
|
164
|
-
const ctx = memorio.createContext(`ws-${userId}`)
|
|
165
|
-
|
|
166
|
-
// Store user data
|
|
167
|
-
ctx.state.userId = userId
|
|
168
|
-
ctx.state.connected = true
|
|
169
|
-
|
|
170
|
-
// Store in connection map
|
|
171
|
-
activeConnections.set(userId, ctx)
|
|
172
|
-
|
|
173
|
-
ws.on('message', (message) => {
|
|
174
|
-
// Process message using isolated context
|
|
175
|
-
ctx.cache.set('lastMessage', message)
|
|
176
|
-
handleMessage(ctx, message)
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
ws.on('close', () => {
|
|
180
|
-
// Clean up
|
|
181
|
-
ctx.state.connected = false
|
|
182
|
-
activeConnections.delete(userId)
|
|
183
|
-
memorio.deleteContext(ctx.id)
|
|
184
|
-
})
|
|
185
|
-
}
|
|
186
|
-
*/
|
|
187
|
-
|
|
188
|
-
console.debug('See code comments for WebSocket integration')
|
|
189
|
-
|
|
190
|
-
// ============================================
|
|
191
|
-
// 7. JOB QUEUE / WORKER EXAMPLE
|
|
192
|
-
// ============================================
|
|
193
|
-
|
|
194
|
-
console.debug('\n=== 7. Job Queue Example ===')
|
|
195
|
-
|
|
196
|
-
/*
|
|
197
|
-
// For background jobs:
|
|
198
|
-
|
|
199
|
-
async function processJob(jobId, jobData) {
|
|
200
|
-
// Create isolated context for this job
|
|
201
|
-
const ctx = memorio.createContext(`job-${jobId}`)
|
|
202
|
-
|
|
203
|
-
try {
|
|
204
|
-
// Track job progress
|
|
205
|
-
ctx.state.jobId = jobId
|
|
206
|
-
ctx.state.status = 'processing'
|
|
207
|
-
ctx.state.progress = 0
|
|
208
|
-
|
|
209
|
-
// Process in stages
|
|
210
|
-
for (let i = 0; i < 10; i++) {
|
|
211
|
-
await doWork(jobData)
|
|
212
|
-
ctx.state.progress = (i + 1) * 10
|
|
213
|
-
|
|
214
|
-
// Cache intermediate results
|
|
215
|
-
ctx.cache.set(`stage-${i}`, true)
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
ctx.state.status = 'completed'
|
|
219
|
-
return { success: true }
|
|
220
|
-
|
|
221
|
-
} catch (error) {
|
|
222
|
-
ctx.state.status = 'failed'
|
|
223
|
-
ctx.state.error = error.message
|
|
224
|
-
throw error
|
|
225
|
-
|
|
226
|
-
} finally {
|
|
227
|
-
// Clean up after job completes
|
|
228
|
-
memorio.deleteContext(ctx.id)
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
*/
|
|
232
|
-
|
|
233
|
-
console.debug('See code comments for Job Queue integration')
|
|
234
|
-
|
|
235
|
-
// ============================================
|
|
236
|
-
// 8. CLI APPLICATION EXAMPLE
|
|
237
|
-
// ============================================
|
|
238
|
-
|
|
239
|
-
console.debug('\n=== 8. CLI Application ===')
|
|
240
|
-
|
|
241
|
-
// Memorio works great in CLI apps too
|
|
242
|
-
state.command = 'build'
|
|
243
|
-
state.options = {
|
|
244
|
-
minify: true,
|
|
245
|
-
sourceMap: false
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
console.debug('Command:', state.command)
|
|
249
|
-
console.debug('Options:', state.options)
|
|
250
|
-
|
|
251
|
-
// ============================================
|
|
252
|
-
// 9. PLATFORM DETECTION
|
|
253
|
-
// ============================================
|
|
254
|
-
|
|
255
|
-
console.debug('\n=== 9. Platform Detection ===')
|
|
256
|
-
|
|
257
|
-
const caps = memorio.getCapabilities()
|
|
258
|
-
console.debug('Platform:', caps.platform)
|
|
259
|
-
console.debug('localStorage:', caps.hasLocalStorage ? '✅' : '❌')
|
|
260
|
-
console.debug('sessionStorage:', caps.hasSessionStorage ? '✅' : '❌')
|
|
261
|
-
console.debug('IndexedDB:', caps.hasIndexedDB ? '✅' : '❌')
|
|
262
|
-
console.debug('Session ID:', caps.sessionId.substring(0, 8) + '...')
|
|
263
|
-
|
|
264
|
-
// ============================================
|
|
265
|
-
// 10. CLEANUP
|
|
266
|
-
// ============================================
|
|
267
|
-
|
|
268
|
-
console.debug('\n=== 10. Cleanup ===')
|
|
269
|
-
|
|
270
|
-
// List all contexts
|
|
271
|
-
console.debug('Active contexts:', memorio.listContexts())
|
|
272
|
-
|
|
273
|
-
// Clean up when done
|
|
274
|
-
memorio.deleteContext('tenant-A')
|
|
275
|
-
memorio.deleteContext('tenant-B')
|
|
276
|
-
|
|
277
|
-
console.debug('After cleanup:', memorio.listContexts())
|
|
278
|
-
|
|
279
|
-
// ============================================
|
|
280
|
-
// SUMMARY
|
|
281
|
-
// ============================================
|
|
282
|
-
|
|
283
|
-
console.debug('\n=== Summary ===')
|
|
284
|
-
console.debug(`
|
|
285
|
-
MEMORIO NODE.JS USAGE:
|
|
286
|
-
|
|
287
|
-
✅ WORKS:
|
|
288
|
-
- state: In-memory global state
|
|
289
|
-
- cache: In-memory temporary cache
|
|
290
|
-
- store: In-memory (NOT persistent!)
|
|
291
|
-
- session: In-memory (NOT persistent!)
|
|
292
|
-
- createContext: Perfect for isolation
|
|
293
|
-
|
|
294
|
-
⚠️ NOTES:
|
|
295
|
-
- store/session don't persist in Node.js
|
|
296
|
-
- Use database for persistence
|
|
297
|
-
- Always use contexts for request isolation
|
|
298
|
-
- Clean up contexts after use
|
|
299
|
-
|
|
300
|
-
🔧 BEST PRACTICES:
|
|
301
|
-
1. Create context per request: createContext(\`req-\${req.id}\`)
|
|
302
|
-
2. Use cache for temporary data
|
|
303
|
-
3. Use state for request-scoped data
|
|
304
|
-
4. Delete contexts after response
|
|
305
|
-
5. Check isPersistent before relying on persistence
|
|
306
|
-
`)
|
|
307
|
-
|
|
308
|
-
console.debug('\nNode.js example complete!')
|
|
1
|
+
/**
|
|
2
|
+
* Memorio Node.js Server Example
|
|
3
|
+
*
|
|
4
|
+
* This example shows how to use Memorio in a Node.js server environment.
|
|
5
|
+
* Includes context isolation for multi-tenant applications.
|
|
6
|
+
*
|
|
7
|
+
* Run: npx ts-node examples/node-server.ts
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { memorio, state, store, session, cache } from 'memorio'
|
|
11
|
+
|
|
12
|
+
// ============================================
|
|
13
|
+
// 1. BASIC USAGE
|
|
14
|
+
// ============================================
|
|
15
|
+
|
|
16
|
+
console.debug('=== 1. Basic Node.js Usage ===')
|
|
17
|
+
|
|
18
|
+
// Check platform
|
|
19
|
+
console.debug('Platform:', memorio.isNode() ? 'Node.js ✅' : 'Other')
|
|
20
|
+
|
|
21
|
+
// Check persistence (false in Node.js - uses memory fallback)
|
|
22
|
+
console.debug('Store persistent:', store.isPersistent) // false
|
|
23
|
+
console.debug('Session persistent:', session.isPersistent) // false
|
|
24
|
+
|
|
25
|
+
// State works exactly like in browser
|
|
26
|
+
state.appName = 'My Server App'
|
|
27
|
+
state.startTime = Date.now()
|
|
28
|
+
state.config = {
|
|
29
|
+
port: 3000,
|
|
30
|
+
env: 'production'
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
console.debug('App name:', state.appName)
|
|
34
|
+
console.debug('Config:', state.config)
|
|
35
|
+
|
|
36
|
+
// ============================================
|
|
37
|
+
// 2. CACHE (In-Memory - Perfect for Server)
|
|
38
|
+
// ============================================
|
|
39
|
+
|
|
40
|
+
console.debug('\n=== 2. Cache (In-Memory) ===')
|
|
41
|
+
|
|
42
|
+
// Cache is perfect for temporary server data
|
|
43
|
+
cache.set('apiResponse', { data: 'cached value' })
|
|
44
|
+
cache.set('userCount', 42)
|
|
45
|
+
|
|
46
|
+
console.debug('Cached API response:', cache.get('apiResponse'))
|
|
47
|
+
console.debug('User count:', cache.get('userCount'))
|
|
48
|
+
|
|
49
|
+
// Clear cache when needed
|
|
50
|
+
cache.remove('apiResponse')
|
|
51
|
+
// cache.clearAll() - clear all
|
|
52
|
+
|
|
53
|
+
// ============================================
|
|
54
|
+
// 3. STORE & SESSION (Memory Fallback in Node.js)
|
|
55
|
+
// ============================================
|
|
56
|
+
|
|
57
|
+
console.debug('\n=== 3. Store & Session (Memory Fallback) ===')
|
|
58
|
+
|
|
59
|
+
// Store and session work but don't persist (no localStorage in Node.js)
|
|
60
|
+
store.set('serverConfig', { debug: true })
|
|
61
|
+
session.set('requestData', { path: '/api/users' })
|
|
62
|
+
|
|
63
|
+
console.debug('Server config:', store.get('serverConfig'))
|
|
64
|
+
console.debug('Request data:', session.get('requestData'))
|
|
65
|
+
|
|
66
|
+
// ⚠️ Data is lost on process restart!
|
|
67
|
+
// For persistence in Node.js, use a database
|
|
68
|
+
|
|
69
|
+
// ============================================
|
|
70
|
+
// 4. CONTEXT ISOLATION (Multi-Tenant)
|
|
71
|
+
// ============================================
|
|
72
|
+
|
|
73
|
+
console.debug('\n=== 4. Context Isolation (Multi-Tenant) ===')
|
|
74
|
+
|
|
75
|
+
// Create isolated contexts for different tenants/requests
|
|
76
|
+
const userAContext = memorio.createContext('tenant-A')
|
|
77
|
+
const userBContext = memorio.createContext('tenant-B')
|
|
78
|
+
|
|
79
|
+
// Each context has completely separate data
|
|
80
|
+
userAContext.state.user = { name: 'Alice', id: 1 }
|
|
81
|
+
userAContext.state.secret = 'Alice secret data'
|
|
82
|
+
userAContext.cache.set('temp', 'A temp data')
|
|
83
|
+
|
|
84
|
+
userBContext.state.user = { name: 'Bob', id: 2 }
|
|
85
|
+
userBContext.state.secret = 'Bob secret data'
|
|
86
|
+
userBContext.cache.set('temp', 'B temp data')
|
|
87
|
+
|
|
88
|
+
// Verify isolation
|
|
89
|
+
console.debug('User A name:', userAContext.state.user.name) // Alice
|
|
90
|
+
console.debug('User B name:', userBContext.state.user.name) // Bob
|
|
91
|
+
|
|
92
|
+
// Global state is separate
|
|
93
|
+
console.debug('Global state:', state.appName) // 'My Server App'
|
|
94
|
+
console.debug('User A global secret:', userAContext.state.secret) // 'Alice secret data'
|
|
95
|
+
console.debug('User B global secret:', userBContext.state.secret) // 'Bob secret data'
|
|
96
|
+
|
|
97
|
+
// ============================================
|
|
98
|
+
// 5. EXPRESS.JS MIDDLEWARE EXAMPLE
|
|
99
|
+
// ============================================
|
|
100
|
+
|
|
101
|
+
console.debug('\n=== 5. Express.js Middleware Example ===')
|
|
102
|
+
|
|
103
|
+
/*
|
|
104
|
+
// In a real Express app:
|
|
105
|
+
|
|
106
|
+
import express from 'express'
|
|
107
|
+
const app = express()
|
|
108
|
+
|
|
109
|
+
// Middleware to create isolated context per request
|
|
110
|
+
app.use((req, res, next) => {
|
|
111
|
+
// Create unique context for this request
|
|
112
|
+
const ctx = memorio.createContext(`req-${req.id}`)
|
|
113
|
+
|
|
114
|
+
// Attach to request for use in handlers
|
|
115
|
+
req.memorio = ctx
|
|
116
|
+
|
|
117
|
+
// Clean up on response finish
|
|
118
|
+
res.on('finish', () => {
|
|
119
|
+
memorio.deleteContext(ctx.id)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
next()
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
// Route handler using isolated context
|
|
126
|
+
app.get('/api/user', (req, res) => {
|
|
127
|
+
const ctx = req.memorio
|
|
128
|
+
|
|
129
|
+
// Set request-specific state
|
|
130
|
+
ctx.state.requestId = req.id
|
|
131
|
+
ctx.state.startTime = Date.now()
|
|
132
|
+
|
|
133
|
+
// Cache data for this request
|
|
134
|
+
ctx.cache.set('query', req.query)
|
|
135
|
+
|
|
136
|
+
// Get user data
|
|
137
|
+
const user = getUserFromDB(req.params.id)
|
|
138
|
+
|
|
139
|
+
// Return response
|
|
140
|
+
res.json({
|
|
141
|
+
user,
|
|
142
|
+
requestId: ctx.state.requestId
|
|
143
|
+
})
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
app.listen(3000)
|
|
147
|
+
*/
|
|
148
|
+
|
|
149
|
+
console.debug('See code comments for Express.js integration')
|
|
150
|
+
|
|
151
|
+
// ============================================
|
|
152
|
+
// 6. WEBSOCKET EXAMPLE
|
|
153
|
+
// ============================================
|
|
154
|
+
|
|
155
|
+
console.debug('\n=== 6. WebSocket Example ===')
|
|
156
|
+
|
|
157
|
+
/*
|
|
158
|
+
// For WebSocket connections:
|
|
159
|
+
|
|
160
|
+
const activeConnections = new Map()
|
|
161
|
+
|
|
162
|
+
function handleConnection(ws, userId) {
|
|
163
|
+
// Create isolated context for this user
|
|
164
|
+
const ctx = memorio.createContext(`ws-${userId}`)
|
|
165
|
+
|
|
166
|
+
// Store user data
|
|
167
|
+
ctx.state.userId = userId
|
|
168
|
+
ctx.state.connected = true
|
|
169
|
+
|
|
170
|
+
// Store in connection map
|
|
171
|
+
activeConnections.set(userId, ctx)
|
|
172
|
+
|
|
173
|
+
ws.on('message', (message) => {
|
|
174
|
+
// Process message using isolated context
|
|
175
|
+
ctx.cache.set('lastMessage', message)
|
|
176
|
+
handleMessage(ctx, message)
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
ws.on('close', () => {
|
|
180
|
+
// Clean up
|
|
181
|
+
ctx.state.connected = false
|
|
182
|
+
activeConnections.delete(userId)
|
|
183
|
+
memorio.deleteContext(ctx.id)
|
|
184
|
+
})
|
|
185
|
+
}
|
|
186
|
+
*/
|
|
187
|
+
|
|
188
|
+
console.debug('See code comments for WebSocket integration')
|
|
189
|
+
|
|
190
|
+
// ============================================
|
|
191
|
+
// 7. JOB QUEUE / WORKER EXAMPLE
|
|
192
|
+
// ============================================
|
|
193
|
+
|
|
194
|
+
console.debug('\n=== 7. Job Queue Example ===')
|
|
195
|
+
|
|
196
|
+
/*
|
|
197
|
+
// For background jobs:
|
|
198
|
+
|
|
199
|
+
async function processJob(jobId, jobData) {
|
|
200
|
+
// Create isolated context for this job
|
|
201
|
+
const ctx = memorio.createContext(`job-${jobId}`)
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
// Track job progress
|
|
205
|
+
ctx.state.jobId = jobId
|
|
206
|
+
ctx.state.status = 'processing'
|
|
207
|
+
ctx.state.progress = 0
|
|
208
|
+
|
|
209
|
+
// Process in stages
|
|
210
|
+
for (let i = 0; i < 10; i++) {
|
|
211
|
+
await doWork(jobData)
|
|
212
|
+
ctx.state.progress = (i + 1) * 10
|
|
213
|
+
|
|
214
|
+
// Cache intermediate results
|
|
215
|
+
ctx.cache.set(`stage-${i}`, true)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
ctx.state.status = 'completed'
|
|
219
|
+
return { success: true }
|
|
220
|
+
|
|
221
|
+
} catch (error) {
|
|
222
|
+
ctx.state.status = 'failed'
|
|
223
|
+
ctx.state.error = error.message
|
|
224
|
+
throw error
|
|
225
|
+
|
|
226
|
+
} finally {
|
|
227
|
+
// Clean up after job completes
|
|
228
|
+
memorio.deleteContext(ctx.id)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
*/
|
|
232
|
+
|
|
233
|
+
console.debug('See code comments for Job Queue integration')
|
|
234
|
+
|
|
235
|
+
// ============================================
|
|
236
|
+
// 8. CLI APPLICATION EXAMPLE
|
|
237
|
+
// ============================================
|
|
238
|
+
|
|
239
|
+
console.debug('\n=== 8. CLI Application ===')
|
|
240
|
+
|
|
241
|
+
// Memorio works great in CLI apps too
|
|
242
|
+
state.command = 'build'
|
|
243
|
+
state.options = {
|
|
244
|
+
minify: true,
|
|
245
|
+
sourceMap: false
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
console.debug('Command:', state.command)
|
|
249
|
+
console.debug('Options:', state.options)
|
|
250
|
+
|
|
251
|
+
// ============================================
|
|
252
|
+
// 9. PLATFORM DETECTION
|
|
253
|
+
// ============================================
|
|
254
|
+
|
|
255
|
+
console.debug('\n=== 9. Platform Detection ===')
|
|
256
|
+
|
|
257
|
+
const caps = memorio.getCapabilities()
|
|
258
|
+
console.debug('Platform:', caps.platform)
|
|
259
|
+
console.debug('localStorage:', caps.hasLocalStorage ? '✅' : '❌')
|
|
260
|
+
console.debug('sessionStorage:', caps.hasSessionStorage ? '✅' : '❌')
|
|
261
|
+
console.debug('IndexedDB:', caps.hasIndexedDB ? '✅' : '❌')
|
|
262
|
+
console.debug('Session ID:', caps.sessionId.substring(0, 8) + '...')
|
|
263
|
+
|
|
264
|
+
// ============================================
|
|
265
|
+
// 10. CLEANUP
|
|
266
|
+
// ============================================
|
|
267
|
+
|
|
268
|
+
console.debug('\n=== 10. Cleanup ===')
|
|
269
|
+
|
|
270
|
+
// List all contexts
|
|
271
|
+
console.debug('Active contexts:', memorio.listContexts())
|
|
272
|
+
|
|
273
|
+
// Clean up when done
|
|
274
|
+
memorio.deleteContext('tenant-A')
|
|
275
|
+
memorio.deleteContext('tenant-B')
|
|
276
|
+
|
|
277
|
+
console.debug('After cleanup:', memorio.listContexts())
|
|
278
|
+
|
|
279
|
+
// ============================================
|
|
280
|
+
// SUMMARY
|
|
281
|
+
// ============================================
|
|
282
|
+
|
|
283
|
+
console.debug('\n=== Summary ===')
|
|
284
|
+
console.debug(`
|
|
285
|
+
MEMORIO NODE.JS USAGE:
|
|
286
|
+
|
|
287
|
+
✅ WORKS:
|
|
288
|
+
- state: In-memory global state
|
|
289
|
+
- cache: In-memory temporary cache
|
|
290
|
+
- store: In-memory (NOT persistent!)
|
|
291
|
+
- session: In-memory (NOT persistent!)
|
|
292
|
+
- createContext: Perfect for isolation
|
|
293
|
+
|
|
294
|
+
⚠️ NOTES:
|
|
295
|
+
- store/session don't persist in Node.js
|
|
296
|
+
- Use database for persistence
|
|
297
|
+
- Always use contexts for request isolation
|
|
298
|
+
- Clean up contexts after use
|
|
299
|
+
|
|
300
|
+
🔧 BEST PRACTICES:
|
|
301
|
+
1. Create context per request: createContext(\`req-\${req.id}\`)
|
|
302
|
+
2. Use cache for temporary data
|
|
303
|
+
3. Use state for request-scoped data
|
|
304
|
+
4. Delete contexts after response
|
|
305
|
+
5. Check isPersistent before relying on persistence
|
|
306
|
+
`)
|
|
307
|
+
|
|
308
|
+
console.debug('\nNode.js example complete!')
|