@push.rocks/smartstate 2.0.23 → 2.0.25
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/dist_bundle/bundle.js +51 -23
- package/dist_bundle/bundle.js.map +2 -2
- package/dist_ts/smartstate.classes.smartstate.d.ts +5 -3
- package/dist_ts/smartstate.classes.smartstate.js +24 -12
- package/dist_ts/smartstate.classes.statepart.d.ts +8 -3
- package/dist_ts/smartstate.classes.statepart.js +33 -13
- package/package.json +8 -7
- package/readme.hints.md +29 -16
- package/readme.md +108 -18
- package/ts/smartstate.classes.smartstate.ts +26 -13
- package/ts/smartstate.classes.statepart.ts +35 -12
|
@@ -4,7 +4,7 @@ import { StateAction, type IActionDef } from './smartstate.classes.stateaction.j
|
|
|
4
4
|
export class StatePart<TStatePartName, TStatePayload> {
|
|
5
5
|
public name: TStatePartName;
|
|
6
6
|
public state = new plugins.smartrx.rxjs.Subject<TStatePayload>();
|
|
7
|
-
public stateStore: TStatePayload;
|
|
7
|
+
public stateStore: TStatePayload | undefined;
|
|
8
8
|
private cumulativeDeferred = plugins.smartpromise.cumulativeDefer();
|
|
9
9
|
|
|
10
10
|
private webStoreOptions: plugins.webstore.IWebStoreOptions;
|
|
@@ -27,9 +27,9 @@ export class StatePart<TStatePartName, TStatePayload> {
|
|
|
27
27
|
this.webStore = new plugins.webstore.WebStore<TStatePayload>(this.webStoreOptions);
|
|
28
28
|
await this.webStore.init();
|
|
29
29
|
const storedState = await this.webStore.get(String(this.name));
|
|
30
|
-
if (storedState) {
|
|
30
|
+
if (storedState && this.validateState(storedState)) {
|
|
31
31
|
this.stateStore = storedState;
|
|
32
|
-
this.notifyChange();
|
|
32
|
+
await this.notifyChange();
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -37,7 +37,7 @@ export class StatePart<TStatePartName, TStatePayload> {
|
|
|
37
37
|
/**
|
|
38
38
|
* gets the state from the state store
|
|
39
39
|
*/
|
|
40
|
-
public getState(): TStatePayload {
|
|
40
|
+
public getState(): TStatePayload | undefined {
|
|
41
41
|
return this.stateStore;
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -46,8 +46,13 @@ export class StatePart<TStatePartName, TStatePayload> {
|
|
|
46
46
|
* @param newStateArg
|
|
47
47
|
*/
|
|
48
48
|
public async setState(newStateArg: TStatePayload) {
|
|
49
|
+
// Validate state structure
|
|
50
|
+
if (!this.validateState(newStateArg)) {
|
|
51
|
+
throw new Error(`Invalid state structure for state part '${this.name}'`);
|
|
52
|
+
}
|
|
53
|
+
|
|
49
54
|
this.stateStore = newStateArg;
|
|
50
|
-
this.notifyChange();
|
|
55
|
+
await this.notifyChange();
|
|
51
56
|
|
|
52
57
|
// Save state to WebStore if initialized
|
|
53
58
|
if (this.webStore) {
|
|
@@ -56,21 +61,34 @@ export class StatePart<TStatePartName, TStatePayload> {
|
|
|
56
61
|
return this.stateStore;
|
|
57
62
|
}
|
|
58
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Validates state structure - can be overridden for custom validation
|
|
66
|
+
* @param stateArg
|
|
67
|
+
*/
|
|
68
|
+
protected validateState(stateArg: any): stateArg is TStatePayload {
|
|
69
|
+
// Basic validation - ensure state is not null/undefined
|
|
70
|
+
// Subclasses can override for more specific validation
|
|
71
|
+
return stateArg !== null && stateArg !== undefined;
|
|
72
|
+
}
|
|
73
|
+
|
|
59
74
|
/**
|
|
60
75
|
* notifies of a change on the state
|
|
61
76
|
*/
|
|
62
|
-
public notifyChange() {
|
|
63
|
-
|
|
64
|
-
return
|
|
77
|
+
public async notifyChange() {
|
|
78
|
+
if (!this.stateStore) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const createStateHash = async (stateArg: any) => {
|
|
82
|
+
return await plugins.smarthashWeb.sha256FromString(plugins.smartjson.stringify(stateArg));
|
|
65
83
|
};
|
|
84
|
+
const currentHash = await createStateHash(this.stateStore);
|
|
66
85
|
if (
|
|
67
|
-
this.stateStore &&
|
|
68
86
|
this.lastStateNotificationPayloadHash &&
|
|
69
|
-
|
|
87
|
+
currentHash === this.lastStateNotificationPayloadHash
|
|
70
88
|
) {
|
|
71
89
|
return;
|
|
72
90
|
} else {
|
|
73
|
-
this.lastStateNotificationPayloadHash =
|
|
91
|
+
this.lastStateNotificationPayloadHash = currentHash;
|
|
74
92
|
}
|
|
75
93
|
this.state.next(this.stateStore);
|
|
76
94
|
}
|
|
@@ -81,7 +99,11 @@ export class StatePart<TStatePartName, TStatePayload> {
|
|
|
81
99
|
*/
|
|
82
100
|
public notifyChangeCumulative() {
|
|
83
101
|
// TODO: check viability
|
|
84
|
-
setTimeout(() =>
|
|
102
|
+
setTimeout(async () => {
|
|
103
|
+
if (this.stateStore) {
|
|
104
|
+
await this.notifyChange();
|
|
105
|
+
}
|
|
106
|
+
}, 0);
|
|
85
107
|
}
|
|
86
108
|
|
|
87
109
|
/**
|
|
@@ -95,6 +117,7 @@ export class StatePart<TStatePartName, TStatePayload> {
|
|
|
95
117
|
}
|
|
96
118
|
const mapped = this.state.pipe(
|
|
97
119
|
plugins.smartrx.rxjs.ops.startWith(this.getState()),
|
|
120
|
+
plugins.smartrx.rxjs.ops.filter((stateArg): stateArg is TStatePayload => stateArg !== undefined),
|
|
98
121
|
plugins.smartrx.rxjs.ops.map((stateArg) => {
|
|
99
122
|
try {
|
|
100
123
|
return selectorFn(stateArg);
|