@alwatr/signal 9.26.0 → 9.30.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.
Files changed (52) hide show
  1. package/README.md +197 -603
  2. package/dist/core/channel-signal.d.ts +12 -53
  3. package/dist/core/channel-signal.d.ts.map +1 -1
  4. package/dist/core/computed-signal.d.ts +19 -33
  5. package/dist/core/computed-signal.d.ts.map +1 -1
  6. package/dist/core/derived-signal.d.ts +71 -0
  7. package/dist/core/derived-signal.d.ts.map +1 -0
  8. package/dist/core/effect-signal.d.ts +15 -1
  9. package/dist/core/effect-signal.d.ts.map +1 -1
  10. package/dist/core/event-signal.d.ts +11 -4
  11. package/dist/core/event-signal.d.ts.map +1 -1
  12. package/dist/core/persistent-state-signal.d.ts +21 -2
  13. package/dist/core/persistent-state-signal.d.ts.map +1 -1
  14. package/dist/core/session-state-signal.d.ts +19 -2
  15. package/dist/core/session-state-signal.d.ts.map +1 -1
  16. package/dist/core/signal-base.d.ts +58 -38
  17. package/dist/core/signal-base.d.ts.map +1 -1
  18. package/dist/core/state-signal.d.ts +33 -14
  19. package/dist/core/state-signal.d.ts.map +1 -1
  20. package/dist/creators/channel.d.ts +1 -1
  21. package/dist/creators/channel.d.ts.map +1 -1
  22. package/dist/creators/derived.d.ts +31 -0
  23. package/dist/creators/derived.d.ts.map +1 -0
  24. package/dist/main.d.ts +2 -1
  25. package/dist/main.d.ts.map +1 -1
  26. package/dist/main.js +3 -3
  27. package/dist/main.js.map +16 -15
  28. package/dist/operators/debounce.d.ts +2 -3
  29. package/dist/operators/debounce.d.ts.map +1 -1
  30. package/dist/operators/filter.d.ts +14 -13
  31. package/dist/operators/filter.d.ts.map +1 -1
  32. package/dist/type.d.ts +68 -3
  33. package/dist/type.d.ts.map +1 -1
  34. package/package.json +6 -6
  35. package/src/core/channel-signal.ts +25 -68
  36. package/src/core/computed-signal.ts +50 -74
  37. package/src/core/derived-signal.ts +166 -0
  38. package/src/core/effect-signal.ts +23 -11
  39. package/src/core/event-signal.ts +14 -9
  40. package/src/core/persistent-state-signal.ts +21 -4
  41. package/src/core/session-state-signal.ts +19 -4
  42. package/src/core/signal-base.ts +98 -61
  43. package/src/core/state-signal.ts +48 -29
  44. package/src/creators/channel.ts +1 -2
  45. package/src/creators/derived.ts +34 -0
  46. package/src/main.ts +2 -1
  47. package/src/operators/debounce.ts +13 -23
  48. package/src/operators/filter.ts +20 -26
  49. package/src/type.ts +71 -3
  50. package/dist/operators/map.d.ts +0 -36
  51. package/dist/operators/map.d.ts.map +0 -1
  52. package/src/operators/map.ts +0 -48
@@ -1,100 +1,120 @@
1
1
  import type { Observer_, SubscribeOptions, SubscribeResult, ListenerCallback, SignalConfig } from '../type.js';
2
2
  import type { AlwatrLogger } from '@alwatr/logger';
3
3
  /**
4
- * An abstract base class for signal implementations.
5
- * It provides the core functionality for managing subscriptions (observers).
4
+ * An abstract base class for all signal implementations in the `@alwatr/signal` package.
6
5
  *
7
- * @template T The type of data that the signal holds or dispatches.
6
+ * It provides core subscription management capabilities, including priority observer queues,
7
+ * microtask/macrotask-friendly updates, type-safe unsubscribes, async promise resolution via `untilNext`,
8
+ * and safe destruction lifecycles to prevent memory leaks.
9
+ *
10
+ * @template T The type of data that the signal holds, dispatches, or streams.
8
11
  */
9
12
  export declare abstract class SignalBase<T> {
10
13
  protected config_: SignalConfig;
11
14
  /**
12
15
  * The unique identifier for this signal instance.
13
- * Useful for debugging and logging.
16
+ * Highly useful for debugging, filtering logs, and tracing data flows.
14
17
  */
15
18
  readonly name: string;
16
19
  /**
17
20
  * The logger instance for this signal.
21
+ * Custom scoped logger based on the signal name and type.
22
+ *
18
23
  * @protected
19
24
  */
20
25
  protected abstract logger_: AlwatrLogger;
21
26
  /**
22
- * The list of observers (listeners) subscribed to this signal.
27
+ * High-priority observers that are executed first during notifications.
28
+ * Allocated lazily upon the first priority subscription to guard heap memory.
29
+ *
30
+ * @protected
31
+ */
32
+ protected priorityObservers_?: Set<Observer_<T>>;
33
+ /**
34
+ * Standard-priority observers executed after priority observers.
35
+ * Allocated lazily upon the first standard subscription to guard heap memory.
36
+ *
23
37
  * @protected
24
38
  */
25
- protected readonly priorityObservers_: Set<Observer_<T>>;
26
- protected readonly observers_: Set<Observer_<T>>;
39
+ protected observers_?: Set<Observer_<T>>;
27
40
  /**
28
- * A flag indicating whether the signal has been destroyed.
41
+ * Internal flag representing whether the signal has been destroyed.
42
+ *
29
43
  * @private
30
44
  */
31
45
  private isDestroyed__;
32
46
  /**
33
47
  * Indicates whether the signal has been destroyed.
34
- * A destroyed signal cannot be used and will throw an error if interacted with.
48
+ * A destroyed signal cannot be subscribed to or dispatched to.
35
49
  *
36
50
  * @returns `true` if the signal is destroyed, `false` otherwise.
37
51
  */
38
52
  get isDestroyed(): boolean;
53
+ /**
54
+ * Creates a new instance of the signal base.
55
+ *
56
+ * @param config_ Configuration options including the unique signal name and cleanup hooks.
57
+ */
39
58
  constructor(config_: SignalConfig);
40
59
  /**
41
- * Removes a specific observer from the observers list.
60
+ * Removes a specific observer from both the standard and priority observer queues.
42
61
  *
43
- * @param observer The observer instance to remove.
62
+ * @param observer The observer wrapper object containing the callback and options to remove.
44
63
  * @protected
45
64
  */
46
65
  protected removeObserver_(observer: Observer_<T>): void;
47
66
  /**
48
67
  * Subscribes a listener function to this signal.
49
68
  *
50
- * The listener will be called whenever the signal is notified (e.g., when `dispatch` or `set` is called).
69
+ * The listener will be called whenever the signal notifies its observers.
51
70
  *
52
- * @param callback The function to be called when the signal is dispatched.
53
- * @param options Subscription options to customize the behavior (e.g., `once`, `priority`).
54
- * @returns A `SubscribeResult` object with an `unsubscribe` method to remove the listener.
71
+ * @param callback The function to invoke when the signal dispatches a new value.
72
+ * @param options Custom options to control priority, immediate callback, or single execution.
73
+ * @returns An object with an `unsubscribe` method to remove the subscription.
55
74
  */
56
75
  subscribe(callback: ListenerCallback<T>, options?: SubscribeOptions): SubscribeResult;
57
76
  /**
58
- * Notifies all registered observers about a new value.
59
- *
60
- * This method iterates through a snapshot of the current observers to prevent issues
61
- * with subscriptions changing during notification (e.g., an observer unsubscribing itself).
77
+ * Notifies all registered priority and standard observers with the given value.
78
+ * Iterates synchronously over current queues.
62
79
  *
63
- * @param value The new value to notify observers about.
80
+ * @param value The value to pass to each observer's callback.
64
81
  * @protected
65
82
  */
66
83
  protected notify_(value: T): void;
67
84
  /**
68
- * Executes a given observer's callback with the provided value, handling both synchronous and asynchronous callbacks.
85
+ * Executes a single observer's callback, handles auto-unsubscribing for `once` listeners,
86
+ * and wraps execution in a try-catch block to prevent observer exceptions from crashing the signal.
87
+ *
88
+ * @param observer The observer descriptor to execute.
89
+ * @param value The value to supply to the observer's callback.
90
+ * @private
69
91
  */
70
92
  private executeObserver__;
71
- private pendingRejects__;
72
93
  /**
73
- * Returns a Promise that resolves with the next value dispatched by the signal.
74
- * This provides an elegant way to wait for a single, future event using `async/await`.
94
+ * Holds the promise rejection functions of any pending `untilNext` invocations
95
+ * to reject them if the signal is destroyed.
75
96
  *
76
- * @returns A Promise that resolves with the next dispatched value.
97
+ * @private
98
+ */
99
+ private pendingRejects__?;
100
+ /**
101
+ * Returns a Promise that resolves with the next value/payload dispatched by the signal.
102
+ * Use this for async orchestration (e.g. `await signal.untilNext()`).
77
103
  *
78
- * @example
79
- * async function onButtonClick() {
80
- * console.log('Waiting for the next signal...');
81
- * const nextValue = await mySignal.untilNext();
82
- * console.log('Signal received:', nextValue);
83
- * }
104
+ * @returns A Promise that resolves with the next value dispatched by the signal.
84
105
  */
85
106
  untilNext(): Promise<T>;
86
107
  /**
87
- * Destroys the signal, clearing all its listeners and making it inactive.
88
- *
89
- * After destruction, any interaction with the signal (like `subscribe` or `untilNext`)
90
- * will throw an error. This is crucial for preventing memory leaks by allowing
91
- * garbage collection of the signal and its observers.
108
+ * Permanently destroys the signal instance.
109
+ * Clears all observers, rejects pending `untilNext` promises with a 'signal_destroyed' error,
110
+ * invokes the optional `onDestroy` config hook, and breaks internal references to facilitate GC.
92
111
  */
93
112
  destroy(): void;
94
113
  /**
95
- * Throws an error if the signal has been destroyed.
96
- * This is a safeguard to prevent interaction with a defunct signal.
114
+ * Checks if the signal has been destroyed. If so, throws an error and logs an accident.
115
+ *
97
116
  * @protected
117
+ * @throws {Error} If the signal has been destroyed.
98
118
  */
99
119
  protected checkDestroyed_(): void;
100
120
  }
@@ -1 +1 @@
1
- {"version":3,"file":"signal-base.d.ts","sourceRoot":"","sources":["../../src/core/signal-base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAC,MAAM,YAAY,CAAC;AAC7G,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAEjD;;;;;GAKG;AACH,8BAAsB,UAAU,CAAC,CAAC;IAoCpB,SAAS,CAAC,OAAO,EAAE,YAAY;IAnC3C;;;OAGG;IACH,SAAgB,IAAI,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAEzC;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,kBAAkB,oBAA2B;IAChE,SAAS,CAAC,QAAQ,CAAC,UAAU,oBAA2B;IAExD;;;OAGG;IACH,OAAO,CAAC,aAAa,CAAS;IAE9B;;;;;OAKG;IACH,IAAW,WAAW,IAAI,OAAO,CAEhC;gBAEqB,OAAO,EAAE,YAAY;IAI3C;;;;;OAKG;IACH,SAAS,CAAC,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAYvD;;;;;;;;OAQG;IACI,SAAS,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,eAAe;IAkB5F;;;;;;;;OAQG;IACH,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;IAiBjC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,gBAAgB,CAAqC;IAE7D;;;;;;;;;;;;OAYG;IACI,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC;IAmB9B;;;;;;OAMG;IACI,OAAO,IAAI,IAAI;IAqBtB;;;;OAIG;IACH,SAAS,CAAC,eAAe,IAAI,IAAI;CAMlC"}
1
+ {"version":3,"file":"signal-base.d.ts","sourceRoot":"","sources":["../../src/core/signal-base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAC,MAAM,YAAY,CAAC;AAC7G,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAEjD;;;;;;;;GAQG;AACH,8BAAsB,UAAU,CAAC,CAAC;IAqDpB,SAAS,CAAC,OAAO,EAAE,YAAY;IApD3C;;;OAGG;IACH,SAAgB,IAAI,EAAE,MAAM,CAAC;IAE7B;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAEzC;;;;;OAKG;IACH,SAAS,CAAC,kBAAkB,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjD;;;;;OAKG;IACH,SAAS,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzC;;;;OAIG;IACH,OAAO,CAAC,aAAa,CAAS;IAE9B;;;;;OAKG;IACH,IAAW,WAAW,IAAI,OAAO,CAEhC;IAED;;;;OAIG;gBACmB,OAAO,EAAE,YAAY;IAI3C;;;;;OAKG;IACH,SAAS,CAAC,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAqBvD;;;;;;;;OAQG;IACI,SAAS,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,eAAe;IAoB5F;;;;;;OAMG;IACH,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;IAuBjC;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB,CAAC,CAA8B;IAEvD;;;;;OAKG;IACI,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC;IAoB9B;;;;OAIG;IACI,OAAO,IAAI,IAAI;IAsBtB;;;;;OAKG;IACH,SAAS,CAAC,eAAe,IAAI,IAAI;CAMlC"}
@@ -37,39 +37,52 @@ import type { StateSignalConfig, ListenerCallback, SubscribeOptions, SubscribeRe
37
37
  export declare class StateSignal<T> extends SignalBase<T> implements IReadonlySignal<T> {
38
38
  /**
39
39
  * The current value of the signal.
40
+ *
40
41
  * @private
41
42
  */
42
43
  private value__;
43
44
  /**
44
45
  * The logger instance for this signal.
46
+ *
45
47
  * @protected
46
48
  */
47
49
  protected logger_: AlwatrLogger;
48
50
  /**
49
51
  * Indicates if a notification is already scheduled.
52
+ * Helps batch multiple synchronous `set` operations into a single microtask notification.
53
+ *
50
54
  * @private
51
55
  */
52
56
  private notifyPending__;
53
57
  /**
54
- * The version of the last notification.
58
+ * The version of the last notification. Incrementing on every state update.
59
+ * Used to guard immediate subscriber execution when updates happen within the same tick.
60
+ *
55
61
  * @private
56
62
  */
57
63
  private notifyVersion__;
64
+ /**
65
+ * Creates a new StateSignal instance.
66
+ *
67
+ * @param config Configuration options including name, initialValue, and custom cleanup hooks.
68
+ */
58
69
  constructor(config: StateSignalConfig<T>);
59
70
  /**
60
71
  * Retrieves the current value of the signal.
61
72
  *
62
73
  * @returns The current value.
74
+ * @throws {Error} If the signal has been destroyed.
63
75
  *
64
76
  * @example
65
77
  * console.log(mySignal.get());
66
78
  */
67
79
  get(): T;
68
80
  /**
69
- * Updates the signal's value and notifies all active listeners.
81
+ * Updates the signal's value and schedules notifications for all active listeners.
70
82
  *
71
- * The notification is scheduled as a microtask, which means the update is deferred
72
- * slightly to batch multiple synchronous changes.
83
+ * Primitives are comparison-checked via `Object.is`. If unchanged, the update is ignored.
84
+ * The notification is scheduled as a microtask, allowing multiple synchronous updates
85
+ * to be batched and executed once.
73
86
  *
74
87
  * @param newValue The new value to set.
75
88
  *
@@ -82,18 +95,18 @@ export declare class StateSignal<T> extends SignalBase<T> implements IReadonlySi
82
95
  */
83
96
  set(newValue: T): void;
84
97
  /**
85
- * Notifies all listeners about the current value, even if it hasn't changed.
98
+ * Forcefully schedules a notification of the current value to all subscribers.
86
99
  *
87
- * This method is useful when you change the value instance directly (e.g., mutating an object) and want to inform listeners about the change.
100
+ * Useful when mutating properties within object states directly without assigning a new reference.
101
+ * Notification is queued as a microtask for batching.
88
102
  */
89
103
  notifyChange(): void;
90
104
  /**
91
105
  * Updates the signal's value based on its previous value.
92
106
  *
93
- * This method is particularly useful for state transitions that depend on the current value,
94
- * especially for objects or arrays, as it promotes an immutable update pattern.
107
+ * A functional update pattern that retrieves the current value, computes the next, and sets it.
95
108
  *
96
- * @param updater A function that receives the current value and returns the new value.
109
+ * @param updater A callback function that receives the current value and returns the new value.
97
110
  *
98
111
  * @example
99
112
  * // For a counter
@@ -104,21 +117,27 @@ export declare class StateSignal<T> extends SignalBase<T> implements IReadonlySi
104
117
  */
105
118
  update(updater: (previousValue: T) => T): void;
106
119
  /**
107
- * Subscribes a listener to this signal.
120
+ * Subscribes a listener function to this state signal.
108
121
  *
109
122
  * By default, the listener is immediately called with the signal's current value (`receivePrevious: true`).
110
- * This behavior can be customized via the `options` parameter.
123
+ * This immediate call is queued as a microtask to match the asynchronous flow of signals.
111
124
  *
112
- * @param callback The function to be called when the signal's value changes.
113
- * @param options Subscription options, including `receivePrevious` and `once`.
125
+ * @param callback The function to invoke when the state changes.
126
+ * @param options Custom options, such as `receivePrevious: false` to only listen to future updates.
114
127
  * @returns An object with an `unsubscribe` method to remove the listener.
115
128
  */
116
129
  subscribe(callback: ListenerCallback<T>, options?: SubscribeOptions): SubscribeResult;
117
130
  /**
118
131
  * Destroys the signal, clearing its value and all listeners.
119
- * This is crucial for memory management to prevent leaks.
132
+ * Breaks references for garbage collection.
120
133
  */
121
134
  destroy(): void;
135
+ /**
136
+ * Returns this signal cast to the `IReadonlySignal<T>` interface.
137
+ * Limits access so external callers can only subscribe/read but not set/update state.
138
+ *
139
+ * @returns A readonly representation of this signal.
140
+ */
122
141
  asReadonly(): IReadonlySignal<T>;
123
142
  }
124
143
  //# sourceMappingURL=state-signal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"state-signal.d.ts","sourceRoot":"","sources":["../../src/core/state-signal.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAE5C,OAAO,KAAK,EAAC,iBAAiB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAC,MAAM,YAAY,CAAC;AAExH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,qBAAa,WAAW,CAAC,CAAC,CAAE,SAAQ,UAAU,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;IAC7E;;;OAGG;IACH,OAAO,CAAC,OAAO,CAAI;IAEnB;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC;IAEhC;;;OAGG;IACH,OAAO,CAAC,eAAe,CAAS;IAEhC;;;OAGG;IACH,OAAO,CAAC,eAAe,CAAK;gBAEhB,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAUxC;;;;;;;OAOG;IACI,GAAG,IAAI,CAAC;IAKf;;;;;;;;;;;;;;OAcG;IACI,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI;IAa7B;;;;OAIG;IACI,YAAY,IAAI,IAAI;IAe3B;;;;;;;;;;;;;;OAcG;IACI,MAAM,CAAC,OAAO,EAAE,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI;IAOrD;;;;;;;;;OASG;IACa,SAAS,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,gBAAqB,GAAG,eAAe;IAyBzG;;;OAGG;IACa,OAAO,IAAI,IAAI;IAKxB,UAAU,IAAI,eAAe,CAAC,CAAC,CAAC;CAGxC"}
1
+ {"version":3,"file":"state-signal.d.ts","sourceRoot":"","sources":["../../src/core/state-signal.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,EAAC,iBAAiB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAC,MAAM,YAAY,CAAC;AAExH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,qBAAa,WAAW,CAAC,CAAC,CAAE,SAAQ,UAAU,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;IAC7E;;;;OAIG;IACH,OAAO,CAAC,OAAO,CAAI;IAEnB;;;;OAIG;IACH,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC;IAEhC;;;;;OAKG;IACH,OAAO,CAAC,eAAe,CAAS;IAEhC;;;;;OAKG;IACH,OAAO,CAAC,eAAe,CAAK;IAE5B;;;;OAIG;gBACS,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAUxC;;;;;;;;OAQG;IACI,GAAG,IAAI,CAAC;IAKf;;;;;;;;;;;;;;;OAeG;IACI,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI;IAa7B;;;;;OAKG;IACI,YAAY,IAAI,IAAI;IAe3B;;;;;;;;;;;;;OAaG;IACI,MAAM,CAAC,OAAO,EAAE,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI;IAOrD;;;;;;;;;OASG;IACa,SAAS,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,gBAAqB,GAAG,eAAe;IA2BzG;;;OAGG;IACa,OAAO,IAAI,IAAI;IAK/B;;;;;OAKG;IACI,UAAU,IAAI,eAAe,CAAC,CAAC,CAAC;CAGxC"}
@@ -1,5 +1,5 @@
1
1
  import { ChannelSignal } from '../core/channel-signal.js';
2
- import type { ChannelSignalConfig } from '../core/channel-signal.js';
2
+ import type { ChannelSignalConfig } from '../type.js';
3
3
  /**
4
4
  * Creates a stateless multi-channel signal that acts as a typed message bus.
5
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/creators/channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,2BAA2B,CAAC;AAExD,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,2BAA2B,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,SAAS,MAAM,EAAE,MAAM,EAAE,mBAAmB,GAAG,aAAa,CAAC,IAAI,CAAC,CAEzG"}
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/creators/channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,2BAA2B,CAAC;AACxD,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,YAAY,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,SAAS,MAAM,EAAE,MAAM,EAAE,mBAAmB,GAAG,aAAa,CAAC,IAAI,CAAC,CAEzG"}
@@ -0,0 +1,31 @@
1
+ import { DerivedSignal } from '../core/derived-signal.js';
2
+ import type { DerivedSignalConfig } from '../type.js';
3
+ /**
4
+ * Creates a read-only signal mapping exactly 1-to-1 over a single upstream source.
5
+ *
6
+ * `createDerivedSignal` is a utility function to instantiate `DerivedSignal` without using the `new` keyword.
7
+ * A derived signal wraps a source signal and maps its value to a new representation using a projector function.
8
+ * It uses the "Cold Awakening Lifecycle" pattern, which avoids subscribing to the source signal until the derived
9
+ * signal has at least one subscriber of its own, saving processing cycles.
10
+ *
11
+ * @template S The type of the source signal's state.
12
+ * @template T The type of the projected derived state.
13
+ *
14
+ * @param config Configuration options including name, source, and projector.
15
+ * @returns A new, readonly derived signal.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const countSignal = createStateSignal({ name: 'count', initialValue: 5 });
20
+ *
21
+ * const isEvenSignal = createDerivedSignal({
22
+ * name: 'is-even-signal',
23
+ * source: countSignal,
24
+ * projector: (count) => count % 2 === 0
25
+ * });
26
+ *
27
+ * console.log(isEvenSignal.get()); // false
28
+ * ```
29
+ */
30
+ export declare function createDerivedSignal<S, T>(config: DerivedSignalConfig<S, T>): DerivedSignal<S, T>;
31
+ //# sourceMappingURL=derived.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derived.d.ts","sourceRoot":"","sources":["../../src/creators/derived.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,2BAA2B,CAAC;AAExD,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,YAAY,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAEhG"}
package/dist/main.d.ts CHANGED
@@ -2,6 +2,7 @@ export * from './core/signal-base.js';
2
2
  export * from './core/event-signal.js';
3
3
  export * from './core/state-signal.js';
4
4
  export * from './core/computed-signal.js';
5
+ export * from './core/derived-signal.js';
5
6
  export * from './core/effect-signal.js';
6
7
  export * from './core/persistent-state-signal.js';
7
8
  export * from './core/session-state-signal.js';
@@ -9,12 +10,12 @@ export * from './core/channel-signal.js';
9
10
  export * from './creators/event.js';
10
11
  export * from './creators/state.js';
11
12
  export * from './creators/computed.js';
13
+ export * from './creators/derived.js';
12
14
  export * from './creators/effect.js';
13
15
  export * from './creators/persistent-state.js';
14
16
  export * from './creators/session-state.js';
15
17
  export * from './creators/channel.js';
16
18
  export * from './operators/debounce.js';
17
19
  export * from './operators/filter.js';
18
- export * from './operators/map.js';
19
20
  export type * from './type.js';
20
21
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AAEzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AAEtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AAEnC,mBAAmB,WAAW,CAAC"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AAEzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AAEtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AAEtC,mBAAmB,WAAW,CAAC"}
package/dist/main.js CHANGED
@@ -1,5 +1,5 @@
1
- /* 📦 @alwatr/signal v9.26.0 */
2
- class B{config_;name;priorityObservers_=new Set;observers_=new Set;isDestroyed__=!1;get isDestroyed(){return this.isDestroyed__}constructor(G){this.config_=G;this.name=G.name}removeObserver_(G){if(this.logger_.logMethod?.("removeObserver_"),this.isDestroyed__){this.logger_.incident?.("removeObserver_","remove_observer_on_destroyed_signal");return}this.priorityObservers_.delete(G),this.observers_.delete(G)}subscribe(G,H){this.logger_.logMethodArgs?.("subscribe.base",H),this.checkDestroyed_();let Q={callback:G,options:H};if(H?.priority)this.priorityObservers_.add(Q);else this.observers_.add(Q);return{unsubscribe:()=>this.removeObserver_(Q)}}notify_(G){if(this.logger_.logMethodArgs?.("notify_",G),this.isDestroyed__){this.logger_.incident?.("notify_","notify_on_destroyed_signal");return}for(let H of this.priorityObservers_)this.executeObserver__(H,G);for(let H of this.observers_)this.executeObserver__(H,G)}executeObserver__(G,H){if(G.options?.once)this.removeObserver_(G);try{let Q=G.callback(H);if(Q instanceof Promise)Q.catch((X)=>this.logger_.error("notify_","async_callback_failed",X,{observer:G}))}catch(Q){this.logger_.error("notify_","sync_callback_failed",Q)}}pendingRejects__=new Set;untilNext(){return this.logger_.logMethod?.("untilNext"),this.checkDestroyed_(),new Promise((G,H)=>{this.pendingRejects__.add(H),this.subscribe((Q)=>{this.pendingRejects__.delete(H),G(Q)},{once:!0,priority:!0,receivePrevious:!1})})}destroy(){if(this.logger_.logMethod?.("destroy"),this.isDestroyed__){this.logger_.incident?.("destroy_","double_destroy_attempt");return}if(this.isDestroyed__=!0,this.pendingRejects__.size){let G=Error("signal_destroyed");for(let H of this.pendingRejects__)H(G);this.pendingRejects__.clear()}this.priorityObservers_.clear(),this.observers_.clear(),this.config_.onDestroy?.(),this.config_=null}checkDestroyed_(){if(this.isDestroyed__)throw this.logger_.accident("checkDestroyed_","attempt_to_use_destroyed_signal"),Error(`Cannot interact with a destroyed signal (id: ${this.name})`)}}import{delay as E}from"@alwatr/delay";import{createLogger as x}from"@alwatr/logger";class R extends B{logger_;constructor(G){super(G);this.logger_=x(`event-signal:${this.name}`),this.logger_.logMethod?.("constructor")}dispatch(G){this.logger_.logMethodArgs?.("dispatch",{payload:G}),this.checkDestroyed_(),E.nextMicrotask().then(()=>this.notify_(G))}}import{delay as _}from"@alwatr/delay";import{createLogger as D}from"@alwatr/logger";class K extends B{value__;logger_;notifyPending__=!1;notifyVersion__=0;constructor(G){super({name:G.name,onDestroy:G.onDestroy});this.logger_=D(`state-signal:${this.name}`),this.value__=G.initialValue,this.logger_.logMethodArgs?.("constructor",{initialValue:this.value__})}get(){return this.checkDestroyed_(),this.value__}set(G){if(this.logger_.logMethodArgs?.("set",{newValue:G}),Object.is(this.value__,G)&&(typeof G!=="object"||G===null))return;this.value__=G,this.notifyChange()}notifyChange(){if(this.logger_.logMethod?.("notifyChange"),this.checkDestroyed_(),this.notifyVersion__++,this.notifyPending__)return;this.notifyPending__=!0,_.nextMicrotask().then(()=>{this.notifyPending__=!1,this.notify_(this.value__)})}update(G){this.checkDestroyed_();let H=G(this.value__);this.logger_.logMethodFull?.("update",this.value__,H),this.set(H)}subscribe(G,H={}){this.logger_.logMethodArgs?.("subscribe",H),this.checkDestroyed_();let Q=super.subscribe(G,H);if(H.receivePrevious===!1)return Q;if(this.notifyPending__)return Q;let X=this.notifyVersion__;return _.nextMicrotask().then(()=>{if(this.logger_.logStep?.("subscribe","immediate_callback"),this.notifyVersion__!==X)return;if(H.once)Q.unsubscribe();G(this.value__)}).catch((Y)=>this.logger_.error("subscribe","immediate_callback_failed",Y)),Q}destroy(){this.value__=null,super.destroy()}asReadonly(){return this}}import{delay as I}from"@alwatr/delay";import{createLogger as N}from"@alwatr/logger";class z{config_;name;logger_;internalSignal_;dependencySubscriptions__=[];isRecalculating__=!1;constructor(G){this.config_=G;this.name=G.name,this.logger_=N(`computed-signal:${this.name}`),this.recalculate_=this.recalculate_.bind(this),this.logger_.logMethod?.("constructor"),this.internalSignal_=new K({name:`compute-${this.name}_`,initialValue:this.config_.get()});for(let H of G.deps)this.logger_.logStep?.("constructor","subscribing_to_dependency",{signal:H.name}),this.dependencySubscriptions__.push(H.subscribe(this.recalculate_,{receivePrevious:!1}))}get(){return this.internalSignal_.get()}get isDestroyed(){return this.internalSignal_.isDestroyed}subscribe(G,H){return this.internalSignal_.subscribe(G,H)}untilNext(){return this.internalSignal_.untilNext()}destroy(){if(this.logger_.logMethod?.("destroy"),this.isDestroyed){this.logger_.incident?.("destroy","already_destroyed");return}for(let G of this.dependencySubscriptions__)G.unsubscribe();this.dependencySubscriptions__.length=0,this.internalSignal_.destroy(),this.config_.onDestroy?.(),this.config_=null}async recalculate_(){if(this.logger_.logMethod?.("recalculate_"),this.internalSignal_.isDestroyed){this.logger_.incident?.("recalculate_","recalculate_on_destroyed_signal");return}if(this.isRecalculating__){this.logger_.logStep?.("recalculate_","skipping_recalculation_already_scheduled");return}this.isRecalculating__=!0;try{if(await I.nextMacrotask(),this.isDestroyed){this.logger_.incident?.("recalculate_","destroyed_during_delay"),this.isRecalculating__=!1;return}this.logger_.logStep?.("recalculate_","recalculating_value"),this.internalSignal_.set(this.config_.get())}catch(G){this.logger_.error("recalculate_","recalculation_failed",G)}this.isRecalculating__=!1}}import{delay as A}from"@alwatr/delay";import{createLogger as k}from"@alwatr/logger";class L{config_;name;logger_;dependencySubscriptions__=[];isRunning__=!1;isDestroyed__=!1;get isDestroyed(){return this.isDestroyed__}constructor(G){this.config_=G;this.name=G.name??`[${G.deps.map((H)=>H.name).join(", ")}]`,this.logger_=k(`effect-signal:${this.name}`),this.scheduleExecution_=this.scheduleExecution_.bind(this),this.logger_.logMethod?.("constructor");for(let H of G.deps)this.logger_.logStep?.("constructor","subscribing_to_dependency",{signal:H.name}),this.dependencySubscriptions__.push(H.subscribe(this.scheduleExecution_,{receivePrevious:!1}));if(G.runImmediately===!0)this.logger_.logStep?.("constructor","scheduling_initial_execution"),this.scheduleExecution_()}async scheduleExecution_(){if(this.logger_.logMethod?.("scheduleExecution_"),this.isDestroyed__){this.logger_.incident?.("scheduleExecution_","schedule_execution_on_destroyed_signal");return}if(this.isRunning__){this.logger_.logStep?.("scheduleExecution_","skipped_because_already_running");return}this.isRunning__=!0;try{if(await A.nextMacrotask(),this.isDestroyed__){this.logger_.incident?.("scheduleExecution_","destroyed_during_delay"),this.isRunning__=!1;return}this.logger_.logStep?.("scheduleExecution_","executing_effect"),await this.config_.run()}catch(G){this.logger_.error("scheduleExecution_","effect_failed",G)}this.isRunning__=!1}destroy(){if(this.logger_.logMethod?.("destroy"),this.isDestroyed__){this.logger_.incident?.("destroy","already_destroyed");return}this.isDestroyed__=!0;for(let G of this.dependencySubscriptions__)G.unsubscribe();this.dependencySubscriptions__.length=0,this.config_.onDestroy?.(),this.config_=null}}import{createDebouncer as V}from"@alwatr/debounce";import{createLocalStorageProvider as j}from"@alwatr/local-storage";class O extends K{storageProvider__;storageDebouncer__;storageSyncSubscription__;windowPageHideListener_=()=>{this.storageDebouncer__.flush()};windowPageShowListener_=(G)=>{if(G.persisted){this.logger_.logMethod?.("windowPageShowListener_//restored_from_bfcache");let H=this.storageProvider__.read();if(H!==null)this.set(H)}};constructor(G){let{name:H,storageKey:Q=H,saveDebounceDelay:X=1000,initialValue:Y,onDestroy:Z,schemaVersion:q,parse:W,stringify:J}=G,P=j({name:Q,schemaVersion:q,parse:W,stringify:J});super({name:H,initialValue:P.read()??Y,onDestroy:Z});if(this.logger_.logMethodArgs?.("constructor",G),this.storageProvider__=P,this.storageDebouncer__=V({delay:X,leading:!1,trailing:!0,thisContext:this,func:this.syncStorage__}),this.storageSyncSubscription__=this.subscribe(this.storageDebouncer__.trigger,{receivePrevious:!1}),typeof globalThis.addEventListener==="function")globalThis.addEventListener("pagehide",this.windowPageHideListener_,{passive:!0}),globalThis.addEventListener("pageshow",this.windowPageShowListener_,{passive:!0})}syncStorage__(G){this.logger_.logMethodArgs?.("syncStorage__",G),this.storageProvider__.write(G)}remove(){this.checkDestroyed_(),this.logger_.logMethod?.("remove"),this.storageProvider__.remove()}destroy(){if(this.logger_.logMethod?.("destroy"),typeof globalThis.removeEventListener==="function")globalThis.removeEventListener("pagehide",this.windowPageHideListener_),globalThis.removeEventListener("pageshow",this.windowPageShowListener_);this.storageDebouncer__.flush(),this.storageSyncSubscription__.unsubscribe(),super.destroy()}}import{createDebouncer as C}from"@alwatr/debounce";import{createSessionStorageProvider as T}from"@alwatr/session-storage";class $ extends K{storageProvider__;storageDebouncer__;storageSyncSubscription__;windowPageHideListener__=()=>{this.storageDebouncer__.flush()};windowPageShowListener__=(G)=>{if(G.persisted){this.logger_.logMethod?.("windowPageShowListener__//restored_from_bfcache");let H=this.storageProvider__.read();if(H!==null)this.set(H)}};constructor(G){let{name:H,storageKey:Q=H,saveDebounceDelay:X=1000,initialValue:Y,onDestroy:Z,parse:q,stringify:W}=G,J=T({name:Q,parse:q,stringify:W});super({name:H,initialValue:J.read()??Y,onDestroy:Z});if(this.logger_.logMethodArgs?.("constructor",G),this.storageProvider__=J,this.storageDebouncer__=C({delay:X,leading:!1,trailing:!0,thisContext:this,func:this.syncStorage__}),this.storageSyncSubscription__=this.subscribe(this.storageDebouncer__.trigger,{receivePrevious:!1}),typeof globalThis.addEventListener==="function")globalThis.addEventListener("pagehide",this.windowPageHideListener__,{passive:!0}),globalThis.addEventListener("pageshow",this.windowPageShowListener__,{passive:!0})}syncStorage__(G){this.logger_.logMethodArgs?.("syncStorage__",G),this.storageProvider__.write(G)}remove(){this.checkDestroyed_(),this.logger_.logMethod?.("remove"),this.storageProvider__.remove()}destroy(){if(this.logger_.logMethod?.("destroy"),typeof globalThis.removeEventListener==="function")globalThis.removeEventListener("pagehide",this.windowPageHideListener__),globalThis.removeEventListener("pageshow",this.windowPageShowListener__);this.storageDebouncer__.flush(),this.storageSyncSubscription__.unsubscribe(),super.destroy()}}import{delay as w}from"@alwatr/delay";import{createLogger as b}from"@alwatr/logger";class M extends B{logger_;namedHandlers__=new Map;constructor(G){super(G);this.logger_=b(`channel-signal:${this.name}`),this.logger_.logMethod?.("constructor")}dispatch(...G){let[H,Q]=G;this.logger_.logMethodArgs?.("dispatch",{name:H,payload:Q}),this.checkDestroyed_(),w.nextMicrotask().then(()=>this.route__(H,Q))}on(G,H,Q){this.logger_.logMethodArgs?.("on",{name:G}),this.checkDestroyed_();let X=this.namedHandlers__.get(G);if(!X)X=new Set,this.namedHandlers__.set(G,X);let Y={handler:H,once:Q?.once??!1};return X.add(Y),{unsubscribe:()=>{if(X.delete(Y),X.size===0)this.namedHandlers__.delete(G)}}}subscribe(G,H){return this.logger_.logMethodArgs?.("subscribe",H),super.subscribe(G,H)}route__(G,H){if(this.isDestroyed)return;let Q=this.namedHandlers__.get(G);if(Q?.size)for(let X of Q){if(X.once){if(Q.delete(X),Q.size===0)this.namedHandlers__.delete(G)}try{let Y=X.handler(H);if(Y instanceof Promise)Y.catch((Z)=>this.logger_.error("route__","async_named_handler_failed",Z))}catch(Y){this.logger_.error("route__","sync_named_handler_failed",Y)}}this.notify_({name:G,payload:H})}destroy(){this.namedHandlers__.clear(),super.destroy()}}function qG(G){return new R(G)}function U(G){return new K(G)}function F(G){return new z(G)}function MG(G){return new L(G)}function UG(G){return new O(G)}function DG(G){return new $(G)}function AG(G){return new M(G)}import{createDebouncer as v}from"@alwatr/debounce";function TG(G,H){let Q=H.name??`${G.name}-debounced`,X=new K({name:`${Q}-internal`,initialValue:G.get()}),Y=v({...H,thisContext:X,func:X.set}),Z=G.subscribe(Y.trigger,{receivePrevious:!1});return F({name:Q,deps:[X],get:()=>X.get(),onDestroy:()=>{if(X.isDestroyed)return;Z.unsubscribe(),Y.cancel(),X.destroy(),H.onDestroy?.(),H=null}})}function yG(G,H,Q=`${G.name}-filtered`){let X=G.get(),Y=H(X)?X:void 0,Z=U({name:`${Q}-internal`,initialValue:Y}),q=G.subscribe((W)=>{if(H(W))Z.set(W)});return F({name:Q,deps:[Z],get:()=>Z.get(),onDestroy:()=>{q.unsubscribe(),Z.destroy()}})}function mG(G,H,Q=`${G.name}-mapped`){return F({name:Q,deps:[G],get:()=>H(G.get())})}export{U as createStateSignal,DG as createSessionStateSignal,UG as createPersistentStateSignal,mG as createMappedSignal,yG as createFilteredSignal,qG as createEventSignal,MG as createEffect,TG as createDebouncedSignal,F as createComputedSignal,AG as createChannelSignal,K as StateSignal,B as SignalBase,$ as SessionStateSignal,O as PersistentStateSignal,R as EventSignal,L as EffectSignal,z as ComputedSignal,M as ChannelSignal};
1
+ /* 📦 @alwatr/signal v9.30.0 */
2
+ class K{config_;name;priorityObservers_;observers_;isDestroyed__=!1;get isDestroyed(){return this.isDestroyed__}constructor(G){this.config_=G;this.name=G.name}removeObserver_(G){if(this.logger_.logMethod?.("removeObserver_"),this.isDestroyed__){this.logger_.incident?.("removeObserver_","remove_observer_on_destroyed_signal");return}if(G.options?.priority){if(this.priorityObservers_?.delete(G),this.priorityObservers_?.size===0)this.priorityObservers_=void 0}else if(this.observers_?.delete(G),this.observers_?.size===0)this.observers_=void 0}subscribe(G,H){this.logger_.logMethodArgs?.("subscribe.base",H),this.checkDestroyed_();let Q={callback:G,options:H};if(H?.priority)this.priorityObservers_??=new Set,this.priorityObservers_.add(Q);else this.observers_??=new Set,this.observers_.add(Q);return{unsubscribe:()=>this.removeObserver_(Q)}}notify_(G){if(this.logger_.logMethodArgs?.("notify_",G),this.isDestroyed__){this.logger_.incident?.("notify_","notify_on_destroyed_signal");return}if(this.priorityObservers_?.size)for(let H of this.priorityObservers_)this.executeObserver__(H,G);if(this.observers_?.size)for(let H of this.observers_)this.executeObserver__(H,G)}executeObserver__(G,H){if(G.options?.once)this.removeObserver_(G);try{G.callback(H)}catch(Q){this.logger_.error("notify_","sync_callback_failed",Q)}}pendingRejects__;untilNext(){return this.logger_.logMethod?.("untilNext"),this.checkDestroyed_(),new Promise((G,H)=>{this.pendingRejects__??=new Set,this.pendingRejects__.add(H),this.subscribe((Q)=>{this.pendingRejects__?.delete(H),G(Q)},{once:!0,priority:!0,receivePrevious:!1})})}destroy(){if(this.logger_.logMethod?.("destroy"),this.isDestroyed__){this.logger_.incident?.("destroy_","double_destroy_attempt");return}if(this.isDestroyed__=!0,this.pendingRejects__?.size){let G=Error("signal_destroyed");for(let H of this.pendingRejects__)H(G);this.pendingRejects__.clear()}this.priorityObservers_?.clear(),this.observers_?.clear(),this.config_.onDestroy?.(),this.config_=null}checkDestroyed_(){if(this.isDestroyed__)throw this.logger_.accident("checkDestroyed_","attempt_to_use_destroyed_signal"),Error(`Cannot interact with a destroyed signal (id: ${this.name})`)}}import{queueMicrotask as x}from"@alwatr/delay";import{createLogger as E}from"@alwatr/logger";class O extends K{logger_;constructor(G){super(G);this.logger_=E(`event_signal:${this.name}`),this.logger_.logMethod?.("constructor")}dispatch(G){this.logger_.logMethodArgs?.("dispatch",{payload:G}),this.checkDestroyed_(),x(()=>this.notify_(G))}}import{queueMicrotask as M}from"@alwatr/delay";import{createLogger as D}from"@alwatr/logger";class Z extends K{value__;logger_;notifyPending__=!1;notifyVersion__=0;constructor(G){super({name:G.name,onDestroy:G.onDestroy});this.logger_=D(`state_signal:${this.name}`),this.value__=G.initialValue,this.logger_.logMethodArgs?.("constructor",{initialValue:this.value__})}get(){return this.checkDestroyed_(),this.value__}set(G){if(this.logger_.logMethodArgs?.("set",{newValue:G}),Object.is(this.value__,G)&&(typeof G!=="object"||G===null))return;this.value__=G,this.notifyChange()}notifyChange(){if(this.logger_.logMethod?.("notifyChange"),this.checkDestroyed_(),this.notifyVersion__++,this.notifyPending__)return;this.notifyPending__=!0,M(()=>{this.notifyPending__=!1,this.notify_(this.value__)})}update(G){this.checkDestroyed_();let H=G(this.value__);this.logger_.logMethodFull?.("update",this.value__,H),this.set(H)}subscribe(G,H={}){this.logger_.logMethodArgs?.("subscribe",H),this.checkDestroyed_();let Q=super.subscribe(G,H);if(H.receivePrevious===!1)return Q;if(this.notifyPending__)return Q;let X=this.notifyVersion__;return M(()=>{if(this.logger_.logStep?.("subscribe","immediate_callback"),this.notifyVersion__!==X)return;if(H.once)Q.unsubscribe();try{G(this.value__)}catch(Y){this.logger_.error("subscribe","immediate_callback_failed",Y)}}),Q}destroy(){this.value__=null,super.destroy()}asReadonly(){return this}}import{queueMicrotask as N}from"@alwatr/delay";import{createLogger as I}from"@alwatr/logger";class R{config_;name;logger_;internalSignal_;dependencySubscriptions__=[];isRecalculating__=!1;constructor(G){this.config_=G;this.name=G.name,this.logger_=I(`computed_signal:${this.name}`),this.recalculate_=this.recalculate_.bind(this),this.logger_.logMethod?.("constructor"),this.internalSignal_=new Z({name:`compute_internal:${this.name}`,initialValue:this.config_.get()});for(let H=0;H<this.config_.deps.length;H++){let Q=this.config_.deps[H];this.logger_.logStep?.("constructor","subscribing_to_dependency",{signal:Q.name}),this.dependencySubscriptions__.push(Q.subscribe(this.recalculate_,{receivePrevious:!1}))}}get(){return this.internalSignal_.get()}get isDestroyed(){return this.internalSignal_.isDestroyed}subscribe(G,H){return this.internalSignal_.subscribe(G,H)}untilNext(){return this.internalSignal_.untilNext()}destroy(){if(this.logger_.logMethod?.("destroy"),this.isDestroyed){this.logger_.incident?.("destroy","already_destroyed");return}for(let G=0;G<this.dependencySubscriptions__.length;G++)this.dependencySubscriptions__[G].unsubscribe();this.dependencySubscriptions__.length=0,this.internalSignal_.destroy(),this.config_.onDestroy?.(),this.config_=null}recalculate_(){if(this.logger_.logMethod?.("recalculate_"),this.isRecalculating__){this.logger_.logStep?.("recalculate_","skipping_recalculation_already_scheduled");return}this.isRecalculating__=!0,N(()=>{if(this.isDestroyed){this.logger_.incident?.("recalculate_","destroyed_during_delay"),this.isRecalculating__=!1;return}this.logger_.logStep?.("recalculate_","recalculating_value");try{this.internalSignal_.set(this.config_.get())}catch(G){this.logger_.error("recalculate_","projection_evaluation_failed",G)}this.isRecalculating__=!1})}}import{createLogger as A}from"@alwatr/logger";class z{config_;name;logger_;internalSignal_;sourceSubscription__;activeConsumerCount__=0;constructor(G){this.config_=G;this.name=this.config_.name,this.logger_=A(`derived_signal:${this.name}`)}untilNext(){return this.logger_.logMethod?.("untilNext"),this.checkDestroyed__(),new Promise((G)=>{this.subscribe((H)=>{G(H)},{receivePrevious:!1,once:!0})})}get(){if(this.logger_.logMethod?.("get"),this.checkDestroyed__(),this.activeConsumerCount__===0)return this.config_.projector(this.config_.source.get());return this.internalSignal_.get()}get isDestroyed(){return this.config_===null}subscribe(G,H){if(this.logger_.logMethod?.("subscribe"),this.checkDestroyed__(),this.activeConsumerCount__++,this.activeConsumerCount__===1)this.logger_.logMethod?.("wakeUp_"),this.internalSignal_=new Z({name:`derived-internal:${this.name}`,initialValue:this.config_.projector(this.config_.source.get())}),this.sourceSubscription__=this.config_.source.subscribe((X)=>{this.internalSignal_.set(this.config_.projector(X))},{receivePrevious:!1});let Q=this.internalSignal_.subscribe(G,H);return{unsubscribe:()=>{if(this.logger_.logMethod?.("unsubscribe"),Q.unsubscribe(),this.activeConsumerCount__--,this.activeConsumerCount__===0&&this.sourceSubscription__)this.logger_.logMethod?.("sleepCleanup_"),this.sourceSubscription__.unsubscribe(),this.sourceSubscription__=void 0,this.internalSignal_?.destroy(),this.internalSignal_=void 0}}}destroy(){if(this.logger_.logMethod?.("destroy"),this.isDestroyed)return;if(this.sourceSubscription__)this.sourceSubscription__.unsubscribe(),this.sourceSubscription__=void 0;this.internalSignal_?.destroy(),this.config_.onDestroy?.(),this.config_=null}checkDestroyed__(){if(this.logger_.logMethod?.("checkDestroyed__"),this.isDestroyed)throw Error(`Cannot interact with a destroyed signal (id: ${this.name})`)}}import{delay as j}from"@alwatr/delay";import{createLogger as C}from"@alwatr/logger";class ${config_;name;logger_;dependencySubscriptions__=[];isRunning__=!1;isDestroyed__=!1;get isDestroyed(){return this.isDestroyed__}constructor(G){this.config_=G;this.name=G.name??`[${G.deps.map((H)=>H.name).join(", ")}]`,this.logger_=C(`effect-signal:${this.name}`),this.scheduleExecution_=this.scheduleExecution_.bind(this),this.logger_.logMethod?.("constructor");for(let H of G.deps)this.logger_.logStep?.("constructor","subscribing_to_dependency",{signal:H.name}),this.dependencySubscriptions__.push(H.subscribe(this.scheduleExecution_,{receivePrevious:!1}));if(G.runImmediately===!0)this.logger_.logStep?.("constructor","scheduling_initial_execution"),this.scheduleExecution_()}async scheduleExecution_(){if(this.logger_.logMethod?.("scheduleExecution_"),this.isDestroyed__){this.logger_.incident?.("scheduleExecution_","schedule_execution_on_destroyed_signal");return}if(this.isRunning__){this.logger_.logStep?.("scheduleExecution_","skipped_because_already_running");return}this.isRunning__=!0;try{if(await j.nextMicrotask(),this.isDestroyed__){this.logger_.incident?.("scheduleExecution_","destroyed_during_delay"),this.isRunning__=!1;return}this.logger_.logStep?.("scheduleExecution_","executing_effect"),this.config_.run()}catch(G){this.logger_.error("scheduleExecution_","effect_failed",G)}this.isRunning__=!1}destroy(){if(this.logger_.logMethod?.("destroy"),this.isDestroyed__){this.logger_.incident?.("destroy","already_destroyed");return}this.isDestroyed__=!0;for(let G of this.dependencySubscriptions__)G.unsubscribe();this.dependencySubscriptions__.length=0,this.config_.onDestroy?.(),this.config_=null}}import{createDebouncer as V}from"@alwatr/debounce";import{createLocalStorageProvider as T}from"@alwatr/local-storage";class q extends Z{storageProvider__;storageDebouncer__;storageSyncSubscription__;windowPageHideListener_=()=>{this.storageDebouncer__.flush()};windowPageShowListener_=(G)=>{if(G.persisted){this.logger_.logMethod?.("windowPageShowListener_//restored_from_bfcache");let H=this.storageProvider__.read();if(H!==null)this.set(H)}};constructor(G){let{name:H,storageKey:Q=H,saveDebounceDelay:X=1000,initialValue:Y,onDestroy:F,schemaVersion:B,parse:J,stringify:W}=G,P=T({name:Q,schemaVersion:B,parse:J,stringify:W});super({name:H,initialValue:P.read()??Y,onDestroy:F});if(this.logger_.logMethodArgs?.("constructor",G),this.storageProvider__=P,this.storageDebouncer__=V({delay:X,leading:!1,trailing:!0,thisContext:this,func:this.syncStorage__}),this.storageSyncSubscription__=this.subscribe(this.storageDebouncer__.trigger,{receivePrevious:!1}),typeof globalThis.addEventListener==="function")globalThis.addEventListener("pagehide",this.windowPageHideListener_,{passive:!0}),globalThis.addEventListener("pageshow",this.windowPageShowListener_,{passive:!0})}syncStorage__(G){this.logger_.logMethodArgs?.("syncStorage__",G),this.storageProvider__.write(G)}remove(){this.checkDestroyed_(),this.logger_.logMethod?.("remove"),this.storageProvider__.remove()}destroy(){if(this.logger_.logMethod?.("destroy"),typeof globalThis.removeEventListener==="function")globalThis.removeEventListener("pagehide",this.windowPageHideListener_),globalThis.removeEventListener("pageshow",this.windowPageShowListener_);this.storageDebouncer__.flush(),this.storageSyncSubscription__.unsubscribe(),super.destroy()}}import{createDebouncer as k}from"@alwatr/debounce";import{createSessionStorageProvider as w}from"@alwatr/session-storage";class _ extends Z{storageProvider__;storageDebouncer__;storageSyncSubscription__;windowPageHideListener__=()=>{this.storageDebouncer__.flush()};windowPageShowListener__=(G)=>{if(G.persisted){this.logger_.logMethod?.("windowPageShowListener__//restored_from_bfcache");let H=this.storageProvider__.read();if(H!==null)this.set(H)}};constructor(G){let{name:H,storageKey:Q=H,saveDebounceDelay:X=1000,initialValue:Y,onDestroy:F,parse:B,stringify:J}=G,W=w({name:Q,parse:B,stringify:J});super({name:H,initialValue:W.read()??Y,onDestroy:F});if(this.logger_.logMethodArgs?.("constructor",G),this.storageProvider__=W,this.storageDebouncer__=k({delay:X,leading:!1,trailing:!0,thisContext:this,func:this.syncStorage__}),this.storageSyncSubscription__=this.subscribe(this.storageDebouncer__.trigger,{receivePrevious:!1}),typeof globalThis.addEventListener==="function")globalThis.addEventListener("pagehide",this.windowPageHideListener__,{passive:!0}),globalThis.addEventListener("pageshow",this.windowPageShowListener__,{passive:!0})}syncStorage__(G){this.logger_.logMethodArgs?.("syncStorage__",G),this.storageProvider__.write(G)}remove(){this.checkDestroyed_(),this.logger_.logMethod?.("remove"),this.storageProvider__.remove()}destroy(){if(this.logger_.logMethod?.("destroy"),typeof globalThis.removeEventListener==="function")globalThis.removeEventListener("pagehide",this.windowPageHideListener__),globalThis.removeEventListener("pageshow",this.windowPageShowListener__);this.storageDebouncer__.flush(),this.storageSyncSubscription__.unsubscribe(),super.destroy()}}import{queueMicrotask as b}from"@alwatr/delay";import{createLogger as S}from"@alwatr/logger";class L extends K{logger_;namedHandlers__=new Map;constructor(G){super(G);this.logger_=S(`channel_signal:${this.name}`),this.logger_.logMethod?.("constructor")}dispatch(...G){let[H,Q]=G;this.logger_.logMethodArgs?.("dispatch",{name:H,payload:Q}),this.checkDestroyed_(),b(()=>this.route__(H,Q))}on(G,H,Q){this.logger_.logMethodArgs?.("on",{name:G}),this.checkDestroyed_();let X=this.namedHandlers__.get(G);if(!X)X=new Set,this.namedHandlers__.set(G,X);let Y={handler:H,once:Q?.once??!1};return X.add(Y),{unsubscribe:()=>{if(X.delete(Y),X.size===0)this.namedHandlers__.delete(G)}}}subscribe(G,H){return this.logger_.logMethodArgs?.("subscribe",H),super.subscribe(G,H)}route__(G,H){if(this.isDestroyed)return;let Q=this.namedHandlers__.get(G);if(Q?.size)for(let X of Q){if(X.once){if(Q.delete(X),Q.size===0)this.namedHandlers__.delete(G)}try{X.handler(H)}catch(Y){this.logger_.error("route__","sync_named_handler_failed",Y)}}this.notify_({name:G,payload:H})}destroy(){this.namedHandlers__.clear(),super.destroy()}}function $G(G){return new O(G)}function U(G){return new Z(G)}function MG(G){return new R(G)}function EG(G){return new z(G)}function IG(G){return new $(G)}function CG(G){return new q(G)}function kG(G){return new _(G)}function SG(G){return new L(G)}import{createDebouncer as v}from"@alwatr/debounce";function hG(G,H){let Q=H.name??`${G.name}_debounced`,X=new Z({name:Q,initialValue:G.get(),onDestroy(){F.unsubscribe(),Y.cancel(),H.onDestroy?.(),H=null}}),Y=v({...H,thisContext:X,func:X.set}),F=G.subscribe(Y.trigger,{receivePrevious:!1});return X}function dG(G,H,Q=`${G.name}_filtered`){let X=G.get(),Y=H(X)?X:void 0,F=U({name:Q,initialValue:Y,onDestroy(){B.unsubscribe()}}),B=G.subscribe((J)=>{if(H(J))F.set(J)});return F}export{U as createStateSignal,kG as createSessionStateSignal,CG as createPersistentStateSignal,dG as createFilteredSignal,$G as createEventSignal,IG as createEffect,EG as createDerivedSignal,hG as createDebouncedSignal,MG as createComputedSignal,SG as createChannelSignal,Z as StateSignal,K as SignalBase,_ as SessionStateSignal,q as PersistentStateSignal,O as EventSignal,$ as EffectSignal,z as DerivedSignal,R as ComputedSignal,L as ChannelSignal};
3
3
 
4
- //# debugId=B292A92FF8D8C98B64756E2164756E21
4
+ //# debugId=2DB7724539464C7064756E2164756E21
5
5
  //# sourceMappingURL=main.js.map