@biglogic/rgs 3.8.4 β 3.9.2
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/README.md +9 -13
- 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/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,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)
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# Security Architecture & Hardening
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
Reactive Global State (RGS) is designed with a "Security-First" philosophy. Our architecture ensures that global state is not only reactive but protected against common web vulnerabilities and unauthorized access.
|
|
5
|
-
|
|
6
|
-
## 1. Data Sanitization (XSS Defense)
|
|
7
|
-
The `sanitizeValue` utility provides a robust baseline defense by stripping malicious content from strings and objects before they enter the store.
|
|
8
|
-
|
|
9
|
-
- **Scheme Blocking**: Specifically blocks `javascript:`, `vbscript:`, and `data:text/html` schemes.
|
|
10
|
-
- **Tag Removal**: Automatically removes dangerous HTML tags such as `<script>`, `<iframe>`, `<form>`, and `<meta>`.
|
|
11
|
-
- **Entity Removal**: Strips HTML entities (`&#...;`) to prevent obfuscation-based bypasses.
|
|
12
|
-
|
|
13
|
-
## 2. Advanced Deep Cloning
|
|
14
|
-
To ensure state immutability and prevent unintended side effects, RGS uses an intelligent cloning engine:
|
|
15
|
-
- **Native structuredClone**: Leverages the browser's native API for maximum performance.
|
|
16
|
-
- **Support for Collections**: Extends cloning capabilities to `Map` and `Set` objects.
|
|
17
|
-
- **Circular Reference Protection**: Uses `WeakMap` to handle complex nested structures safely.
|
|
18
|
-
|
|
19
|
-
## 3. Cryptography (AES-256-GCM)
|
|
20
|
-
The security module uses the Web Crypto API to provide high-performance, authenticated encryption:
|
|
21
|
-
- **AES-GCM**: Provides both confidentiality and integrity verification.
|
|
22
|
-
- **GCM (Galois/Counter Mode)**: Ensures that data has not been tampered with during storage.
|
|
23
|
-
- **Safe Random UUID**: Fallback generation for environments without Web Crypto API.
|
|
24
|
-
|
|
25
|
-
## 4. RBAC (Role-Based Access Control)
|
|
26
|
-
RGS supports fine-grained access rules:
|
|
27
|
-
- **Fail-Closed Design**: Access is denied by default if any rules are defined.
|
|
28
|
-
- **Regex Caching**: Store instances cache compiled regular expressions for ultra-fast permission checks.
|
|
29
|
-
- **ReDoS Protection**: Regex patterns have a 100ms timeout to prevent denial-of-service attacks.
|
|
30
|
-
- **Storage Key Validation**: All persisted keys are validated against a strict pattern before storage.
|
|
31
|
-
|
|
32
|
-
## 5. Security Best Practices
|
|
33
|
-
For real-world implementations, refer to the `examples/security-best-practices` directory, which covers:
|
|
34
|
-
- **Encryption Key Management**: Using `generateEncryptionKey()` for secure key generation.
|
|
35
|
-
- **Audit Logging**: Tracking all store modifications for compliance.
|
|
36
|
-
- **GDPR Compliance**: Managing user consent and data export/deletion.
|
|
37
|
-
|
|
38
|
-
## Summary of 2.9.5 Enhancements
|
|
39
|
-
- Robust regex patterns for `sanitizeValue`.
|
|
40
|
-
- Recursive sanitization for plain objects.
|
|
41
|
-
- `Map` and `Set` support in `deepClone`.
|
|
42
|
-
- **Exposed Metadata**: Store instances now expose read-only `namespace` and `userId`.
|
|
43
|
-
- **Direct Store Access**: Added `getStore()` utility for non-React contexts.
|
|
44
|
-
|
|
45
|
-
## Summary of 3.7.0 Enhancements
|
|
46
|
-
- **ReDoS Protection**: Regex patterns timeout after 100ms to prevent malicious patterns.
|
|
47
|
-
- **Safe UUID**: Fallback UUID generation for environments without Web Crypto API.
|
|
48
|
-
- **Storage Key Validation**: Keys validated before persistence to prevent injection.
|
|
49
|
-
- **Production Safety**: Global window access only enabled in development mode (`NODE_ENV !== 'production'`).
|
|
50
|
-
- **PBKDF2 Key Derivation**: New `deriveKeyFromPassword()` and `generateSalt()` functions for secure password-based encryption (NIST SC-12 compliant).
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# π Chapter 3: The Magnetar Way - Peak Simplicity
|
|
2
|
-
|
|
3
|
-
If you are a fan of "Clean Code" or just hate writing imports, the **Magnetar** method is your new best friend.
|
|
4
|
-
|
|
5
|
-
It's a single function that creates the store and the hook simultaneously. **Zero config, 100% typed.**
|
|
6
|
-
|
|
7
|
-
## π οΈ The "Master" Example
|
|
8
|
-
|
|
9
|
-
Let's create a User Profile module.
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
import { gstate } from '@biglogic/rgs';
|
|
13
|
-
|
|
14
|
-
// 1. Define the state and create everything in ONE shot
|
|
15
|
-
// Pass a string namespace to enable automatic persistence to localStorage
|
|
16
|
-
export const useUser = gstate({
|
|
17
|
-
name: 'Guest',
|
|
18
|
-
isLogged: false,
|
|
19
|
-
preferences: { theme: 'dark', lang: 'en' }
|
|
20
|
-
}, 'user_module'); // Auto-persists to localStorage (excludes sensitive fields)
|
|
21
|
-
|
|
22
|
-
// Or use an object config for more control:
|
|
23
|
-
export const useUserNoPersist = gstate({
|
|
24
|
-
name: 'Guest',
|
|
25
|
-
isLogged: false
|
|
26
|
-
}, { namespace: 'user_module', autoPersist: false }); // No persistence
|
|
27
|
-
|
|
28
|
-
// 2. Use it anywhere
|
|
29
|
-
function ProfileHeader() {
|
|
30
|
-
const [name, setName] = useUser('name');
|
|
31
|
-
// Note: 'setName' is already typed! It only accepts strings.
|
|
32
|
-
|
|
33
|
-
return <h1>Hello, {name}!</h1>;
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## π Why Magnetar Rocks
|
|
38
|
-
|
|
39
|
-
1. **Inferred Types**: No need to define `<string>`. TypeScript looks at the initial value you passed to `gstate` and figures it out.
|
|
40
|
-
2. **Auto-Persistence**: When you pass a string namespace, RGS automatically persists to localStorage (excluding sensitive fields like tokens, passwords, secrets).
|
|
41
|
-
3. **Security**: Sensitive fields (containing 'token', 'password', 'secret', 'key') are automatically excluded from persistence.
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
// You can access the store OUTSIDE components!
|
|
45
|
-
const currentUser = useUser.get('name');
|
|
46
|
-
useUser.set('isLogged', true);
|
|
47
|
-
|
|
48
|
-
// You can even compute data on the fly (Computed State)
|
|
49
|
-
useUser.compute('fullName', ['firstName', 'lastName'], (s) => `${s.firstName} ${s.lastName}`);
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## π Production Strategy: "The Store Folder"
|
|
53
|
-
|
|
54
|
-
Don't scatter stores everywhere. Create a `src/stores` folder and put your Magnetar files there:
|
|
55
|
-
|
|
56
|
-
- `auth.ts`
|
|
57
|
-
- `cart.ts`
|
|
58
|
-
- `settings.ts`
|
|
59
|
-
|
|
60
|
-
Then import them whenever needed. Itβs clean, fast, and professional.
|
|
61
|
-
|
|
62
|
-
## π§ Reflection for the Senior Dev
|
|
63
|
-
|
|
64
|
-
*"Wait, does Magnetar create a new store every time?"*
|
|
65
|
-
Yes, and that's the point! You can have isolated micro-stores for every domain of your app, while still keeping the ability to make them talk to each other. Itβs the evolution of the "Atomic State" concept.
|
|
66
|
-
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
**Next step:** [Persistence and Safety: Data Never Dies](04-persistence-and-safety.md)
|