memorio 2.8.0 → 2.9.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.
@@ -0,0 +1,180 @@
1
+ # Observer - Memorio
2
+
3
+ > ⚠️ **DEPRECATED**: This function is deprecated and will be removed in future versions. Please use [`useObserver`](USEOBSERVER.md) instead.
4
+
5
+ Observer lets you react to state changes. When a state key changes, your callback function runs.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install memorio
11
+ ```
12
+
13
+ ```javascript
14
+ import 'memorio';
15
+ ```
16
+
17
+ ---
18
+
19
+ ## Quick Examples
20
+
21
+ ### Example 1: Basic Usage
22
+
23
+ ```javascript
24
+ // Simple observer (DEPRECATED - use useObserver instead)
25
+ console.warn('observer() is deprecated. Please use useObserver() for React or memorio.dispatch for vanilla JS.');
26
+
27
+ observer('state.counter', (newValue) => {
28
+ console.log('Counter is now:', newValue);
29
+ });
30
+
31
+ state.counter = 1;
32
+ // Output: "Counter is now: 1"
33
+
34
+ state.counter = 5;
35
+ // Output: "Counter is now: 5"
36
+ ```
37
+
38
+ > **Note**: For new projects, use [`useObserver`](USEOBSERVER.md) for React or [`memorio.dispatch`](SUMMARY.md) for vanilla JS.
39
+
40
+ ### Example 2: Intermediate
41
+
42
+ ```javascript
43
+ // Observer with old value
44
+ observer('state.user', (newValue, oldValue) => {
45
+ console.log(`User changed from ${oldValue?.name} to ${newValue?.name}`);
46
+ });
47
+
48
+ state.user = { name: 'Mario' };
49
+ // Output: "User changed from undefined to Mario"
50
+
51
+ state.user = { name: 'Luigi' };
52
+ // Output: "User changed from Mario to Luigi"
53
+ ```
54
+
55
+ ### Example 3: Advanced
56
+
57
+ ```javascript
58
+ // Multiple observers
59
+ const obs1 = observer('state.data', handler1);
60
+ const obs2 = observer('state.data', handler2);
61
+
62
+ // List all observers
63
+ console.log(observer.list);
64
+ // Output: [{ name: 'state.data', id: '...' }, ...]
65
+
66
+ // Remove specific observer
67
+ observer.remove('state.data');
68
+
69
+ // Remove all observers
70
+ observer.removeAll();
71
+ ```
72
+
73
+ ---
74
+
75
+ ## API Reference
76
+
77
+ ### observer(path, callback)
78
+
79
+ | Parameter | Type | Description |
80
+ |-----------|------|-------------|
81
+ | `path` | `string` | State path to watch (e.g., `'state.counter'`) |
82
+ | `callback` | `function` | Function called on change |
83
+
84
+ ### Callback Parameters
85
+
86
+ ```javascript
87
+ observer('state.key', (newValue, oldValue) => {
88
+ // newValue: the new value
89
+ // oldValue: the previous value
90
+ });
91
+ ```
92
+
93
+ ### Properties
94
+
95
+ | Property | Type | Description |
96
+ |----------|------|-------------|
97
+ | `observer.list` | `Array` | Get all active observers |
98
+
99
+ ### Methods
100
+
101
+ | Method | Parameters | Description |
102
+ |--------|------------|-------------|
103
+ | `observer.remove(name)` | `string` | Remove observer for specific path |
104
+ | `observer.removeAll()` | none | Remove all observers |
105
+
106
+ ---
107
+
108
+ ## React Integration
109
+
110
+ ### With useState
111
+
112
+ ```javascript
113
+ const [count, setCount] = useState(0);
114
+
115
+ observer('state.counter', () => {
116
+ setCount(state.counter);
117
+ });
118
+ ```
119
+
120
+ ### With useEffect
121
+
122
+ ```javascript
123
+ useEffect(() => {
124
+ const handleChange = (newVal) => {
125
+ console.log('Changed:', newVal);
126
+ };
127
+
128
+ observer('state.data', handleChange);
129
+
130
+ // Cleanup
131
+ return () => observer.remove('state.data');
132
+ }, []);
133
+ ```
134
+
135
+ ---
136
+
137
+ ## How It Works
138
+
139
+ Observer subscribes to state changes via the Proxy's set trap. When `state.key = value` is called:
140
+ 1. The Proxy intercepts the set
141
+ 2. Fires all callbacks registered for that path
142
+ 3. Callbacks receive newValue and oldValue
143
+
144
+ ---
145
+
146
+ ## Best Practices
147
+
148
+ 1. Clean up observers in React `useEffect` return
149
+ 2. Use specific paths: `'state.user.name'` not `'state'`
150
+ 3. Remove observers when components unmount
151
+ 4. Use `observer.removeAll()` on page navigation
152
+
153
+ ---
154
+
155
+ ## Common Patterns
156
+
157
+ ### Form Validation
158
+
159
+ ```javascript
160
+ observer('state.form.email', (email) => {
161
+ const isValid = email.includes('@');
162
+ state.form.isValid = isValid;
163
+ });
164
+ ```
165
+
166
+ ### Analytics
167
+
168
+ ```javascript
169
+ observer('state.page', (page) => {
170
+ analytics.track('page_view', { page });
171
+ });
172
+ ```
173
+
174
+ ### Auto-save
175
+
176
+ ```javascript
177
+ observer('state.draft', (content) => {
178
+ store.set('autosave', content);
179
+ });
180
+ ```
@@ -0,0 +1,260 @@
1
+ # Platform & Context Isolation - Memorio
2
+
3
+ > ℹ️ **New in v2.7.0**: Context isolation system for multi-tenant server-side applications
4
+
5
+ Memorio automatically detects the runtime environment and adapts its behavior accordingly. This document explains platform compatibility, session isolation, and the new context system.
6
+
7
+ ---
8
+
9
+ ## Quick Reference: Client vs Server
10
+
11
+ ### Which Module to Use?
12
+
13
+ | Scenario | Recommended Module | Persistence |
14
+ |----------|-------------------|-------------|
15
+ | UI State (React/components) | `state` | Memory |
16
+ | Temporary computed data | `cache` | Memory |
17
+ | User preferences | `store` | Browser localStorage |
18
+ | Auth tokens | `session` | Browser sessionStorage |
19
+ | Large offline data | `idb` | IndexedDB |
20
+ | Server request isolation | `memorio.createContext()` | Memory |
21
+
22
+ ### Module Availability
23
+
24
+ | Module | Browser | Node.js | Deno | Edge |
25
+ |--------|--------|---------|------|------|
26
+ | `state` | ✅ | ✅ | ✅ | ✅ |
27
+ | `cache` | ✅ | ✅ | ✅ | ✅ |
28
+ | `store` | ✅ (localStorage) | ⚠️ (memory) | ⚠️ (memory) | ✅ |
29
+ | `session` | ✅ (sessionStorage) | ⚠️ (memory) | ⚠️ (memory) | ✅ |
30
+ | `idb` | ✅ | ❌ | ❌ | ⚠️ |
31
+ | `useObserver` | ✅ | ⚠️ | ⚠️ | ✅ |
32
+ | `devtools` | ✅ | ❌ | ❌ | ❌ |
33
+
34
+ ---
35
+
36
+ ## Platform Detection
37
+
38
+ Memorio automatically detects the environment on import:
39
+
40
+ ```javascript
41
+ import 'memorio';
42
+
43
+ // Check current platform
44
+ console.log(memorio.platform); // 'browser' | 'node' | 'deno' | 'edge'
45
+ console.log(memorio.isPersistent); // true if using real storage
46
+ ```
47
+
48
+ ### Available Platform APIs
49
+
50
+ ```javascript
51
+ // Check platform
52
+ memorio.isBrowser() // true in browser
53
+ memorio.isNode() // true in Node.js
54
+ memorio.isDeno() // true in Deno
55
+ memorio.isEdge() // true in Edge Workers
56
+
57
+ // Get capabilities
58
+ const caps = memorio.getCapabilities();
59
+ // caps.platform, caps.hasSessionStorage, caps.hasLocalStorage, etc.
60
+ ```
61
+
62
+ ---
63
+
64
+ ## Platform Compatibility Matrix
65
+
66
+ | Feature | Browser | Node.js | Deno | Edge Workers |
67
+ |---------|---------|---------|------|--------------|
68
+ | `state` | ✅ | ✅ | ✅ | ✅ |
69
+ | `observer` | ✅ | ✅ | ✅ | ✅ |
70
+ | `useObserver` | ✅ | ⚠️ React only | ⚠️ React only | ✅ |
71
+ | `cache` | ✅ | ✅ | ✅ | ✅ |
72
+ | `store` | ✅ (localStorage) | ⚠️ (memory) | ⚠️ (memory) | ✅ (localStorage) |
73
+ | `session` | ✅ (sessionStorage) | ⚠️ (memory) | ⚠️ (memory) | ✅ (sessionStorage) |
74
+ | `idb` | ✅ | ❌ | ❌ | ⚠️ |
75
+
76
+ - ✅ Full support
77
+ - ⚠️ Partial support (fallback to in-memory)
78
+ - ❌ Not available
79
+
80
+ ---
81
+
82
+ ## Client vs Server Usage
83
+
84
+ ### 🖥️ Client-Side (Browser)
85
+
86
+ All features work with real browser storage:
87
+
88
+ ```javascript
89
+ // Store - persistent localStorage
90
+ store.set('preferences', { theme: 'dark' });
91
+ store.isPersistent; // true
92
+
93
+ // Session - temporary sessionStorage
94
+ session.set('token', 'jwt-token');
95
+ session.isPersistent; // true (survives refresh)
96
+
97
+ // IDB - large data storage
98
+ idb.db.create('myApp');
99
+ ```
100
+
101
+ ### 🖥️ Server-Side (Node.js/Deno)
102
+
103
+ Use `state` and `cache` for in-memory data. Store/session fall back to memory:
104
+
105
+ ```javascript
106
+ // State - in-memory global state
107
+ state.user = { name: 'Server User' };
108
+
109
+ // Cache - in-memory temporary cache
110
+ cache.set('apiResponse', data);
111
+
112
+ // Store - in-memory fallback (not persistent)
113
+ store.set('temp', data);
114
+ store.isPersistent; // false - data lost on restart
115
+
116
+ // Session - in-memory fallback
117
+ session.set('requestData', data);
118
+ session.isPersistent; // false - data lost on restart
119
+ ```
120
+
121
+ ---
122
+
123
+ ## Session Isolation
124
+
125
+ Each instance/session gets unique storage keys to prevent conflicts:
126
+
127
+ ```javascript
128
+ // Keys are prefixed with session ID
129
+ // store: "memorio_store_[sessionId]_key"
130
+ // session: "memorio_session_[sessionId]_key"
131
+ ```
132
+
133
+ This ensures:
134
+ - Multiple browser tabs don't share session data
135
+ - Server-side requests are isolated
136
+
137
+ ---
138
+
139
+ ## Context Isolation (Server-Side Multi-Tenancy)
140
+
141
+ > ⚠️ **Server-Side Only**: This feature is designed for multi-tenant server environments (Node.js, Deno). Not needed for client-side applications.
142
+
143
+ For server-side applications handling multiple tenants (e.g., different users/requests), use **contexts** to isolate data:
144
+
145
+ ### Creating a Context
146
+
147
+ ```javascript
148
+ // Create isolated context for a user/session
149
+ const ctx = memorio.createContext('user-123');
150
+
151
+ // Use context's isolated storage
152
+ ctx.state.user = { name: 'Isolated User' };
153
+ ctx.store.set('settings', { theme: 'dark' });
154
+ ctx.session.set('token', 'abc123');
155
+ ctx.cache.set('temp', data);
156
+
157
+ // Context is completely isolated from global state
158
+ console.log(state.user); // undefined - global state is separate
159
+ ```
160
+
161
+ ### Managing Contexts
162
+
163
+ ```javascript
164
+ // List all contexts
165
+ const contexts = memorio.listContexts();
166
+ console.log(contexts); // ['user-123', 'user-456', ...]
167
+
168
+ // Delete a context (cleanup)
169
+ memorio.deleteContext('user-123');
170
+
171
+ // Shorthand for createContext
172
+ const ctx2 = memorio.isolate('tenant-A');
173
+ ```
174
+
175
+ ### Context Use Cases
176
+
177
+ #### 1. Per-Request Isolation (Express/Fastify)
178
+
179
+ ```javascript
180
+ // Middleware to isolate each request
181
+ app.use((req, res, next) => {
182
+ const ctx = memorio.createContext(`req-${req.id}`);
183
+ req.memorioContext = ctx;
184
+ next();
185
+ });
186
+
187
+ // In route handler
188
+ app.get('/user', (req, res) => {
189
+ const ctx = req.memorioContext;
190
+ ctx.state.user = getUserData();
191
+ // Each request has isolated state
192
+ });
193
+ ```
194
+
195
+ #### 2. Multi-Tenant SaaS
196
+
197
+ ```javascript
198
+ // Each tenant gets isolated storage
199
+ function handleTenant(tenantId) {
200
+ const ctx = memorio.createContext(tenantId);
201
+
202
+ ctx.state.config = getTenantConfig(tenantId);
203
+ ctx.store.set('data', tenantData);
204
+
205
+ return ctx;
206
+ }
207
+ ```
208
+
209
+ ---
210
+
211
+ ## Best Practices
212
+
213
+ ### Client-Side (Browser)
214
+
215
+ 1. Use `store` for persistent data (preferences, user settings)
216
+ 2. Use `session` for temporary data (auth tokens)
217
+ 3. Use `cache` for computed values
218
+ 4. Use `state` for reactive UI state
219
+
220
+ ### Server-Side (Node.js/Deno)
221
+
222
+ 1. Use `memorio.createContext()` for each request/tenant
223
+ 2. Don't use global `state`/`store`/`session` across requests
224
+ 3. Use `cache` for request-scoped caching
225
+ 4. Check `store.isPersistent` / `session.isPersistent` if persistence matters
226
+
227
+ ### Edge Workers
228
+
229
+ Same as browser - localStorage and sessionStorage are available.
230
+
231
+ ---
232
+
233
+ ## API Reference
234
+
235
+ ### Global Functions
236
+
237
+ | Function | Returns | Description |
238
+ |----------|---------|-------------|
239
+ | `memorio.isBrowser()` | `boolean` | Check if running in browser |
240
+ | `memorio.isNode()` | `boolean` | Check if running in Node.js |
241
+ | `memorio.isDeno()` | `boolean` | Check if running in Deno |
242
+ | `memorio.isEdge()` | `boolean` | Check if running in Edge |
243
+ | `memorio.getCapabilities()` | `object` | Get platform capabilities |
244
+
245
+ ### Context Management
246
+
247
+ | Function | Returns | Description |
248
+ |----------|---------|-------------|
249
+ | `memorio.createContext(name?)` | `Context` | Create isolated context |
250
+ | `memorio.listContexts()` | `string[]` | List all context IDs |
251
+ | `memorio.deleteContext(id)` | `boolean` | Delete a context |
252
+ | `memorio.isolate(name?)` | `Context` | Alias for createContext |
253
+
254
+ ### Properties
255
+
256
+ | Property | Type | Description |
257
+ |----------|------|-------------|
258
+ | `memorio.version` | `string` | Memorio version |
259
+ | `memorio.platform` | `string` | Current platform |
260
+ | `memorio._sessionId` | `string` | Unique session identifier |