@biglogic/rgs 3.8.4 → 3.9.1
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/core/advanced.cjs +1 -0
- package/core/advanced.js +1 -0
- package/core/minimal.cjs +1 -0
- package/core/minimal.js +1 -19
- package/index.cjs +1 -0
- package/index.js +1 -3925
- package/package.json +43 -47
- package/types/rgs.d.ts +7 -0
- package/README.md +0 -483
- package/docs/README.md +0 -483
- package/docs/SUMMARY.md +0 -55
- package/docs/_config.yml +0 -1
- package/docs/chapters/case-studies.md +0 -69
- package/docs/chapters/faq.md +0 -53
- package/docs/chapters/getting-started.md +0 -68
- package/docs/chapters/local-first-sync.md +0 -146
- package/docs/chapters/migration-guide.md +0 -284
- package/docs/chapters/persistence-and-safety.md +0 -125
- package/docs/chapters/philosophy.md +0 -54
- package/docs/chapters/security-architecture.md +0 -50
- package/docs/chapters/the-magnetar-way.md +0 -69
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
# ⚡ Chapter 2: Quick Start - From Zero to State in 30 Seconds
|
|
2
|
-
|
|
3
|
-
Stop wasting time on boilerplate. Here is how you deploy the RGS Panzer in your React project.
|
|
4
|
-
|
|
5
|
-
## 1. Installation
|
|
6
|
-
|
|
7
|
-
The engine is lightweight but armored.
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install rgs
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## 2. Initialization: The "Big Bang"
|
|
14
|
-
|
|
15
|
-
In your main entry file (e.g., `main.tsx` or `App.tsx`), wake up the engine once.
|
|
16
|
-
|
|
17
|
-
```typescript
|
|
18
|
-
import { initState, useStore } from '@biglogic/rgs';
|
|
19
|
-
|
|
20
|
-
// Initialize with optional settings
|
|
21
|
-
initState({
|
|
22
|
-
namespace: 'my-awesome-app',
|
|
23
|
-
persistence: true // Optional: Saves everything to localStorage automatically
|
|
24
|
-
});
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## 3. Usage: Instant Reactions
|
|
28
|
-
|
|
29
|
-
Use the `useStore` hook. No providers, no wrappers. Just raw, atomic power.
|
|
30
|
-
|
|
31
|
-
```tsx
|
|
32
|
-
import { useStore } from '@biglogic/rgs';
|
|
33
|
-
|
|
34
|
-
function Counter() {
|
|
35
|
-
// If 'count' doesn't exist yet, it defaults to undefined. Easy.
|
|
36
|
-
const [count, setCount] = useStore<number>('count');
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<div className="card">
|
|
40
|
-
<h1>Power Level: {count ?? 0}</h1>
|
|
41
|
-
<button onClick={() => setCount((prev) => (prev || 0) + 1)}>
|
|
42
|
-
Boost Power 💥
|
|
43
|
-
</button>
|
|
44
|
-
</div>
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## 🧐 What just happened?
|
|
50
|
-
|
|
51
|
-
- **Reactive Subscription**: `useStore('count')` tells React to watch the 'count' key. Surgical updates only.
|
|
52
|
-
- **Global Scope**: `setCount` updates the value everywhere in the app, instantly.
|
|
53
|
-
- **Resilient Nature**: If you access a key that hasn't been set yet, RGS returns `undefined` gracefully instead of throwing a tantrum.
|
|
54
|
-
|
|
55
|
-
## 🚨 Pro Tip: Direct Store Access
|
|
56
|
-
|
|
57
|
-
Need to access state outside of React components? Simple.
|
|
58
|
-
|
|
59
|
-
```typescript
|
|
60
|
-
import { getStore } from '@biglogic/rgs';
|
|
61
|
-
|
|
62
|
-
const value = getStore()?.get('count');
|
|
63
|
-
getStore()?.set('count', 9001);
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
---
|
|
67
|
-
|
|
68
|
-
**Next step:** [The Magnetar Way: One-Liner Power](03-the-magnetar-way.md)
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
# 🚀 Chapter 10: Local-First Sync Engine
|
|
2
|
-
|
|
3
|
-
RGS now includes a powerful **Local-First Sync Engine** that makes your app work offline by default and automatically synchronize when connectivity is restored.
|
|
4
|
-
|
|
5
|
-
## Why Local-First?
|
|
6
|
-
|
|
7
|
-
Traditional apps require an internet connection to work. Local-First apps work immediately with local data and sync in the background when possible.
|
|
8
|
-
|
|
9
|
-
### Benefits
|
|
10
|
-
|
|
11
|
-
- **Instant Load** - No waiting for server responses
|
|
12
|
-
- **Works Offline** - App functions without internet
|
|
13
|
-
- **Better UX** - No loading spinners for data
|
|
14
|
-
- **Conflict Resolution** - Smart merge strategies
|
|
15
|
-
|
|
16
|
-
## Quick Start
|
|
17
|
-
|
|
18
|
-
```typescript
|
|
19
|
-
import { gstate, useSyncedState } from '@biglogic/rgs'
|
|
20
|
-
|
|
21
|
-
// Create store with sync enabled
|
|
22
|
-
const store = gstate({
|
|
23
|
-
todos: [],
|
|
24
|
-
user: null
|
|
25
|
-
}, {
|
|
26
|
-
namespace: 'myapp',
|
|
27
|
-
sync: {
|
|
28
|
-
endpoint: 'https://api.example.com/sync',
|
|
29
|
-
// Use a getter function for secure token retrieval
|
|
30
|
-
authToken: () => localStorage.getItem('auth_token'),
|
|
31
|
-
autoSyncInterval: 30000, // Sync every 30s
|
|
32
|
-
syncOnReconnect: true // Auto-sync when back online
|
|
33
|
-
}
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
// Use in React components
|
|
37
|
-
function TodoList() {
|
|
38
|
-
const [todos, setTodos] = useSyncedState('todos')
|
|
39
|
-
|
|
40
|
-
// Add todo - automatically queued for sync
|
|
41
|
-
const addTodo = (text) => {
|
|
42
|
-
setTodos([...todos, { id: Date.now(), text }])
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return <div>{/* ... */}</div>
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Configuration Options
|
|
50
|
-
|
|
51
|
-
| Option | Type | Default | Description |
|
|
52
|
-
|--------|------|---------|-------------|
|
|
53
|
-
| `endpoint` | `string` | required | Remote sync server URL |
|
|
54
|
-
| `authToken` | `string` or `() => string \| null` | - | Authentication token or getter function for secure retrieval |
|
|
55
|
-
| `strategy` | `string` | `'last-write-wins'` | Conflict resolution |
|
|
56
|
-
| `autoSyncInterval` | `number` | `30000` | Auto-sync interval (ms) |
|
|
57
|
-
| `syncOnReconnect` | `boolean` | `true` | Sync on network restore |
|
|
58
|
-
| `debounceTime` | `number` | `1000` | Batch changes (ms) |
|
|
59
|
-
| `maxRetries` | `number` | `3` | Failed sync retries |
|
|
60
|
-
| `onConflict` | `function` | - | Custom conflict handler |
|
|
61
|
-
| `onSync` | `function` | - | Sync completion callback |
|
|
62
|
-
|
|
63
|
-
## Conflict Resolution Strategies
|
|
64
|
-
|
|
65
|
-
### 1. Last-Write-Wins (Default)
|
|
66
|
-
|
|
67
|
-
```typescript
|
|
68
|
-
sync: { strategy: 'last-write-wins' }
|
|
69
|
-
```
|
|
70
|
-
Latest timestamp wins - simplest strategy.
|
|
71
|
-
|
|
72
|
-
### 2. Server-Wins
|
|
73
|
-
|
|
74
|
-
```typescript
|
|
75
|
-
sync: { strategy: 'server-wins' }
|
|
76
|
-
```
|
|
77
|
-
Always prefer remote values - useful for read-heavy apps.
|
|
78
|
-
|
|
79
|
-
### 3. Client-Wins
|
|
80
|
-
|
|
81
|
-
```typescript
|
|
82
|
-
sync: { strategy: 'client-wins' }
|
|
83
|
-
```
|
|
84
|
-
Always prefer local values - useful for write-heavy apps.
|
|
85
|
-
|
|
86
|
-
### 4. Custom Merge
|
|
87
|
-
|
|
88
|
-
```typescript
|
|
89
|
-
sync: {
|
|
90
|
-
strategy: 'merge',
|
|
91
|
-
onConflict: (conflict) => {
|
|
92
|
-
// Custom logic for merging
|
|
93
|
-
return {
|
|
94
|
-
action: 'merge',
|
|
95
|
-
value: { /* merged result */ }
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## Hook API
|
|
102
|
-
|
|
103
|
-
### useSyncedState
|
|
104
|
-
|
|
105
|
-
```typescript
|
|
106
|
-
const [value, setValue, syncState] = useSyncedState('key')
|
|
107
|
-
|
|
108
|
-
// syncState contains:
|
|
109
|
-
// - isOnline: boolean
|
|
110
|
-
// - isSyncing: boolean
|
|
111
|
-
// - pendingChanges: number
|
|
112
|
-
// - conflicts: number
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
### useSyncStatus
|
|
116
|
-
|
|
117
|
-
```typescript
|
|
118
|
-
const status = useSyncStatus()
|
|
119
|
-
// Global sync status across all stores
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## Manual Sync Control
|
|
123
|
-
|
|
124
|
-
```typescript
|
|
125
|
-
// Force sync
|
|
126
|
-
await store.plugins.sync.flush()
|
|
127
|
-
|
|
128
|
-
// Get sync state
|
|
129
|
-
const state = store.plugins.sync.getState()
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
## Integration with Persistence
|
|
133
|
-
|
|
134
|
-
The Sync Engine works seamlessly with RGS's existing persistence layer:
|
|
135
|
-
|
|
136
|
-
- **Local Storage** - Data persists locally first
|
|
137
|
-
- **IndexedDB** - For larger datasets
|
|
138
|
-
- **Cloud Sync** - Optional remote backup
|
|
139
|
-
|
|
140
|
-
Your data survives browser refresh, works offline, and stays synchronized across devices.
|
|
141
|
-
|
|
142
|
-
## Next Steps
|
|
143
|
-
|
|
144
|
-
- Learn about [Security Architecture](09-security-architecture.md)
|
|
145
|
-
- Explore [Plugin SDK](05-plugin-sdk.md)
|
|
146
|
-
- Check [Migration Guide](08-migration-guide.md)
|
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
# 8. Migration Guide
|
|
2
|
-
|
|
3
|
-
## Upgrading to v3.5.0 (The Type-Safe Era)
|
|
4
|
-
|
|
5
|
-
### New Feature: Selectors
|
|
6
|
-
v3.5.0 introduces **Function Selectors** for `useStore`. This is fully backward compatible, but we recommend migrating new code to this pattern for better type safety.
|
|
7
|
-
|
|
8
|
-
#### ✅ Recommended Pattern
|
|
9
|
-
```tsx
|
|
10
|
-
// Type-safe, autocomplete friendly
|
|
11
|
-
const userName = useStore(state => state.user.name)
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
#### 🟡 Legacy Pattern (Still Supported)
|
|
15
|
-
```tsx
|
|
16
|
-
// String-based, prone to typos
|
|
17
|
-
const [userName] = useStore('user_name')
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## Upgrading to v3.4.0
|
|
23
|
-
|
|
24
|
-
### Performance Defaults
|
|
25
|
-
- **Size Limits**: `maxObjectSize` and `maxTotalSize` now default to `0` (disabled). If you relied on these warnings during development, explicitly enable them in `initState` or `gstate` options.
|
|
26
|
-
|
|
27
|
-
### Deprecations Removed
|
|
28
|
-
- `useGState` and `useSimpleState` have been removed. Replace all instances with `useStore`.
|
|
29
|
-
- `_registerMethod(name, fn)` support is removed from types (runtime warning remains). Update plugins to use `_registerMethod(pluginName, methodName, fn)`.
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## Upgrading from Previous Versions
|
|
34
|
-
|
|
35
|
-
### Security: `secure` → `encoded`
|
|
36
|
-
|
|
37
|
-
**IMPORTANT:** The `secure` option has been deprecated in favor of `encoded` to clarify that it only applies **base64 encoding**, not encryption.
|
|
38
|
-
|
|
39
|
-
#### ❌ Old Code (Deprecated)
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
store.set('apiKey', 'secret123', {
|
|
43
|
-
persist: true,
|
|
44
|
-
secure: true // ⚠️ DEPRECATED: This is NOT encryption!
|
|
45
|
-
})
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
#### ✅ New Code (Recommended)
|
|
49
|
-
|
|
50
|
-
```typescript
|
|
51
|
-
store.set('apiKey', 'secret123', {
|
|
52
|
-
persist: true,
|
|
53
|
-
encoded: true // ✅ Clear: This is base64 encoding
|
|
54
|
-
})
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
#### Backward Compatibility
|
|
58
|
-
|
|
59
|
-
Your old code will **still work**, but you'll see a deprecation warning in TypeScript:
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
/** @deprecated Use 'encoded' instead. 'secure' only applies base64 encoding, not encryption. */
|
|
63
|
-
secure?: boolean
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
#### Why This Change?
|
|
67
|
-
|
|
68
|
-
Base64 encoding is **NOT encryption**. It's trivial to decode:
|
|
69
|
-
|
|
70
|
-
```javascript
|
|
71
|
-
// Anyone can decode base64
|
|
72
|
-
const encoded = btoa(JSON.stringify({ secret: 'password123' }))
|
|
73
|
-
const decoded = JSON.parse(atob(encoded)) // { secret: 'password123' }
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
**For real security**, use proper encryption libraries like:
|
|
77
|
-
|
|
78
|
-
- `crypto-js` (AES encryption)
|
|
79
|
-
- `tweetnacl` (NaCl encryption)
|
|
80
|
-
- Web Crypto API (`crypto.subtle`)
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
### Error Handling: `onError` Callback
|
|
85
|
-
|
|
86
|
-
**NEW:** You can now catch and handle errors from plugins, hydration, and other operations.
|
|
87
|
-
|
|
88
|
-
#### Example: Custom Error Logging
|
|
89
|
-
|
|
90
|
-
```typescript
|
|
91
|
-
import { initState, useStore } from '@biglogic/rgs'
|
|
92
|
-
|
|
93
|
-
const store = initState({
|
|
94
|
-
namespace: 'myapp',
|
|
95
|
-
onError: (error, context) => {
|
|
96
|
-
// Send to your error tracking service
|
|
97
|
-
console.error(`[gState Error] ${context.operation}:`, error)
|
|
98
|
-
|
|
99
|
-
if (context.operation === 'hydration') {
|
|
100
|
-
// Handle corrupted localStorage
|
|
101
|
-
localStorage.clear()
|
|
102
|
-
alert('Storage corrupted, resetting...')
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (context.operation.startsWith('plugin:')) {
|
|
106
|
-
// Handle plugin crashes
|
|
107
|
-
Sentry.captureException(error, { tags: { plugin: context.operation } })
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
})
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
#### Error Context
|
|
114
|
-
|
|
115
|
-
```typescript
|
|
116
|
-
interface ErrorContext {
|
|
117
|
-
operation: string // 'hydration', 'plugin:name:hook', 'set'
|
|
118
|
-
key?: string // State key (if applicable)
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
### Performance: `maxObjectSize` Warning
|
|
125
|
-
|
|
126
|
-
**NEW:** Get warned when storing objects larger than a configurable limit (default: 5MB).
|
|
127
|
-
|
|
128
|
-
#### Example: Custom Size Limit
|
|
129
|
-
|
|
130
|
-
```typescript
|
|
131
|
-
import { createStore } from '@biglogic/rgs'
|
|
132
|
-
|
|
133
|
-
const store = createStore({
|
|
134
|
-
maxObjectSize: 10 * 1024 * 1024, // 10MB limit
|
|
135
|
-
onError: (error, context) => {
|
|
136
|
-
if (context.operation === 'set') {
|
|
137
|
-
console.warn(`Large object detected in key: ${context.key}`)
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
// This will trigger a warning if > 10MB
|
|
143
|
-
store.set('bigData', hugeArray)
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
#### Disable Size Checking
|
|
147
|
-
|
|
148
|
-
```typescript
|
|
149
|
-
const store = createStore({
|
|
150
|
-
maxObjectSize: 0 // Disable size warnings
|
|
151
|
-
})
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
---
|
|
155
|
-
|
|
156
|
-
## Upgrading to Latest Version (The Enterprise Update)
|
|
157
|
-
|
|
158
|
-
**IMPORTANT:** This release introduces a fundamental shift towards **Multi-Store Isolation**. Security rules and GDPR consents are now instance-bound rather than global.
|
|
159
|
-
|
|
160
|
-
### 1. Security: Global → Instance-Specific
|
|
161
|
-
|
|
162
|
-
In previous versions, security rules were shared globally. Now, each store instance maintains its own rules for better isolation in micro-frontend environments.
|
|
163
|
-
|
|
164
|
-
#### ❌ Deprecated Global Methods
|
|
165
|
-
|
|
166
|
-
```typescript
|
|
167
|
-
import { addAccessRule, recordConsent } from '@biglogic/rgs'
|
|
168
|
-
|
|
169
|
-
// ⚠️ DEPRECATED: These affect the 'default' store only and are less isolated
|
|
170
|
-
addAccessRule('user_*', ['read', 'write'])
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
#### ✅ Recommended Instance Methods
|
|
174
|
-
|
|
175
|
-
```typescript
|
|
176
|
-
const store = createStore({ namespace: 'my-isolated-app' })
|
|
177
|
-
|
|
178
|
-
// ✅ Use the instance methods
|
|
179
|
-
store.addAccessRule('user_*', ['read', 'write'])
|
|
180
|
-
store.recordConsent('user123', 'marketing', true)
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
### 2. Operational Resilience: Ghost Stores
|
|
184
|
-
|
|
185
|
-
**NEW:** If you access a store that hasn't finished its initialization (e.g., during slow hydration), RGS now returns a **Ghost Store Proxy**.
|
|
186
|
-
|
|
187
|
-
- **Behavior:** It prevents application crashes by providing a safe fallback.
|
|
188
|
-
- **Developer Warning:** It logs a detailed warning in the console so you can fix the initialization sequence.
|
|
189
|
-
|
|
190
|
-
### 3. Performance: Regex Caching
|
|
191
|
-
|
|
192
|
-
**NEW:** Permission checks now use an internal **Regex Cache** per instance.
|
|
193
|
-
|
|
194
|
-
- **Why?** Avoids the overhead of re-compiling regex strings on every `.get()` or `.set()` call.
|
|
195
|
-
- **Impact:** Significant performance boost for applications with high-frequency state updates and complex RBAC rules.
|
|
196
|
-
|
|
197
|
-
### 4. Advanced Plugin Typing
|
|
198
|
-
|
|
199
|
-
**NEW:** Introducing `GStatePlugins` for Module Augmentation.
|
|
200
|
-
|
|
201
|
-
- You can now define types for your custom plugins to get full IDE autocomplete.
|
|
202
|
-
|
|
203
|
-
---
|
|
204
|
-
|
|
205
|
-
## v2.9.5: The Architecture & Safety Update (2026-02-16)
|
|
206
|
-
|
|
207
|
-
This release focuses on improving developer ergonomics, security visibility, and complex dependency handling.
|
|
208
|
-
|
|
209
|
-
### 1. Nested Computed Dependencies
|
|
210
|
-
|
|
211
|
-
**NEW:** Computed values can now re-trigger based on other computed values.
|
|
212
|
-
|
|
213
|
-
```typescript
|
|
214
|
-
store.compute('tax', (get) => (get<number>('subtotal') || 0) * 0.2)
|
|
215
|
-
store.compute('total', (get) => (get<number>('subtotal') || 0) + (get<number>('tax') || 0))
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
### 2. Direct Store Access: `getStore()`
|
|
219
|
-
**NEW:** A top-level utility to retrieve the default store without React hooks.
|
|
220
|
-
|
|
221
|
-
```typescript
|
|
222
|
-
import { getStore } from '@biglogic/rgs'
|
|
223
|
-
|
|
224
|
-
export const toggleTheme = () => {
|
|
225
|
-
const store = getStore()
|
|
226
|
-
if (store) store.set('mode', 'dark')
|
|
227
|
-
}
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
### 3. Exposed Metadata: `namespace` and `userId`
|
|
231
|
-
**NEW:** Store instances now expose their identifying properties as read-only getters.
|
|
232
|
-
|
|
233
|
-
```typescript
|
|
234
|
-
const store = createStore({ namespace: 'auth-vault', userId: 'user-001' })
|
|
235
|
-
console.log(store.namespace) // 'auth-vault'
|
|
236
|
-
console.log(store.userId) // 'user-001'
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### 4. High-Volume & Hybrid Sync (Plugins)
|
|
240
|
-
**NEW:** Support for GB-scale storage and Remote Cloud Backups.
|
|
241
|
-
|
|
242
|
-
- **IndexedDB Plugin**: Replaces localStorage for massive browser datasets.
|
|
243
|
-
- **Cloud Sync Plugin**: Differential synchronization to MongoDB, Firebase, or any SQL backend.
|
|
244
|
-
|
|
245
|
-
```typescript
|
|
246
|
-
// Example: Manual Cloud Sync
|
|
247
|
-
const result = await store.plugins.cloudSync.sync()
|
|
248
|
-
console.log('Stats:', store.plugins.cloudSync.getStats())
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
---
|
|
252
|
-
|
|
253
|
-
## Breaking Changes
|
|
254
|
-
|
|
255
|
-
### 🔒 Security Isolation
|
|
256
|
-
|
|
257
|
-
If you relied on `addAccessRule()` from the global export to affect a `createStore()` instance, you must now call `store.addAccessRule()` on that specific instance.
|
|
258
|
-
|
|
259
|
-
---
|
|
260
|
-
|
|
261
|
-
## Recommended Actions
|
|
262
|
-
|
|
263
|
-
### 1. Migrate Security Calls to Store Instances
|
|
264
|
-
|
|
265
|
-
**Priority:** High (if using multiple stores)
|
|
266
|
-
|
|
267
|
-
**Effort:** Low
|
|
268
|
-
|
|
269
|
-
### 2. Implement `GStatePlugins` for Custom Plugins
|
|
270
|
-
|
|
271
|
-
**Priority:** Medium (Developer Experience)
|
|
272
|
-
|
|
273
|
-
**Effort:** Low
|
|
274
|
-
|
|
275
|
-
---
|
|
276
|
-
|
|
277
|
-
## Need Help?
|
|
278
|
-
|
|
279
|
-
- **Issues:** [GitHub Issues](https://github.com/@biglogic/rgs/issues)
|
|
280
|
-
- **Docs:** [Galaxy Documentation](../SUMMARY.md)
|
|
281
|
-
|
|
282
|
-
---
|
|
283
|
-
|
|
284
|
-
## Last updated: 2026-02-16
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
# 🏗️ Chapter 4: Persistence and Safety - Built like a Tank
|
|
2
|
-
|
|
3
|
-
In a real-world application, state that vanishes on page refresh is a developer failure. RGS handles data saving **intelligently**.
|
|
4
|
-
|
|
5
|
-
## 💾 Persistence: "Set and Forget"
|
|
6
|
-
|
|
7
|
-
When you initialize RGS or a Magnetar, you can enable persistence. But it's not a simple `localStorage.set`.
|
|
8
|
-
|
|
9
|
-
```typescript
|
|
10
|
-
initState({
|
|
11
|
-
persist: true,
|
|
12
|
-
storage: 'local' // or 'session', or a custom adapter
|
|
13
|
-
});
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
### Advanced Storage: Beyond 5MB
|
|
17
|
-
|
|
18
|
-
For applications that need to store massive amounts of data (Gigabytes), standard `localStorage` is not enough. RGS provides official plugins for advanced scenarios:
|
|
19
|
-
|
|
20
|
-
| Technology | Capacity | Purpose | Plugin |
|
|
21
|
-
| :--- | :--- | :--- | :--- |
|
|
22
|
-
| **LocalStorage** | ~5MB | Basic UI settings, small profiles. | Core (Native) |
|
|
23
|
-
| **IndexedDB** | GBs | Offline-first apps, large datasets, logs. | `indexedDBPlugin` |
|
|
24
|
-
| **Cloud Sync** | Unlimited | Remote backup, cross-device sync. | `cloudSyncPlugin` |
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## ☁️ Hybrid Persistence: The "Cloud-Cloud" Strategy
|
|
29
|
-
|
|
30
|
-
RGS allows you to combine local power with cloud safety. You can store your active data in **IndexedDB** for speed and capacity, while automatically backing it up to a remote database (MongoDB, Firebase, SQL) using the **Cloud Sync Plugin**.
|
|
31
|
-
|
|
32
|
-
### Why use Cloud Sync?
|
|
33
|
-
- **Differential Updates**: Safely sends only what was changed since the last sync.
|
|
34
|
-
- **Scheduled or On-Demand**: Sync every 5 minutes automatically, or triggered by a "Save to Cloud" button.
|
|
35
|
-
- **Diagnostics**: Track how much data you are syncing and detect errors before they reach the user.
|
|
36
|
-
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
### What happens under the hood?
|
|
40
|
-
|
|
41
|
-
```mermaid
|
|
42
|
-
sequenceDiagram
|
|
43
|
-
participant C as Component
|
|
44
|
-
participant RGS as Globo State
|
|
45
|
-
participant S as LocalStorage
|
|
46
|
-
|
|
47
|
-
Note over C,RGS: User clicks a button
|
|
48
|
-
C->>RGS: set('count', 10)
|
|
49
|
-
RGS-->>C: Update UI (Instant)
|
|
50
|
-
|
|
51
|
-
Note over RGS: Waiting 300ms (Debounce)
|
|
52
|
-
|
|
53
|
-
RGS->>S: Write to Disk
|
|
54
|
-
Note right of S: Data saved successfully
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
- **Debouncing**: If you update the state 100 times in one second, RGS writes to the disk only once at the end. This saves battery life and browser performance.
|
|
58
|
-
- **Selective Persistence**: Don't want to save everything? You can tell RGS which keys to ignore or which ones to save only temporarily.
|
|
59
|
-
|
|
60
|
-
## 🛡️ Immutability: The Immer Shield
|
|
61
|
-
|
|
62
|
-
Have you ever had bugs where state changed "mysteriously" because you mutated an array directly? RGS uses **Immer** at its core (the Stellar Engine).
|
|
63
|
-
|
|
64
|
-
**Dangerous Code (Standard JS):**
|
|
65
|
-
|
|
66
|
-
```javascript
|
|
67
|
-
const user = store.get('user');
|
|
68
|
-
user.permissions.push('admin'); // BOOM! You mutated the original without triggering a re-render.
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
**The RGS Way:**
|
|
72
|
-
|
|
73
|
-
```javascript
|
|
74
|
-
store.set('user', (draft) => {
|
|
75
|
-
draft.permissions.push('admin'); // SAFE! RGS creates an immutable copy for you.
|
|
76
|
-
});
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## 🕵️ Validation: Schema Plugin
|
|
80
|
-
|
|
81
|
-
Never trust data coming back from the server or saved in the browser 6 months ago. Use the **schemaPlugin**.
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
import { schemaPlugin } from '@biglogic/rgs';
|
|
85
|
-
import { z } from 'zod'; // Recommended!
|
|
86
|
-
|
|
87
|
-
const store = initState();
|
|
88
|
-
store._addPlugin(schemaPlugin({
|
|
89
|
-
price: (val) => typeof val === 'number' && val > 0,
|
|
90
|
-
email: (val) => val.includes('@')
|
|
91
|
-
}));
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
If anyone tries to `set('price', -50)`, RGS will block the operation and warn you. **Clean State = Happy App.**
|
|
95
|
-
|
|
96
|
-
---
|
|
97
|
-
|
|
98
|
-
## ⚠️ Size Limits: maxObjectSize & maxTotalSize
|
|
99
|
-
|
|
100
|
-
Protect your app from memory issues with automatic size warnings:
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
const store = initState({
|
|
104
|
-
// Warn if single value exceeds 5MB (default: 5MB)
|
|
105
|
-
maxObjectSize: 5 * 1024 * 1024,
|
|
106
|
-
// Warn if total store exceeds 50MB (default: 50MB)
|
|
107
|
-
maxTotalSize: 50 * 1024 * 1024
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
// Setting a value that exceeds the limit will trigger a warning
|
|
111
|
-
store.set('largeData', bigObject); // Warns if > maxObjectSize
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
---
|
|
115
|
-
|
|
116
|
-
## 💡 Case Study: The Cart that Never Lost an Item
|
|
117
|
-
|
|
118
|
-
**Challenge**: User adds products, closes the browser, comes back after two days. The cart must still be there, and synced with their account on other devices.
|
|
119
|
-
**RGS Solution**:
|
|
120
|
-
|
|
121
|
-
1. Enable `indexedDBPlugin` for robust local storage (handles thousands of items).
|
|
122
|
-
2. Use `cloudSyncPlugin` to bridge the local state with your company's MongoDB Atlas or Firebase.
|
|
123
|
-
3. Result? 5-star UX with full data durability and cross-device sync.
|
|
124
|
-
|
|
125
|
-
**Next step:** [Ecosystem and Plugins: Extending the Power](05-plugins-and-extensibility.md)
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# 🧠 Chapter 1: The Philosophy - Panzer vs. Bicycle
|
|
2
|
-
|
|
3
|
-
You are a developer. You have deadlines. You have bugs. But more importantly, you have a reputation to protect.
|
|
4
|
-
|
|
5
|
-
## 🚜 Choose Your Vehicle
|
|
6
|
-
|
|
7
|
-
Most state managers focus on being "lightweight" or "easy." **RGS (Argis)** has evolved beyond that. It is a framework designed for high-stakes applications where data leakage is a disaster and production uptime is non-negotiable.
|
|
8
|
-
|
|
9
|
-
### The Bicycle (Standard Hooks/Context)
|
|
10
|
-
|
|
11
|
-
If you just need a counter for a simple todo list, use a basic hook or `useState`. You don't need a Panzer to go to the grocery store. It's light, it's fast to set up, but it offers zero protection when the road gets rough.
|
|
12
|
-
|
|
13
|
-
### The Panzer (RGS)
|
|
14
|
-
|
|
15
|
-
If you are building an Enterprise platform where:
|
|
16
|
-
|
|
17
|
-
- **Isolation is King**: User A's data must never collide with User B's state.
|
|
18
|
-
- **Fail-Safe Security**: RBAC (Role-Based Access Control) is built into the state layer.
|
|
19
|
-
- **Resilience**: The app must survive uninitialized states without crashing (`Ghost Stores`).
|
|
20
|
-
|
|
21
|
-
...then you need a Panzer. **You need RGS.**
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## 🚀 Surgical Performance: Atomic Access
|
|
26
|
-
|
|
27
|
-
RGS was born from a "crazy" idea: **State should be global by nature, but atomic by access.**
|
|
28
|
-
|
|
29
|
-
### 🔴 Camp A: Context API (The Re-render Rain)
|
|
30
|
-
|
|
31
|
-
In React Context, any change in the provider forces a global re-render of the entire tree consuming it. Change a theme brand color? The whole product list re-renders.
|
|
32
|
-
|
|
33
|
-
### 🟢 Camp B: RGS (The Sniper)
|
|
34
|
-
|
|
35
|
-
In RGS, only the component observing a specific key wakes up. Change the 'cart'? Only the cart icon updates. Total silence for the rest of the application.
|
|
36
|
-
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
## 🛡️ Defensive Engineering
|
|
40
|
-
|
|
41
|
-
We don't just manage state; we protect it:
|
|
42
|
-
|
|
43
|
-
- **Zero Boilerplate**: No actions, no reducers. Just `.set()` and Move on.
|
|
44
|
-
- **Fail-Closed Security**: If a pattern is defined but doesn't explicitly match the action, access is denied. No exceptions.
|
|
45
|
-
- **Ghost Stores**: If a component accesses an uninitialized store, we return a Proxy that warns you but **keeps the UI alive**. No more `ReferenceError: store is not defined`.
|
|
46
|
-
|
|
47
|
-
## 💡 Case Study: "No-Stress" E-commerce
|
|
48
|
-
|
|
49
|
-
Imagine a shopping cart.
|
|
50
|
-
|
|
51
|
-
- **Standard Approach**: The user adds a sock, and the entire product list (2000 items) re-renders because they share a Context.
|
|
52
|
-
- **RGS Approach**: Adds the item with `set('cart', [...])`. Only the tiny cart badge updates. 3ms execution time. Happy client, happy developer.
|
|
53
|
-
|
|
54
|
-
**Next step:** [Quick Start: 30-Second Setup](02-getting-started.md)
|