@push.rocks/smartstate 2.0.31 → 2.1.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.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartstate',
6
- version: '2.0.31',
7
- description: 'A package for handling and managing state in applications.'
6
+ version: '2.1.0',
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLDREQUE0RDtDQUMxRSxDQUFBIn0=
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDBKQUEwSjtDQUN4SyxDQUFBIn0=
@@ -1,3 +1,5 @@
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
+ export * from './smartstate.classes.computed.js';
5
+ export * from './smartstate.contextprovider.js';
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
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLG9DQUFvQyxDQUFDO0FBQ25ELGNBQWMsbUNBQW1DLENBQUM7QUFDbEQsY0FBYyxxQ0FBcUMsQ0FBQyJ9
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,31 @@ 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 pendingNotifications;
11
14
  constructor();
15
+ /**
16
+ * whether state changes are currently being batched
17
+ */
18
+ get isBatching(): boolean;
19
+ /**
20
+ * registers a state part for deferred notification during a batch
21
+ */
22
+ registerPendingNotification(statePart: StatePart<any, any>): void;
23
+ /**
24
+ * batches multiple state updates so subscribers are only notified once all updates complete
25
+ */
26
+ batch(updateFn: () => Promise<void> | void): Promise<void>;
27
+ /**
28
+ * creates a computed observable derived from multiple state parts
29
+ */
30
+ computed<TResult>(sources: StatePart<StatePartNameType, any>[], computeFn: (...states: any[]) => TResult): plugins.smartrx.rxjs.Observable<TResult>;
12
31
  /**
13
32
  * 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
33
  */
22
34
  getStatePart<PayloadType>(statePartNameArg: StatePartNameType, initialArg?: PayloadType, initMode?: TInitMode): Promise<StatePart<StatePartNameType, PayloadType>>;
23
35
  /**
24
36
  * Creates a statepart
25
- * @param statePartName
26
- * @param initialPayloadArg
27
- * @param initMode
28
37
  */
29
38
  private createStatePart;
30
39
  }
@@ -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,49 @@ 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.pendingNotifications = new Set();
14
+ }
15
+ /**
16
+ * whether state changes are currently being batched
17
+ */
18
+ get isBatching() {
19
+ return this.batchDepth > 0;
20
+ }
21
+ /**
22
+ * registers a state part for deferred notification during a batch
23
+ */
24
+ registerPendingNotification(statePart) {
25
+ this.pendingNotifications.add(statePart);
26
+ }
27
+ /**
28
+ * batches multiple state updates so subscribers are only notified once all updates complete
29
+ */
30
+ async batch(updateFn) {
31
+ this.batchDepth++;
32
+ try {
33
+ await updateFn();
34
+ }
35
+ finally {
36
+ this.batchDepth--;
37
+ if (this.batchDepth === 0) {
38
+ const pending = [...this.pendingNotifications];
39
+ this.pendingNotifications.clear();
40
+ for (const sp of pending) {
41
+ await sp.notifyChange();
42
+ }
43
+ }
44
+ }
45
+ }
46
+ /**
47
+ * creates a computed observable derived from multiple state parts
48
+ */
49
+ computed(sources, computeFn) {
50
+ return computed(sources, computeFn);
10
51
  }
11
52
  /**
12
53
  * 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
54
  */
21
55
  async getStatePart(statePartNameArg, initialArg, initMode = 'soft') {
22
56
  // Return pending creation if one exists to prevent duplicate state parts
@@ -30,17 +64,14 @@ export class Smartstate {
30
64
  case 'mandatory':
31
65
  throw new Error(`State part '${statePartNameArg}' already exists, but initMode is 'mandatory'`);
32
66
  case 'force':
33
- // Force mode: create new state part
34
- break; // Fall through to creation
67
+ break;
35
68
  case 'soft':
36
69
  case 'persistent':
37
70
  default:
38
- // Return existing state part
39
71
  return existingStatePart;
40
72
  }
41
73
  }
42
74
  else {
43
- // State part doesn't exist
44
75
  if (!initialArg) {
45
76
  throw new Error(`State part '${statePartNameArg}' does not exist and no initial state provided`);
46
77
  }
@@ -57,9 +88,6 @@ export class Smartstate {
57
88
  }
58
89
  /**
59
90
  * Creates a statepart
60
- * @param statePartName
61
- * @param initialPayloadArg
62
- * @param initMode
63
91
  */
64
92
  async createStatePart(statePartName, initialPayloadArg, initMode = 'soft') {
65
93
  const newState = new StatePart(statePartName, initMode === 'persistent'
@@ -68,21 +96,20 @@ export class Smartstate {
68
96
  storeName: statePartName,
69
97
  }
70
98
  : null);
99
+ newState.smartstateRef = this;
71
100
  await newState.init();
72
101
  const currentState = newState.getState();
73
102
  if (initMode === 'persistent' && currentState !== undefined) {
74
- // Persisted state exists - merge with defaults, persisted values take precedence
75
103
  await newState.setState({
76
104
  ...initialPayloadArg,
77
105
  ...currentState,
78
106
  });
79
107
  }
80
108
  else {
81
- // No persisted state or non-persistent mode
82
109
  await newState.setState(initialPayloadArg);
83
110
  }
84
111
  this.statePartMap[statePartName] = newState;
85
112
  return newState;
86
113
  }
87
114
  }
88
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzdGF0ZS5jbGFzc2VzLnNtYXJ0c3RhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHN0YXRlLmNsYXNzZXMuc21hcnRzdGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHlCQUF5QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUk5RDs7R0FFRztBQUNILE1BQU0sT0FBTyxVQUFVO0lBS3JCO1FBSk8saUJBQVksR0FBdUUsRUFBRSxDQUFDO1FBRXJGLDZCQUF3QixHQUE0RCxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBRXZGLENBQUM7SUFFaEI7Ozs7Ozs7OztPQVNHO0lBQ0ksS0FBSyxDQUFDLFlBQVksQ0FDdkIsZ0JBQW1DLEVBQ25DLFVBQXdCLEVBQ3hCLFdBQXNCLE1BQU07UUFFNUIseUVBQXlFO1FBQ3pFLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUNwRSxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQ1osT0FBTyxPQUE2RCxDQUFDO1FBQ3ZFLENBQUM7UUFFRCxNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUU5RCxJQUFJLGlCQUFpQixFQUFFLENBQUM7WUFDdEIsUUFBUSxRQUFRLEVBQUUsQ0FBQztnQkFDakIsS0FBSyxXQUFXO29CQUNkLE1BQU0sSUFBSSxLQUFLLENBQ2IsZUFBZSxnQkFBZ0IsK0NBQStDLENBQy9FLENBQUM7Z0JBQ0osS0FBSyxPQUFPO29CQUNWLG9DQUFvQztvQkFDcEMsTUFBTSxDQUFDLDJCQUEyQjtnQkFDcEMsS0FBSyxNQUFNLENBQUM7Z0JBQ1osS0FBSyxZQUFZLENBQUM7Z0JBQ2xCO29CQUNFLDZCQUE2QjtvQkFDN0IsT0FBTyxpQkFBOEQsQ0FBQztZQUMxRSxDQUFDO1FBQ0gsQ0FBQzthQUFNLENBQUM7WUFDTiwyQkFBMkI7WUFDM0IsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUNoQixNQUFNLElBQUksS0FBSyxDQUNiLGVBQWUsZ0JBQWdCLGdEQUFnRCxDQUNoRixDQUFDO1lBQ0osQ0FBQztRQUNILENBQUM7UUFFRCxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFjLGdCQUFnQixFQUFFLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUNsRyxJQUFJLENBQUMsd0JBQXdCLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBRXJFLElBQUksQ0FBQztZQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sZUFBZSxDQUFDO1lBQ3JDLE9BQU8sTUFBTSxDQUFDO1FBQ2hCLENBQUM7Z0JBQVMsQ0FBQztZQUNULElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUN6RCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssS0FBSyxDQUFDLGVBQWUsQ0FDM0IsYUFBZ0MsRUFDaEMsaUJBQThCLEVBQzlCLFdBQXNCLE1BQU07UUFFNUIsTUFBTSxRQUFRLEdBQUcsSUFBSSxTQUFTLENBQzVCLGFBQWEsRUFDYixRQUFRLEtBQUssWUFBWTtZQUN2QixDQUFDLENBQUM7Z0JBQ0UsTUFBTSxFQUFFLFlBQVk7Z0JBQ3BCLFNBQVMsRUFBRSxhQUFhO2FBQ3pCO1lBQ0gsQ0FBQyxDQUFDLElBQUksQ0FDVCxDQUFDO1FBQ0YsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdEIsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBRXpDLElBQUksUUFBUSxLQUFLLFlBQVksSUFBSSxZQUFZLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDNUQsaUZBQWlGO1lBQ2pGLE1BQU0sUUFBUSxDQUFDLFFBQVEsQ0FBQztnQkFDdEIsR0FBRyxpQkFBaUI7Z0JBQ3BCLEdBQUcsWUFBWTthQUNoQixDQUFDLENBQUM7UUFDTCxDQUFDO2FBQU0sQ0FBQztZQUNOLDRDQUE0QztZQUM1QyxNQUFNLFFBQVEsQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUM3QyxDQUFDO1FBRUQsSUFBSSxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUMsR0FBRyxRQUFRLENBQUM7UUFDNUMsT0FBTyxRQUFRLENBQUM7SUFDbEIsQ0FBQztDQUNGIn0=
115
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzdGF0ZS5jbGFzc2VzLnNtYXJ0c3RhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHN0YXRlLmNsYXNzZXMuc21hcnRzdGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHlCQUF5QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUM5RCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFJNUQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8sVUFBVTtJQVNyQjtRQVJPLGlCQUFZLEdBQXVFLEVBQUUsQ0FBQztRQUVyRiw2QkFBd0IsR0FBNEQsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUV0RyxnQkFBZ0I7UUFDUixlQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ2YseUJBQW9CLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUM7SUFFL0MsQ0FBQztJQUVoQjs7T0FFRztJQUNILElBQVcsVUFBVTtRQUNuQixPQUFPLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDO0lBQzdCLENBQUM7SUFFRDs7T0FFRztJQUNJLDJCQUEyQixDQUFDLFNBQThCO1FBQy9ELElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLEtBQUssQ0FBQyxRQUFvQztRQUNyRCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDbEIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxRQUFRLEVBQUUsQ0FBQztRQUNuQixDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDbEIsSUFBSSxJQUFJLENBQUMsVUFBVSxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUMxQixNQUFNLE9BQU8sR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixD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
@@ -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;
8
11
  private pendingCumulativeNotification;
12
+ private pendingBatchNotification;
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
@@ -17,14 +24,18 @@ export declare class StatePart<TStatePartName, TStatePayload> {
17
24
  * gets the state from the state store
18
25
  */
19
26
  getState(): TStatePayload | undefined;
27
+ /**
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;
20
33
  /**
21
34
  * sets the stateStore to the new state
22
- * @param newStateArg
23
35
  */
24
36
  setState(newStateArg: TStatePayload): Promise<TStatePayload>;
25
37
  /**
26
38
  * Validates state structure - can be overridden for custom validation
27
- * @param stateArg
28
39
  */
29
40
  protected validateState(stateArg: any): stateArg is TStatePayload;
30
41
  /**
@@ -33,13 +44,17 @@ export declare class StatePart<TStatePartName, TStatePayload> {
33
44
  notifyChange(): Promise<void>;
34
45
  private lastStateNotificationPayloadHash;
35
46
  /**
36
- * creates a cumulative notification by adding a change notification at the end of the call stack;
47
+ * creates a cumulative notification by adding a change notification at the end of the call stack
37
48
  */
38
49
  notifyChangeCumulative(): void;
39
50
  /**
40
- * selects a state or a substate
51
+ * selects a state or a substate.
52
+ * supports an optional AbortSignal for automatic unsubscription.
53
+ * memoizes observables by selector function reference.
41
54
  */
42
- select<T = TStatePayload>(selectorFn?: (state: TStatePayload) => T): plugins.smartrx.rxjs.Observable<T>;
55
+ select<T = TStatePayload>(selectorFn?: (state: TStatePayload) => T, options?: {
56
+ signal?: AbortSignal;
57
+ }): plugins.smartrx.rxjs.Observable<T>;
43
58
  /**
44
59
  * creates an action capable of modifying the state
45
60
  */
@@ -49,11 +64,13 @@ export declare class StatePart<TStatePartName, TStatePayload> {
49
64
  */
50
65
  dispatchAction<T>(stateAction: StateAction<TStatePayload, T>, actionPayload: T): Promise<TStatePayload>;
51
66
  /**
52
- * waits until a certain part of the state becomes available
53
- * @param selectorFn
54
- * @param timeoutMs - optional timeout in milliseconds to prevent indefinite waiting
67
+ * waits until a certain part of the state becomes available.
68
+ * supports optional timeout and AbortSignal.
55
69
  */
56
- waitUntilPresent<T = TStatePayload>(selectorFn?: (state: TStatePayload) => T, timeoutMs?: number): Promise<T>;
70
+ waitUntilPresent<T = TStatePayload>(selectorFn?: (state: TStatePayload) => T, optionsOrTimeout?: number | {
71
+ timeoutMs?: number;
72
+ signal?: AbortSignal;
73
+ }): Promise<T>;
57
74
  /**
58
75
  * is executed
59
76
  */
@@ -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();
7
26
  this.pendingCumulativeNotification = null;
8
- this.webStore = null; // Add WebStore instance
27
+ this.pendingBatchNotification = false;
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
  }
@@ -32,31 +55,46 @@ export class StatePart {
32
55
  getState() {
33
56
  return this.stateStore;
34
57
  }
58
+ /**
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
+ }
35
72
  /**
36
73
  * sets the stateStore to the new state
37
- * @param newStateArg
38
74
  */
39
75
  async setState(newStateArg) {
76
+ // Run middleware chain
77
+ let processedState = newStateArg;
78
+ for (const mw of this.middlewares) {
79
+ processedState = await mw(processedState, this.stateStore);
80
+ }
40
81
  // Validate state structure
41
- if (!this.validateState(newStateArg)) {
82
+ if (!this.validateState(processedState)) {
42
83
  throw new Error(`Invalid state structure for state part '${this.name}'`);
43
84
  }
44
- // Save to WebStore first to ensure atomicity - if save fails, memory state remains unchanged
85
+ // Save to WebStore first to ensure atomicity
45
86
  if (this.webStore) {
46
- await this.webStore.set(String(this.name), newStateArg);
87
+ await this.webStore.set(String(this.name), processedState);
47
88
  }
48
89
  // Update in-memory state after successful persistence
49
- this.stateStore = newStateArg;
90
+ this.stateStore = processedState;
50
91
  await this.notifyChange();
51
92
  return this.stateStore;
52
93
  }
53
94
  /**
54
95
  * Validates state structure - can be overridden for custom validation
55
- * @param stateArg
56
96
  */
57
97
  validateState(stateArg) {
58
- // Basic validation - ensure state is not null/undefined
59
- // Subclasses can override for more specific validation
60
98
  return stateArg !== null && stateArg !== undefined;
61
99
  }
62
100
  /**
@@ -66,6 +104,12 @@ export class StatePart {
66
104
  if (!this.stateStore) {
67
105
  return;
68
106
  }
107
+ // If inside a batch, defer the notification
108
+ if (this.smartstateRef?.isBatching) {
109
+ this.pendingBatchNotification = true;
110
+ this.smartstateRef.registerPendingNotification(this);
111
+ return;
112
+ }
69
113
  const createStateHash = async (stateArg) => {
70
114
  return await plugins.smarthashWeb.sha256FromString(plugins.smartjson.stableOneWayStringify(stateArg));
71
115
  };
@@ -80,10 +124,9 @@ export class StatePart {
80
124
  this.state.next(this.stateStore);
81
125
  }
82
126
  /**
83
- * creates a cumulative notification by adding a change notification at the end of the call stack;
127
+ * creates a cumulative notification by adding a change notification at the end of the call stack
84
128
  */
85
129
  notifyChangeCumulative() {
86
- // Debounce: clear any pending notification
87
130
  if (this.pendingCumulativeNotification) {
88
131
  clearTimeout(this.pendingCumulativeNotification);
89
132
  }
@@ -95,22 +138,46 @@ export class StatePart {
95
138
  }, 0);
96
139
  }
97
140
  /**
98
- * selects a state or a substate
141
+ * selects a state or a substate.
142
+ * supports an optional AbortSignal for automatic unsubscription.
143
+ * memoizes observables by selector function reference.
99
144
  */
100
- select(selectorFn) {
101
- if (!selectorFn) {
102
- selectorFn = (state) => state;
145
+ select(selectorFn, options) {
146
+ const hasSignal = options?.signal != null;
147
+ // Check memoization cache (only for non-signal selects)
148
+ if (!hasSignal) {
149
+ if (!selectorFn) {
150
+ if (this.defaultSelectObservable) {
151
+ return this.defaultSelectObservable;
152
+ }
153
+ }
154
+ else if (this.selectorCache.has(selectorFn)) {
155
+ return this.selectorCache.get(selectorFn);
156
+ }
103
157
  }
104
- const 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) => {
158
+ const effectiveSelectorFn = selectorFn || ((state) => state);
159
+ 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
160
  try {
106
- return selectorFn(stateArg);
161
+ return effectiveSelectorFn(stateArg);
107
162
  }
108
163
  catch (e) {
109
164
  console.error(`Selector error in state part '${this.name}':`, e);
110
165
  return undefined;
111
166
  }
112
167
  }));
113
- return mapped;
168
+ if (hasSignal) {
169
+ mapped = mapped.pipe(takeUntil(fromAbortSignal(options.signal)));
170
+ return mapped;
171
+ }
172
+ // Apply shareReplay for caching and store in memo cache
173
+ const shared = mapped.pipe(shareReplay({ bufferSize: 1, refCount: true }));
174
+ if (!selectorFn) {
175
+ this.defaultSelectObservable = shared;
176
+ }
177
+ else {
178
+ this.selectorCache.set(selectorFn, shared);
179
+ }
180
+ return shared;
114
181
  }
115
182
  /**
116
183
  * creates an action capable of modifying the state
@@ -128,14 +195,27 @@ export class StatePart {
128
195
  return this.getState();
129
196
  }
130
197
  /**
131
- * waits until a certain part of the state becomes available
132
- * @param selectorFn
133
- * @param timeoutMs - optional timeout in milliseconds to prevent indefinite waiting
198
+ * waits until a certain part of the state becomes available.
199
+ * supports optional timeout and AbortSignal.
134
200
  */
135
- async waitUntilPresent(selectorFn, timeoutMs) {
201
+ async waitUntilPresent(selectorFn, optionsOrTimeout) {
202
+ // Parse backward-compatible args
203
+ let timeoutMs;
204
+ let signal;
205
+ if (typeof optionsOrTimeout === 'number') {
206
+ timeoutMs = optionsOrTimeout;
207
+ }
208
+ else if (optionsOrTimeout) {
209
+ timeoutMs = optionsOrTimeout.timeoutMs;
210
+ signal = optionsOrTimeout.signal;
211
+ }
136
212
  const done = plugins.smartpromise.defer();
137
213
  const selectedObservable = this.select(selectorFn);
138
214
  let resolved = false;
215
+ // Check if already aborted
216
+ if (signal?.aborted) {
217
+ throw new Error('Aborted');
218
+ }
139
219
  const subscription = selectedObservable.subscribe((value) => {
140
220
  if (value && !resolved) {
141
221
  resolved = true;
@@ -152,6 +232,19 @@ export class StatePart {
152
232
  }
153
233
  }, timeoutMs);
154
234
  }
235
+ // Handle abort signal
236
+ const abortHandler = signal ? () => {
237
+ if (!resolved) {
238
+ resolved = true;
239
+ subscription.unsubscribe();
240
+ if (timeoutId)
241
+ clearTimeout(timeoutId);
242
+ done.reject(new Error('Aborted'));
243
+ }
244
+ } : undefined;
245
+ if (signal && abortHandler) {
246
+ signal.addEventListener('abort', abortHandler);
247
+ }
155
248
  try {
156
249
  const result = await done.promise;
157
250
  return result;
@@ -160,6 +253,9 @@ export class StatePart {
160
253
  subscription.unsubscribe();
161
254
  if (timeoutId)
162
255
  clearTimeout(timeoutId);
256
+ if (signal && abortHandler) {
257
+ signal.removeEventListener('abort', abortHandler);
258
+ }
163
259
  }
164
260
  }
165
261
  /**
@@ -171,4 +267,4 @@ export class StatePart {
171
267
  await this.setState(await resultPromise);
172
268
  }
173
269
  }
174
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzdGF0ZS5jbGFzc2VzLnN0YXRlcGFydC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0c3RhdGUuY2xhc3Nlcy5zdGF0ZXBhcnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSx5QkFBeUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsV0FBVyxFQUFtQixNQUFNLHFDQUFxQyxDQUFDO0FBRW5GLE1BQU0sT0FBTyxTQUFTO0lBV3BCLFlBQVksT0FBdUIsRUFBRSxrQkFBc0Q7UUFUcEYsVUFBSyxHQUFHLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFpQixDQUFDO1FBRXpELHVCQUFrQixHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsZUFBZSxFQUFFLENBQUM7UUFFNUQsa0NBQTZCLEdBQXlDLElBQUksQ0FBQztRQUczRSxhQUFRLEdBQW9ELElBQUksQ0FBQyxDQUFDLHdCQUF3QjtRQUdoRyxJQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQztRQUVwQixzREFBc0Q7UUFDdEQsSUFBSSxrQkFBa0IsRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxlQUFlLEdBQUcsa0JBQWtCLENBQUM7UUFDNUMsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxJQUFJO1FBQ2YsSUFBSSxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFnQixJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDbkYsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzNCLE1BQU0sV0FBVyxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQy9E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
270
+ //# 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==