@biglogic/rgs 3.0.1 → 3.2.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.
- package/README.md +14 -0
- package/advanced.js +1 -1
- package/index.js +1 -1
- package/package.json +26 -28
- package/rgs-extension.vsix +0 -0
- package/examples/README.md +0 -41
- package/examples/async-data-fetch/UserLoader.d.ts +0 -12
- package/examples/async-data-fetch/UserLoader.ts +0 -30
- package/examples/basic-counter/CounterComponent.d.ts +0 -2
- package/examples/basic-counter/CounterComponent.tsx +0 -22
- package/examples/basic-counter/CounterStore.d.ts +0 -7
- package/examples/basic-counter/CounterStore.ts +0 -25
- package/examples/big-data-indexeddb/BigDataStore.d.ts +0 -10
- package/examples/big-data-indexeddb/BigDataStore.ts +0 -60
- package/examples/global-theme/ThemeManager.d.ts +0 -7
- package/examples/global-theme/ThemeManager.ts +0 -32
- package/examples/hybrid-cloud-sync/HybridStore.d.ts +0 -19
- package/examples/hybrid-cloud-sync/HybridStore.ts +0 -78
- package/examples/persistent-cart/CartStore.d.ts +0 -13
- package/examples/persistent-cart/CartStore.ts +0 -41
- package/examples/rbac-dashboard/DashboardStore.d.ts +0 -47
- package/examples/rbac-dashboard/DashboardStore.ts +0 -46
- package/examples/secure-auth/AuthStore.d.ts +0 -14
- package/examples/secure-auth/AuthStore.ts +0 -36
- package/examples/security-best-practices/SecurityStore.d.ts +0 -22
- package/examples/security-best-practices/SecurityStore.ts +0 -75
- package/examples/stress-tests/StressStore.d.ts +0 -41
- package/examples/stress-tests/StressStore.ts +0 -61
- package/examples/super-easy/EasyStore.d.ts +0 -44
- package/examples/super-easy/EasyStore.ts +0 -61
- package/examples/undo-redo-editor/EditorStore.d.ts +0 -9
- package/examples/undo-redo-editor/EditorStore.ts +0 -28
- package/markdown/SUMMARY.md +0 -59
- package/markdown/api.md +0 -381
- package/markdown/chapters/01-philosophy.md +0 -54
- package/markdown/chapters/02-getting-started.md +0 -68
- package/markdown/chapters/03-the-magnetar-way.md +0 -69
- package/markdown/chapters/04-persistence-and-safety.md +0 -125
- package/markdown/chapters/05-plugin-sdk.md +0 -290
- package/markdown/chapters/05-plugins-and-extensibility.md +0 -190
- package/markdown/chapters/06-case-studies.md +0 -69
- package/markdown/chapters/07-faq.md +0 -53
- package/markdown/chapters/08-migration-guide.md +0 -253
- package/markdown/chapters/09-security-architecture.md +0 -40
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { gstate } from '../../index'
|
|
2
|
-
import { indexedDBPlugin } from '../../plugins/official/indexeddb.plugin'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Big Data Store using IndexedDB
|
|
6
|
-
* RECOMMENDED FOR: Frontend (FE)
|
|
7
|
-
*
|
|
8
|
-
* Demonstrates how to handle massive datasets (GBs) that would exceed
|
|
9
|
-
* the standard 5MB-10MB limit of localStorage.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
export interface BigDataState extends Record<string, unknown> {
|
|
13
|
-
largeCollection: any[]
|
|
14
|
-
metaInfo: { totalItems: number, lastSync: number }
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const initialState: BigDataState = {
|
|
18
|
-
largeCollection: [],
|
|
19
|
-
metaInfo: { totalItems: 0, lastSync: Date.now() }
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// 1. Define the store
|
|
23
|
-
export const useBigData = gstate<BigDataState>(initialState, {
|
|
24
|
-
namespace: 'big-data-vault',
|
|
25
|
-
persist: false // Disable standard persistence to use IndexedDB exclusively
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
// 2. Add the IndexedDB Plugin
|
|
29
|
-
useBigData._addPlugin(indexedDBPlugin({
|
|
30
|
-
dbName: 'UserLargeStorage',
|
|
31
|
-
storeName: 'appStates'
|
|
32
|
-
}))
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Action to simulate adding a large amount of data.
|
|
36
|
-
*/
|
|
37
|
-
export const populateData = (count: number = 1000) => {
|
|
38
|
-
const data: Array<{ id: string, payload: string, timestamp: number }> = []
|
|
39
|
-
for (let i = 0; i < count; i++) {
|
|
40
|
-
data.push({
|
|
41
|
-
id: `item_${i}`,
|
|
42
|
-
payload: 'X'.repeat(1024), // 1KB per item
|
|
43
|
-
timestamp: Date.now()
|
|
44
|
-
})
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
useBigData.transaction(() => {
|
|
48
|
-
useBigData.set('largeCollection', data)
|
|
49
|
-
useBigData.set('metaInfo', { totalItems: count, lastSync: Date.now() })
|
|
50
|
-
})
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Clear the database
|
|
55
|
-
*/
|
|
56
|
-
export const clearBigData = async () => {
|
|
57
|
-
// Access plugin methods registered on the store
|
|
58
|
-
await (useBigData as any).plugins.indexedDB.clear()
|
|
59
|
-
useBigData.set('largeCollection', [])
|
|
60
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export interface ThemeState extends Record<string, unknown> {
|
|
2
|
-
mode: 'light' | 'dark';
|
|
3
|
-
accent: string;
|
|
4
|
-
}
|
|
5
|
-
export declare const useTheme: import("../../advanced").IStore<ThemeState> & (<K extends keyof ThemeState>(key: K) => readonly [ThemeState[K] | undefined, (val: ThemeState[K] | ((draft: ThemeState[K]) => ThemeState[K]), options?: unknown) => boolean]);
|
|
6
|
-
export declare const initTheme: () => import("../../advanced").IStore<ThemeState> & (<K extends keyof ThemeState>(key: K) => readonly [ThemeState[K] | undefined, (val: ThemeState[K] | ((draft: ThemeState[K]) => ThemeState[K]), options?: unknown) => boolean]);
|
|
7
|
-
export declare const toggleTheme: () => void;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { gstate, getStore } from '../../index'
|
|
2
|
-
|
|
3
|
-
// Define the shape of our theme state
|
|
4
|
-
export interface ThemeState extends Record<string, unknown> {
|
|
5
|
-
mode: 'light' | 'dark'
|
|
6
|
-
accent: string
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Global Theme Manager
|
|
11
|
-
* RECOMMENDED FOR: Frontend (FE)
|
|
12
|
-
*
|
|
13
|
-
* Demonstrates global state using a dedicated store instance.
|
|
14
|
-
*/
|
|
15
|
-
export const useTheme = gstate<ThemeState>({
|
|
16
|
-
mode: 'light',
|
|
17
|
-
accent: '#007bff'
|
|
18
|
-
}, {
|
|
19
|
-
namespace: 'theme-store',
|
|
20
|
-
persist: true
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Helper to initialize the theme (useful for SSR or specific init logic)
|
|
25
|
-
*/
|
|
26
|
-
export const initTheme = () => useTheme
|
|
27
|
-
|
|
28
|
-
// Reusable action to toggle theme
|
|
29
|
-
export const toggleTheme = () => {
|
|
30
|
-
const current = useTheme.get('mode')
|
|
31
|
-
useTheme.set('mode', current === 'light' ? 'dark' : 'light')
|
|
32
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export interface AppState extends Record<string, unknown> {
|
|
2
|
-
userProfile: {
|
|
3
|
-
name: string;
|
|
4
|
-
preferences: any;
|
|
5
|
-
};
|
|
6
|
-
projects: Array<{
|
|
7
|
-
id: string;
|
|
8
|
-
content: string;
|
|
9
|
-
}>;
|
|
10
|
-
}
|
|
11
|
-
export declare const useHybridStore: import("../../advanced").IStore<AppState> & (<K extends keyof AppState>(key: K) => readonly [AppState[K] | undefined, (val: AppState[K] | ((draft: AppState[K]) => AppState[K]), options?: unknown) => boolean]);
|
|
12
|
-
export declare const syncNow: () => Promise<void>;
|
|
13
|
-
export declare const getSyncReport: () => {
|
|
14
|
-
lastSync: string;
|
|
15
|
-
count: any;
|
|
16
|
-
errors: any;
|
|
17
|
-
averageKeysPerSync: number;
|
|
18
|
-
};
|
|
19
|
-
export declare const updateName: (newName: string) => void;
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { gstate } from '../../index'
|
|
2
|
-
import { indexedDBPlugin } from '../../plugins/official/indexeddb.plugin'
|
|
3
|
-
import { cloudSyncPlugin, createMongoAdapter } from '../../plugins/official/cloud-sync.plugin'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Hybrid Cloud Sync Store
|
|
7
|
-
* RECOMMENDED FOR: Frontend (FE) with Cloud Backup
|
|
8
|
-
*
|
|
9
|
-
* Demonstrates a multi-layer storage strategy:
|
|
10
|
-
* 1. Cache: Memory (fast)
|
|
11
|
-
* 2. Persistent Local: IndexedDB (large capacity)
|
|
12
|
-
* 3. remote: MongoDB Cloud (On-demand/Scheduled backup)
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
export interface AppState extends Record<string, unknown> {
|
|
16
|
-
userProfile: { name: string; preferences: any }
|
|
17
|
-
projects: Array<{ id: string; content: string }>
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const initialState: AppState = {
|
|
21
|
-
userProfile: { name: 'Dario', preferences: { theme: 'dark' } },
|
|
22
|
-
projects: []
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// 1. Initialize the store
|
|
26
|
-
export const useHybridStore = gstate<AppState>(initialState, {
|
|
27
|
-
namespace: 'hybrid-app-vault',
|
|
28
|
-
persist: false // We use plugins for persistence
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
// 2. Add IndexedDB for local persistence (up to GBs)
|
|
32
|
-
useHybridStore._addPlugin(indexedDBPlugin({
|
|
33
|
-
dbName: 'LocalCacheDB'
|
|
34
|
-
}))
|
|
35
|
-
|
|
36
|
-
// 3. Add Cloud Sync for remote backup
|
|
37
|
-
// Configured to automatically sync every 5 minutes (300000ms)
|
|
38
|
-
useHybridStore._addPlugin(cloudSyncPlugin({
|
|
39
|
-
adapter: createMongoAdapter('https://api.mongodb.com/v1', 'YOUR_SECRET_API_KEY'),
|
|
40
|
-
autoSyncInterval: 300000,
|
|
41
|
-
onSync: (stats) => {
|
|
42
|
-
console.info(`[CloudSync] Success! Keys: ${stats.totalKeysSynced}, Total Bytes: ${stats.totalBytesSynced}`)
|
|
43
|
-
}
|
|
44
|
-
}))
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Manual Trigger for Cloud Sync
|
|
48
|
-
*/
|
|
49
|
-
export const syncNow = async () => {
|
|
50
|
-
const result = await (useHybridStore as any).plugins.cloudSync.sync()
|
|
51
|
-
if (result.status === 'success') {
|
|
52
|
-
alert(`Sync completed! ${result.stats.totalKeysSynced} items pushed to cloud.`)
|
|
53
|
-
} else if (result.status === 'no-change') {
|
|
54
|
-
console.log('No new changes to sync.')
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Get synchronization diagnostics
|
|
60
|
-
*/
|
|
61
|
-
export const getSyncReport = () => {
|
|
62
|
-
const stats = (useHybridStore as any).plugins.cloudSync.getStats()
|
|
63
|
-
return {
|
|
64
|
-
lastSync: stats.lastSyncTimestamp ? new Date(stats.lastSyncTimestamp).toLocaleString() : 'Never',
|
|
65
|
-
count: stats.syncCount,
|
|
66
|
-
errors: stats.errors,
|
|
67
|
-
averageKeysPerSync: stats.syncCount > 0 ? stats.totalKeysSynced / stats.syncCount : 0
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Action to update profile
|
|
73
|
-
*/
|
|
74
|
-
export const updateName = (newName: string) => {
|
|
75
|
-
useHybridStore.set('userProfile', (draft) => {
|
|
76
|
-
draft.name = newName
|
|
77
|
-
})
|
|
78
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export interface CartItem {
|
|
2
|
-
id: string;
|
|
3
|
-
name: string;
|
|
4
|
-
price: number;
|
|
5
|
-
quantity: number;
|
|
6
|
-
}
|
|
7
|
-
export interface CartState extends Record<string, unknown> {
|
|
8
|
-
items: CartItem[];
|
|
9
|
-
coupon: string | null;
|
|
10
|
-
}
|
|
11
|
-
export declare const useCart: import("../../advanced").IStore<CartState> & (<K extends keyof CartState>(key: K) => readonly [CartState[K] | undefined, (val: CartState[K] | ((draft: CartState[K]) => CartState[K]), options?: unknown) => boolean]);
|
|
12
|
-
export declare const addToCart: (product: Omit<CartItem, "quantity">) => void;
|
|
13
|
-
export declare const getCartTotal: () => number;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { gstate } from '../../index'
|
|
2
|
-
|
|
3
|
-
export interface CartItem {
|
|
4
|
-
id: string
|
|
5
|
-
name: string
|
|
6
|
-
price: number
|
|
7
|
-
quantity: number
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface CartState extends Record<string, unknown> {
|
|
11
|
-
items: CartItem[]
|
|
12
|
-
coupon: string | null
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Persistent Cart Store
|
|
17
|
-
* RECOMMENDED FOR: Frontend (FE)
|
|
18
|
-
*/
|
|
19
|
-
export const useCart = gstate<CartState>({
|
|
20
|
-
items: [],
|
|
21
|
-
coupon: null
|
|
22
|
-
}, {
|
|
23
|
-
namespace: 'shopping-cart',
|
|
24
|
-
persist: true
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
export const addToCart = (product: Omit<CartItem, 'quantity'>) => {
|
|
28
|
-
useCart.set('items', (items) => {
|
|
29
|
-
const existing = items.find(item => item.id === product.id)
|
|
30
|
-
if (existing) {
|
|
31
|
-
existing.quantity++
|
|
32
|
-
} else {
|
|
33
|
-
items.push({ ...product, quantity: 1 })
|
|
34
|
-
}
|
|
35
|
-
})
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export const getCartTotal = () => useCart.compute('totalPrice', (get) => {
|
|
39
|
-
const items = get<CartItem[]>('items') || []
|
|
40
|
-
return items.reduce((total, item) => total + (item.price * item.quantity), 0)
|
|
41
|
-
})
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
export declare const useDashboard: import("../../advanced").IStore<{
|
|
2
|
-
stats: {
|
|
3
|
-
visitors: number;
|
|
4
|
-
revenue: number;
|
|
5
|
-
};
|
|
6
|
-
settings: {
|
|
7
|
-
allowPublicSignup: boolean;
|
|
8
|
-
};
|
|
9
|
-
logs: string[];
|
|
10
|
-
}> & (<K extends "stats" | "settings" | "logs">(key: K) => readonly [{
|
|
11
|
-
stats: {
|
|
12
|
-
visitors: number;
|
|
13
|
-
revenue: number;
|
|
14
|
-
};
|
|
15
|
-
settings: {
|
|
16
|
-
allowPublicSignup: boolean;
|
|
17
|
-
};
|
|
18
|
-
logs: string[];
|
|
19
|
-
}[K] | undefined, (val: {
|
|
20
|
-
stats: {
|
|
21
|
-
visitors: number;
|
|
22
|
-
revenue: number;
|
|
23
|
-
};
|
|
24
|
-
settings: {
|
|
25
|
-
allowPublicSignup: boolean;
|
|
26
|
-
};
|
|
27
|
-
logs: string[];
|
|
28
|
-
}[K] | ((draft: {
|
|
29
|
-
stats: {
|
|
30
|
-
visitors: number;
|
|
31
|
-
revenue: number;
|
|
32
|
-
};
|
|
33
|
-
settings: {
|
|
34
|
-
allowPublicSignup: boolean;
|
|
35
|
-
};
|
|
36
|
-
logs: string[];
|
|
37
|
-
}[K]) => {
|
|
38
|
-
stats: {
|
|
39
|
-
visitors: number;
|
|
40
|
-
revenue: number;
|
|
41
|
-
};
|
|
42
|
-
settings: {
|
|
43
|
-
allowPublicSignup: boolean;
|
|
44
|
-
};
|
|
45
|
-
logs: string[];
|
|
46
|
-
}[K]), options?: unknown) => boolean]);
|
|
47
|
-
export declare const addLog: (msg: string) => boolean;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { gstate } from '../../index'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* RBAC Dashboard Store
|
|
5
|
-
* RECOMMENDED FOR: Backend (BE) / Admin Frontend (FE)
|
|
6
|
-
*
|
|
7
|
-
* Demonstrates Role-Based Access Control.
|
|
8
|
-
*/
|
|
9
|
-
export const useDashboard = gstate({
|
|
10
|
-
stats: { visitors: 100, revenue: 5000 },
|
|
11
|
-
settings: { allowPublicSignup: true },
|
|
12
|
-
logs: [] as string[]
|
|
13
|
-
}, {
|
|
14
|
-
userId: 'manager-101',
|
|
15
|
-
accessRules: [
|
|
16
|
-
{
|
|
17
|
-
// Allow 'manager-101' read access to stats
|
|
18
|
-
pattern: (key, userId) => key === 'stats' && userId === 'manager-101',
|
|
19
|
-
permissions: ['read']
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
// Allow 'manager-101' full access to settings
|
|
23
|
-
pattern: (key, userId) => key === 'settings' && userId === 'manager-101',
|
|
24
|
-
permissions: ['read', 'write']
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
// ONLY 'admin-user' can access logs
|
|
28
|
-
pattern: (key, userId) => key === 'logs' && userId === 'admin-user',
|
|
29
|
-
permissions: ['admin']
|
|
30
|
-
}
|
|
31
|
-
]
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Attempt to add a log entry.
|
|
36
|
-
* Will fail if the current store userId is not 'admin-user'.
|
|
37
|
-
*/
|
|
38
|
-
export const addLog = (msg: string) => {
|
|
39
|
-
const success = useDashboard.set('logs', (draft: string[]) => {
|
|
40
|
-
draft.push(msg)
|
|
41
|
-
})
|
|
42
|
-
if (!success) {
|
|
43
|
-
console.warn(`[Security] Access Denied for user ${useDashboard.userId}: Insufficient permissions for 'logs'`)
|
|
44
|
-
}
|
|
45
|
-
return success
|
|
46
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export interface AuthState extends Record<string, unknown> {
|
|
2
|
-
user: {
|
|
3
|
-
id: string;
|
|
4
|
-
email: string;
|
|
5
|
-
} | null;
|
|
6
|
-
token: string | null;
|
|
7
|
-
isAuthenticated: boolean;
|
|
8
|
-
}
|
|
9
|
-
export declare const useAuth: import("../../advanced").IStore<AuthState> & (<K extends keyof AuthState>(key: K) => readonly [AuthState[K] | undefined, (val: AuthState[K] | ((draft: AuthState[K]) => AuthState[K]), options?: unknown) => boolean]);
|
|
10
|
-
export declare const login: (user: {
|
|
11
|
-
id: string;
|
|
12
|
-
email: string;
|
|
13
|
-
}, token: string) => void;
|
|
14
|
-
export declare const logout: () => void;
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { gstate } from '../../index'
|
|
2
|
-
|
|
3
|
-
export interface AuthState extends Record<string, unknown> {
|
|
4
|
-
user: { id: string, email: string } | null
|
|
5
|
-
token: string | null
|
|
6
|
-
isAuthenticated: boolean
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Secure Authentication Store
|
|
11
|
-
* RECOMMENDED FOR: Frontend (FE) / Backend (BE)
|
|
12
|
-
*
|
|
13
|
-
* Demonstrates the 'encoded' option for basic obfuscation in localStorage.
|
|
14
|
-
* Notice: For industrial-grade security, use encryptionKey in config.
|
|
15
|
-
*/
|
|
16
|
-
export const useAuth = gstate<AuthState>({
|
|
17
|
-
user: null,
|
|
18
|
-
token: null,
|
|
19
|
-
isAuthenticated: false
|
|
20
|
-
}, {
|
|
21
|
-
namespace: 'secure-auth',
|
|
22
|
-
encoded: true, // Base64 encodes data in localStorage
|
|
23
|
-
persist: true
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
export const login = (user: { id: string, email: string }, token: string) => {
|
|
27
|
-
useAuth.transaction(() => {
|
|
28
|
-
useAuth.set('user', user)
|
|
29
|
-
useAuth.set('token', token)
|
|
30
|
-
useAuth.set('isAuthenticated', true)
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export const logout = () => {
|
|
35
|
-
useAuth.deleteAll() // Clears all state and storage for this namespace
|
|
36
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export interface VaultState extends Record<string, unknown> {
|
|
2
|
-
encryptedData: string | null;
|
|
3
|
-
}
|
|
4
|
-
export declare const initSecureVault: () => Promise<IStore<VaultState> & (<K extends keyof VaultState>(key: K) => readonly [VaultState[K] | undefined, (val: VaultState[K] | ((draft: VaultState[K]) => VaultState[K]), options?: unknown) => boolean])>;
|
|
5
|
-
export declare const useProfileStore: IStore<{
|
|
6
|
-
bio: string;
|
|
7
|
-
displayName: string;
|
|
8
|
-
}> & (<K extends "bio" | "displayName">(key: K) => readonly [{
|
|
9
|
-
bio: string;
|
|
10
|
-
displayName: string;
|
|
11
|
-
}[K] | undefined, (val: {
|
|
12
|
-
bio: string;
|
|
13
|
-
displayName: string;
|
|
14
|
-
}[K] | ((draft: {
|
|
15
|
-
bio: string;
|
|
16
|
-
displayName: string;
|
|
17
|
-
}[K]) => {
|
|
18
|
-
bio: string;
|
|
19
|
-
displayName: string;
|
|
20
|
-
}[K]), options?: unknown) => boolean]);
|
|
21
|
-
import type { IStore } from '../../index';
|
|
22
|
-
export declare const purgeUserData: (store: IStore<Record<string, unknown>>, userId: string) => void;
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { gstate, setAuditLogger, generateEncryptionKey } from '../../index'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* SECURITY BEST PRACTICES EXAMPLE
|
|
5
|
-
*
|
|
6
|
-
* RECOMMENDED FOR: Frontend (FE) and Backend (BE/Node)
|
|
7
|
-
*
|
|
8
|
-
* DESIGN PRINCIPLE:
|
|
9
|
-
* - NEVER hardcode sensitive data (PII, Credit Cards, Keys) in source code.
|
|
10
|
-
* - Use environment variables or secure user input at runtime.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
export interface VaultState extends Record<string, unknown> {
|
|
14
|
-
encryptedData: string | null
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* 1. AES-256-GCM Encryption (Enterprise Grade)
|
|
19
|
-
* This store demonstrates how to handle sensitive information securely.
|
|
20
|
-
*/
|
|
21
|
-
export const initSecureVault = async () => {
|
|
22
|
-
// At runtime, you would typically fetch the key from a secure vault or env
|
|
23
|
-
const masterKey = await generateEncryptionKey()
|
|
24
|
-
|
|
25
|
-
return gstate<VaultState>({
|
|
26
|
-
encryptedData: null
|
|
27
|
-
}, {
|
|
28
|
-
namespace: 'secure-vault',
|
|
29
|
-
persist: true,
|
|
30
|
-
encryptionKey: masterKey, // Real AES-256-GCM encryption
|
|
31
|
-
encoded: true
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* 2. Field-Level Sanitization (XSS Defense)
|
|
37
|
-
* RECOMMENDED FOR: Frontend (FE)
|
|
38
|
-
* Automatically strips <script> and other XSS vectors from input values.
|
|
39
|
-
*/
|
|
40
|
-
export const useProfileStore = gstate({
|
|
41
|
-
bio: '',
|
|
42
|
-
displayName: ''
|
|
43
|
-
}, {
|
|
44
|
-
validateInput: true // Enables automatic sanitizeValue() on all .set() calls
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* 3. Audit Logging Integration
|
|
49
|
-
* RECOMMENDED FOR: Backend (BE) / Regulatory Compliance
|
|
50
|
-
* Tracks every 'set' or 'delete' operation for accountability.
|
|
51
|
-
*/
|
|
52
|
-
const auditBuffer: any[] = []
|
|
53
|
-
setAuditLogger((entry) => {
|
|
54
|
-
// In a real BE scenario, send this to a logging service (Datadog, Elastic, etc.)
|
|
55
|
-
auditBuffer.push({
|
|
56
|
-
...entry,
|
|
57
|
-
timestamp: new Date().toISOString()
|
|
58
|
-
})
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
import type { IStore } from '../../index'
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 4. GDPR "Right to be Forgotten"
|
|
65
|
-
* RECOMMENDED FOR: Compliance
|
|
66
|
-
*/
|
|
67
|
-
export const purgeUserData = (store: IStore<Record<string, unknown>>, userId: string) => {
|
|
68
|
-
// Wipe state and storage
|
|
69
|
-
store.deleteAll()
|
|
70
|
-
|
|
71
|
-
// Enterprise: Wipe GDPR consents and audit traces
|
|
72
|
-
store.deleteUserData(userId)
|
|
73
|
-
|
|
74
|
-
console.info(`[Security] Data purge requested for ${userId}`)
|
|
75
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
export declare const useRapidStore: import("../../advanced").IStore<{
|
|
2
|
-
updates: number;
|
|
3
|
-
lastBatchTime: number;
|
|
4
|
-
}> & (<K extends "updates" | "lastBatchTime">(key: K) => readonly [{
|
|
5
|
-
updates: number;
|
|
6
|
-
lastBatchTime: number;
|
|
7
|
-
}[K] | undefined, (val: {
|
|
8
|
-
updates: number;
|
|
9
|
-
lastBatchTime: number;
|
|
10
|
-
}[K] | ((draft: {
|
|
11
|
-
updates: number;
|
|
12
|
-
lastBatchTime: number;
|
|
13
|
-
}[K]) => {
|
|
14
|
-
updates: number;
|
|
15
|
-
lastBatchTime: number;
|
|
16
|
-
}[K]), options?: unknown) => boolean]);
|
|
17
|
-
export declare const runRapidFire: (iterations?: number) => number;
|
|
18
|
-
export declare const usePayloadStore: import("../../advanced").IStore<{
|
|
19
|
-
data: any;
|
|
20
|
-
}> & (<K extends "data">(key: K) => readonly [{
|
|
21
|
-
data: any;
|
|
22
|
-
}[K] | undefined, (val: {
|
|
23
|
-
data: any;
|
|
24
|
-
}[K] | ((draft: {
|
|
25
|
-
data: any;
|
|
26
|
-
}[K]) => {
|
|
27
|
-
data: any;
|
|
28
|
-
}[K]), options?: unknown) => boolean]);
|
|
29
|
-
export declare const generateBigPayload: (keys?: number) => number;
|
|
30
|
-
export declare const useChainStore: import("../../advanced").IStore<{
|
|
31
|
-
base: number;
|
|
32
|
-
}> & (<K extends "base">(key: K) => readonly [{
|
|
33
|
-
base: number;
|
|
34
|
-
}[K] | undefined, (val: {
|
|
35
|
-
base: number;
|
|
36
|
-
}[K] | ((draft: {
|
|
37
|
-
base: number;
|
|
38
|
-
}[K]) => {
|
|
39
|
-
base: number;
|
|
40
|
-
}[K]), options?: unknown) => boolean]);
|
|
41
|
-
export declare const setupChain: () => void;
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { gstate } from '../../index'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Rapid Fire Stress Test
|
|
5
|
-
* Tests RGS ability to handle massive bursts of updates.
|
|
6
|
-
*/
|
|
7
|
-
export const useRapidStore = gstate({
|
|
8
|
-
updates: 0,
|
|
9
|
-
lastBatchTime: 0
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
export const runRapidFire = (iterations: number = 1000) => {
|
|
13
|
-
const start = performance.now()
|
|
14
|
-
for (let i = 0; i < iterations; i++) {
|
|
15
|
-
useRapidStore.set('updates', i + 1)
|
|
16
|
-
}
|
|
17
|
-
const end = performance.now()
|
|
18
|
-
useRapidStore.set('lastBatchTime', end - start)
|
|
19
|
-
return end - start
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Big Payload Stress Test
|
|
24
|
-
* Tests memory handling and cloning performance with large objects.
|
|
25
|
-
*/
|
|
26
|
-
export const usePayloadStore = gstate({
|
|
27
|
-
data: {} as any
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
export const generateBigPayload = (keys: number = 5000) => {
|
|
31
|
-
const bigObj: Record<string, any> = {}
|
|
32
|
-
for (let i = 0; i < keys; i++) {
|
|
33
|
-
bigObj[`key_${i}`] = {
|
|
34
|
-
id: i,
|
|
35
|
-
value: Math.random(),
|
|
36
|
-
meta: { timestamp: Date.now(), tags: ['test', 'stress', 'payload'] }
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const start = performance.now()
|
|
41
|
-
usePayloadStore.set('data', bigObj)
|
|
42
|
-
const end = performance.now()
|
|
43
|
-
return end - start
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Computed Chain Stress Test
|
|
48
|
-
* Tests dependency tracking and recursive updates.
|
|
49
|
-
*/
|
|
50
|
-
export const useChainStore = gstate({
|
|
51
|
-
base: 0
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
// Create a chain of 5 computed values
|
|
55
|
-
export const setupChain = () => {
|
|
56
|
-
useChainStore.compute('level1', (get) => (get<number>('base') || 0) + 1)
|
|
57
|
-
useChainStore.compute('level2', (get) => (get<number>('level1') || 0) + 1)
|
|
58
|
-
useChainStore.compute('level3', (get) => (get<number>('level2') || 0) + 1)
|
|
59
|
-
useChainStore.compute('level4', (get) => (get<number>('level3') || 0) + 1)
|
|
60
|
-
useChainStore.compute('level5', (get) => (get<number>('level4') || 0) + 1)
|
|
61
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
export declare const useEasyStore: import("../../advanced").IStore<{
|
|
2
|
-
user: {
|
|
3
|
-
name: string;
|
|
4
|
-
role: string;
|
|
5
|
-
};
|
|
6
|
-
theme: string;
|
|
7
|
-
notifications: number;
|
|
8
|
-
tempData: string;
|
|
9
|
-
}> & (<K extends "user" | "theme" | "notifications" | "tempData">(key: K) => readonly [{
|
|
10
|
-
user: {
|
|
11
|
-
name: string;
|
|
12
|
-
role: string;
|
|
13
|
-
};
|
|
14
|
-
theme: string;
|
|
15
|
-
notifications: number;
|
|
16
|
-
tempData: string;
|
|
17
|
-
}[K] | undefined, (val: {
|
|
18
|
-
user: {
|
|
19
|
-
name: string;
|
|
20
|
-
role: string;
|
|
21
|
-
};
|
|
22
|
-
theme: string;
|
|
23
|
-
notifications: number;
|
|
24
|
-
tempData: string;
|
|
25
|
-
}[K] | ((draft: {
|
|
26
|
-
user: {
|
|
27
|
-
name: string;
|
|
28
|
-
role: string;
|
|
29
|
-
};
|
|
30
|
-
theme: string;
|
|
31
|
-
notifications: number;
|
|
32
|
-
tempData: string;
|
|
33
|
-
}[K]) => {
|
|
34
|
-
user: {
|
|
35
|
-
name: string;
|
|
36
|
-
role: string;
|
|
37
|
-
};
|
|
38
|
-
theme: string;
|
|
39
|
-
notifications: number;
|
|
40
|
-
tempData: string;
|
|
41
|
-
}[K]), options?: unknown) => boolean]);
|
|
42
|
-
export declare const updateSettings: () => void;
|
|
43
|
-
export declare const checkState: () => void;
|
|
44
|
-
export declare const clearTempData: () => boolean;
|