@alwatr/signal 5.2.1 โ 5.2.2
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/CHANGELOG.md +18 -0
- package/dist/core/effect-signal.d.ts.map +1 -1
- package/dist/core/state-signal.d.ts.map +1 -1
- package/dist/main.cjs +2 -621
- package/dist/main.cjs.map +2 -2
- package/dist/main.mjs +2 -586
- package/dist/main.mjs.map +2 -2
- package/package.json +6 -6
- package/src/core/computed-signal.test.js +16 -0
- package/src/core/state-signal.test.js +19 -4
- package/src/operators/debounce.test.js +206 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [5.2.2](https://github.com/Alwatr/flux/compare/v5.2.1...v5.2.2) (2025-09-15)
|
|
7
|
+
|
|
8
|
+
### ๐ Bug Fixes
|
|
9
|
+
|
|
10
|
+
* update subscription to prevent receiving previous value in debounced signal ([044780d](https://github.com/Alwatr/flux/commit/044780d35427a97711788224e60e209fb53dea53))
|
|
11
|
+
* update subscription to trigger debouncer with value from source signal ([a7e8eff](https://github.com/Alwatr/flux/commit/a7e8effd7e963aaf905afae08a652d7abe222c3a))
|
|
12
|
+
|
|
13
|
+
### ๐จ Code Refactoring
|
|
14
|
+
|
|
15
|
+
* improve logging in subscribe method to pass options directly ([e026dbf](https://github.com/Alwatr/flux/commit/e026dbf74ca96ec6d878bd5fb08f4939c46d08f2))
|
|
16
|
+
* simplify signalId assignment using nullish coalescing operator ([0578c85](https://github.com/Alwatr/flux/commit/0578c854677df2fe0a62e5fbbfa017856d82b611))
|
|
17
|
+
* update logging in subscribe method to pass options directly ([a7e32f2](https://github.com/Alwatr/flux/commit/a7e32f20df6b12c1c9dd06feaf01fca8170a5346))
|
|
18
|
+
|
|
19
|
+
### ๐งน Miscellaneous Chores
|
|
20
|
+
|
|
21
|
+
* update @alwatr/debounce dependency to version 1.1.1 ([c2e2ae4](https://github.com/Alwatr/flux/commit/c2e2ae4fe54f8fdd482bd53b598f5e88570a26f2))
|
|
22
|
+
* update package dependencies to latest versions ([a517c82](https://github.com/Alwatr/flux/commit/a517c82b99073a65a8470da428dfd288080b7ea5))
|
|
23
|
+
|
|
6
24
|
## [5.2.1](https://github.com/Alwatr/flux/compare/v5.2.0...v5.2.1) (2025-09-15)
|
|
7
25
|
|
|
8
26
|
### โก Performance Improvements
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"effect-signal.d.ts","sourceRoot":"","sources":["../../src/core/effect-signal.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,kBAAkB,EAAE,aAAa,EAAkB,MAAM,YAAY,CAAC;AAEnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,qBAAa,YAAa,YAAW,aAAa;IAwC7B,SAAS,CAAC,OAAO,EAAE,kBAAkB;IAvCxD;;OAEG;IACH,SAAgB,QAAQ,
|
|
1
|
+
{"version":3,"file":"effect-signal.d.ts","sourceRoot":"","sources":["../../src/core/effect-signal.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,kBAAkB,EAAE,aAAa,EAAkB,MAAM,YAAY,CAAC;AAEnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,qBAAa,YAAa,YAAW,aAAa;IAwC7B,SAAS,CAAC,OAAO,EAAE,kBAAkB;IAvCxD;;OAEG;IACH,SAAgB,QAAQ,SAA2F;IAEnH;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,OAAO,wCAAmD;IAE7E;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAyB;IAEnE;;;OAGG;IACH,OAAO,CAAC,WAAW,CAAS;IAE5B;;;OAGG;IACH,OAAO,CAAC,aAAa,CAAS;IAE9B;;;;;OAKG;IACH,IAAW,WAAW,IAAI,OAAO,CAEhC;gBAE4B,OAAO,EAAE,kBAAkB;IAiBxD;;;;;;;OAOG;cACa,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAmCnD;;;;;;OAMG;IACI,OAAO,IAAI,IAAI;CAmBvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-signal.d.ts","sourceRoot":"","sources":["../../src/core/state-signal.ts"],"names":[],"mappings":"AAGA,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,wCAAkD;gBAEhD,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAM/C;;;;;;;OAOG;IACI,GAAG,IAAI,CAAC;IAKf;;;;;;;;;;;;;;OAcG;IACI,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI;IAe7B;;;;;;;;;;;;;;OAcG;IACI,MAAM,CAAC,OAAO,EAAE,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI;IAQrD;;;;;;;;;OASG;IACa,SAAS,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,gBAAqB,GAAG,eAAe;
|
|
1
|
+
{"version":3,"file":"state-signal.d.ts","sourceRoot":"","sources":["../../src/core/state-signal.ts"],"names":[],"mappings":"AAGA,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,wCAAkD;gBAEhD,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAM/C;;;;;;;OAOG;IACI,GAAG,IAAI,CAAC;IAKf;;;;;;;;;;;;;;OAcG;IACI,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI;IAe7B;;;;;;;;;;;;;;OAcG;IACI,MAAM,CAAC,OAAO,EAAE,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI;IAQrD;;;;;;;;;OASG;IACa,SAAS,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,gBAAqB,GAAG,eAAe;IA2BzG;;;OAGG;IACa,OAAO,IAAI,IAAI;CAIhC"}
|
package/dist/main.cjs
CHANGED
|
@@ -1,622 +1,3 @@
|
|
|
1
|
-
/* @alwatr/signal v5.2.
|
|
2
|
-
"use strict";
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __export = (target, all) => {
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
-
|
|
21
|
-
// src/main.ts
|
|
22
|
-
var main_exports = {};
|
|
23
|
-
__export(main_exports, {
|
|
24
|
-
ComputedSignal: () => ComputedSignal,
|
|
25
|
-
EffectSignal: () => EffectSignal,
|
|
26
|
-
EventSignal: () => EventSignal,
|
|
27
|
-
SignalBase: () => SignalBase,
|
|
28
|
-
StateSignal: () => StateSignal,
|
|
29
|
-
createComputedSignal: () => createComputedSignal,
|
|
30
|
-
createDebouncedSignal: () => createDebouncedSignal,
|
|
31
|
-
createEffect: () => createEffect,
|
|
32
|
-
createEventSignal: () => createEventSignal,
|
|
33
|
-
createStateSignal: () => createStateSignal
|
|
34
|
-
});
|
|
35
|
-
module.exports = __toCommonJS(main_exports);
|
|
36
|
-
|
|
37
|
-
// src/core/signal-base.ts
|
|
38
|
-
var SignalBase = class {
|
|
39
|
-
constructor(config_) {
|
|
40
|
-
this.config_ = config_;
|
|
41
|
-
/**
|
|
42
|
-
* The unique identifier for this signal instance.
|
|
43
|
-
* Useful for debugging and logging.
|
|
44
|
-
*/
|
|
45
|
-
this.signalId = this.config_.signalId;
|
|
46
|
-
/**
|
|
47
|
-
* The list of observers (listeners) subscribed to this signal.
|
|
48
|
-
* @protected
|
|
49
|
-
*/
|
|
50
|
-
this.observers_ = [];
|
|
51
|
-
/**
|
|
52
|
-
* A flag indicating whether the signal has been destroyed.
|
|
53
|
-
* @private
|
|
54
|
-
*/
|
|
55
|
-
this.isDestroyed__ = false;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Indicates whether the signal has been destroyed.
|
|
59
|
-
* A destroyed signal cannot be used and will throw an error if interacted with.
|
|
60
|
-
*
|
|
61
|
-
* @returns `true` if the signal is destroyed, `false` otherwise.
|
|
62
|
-
*/
|
|
63
|
-
get isDestroyed() {
|
|
64
|
-
return this.isDestroyed__;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Removes a specific observer from the observers list.
|
|
68
|
-
*
|
|
69
|
-
* @param observer The observer instance to remove.
|
|
70
|
-
* @protected
|
|
71
|
-
*/
|
|
72
|
-
removeObserver_(observer) {
|
|
73
|
-
this.logger_.logMethod?.("removeObserver_");
|
|
74
|
-
if (this.isDestroyed__) {
|
|
75
|
-
this.logger_.incident?.("removeObserver_", "remove_observer_on_destroyed_signal");
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const index = this.observers_.indexOf(observer);
|
|
79
|
-
if (index !== -1) {
|
|
80
|
-
this.observers_.splice(index, 1);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Subscribes a listener function to this signal.
|
|
85
|
-
*
|
|
86
|
-
* The listener will be called whenever the signal is notified (e.g., when `dispatch` or `set` is called).
|
|
87
|
-
*
|
|
88
|
-
* @param callback The function to be called when the signal is dispatched.
|
|
89
|
-
* @param options Subscription options to customize the behavior (e.g., `once`, `priority`).
|
|
90
|
-
* @returns A `SubscribeResult` object with an `unsubscribe` method to remove the listener.
|
|
91
|
-
*/
|
|
92
|
-
subscribe(callback, options) {
|
|
93
|
-
this.logger_.logMethodArgs?.("subscribe.base", { options });
|
|
94
|
-
this.checkDestroyed_();
|
|
95
|
-
const observer = { callback, options };
|
|
96
|
-
if (options?.priority) {
|
|
97
|
-
this.observers_.unshift(observer);
|
|
98
|
-
} else {
|
|
99
|
-
this.observers_.push(observer);
|
|
100
|
-
}
|
|
101
|
-
return {
|
|
102
|
-
unsubscribe: () => this.removeObserver_(observer)
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Notifies all registered observers about a new value.
|
|
107
|
-
*
|
|
108
|
-
* This method iterates through a snapshot of the current observers to prevent issues
|
|
109
|
-
* with subscriptions changing during notification (e.g., an observer unsubscribing itself).
|
|
110
|
-
*
|
|
111
|
-
* @param value The new value to notify observers about.
|
|
112
|
-
* @protected
|
|
113
|
-
*/
|
|
114
|
-
notify_(value) {
|
|
115
|
-
this.logger_.logMethodArgs?.("notify_", value);
|
|
116
|
-
if (this.isDestroyed__) {
|
|
117
|
-
this.logger_.incident?.("notify_", "notify_on_destroyed_signal");
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
const currentObservers = [...this.observers_];
|
|
121
|
-
for (const observer of currentObservers) {
|
|
122
|
-
if (observer.options?.once) {
|
|
123
|
-
this.removeObserver_(observer);
|
|
124
|
-
}
|
|
125
|
-
try {
|
|
126
|
-
const result = observer.callback(value);
|
|
127
|
-
if (result instanceof Promise) {
|
|
128
|
-
result.catch((err) => this.logger_.error("notify_", "async_callback_failed", err, { observer }));
|
|
129
|
-
}
|
|
130
|
-
} catch (err) {
|
|
131
|
-
this.logger_.error("notify_", "sync_callback_failed", err);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Returns a Promise that resolves with the next value dispatched by the signal.
|
|
137
|
-
* This provides an elegant way to wait for a single, future event using `async/await`.
|
|
138
|
-
*
|
|
139
|
-
* @returns A Promise that resolves with the next dispatched value.
|
|
140
|
-
*
|
|
141
|
-
* @example
|
|
142
|
-
* async function onButtonClick() {
|
|
143
|
-
* console.log('Waiting for the next signal...');
|
|
144
|
-
* const nextValue = await mySignal.untilNext();
|
|
145
|
-
* console.log('Signal received:', nextValue);
|
|
146
|
-
* }
|
|
147
|
-
*/
|
|
148
|
-
untilNext() {
|
|
149
|
-
this.logger_.logMethod?.("untilNext");
|
|
150
|
-
this.checkDestroyed_();
|
|
151
|
-
return new Promise((resolve) => {
|
|
152
|
-
this.subscribe(resolve, {
|
|
153
|
-
once: true,
|
|
154
|
-
priority: true,
|
|
155
|
-
// Resolve the promise before other listeners are called.
|
|
156
|
-
receivePrevious: false
|
|
157
|
-
// We only want the *next* value, not the current one.
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Destroys the signal, clearing all its listeners and making it inactive.
|
|
163
|
-
*
|
|
164
|
-
* After destruction, any interaction with the signal (like `subscribe` or `untilNext`)
|
|
165
|
-
* will throw an error. This is crucial for preventing memory leaks by allowing
|
|
166
|
-
* garbage collection of the signal and its observers.
|
|
167
|
-
*/
|
|
168
|
-
destroy() {
|
|
169
|
-
this.logger_.logMethod?.("destroy");
|
|
170
|
-
if (this.isDestroyed__) {
|
|
171
|
-
this.logger_.incident?.("destroy_", "double_destroy_attempt");
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
this.isDestroyed__ = true;
|
|
175
|
-
this.observers_.length = 0;
|
|
176
|
-
this.config_.onDestroy?.();
|
|
177
|
-
this.config_ = null;
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Throws an error if the signal has been destroyed.
|
|
181
|
-
* This is a safeguard to prevent interaction with a defunct signal.
|
|
182
|
-
* @protected
|
|
183
|
-
*/
|
|
184
|
-
checkDestroyed_() {
|
|
185
|
-
if (this.isDestroyed__) {
|
|
186
|
-
this.logger_.accident("checkDestroyed_", "attempt_to_use_destroyed_signal");
|
|
187
|
-
throw new Error(`Cannot interact with a destroyed signal (id: ${this.signalId})`);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
// src/core/event-signal.ts
|
|
193
|
-
var import_delay = require("@alwatr/delay");
|
|
194
|
-
var import_logger = require("@alwatr/logger");
|
|
195
|
-
var EventSignal = class extends SignalBase {
|
|
196
|
-
constructor(config) {
|
|
197
|
-
super(config);
|
|
198
|
-
/**
|
|
199
|
-
* The logger instance for this signal.
|
|
200
|
-
* @protected
|
|
201
|
-
*/
|
|
202
|
-
this.logger_ = (0, import_logger.createLogger)(`event-signal: ${this.signalId}`);
|
|
203
|
-
this.logger_.logMethod?.("constructor");
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Dispatches an event with an optional payload to all active listeners.
|
|
207
|
-
* The notification is scheduled as a microtask to prevent blocking and ensure
|
|
208
|
-
* a consistent, non-blocking flow.
|
|
209
|
-
*
|
|
210
|
-
* @param payload The data to send with the event.
|
|
211
|
-
*/
|
|
212
|
-
dispatch(payload) {
|
|
213
|
-
this.logger_.logMethodArgs?.("dispatch", { payload });
|
|
214
|
-
this.checkDestroyed_();
|
|
215
|
-
import_delay.delay.nextMicrotask().then(() => this.notify_(payload));
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
// src/core/state-signal.ts
|
|
220
|
-
var import_delay2 = require("@alwatr/delay");
|
|
221
|
-
var import_logger2 = require("@alwatr/logger");
|
|
222
|
-
var StateSignal = class extends SignalBase {
|
|
223
|
-
constructor(config) {
|
|
224
|
-
super(config);
|
|
225
|
-
/**
|
|
226
|
-
* The logger instance for this signal.
|
|
227
|
-
* @protected
|
|
228
|
-
*/
|
|
229
|
-
this.logger_ = (0, import_logger2.createLogger)(`state-signal: ${this.signalId}`);
|
|
230
|
-
this.value__ = config.initialValue;
|
|
231
|
-
this.logger_.logMethodArgs?.("constructor", { initialValue: this.value__ });
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* Retrieves the current value of the signal.
|
|
235
|
-
*
|
|
236
|
-
* @returns The current value.
|
|
237
|
-
*
|
|
238
|
-
* @example
|
|
239
|
-
* console.log(mySignal.get());
|
|
240
|
-
*/
|
|
241
|
-
get() {
|
|
242
|
-
this.checkDestroyed_();
|
|
243
|
-
return this.value__;
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Updates the signal's value and notifies all active listeners.
|
|
247
|
-
*
|
|
248
|
-
* The notification is scheduled as a microtask, which means the update is deferred
|
|
249
|
-
* slightly to batch multiple synchronous changes.
|
|
250
|
-
*
|
|
251
|
-
* @param newValue The new value to set.
|
|
252
|
-
*
|
|
253
|
-
* @example
|
|
254
|
-
* // For primitive types
|
|
255
|
-
* mySignal.set(42);
|
|
256
|
-
*
|
|
257
|
-
* // For object types, it's best practice to set an immutable new object.
|
|
258
|
-
* mySignal.set({ ...mySignal.get(), property: 'new-value' });
|
|
259
|
-
*/
|
|
260
|
-
set(newValue) {
|
|
261
|
-
this.logger_.logMethodArgs?.("set", { newValue });
|
|
262
|
-
this.checkDestroyed_();
|
|
263
|
-
if (Object.is(this.value__, newValue) && (typeof newValue !== "object" || newValue === null)) {
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
this.value__ = newValue;
|
|
267
|
-
import_delay2.delay.nextMicrotask().then(() => this.notify_(newValue));
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* Updates the signal's value based on its previous value.
|
|
271
|
-
*
|
|
272
|
-
* This method is particularly useful for state transitions that depend on the current value,
|
|
273
|
-
* especially for objects or arrays, as it promotes an immutable update pattern.
|
|
274
|
-
*
|
|
275
|
-
* @param updater A function that receives the current value and returns the new value.
|
|
276
|
-
*
|
|
277
|
-
* @example
|
|
278
|
-
* // For a counter
|
|
279
|
-
* counterSignal.update(current => current + 1);
|
|
280
|
-
*
|
|
281
|
-
* // For an object state
|
|
282
|
-
* userSignal.update(currentUser => ({ ...currentUser, loggedIn: true }));
|
|
283
|
-
*/
|
|
284
|
-
update(updater) {
|
|
285
|
-
this.logger_.logMethod?.("update");
|
|
286
|
-
this.checkDestroyed_();
|
|
287
|
-
this.set(updater(this.value__));
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Subscribes a listener to this signal.
|
|
291
|
-
*
|
|
292
|
-
* By default, the listener is immediately called with the signal's current value (`receivePrevious: true`).
|
|
293
|
-
* This behavior can be customized via the `options` parameter.
|
|
294
|
-
*
|
|
295
|
-
* @param callback The function to be called when the signal's value changes.
|
|
296
|
-
* @param options Subscription options, including `receivePrevious` and `once`.
|
|
297
|
-
* @returns An object with an `unsubscribe` method to remove the listener.
|
|
298
|
-
*/
|
|
299
|
-
subscribe(callback, options = {}) {
|
|
300
|
-
this.logger_.logMethodArgs?.("subscribe", { options });
|
|
301
|
-
this.checkDestroyed_();
|
|
302
|
-
if (options.receivePrevious !== false) {
|
|
303
|
-
import_delay2.delay.nextMicrotask().then(() => callback(this.value__)).catch((err) => this.logger_.error("subscribe", "immediate_callback_failed", err));
|
|
304
|
-
if (options.once) {
|
|
305
|
-
return { unsubscribe: () => {
|
|
306
|
-
} };
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
return super.subscribe(callback, options);
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* Destroys the signal, clearing its value and all listeners.
|
|
313
|
-
* This is crucial for memory management to prevent leaks.
|
|
314
|
-
*/
|
|
315
|
-
destroy() {
|
|
316
|
-
this.value__ = null;
|
|
317
|
-
super.destroy();
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
// src/core/computed-signal.ts
|
|
322
|
-
var import_delay3 = require("@alwatr/delay");
|
|
323
|
-
var import_logger3 = require("@alwatr/logger");
|
|
324
|
-
var ComputedSignal = class {
|
|
325
|
-
constructor(config_) {
|
|
326
|
-
this.config_ = config_;
|
|
327
|
-
/**
|
|
328
|
-
* The unique identifier for this signal instance.
|
|
329
|
-
*/
|
|
330
|
-
this.signalId = this.config_.signalId;
|
|
331
|
-
/**
|
|
332
|
-
* The logger instance for this signal.
|
|
333
|
-
* @protected
|
|
334
|
-
*/
|
|
335
|
-
this.logger_ = (0, import_logger3.createLogger)(`computed-signal: ${this.signalId}`);
|
|
336
|
-
/**
|
|
337
|
-
* The internal `StateSignal` that holds the computed value.
|
|
338
|
-
* This is how the computed signal provides `.get()` and `.subscribe()` methods.
|
|
339
|
-
* @protected
|
|
340
|
-
*/
|
|
341
|
-
this.internalSignal_ = new StateSignal({
|
|
342
|
-
signalId: `${this.signalId}-internal`,
|
|
343
|
-
initialValue: this.config_.get()
|
|
344
|
-
});
|
|
345
|
-
/**
|
|
346
|
-
* A list of subscriptions to dependency signals.
|
|
347
|
-
* @private
|
|
348
|
-
*/
|
|
349
|
-
this.dependencySubscriptions__ = [];
|
|
350
|
-
/**
|
|
351
|
-
* A flag to prevent concurrent recalculations.
|
|
352
|
-
* @private
|
|
353
|
-
*/
|
|
354
|
-
this.isRecalculating__ = false;
|
|
355
|
-
this.logger_.logMethod?.("constructor");
|
|
356
|
-
this.recalculate_ = this.recalculate_.bind(this);
|
|
357
|
-
for (const signal of config_.deps) {
|
|
358
|
-
this.dependencySubscriptions__.push(signal.subscribe(this.recalculate_, { receivePrevious: false }));
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
/**
|
|
362
|
-
* The current value of the computed signal.
|
|
363
|
-
* Accessing this property returns the memoized value and does not trigger a recalculation.
|
|
364
|
-
*
|
|
365
|
-
* @returns The current computed value.
|
|
366
|
-
* @throws {Error} If accessed after the signal has been destroyed.
|
|
367
|
-
*/
|
|
368
|
-
get() {
|
|
369
|
-
return this.internalSignal_.get();
|
|
370
|
-
}
|
|
371
|
-
/**
|
|
372
|
-
* Indicates whether the computed signal has been destroyed.
|
|
373
|
-
* A destroyed signal cannot be used and will throw an error if interacted with.
|
|
374
|
-
* @returns `true` if the signal is destroyed, `false` otherwise.
|
|
375
|
-
*/
|
|
376
|
-
get isDestroyed() {
|
|
377
|
-
return this.internalSignal_.isDestroyed;
|
|
378
|
-
}
|
|
379
|
-
/**
|
|
380
|
-
* Subscribes a listener to this signal.
|
|
381
|
-
* The listener will be called whenever the computed value changes.
|
|
382
|
-
*
|
|
383
|
-
* @param callback The function to be called with the new value.
|
|
384
|
-
* @param options Subscription options.
|
|
385
|
-
* @returns A `SubscribeResult` object with an `unsubscribe` method.
|
|
386
|
-
*/
|
|
387
|
-
subscribe(callback, options) {
|
|
388
|
-
return this.internalSignal_.subscribe(callback, options);
|
|
389
|
-
}
|
|
390
|
-
/**
|
|
391
|
-
* Returns a Promise that resolves with the next computed value.
|
|
392
|
-
*
|
|
393
|
-
* @returns A Promise that resolves with the next value.
|
|
394
|
-
*/
|
|
395
|
-
untilNext() {
|
|
396
|
-
return this.internalSignal_.untilNext();
|
|
397
|
-
}
|
|
398
|
-
/**
|
|
399
|
-
* Permanently disposes of the computed signal.
|
|
400
|
-
*
|
|
401
|
-
* This is a critical cleanup step. It unsubscribes from all dependency signals,
|
|
402
|
-
* stopping future recalculations and allowing the signal to be garbage collected.
|
|
403
|
-
* Failure to call `destroy()` will result in memory leaks.
|
|
404
|
-
*
|
|
405
|
-
* After `destroy()` is called, any attempt to access `.get()` or `.subscribe()` will throw an error.
|
|
406
|
-
*/
|
|
407
|
-
destroy() {
|
|
408
|
-
this.logger_.logMethod?.("destroy");
|
|
409
|
-
if (this.isDestroyed) {
|
|
410
|
-
this.logger_.incident?.("destroy", "already_destroyed");
|
|
411
|
-
return;
|
|
412
|
-
}
|
|
413
|
-
for (const subscription of this.dependencySubscriptions__) {
|
|
414
|
-
subscription.unsubscribe();
|
|
415
|
-
}
|
|
416
|
-
this.dependencySubscriptions__.length = 0;
|
|
417
|
-
this.internalSignal_.destroy();
|
|
418
|
-
this.config_.onDestroy?.();
|
|
419
|
-
this.config_ = null;
|
|
420
|
-
}
|
|
421
|
-
/**
|
|
422
|
-
* Schedules a recalculation of the signal's value.
|
|
423
|
-
*
|
|
424
|
-
* This method batches updates using a macrotask (`delay.nextMacrotask`) to ensure the
|
|
425
|
-
* `get` function runs only once per event loop tick, even if multiple dependencies
|
|
426
|
-
* change in the same synchronous block of code.
|
|
427
|
-
* @protected
|
|
428
|
-
*/
|
|
429
|
-
async recalculate_() {
|
|
430
|
-
this.logger_.logMethod?.("recalculate_");
|
|
431
|
-
if (this.internalSignal_.isDestroyed) {
|
|
432
|
-
this.logger_.incident?.("recalculate_", "recalculate_on_destroyed_signal");
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
if (this.isRecalculating__) {
|
|
436
|
-
this.logger_.logStep?.("recalculate_", "skipping_recalculation_already_scheduled");
|
|
437
|
-
return;
|
|
438
|
-
}
|
|
439
|
-
this.isRecalculating__ = true;
|
|
440
|
-
try {
|
|
441
|
-
await import_delay3.delay.nextMacrotask();
|
|
442
|
-
if (this.isDestroyed) {
|
|
443
|
-
this.logger_.incident?.("recalculate_", "destroyed_during_delay");
|
|
444
|
-
this.isRecalculating__ = false;
|
|
445
|
-
return;
|
|
446
|
-
}
|
|
447
|
-
this.logger_.logStep?.("recalculate_", "recalculating_value");
|
|
448
|
-
this.internalSignal_.set(this.config_.get());
|
|
449
|
-
} catch (err) {
|
|
450
|
-
this.logger_.error("recalculate_", "recalculation_failed", err);
|
|
451
|
-
}
|
|
452
|
-
this.isRecalculating__ = false;
|
|
453
|
-
}
|
|
454
|
-
};
|
|
455
|
-
|
|
456
|
-
// src/core/effect-signal.ts
|
|
457
|
-
var import_delay4 = require("@alwatr/delay");
|
|
458
|
-
var import_logger4 = require("@alwatr/logger");
|
|
459
|
-
var EffectSignal = class {
|
|
460
|
-
constructor(config_) {
|
|
461
|
-
this.config_ = config_;
|
|
462
|
-
/**
|
|
463
|
-
* The unique identifier for this signal instance.
|
|
464
|
-
*/
|
|
465
|
-
this.signalId = this.config_.signalId ? this.config_.signalId : `[${this.config_.deps.map((dep) => dep.signalId).join(", ")}]`;
|
|
466
|
-
/**
|
|
467
|
-
* The logger instance for this signal.
|
|
468
|
-
* @protected
|
|
469
|
-
*/
|
|
470
|
-
this.logger_ = (0, import_logger4.createLogger)(`effect-signal: ${this.signalId}`);
|
|
471
|
-
/**
|
|
472
|
-
* A list of subscriptions to dependency signals.
|
|
473
|
-
* @private
|
|
474
|
-
*/
|
|
475
|
-
this.dependencySubscriptions__ = [];
|
|
476
|
-
/**
|
|
477
|
-
* A flag to prevent concurrent executions of the effect.
|
|
478
|
-
* @private
|
|
479
|
-
*/
|
|
480
|
-
this.isRunning__ = false;
|
|
481
|
-
/**
|
|
482
|
-
* A flag indicating whether the effect has been destroyed.
|
|
483
|
-
* @private
|
|
484
|
-
*/
|
|
485
|
-
this.isDestroyed__ = false;
|
|
486
|
-
this.logger_.logMethod?.("constructor");
|
|
487
|
-
this.scheduleExecution_ = this.scheduleExecution_.bind(this);
|
|
488
|
-
for (const signal of config_.deps) {
|
|
489
|
-
this.dependencySubscriptions__.push(signal.subscribe(this.scheduleExecution_, { receivePrevious: false }));
|
|
490
|
-
}
|
|
491
|
-
if (config_.runImmediately === true) {
|
|
492
|
-
void this.scheduleExecution_();
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
/**
|
|
496
|
-
* Indicates whether the effect signal has been destroyed.
|
|
497
|
-
* A destroyed signal will no longer execute its effect and cannot be reused.
|
|
498
|
-
*
|
|
499
|
-
* @returns `true` if the signal is destroyed, `false` otherwise.
|
|
500
|
-
*/
|
|
501
|
-
get isDestroyed() {
|
|
502
|
-
return this.isDestroyed__;
|
|
503
|
-
}
|
|
504
|
-
/**
|
|
505
|
-
* Schedules the execution of the effect's `run` function.
|
|
506
|
-
*
|
|
507
|
-
* This method batches updates using a macrotask (`delay.nextMacrotask`) to ensure the
|
|
508
|
-
* `run` function executes only once per event loop tick, even if multiple
|
|
509
|
-
* dependencies change simultaneously.
|
|
510
|
-
* @protected
|
|
511
|
-
*/
|
|
512
|
-
async scheduleExecution_() {
|
|
513
|
-
this.logger_.logMethod?.("scheduleExecution_");
|
|
514
|
-
if (this.isDestroyed__) {
|
|
515
|
-
this.logger_.incident?.("scheduleExecution_", "schedule_execution_on_destroyed_signal");
|
|
516
|
-
return;
|
|
517
|
-
}
|
|
518
|
-
if (this.isRunning__) {
|
|
519
|
-
this.logger_.logStep?.("scheduleExecution_", "skipped_because_already_running");
|
|
520
|
-
return;
|
|
521
|
-
}
|
|
522
|
-
this.isRunning__ = true;
|
|
523
|
-
try {
|
|
524
|
-
await import_delay4.delay.nextMacrotask();
|
|
525
|
-
if (this.isDestroyed__) {
|
|
526
|
-
this.logger_.incident?.("scheduleExecution_", "destroyed_during_delay");
|
|
527
|
-
this.isRunning__ = false;
|
|
528
|
-
return;
|
|
529
|
-
}
|
|
530
|
-
this.logger_.logStep?.("scheduleExecution_", "executing_effect");
|
|
531
|
-
await this.config_.run();
|
|
532
|
-
} catch (err) {
|
|
533
|
-
this.logger_.error("scheduleExecution_", "effect_failed", err);
|
|
534
|
-
}
|
|
535
|
-
this.isRunning__ = false;
|
|
536
|
-
}
|
|
537
|
-
/**
|
|
538
|
-
* Permanently disposes of the effect signal.
|
|
539
|
-
*
|
|
540
|
-
* This is a critical cleanup step. It unsubscribes from all dependency signals,
|
|
541
|
-
* stopping any future executions of the effect and allowing it to be garbage collected.
|
|
542
|
-
* Failure to call `destroy()` will result in memory leaks and potentially unwanted side effects.
|
|
543
|
-
*/
|
|
544
|
-
destroy() {
|
|
545
|
-
this.logger_.logMethod?.("destroy");
|
|
546
|
-
if (this.isDestroyed__) {
|
|
547
|
-
this.logger_.incident?.("destroy", "already_destroyed");
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
550
|
-
this.isDestroyed__ = true;
|
|
551
|
-
for (const subscription of this.dependencySubscriptions__) {
|
|
552
|
-
subscription.unsubscribe();
|
|
553
|
-
}
|
|
554
|
-
this.dependencySubscriptions__.length = 0;
|
|
555
|
-
this.config_.onDestroy?.();
|
|
556
|
-
this.config_ = null;
|
|
557
|
-
}
|
|
558
|
-
};
|
|
559
|
-
|
|
560
|
-
// src/creators/event.ts
|
|
561
|
-
function createEventSignal(config) {
|
|
562
|
-
return new EventSignal(config);
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
// src/creators/state.ts
|
|
566
|
-
function createStateSignal(config) {
|
|
567
|
-
return new StateSignal(config);
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
// src/creators/computed.ts
|
|
571
|
-
function createComputedSignal(config) {
|
|
572
|
-
return new ComputedSignal(config);
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
// src/creators/effect.ts
|
|
576
|
-
function createEffect(config) {
|
|
577
|
-
return new EffectSignal(config);
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
// src/operators/debounce.ts
|
|
581
|
-
var import_debounce = require("@alwatr/debounce");
|
|
582
|
-
function createDebouncedSignal(sourceSignal, config) {
|
|
583
|
-
const signalId = config.signalId ?? `${sourceSignal.signalId}-debounced`;
|
|
584
|
-
const internalSignal = new StateSignal({
|
|
585
|
-
signalId: `${signalId}-internal`,
|
|
586
|
-
initialValue: sourceSignal.get()
|
|
587
|
-
});
|
|
588
|
-
const debouncer = (0, import_debounce.createDebouncer)({
|
|
589
|
-
...config,
|
|
590
|
-
func: (value) => {
|
|
591
|
-
internalSignal.set(value);
|
|
592
|
-
}
|
|
593
|
-
});
|
|
594
|
-
const subscription = sourceSignal.subscribe(debouncer.trigger);
|
|
595
|
-
return createComputedSignal({
|
|
596
|
-
signalId,
|
|
597
|
-
deps: [internalSignal],
|
|
598
|
-
get: () => internalSignal.get(),
|
|
599
|
-
onDestroy: () => {
|
|
600
|
-
if (internalSignal.isDestroyed) return;
|
|
601
|
-
subscription.unsubscribe();
|
|
602
|
-
debouncer.cancel();
|
|
603
|
-
internalSignal.destroy();
|
|
604
|
-
config.onDestroy?.();
|
|
605
|
-
config = null;
|
|
606
|
-
}
|
|
607
|
-
});
|
|
608
|
-
}
|
|
609
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
610
|
-
0 && (module.exports = {
|
|
611
|
-
ComputedSignal,
|
|
612
|
-
EffectSignal,
|
|
613
|
-
EventSignal,
|
|
614
|
-
SignalBase,
|
|
615
|
-
StateSignal,
|
|
616
|
-
createComputedSignal,
|
|
617
|
-
createDebouncedSignal,
|
|
618
|
-
createEffect,
|
|
619
|
-
createEventSignal,
|
|
620
|
-
createStateSignal
|
|
621
|
-
});
|
|
1
|
+
/* @alwatr/signal v5.2.2 */
|
|
2
|
+
"use strict";var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var main_exports={};__export(main_exports,{ComputedSignal:()=>ComputedSignal,EffectSignal:()=>EffectSignal,EventSignal:()=>EventSignal,SignalBase:()=>SignalBase,StateSignal:()=>StateSignal,createComputedSignal:()=>createComputedSignal,createDebouncedSignal:()=>createDebouncedSignal,createEffect:()=>createEffect,createEventSignal:()=>createEventSignal,createStateSignal:()=>createStateSignal});module.exports=__toCommonJS(main_exports);var SignalBase=class{constructor(config_){this.config_=config_;this.signalId=this.config_.signalId;this.observers_=[];this.isDestroyed__=false}get isDestroyed(){return this.isDestroyed__}removeObserver_(observer){this.logger_.logMethod?.("removeObserver_");if(this.isDestroyed__){this.logger_.incident?.("removeObserver_","remove_observer_on_destroyed_signal");return}const index=this.observers_.indexOf(observer);if(index!==-1){this.observers_.splice(index,1)}}subscribe(callback,options){this.logger_.logMethodArgs?.("subscribe.base",options);this.checkDestroyed_();const observer={callback,options};if(options?.priority){this.observers_.unshift(observer)}else{this.observers_.push(observer)}return{unsubscribe:()=>this.removeObserver_(observer)}}notify_(value){this.logger_.logMethodArgs?.("notify_",value);if(this.isDestroyed__){this.logger_.incident?.("notify_","notify_on_destroyed_signal");return}const currentObservers=[...this.observers_];for(const observer of currentObservers){if(observer.options?.once){this.removeObserver_(observer)}try{const result=observer.callback(value);if(result instanceof Promise){result.catch(err=>this.logger_.error("notify_","async_callback_failed",err,{observer}))}}catch(err){this.logger_.error("notify_","sync_callback_failed",err)}}}untilNext(){this.logger_.logMethod?.("untilNext");this.checkDestroyed_();return new Promise(resolve=>{this.subscribe(resolve,{once:true,priority:true,receivePrevious:false})})}destroy(){this.logger_.logMethod?.("destroy");if(this.isDestroyed__){this.logger_.incident?.("destroy_","double_destroy_attempt");return}this.isDestroyed__=true;this.observers_.length=0;this.config_.onDestroy?.();this.config_=null}checkDestroyed_(){if(this.isDestroyed__){this.logger_.accident("checkDestroyed_","attempt_to_use_destroyed_signal");throw new Error(`Cannot interact with a destroyed signal (id: ${this.signalId})`)}}};var import_delay=require("@alwatr/delay");var import_logger=require("@alwatr/logger");var EventSignal=class extends SignalBase{constructor(config){super(config);this.logger_=(0,import_logger.createLogger)(`event-signal: ${this.signalId}`);this.logger_.logMethod?.("constructor")}dispatch(payload){this.logger_.logMethodArgs?.("dispatch",{payload});this.checkDestroyed_();import_delay.delay.nextMicrotask().then(()=>this.notify_(payload))}};var import_delay2=require("@alwatr/delay");var import_logger2=require("@alwatr/logger");var StateSignal=class extends SignalBase{constructor(config){super(config);this.logger_=(0,import_logger2.createLogger)(`state-signal: ${this.signalId}`);this.value__=config.initialValue;this.logger_.logMethodArgs?.("constructor",{initialValue:this.value__})}get(){this.checkDestroyed_();return this.value__}set(newValue){this.logger_.logMethodArgs?.("set",{newValue});this.checkDestroyed_();if(Object.is(this.value__,newValue)&&(typeof newValue!=="object"||newValue===null)){return}this.value__=newValue;import_delay2.delay.nextMicrotask().then(()=>this.notify_(newValue))}update(updater){this.logger_.logMethod?.("update");this.checkDestroyed_();this.set(updater(this.value__))}subscribe(callback,options={}){this.logger_.logMethodArgs?.("subscribe",options);this.checkDestroyed_();if(options.receivePrevious!==false){import_delay2.delay.nextMicrotask().then(()=>{this.logger_.logStep?.("subscribe","immediate_callback");callback(this.value__)}).catch(err=>this.logger_.error("subscribe","immediate_callback_failed",err));if(options.once){return{unsubscribe:()=>{}}}}return super.subscribe(callback,options)}destroy(){this.value__=null;super.destroy()}};var import_delay3=require("@alwatr/delay");var import_logger3=require("@alwatr/logger");var ComputedSignal=class{constructor(config_){this.config_=config_;this.signalId=this.config_.signalId;this.logger_=(0,import_logger3.createLogger)(`computed-signal: ${this.signalId}`);this.internalSignal_=new StateSignal({signalId:`${this.signalId}-internal`,initialValue:this.config_.get()});this.dependencySubscriptions__=[];this.isRecalculating__=false;this.logger_.logMethod?.("constructor");this.recalculate_=this.recalculate_.bind(this);for(const signal of config_.deps){this.dependencySubscriptions__.push(signal.subscribe(this.recalculate_,{receivePrevious:false}))}}get(){return this.internalSignal_.get()}get isDestroyed(){return this.internalSignal_.isDestroyed}subscribe(callback,options){return this.internalSignal_.subscribe(callback,options)}untilNext(){return this.internalSignal_.untilNext()}destroy(){this.logger_.logMethod?.("destroy");if(this.isDestroyed){this.logger_.incident?.("destroy","already_destroyed");return}for(const subscription of this.dependencySubscriptions__){subscription.unsubscribe()}this.dependencySubscriptions__.length=0;this.internalSignal_.destroy();this.config_.onDestroy?.();this.config_=null}async recalculate_(){this.logger_.logMethod?.("recalculate_");if(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__=true;try{await import_delay3.delay.nextMacrotask();if(this.isDestroyed){this.logger_.incident?.("recalculate_","destroyed_during_delay");this.isRecalculating__=false;return}this.logger_.logStep?.("recalculate_","recalculating_value");this.internalSignal_.set(this.config_.get())}catch(err){this.logger_.error("recalculate_","recalculation_failed",err)}this.isRecalculating__=false}};var import_delay4=require("@alwatr/delay");var import_logger4=require("@alwatr/logger");var EffectSignal=class{constructor(config_){this.config_=config_;this.signalId=this.config_.signalId??`[${this.config_.deps.map(dep=>dep.signalId).join(", ")}]`;this.logger_=(0,import_logger4.createLogger)(`effect-signal: ${this.signalId}`);this.dependencySubscriptions__=[];this.isRunning__=false;this.isDestroyed__=false;this.logger_.logMethod?.("constructor");this.scheduleExecution_=this.scheduleExecution_.bind(this);for(const signal of config_.deps){this.dependencySubscriptions__.push(signal.subscribe(this.scheduleExecution_,{receivePrevious:false}))}if(config_.runImmediately===true){void this.scheduleExecution_()}}get isDestroyed(){return this.isDestroyed__}async scheduleExecution_(){this.logger_.logMethod?.("scheduleExecution_");if(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__=true;try{await import_delay4.delay.nextMacrotask();if(this.isDestroyed__){this.logger_.incident?.("scheduleExecution_","destroyed_during_delay");this.isRunning__=false;return}this.logger_.logStep?.("scheduleExecution_","executing_effect");await this.config_.run()}catch(err){this.logger_.error("scheduleExecution_","effect_failed",err)}this.isRunning__=false}destroy(){this.logger_.logMethod?.("destroy");if(this.isDestroyed__){this.logger_.incident?.("destroy","already_destroyed");return}this.isDestroyed__=true;for(const subscription of this.dependencySubscriptions__){subscription.unsubscribe()}this.dependencySubscriptions__.length=0;this.config_.onDestroy?.();this.config_=null}};function createEventSignal(config){return new EventSignal(config)}function createStateSignal(config){return new StateSignal(config)}function createComputedSignal(config){return new ComputedSignal(config)}function createEffect(config){return new EffectSignal(config)}var import_debounce=require("@alwatr/debounce");function createDebouncedSignal(sourceSignal,config){const signalId=config.signalId??`${sourceSignal.signalId}-debounced`;const internalSignal=new StateSignal({signalId:`${signalId}-internal`,initialValue:sourceSignal.get()});const debouncer=(0,import_debounce.createDebouncer)({...config,func:value=>{internalSignal.set(value)}});const subscription=sourceSignal.subscribe(value=>debouncer.trigger(value),{receivePrevious:false});return createComputedSignal({signalId,deps:[internalSignal],get:()=>internalSignal.get(),onDestroy:()=>{if(internalSignal.isDestroyed)return;subscription.unsubscribe();debouncer.cancel();internalSignal.destroy();config.onDestroy?.();config=null}})}0&&(module.exports={ComputedSignal,EffectSignal,EventSignal,SignalBase,StateSignal,createComputedSignal,createDebouncedSignal,createEffect,createEventSignal,createStateSignal});
|
|
622
3
|
//# sourceMappingURL=main.cjs.map
|