@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
|
@@ -1,13 +1,36 @@
|
|
|
1
1
|
import * as plugins from './smartstate.plugins.js';
|
|
2
|
+
import { Observable, shareReplay, takeUntil } from 'rxjs';
|
|
2
3
|
import { StateAction } from './smartstate.classes.stateaction.js';
|
|
4
|
+
/**
|
|
5
|
+
* creates an Observable that emits once when the given AbortSignal fires
|
|
6
|
+
*/
|
|
7
|
+
function fromAbortSignal(signal) {
|
|
8
|
+
return new Observable((subscriber) => {
|
|
9
|
+
if (signal.aborted) {
|
|
10
|
+
subscriber.next();
|
|
11
|
+
subscriber.complete();
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const handler = () => {
|
|
15
|
+
subscriber.next();
|
|
16
|
+
subscriber.complete();
|
|
17
|
+
};
|
|
18
|
+
signal.addEventListener('abort', handler);
|
|
19
|
+
return () => signal.removeEventListener('abort', handler);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
3
22
|
export class StatePart {
|
|
4
23
|
constructor(nameArg, webStoreOptionsArg) {
|
|
5
24
|
this.state = new plugins.smartrx.rxjs.Subject();
|
|
6
25
|
this.cumulativeDeferred = plugins.smartpromise.cumulativeDefer();
|
|
26
|
+
this.mutationQueue = Promise.resolve();
|
|
7
27
|
this.pendingCumulativeNotification = null;
|
|
8
|
-
this.webStore = null;
|
|
28
|
+
this.webStore = null;
|
|
29
|
+
this.middlewares = [];
|
|
30
|
+
// Selector memoization
|
|
31
|
+
this.selectorCache = new WeakMap();
|
|
32
|
+
this.defaultSelectObservable = null;
|
|
9
33
|
this.name = nameArg;
|
|
10
|
-
// Initialize WebStore if webStoreOptions are provided
|
|
11
34
|
if (webStoreOptionsArg) {
|
|
12
35
|
this.webStoreOptions = webStoreOptionsArg;
|
|
13
36
|
}
|
|
@@ -33,84 +56,139 @@ export class StatePart {
|
|
|
33
56
|
return this.stateStore;
|
|
34
57
|
}
|
|
35
58
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
59
|
+
* adds a middleware that intercepts setState calls.
|
|
60
|
+
* middleware can transform the state or throw to reject it.
|
|
61
|
+
* returns a removal function.
|
|
62
|
+
*/
|
|
63
|
+
addMiddleware(middleware) {
|
|
64
|
+
this.middlewares.push(middleware);
|
|
65
|
+
return () => {
|
|
66
|
+
const idx = this.middlewares.indexOf(middleware);
|
|
67
|
+
if (idx !== -1) {
|
|
68
|
+
this.middlewares.splice(idx, 1);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* sets the stateStore to the new state (serialized via mutation queue)
|
|
38
74
|
*/
|
|
39
75
|
async setState(newStateArg) {
|
|
76
|
+
return this.mutationQueue = this.mutationQueue.then(() => this.applyState(newStateArg), () => this.applyState(newStateArg));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* applies the state change (middleware → validate → persist → notify)
|
|
80
|
+
*/
|
|
81
|
+
async applyState(newStateArg) {
|
|
82
|
+
// Run middleware chain
|
|
83
|
+
let processedState = newStateArg;
|
|
84
|
+
for (const mw of this.middlewares) {
|
|
85
|
+
processedState = await mw(processedState, this.stateStore);
|
|
86
|
+
}
|
|
40
87
|
// Validate state structure
|
|
41
|
-
if (!this.validateState(
|
|
88
|
+
if (!this.validateState(processedState)) {
|
|
42
89
|
throw new Error(`Invalid state structure for state part '${this.name}'`);
|
|
43
90
|
}
|
|
44
|
-
// Save to WebStore first to ensure atomicity
|
|
91
|
+
// Save to WebStore first to ensure atomicity
|
|
45
92
|
if (this.webStore) {
|
|
46
|
-
await this.webStore.set(String(this.name),
|
|
93
|
+
await this.webStore.set(String(this.name), processedState);
|
|
47
94
|
}
|
|
48
95
|
// Update in-memory state after successful persistence
|
|
49
|
-
this.stateStore =
|
|
96
|
+
this.stateStore = processedState;
|
|
50
97
|
await this.notifyChange();
|
|
51
98
|
return this.stateStore;
|
|
52
99
|
}
|
|
53
100
|
/**
|
|
54
101
|
* Validates state structure - can be overridden for custom validation
|
|
55
|
-
* @param stateArg
|
|
56
102
|
*/
|
|
57
103
|
validateState(stateArg) {
|
|
58
|
-
// Basic validation - ensure state is not null/undefined
|
|
59
|
-
// Subclasses can override for more specific validation
|
|
60
104
|
return stateArg !== null && stateArg !== undefined;
|
|
61
105
|
}
|
|
62
106
|
/**
|
|
63
107
|
* notifies of a change on the state
|
|
64
108
|
*/
|
|
65
109
|
async notifyChange() {
|
|
66
|
-
|
|
110
|
+
const snapshot = this.stateStore;
|
|
111
|
+
if (snapshot === undefined) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
// If inside a batch, defer the notification
|
|
115
|
+
if (this.smartstateRef?.isBatching) {
|
|
116
|
+
this.smartstateRef.registerPendingNotification(this);
|
|
67
117
|
return;
|
|
68
118
|
}
|
|
69
119
|
const createStateHash = async (stateArg) => {
|
|
70
120
|
return await plugins.smarthashWeb.sha256FromString(plugins.smartjson.stableOneWayStringify(stateArg));
|
|
71
121
|
};
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
122
|
+
try {
|
|
123
|
+
const currentHash = await createStateHash(snapshot);
|
|
124
|
+
if (this.lastStateNotificationPayloadHash &&
|
|
125
|
+
currentHash === this.lastStateNotificationPayloadHash) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
78
128
|
this.lastStateNotificationPayloadHash = currentHash;
|
|
79
129
|
}
|
|
80
|
-
|
|
130
|
+
catch (err) {
|
|
131
|
+
console.error(`State hash computation failed for '${this.name}':`, err);
|
|
132
|
+
}
|
|
133
|
+
this.state.next(snapshot);
|
|
81
134
|
}
|
|
82
135
|
/**
|
|
83
|
-
* creates a cumulative notification by adding a change notification at the end of the call stack
|
|
136
|
+
* creates a cumulative notification by adding a change notification at the end of the call stack
|
|
84
137
|
*/
|
|
85
138
|
notifyChangeCumulative() {
|
|
86
|
-
// Debounce: clear any pending notification
|
|
87
139
|
if (this.pendingCumulativeNotification) {
|
|
88
140
|
clearTimeout(this.pendingCumulativeNotification);
|
|
89
141
|
}
|
|
90
|
-
this.pendingCumulativeNotification = setTimeout(
|
|
142
|
+
this.pendingCumulativeNotification = setTimeout(() => {
|
|
91
143
|
this.pendingCumulativeNotification = null;
|
|
92
|
-
if (this.stateStore) {
|
|
93
|
-
|
|
144
|
+
if (this.stateStore !== undefined) {
|
|
145
|
+
this.notifyChange().catch((err) => {
|
|
146
|
+
console.error(`notifyChangeCumulative failed for '${this.name}':`, err);
|
|
147
|
+
});
|
|
94
148
|
}
|
|
95
149
|
}, 0);
|
|
96
150
|
}
|
|
97
151
|
/**
|
|
98
|
-
* selects a state or a substate
|
|
152
|
+
* selects a state or a substate.
|
|
153
|
+
* supports an optional AbortSignal for automatic unsubscription.
|
|
154
|
+
* memoizes observables by selector function reference.
|
|
99
155
|
*/
|
|
100
|
-
select(selectorFn) {
|
|
101
|
-
|
|
102
|
-
|
|
156
|
+
select(selectorFn, options) {
|
|
157
|
+
const hasSignal = options?.signal != null;
|
|
158
|
+
// Check memoization cache (only for non-signal selects)
|
|
159
|
+
if (!hasSignal) {
|
|
160
|
+
if (!selectorFn) {
|
|
161
|
+
if (this.defaultSelectObservable) {
|
|
162
|
+
return this.defaultSelectObservable;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else if (this.selectorCache.has(selectorFn)) {
|
|
166
|
+
return this.selectorCache.get(selectorFn);
|
|
167
|
+
}
|
|
103
168
|
}
|
|
104
|
-
const
|
|
169
|
+
const effectiveSelectorFn = selectorFn || ((state) => state);
|
|
170
|
+
let mapped = this.state.pipe(plugins.smartrx.rxjs.ops.startWith(this.getState()), plugins.smartrx.rxjs.ops.filter((stateArg) => stateArg !== undefined), plugins.smartrx.rxjs.ops.map((stateArg) => {
|
|
105
171
|
try {
|
|
106
|
-
return
|
|
172
|
+
return effectiveSelectorFn(stateArg);
|
|
107
173
|
}
|
|
108
174
|
catch (e) {
|
|
109
175
|
console.error(`Selector error in state part '${this.name}':`, e);
|
|
110
176
|
return undefined;
|
|
111
177
|
}
|
|
112
178
|
}));
|
|
113
|
-
|
|
179
|
+
if (hasSignal) {
|
|
180
|
+
mapped = mapped.pipe(takeUntil(fromAbortSignal(options.signal)));
|
|
181
|
+
return mapped;
|
|
182
|
+
}
|
|
183
|
+
// Apply shareReplay for caching and store in memo cache
|
|
184
|
+
const shared = mapped.pipe(shareReplay({ bufferSize: 1, refCount: true }));
|
|
185
|
+
if (!selectorFn) {
|
|
186
|
+
this.defaultSelectObservable = shared;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
this.selectorCache.set(selectorFn, shared);
|
|
190
|
+
}
|
|
191
|
+
return shared;
|
|
114
192
|
}
|
|
115
193
|
/**
|
|
116
194
|
* creates an action capable of modifying the state
|
|
@@ -123,21 +201,38 @@ export class StatePart {
|
|
|
123
201
|
*/
|
|
124
202
|
async dispatchAction(stateAction, actionPayload) {
|
|
125
203
|
await this.cumulativeDeferred.promise;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
204
|
+
return this.mutationQueue = this.mutationQueue.then(async () => {
|
|
205
|
+
const newState = await stateAction.actionDef(this, actionPayload);
|
|
206
|
+
return this.applyState(newState);
|
|
207
|
+
}, async () => {
|
|
208
|
+
const newState = await stateAction.actionDef(this, actionPayload);
|
|
209
|
+
return this.applyState(newState);
|
|
210
|
+
});
|
|
129
211
|
}
|
|
130
212
|
/**
|
|
131
|
-
* waits until a certain part of the state becomes available
|
|
132
|
-
*
|
|
133
|
-
* @param timeoutMs - optional timeout in milliseconds to prevent indefinite waiting
|
|
213
|
+
* waits until a certain part of the state becomes available.
|
|
214
|
+
* supports optional timeout and AbortSignal.
|
|
134
215
|
*/
|
|
135
|
-
async waitUntilPresent(selectorFn,
|
|
216
|
+
async waitUntilPresent(selectorFn, optionsOrTimeout) {
|
|
217
|
+
// Parse backward-compatible args
|
|
218
|
+
let timeoutMs;
|
|
219
|
+
let signal;
|
|
220
|
+
if (typeof optionsOrTimeout === 'number') {
|
|
221
|
+
timeoutMs = optionsOrTimeout;
|
|
222
|
+
}
|
|
223
|
+
else if (optionsOrTimeout) {
|
|
224
|
+
timeoutMs = optionsOrTimeout.timeoutMs;
|
|
225
|
+
signal = optionsOrTimeout.signal;
|
|
226
|
+
}
|
|
136
227
|
const done = plugins.smartpromise.defer();
|
|
137
228
|
const selectedObservable = this.select(selectorFn);
|
|
138
229
|
let resolved = false;
|
|
230
|
+
// Check if already aborted
|
|
231
|
+
if (signal?.aborted) {
|
|
232
|
+
throw new Error('Aborted');
|
|
233
|
+
}
|
|
139
234
|
const subscription = selectedObservable.subscribe((value) => {
|
|
140
|
-
if (value && !resolved) {
|
|
235
|
+
if (value !== undefined && value !== null && !resolved) {
|
|
141
236
|
resolved = true;
|
|
142
237
|
done.resolve(value);
|
|
143
238
|
}
|
|
@@ -152,6 +247,19 @@ export class StatePart {
|
|
|
152
247
|
}
|
|
153
248
|
}, timeoutMs);
|
|
154
249
|
}
|
|
250
|
+
// Handle abort signal
|
|
251
|
+
const abortHandler = signal ? () => {
|
|
252
|
+
if (!resolved) {
|
|
253
|
+
resolved = true;
|
|
254
|
+
subscription.unsubscribe();
|
|
255
|
+
if (timeoutId)
|
|
256
|
+
clearTimeout(timeoutId);
|
|
257
|
+
done.reject(new Error('Aborted'));
|
|
258
|
+
}
|
|
259
|
+
} : undefined;
|
|
260
|
+
if (signal && abortHandler) {
|
|
261
|
+
signal.addEventListener('abort', abortHandler);
|
|
262
|
+
}
|
|
155
263
|
try {
|
|
156
264
|
const result = await done.promise;
|
|
157
265
|
return result;
|
|
@@ -160,6 +268,9 @@ export class StatePart {
|
|
|
160
268
|
subscription.unsubscribe();
|
|
161
269
|
if (timeoutId)
|
|
162
270
|
clearTimeout(timeoutId);
|
|
271
|
+
if (signal && abortHandler) {
|
|
272
|
+
signal.removeEventListener('abort', abortHandler);
|
|
273
|
+
}
|
|
163
274
|
}
|
|
164
275
|
}
|
|
165
276
|
/**
|
|
@@ -170,5 +281,20 @@ export class StatePart {
|
|
|
170
281
|
this.cumulativeDeferred.addPromise(resultPromise);
|
|
171
282
|
await this.setState(await resultPromise);
|
|
172
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* disposes the state part, completing the Subject and cleaning up resources
|
|
286
|
+
*/
|
|
287
|
+
dispose() {
|
|
288
|
+
this.state.complete();
|
|
289
|
+
if (this.pendingCumulativeNotification) {
|
|
290
|
+
clearTimeout(this.pendingCumulativeNotification);
|
|
291
|
+
this.pendingCumulativeNotification = null;
|
|
292
|
+
}
|
|
293
|
+
this.middlewares.length = 0;
|
|
294
|
+
this.selectorCache = new WeakMap();
|
|
295
|
+
this.defaultSelectObservable = null;
|
|
296
|
+
this.webStore = null;
|
|
297
|
+
this.smartstateRef = undefined;
|
|
298
|
+
}
|
|
173
299
|
}
|
|
174
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzdGF0ZS5jbGFzc2VzLnN0YXRlcGFydC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0c3RhdGUuY2xhc3Nlcy5zdGF0ZXBhcnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSx5QkFBeUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsV0FBVyxFQUFtQixNQUFNLHFDQUFxQyxDQUFDO0FBRW5GLE1BQU0sT0FBTyxTQUFTO0lBV3BCLFlBQVksT0FBdUIsRUFBRSxrQkFBc0Q7UUFUcEYsVUFBSyxHQUFHLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFpQixDQUFDO1FBRXpELHVCQUFrQixHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsZUFBZSxFQUFFLENBQUM7UUFFNUQsa0NBQTZCLEdBQXlDLElBQUksQ0FBQztRQUczRSxhQUFRLEdBQW9ELElBQUksQ0FBQyxDQUFDLHdCQUF3QjtRQUdoRyxJQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQztRQUVwQixzREFBc0Q7UUFDdEQsSUFBSSxrQkFBa0IsRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxlQUFlLEdBQUcsa0JBQWtCLENBQUM7UUFDNUMsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxJQUFJO1FBQ2YsSUFBSSxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFnQixJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDbkYsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzNCLE1BQU0sV0FBVyxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQy9E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
|
|
300
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzdGF0ZS5jbGFzc2VzLnN0YXRlcGFydC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0c3RhdGUuY2xhc3Nlcy5zdGF0ZXBhcnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSx5QkFBeUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDMUQsT0FBTyxFQUFFLFdBQVcsRUFBbUIsTUFBTSxxQ0FBcUMsQ0FBQztBQVFuRjs7R0FFRztBQUNILFNBQVMsZUFBZSxDQUFDLE1BQW1CO0lBQzFDLE9BQU8sSUFBSSxVQUFVLENBQU8sQ0FBQyxVQUFVLEVBQUUsRUFBRTtRQUN6QyxJQUFJLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNuQixVQUFVLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbEIsVUFBVSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3RCLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxPQUFPLEdBQUcsR0FBRyxFQUFFO1lBQ25CLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNsQixVQUFVLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDeEIsQ0FBQyxDQUFDO1FBQ0YsTUFBTSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUMxQyxPQUFPLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDNUQsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsTUFBTSxPQUFPLFNBQVM7SUFtQnBCLFlBQVksT0FBdUIsRUFBRSxrQkFBc0Q7UUFqQnBGLFVBQUssR0FBRyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBaUIsQ0FBQztRQUd6RCx1QkFBa0IsR0FBRyxPQUFPLENBQUMs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
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { StatePart } from './smartstate.classes.statepart.js';
|
|
2
|
+
export interface IContextProviderOptions<TPayload> {
|
|
3
|
+
/** the context key (compared by strict equality) */
|
|
4
|
+
context: unknown;
|
|
5
|
+
/** the state part to provide */
|
|
6
|
+
statePart: StatePart<any, TPayload>;
|
|
7
|
+
/** optional selector to provide a derived value instead of the full state */
|
|
8
|
+
selectorFn?: (state: TPayload) => any;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* attaches a Context Protocol provider to an HTML element.
|
|
12
|
+
* listens for `context-request` events and responds with the state part's value.
|
|
13
|
+
* if subscribe=true, retains the callback and invokes it on every state change.
|
|
14
|
+
* returns a cleanup function that removes the listener and unsubscribes.
|
|
15
|
+
*/
|
|
16
|
+
export declare function attachContextProvider<TPayload>(element: HTMLElement, options: IContextProviderOptions<TPayload>): () => void;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* attaches a Context Protocol provider to an HTML element.
|
|
3
|
+
* listens for `context-request` events and responds with the state part's value.
|
|
4
|
+
* if subscribe=true, retains the callback and invokes it on every state change.
|
|
5
|
+
* returns a cleanup function that removes the listener and unsubscribes.
|
|
6
|
+
*/
|
|
7
|
+
export function attachContextProvider(element, options) {
|
|
8
|
+
const { context, statePart, selectorFn } = options;
|
|
9
|
+
const subscribers = new Set();
|
|
10
|
+
const subscription = statePart.select(selectorFn).subscribe((value) => {
|
|
11
|
+
for (const cb of subscribers) {
|
|
12
|
+
cb(value);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
const getValue = () => {
|
|
16
|
+
const state = statePart.getState();
|
|
17
|
+
if (state === undefined)
|
|
18
|
+
return undefined;
|
|
19
|
+
return selectorFn ? selectorFn(state) : state;
|
|
20
|
+
};
|
|
21
|
+
const handler = (event) => {
|
|
22
|
+
const e = event;
|
|
23
|
+
const detail = e.detail;
|
|
24
|
+
if (!detail || detail.context !== context)
|
|
25
|
+
return;
|
|
26
|
+
e.stopPropagation();
|
|
27
|
+
if (detail.subscribe) {
|
|
28
|
+
const cb = detail.callback;
|
|
29
|
+
subscribers.add(cb);
|
|
30
|
+
const unsubscribe = () => subscribers.delete(cb);
|
|
31
|
+
cb(getValue(), unsubscribe);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
detail.callback(getValue());
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
element.addEventListener('context-request', handler);
|
|
38
|
+
return () => {
|
|
39
|
+
element.removeEventListener('context-request', handler);
|
|
40
|
+
subscription.unsubscribe();
|
|
41
|
+
subscribers.clear();
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzdGF0ZS5jb250ZXh0cHJvdmlkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHN0YXRlLmNvbnRleHRwcm92aWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFXQTs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxxQkFBcUIsQ0FDbkMsT0FBb0IsRUFDcEIsT0FBMEM7SUFFMUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLEdBQUcsT0FBTyxDQUFDO0lBQ25ELE1BQU0sV0FBVyxHQUFHLElBQUksR0FBRyxFQUFrRCxDQUFDO0lBRTlFLE1BQU0sWUFBWSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7UUFDcEUsS0FBSyxNQUFNLEVBQUUsSUFBSSxXQUFXLEVBQUUsQ0FBQztZQUM3QixFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDWixDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7SUFFSCxNQUFNLFFBQVEsR0FBRyxHQUFRLEVBQUU7UUFDekIsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ25DLElBQUksS0FBSyxLQUFLLFNBQVM7WUFBRSxPQUFPLFNBQVMsQ0FBQztRQUMxQyxPQUFPLFVBQVUsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7SUFDaEQsQ0FBQyxDQUFDO0lBRUYsTUFBTSxPQUFPLEdBQUcsQ0FBQyxLQUFZLEVBQUUsRUFBRTtRQUMvQixNQUFNLENBQUMsR0FBRyxLQUFvQixDQUFDO1FBQy9CLE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFDeEIsSUFBSSxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUMsT0FBTyxLQUFLLE9BQU87WUFBRSxPQUFPO1FBRWxELENBQUMsQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUVwQixJQUFJLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNyQixNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDO1lBQzNCLFdBQVcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDcEIsTUFBTSxXQUFXLEdBQUcsR0FBRyxFQUFFLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNqRCxFQUFFLENBQUMsUUFBUSxFQUFFLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDOUIsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDOUIsQ0FBQztJQUNILENBQUMsQ0FBQztJQUVGLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxpQkFBaUIsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUVyRCxPQUFPLEdBQUcsRUFBRTtRQUNWLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxpQkFBaUIsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUN4RCxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDM0IsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3RCLENBQUMsQ0FBQztBQUNKLENBQUMifQ==
|
package/npmextra.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"githost": "code.foss.global",
|
|
17
17
|
"gitscope": "push.rocks",
|
|
18
18
|
"gitrepo": "smartstate",
|
|
19
|
-
"description": "A
|
|
19
|
+
"description": "A TypeScript-first reactive state management library with middleware, computed state, batching, persistence, and Web Component Context Protocol support.",
|
|
20
20
|
"npmPackagename": "@push.rocks/smartstate",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"keywords": [
|
|
@@ -29,7 +29,13 @@
|
|
|
29
29
|
"state selection",
|
|
30
30
|
"state notification",
|
|
31
31
|
"asynchronous state",
|
|
32
|
-
"cumulative notification"
|
|
32
|
+
"cumulative notification",
|
|
33
|
+
"middleware",
|
|
34
|
+
"computed state",
|
|
35
|
+
"batch updates",
|
|
36
|
+
"context protocol",
|
|
37
|
+
"web components",
|
|
38
|
+
"AbortSignal"
|
|
33
39
|
]
|
|
34
40
|
},
|
|
35
41
|
"release": {
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@push.rocks/smartstate",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "A
|
|
5
|
+
"description": "A TypeScript-first reactive state management library with middleware, computed state, batching, persistence, and Web Component Context Protocol support.",
|
|
6
6
|
"main": "dist_ts/index.js",
|
|
7
7
|
"typings": "dist_ts/index.d.ts",
|
|
8
8
|
"type": "module",
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
"@types/node": "^25.3.2"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@push.rocks/lik": "^6.2.2",
|
|
26
25
|
"@push.rocks/smarthash": "^3.2.6",
|
|
27
26
|
"@push.rocks/smartjson": "^6.0.0",
|
|
28
27
|
"@push.rocks/smartpromise": "^4.2.3",
|
|
@@ -54,7 +53,13 @@
|
|
|
54
53
|
"state selection",
|
|
55
54
|
"state notification",
|
|
56
55
|
"asynchronous state",
|
|
57
|
-
"cumulative notification"
|
|
56
|
+
"cumulative notification",
|
|
57
|
+
"middleware",
|
|
58
|
+
"computed state",
|
|
59
|
+
"batch updates",
|
|
60
|
+
"context protocol",
|
|
61
|
+
"web components",
|
|
62
|
+
"AbortSignal"
|
|
58
63
|
],
|
|
59
64
|
"homepage": "https://code.foss.global/push.rocks/smartstate",
|
|
60
65
|
"repository": {
|
package/readme.hints.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Smartstate Implementation Notes
|
|
2
2
|
|
|
3
|
-
## Current API (as of v2.0.
|
|
3
|
+
## Current API (as of v2.0.31)
|
|
4
4
|
|
|
5
5
|
### State Part Initialization
|
|
6
6
|
- State parts can be created with different init modes: 'soft' (default), 'mandatory', 'force', 'persistent'
|
|
@@ -8,53 +8,70 @@
|
|
|
8
8
|
- 'mandatory' - requires state part to not exist, fails if it does
|
|
9
9
|
- 'force' - always creates new state part, overwriting any existing
|
|
10
10
|
- 'persistent' - like 'soft' but with WebStore persistence (IndexedDB)
|
|
11
|
-
- Persistent mode automatically calls init() internally
|
|
11
|
+
- Persistent mode automatically calls init() internally
|
|
12
12
|
- State merge order fixed: initial state takes precedence over stored state
|
|
13
13
|
|
|
14
14
|
### Actions
|
|
15
15
|
- Actions are created with `createAction()` method
|
|
16
|
-
- Two ways to dispatch
|
|
17
|
-
|
|
18
|
-
2. `await statePart.dispatchAction(stateAction, payload)` - returns Promise<TStatePayload>
|
|
19
|
-
- Both methods return the same Promise, providing flexibility in usage
|
|
16
|
+
- Two ways to dispatch: `stateAction.trigger(payload)` or `statePart.dispatchAction(stateAction, payload)`
|
|
17
|
+
- Both return Promise<TStatePayload>
|
|
20
18
|
|
|
21
19
|
### State Management Methods
|
|
22
|
-
- `select()` - returns Observable
|
|
23
|
-
- `waitUntilPresent()` - waits for
|
|
20
|
+
- `select(fn?, { signal? })` - returns Observable, memoized by selector fn ref, supports AbortSignal
|
|
21
|
+
- `waitUntilPresent(fn?, number | { timeoutMs?, signal? })` - waits for state condition, backward compat with number arg
|
|
24
22
|
- `stateSetup()` - async state initialization with cumulative defer
|
|
25
23
|
- `notifyChangeCumulative()` - defers notification to end of call stack
|
|
26
24
|
- `getState()` - returns current state or undefined
|
|
27
|
-
- `setState()` -
|
|
25
|
+
- `setState()` - runs middleware, validates, persists, notifies
|
|
26
|
+
- `addMiddleware(fn)` - intercepts setState, returns removal function
|
|
27
|
+
|
|
28
|
+
### Middleware
|
|
29
|
+
- Type: `(newState, oldState) => newState | Promise<newState>`
|
|
30
|
+
- Runs sequentially in insertion order before validation/persistence
|
|
31
|
+
- Throw to reject state changes (atomic — state unchanged on error)
|
|
32
|
+
- Does NOT run during initial createStatePart() hydration
|
|
33
|
+
|
|
34
|
+
### Selector Memoization
|
|
35
|
+
- Uses WeakMap<Function, Observable> for fn-keyed cache
|
|
36
|
+
- `defaultSelectObservable` for no-arg select()
|
|
37
|
+
- Wrapped in `shareReplay({ bufferSize: 1, refCount: true })`
|
|
38
|
+
- NOT cached when AbortSignal is provided
|
|
39
|
+
|
|
40
|
+
### Batch Updates
|
|
41
|
+
- `smartstate.batch(async () => {...})` — defers notifications until batch completes
|
|
42
|
+
- Supports nesting — only flushes at outermost level
|
|
43
|
+
- StatePart has `smartstateRef` set by `createStatePart()` for batch awareness
|
|
44
|
+
- State parts created via `new StatePart()` directly work without batching
|
|
45
|
+
|
|
46
|
+
### Computed State
|
|
47
|
+
- `computed(sources, fn)` — standalone function using `combineLatest` + `map`
|
|
48
|
+
- Also available as `smartstate.computed(sources, fn)`
|
|
49
|
+
- Lazy — only subscribes when subscribed to
|
|
50
|
+
|
|
51
|
+
### Context Protocol Bridge
|
|
52
|
+
- `attachContextProvider(element, { context, statePart, selectorFn? })` — returns cleanup fn
|
|
53
|
+
- Listens for `context-request` CustomEvent on element
|
|
54
|
+
- Supports one-shot and subscription modes
|
|
55
|
+
- Works with Lit @consume(), FAST, or any Context Protocol consumer
|
|
28
56
|
|
|
29
57
|
### State Hash Detection
|
|
30
58
|
- Uses SHA256 hash to detect actual state changes
|
|
31
|
-
-
|
|
59
|
+
- Hash comparison properly awaits async hash calculation
|
|
32
60
|
- Prevents duplicate notifications for identical state values
|
|
33
|
-
- `notifyChange()` is now async to support proper hash comparison
|
|
34
61
|
|
|
35
62
|
### State Validation
|
|
36
63
|
- Basic validation ensures state is not null/undefined
|
|
37
|
-
- `validateState()`
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
## Recent Fixes (v2.0.24+)
|
|
46
|
-
1. Fixed state hash bug - now properly compares hash values instead of promises
|
|
47
|
-
2. Fixed state initialization merge order - initial state now takes precedence
|
|
48
|
-
3. Ensured stateStore is properly typed as potentially undefined
|
|
49
|
-
4. Simplified init mode logic with clear behavior for each mode
|
|
50
|
-
5. Added state validation with extensible validateState() method
|
|
51
|
-
6. Made notifyChange() async to support proper hash comparison
|
|
52
|
-
7. Updated select() to filter undefined states
|
|
53
|
-
|
|
54
|
-
## Dependency Versions (v2.0.30)
|
|
64
|
+
- `validateState()` can be overridden in subclasses
|
|
65
|
+
|
|
66
|
+
### Key Notes
|
|
67
|
+
- `smartstateRef` creates circular ref between StatePart and Smartstate
|
|
68
|
+
- Use `===` not deep equality for StatePart comparison in tests
|
|
69
|
+
- Direct rxjs imports used for: Observable, shareReplay, takeUntil, combineLatest, map
|
|
70
|
+
|
|
71
|
+
## Dependency Versions (v2.0.31)
|
|
55
72
|
- @git.zone/tsbuild: ^4.1.2
|
|
56
73
|
- @git.zone/tsbundle: ^2.9.0
|
|
57
74
|
- @git.zone/tsrun: ^2.0.1
|
|
58
75
|
- @git.zone/tstest: ^3.1.8
|
|
59
76
|
- @push.rocks/smartjson: ^6.0.0
|
|
60
|
-
- @types/node: ^25.3.2
|
|
77
|
+
- @types/node: ^25.3.2
|