/** * Memorio Node.js Server Example * * This example shows how to use Memorio in a Node.js server environment. * Includes context isolation for multi-tenant applications. * * Run: npx ts-node examples/node-server.ts */ import 'memorio' // ============================================ // 1. BASIC USAGE // ============================================ console.debug('=== 1. Basic Node.js Usage ===') // Check platform console.debug('Platform:', memorio.isNode() ? 'Node.js ✅' : 'Other') // Check persistence (false in Node.js - uses memory fallback) console.debug('Store persistent:', store.isPersistent) // false console.debug('Session persistent:', session.isPersistent) // false // State works exactly like in browser state.appName = 'My Server App' state.startTime = Date.now() state.config = { port: 3000, env: 'production' } console.debug('App name:', state.appName) console.debug('Config:', state.config) // ============================================ // 2. CACHE (In-Memory - Perfect for Server) // ============================================ console.debug('\n=== 2. Cache (In-Memory) ===') // Cache is perfect for temporary server data cache.set('apiResponse', { data: 'cached value' }) cache.set('userCount', 42) console.debug('Cached API response:', cache.get('apiResponse')) console.debug('User count:', cache.get('userCount')) // Clear cache when needed cache.remove('apiResponse') // cache.clearAll() - clear all // ============================================ // 3. STORE & SESSION (Memory Fallback in Node.js) // ============================================ console.debug('\n=== 3. Store & Session (Memory Fallback) ===') // Store and session work but don't persist (no localStorage in Node.js) store.set('serverConfig', { debug: true }) session.set('requestData', { path: '/api/users' }) console.debug('Server config:', store.get('serverConfig')) console.debug('Request data:', session.get('requestData')) // ⚠️ Data is lost on process restart! // For persistence in Node.js, use a database // ============================================ // 4. CONTEXT ISOLATION (Multi-Tenant) // ============================================ console.debug('\n=== 4. Context Isolation (Multi-Tenant) ===') // Create isolated contexts for different tenants/requests const userAContext = memorio.createContext('tenant-A') const userBContext = memorio.createContext('tenant-B') // Each context has completely separate data userAContext.state.user = { name: 'Alice', id: 1 } userAContext.state.secret = 'Alice secret data' userAContext.cache.set('temp', 'A temp data') userBContext.state.user = { name: 'Bob', id: 2 } userBContext.state.secret = 'Bob secret data' userBContext.cache.set('temp', 'B temp data') // Verify isolation console.debug('User A name:', userAContext.state.user.name) // Alice console.debug('User B name:', userBContext.state.user.name) // Bob // Global state is separate console.debug('Global state:', state.appName) // 'My Server App' console.debug('User A global secret:', userAContext.state.secret) // 'Alice secret data' console.debug('User B global secret:', userBContext.state.secret) // 'Bob secret data' // ============================================ // 5. EXPRESS.JS MIDDLEWARE EXAMPLE // ============================================ console.debug('\n=== 5. Express.js Middleware Example ===') /* // In a real Express app: import express from 'express' const app = express() // Middleware to create isolated context per request app.use((req, res, next) => { // Create unique context for this request const ctx = memorio.createContext(`req-${req.id}`) // Attach to request for use in handlers req.memorio = ctx // Clean up on response finish res.on('finish', () => { memorio.deleteContext(ctx.id) }) next() }) // Route handler using isolated context app.get('/api/user', (req, res) => { const ctx = req.memorio // Set request-specific state ctx.state.requestId = req.id ctx.state.startTime = Date.now() // Cache data for this request ctx.cache.set('query', req.query) // Get user data const user = getUserFromDB(req.params.id) // Return response res.json({ user, requestId: ctx.state.requestId }) }) app.listen(3000) */ console.debug('See code comments for Express.js integration') // ============================================ // 6. WEBSOCKET EXAMPLE // ============================================ console.debug('\n=== 6. WebSocket Example ===') /* // For WebSocket connections: const activeConnections = new Map() function handleConnection(ws, userId) { // Create isolated context for this user const ctx = memorio.createContext(`ws-${userId}`) // Store user data ctx.state.userId = userId ctx.state.connected = true // Store in connection map activeConnections.set(userId, ctx) ws.on('message', (message) => { // Process message using isolated context ctx.cache.set('lastMessage', message) handleMessage(ctx, message) }) ws.on('close', () => { // Clean up ctx.state.connected = false activeConnections.delete(userId) memorio.deleteContext(ctx.id) }) } */ console.debug('See code comments for WebSocket integration') // ============================================ // 7. JOB QUEUE / WORKER EXAMPLE // ============================================ console.debug('\n=== 7. Job Queue Example ===') /* // For background jobs: async function processJob(jobId, jobData) { // Create isolated context for this job const ctx = memorio.createContext(`job-${jobId}`) try { // Track job progress ctx.state.jobId = jobId ctx.state.status = 'processing' ctx.state.progress = 0 // Process in stages for (let i = 0; i < 10; i++) { await doWork(jobData) ctx.state.progress = (i + 1) * 10 // Cache intermediate results ctx.cache.set(`stage-${i}`, true) } ctx.state.status = 'completed' return { success: true } } catch (error) { ctx.state.status = 'failed' ctx.state.error = error.message throw error } finally { // Clean up after job completes memorio.deleteContext(ctx.id) } } */ console.debug('See code comments for Job Queue integration') // ============================================ // 8. CLI APPLICATION EXAMPLE // ============================================ console.debug('\n=== 8. CLI Application ===') // Memorio works great in CLI apps too state.command = 'build' state.options = { minify: true, sourceMap: false } console.debug('Command:', state.command) console.debug('Options:', state.options) // ============================================ // 9. PLATFORM DETECTION // ============================================ console.debug('\n=== 9. Platform Detection ===') const caps = memorio.getCapabilities() console.debug('Platform:', caps.platform) console.debug('localStorage:', caps.hasLocalStorage ? '✅' : '❌') console.debug('sessionStorage:', caps.hasSessionStorage ? '✅' : '❌') console.debug('IndexedDB:', caps.hasIndexedDB ? '✅' : '❌') console.debug('Session ID:', caps.sessionId.substring(0, 8) + '...') // ============================================ // 10. CLEANUP // ============================================ console.debug('\n=== 10. Cleanup ===') // List all contexts console.debug('Active contexts:', memorio.listContexts()) // Clean up when done memorio.deleteContext('tenant-A') memorio.deleteContext('tenant-B') console.debug('After cleanup:', memorio.listContexts()) // ============================================ // SUMMARY // ============================================ console.debug('\n=== Summary ===') console.debug(` MEMORIO NODE.JS USAGE: ✅ WORKS: - state: In-memory global state - cache: In-memory temporary cache - store: In-memory (NOT persistent!) - session: In-memory (NOT persistent!) - createContext: Perfect for isolation ⚠️ NOTES: - store/session don't persist in Node.js - Use database for persistence - Always use contexts for request isolation - Clean up contexts after use 🔧 BEST PRACTICES: 1. Create context per request: createContext(\`req-\${req.id}\`) 2. Use cache for temporary data 3. Use state for request-scoped data 4. Delete contexts after response 5. Check isPersistent before relying on persistence `) console.debug('\nNode.js example complete!')