@biglogic/rgs 2.9.3 → 3.0.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.
Files changed (49) hide show
  1. package/README.md +29 -8
  2. package/SECURITY.md +10 -0
  3. package/advanced.js +1 -1
  4. package/core/types.d.ts +22 -1
  5. package/core/utils.d.ts +2 -0
  6. package/examples/README.md +41 -0
  7. package/examples/async-data-fetch/UserLoader.d.ts +12 -0
  8. package/examples/async-data-fetch/UserLoader.ts +30 -0
  9. package/examples/basic-counter/CounterComponent.d.ts +2 -0
  10. package/examples/basic-counter/CounterComponent.tsx +22 -0
  11. package/examples/basic-counter/CounterStore.d.ts +7 -0
  12. package/examples/basic-counter/CounterStore.ts +25 -0
  13. package/examples/big-data-indexeddb/BigDataStore.d.ts +10 -0
  14. package/examples/big-data-indexeddb/BigDataStore.ts +60 -0
  15. package/examples/global-theme/ThemeManager.d.ts +7 -0
  16. package/examples/global-theme/ThemeManager.ts +32 -0
  17. package/examples/hybrid-cloud-sync/HybridStore.d.ts +19 -0
  18. package/examples/hybrid-cloud-sync/HybridStore.ts +78 -0
  19. package/examples/persistent-cart/CartStore.d.ts +13 -0
  20. package/examples/persistent-cart/CartStore.ts +41 -0
  21. package/examples/rbac-dashboard/DashboardStore.d.ts +47 -0
  22. package/examples/rbac-dashboard/DashboardStore.ts +46 -0
  23. package/examples/secure-auth/AuthStore.d.ts +14 -0
  24. package/examples/secure-auth/AuthStore.ts +36 -0
  25. package/examples/security-best-practices/SecurityStore.d.ts +22 -0
  26. package/examples/security-best-practices/SecurityStore.ts +75 -0
  27. package/examples/stress-tests/StressStore.d.ts +41 -0
  28. package/examples/stress-tests/StressStore.ts +61 -0
  29. package/examples/super-easy/EasyStore.d.ts +44 -0
  30. package/examples/super-easy/EasyStore.ts +61 -0
  31. package/examples/undo-redo-editor/EditorStore.d.ts +9 -0
  32. package/examples/undo-redo-editor/EditorStore.ts +28 -0
  33. package/index.d.ts +3 -2
  34. package/index.js +1 -1
  35. package/markdown/SUMMARY.md +4 -0
  36. package/markdown/api.md +40 -1
  37. package/markdown/chapters/03-the-magnetar-way.md +10 -3
  38. package/markdown/chapters/04-persistence-and-safety.md +46 -5
  39. package/markdown/chapters/05-plugins-and-extensibility.md +24 -8
  40. package/markdown/chapters/06-case-studies.md +69 -69
  41. package/markdown/chapters/08-migration-guide.md +48 -1
  42. package/markdown/chapters/09-security-architecture.md +40 -0
  43. package/package.json +84 -79
  44. package/plugins/index.d.ts +4 -2
  45. package/plugins/official/cloud-sync.plugin.d.ts +22 -0
  46. package/plugins/official/immer.plugin.d.ts +1 -1
  47. package/plugins/official/indexeddb.plugin.d.ts +7 -0
  48. package/plugins/official/undo-redo.plugin.d.ts +2 -2
  49. package/rgs-highlighter-2.9.5.vsix +0 -0
@@ -172,6 +172,53 @@ store.recordConsent('user123', 'marketing', true)
172
172
 
173
173
  ---
174
174
 
175
+ ## v2.9.5: The Architecture & Safety Update (2026-02-16)
176
+
177
+ This release focuses on improving developer ergonomics, security visibility, and complex dependency handling.
178
+
179
+ ### 1. Nested Computed Dependencies
180
+ **NEW:** Computed values can now re-trigger based on other computed values.
181
+
182
+ ```typescript
183
+ store.compute('tax', (get) => (get<number>('subtotal') || 0) * 0.2)
184
+ store.compute('total', (get) => (get<number>('subtotal') || 0) + (get<number>('tax') || 0))
185
+ ```
186
+
187
+ ### 2. Direct Store Access: `getStore()`
188
+ **NEW:** A top-level utility to retrieve the default store without React hooks.
189
+
190
+ ```typescript
191
+ import { getStore } from '@biglogic/rgs'
192
+
193
+ export const toggleTheme = () => {
194
+ const store = getStore()
195
+ if (store) store.set('mode', 'dark')
196
+ }
197
+ ```
198
+
199
+ ### 3. Exposed Metadata: `namespace` and `userId`
200
+ **NEW:** Store instances now expose their identifying properties as read-only getters.
201
+
202
+ ```typescript
203
+ const store = createStore({ namespace: 'auth-vault', userId: 'user-001' })
204
+ console.log(store.namespace) // 'auth-vault'
205
+ console.log(store.userId) // 'user-001'
206
+ ```
207
+
208
+ ### 4. High-Volume & Hybrid Sync (Plugins)
209
+ **NEW:** Support for GB-scale storage and Remote Cloud Backups.
210
+
211
+ - **IndexedDB Plugin**: Replaces localStorage for massive browser datasets.
212
+ - **Cloud Sync Plugin**: Differential synchronization to MongoDB, Firebase, or any SQL backend.
213
+
214
+ ```typescript
215
+ // Example: Manual Cloud Sync
216
+ const result = await store.plugins.cloudSync.sync()
217
+ console.log('Stats:', store.plugins.cloudSync.getStats())
218
+ ```
219
+
220
+ ---
221
+
175
222
  ## Breaking Changes
176
223
 
177
224
  ### 🔒 Security Isolation
@@ -203,4 +250,4 @@ If you relied on `addAccessRule()` from the global export to affect a `createSto
203
250
 
204
251
  ---
205
252
 
206
- ## Last updated: 2026-02-15
253
+ ## Last updated: 2026-02-16
@@ -0,0 +1,40 @@
1
+ # Security Architecture & Hardening
2
+
3
+ ## Overview
4
+ React Globo 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
+
24
+ ## 4. RBAC (Role-Based Access Control)
25
+ RGS supports fine-grained access rules:
26
+ - **Fail-Closed Design**: Access is denied by default if any rules are defined.
27
+ - **Regex Caching**: Store instances cache compiled regular expressions for ultra-fast permission checks.
28
+
29
+ ## 5. Security Best Practices
30
+ For real-world implementations, refer to the `examples/security-best-practices` directory, which covers:
31
+ - **Encryption Key Management**: Using `generateEncryptionKey()` for secure key generation.
32
+ - **Audit Logging**: Tracking all store modifications for compliance.
33
+ - **GDPR Compliance**: Managing user consent and data export/deletion.
34
+
35
+ ## Summary of 2.9.5 Enhancements
36
+ - Robust regex patterns for `sanitizeValue`.
37
+ - Recursive sanitization for plain objects.
38
+ - `Map` and `Set` support in `deepClone`.
39
+ - **Exposed Metadata**: Store instances now expose read-only `namespace` and `userId`.
40
+ - **Direct Store Access**: Added `getStore()` utility for non-React contexts.
package/package.json CHANGED
@@ -1,79 +1,84 @@
1
- {
2
- "name": "@biglogic/rgs",
3
- "version": "2.9.3",
4
- "description": "Argis (RGS) - React Globo State: A react state everywhere made easy",
5
- "deprecated": false,
6
- "preferGlobal": true,
7
- "type": "module",
8
- "keywords": [
9
- "rgs",
10
- "gstate",
11
- "state-management",
12
- "react",
13
- "enterprise",
14
- "hooks",
15
- "global-state",
16
- "immer",
17
- "biglogic",
18
- "persistence",
19
- "react-globo-state",
20
- "argis"
21
- ],
22
- "license": "MIT",
23
- "author": "Dario Passariello",
24
- "contributors": [
25
- {
26
- "name": "Dario Passariello",
27
- "email": "dariopassariello@gmail.com",
28
- "url": "https://dario.passariello.ca/"
29
- },
30
- {
31
- "name": "Valeria Cala Scaglitta",
32
- "email": "valeriacalascaglitta@gmail.com"
33
- }
34
- ],
35
- "main": "./index.js",
36
- "types": "./index.d.ts",
37
- "exports": {
38
- ".": "./index.js"
39
- },
40
- "scripts": {
41
- "build": "tsc --emitDeclarationOnly --outDir dist && node ./esbuild.config.mjs",
42
- "npm: pack": "npm run build && cd dist && npm pack",
43
- "npm: publish": "npm run build && cd dist && npm publish --access=public"
44
- },
45
- "dependencies": {
46
- "immer": "^11.1.4"
47
- },
48
- "peerDependencies": {
49
- "react": ">=16.8.0",
50
- "react-dom": ">=16.8.0"
51
- },
52
- "devDependencies": {
53
- "@eslint/js": "10.0.1",
54
- "@playwright/test": "1.58.2",
55
- "@testing-library/dom": "10.4.1",
56
- "@testing-library/jest-dom": "6.9.1",
57
- "@testing-library/react": "16.3.2",
58
- "@types/jest": "30.0.0",
59
- "@types/node": "25.2.3",
60
- "@types/react": "19.2.14",
61
- "@types/react-dom": "19.2.3",
62
- "@typescript-eslint/eslint-plugin": "^8.56.0",
63
- "@typescript-eslint/parser": "^8.56.0",
64
- "dphelper": "2.6.3",
65
- "esbuild": "0.27.3",
66
- "esbuild-plugin-copy": "2.1.1",
67
- "eslint": "^10.0.0",
68
- "eslint-plugin-react": "7.37.5",
69
- "eslint-plugin-react-hooks": "7.0.1",
70
- "jest": "30.2.0",
71
- "jest-environment-jsdom": "30.2.0",
72
- "react": "19.2.4",
73
- "react-dom": "19.2.4",
74
- "ts-jest": "29.4.6",
75
- "tslib": "^2.8.1",
76
- "typescript": "^5.9.3",
77
- "typescript-eslint": "8.56.0"
78
- }
79
- }
1
+ {
2
+ "name": "@biglogic/rgs",
3
+ "version": "3.0.0",
4
+ "description": "Argis (RGS) - React Globo State: A react state everywhere made easy",
5
+ "type": "module",
6
+ "keywords": [
7
+ "rgs",
8
+ "gstate",
9
+ "state-management",
10
+ "react",
11
+ "enterprise",
12
+ "hooks",
13
+ "global-state",
14
+ "immer",
15
+ "biglogic",
16
+ "persistence",
17
+ "react-globo-state",
18
+ "argis"
19
+ ],
20
+ "homepage": "https://https://github.com/BigLogic-ca/rgs",
21
+ "bugs": {
22
+ "url": "https://github.com/BigLogic-ca/rgs/issues"
23
+ },
24
+ "license": "MIT",
25
+ "author": "Dario Passariello <dariopassariello@gmail.com>",
26
+ "contributors": [
27
+ {
28
+ "name": "Dario Passariello",
29
+ "email": "dariopassariello@gmail.com",
30
+ "url": "https://dario.passariello.ca/"
31
+ },
32
+ {
33
+ "name": "Valeria Cala Scaglitta",
34
+ "email": "valeriacalascaglitta@gmail.com"
35
+ }
36
+ ],
37
+ "main": "./index.js",
38
+ "types": "./index.d.ts",
39
+ "exports": {
40
+ ".": "./index.js"
41
+ },
42
+ "scripts": {
43
+ "build": "tsc --emitDeclarationOnly --outDir dist && node ./esbuild.config.mjs && npm run build:extension",
44
+ "build:extension": "cd vscode-extension && vsce package -o ../dist",
45
+ "test": "jest --config tests/jest/jest.config.ts",
46
+ "npm: pack": "npm run build && cd dist && npm pack",
47
+ "npm: publish": "npm run build && cd dist && npm publish --access=public"
48
+ },
49
+ "dependencies": {
50
+ "immer": "^11.1.4"
51
+ },
52
+ "peerDependencies": {
53
+ "react": ">=16.8.0",
54
+ "react-dom": ">=16.8.0"
55
+ },
56
+ "devDependencies": {
57
+ "@eslint/js": "10.0.1",
58
+ "@playwright/test": "1.58.2",
59
+ "@testing-library/dom": "10.4.1",
60
+ "@testing-library/jest-dom": "6.9.1",
61
+ "@testing-library/react": "16.3.2",
62
+ "@types/jest": "30.0.0",
63
+ "@types/node": "25.2.3",
64
+ "@types/react": "19.2.14",
65
+ "@types/react-dom": "19.2.3",
66
+ "@typescript-eslint/eslint-plugin": "^8.56.0",
67
+ "@typescript-eslint/parser": "^8.56.0",
68
+ "dphelper": "2.6.3",
69
+ "esbuild": "0.27.3",
70
+ "esbuild-plugin-copy": "2.1.1",
71
+ "eslint": "^10.0.0",
72
+ "eslint-plugin-react": "7.37.5",
73
+ "eslint-plugin-react-hooks": "7.0.1",
74
+ "globals": "17.3.0",
75
+ "jest": "30.2.0",
76
+ "jest-environment-jsdom": "30.2.0",
77
+ "react": "19.2.4",
78
+ "react-dom": "19.2.4",
79
+ "ts-jest": "29.4.6",
80
+ "tslib": "^2.8.1",
81
+ "typescript": "^5.9.3",
82
+ "typescript-eslint": "8.56.0"
83
+ }
84
+ }
@@ -7,7 +7,9 @@ export { guardPlugin } from "./official/guard.plugin";
7
7
  export { analyticsPlugin } from "./official/analytics.plugin";
8
8
  export { syncPlugin } from "./official/sync.plugin";
9
9
  export { debugPlugin } from "./official/debug.plugin";
10
+ export { indexedDBPlugin } from "./official/indexeddb.plugin";
11
+ export { cloudSyncPlugin, createMongoAdapter, createFirestoreAdapter, createSqlRestAdapter } from "./official/cloud-sync.plugin";
10
12
  import type { IPlugin } from "../core/types";
11
- export declare const loggerPlugin: (options?: {
13
+ export declare const loggerPlugin: <S extends Record<string, unknown>>(options?: {
12
14
  collapsed?: boolean;
13
- }) => IPlugin;
15
+ }) => IPlugin<S>;
@@ -0,0 +1,22 @@
1
+ import type { IPlugin } from '../../core/types';
2
+ export interface SyncStats {
3
+ lastSyncTimestamp: number | null;
4
+ totalKeysSynced: number;
5
+ totalBytesSynced: number;
6
+ syncCount: number;
7
+ lastDuration: number;
8
+ errors: number;
9
+ }
10
+ export interface CloudSyncAdapter {
11
+ name: string;
12
+ save: (data: Record<string, unknown>) => Promise<boolean>;
13
+ }
14
+ export interface CloudSyncOptions {
15
+ adapter: CloudSyncAdapter;
16
+ autoSyncInterval?: number;
17
+ onSync?: (stats: SyncStats) => void;
18
+ }
19
+ export declare const cloudSyncPlugin: <S extends Record<string, unknown>>(options: CloudSyncOptions) => IPlugin<S>;
20
+ export declare const createMongoAdapter: (apiUrl: string, apiKey: string) => CloudSyncAdapter;
21
+ export declare const createFirestoreAdapter: (db: unknown, docPath: string) => CloudSyncAdapter;
22
+ export declare const createSqlRestAdapter: (endpoint: string, authToken: string) => CloudSyncAdapter;
@@ -1,2 +1,2 @@
1
1
  import type { IPlugin } from '../../core/types';
2
- export declare const immerPlugin: () => IPlugin;
2
+ export declare const immerPlugin: <S extends Record<string, unknown>>() => IPlugin<S>;
@@ -0,0 +1,7 @@
1
+ import type { IPlugin } from '../../core/types';
2
+ export interface IndexedDBOptions {
3
+ dbName?: string;
4
+ storeName?: string;
5
+ version?: number;
6
+ }
7
+ export declare const indexedDBPlugin: <S extends Record<string, unknown>>(options?: IndexedDBOptions) => IPlugin<S>;
@@ -1,4 +1,4 @@
1
1
  import type { IPlugin } from '../../core/types';
2
- export declare const undoRedoPlugin: (options?: {
2
+ export declare const undoRedoPlugin: <S extends Record<string, unknown>>(options?: {
3
3
  limit?: number;
4
- }) => IPlugin;
4
+ }) => IPlugin<S>;
Binary file