@biglogic/rgs 3.9.6 → 3.9.8
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/ssr.d.ts +73 -0
- package/core/thunk.d.ts +75 -0
- package/docs/README.md +479 -0
- package/docs/SUMMARY.md +55 -0
- package/docs/_config.yml +1 -0
- package/docs/markdown/api.md +381 -0
- package/docs/markdown/case-studies.md +69 -0
- package/docs/markdown/faq.md +53 -0
- package/docs/markdown/getting-started.md +68 -0
- package/docs/markdown/local-first-sync.md +146 -0
- package/docs/markdown/migration-guide.md +284 -0
- package/docs/markdown/persistence-and-safety.md +125 -0
- package/docs/markdown/philosophy.md +54 -0
- package/docs/markdown/plugin-sdk.md +161 -0
- package/docs/markdown/plugins-and-extensibility.md +82 -0
- package/docs/markdown/security-architecture.md +50 -0
- package/docs/markdown/the-magnetar-way.md +69 -0
- package/index.cjs +1004 -276
- package/index.d.ts +4 -0
- package/index.js +1206 -485
- package/package.json +2 -1
package/core/ssr.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { IStore, StoreConfig } from "./types";
|
|
2
|
+
export declare const isServerSide: () => boolean;
|
|
3
|
+
export declare const isClientSide: () => boolean;
|
|
4
|
+
export interface SSRStoreConfig<S extends Record<string, unknown>> extends StoreConfig<S> {
|
|
5
|
+
deferHydration?: boolean;
|
|
6
|
+
initialState?: S;
|
|
7
|
+
ssrSafe?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare const createSSRStore: <S extends Record<string, unknown>>(config?: SSRStoreConfig<S>) => IStore<S> & {
|
|
10
|
+
hydrate: () => Promise<void>;
|
|
11
|
+
getSerializedState: () => string | null;
|
|
12
|
+
isHydrated: () => boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare const hydrateOnClient: (store: IStore<Record<string, unknown>>) => Promise<void>;
|
|
15
|
+
export declare const dehydrateStore: (store: IStore<Record<string, unknown>>) => string;
|
|
16
|
+
export declare const rehydrateStore: (store: IStore<Record<string, unknown>>, serializedState: string) => void;
|
|
17
|
+
export declare const useHydrated: () => boolean;
|
|
18
|
+
export declare const useHydrationStatus: () => {
|
|
19
|
+
isHydrated: boolean;
|
|
20
|
+
isHydrating: boolean;
|
|
21
|
+
};
|
|
22
|
+
export declare const useDeferredStore: <S extends Record<string, unknown>>(store: IStore<S> & {
|
|
23
|
+
isHydrated?: () => boolean;
|
|
24
|
+
}) => IStore<S>;
|
|
25
|
+
export declare const createNextStore: <S extends Record<string, unknown>>(config?: SSRStoreConfig<S>) => IStore<S> & {
|
|
26
|
+
hydrate: () => Promise<void>;
|
|
27
|
+
getSerializedState: () => string | null;
|
|
28
|
+
isHydrated: () => boolean;
|
|
29
|
+
} & {
|
|
30
|
+
useHydrated: () => boolean;
|
|
31
|
+
useHydrationStatus: () => {
|
|
32
|
+
isHydrated: boolean;
|
|
33
|
+
isHydrating: boolean;
|
|
34
|
+
};
|
|
35
|
+
useDeferredStore: <K extends keyof S>(key: K) => unknown;
|
|
36
|
+
};
|
|
37
|
+
export declare const getSSRInitialState: (store: IStore<Record<string, unknown>>) => Record<string, unknown>;
|
|
38
|
+
export declare const initializeFromSSR: (store: IStore<Record<string, unknown>>, initialState: Record<string, unknown>) => void;
|
|
39
|
+
declare const _default: {
|
|
40
|
+
isServerSide: () => boolean;
|
|
41
|
+
isClientSide: () => boolean;
|
|
42
|
+
createSSRStore: <S extends Record<string, unknown>>(config?: SSRStoreConfig<S>) => IStore<S> & {
|
|
43
|
+
hydrate: () => Promise<void>;
|
|
44
|
+
getSerializedState: () => string | null;
|
|
45
|
+
isHydrated: () => boolean;
|
|
46
|
+
};
|
|
47
|
+
hydrateOnClient: (store: IStore<Record<string, unknown>>) => Promise<void>;
|
|
48
|
+
dehydrateStore: (store: IStore<Record<string, unknown>>) => string;
|
|
49
|
+
rehydrateStore: (store: IStore<Record<string, unknown>>, serializedState: string) => void;
|
|
50
|
+
useHydrated: () => boolean;
|
|
51
|
+
useHydrationStatus: () => {
|
|
52
|
+
isHydrated: boolean;
|
|
53
|
+
isHydrating: boolean;
|
|
54
|
+
};
|
|
55
|
+
useDeferredStore: <S extends Record<string, unknown>>(store: IStore<S> & {
|
|
56
|
+
isHydrated?: () => boolean;
|
|
57
|
+
}) => IStore<S>;
|
|
58
|
+
createNextStore: <S extends Record<string, unknown>>(config?: SSRStoreConfig<S>) => IStore<S> & {
|
|
59
|
+
hydrate: () => Promise<void>;
|
|
60
|
+
getSerializedState: () => string | null;
|
|
61
|
+
isHydrated: () => boolean;
|
|
62
|
+
} & {
|
|
63
|
+
useHydrated: () => boolean;
|
|
64
|
+
useHydrationStatus: () => {
|
|
65
|
+
isHydrated: boolean;
|
|
66
|
+
isHydrating: boolean;
|
|
67
|
+
};
|
|
68
|
+
useDeferredStore: <K extends keyof S>(key: K) => unknown;
|
|
69
|
+
};
|
|
70
|
+
getSSRInitialState: (store: IStore<Record<string, unknown>>) => Record<string, unknown>;
|
|
71
|
+
initializeFromSSR: (store: IStore<Record<string, unknown>>, initialState: Record<string, unknown>) => void;
|
|
72
|
+
};
|
|
73
|
+
export default _default;
|
package/core/thunk.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { IStore } from "./types";
|
|
2
|
+
export type ThunkAction<R = void, S extends Record<string, unknown> = Record<string, unknown>> = (dispatch: ThunkDispatch<S>, getState: () => S, extraArgument?: unknown) => Promise<R> | R;
|
|
3
|
+
export type ThunkDispatch<S extends Record<string, unknown> = Record<string, unknown>> = <R>(action: ThunkAction<R, S> | ThunkActionPayload<S>) => Promise<R>;
|
|
4
|
+
export interface ThunkActionPayload<_S extends Record<string, unknown> = Record<string, unknown>> {
|
|
5
|
+
type: string;
|
|
6
|
+
payload?: unknown;
|
|
7
|
+
meta?: Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
export interface ThunkMiddlewareConfig {
|
|
10
|
+
extraArgument?: unknown;
|
|
11
|
+
dispatchKey?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare const createThunkStore: <S extends Record<string, unknown>>(store: IStore<S>, config?: ThunkMiddlewareConfig) => IStore<S> & {
|
|
14
|
+
dispatch: ThunkDispatch<S>;
|
|
15
|
+
};
|
|
16
|
+
export declare const createActions: <S extends Record<string, unknown>, T extends Record<string, unknown>>(store: IStore<S>, creators: T) => T & {
|
|
17
|
+
dispatch: ThunkDispatch<S>;
|
|
18
|
+
};
|
|
19
|
+
export declare const createAsyncAction: <T>(key: string, fetcher: () => Promise<T>) => ThunkAction<T, Record<string, {
|
|
20
|
+
data: T | null;
|
|
21
|
+
loading: boolean;
|
|
22
|
+
error: Error | null;
|
|
23
|
+
}>>;
|
|
24
|
+
export declare const createAsyncActions: <S extends Record<string, unknown>>(store: IStore<S>, actions: Record<string, () => Promise<unknown>>) => Record<string, ThunkAction<unknown, S>>;
|
|
25
|
+
export type Effect = {
|
|
26
|
+
type: 'call';
|
|
27
|
+
fn: () => Promise<unknown>;
|
|
28
|
+
args?: unknown[];
|
|
29
|
+
} | {
|
|
30
|
+
type: 'put';
|
|
31
|
+
action: ThunkActionPayload<Record<string, unknown>>;
|
|
32
|
+
} | {
|
|
33
|
+
type: 'select';
|
|
34
|
+
selector: (state: Record<string, unknown>) => unknown;
|
|
35
|
+
} | {
|
|
36
|
+
type: 'take';
|
|
37
|
+
pattern: string | ((action: ThunkActionPayload) => boolean);
|
|
38
|
+
} | {
|
|
39
|
+
type: 'all';
|
|
40
|
+
effects: Effect[];
|
|
41
|
+
} | {
|
|
42
|
+
type: 'race';
|
|
43
|
+
effects: Record<string, Effect>;
|
|
44
|
+
};
|
|
45
|
+
export declare const call: (fn: () => Promise<unknown>, ...args: unknown[]) => Effect;
|
|
46
|
+
export declare const put: (action: ThunkActionPayload<Record<string, unknown>>) => Effect;
|
|
47
|
+
export declare const select: (selector: (state: Record<string, unknown>) => unknown) => Effect;
|
|
48
|
+
export declare const take: (pattern: string | ((action: ThunkActionPayload) => boolean)) => Effect;
|
|
49
|
+
export declare const all: (effects: Effect[]) => Effect;
|
|
50
|
+
export declare const race: (effects: Record<string, Effect>) => Effect;
|
|
51
|
+
export declare const createSaga: <S extends Record<string, unknown>>(generator: Generator<Effect, void, unknown>) => ((dispatch: ThunkDispatch<S>, getState: () => S, extraArgument?: unknown) => Promise<void>);
|
|
52
|
+
export declare const runSaga: <S extends Record<string, unknown>>(store: IStore<S>, saga: ThunkAction<void, S>) => (() => void);
|
|
53
|
+
declare const _default: {
|
|
54
|
+
createThunkStore: <S extends Record<string, unknown>>(store: IStore<S>, config?: ThunkMiddlewareConfig) => IStore<S> & {
|
|
55
|
+
dispatch: ThunkDispatch<S>;
|
|
56
|
+
};
|
|
57
|
+
createActions: <S extends Record<string, unknown>, T extends Record<string, unknown>>(store: IStore<S>, creators: T) => T & {
|
|
58
|
+
dispatch: ThunkDispatch<S>;
|
|
59
|
+
};
|
|
60
|
+
createAsyncAction: <T>(key: string, fetcher: () => Promise<T>) => ThunkAction<T, Record<string, {
|
|
61
|
+
data: T | null;
|
|
62
|
+
loading: boolean;
|
|
63
|
+
error: Error | null;
|
|
64
|
+
}>>;
|
|
65
|
+
createAsyncActions: <S extends Record<string, unknown>>(store: IStore<S>, actions: Record<string, () => Promise<unknown>>) => Record<string, ThunkAction<unknown, S>>;
|
|
66
|
+
call: (fn: () => Promise<unknown>, ...args: unknown[]) => Effect;
|
|
67
|
+
put: (action: ThunkActionPayload<Record<string, unknown>>) => Effect;
|
|
68
|
+
select: (selector: (state: Record<string, unknown>) => unknown) => Effect;
|
|
69
|
+
take: (pattern: string | ((action: ThunkActionPayload) => boolean)) => Effect;
|
|
70
|
+
all: (effects: Effect[]) => Effect;
|
|
71
|
+
race: (effects: Record<string, Effect>) => Effect;
|
|
72
|
+
createSaga: <S extends Record<string, unknown>>(generator: Generator<Effect, void, unknown>) => ((dispatch: ThunkDispatch<S>, getState: () => S, extraArgument?: unknown) => Promise<void>);
|
|
73
|
+
runSaga: <S extends Record<string, unknown>>(store: IStore<S>, saga: ThunkAction<void, S>) => (() => void);
|
|
74
|
+
};
|
|
75
|
+
export default _default;
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
# 🚀 ARGIS (RGS) - Reactive Global State
|
|
2
|
+
|
|
3
|
+
> **"Atomic Precision. Immutable Safety. Zen Simplicity."**
|
|
4
|
+
> The state management engine that **won't let you fail**.
|
|
5
|
+
|
|
6
|
+
[](https://npmjs.org/package/@biglogic/rgs)
|
|
7
|
+
[](https://npmjs.org/package/@biglogic/rgs)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
[](https://www.typescriptlang.org/)
|
|
10
|
+
[](https://react.dev/)
|
|
11
|
+
|
|
12
|
+
> **🔐 Security Compliance**: This project is fully compliant with **NIST SP 800-132** standards for password-based key derivation, featuring AES-256-GCM encryption, PBKDF2 with 600k iterations, and 32-byte salts.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## ⚡ TL;DR
|
|
17
|
+
|
|
18
|
+
>Why ARGIS (RGS) Will Change How You Code Forever
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
// One line. Zero boilerplate. Enterprise-grade power.
|
|
22
|
+
const useUser = gstate({
|
|
23
|
+
name: 'Alice',
|
|
24
|
+
cart: [],
|
|
25
|
+
preferences: { theme: 'dark' }
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
// That's it. Use it anywhere:
|
|
29
|
+
const name = useUser(s => s.name)
|
|
30
|
+
const theme = useUser(s => s.preferences.theme)
|
|
31
|
+
|
|
32
|
+
// Mutations? Just write it. Immer handles immutability automatically.
|
|
33
|
+
useUser(s => {
|
|
34
|
+
s.cart.push({ id: 1, item: 'Coffee Machine', price: 99 })
|
|
35
|
+
})
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Stop fighting your state management. Start building.**
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 🎯 Why Developers Are **Obsessed** With ARGIS (RGS)
|
|
43
|
+
|
|
44
|
+
| Feature | Other Libraries | ARGIS (RGS) |
|
|
45
|
+
|---------|----------------|--------------|
|
|
46
|
+
| **API Complexity** | 10+ functions, providers, reducers | **1 function** - `gstate()` |
|
|
47
|
+
| **Immutability** | Manual spreads, Redux boilerplate | **Automatic** - Powered by Immer |
|
|
48
|
+
| **Security** | None | **AES-256 + RBAC + GDPR** built-in |
|
|
49
|
+
| **Persistence** | Manual localStorage/sessionStorage | **First-class** - Auto-save anywhere |
|
|
50
|
+
| **Offline/Cloud Sync** | Non-existent | **Local-First + Cloud Sync** included |
|
|
51
|
+
| **Bundle Size** | 10-50KB+ | **~2KB** minimal / **~32KB** full |
|
|
52
|
+
| **Type Safety** | Partial | **100% TypeScript** out of the box |
|
|
53
|
+
|
|
54
|
+
### 🔥 The Truth About State Management
|
|
55
|
+
|
|
56
|
+
Most libraries make you **choose** between:
|
|
57
|
+
- ✗ Simplicity vs Power
|
|
58
|
+
- ✗ Security vs Speed
|
|
59
|
+
- ✗ Offline vs Cloud
|
|
60
|
+
|
|
61
|
+
**ARGIS (RGS) gives you ALL of it.**
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 🏆 RGS vs The Competition
|
|
66
|
+
|
|
67
|
+
| Feature | **RGS (Argis)** | Zustand | Redux Toolkit | Recoil | Jotai |
|
|
68
|
+
|---------|:---:|:---:|:---:|:---:|:---:|
|
|
69
|
+
| **Philosophy** | Zen State | Minimalist | Enterprise Flux | Atomic | Atomic |
|
|
70
|
+
| **API Surface** | **1 Function** | Simple | Complex | Complex | Simple |
|
|
71
|
+
| **Mutations** | **Magic (Immer)** | Manual | Magic | Manual | Manual |
|
|
72
|
+
| **Security** | 🛡️ **AES-256 + RBAC** | ❌ | ❌ | ❌ | ❌ |
|
|
73
|
+
| **Persistence** | 💾 **First-class** | 🔌 | 🔌 | 🔌 | 🔌 |
|
|
74
|
+
| **Local-First Sync** | ✅ **Built-in** | ❌ | ❌ | ❌ | ❌ |
|
|
75
|
+
| **Bundle Size** | **~2KB/32KB** | ~1KB | >10KB | >20KB | ~3KB |
|
|
76
|
+
|
|
77
|
+
> **RGS is the ONLY library treating Security and Persistence as first-class citizens.**
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 🚀 Installation
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# The fastest way to upgrade your React app
|
|
85
|
+
npm install @biglogic/rgs
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Or with pnpm
|
|
90
|
+
pnpm add @biglogic/rgs
|
|
91
|
+
|
|
92
|
+
# Or with yarn
|
|
93
|
+
yarn add @biglogic/rgs
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 🎮 Quick Start - 30 Seconds to Glory
|
|
99
|
+
|
|
100
|
+
### The Zen Way (Recommended)
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import { gstate } from '@biglogic/rgs'
|
|
104
|
+
|
|
105
|
+
// ONE line creates a typed store hook
|
|
106
|
+
const useStore = gstate({
|
|
107
|
+
count: 0,
|
|
108
|
+
user: { name: 'Alice', email: 'alice@example.com' }
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
function Counter() {
|
|
112
|
+
// Type-safe selectors - the React way
|
|
113
|
+
const count = useStore(s => s.count)
|
|
114
|
+
const userName = useStore(s => s.user.name)
|
|
115
|
+
|
|
116
|
+
// Direct mutations - just write JavaScript
|
|
117
|
+
const increment = () => useStore(s => { s.count++ })
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<div>
|
|
121
|
+
<h1>Hello, {userName}!</h1>
|
|
122
|
+
<p>Count: {count}</p>
|
|
123
|
+
<button onClick={increment}>+1</button>
|
|
124
|
+
</div>
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### The Classic Way (Global Store)
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
import { initState, useStore } from '@biglogic/rgs'
|
|
133
|
+
|
|
134
|
+
// Initialize once at app root
|
|
135
|
+
initState({ namespace: 'myapp' })
|
|
136
|
+
|
|
137
|
+
// Use anywhere in your app
|
|
138
|
+
const [user, setUser] = useStore('user')
|
|
139
|
+
const [theme, setTheme] = useStore('theme')
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 🛡️ Enterprise-Grade Security (No Extra Code)
|
|
145
|
+
|
|
146
|
+
### AES-256-GCM Encryption
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
// Your sensitive data is encrypted automatically
|
|
150
|
+
const useAuth = gstate({
|
|
151
|
+
token: 'jwt-token-here',
|
|
152
|
+
refreshToken: 'refresh-token'
|
|
153
|
+
}, { encoded: true }) // 🔐 AES-256-GCM encryption enabled
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### RBAC (Role-Based Access Control)
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
const store = gstate({
|
|
160
|
+
adminPanel: { users: [], settings: {} },
|
|
161
|
+
userProfile: {}
|
|
162
|
+
}, {
|
|
163
|
+
rbac: {
|
|
164
|
+
admin: ['adminPanel', 'userProfile'],
|
|
165
|
+
user: ['userProfile'],
|
|
166
|
+
guest: []
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
// Only admins can touch adminPanel
|
|
171
|
+
store.set('adminPanel', { users: ['new'] }) // ✅ Works for admins
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### GDPR Compliance
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
// Export all user data (GDPR requirement)
|
|
178
|
+
store.exportData() // Returns JSON of all stored data
|
|
179
|
+
|
|
180
|
+
// Delete all user data (GDPR "right to be forgotten")
|
|
181
|
+
store.deleteData()
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## 💾 Persistence That Just Works
|
|
187
|
+
|
|
188
|
+
### Built-in Storage Adapters
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
// localStorage (default) - survives browser restart
|
|
192
|
+
const useSettings = gstate({ theme: 'dark' }, { persist: true })
|
|
193
|
+
|
|
194
|
+
// sessionStorage - survives page refresh but not tab close
|
|
195
|
+
const useSession = gstate({ temporary: 'data' }, { storage: 'session' })
|
|
196
|
+
|
|
197
|
+
// Memory only - for ephemeral data
|
|
198
|
+
const useMemory = gstate({ cache: [] }, { storage: 'memory' })
|
|
199
|
+
|
|
200
|
+
// IndexedDB - for GB-scale data
|
|
201
|
+
const useBigData = gstate({ dataset: [] })
|
|
202
|
+
store._addPlugin(indexedDBPlugin({ dbName: 'my-app-db' }))
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 🔌 Plugins Ecosystem - Extend Without Limits
|
|
208
|
+
|
|
209
|
+
RGS comes with **11+ official plugins** ready to supercharge your app:
|
|
210
|
+
|
|
211
|
+
| Plugin | Purpose | One-Liner |
|
|
212
|
+
|--------|---------|-----------|
|
|
213
|
+
| `undoRedoPlugin` | Time travel through state | `store.undo()` / `store.redo()` |
|
|
214
|
+
| `syncPlugin` | Cross-tab sync (no server) | `store._addPlugin(syncPlugin(...))` |
|
|
215
|
+
| `indexedDBPlugin` | GB-scale storage | `store._addPlugin(indexedDBPlugin(...))` |
|
|
216
|
+
| `cloudSyncPlugin` | Cloud backup & sync | `store.plugins.cloudSync.sync()` |
|
|
217
|
+
| `devToolsPlugin` | Redux DevTools | `store._addPlugin(devToolsPlugin(...))` |
|
|
218
|
+
| `immerPlugin` | Mutable-style updates | `store.setWithProduce('key', fn)` |
|
|
219
|
+
| `snapshotPlugin` | Save/restore checkpoints | `store.takeSnapshot('backup')` |
|
|
220
|
+
| `schemaPlugin` | Runtime validation | `store._addPlugin(schemaPlugin(...))` |
|
|
221
|
+
| `guardPlugin` | Transform on set | `store._addPlugin(guardPlugin(...))` |
|
|
222
|
+
| `analyticsPlugin` | Track changes | `store._addPlugin(analyticsPlugin(...))` |
|
|
223
|
+
| `debugPlugin` | Console access (DEV) | `window.gstate.list()` |
|
|
224
|
+
|
|
225
|
+
### Undo/Redo - Never Lose Work
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
import { undoRedoPlugin } from '@biglogic/rgs'
|
|
229
|
+
|
|
230
|
+
const store = gstate({ text: '' })
|
|
231
|
+
store._addPlugin(undoRedoPlugin({ limit: 50 }))
|
|
232
|
+
|
|
233
|
+
// User makes changes...
|
|
234
|
+
store.set('text', 'Hello World')
|
|
235
|
+
store.set('text', 'Hello Universe')
|
|
236
|
+
|
|
237
|
+
// Oops! Let's go back
|
|
238
|
+
store.undo() // Returns to 'Hello World'
|
|
239
|
+
store.redo() // Returns to 'Hello Universe'
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Cross-Tab Sync - Real-Time Everywhere
|
|
243
|
+
|
|
244
|
+
```tsx
|
|
245
|
+
import { syncPlugin } from '@biglogic/rgs/advanced'
|
|
246
|
+
|
|
247
|
+
const store = gstate({ theme: 'light' })
|
|
248
|
+
store._addPlugin(syncPlugin({ channelName: 'my-app' }))
|
|
249
|
+
|
|
250
|
+
// Change in Tab 1 → Instantly updates Tab 2, Tab 3, etc.
|
|
251
|
+
// ZERO server calls. Pure browser magic.
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Cloud Sync - Your Data, Everywhere
|
|
255
|
+
|
|
256
|
+
```tsx
|
|
257
|
+
import { cloudSyncPlugin, createMongoAdapter } from '@biglogic/rgs/advanced'
|
|
258
|
+
|
|
259
|
+
const adapter = createMongoAdapter(
|
|
260
|
+
'https://data.mongodb-api.com/...',
|
|
261
|
+
'your-api-key'
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
const store = gstate({ todos: [] })
|
|
265
|
+
store._addPlugin(cloudSyncPlugin({
|
|
266
|
+
adapter,
|
|
267
|
+
autoSyncInterval: 30000 // Every 30 seconds
|
|
268
|
+
}))
|
|
269
|
+
|
|
270
|
+
// Manual sync when needed
|
|
271
|
+
await store.plugins.cloudSync.sync()
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## ☁️ Local-First Sync - Offline by Default
|
|
277
|
+
|
|
278
|
+
The **killer feature** that makes RGS unique:
|
|
279
|
+
|
|
280
|
+
```tsx
|
|
281
|
+
import { gstate, useSyncedState } from '@biglogic/rgs'
|
|
282
|
+
|
|
283
|
+
// Create store with automatic offline-first sync
|
|
284
|
+
const store = gstate({
|
|
285
|
+
todos: [],
|
|
286
|
+
user: null
|
|
287
|
+
}, {
|
|
288
|
+
namespace: 'myapp',
|
|
289
|
+
sync: {
|
|
290
|
+
endpoint: 'https://api.example.com/sync',
|
|
291
|
+
authToken: () => localStorage.getItem('auth_token'),
|
|
292
|
+
autoSyncInterval: 30000,
|
|
293
|
+
syncOnReconnect: true,
|
|
294
|
+
strategy: 'last-write-wins'
|
|
295
|
+
}
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
// Works offline. Automatically syncs when online.
|
|
299
|
+
function TodoList() {
|
|
300
|
+
const [todos, setTodos] = useSyncedState('todos')
|
|
301
|
+
|
|
302
|
+
const addTodo = (text) => {
|
|
303
|
+
setTodos([...todos, { id: Date.now(), text }])
|
|
304
|
+
// Synced automatically! ✨
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return <ul>{todos.map(t => <li>{t.text}</li>)}</ul>
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## ⚡ Advanced Superpowers
|
|
314
|
+
|
|
315
|
+
### Computed Values (Derived State)
|
|
316
|
+
|
|
317
|
+
```tsx
|
|
318
|
+
const store = gstate({
|
|
319
|
+
firstName: 'John',
|
|
320
|
+
lastName: 'Doe'
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
// Auto-calculated derived state
|
|
324
|
+
store.compute('fullName', (get) => `${get('firstName')} ${get('lastName')}`)
|
|
325
|
+
|
|
326
|
+
const fullName = store.get('fullName') // "John Doe"
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Error Handling
|
|
330
|
+
|
|
331
|
+
```tsx
|
|
332
|
+
const store = gstate({ data: null }, {
|
|
333
|
+
onError: (error, context) => {
|
|
334
|
+
console.error(`Error in ${context.operation}:`, error.message)
|
|
335
|
+
// Send to Sentry, Datadog, etc.
|
|
336
|
+
}
|
|
337
|
+
})
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Size Limits (Memory Protection)
|
|
341
|
+
|
|
342
|
+
```tsx
|
|
343
|
+
const store = gstate({ data: {} }, {
|
|
344
|
+
maxObjectSize: 5 * 1024 * 1024, // Warn if single value > 5MB
|
|
345
|
+
maxTotalSize: 50 * 1024 * 1024 // Warn if total > 50MB
|
|
346
|
+
})
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## 📦 Build Sizes - Choose Your Weapon
|
|
352
|
+
|
|
353
|
+
### Minimal Version (~0.16 KB)
|
|
354
|
+
For embedded systems, widgets, IoT:
|
|
355
|
+
|
|
356
|
+
```javascript
|
|
357
|
+
import { createStore } from '@biglogic/rgs/core/minimal'
|
|
358
|
+
|
|
359
|
+
const store = createStore({ count: 0 })
|
|
360
|
+
store.get('count') // → 0
|
|
361
|
+
store.set('count', 5) // → true
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Full Version (~32 KB)
|
|
365
|
+
For production React apps with all features:
|
|
366
|
+
|
|
367
|
+
```javascript
|
|
368
|
+
import { gstate, createStore } from '@biglogic/rgs'
|
|
369
|
+
|
|
370
|
+
const useCounter = gstate({ count: 0 })
|
|
371
|
+
const count = useCounter(s => s.count)
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
| Version | Size | Use Case |
|
|
375
|
+
|---------|------|----------|
|
|
376
|
+
| **Minimal** | 0.16 KB | Embedded, IoT, Widgets |
|
|
377
|
+
| **Full** | ~32 KB | React Apps, Enterprise |
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## 🧪 Testing - Rock-Solid Reliability
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
# Run unit tests
|
|
385
|
+
npm run test
|
|
386
|
+
|
|
387
|
+
# Run E2E tests (Playwright)
|
|
388
|
+
npm run test:e2e
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
- ✅ **100+ Unit Tests** (Jest) - Core logic, stores, hooks
|
|
392
|
+
- ✅ **E2E Tests** (Playwright) - Real browser, cross-tab sync
|
|
393
|
+
- ✅ **Concurrency Testing** - Race condition verification
|
|
394
|
+
- ✅ **Security Tests** - AES-256, RBAC, GDPR
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## 🏗️ Architecture
|
|
399
|
+
|
|
400
|
+
```mermaid
|
|
401
|
+
graph TB
|
|
402
|
+
subgraph API
|
|
403
|
+
A[gstate] --> D[IStore]
|
|
404
|
+
B[useStore] --> D
|
|
405
|
+
C[createStore] --> D
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
D --> E[Storage Adapter]
|
|
409
|
+
D --> F[Immer Proxy]
|
|
410
|
+
D --> G[Plugins]
|
|
411
|
+
D --> H[Security]
|
|
412
|
+
D --> I[Async Store]
|
|
413
|
+
|
|
414
|
+
E --> J[local]
|
|
415
|
+
E --> K[session]
|
|
416
|
+
E --> L[memory]
|
|
417
|
+
|
|
418
|
+
G --> M[UndoRedo]
|
|
419
|
+
G --> N[Sync]
|
|
420
|
+
G --> O[Schema]
|
|
421
|
+
G --> P[Analytics]
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### Core Components
|
|
425
|
+
|
|
426
|
+
| Component | Description |
|
|
427
|
+
|-----------|-------------|
|
|
428
|
+
| **gstate()** | Creates store + hook in one line |
|
|
429
|
+
| **useStore()** | React hook for subscribing to state |
|
|
430
|
+
| **createStore()** | Classic store factory |
|
|
431
|
+
| **IStore** | Core interface with get/set/subscribe |
|
|
432
|
+
| **StorageAdapters** | local, session, memory persistence |
|
|
433
|
+
| **Plugins** | Immer, Undo/Redo, Sync, Schema, etc. |
|
|
434
|
+
| **Security** | Encryption, RBAC, GDPR consent |
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## 📚 Documentation
|
|
439
|
+
|
|
440
|
+
- [Getting Started](docs/markdown/getting-started.md)
|
|
441
|
+
- [Plugin SDK](docs/markdown/plugin-sdk.md)
|
|
442
|
+
- [Security Architecture](docs/markdown/security-architecture.md)
|
|
443
|
+
- [Migration Guide](docs/markdown/migration-guide.md)
|
|
444
|
+
- [API Reference](docs/markdown/api.md)
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## 🤝 Contributing
|
|
449
|
+
|
|
450
|
+
Contributions are welcome! Please read our [contributing guidelines](CONTRIBUTING.md) first.
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
# Clone and setup
|
|
454
|
+
git clone https://github.com/BigLogic-ca/rgs.git
|
|
455
|
+
cd rgs
|
|
456
|
+
npm install
|
|
457
|
+
|
|
458
|
+
# Run tests
|
|
459
|
+
npm run test
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
464
|
+
## 📄 License
|
|
465
|
+
|
|
466
|
+
**MIT** © [Dario Passariello](https://github.com/passariello)
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
## 🔥 Built for Those Who Demand **Excellence**
|
|
471
|
+
|
|
472
|
+
[](https://github.com/immerjs/immer)
|
|
473
|
+
[](https://www.typescriptlang.org/)
|
|
474
|
+
[](https://jestjs.io/)
|
|
475
|
+
[](https://playwright.dev/)
|
|
476
|
+
|
|
477
|
+
**Made with ❤️ and a lot of caffè espresso!**
|
|
478
|
+
|
|
479
|
+
[⬆ Back to top](#-argis-rgs---reactive-global-state)
|
package/docs/SUMMARY.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# 🌌 Argis (RGS) - Reactive Global State: The Final Guide
|
|
2
|
+
|
|
3
|
+
Welcome to the definitive documentation for **Reactive Global State (RGS)**. If you are here, you're likely tired of endless boilerplate, complex configurations, and state management tools that seem to require a PhD in rocket science.
|
|
4
|
+
|
|
5
|
+
This documentation is written for everyone: from **easy setup** for those who just want things to work, to **advanced implementation** for those who want to master the engine.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🗺️ Summary
|
|
10
|
+
|
|
11
|
+
- **[The Philosophy: Panzer vs. Bicycle](markdown/philosophy.md)**
|
|
12
|
+
- Reliability and Security as First-Class Citizens.
|
|
13
|
+
- The "Ironclad" Core: Simplicity meets Power.
|
|
14
|
+
|
|
15
|
+
- **[Quick Start: 30-Second Setup](markdown/getting-started.md)**
|
|
16
|
+
- Deploying the RGS Panzer in your React project.
|
|
17
|
+
|
|
18
|
+
- **[The Magnetar Way: One-Liner Power](markdown/the-magnetar-way.md)**
|
|
19
|
+
- Creating stores and hooks simultaneously. Types included.
|
|
20
|
+
|
|
21
|
+
- **[Persistence and Safety](markdown/persistence-and-safety.md)**
|
|
22
|
+
- Never lose user data again (without localStorage headaches).
|
|
23
|
+
- Native immutability with Immer (Stellar Engine).
|
|
24
|
+
|
|
25
|
+
- **[Ecosystem and Plugins](markdown/plugins-and-extensibility.md)**
|
|
26
|
+
- DevTools, Cross-Tab Sync, Analytics, and Typed Plugins.
|
|
27
|
+
|
|
28
|
+
- **[Plugin SDK: Build Your Own Extensions](markdown/plugin-sdk.md)**
|
|
29
|
+
- Create custom plugins with lifecycle hooks.
|
|
30
|
+
- Register methods via `store.plugins`.
|
|
31
|
+
- Full API reference and examples.
|
|
32
|
+
|
|
33
|
+
- **[Case Studies: Real World Strategies](markdown/case-studies.md)**
|
|
34
|
+
- **E-commerce**: Cart isolation and atomic updates.
|
|
35
|
+
- **Dashboards**: Multi-store strategies and complex flows.
|
|
36
|
+
|
|
37
|
+
- **[Architectural Insights (FAQ)](markdown/faq.md)**
|
|
38
|
+
- Honest answers on security, performance, and Proxies.
|
|
39
|
+
|
|
40
|
+
- **[Migration Guide](markdown/migration-guide.md)**
|
|
41
|
+
- Upgrading to latest version (Enterprise Isolation)
|
|
42
|
+
- Upgrading to previous version (`secure` → `encoded`)
|
|
43
|
+
|
|
44
|
+
- **[Security Architecture & Hardening](markdown/security-architecture.md)**
|
|
45
|
+
- Advanced XSS prevention and deep cloning reliability.
|
|
46
|
+
- AES-256-GCM and RBAC.
|
|
47
|
+
|
|
48
|
+
- **[Local-First Sync Engine](markdown/local-first-sync.md)**
|
|
49
|
+
- Offline-by-default with automatic background sync.
|
|
50
|
+
- Conflict resolution strategies (last-write-wins, merge, etc.).
|
|
51
|
+
- `useSyncedState` hook for React components.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
> *"Make things simple, but not simpler than necessary."* – RGS Team
|
package/docs/_config.yml
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
theme: jekyll-theme-modernist
|