@asaidimu/react-store 1.0.1 → 1.1.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/index.cjs +1 -1
- package/index.d.cts +71 -36
- package/index.d.ts +71 -36
- package/index.js +1 -1
- package/package.json +2 -2
package/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var m=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var M=(n,t)=>{for(var e in t)m(n,e,{get:t[e],enumerable:!0})},E=(n,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of b(t))!T.call(n,r)&&r!==e&&m(n,r,{get:()=>t[r],enumerable:!(i=w(t,r))||i.enumerable});return n};var k=n=>E(m({},"__esModule",{value:!0}),n);var R={};M(R,{StateManager:()=>h,createStore:()=>x});module.exports=k(R);var g=require("react");var S=require("@asaidimu/node");var p=class{cache=new Map;maxSize;maxAge;constructor(t=100,e=5e3){this.maxSize=t,this.maxAge=e}get(t){let e=this.cache.get(t);if(e){if(Date.now()-e.timestamp>this.maxAge){this.cache.delete(t);return}return e.value}}set(t,e){if(this.cache.size>=this.maxSize){let i=Array.from(this.cache.entries()).sort(([,r],[,a])=>r.timestamp-a.timestamp)[0][0];this.cache.delete(i)}this.cache.set(t,{value:e,timestamp:Date.now()})}clear(){this.cache.clear()}};var f=class{validation;constructor(t={}){this.validation=t}validate(t,e){let i=[],r=e.split("/").pop(),a=this.validation[r];return a?(a.forEach((o,s)=>{try{o.validate(t[r])||i.push(o.message||`Validation failed for ${String(r)} at rule ${s}`)}catch(c){i.push(`Validation error at ${e}: ${c.message}`)}}),{valid:i.length===0,errors:i}):{valid:!0,errors:[]}}};var u="root",h=class{manager;subscribers=new Set;middleware;options;definition;middlewareCache;validator;lastValidationResult={valid:!0,errors:[]};constructor(t,e={}){this.definition=t,this.options=e,this.middleware=this.sortMiddleware(e.middleware||[]),this.middlewareCache=new p,this.validator=new f(e.validation),this.manager=this.initializeManager()}sortMiddleware(t){let e=new Map;t.forEach(s=>{e.set(s.id,new Set(s.dependencies||[]))});let i=[],r=new Set,a=new Set,o=s=>{if(a.has(s))throw new Error(`Circular dependency found: ${s}`);if(r.has(s))return;a.add(s),(e.get(s)||new Set).forEach(d=>o(d)),a.delete(s),r.add(s),i.push(t.find(d=>d.id===s))};return t.forEach(s=>{r.has(s.id)||o(s.id)}),i.sort((s,c)=>(c.priority||0)-(s.priority||0))}initializeManager(){let t=(0,S.createNodeManager)();t.add(u,null,{key:u});let e=(i=u,r=this.definition.state)=>{for(let[a,o]of Object.entries(r))typeof o=="object"&&!Array.isArray(o)?(t.add(`${i}/${a}`,o,{key:a}),e(`${i}/${a}`,o)):t.add(`${i}/${a}`,o,{key:a})};if(e(),this.definition.sync){let i=this.getState.bind(this);t.subscribe("node",()=>{this.definition.sync(i())})}return t}async applyMiddleware(t,e,i={value:!1}){let r=`${e}-${JSON.stringify(t)}`,a=this.middlewareCache.get(r);if(a)return a;if(this.lastValidationResult=this.validator.validate(t,e),!this.lastValidationResult.valid)throw new Error(`Validation failed: ${this.lastValidationResult.errors.join(", ")}`);let o={fullState:this.getState(),path:e,abortUpdate:()=>{i.value=!0},getValidationResult:()=>this.lastValidationResult};try{let s=t;for(let c of this.middleware){if(i.value)throw new Error("Update aborted by middleware");if(s=await Promise.resolve(c.transform(s,o)),this.lastValidationResult=this.validator.validate(s,e),!this.lastValidationResult.valid)throw new Error(`Validation failed after middleware ${c.id}: ${this.lastValidationResult.errors.join(", ")}`)}return this.middlewareCache.set(r,s),s}catch(s){throw this.handleMiddlewareError(s,t,e),s}}handleMiddlewareError(t,e,i){if(this.options.error?.onError&&this.options.error.onError(t,{action:"applyMiddleware",state:e,path:i,error:t}),this.options.error?.recovery)switch(this.middlewareCache.clear(),this.options.error.recovery.strategy){case"retry":break;case"revert":this.revertState(i);break;case"ignore":break}}revertState(t){let e=this.getState(),i=t.split("/"),r=e;for(let o=1;o<i.length-1;o++)r=r[i[o]];let a=i[i.length-1];this.manager.update(t,r[a],{force:!0})}async setState(t,e){let r=[{path:e||u,state:t}];try{this.options.lifecycleHooks?.beforeAll?.(r);let a={value:!1};for(let o of r){if(a.value)break;let s=await this.applyMiddleware(o.state,o.path,a);a.value||this.updateState(s,o.path)}this.options.lifecycleHooks?.afterAll?.(r),this.notifySubscribers()}catch(a){this.handleError(a,{action:"batchUpdate",state:r})}}updateState(t,e){let i=(r,a)=>{typeof a=="object"&&a!==null&&!Array.isArray(a)?Object.entries(a).forEach(([o,s])=>{i(`${r}/${o}`,s)}):this.manager.update(r,a,{force:!0})};Object.entries(t).forEach(([r,a])=>{let o=e===u?`${u}/${r}`:`${e}/${r}`;i(o,a)})}handleError(t,e){this.options.error?.onError&&this.options.error.onError(t,e)}getState(){return this.manager.store().map("key")[u]}getValidationResult(){return this.lastValidationResult}subscribe(t){return this.subscribers.add(t),()=>{this.subscribers.delete(t)}}notifySubscribers(){this.subscribers.forEach(t=>t())}select(t,e){let i=[],r=this.manager;function a(o){let s={get:(c,d)=>{let l=`${o}/${d}`;return r.exists(l)&&i.push(l),a(l)}};return new Proxy({},s)}return t(a(u)),r.subscribe({event:"node",path:i},()=>{e(t(this.getState()))})}getTree(){return this.manager.store().serialize()}};var v=class{metrics={updates:0,subscriptionTriggers:0,middlewareExecutions:0,batchSize:0,lastUpdateDuration:0};enableMetrics;constructor(t=!1){this.enableMetrics=t}track(t,e){if(!this.enableMetrics)return e();let i=performance.now();try{let r=e();return this.recordMetric(t,performance.now()-i),r}catch(r){throw this.recordError(t,r),r}}recordMetric(t,e){switch(t){case"update":this.metrics.updates++,this.metrics.lastUpdateDuration=e;break;case"subscription":this.metrics.subscriptionTriggers++;break;case"middleware":this.metrics.middlewareExecutions++;break}}recordError(t,e){console.error(`Error in ${t}:`,e)}getMetrics(){return{...this.metrics}}reset(){this.metrics={updates:0,subscriptionTriggers:0,middlewareExecutions:0,batchSize:0,lastUpdateDuration:0}}},y=class{selectorCache=new WeakMap;create(t){return e=>{let i=this.selectorCache.get(t);i||(i=new WeakMap,this.selectorCache.set(t,i));let r=i.get(e);if(r)return r.result;let a=t(e);return i.set(e,{result:a,deps:[]}),a}}};function x(n,t={}){let e=new h(n,t),i=new y,r=new v(t.enableMetrics),a=Object.entries(n.actions).reduce((o,[s,c])=>(o[s]=async(...d)=>{try{return await r.track("update",async()=>{let l=await c(e.getState(),...d);return e.setState(l),l})}catch(l){throw console.error(`Error in action ${s}:`,l),l}},o),{});return function(){return{select:(0,g.useCallback)(c=>{let d=i.create(c);return(0,g.useSyncExternalStore)(l=>r.track("subscription",()=>e.select(d,l)),()=>d(e.getState()),()=>d(e.getState()))},[]),actions:a,getState:()=>e.getState(),getTree:()=>e.getTree(),getMetrics:()=>r.getMetrics(),resetMetrics:()=>r.reset()}}}0&&(module.exports={StateManager,createStore});
|
package/index.d.cts
CHANGED
|
@@ -1,6 +1,63 @@
|
|
|
1
1
|
import * as _asaidimu_node from '@asaidimu/node';
|
|
2
2
|
|
|
3
|
-
type
|
|
3
|
+
type ValidationRule<T> = {
|
|
4
|
+
validate: (value: T) => boolean;
|
|
5
|
+
message?: string;
|
|
6
|
+
};
|
|
7
|
+
type ValidationResult = {
|
|
8
|
+
valid: boolean;
|
|
9
|
+
errors: string[];
|
|
10
|
+
};
|
|
11
|
+
type Validation<T> = {
|
|
12
|
+
[K in keyof T]?: ValidationRule<T[K]>[];
|
|
13
|
+
};
|
|
14
|
+
type ErrorInfo = {
|
|
15
|
+
action: string;
|
|
16
|
+
state: unknown;
|
|
17
|
+
path?: string;
|
|
18
|
+
error?: Error;
|
|
19
|
+
};
|
|
20
|
+
type ErrorHandler = (error: Error, info: ErrorInfo) => void;
|
|
21
|
+
type RecoveryStrategy = 'retry' | 'revert' | 'ignore';
|
|
22
|
+
type ErrorRecovery = {
|
|
23
|
+
strategy: RecoveryStrategy;
|
|
24
|
+
maxAttempts?: number;
|
|
25
|
+
};
|
|
26
|
+
type ErrorOptions = {
|
|
27
|
+
onError?: ErrorHandler;
|
|
28
|
+
recovery?: ErrorRecovery;
|
|
29
|
+
};
|
|
30
|
+
type MiddlewareContext<T> = {
|
|
31
|
+
fullState: T;
|
|
32
|
+
path: string;
|
|
33
|
+
abortUpdate: () => void;
|
|
34
|
+
getValidationResult: () => ValidationResult;
|
|
35
|
+
};
|
|
36
|
+
type MiddleWare<T> = {
|
|
37
|
+
id: string;
|
|
38
|
+
priority?: number;
|
|
39
|
+
dependencies?: string[];
|
|
40
|
+
transform: (state: Partial<T>, context: MiddlewareContext<T>) => Promise<Partial<T>> | Partial<T>;
|
|
41
|
+
};
|
|
42
|
+
type BatchUpdate<T> = {
|
|
43
|
+
path: string;
|
|
44
|
+
state: Partial<T>;
|
|
45
|
+
};
|
|
46
|
+
type MiddlewareLifecycleHooks<T> = {
|
|
47
|
+
beforeAll?: (updates: BatchUpdate<T>[]) => void;
|
|
48
|
+
afterAll?: (updates: BatchUpdate<T>[]) => void;
|
|
49
|
+
};
|
|
50
|
+
interface StoreOptions<T> {
|
|
51
|
+
middleware?: MiddleWare<T>[];
|
|
52
|
+
validation?: Validation<T>;
|
|
53
|
+
error?: ErrorOptions;
|
|
54
|
+
lifecycleHooks?: MiddlewareLifecycleHooks<T>;
|
|
55
|
+
name?: string;
|
|
56
|
+
trace?: boolean;
|
|
57
|
+
maxTraceHistory?: number;
|
|
58
|
+
traceRetentionPeriod?: number;
|
|
59
|
+
migrations?: Migration<T>[];
|
|
60
|
+
}
|
|
4
61
|
type Actions<T> = {
|
|
5
62
|
[K: string]: (state: T, ...args: any[]) => Partial<T> | Promise<Partial<T>>;
|
|
6
63
|
};
|
|
@@ -9,38 +66,10 @@ interface StoreDefinition<T, R extends Actions<T>> {
|
|
|
9
66
|
actions: R;
|
|
10
67
|
sync?: (args: T) => void;
|
|
11
68
|
}
|
|
12
|
-
type Schema<T> = {
|
|
13
|
-
[K in keyof T]?: {
|
|
14
|
-
validate: (value: T[K]) => boolean;
|
|
15
|
-
message: string;
|
|
16
|
-
}[];
|
|
17
|
-
};
|
|
18
69
|
interface Migration<T> {
|
|
19
70
|
version: number;
|
|
20
71
|
migrate: (state: T) => T;
|
|
21
72
|
}
|
|
22
|
-
interface ErrorConfig {
|
|
23
|
-
onError?: (error: Error, errorInfo: {
|
|
24
|
-
action?: string;
|
|
25
|
-
state?: any;
|
|
26
|
-
[key: string]: unknown;
|
|
27
|
-
}) => void;
|
|
28
|
-
recovery?: {
|
|
29
|
-
strategy: "rollback" | "retry" | "reset";
|
|
30
|
-
maxAttempts: number;
|
|
31
|
-
backoffMs: number;
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
interface StoreOptions<T> {
|
|
35
|
-
name?: string;
|
|
36
|
-
trace?: boolean;
|
|
37
|
-
maxTraceHistory?: number;
|
|
38
|
-
traceRetentionPeriod?: number;
|
|
39
|
-
middleware?: Middleware<T>[];
|
|
40
|
-
migrations?: Migration<T>[];
|
|
41
|
-
validation?: Schema<T>;
|
|
42
|
-
error?: ErrorConfig;
|
|
43
|
-
}
|
|
44
73
|
interface StateManagerMetrics {
|
|
45
74
|
updates: number;
|
|
46
75
|
subscriptionTriggers: number;
|
|
@@ -73,19 +102,25 @@ declare class StateManager<T extends Record<string, unknown>, R extends Actions<
|
|
|
73
102
|
private options;
|
|
74
103
|
private definition;
|
|
75
104
|
private middlewareCache;
|
|
105
|
+
private validator;
|
|
106
|
+
private lastValidationResult;
|
|
76
107
|
constructor(definition: StoreDefinition<T, R>, options?: StoreOptions<T>);
|
|
108
|
+
private sortMiddleware;
|
|
77
109
|
private initializeManager;
|
|
78
|
-
getState(): T;
|
|
79
|
-
getTree(): _asaidimu_node.Node<any, {
|
|
80
|
-
key: string;
|
|
81
|
-
}>[];
|
|
82
|
-
setState(nextState: Partial<T>, path?: string): void;
|
|
83
|
-
private validateState;
|
|
84
110
|
private applyMiddleware;
|
|
111
|
+
private handleMiddlewareError;
|
|
112
|
+
private revertState;
|
|
113
|
+
setState(nextState: Partial<T>, path?: string): Promise<void>;
|
|
114
|
+
private updateState;
|
|
85
115
|
private handleError;
|
|
116
|
+
getState(): T;
|
|
117
|
+
getValidationResult(): ValidationResult;
|
|
86
118
|
subscribe(callback: () => void): () => void;
|
|
87
119
|
private notifySubscribers;
|
|
88
|
-
select<S>(selector: (state: T) => S, callback: (state:
|
|
120
|
+
select<S>(selector: (state: T) => S, callback: (state: S) => void): () => void;
|
|
121
|
+
getTree(): _asaidimu_node.Node<any, {
|
|
122
|
+
key: string;
|
|
123
|
+
}>[];
|
|
89
124
|
}
|
|
90
125
|
|
|
91
126
|
export { StateManager, createStore };
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,63 @@
|
|
|
1
1
|
import * as _asaidimu_node from '@asaidimu/node';
|
|
2
2
|
|
|
3
|
-
type
|
|
3
|
+
type ValidationRule<T> = {
|
|
4
|
+
validate: (value: T) => boolean;
|
|
5
|
+
message?: string;
|
|
6
|
+
};
|
|
7
|
+
type ValidationResult = {
|
|
8
|
+
valid: boolean;
|
|
9
|
+
errors: string[];
|
|
10
|
+
};
|
|
11
|
+
type Validation<T> = {
|
|
12
|
+
[K in keyof T]?: ValidationRule<T[K]>[];
|
|
13
|
+
};
|
|
14
|
+
type ErrorInfo = {
|
|
15
|
+
action: string;
|
|
16
|
+
state: unknown;
|
|
17
|
+
path?: string;
|
|
18
|
+
error?: Error;
|
|
19
|
+
};
|
|
20
|
+
type ErrorHandler = (error: Error, info: ErrorInfo) => void;
|
|
21
|
+
type RecoveryStrategy = 'retry' | 'revert' | 'ignore';
|
|
22
|
+
type ErrorRecovery = {
|
|
23
|
+
strategy: RecoveryStrategy;
|
|
24
|
+
maxAttempts?: number;
|
|
25
|
+
};
|
|
26
|
+
type ErrorOptions = {
|
|
27
|
+
onError?: ErrorHandler;
|
|
28
|
+
recovery?: ErrorRecovery;
|
|
29
|
+
};
|
|
30
|
+
type MiddlewareContext<T> = {
|
|
31
|
+
fullState: T;
|
|
32
|
+
path: string;
|
|
33
|
+
abortUpdate: () => void;
|
|
34
|
+
getValidationResult: () => ValidationResult;
|
|
35
|
+
};
|
|
36
|
+
type MiddleWare<T> = {
|
|
37
|
+
id: string;
|
|
38
|
+
priority?: number;
|
|
39
|
+
dependencies?: string[];
|
|
40
|
+
transform: (state: Partial<T>, context: MiddlewareContext<T>) => Promise<Partial<T>> | Partial<T>;
|
|
41
|
+
};
|
|
42
|
+
type BatchUpdate<T> = {
|
|
43
|
+
path: string;
|
|
44
|
+
state: Partial<T>;
|
|
45
|
+
};
|
|
46
|
+
type MiddlewareLifecycleHooks<T> = {
|
|
47
|
+
beforeAll?: (updates: BatchUpdate<T>[]) => void;
|
|
48
|
+
afterAll?: (updates: BatchUpdate<T>[]) => void;
|
|
49
|
+
};
|
|
50
|
+
interface StoreOptions<T> {
|
|
51
|
+
middleware?: MiddleWare<T>[];
|
|
52
|
+
validation?: Validation<T>;
|
|
53
|
+
error?: ErrorOptions;
|
|
54
|
+
lifecycleHooks?: MiddlewareLifecycleHooks<T>;
|
|
55
|
+
name?: string;
|
|
56
|
+
trace?: boolean;
|
|
57
|
+
maxTraceHistory?: number;
|
|
58
|
+
traceRetentionPeriod?: number;
|
|
59
|
+
migrations?: Migration<T>[];
|
|
60
|
+
}
|
|
4
61
|
type Actions<T> = {
|
|
5
62
|
[K: string]: (state: T, ...args: any[]) => Partial<T> | Promise<Partial<T>>;
|
|
6
63
|
};
|
|
@@ -9,38 +66,10 @@ interface StoreDefinition<T, R extends Actions<T>> {
|
|
|
9
66
|
actions: R;
|
|
10
67
|
sync?: (args: T) => void;
|
|
11
68
|
}
|
|
12
|
-
type Schema<T> = {
|
|
13
|
-
[K in keyof T]?: {
|
|
14
|
-
validate: (value: T[K]) => boolean;
|
|
15
|
-
message: string;
|
|
16
|
-
}[];
|
|
17
|
-
};
|
|
18
69
|
interface Migration<T> {
|
|
19
70
|
version: number;
|
|
20
71
|
migrate: (state: T) => T;
|
|
21
72
|
}
|
|
22
|
-
interface ErrorConfig {
|
|
23
|
-
onError?: (error: Error, errorInfo: {
|
|
24
|
-
action?: string;
|
|
25
|
-
state?: any;
|
|
26
|
-
[key: string]: unknown;
|
|
27
|
-
}) => void;
|
|
28
|
-
recovery?: {
|
|
29
|
-
strategy: "rollback" | "retry" | "reset";
|
|
30
|
-
maxAttempts: number;
|
|
31
|
-
backoffMs: number;
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
interface StoreOptions<T> {
|
|
35
|
-
name?: string;
|
|
36
|
-
trace?: boolean;
|
|
37
|
-
maxTraceHistory?: number;
|
|
38
|
-
traceRetentionPeriod?: number;
|
|
39
|
-
middleware?: Middleware<T>[];
|
|
40
|
-
migrations?: Migration<T>[];
|
|
41
|
-
validation?: Schema<T>;
|
|
42
|
-
error?: ErrorConfig;
|
|
43
|
-
}
|
|
44
73
|
interface StateManagerMetrics {
|
|
45
74
|
updates: number;
|
|
46
75
|
subscriptionTriggers: number;
|
|
@@ -73,19 +102,25 @@ declare class StateManager<T extends Record<string, unknown>, R extends Actions<
|
|
|
73
102
|
private options;
|
|
74
103
|
private definition;
|
|
75
104
|
private middlewareCache;
|
|
105
|
+
private validator;
|
|
106
|
+
private lastValidationResult;
|
|
76
107
|
constructor(definition: StoreDefinition<T, R>, options?: StoreOptions<T>);
|
|
108
|
+
private sortMiddleware;
|
|
77
109
|
private initializeManager;
|
|
78
|
-
getState(): T;
|
|
79
|
-
getTree(): _asaidimu_node.Node<any, {
|
|
80
|
-
key: string;
|
|
81
|
-
}>[];
|
|
82
|
-
setState(nextState: Partial<T>, path?: string): void;
|
|
83
|
-
private validateState;
|
|
84
110
|
private applyMiddleware;
|
|
111
|
+
private handleMiddlewareError;
|
|
112
|
+
private revertState;
|
|
113
|
+
setState(nextState: Partial<T>, path?: string): Promise<void>;
|
|
114
|
+
private updateState;
|
|
85
115
|
private handleError;
|
|
116
|
+
getState(): T;
|
|
117
|
+
getValidationResult(): ValidationResult;
|
|
86
118
|
subscribe(callback: () => void): () => void;
|
|
87
119
|
private notifySubscribers;
|
|
88
|
-
select<S>(selector: (state: T) => S, callback: (state:
|
|
120
|
+
select<S>(selector: (state: T) => S, callback: (state: S) => void): () => void;
|
|
121
|
+
getTree(): _asaidimu_node.Node<any, {
|
|
122
|
+
key: string;
|
|
123
|
+
}>[];
|
|
89
124
|
}
|
|
90
125
|
|
|
91
126
|
export { StateManager, createStore };
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useCallback as y,useSyncExternalStore as S}from"react";import{createNodeManager as
|
|
1
|
+
import{useCallback as y,useSyncExternalStore as S}from"react";import{createNodeManager as v}from"@asaidimu/node";var h=class{cache=new Map;maxSize;maxAge;constructor(t=100,e=5e3){this.maxSize=t,this.maxAge=e}get(t){let e=this.cache.get(t);if(e){if(Date.now()-e.timestamp>this.maxAge){this.cache.delete(t);return}return e.value}}set(t,e){if(this.cache.size>=this.maxSize){let i=Array.from(this.cache.entries()).sort(([,r],[,a])=>r.timestamp-a.timestamp)[0][0];this.cache.delete(i)}this.cache.set(t,{value:e,timestamp:Date.now()})}clear(){this.cache.clear()}};var p=class{validation;constructor(t={}){this.validation=t}validate(t,e){let i=[],r=e.split("/").pop(),a=this.validation[r];return a?(a.forEach((o,s)=>{try{o.validate(t[r])||i.push(o.message||`Validation failed for ${String(r)} at rule ${s}`)}catch(n){i.push(`Validation error at ${e}: ${n.message}`)}}),{valid:i.length===0,errors:i}):{valid:!0,errors:[]}}};var l="root",f=class{manager;subscribers=new Set;middleware;options;definition;middlewareCache;validator;lastValidationResult={valid:!0,errors:[]};constructor(t,e={}){this.definition=t,this.options=e,this.middleware=this.sortMiddleware(e.middleware||[]),this.middlewareCache=new h,this.validator=new p(e.validation),this.manager=this.initializeManager()}sortMiddleware(t){let e=new Map;t.forEach(s=>{e.set(s.id,new Set(s.dependencies||[]))});let i=[],r=new Set,a=new Set,o=s=>{if(a.has(s))throw new Error(`Circular dependency found: ${s}`);if(r.has(s))return;a.add(s),(e.get(s)||new Set).forEach(c=>o(c)),a.delete(s),r.add(s),i.push(t.find(c=>c.id===s))};return t.forEach(s=>{r.has(s.id)||o(s.id)}),i.sort((s,n)=>(n.priority||0)-(s.priority||0))}initializeManager(){let t=v();t.add(l,null,{key:l});let e=(i=l,r=this.definition.state)=>{for(let[a,o]of Object.entries(r))typeof o=="object"&&!Array.isArray(o)?(t.add(`${i}/${a}`,o,{key:a}),e(`${i}/${a}`,o)):t.add(`${i}/${a}`,o,{key:a})};if(e(),this.definition.sync){let i=this.getState.bind(this);t.subscribe("node",()=>{this.definition.sync(i())})}return t}async applyMiddleware(t,e,i={value:!1}){let r=`${e}-${JSON.stringify(t)}`,a=this.middlewareCache.get(r);if(a)return a;if(this.lastValidationResult=this.validator.validate(t,e),!this.lastValidationResult.valid)throw new Error(`Validation failed: ${this.lastValidationResult.errors.join(", ")}`);let o={fullState:this.getState(),path:e,abortUpdate:()=>{i.value=!0},getValidationResult:()=>this.lastValidationResult};try{let s=t;for(let n of this.middleware){if(i.value)throw new Error("Update aborted by middleware");if(s=await Promise.resolve(n.transform(s,o)),this.lastValidationResult=this.validator.validate(s,e),!this.lastValidationResult.valid)throw new Error(`Validation failed after middleware ${n.id}: ${this.lastValidationResult.errors.join(", ")}`)}return this.middlewareCache.set(r,s),s}catch(s){throw this.handleMiddlewareError(s,t,e),s}}handleMiddlewareError(t,e,i){if(this.options.error?.onError&&this.options.error.onError(t,{action:"applyMiddleware",state:e,path:i,error:t}),this.options.error?.recovery)switch(this.middlewareCache.clear(),this.options.error.recovery.strategy){case"retry":break;case"revert":this.revertState(i);break;case"ignore":break}}revertState(t){let e=this.getState(),i=t.split("/"),r=e;for(let o=1;o<i.length-1;o++)r=r[i[o]];let a=i[i.length-1];this.manager.update(t,r[a],{force:!0})}async setState(t,e){let r=[{path:e||l,state:t}];try{this.options.lifecycleHooks?.beforeAll?.(r);let a={value:!1};for(let o of r){if(a.value)break;let s=await this.applyMiddleware(o.state,o.path,a);a.value||this.updateState(s,o.path)}this.options.lifecycleHooks?.afterAll?.(r),this.notifySubscribers()}catch(a){this.handleError(a,{action:"batchUpdate",state:r})}}updateState(t,e){let i=(r,a)=>{typeof a=="object"&&a!==null&&!Array.isArray(a)?Object.entries(a).forEach(([o,s])=>{i(`${r}/${o}`,s)}):this.manager.update(r,a,{force:!0})};Object.entries(t).forEach(([r,a])=>{let o=e===l?`${l}/${r}`:`${e}/${r}`;i(o,a)})}handleError(t,e){this.options.error?.onError&&this.options.error.onError(t,e)}getState(){return this.manager.store().map("key")[l]}getValidationResult(){return this.lastValidationResult}subscribe(t){return this.subscribers.add(t),()=>{this.subscribers.delete(t)}}notifySubscribers(){this.subscribers.forEach(t=>t())}select(t,e){let i=[],r=this.manager;function a(o){let s={get:(n,c)=>{let d=`${o}/${c}`;return r.exists(d)&&i.push(d),a(d)}};return new Proxy({},s)}return t(a(l)),r.subscribe({event:"node",path:i},()=>{e(t(this.getState()))})}getTree(){return this.manager.store().serialize()}};var g=class{metrics={updates:0,subscriptionTriggers:0,middlewareExecutions:0,batchSize:0,lastUpdateDuration:0};enableMetrics;constructor(t=!1){this.enableMetrics=t}track(t,e){if(!this.enableMetrics)return e();let i=performance.now();try{let r=e();return this.recordMetric(t,performance.now()-i),r}catch(r){throw this.recordError(t,r),r}}recordMetric(t,e){switch(t){case"update":this.metrics.updates++,this.metrics.lastUpdateDuration=e;break;case"subscription":this.metrics.subscriptionTriggers++;break;case"middleware":this.metrics.middlewareExecutions++;break}}recordError(t,e){console.error(`Error in ${t}:`,e)}getMetrics(){return{...this.metrics}}reset(){this.metrics={updates:0,subscriptionTriggers:0,middlewareExecutions:0,batchSize:0,lastUpdateDuration:0}}},m=class{selectorCache=new WeakMap;create(t){return e=>{let i=this.selectorCache.get(t);i||(i=new WeakMap,this.selectorCache.set(t,i));let r=i.get(e);if(r)return r.result;let a=t(e);return i.set(e,{result:a,deps:[]}),a}}};function V(u,t={}){let e=new f(u,t),i=new m,r=new g(t.enableMetrics),a=Object.entries(u.actions).reduce((o,[s,n])=>(o[s]=async(...c)=>{try{return await r.track("update",async()=>{let d=await n(e.getState(),...c);return e.setState(d),d})}catch(d){throw console.error(`Error in action ${s}:`,d),d}},o),{});return function(){return{select:y(n=>{let c=i.create(n);return S(d=>r.track("subscription",()=>e.select(c,d)),()=>c(e.getState()),()=>c(e.getState()))},[]),actions:a,getState:()=>e.getState(),getTree:()=>e.getTree(),getMetrics:()=>r.getMetrics(),resetMetrics:()=>r.reset()}}}export{f as StateManager,V as createStore};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asaidimu/react-store",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Efficient react state manager.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@asaidimu/events": "^1.0.0",
|
|
30
|
-
"@asaidimu/node": "^1.0.
|
|
30
|
+
"@asaidimu/node": "^1.0.5",
|
|
31
31
|
"react": "^19.0.0"
|
|
32
32
|
}
|
|
33
33
|
}
|