@push.rocks/smartstate 2.0.31 → 2.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/dist_ts/00_commitinfo_data.js +3 -3
- package/dist_ts/index.d.ts +2 -0
- package/dist_ts/index.js +3 -1
- package/dist_ts/smartstate.classes.computed.d.ts +7 -0
- package/dist_ts/smartstate.classes.computed.js +10 -0
- package/dist_ts/smartstate.classes.smartstate.d.ts +20 -10
- package/dist_ts/smartstate.classes.smartstate.js +55 -18
- package/dist_ts/smartstate.classes.stateaction.js +1 -2
- package/dist_ts/smartstate.classes.statepart.d.ts +35 -10
- package/dist_ts/smartstate.classes.statepart.js +166 -40
- package/dist_ts/smartstate.contextprovider.d.ts +16 -0
- package/dist_ts/smartstate.contextprovider.js +44 -0
- package/npmextra.json +8 -2
- package/package.json +9 -4
- package/readme.hints.md +47 -30
- package/readme.md +275 -202
- package/ts/00_commitinfo_data.ts +2 -2
- package/ts/index.ts +2 -0
- package/ts/smartstate.classes.computed.ts +16 -0
- package/ts/smartstate.classes.smartstate.ts +61 -18
- package/ts/smartstate.classes.stateaction.ts +0 -1
- package/ts/smartstate.classes.statepart.ts +196 -41
- package/ts/smartstate.contextprovider.ts +61 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smartstate',
|
|
6
|
-
version: '2.
|
|
7
|
-
description: 'A
|
|
6
|
+
version: '2.1.1',
|
|
7
|
+
description: 'A TypeScript-first reactive state management library with middleware, computed state, batching, persistence, and Web Component Context Protocol support.'
|
|
8
8
|
};
|
|
9
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDBKQUEwSjtDQUN4SyxDQUFBIn0=
|
package/dist_ts/index.d.ts
CHANGED
package/dist_ts/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export * from './smartstate.classes.smartstate.js';
|
|
2
2
|
export * from './smartstate.classes.statepart.js';
|
|
3
3
|
export * from './smartstate.classes.stateaction.js';
|
|
4
|
-
|
|
4
|
+
export * from './smartstate.classes.computed.js';
|
|
5
|
+
export * from './smartstate.contextprovider.js';
|
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLG9DQUFvQyxDQUFDO0FBQ25ELGNBQWMsbUNBQW1DLENBQUM7QUFDbEQsY0FBYyxxQ0FBcUMsQ0FBQztBQUNwRCxjQUFjLGtDQUFrQyxDQUFDO0FBQ2pELGNBQWMsaUNBQWlDLENBQUMifQ==
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as plugins from './smartstate.plugins.js';
|
|
2
|
+
import type { StatePart } from './smartstate.classes.statepart.js';
|
|
3
|
+
/**
|
|
4
|
+
* creates a computed observable derived from multiple state parts.
|
|
5
|
+
* the observable is lazy — it only subscribes to sources when subscribed to.
|
|
6
|
+
*/
|
|
7
|
+
export declare function computed<TResult>(sources: StatePart<any, any>[], computeFn: (...states: any[]) => TResult): plugins.smartrx.rxjs.Observable<TResult>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as plugins from './smartstate.plugins.js';
|
|
2
|
+
import { combineLatest, map } from 'rxjs';
|
|
3
|
+
/**
|
|
4
|
+
* creates a computed observable derived from multiple state parts.
|
|
5
|
+
* the observable is lazy — it only subscribes to sources when subscribed to.
|
|
6
|
+
*/
|
|
7
|
+
export function computed(sources, computeFn) {
|
|
8
|
+
return combineLatest(sources.map((sp) => sp.select())).pipe(map((states) => computeFn(...states)));
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzdGF0ZS5jbGFzc2VzLmNvbXB1dGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRzdGF0ZS5jbGFzc2VzLmNvbXB1dGVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0seUJBQXlCLENBQUM7QUFDbkQsT0FBTyxFQUFFLGFBQWEsRUFBRSxHQUFHLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFHMUM7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FDdEIsT0FBOEIsRUFDOUIsU0FBd0M7SUFFeEMsT0FBTyxhQUFhLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQ3pELEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FDTSxDQUFDO0FBQ2hELENBQUMifQ==
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as plugins from './smartstate.plugins.js';
|
|
1
2
|
import { StatePart } from './smartstate.classes.statepart.js';
|
|
2
3
|
export type TInitMode = 'soft' | 'mandatory' | 'force' | 'persistent';
|
|
3
4
|
/**
|
|
@@ -8,23 +9,32 @@ export declare class Smartstate<StatePartNameType extends string> {
|
|
|
8
9
|
[key in StatePartNameType]?: StatePart<StatePartNameType, any>;
|
|
9
10
|
};
|
|
10
11
|
private pendingStatePartCreation;
|
|
12
|
+
private batchDepth;
|
|
13
|
+
private isFlushing;
|
|
14
|
+
private pendingNotifications;
|
|
11
15
|
constructor();
|
|
16
|
+
/**
|
|
17
|
+
* whether state changes are currently being batched
|
|
18
|
+
*/
|
|
19
|
+
get isBatching(): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* registers a state part for deferred notification during a batch
|
|
22
|
+
*/
|
|
23
|
+
registerPendingNotification(statePart: StatePart<any, any>): void;
|
|
24
|
+
/**
|
|
25
|
+
* batches multiple state updates so subscribers are only notified once all updates complete
|
|
26
|
+
*/
|
|
27
|
+
batch(updateFn: () => Promise<void> | void): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* creates a computed observable derived from multiple state parts
|
|
30
|
+
*/
|
|
31
|
+
computed<TResult>(sources: StatePart<StatePartNameType, any>[], computeFn: (...states: any[]) => TResult): plugins.smartrx.rxjs.Observable<TResult>;
|
|
12
32
|
/**
|
|
13
33
|
* Allows getting and initializing a new statepart
|
|
14
|
-
* initMode === 'soft' (default) - returns existing statepart if exists, creates new if not
|
|
15
|
-
* initMode === 'mandatory' - requires statepart to not exist, fails if it does
|
|
16
|
-
* initMode === 'force' - always creates new statepart, overwriting any existing
|
|
17
|
-
* initMode === 'persistent' - like 'soft' but with webstore persistence
|
|
18
|
-
* @param statePartNameArg
|
|
19
|
-
* @param initialArg
|
|
20
|
-
* @param initMode
|
|
21
34
|
*/
|
|
22
35
|
getStatePart<PayloadType>(statePartNameArg: StatePartNameType, initialArg?: PayloadType, initMode?: TInitMode): Promise<StatePart<StatePartNameType, PayloadType>>;
|
|
23
36
|
/**
|
|
24
37
|
* Creates a statepart
|
|
25
|
-
* @param statePartName
|
|
26
|
-
* @param initialPayloadArg
|
|
27
|
-
* @param initMode
|
|
28
38
|
*/
|
|
29
39
|
private createStatePart;
|
|
30
40
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as plugins from './smartstate.plugins.js';
|
|
2
2
|
import { StatePart } from './smartstate.classes.statepart.js';
|
|
3
|
+
import { computed } from './smartstate.classes.computed.js';
|
|
3
4
|
/**
|
|
4
5
|
* Smartstate takes care of providing state
|
|
5
6
|
*/
|
|
@@ -7,16 +8,58 @@ export class Smartstate {
|
|
|
7
8
|
constructor() {
|
|
8
9
|
this.statePartMap = {};
|
|
9
10
|
this.pendingStatePartCreation = new Map();
|
|
11
|
+
// Batch support
|
|
12
|
+
this.batchDepth = 0;
|
|
13
|
+
this.isFlushing = false;
|
|
14
|
+
this.pendingNotifications = new Set();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* whether state changes are currently being batched
|
|
18
|
+
*/
|
|
19
|
+
get isBatching() {
|
|
20
|
+
return this.batchDepth > 0;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* registers a state part for deferred notification during a batch
|
|
24
|
+
*/
|
|
25
|
+
registerPendingNotification(statePart) {
|
|
26
|
+
this.pendingNotifications.add(statePart);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* batches multiple state updates so subscribers are only notified once all updates complete
|
|
30
|
+
*/
|
|
31
|
+
async batch(updateFn) {
|
|
32
|
+
this.batchDepth++;
|
|
33
|
+
try {
|
|
34
|
+
await updateFn();
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
this.batchDepth--;
|
|
38
|
+
if (this.batchDepth === 0 && !this.isFlushing) {
|
|
39
|
+
this.isFlushing = true;
|
|
40
|
+
try {
|
|
41
|
+
while (this.pendingNotifications.size > 0) {
|
|
42
|
+
const pending = [...this.pendingNotifications];
|
|
43
|
+
this.pendingNotifications.clear();
|
|
44
|
+
for (const sp of pending) {
|
|
45
|
+
await sp.notifyChange();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
this.isFlushing = false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* creates a computed observable derived from multiple state parts
|
|
57
|
+
*/
|
|
58
|
+
computed(sources, computeFn) {
|
|
59
|
+
return computed(sources, computeFn);
|
|
10
60
|
}
|
|
11
61
|
/**
|
|
12
62
|
* Allows getting and initializing a new statepart
|
|
13
|
-
* initMode === 'soft' (default) - returns existing statepart if exists, creates new if not
|
|
14
|
-
* initMode === 'mandatory' - requires statepart to not exist, fails if it does
|
|
15
|
-
* initMode === 'force' - always creates new statepart, overwriting any existing
|
|
16
|
-
* initMode === 'persistent' - like 'soft' but with webstore persistence
|
|
17
|
-
* @param statePartNameArg
|
|
18
|
-
* @param initialArg
|
|
19
|
-
* @param initMode
|
|
20
63
|
*/
|
|
21
64
|
async getStatePart(statePartNameArg, initialArg, initMode = 'soft') {
|
|
22
65
|
// Return pending creation if one exists to prevent duplicate state parts
|
|
@@ -30,18 +73,16 @@ export class Smartstate {
|
|
|
30
73
|
case 'mandatory':
|
|
31
74
|
throw new Error(`State part '${statePartNameArg}' already exists, but initMode is 'mandatory'`);
|
|
32
75
|
case 'force':
|
|
33
|
-
|
|
34
|
-
break;
|
|
76
|
+
existingStatePart.dispose();
|
|
77
|
+
break;
|
|
35
78
|
case 'soft':
|
|
36
79
|
case 'persistent':
|
|
37
80
|
default:
|
|
38
|
-
// Return existing state part
|
|
39
81
|
return existingStatePart;
|
|
40
82
|
}
|
|
41
83
|
}
|
|
42
84
|
else {
|
|
43
|
-
|
|
44
|
-
if (!initialArg) {
|
|
85
|
+
if (initialArg === undefined) {
|
|
45
86
|
throw new Error(`State part '${statePartNameArg}' does not exist and no initial state provided`);
|
|
46
87
|
}
|
|
47
88
|
}
|
|
@@ -57,9 +98,6 @@ export class Smartstate {
|
|
|
57
98
|
}
|
|
58
99
|
/**
|
|
59
100
|
* Creates a statepart
|
|
60
|
-
* @param statePartName
|
|
61
|
-
* @param initialPayloadArg
|
|
62
|
-
* @param initMode
|
|
63
101
|
*/
|
|
64
102
|
async createStatePart(statePartName, initialPayloadArg, initMode = 'soft') {
|
|
65
103
|
const newState = new StatePart(statePartName, initMode === 'persistent'
|
|
@@ -68,21 +106,20 @@ export class Smartstate {
|
|
|
68
106
|
storeName: statePartName,
|
|
69
107
|
}
|
|
70
108
|
: null);
|
|
109
|
+
newState.smartstateRef = this;
|
|
71
110
|
await newState.init();
|
|
72
111
|
const currentState = newState.getState();
|
|
73
112
|
if (initMode === 'persistent' && currentState !== undefined) {
|
|
74
|
-
// Persisted state exists - merge with defaults, persisted values take precedence
|
|
75
113
|
await newState.setState({
|
|
76
114
|
...initialPayloadArg,
|
|
77
115
|
...currentState,
|
|
78
116
|
});
|
|
79
117
|
}
|
|
80
118
|
else {
|
|
81
|
-
// No persisted state or non-persistent mode
|
|
82
119
|
await newState.setState(initialPayloadArg);
|
|
83
120
|
}
|
|
84
121
|
this.statePartMap[statePartName] = newState;
|
|
85
122
|
return newState;
|
|
86
123
|
}
|
|
87
124
|
}
|
|
88
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
125
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzdGF0ZS5jbGFzc2VzLnNtYXJ0c3RhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHN0YXRlLmNsYXNzZXMuc21hcnRzdGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHlCQUF5QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUM5RCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFJNUQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8sVUFBVTtJQVVyQjtRQVRPLGlCQUFZLEdBQXVFLEVBQUUsQ0FBQztRQUVyRiw2QkFBd0IsR0FBNEQsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUV0RyxnQkFBZ0I7UUFDUixlQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ2YsZUFBVSxHQUFHLEtBQUssQ0FBQztRQUNuQix5QkFBb0IsR0FBRyxJQUFJLEdBQUcsRUFBdUIsQ0FBQztJQUUvQyxDQUFDO0lBRWhCOztPQUVHO0lBQ0gsSUFBVyxVQUFVO1FBQ25CLE9BQU8sSUFBSSxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVEOztPQUVHO0lBQ0ksMkJBQTJCLENBQUMsU0FBOEI7UUFDL0QsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsS0FBSyxDQUFDLFFBQW9DO1FBQ3JELElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNsQixJQUFJLENBQUM7WUFDSCxNQUFNLFFBQVEsRUFBRSxDQUFDO1FBQ25CLENBQUM7Z0JBQVMsQ0FBQztZQUNULElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNsQixJQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFD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
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as plugins from './smartstate.plugins.js';
|
|
2
1
|
import { StatePart } from './smartstate.classes.statepart.js';
|
|
3
2
|
/**
|
|
4
3
|
* an actionmodifier for the state
|
|
@@ -12,4 +11,4 @@ export class StateAction {
|
|
|
12
11
|
return this.statePartRef.dispatchAction(this, payload);
|
|
13
12
|
}
|
|
14
13
|
}
|
|
15
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
14
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzdGF0ZS5jbGFzc2VzLnN0YXRlYWN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRzdGF0ZS5jbGFzc2VzLnN0YXRlYWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQU05RDs7R0FFRztBQUNILE1BQU0sT0FBTyxXQUFXO0lBQ3RCLFlBQ1MsWUFBaUMsRUFDakMsU0FBcUQ7UUFEckQsaUJBQVksR0FBWixZQUFZLENBQXFCO1FBQ2pDLGNBQVMsR0FBVCxTQUFTLENBQTRDO0lBQzNELENBQUM7SUFFRyxPQUFPLENBQUMsT0FBMkI7UUFDeEMsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDekQsQ0FBQztDQUNGIn0=
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import * as plugins from './smartstate.plugins.js';
|
|
2
2
|
import { StateAction, type IActionDef } from './smartstate.classes.stateaction.js';
|
|
3
|
+
import type { Smartstate } from './smartstate.classes.smartstate.js';
|
|
4
|
+
export type TMiddleware<TPayload> = (newState: TPayload, oldState: TPayload | undefined) => TPayload | Promise<TPayload>;
|
|
3
5
|
export declare class StatePart<TStatePartName, TStatePayload> {
|
|
4
6
|
name: TStatePartName;
|
|
5
7
|
state: plugins.smartrx.rxjs.Subject<TStatePayload>;
|
|
6
8
|
stateStore: TStatePayload | undefined;
|
|
9
|
+
smartstateRef?: Smartstate<any>;
|
|
7
10
|
private cumulativeDeferred;
|
|
11
|
+
private mutationQueue;
|
|
8
12
|
private pendingCumulativeNotification;
|
|
9
13
|
private webStoreOptions;
|
|
10
14
|
private webStore;
|
|
15
|
+
private middlewares;
|
|
16
|
+
private selectorCache;
|
|
17
|
+
private defaultSelectObservable;
|
|
11
18
|
constructor(nameArg: TStatePartName, webStoreOptionsArg?: plugins.webstore.IWebStoreOptions);
|
|
12
19
|
/**
|
|
13
20
|
* initializes the webstore
|
|
@@ -18,13 +25,21 @@ export declare class StatePart<TStatePartName, TStatePayload> {
|
|
|
18
25
|
*/
|
|
19
26
|
getState(): TStatePayload | undefined;
|
|
20
27
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
28
|
+
* adds a middleware that intercepts setState calls.
|
|
29
|
+
* middleware can transform the state or throw to reject it.
|
|
30
|
+
* returns a removal function.
|
|
31
|
+
*/
|
|
32
|
+
addMiddleware(middleware: TMiddleware<TStatePayload>): () => void;
|
|
33
|
+
/**
|
|
34
|
+
* sets the stateStore to the new state (serialized via mutation queue)
|
|
23
35
|
*/
|
|
24
36
|
setState(newStateArg: TStatePayload): Promise<TStatePayload>;
|
|
37
|
+
/**
|
|
38
|
+
* applies the state change (middleware → validate → persist → notify)
|
|
39
|
+
*/
|
|
40
|
+
private applyState;
|
|
25
41
|
/**
|
|
26
42
|
* Validates state structure - can be overridden for custom validation
|
|
27
|
-
* @param stateArg
|
|
28
43
|
*/
|
|
29
44
|
protected validateState(stateArg: any): stateArg is TStatePayload;
|
|
30
45
|
/**
|
|
@@ -33,13 +48,17 @@ export declare class StatePart<TStatePartName, TStatePayload> {
|
|
|
33
48
|
notifyChange(): Promise<void>;
|
|
34
49
|
private lastStateNotificationPayloadHash;
|
|
35
50
|
/**
|
|
36
|
-
* creates a cumulative notification by adding a change notification at the end of the call stack
|
|
51
|
+
* creates a cumulative notification by adding a change notification at the end of the call stack
|
|
37
52
|
*/
|
|
38
53
|
notifyChangeCumulative(): void;
|
|
39
54
|
/**
|
|
40
|
-
* selects a state or a substate
|
|
55
|
+
* selects a state or a substate.
|
|
56
|
+
* supports an optional AbortSignal for automatic unsubscription.
|
|
57
|
+
* memoizes observables by selector function reference.
|
|
41
58
|
*/
|
|
42
|
-
select<T = TStatePayload>(selectorFn?: (state: TStatePayload) => T
|
|
59
|
+
select<T = TStatePayload>(selectorFn?: (state: TStatePayload) => T, options?: {
|
|
60
|
+
signal?: AbortSignal;
|
|
61
|
+
}): plugins.smartrx.rxjs.Observable<T>;
|
|
43
62
|
/**
|
|
44
63
|
* creates an action capable of modifying the state
|
|
45
64
|
*/
|
|
@@ -49,13 +68,19 @@ export declare class StatePart<TStatePartName, TStatePayload> {
|
|
|
49
68
|
*/
|
|
50
69
|
dispatchAction<T>(stateAction: StateAction<TStatePayload, T>, actionPayload: T): Promise<TStatePayload>;
|
|
51
70
|
/**
|
|
52
|
-
* waits until a certain part of the state becomes available
|
|
53
|
-
*
|
|
54
|
-
* @param timeoutMs - optional timeout in milliseconds to prevent indefinite waiting
|
|
71
|
+
* waits until a certain part of the state becomes available.
|
|
72
|
+
* supports optional timeout and AbortSignal.
|
|
55
73
|
*/
|
|
56
|
-
waitUntilPresent<T = TStatePayload>(selectorFn?: (state: TStatePayload) => T,
|
|
74
|
+
waitUntilPresent<T = TStatePayload>(selectorFn?: (state: TStatePayload) => T, optionsOrTimeout?: number | {
|
|
75
|
+
timeoutMs?: number;
|
|
76
|
+
signal?: AbortSignal;
|
|
77
|
+
}): Promise<T>;
|
|
57
78
|
/**
|
|
58
79
|
* is executed
|
|
59
80
|
*/
|
|
60
81
|
stateSetup(funcArg: (statePartArg?: StatePart<any, TStatePayload>) => Promise<TStatePayload>): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* disposes the state part, completing the Subject and cleaning up resources
|
|
84
|
+
*/
|
|
85
|
+
dispose(): void;
|
|
61
86
|
}
|