@alwatr/signal 5.0.0 → 5.2.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.
- package/CHANGELOG.md +63 -0
- package/dist/{computed-signal.d.ts → core/computed-signal.d.ts} +32 -9
- package/dist/core/computed-signal.d.ts.map +1 -0
- package/dist/{effect-signal.d.ts → core/effect-signal.d.ts} +25 -7
- package/dist/core/effect-signal.d.ts.map +1 -0
- package/dist/{event-signal.d.ts → core/event-signal.d.ts} +4 -4
- package/dist/core/event-signal.d.ts.map +1 -0
- package/dist/{signal-base.d.ts → core/signal-base.d.ts} +19 -14
- package/dist/core/signal-base.d.ts.map +1 -0
- package/dist/{state-signal.d.ts → core/state-signal.d.ts} +27 -4
- package/dist/core/state-signal.d.ts.map +1 -0
- package/dist/creators/computed.d.ts +34 -0
- package/dist/creators/computed.d.ts.map +1 -0
- package/dist/creators/effect.d.ts +43 -0
- package/dist/creators/effect.d.ts.map +1 -0
- package/dist/creators/event.d.ts +28 -0
- package/dist/creators/event.d.ts.map +1 -0
- package/dist/creators/state.d.ts +25 -0
- package/dist/creators/state.d.ts.map +1 -0
- package/dist/main.cjs +225 -92
- package/dist/main.cjs.map +3 -3
- package/dist/main.d.ts +10 -5
- package/dist/main.d.ts.map +1 -1
- package/dist/main.mjs +219 -91
- package/dist/main.mjs.map +3 -3
- package/dist/operators/debounce.d.ts +57 -0
- package/dist/operators/debounce.d.ts.map +1 -0
- package/dist/operators/filter.d.ts +47 -0
- package/dist/operators/filter.d.ts.map +1 -0
- package/dist/operators/map.d.ts +36 -0
- package/dist/operators/map.d.ts.map +1 -0
- package/dist/type.d.ts +57 -15
- package/dist/type.d.ts.map +1 -1
- package/package.json +8 -8
- package/dist/computed-signal.d.ts.map +0 -1
- package/dist/effect-signal.d.ts.map +0 -1
- package/dist/event-signal.d.ts.map +0 -1
- package/dist/signal-base.d.ts.map +0 -1
- package/dist/state-signal.d.ts.map +0 -1
- /package/src/{computed-signal.test.js → core/computed-signal.test.js} +0 -0
- /package/src/{effect-signal.test.js → core/effect-signal.test.js} +0 -0
- /package/src/{event-signal.test.js → core/event-signal.test.js} +0 -0
- /package/src/{state-signal.test.js → core/state-signal.test.js} +0 -0
package/dist/main.mjs
CHANGED
|
@@ -1,52 +1,46 @@
|
|
|
1
|
-
/* @alwatr/signal v5.
|
|
1
|
+
/* @alwatr/signal v5.2.0 */
|
|
2
2
|
|
|
3
|
-
// src/signal-base.ts
|
|
4
|
-
import { packageTracer } from "@alwatr/package-tracer";
|
|
5
|
-
__dev_mode__: packageTracer.add("@alwatr/signal", "5.0.0");
|
|
3
|
+
// src/core/signal-base.ts
|
|
6
4
|
var SignalBase = class {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
constructor(config_) {
|
|
6
|
+
this.config_ = config_;
|
|
7
|
+
/**
|
|
8
|
+
* The unique identifier for this signal instance.
|
|
9
|
+
* Useful for debugging and logging.
|
|
10
|
+
*/
|
|
11
|
+
this.signalId = this.config_.signalId;
|
|
12
12
|
/**
|
|
13
13
|
* The list of observers (listeners) subscribed to this signal.
|
|
14
14
|
* @protected
|
|
15
15
|
*/
|
|
16
16
|
this.observers_ = [];
|
|
17
|
-
this.isDestroyed_ = false;
|
|
18
17
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* @protected
|
|
18
|
+
* A flag indicating whether the signal has been destroyed.
|
|
19
|
+
* @private
|
|
22
20
|
*/
|
|
23
|
-
this.
|
|
24
|
-
if (this.isDestroyed_) {
|
|
25
|
-
this.logger_.accident("checkDestroyed_", "attempt_to_use_destroyed_signal");
|
|
26
|
-
throw new Error(`Cannot interact with a destroyed signal (id: ${this.signalId})`);
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
this.signalId = config.signalId;
|
|
21
|
+
this.isDestroyed__ = false;
|
|
30
22
|
}
|
|
31
23
|
/**
|
|
32
24
|
* Indicates whether the signal has been destroyed.
|
|
33
25
|
* A destroyed signal cannot be used and will throw an error if interacted with.
|
|
26
|
+
*
|
|
34
27
|
* @returns `true` if the signal is destroyed, `false` otherwise.
|
|
35
28
|
*/
|
|
36
29
|
get isDestroyed() {
|
|
37
|
-
return this.
|
|
30
|
+
return this.isDestroyed__;
|
|
38
31
|
}
|
|
39
32
|
/**
|
|
40
33
|
* Removes a specific observer from the observers list.
|
|
34
|
+
*
|
|
41
35
|
* @param observer The observer instance to remove.
|
|
42
36
|
* @protected
|
|
43
37
|
*/
|
|
44
38
|
removeObserver_(observer) {
|
|
45
|
-
|
|
39
|
+
this.logger_.logMethod?.("removeObserver_");
|
|
40
|
+
if (this.isDestroyed__) {
|
|
46
41
|
this.logger_.incident?.("removeObserver_", "remove_observer_on_destroyed_signal");
|
|
47
42
|
return;
|
|
48
43
|
}
|
|
49
|
-
this.logger_.logMethod?.("removeObserver_");
|
|
50
44
|
const index = this.observers_.indexOf(observer);
|
|
51
45
|
if (index !== -1) {
|
|
52
46
|
this.observers_.splice(index, 1);
|
|
@@ -70,8 +64,9 @@ var SignalBase = class {
|
|
|
70
64
|
} else {
|
|
71
65
|
this.observers_.push(observer);
|
|
72
66
|
}
|
|
73
|
-
|
|
74
|
-
|
|
67
|
+
return {
|
|
68
|
+
unsubscribe: () => this.removeObserver_(observer)
|
|
69
|
+
};
|
|
75
70
|
}
|
|
76
71
|
/**
|
|
77
72
|
* Notifies all registered observers about a new value.
|
|
@@ -83,11 +78,11 @@ var SignalBase = class {
|
|
|
83
78
|
* @protected
|
|
84
79
|
*/
|
|
85
80
|
notify_(value) {
|
|
86
|
-
|
|
81
|
+
this.logger_.logMethodArgs?.("notify_", value);
|
|
82
|
+
if (this.isDestroyed__) {
|
|
87
83
|
this.logger_.incident?.("notify_", "notify_on_destroyed_signal");
|
|
88
84
|
return;
|
|
89
85
|
}
|
|
90
|
-
this.logger_.logMethodArgs?.("notify_", value);
|
|
91
86
|
const currentObservers = [...this.observers_];
|
|
92
87
|
for (const observer of currentObservers) {
|
|
93
88
|
if (observer.options?.once) {
|
|
@@ -96,9 +91,7 @@ var SignalBase = class {
|
|
|
96
91
|
try {
|
|
97
92
|
const result = observer.callback(value);
|
|
98
93
|
if (result instanceof Promise) {
|
|
99
|
-
result.catch((err) => {
|
|
100
|
-
this.logger_.error("notify_", "async_callback_failed", err, { observer });
|
|
101
|
-
});
|
|
94
|
+
result.catch((err) => this.logger_.error("notify_", "async_callback_failed", err, { observer }));
|
|
102
95
|
}
|
|
103
96
|
} catch (err) {
|
|
104
97
|
this.logger_.error("notify_", "sync_callback_failed", err);
|
|
@@ -140,21 +133,38 @@ var SignalBase = class {
|
|
|
140
133
|
*/
|
|
141
134
|
destroy() {
|
|
142
135
|
this.logger_.logMethod?.("destroy");
|
|
143
|
-
this.
|
|
136
|
+
if (this.isDestroyed__) {
|
|
137
|
+
this.logger_.incident?.("destroy_", "double_destroy_attempt");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
this.isDestroyed__ = true;
|
|
144
141
|
this.observers_.length = 0;
|
|
142
|
+
this.config_.onDestroy?.();
|
|
143
|
+
this.config_ = null;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Throws an error if the signal has been destroyed.
|
|
147
|
+
* This is a safeguard to prevent interaction with a defunct signal.
|
|
148
|
+
* @protected
|
|
149
|
+
*/
|
|
150
|
+
checkDestroyed_() {
|
|
151
|
+
if (this.isDestroyed__) {
|
|
152
|
+
this.logger_.accident("checkDestroyed_", "attempt_to_use_destroyed_signal");
|
|
153
|
+
throw new Error(`Cannot interact with a destroyed signal (id: ${this.signalId})`);
|
|
154
|
+
}
|
|
145
155
|
}
|
|
146
156
|
};
|
|
147
157
|
|
|
148
|
-
// src/event-signal.ts
|
|
158
|
+
// src/core/event-signal.ts
|
|
149
159
|
import { delay } from "@alwatr/delay";
|
|
150
160
|
import { createLogger } from "@alwatr/logger";
|
|
151
161
|
var EventSignal = class extends SignalBase {
|
|
152
|
-
/**
|
|
153
|
-
* Initializes a new `EventSignal`.
|
|
154
|
-
* @param config The configuration for the signal, containing its `signalId`.
|
|
155
|
-
*/
|
|
156
162
|
constructor(config) {
|
|
157
163
|
super(config);
|
|
164
|
+
/**
|
|
165
|
+
* The logger instance for this signal.
|
|
166
|
+
* @protected
|
|
167
|
+
*/
|
|
158
168
|
this.logger_ = createLogger(`event-signal: ${this.signalId}`);
|
|
159
169
|
this.logger_.logMethod?.("constructor");
|
|
160
170
|
}
|
|
@@ -166,24 +176,22 @@ var EventSignal = class extends SignalBase {
|
|
|
166
176
|
* @param payload The data to send with the event.
|
|
167
177
|
*/
|
|
168
178
|
dispatch(payload) {
|
|
169
|
-
this.logger_.logMethodArgs?.("dispatch", payload);
|
|
179
|
+
this.logger_.logMethodArgs?.("dispatch", { payload });
|
|
170
180
|
this.checkDestroyed_();
|
|
171
|
-
delay.nextMicrotask().then(() =>
|
|
172
|
-
this.notify_(payload);
|
|
173
|
-
});
|
|
181
|
+
delay.nextMicrotask().then(() => this.notify_(payload));
|
|
174
182
|
}
|
|
175
183
|
};
|
|
176
184
|
|
|
177
|
-
// src/state-signal.ts
|
|
185
|
+
// src/core/state-signal.ts
|
|
178
186
|
import { delay as delay2 } from "@alwatr/delay";
|
|
179
187
|
import { createLogger as createLogger2 } from "@alwatr/logger";
|
|
180
188
|
var StateSignal = class extends SignalBase {
|
|
181
|
-
/**
|
|
182
|
-
* Initializes a new `StateSignal`.
|
|
183
|
-
* @param config The configuration for the state signal, including `signalId` and `initialValue`.
|
|
184
|
-
*/
|
|
185
189
|
constructor(config) {
|
|
186
190
|
super(config);
|
|
191
|
+
/**
|
|
192
|
+
* The logger instance for this signal.
|
|
193
|
+
* @protected
|
|
194
|
+
*/
|
|
187
195
|
this.logger_ = createLogger2(`state-signal: ${this.signalId}`);
|
|
188
196
|
this.value__ = config.initialValue;
|
|
189
197
|
this.logger_.logMethodArgs?.("constructor", { initialValue: this.value__ });
|
|
@@ -218,11 +226,31 @@ var StateSignal = class extends SignalBase {
|
|
|
218
226
|
set(newValue) {
|
|
219
227
|
this.logger_.logMethodArgs?.("set", { newValue });
|
|
220
228
|
this.checkDestroyed_();
|
|
221
|
-
if (Object.is(this.value__, newValue) && (typeof newValue !== "object" || newValue === null))
|
|
229
|
+
if (Object.is(this.value__, newValue) && (typeof newValue !== "object" || newValue === null)) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
222
232
|
this.value__ = newValue;
|
|
223
|
-
delay2.nextMicrotask().then(() =>
|
|
224
|
-
|
|
225
|
-
|
|
233
|
+
delay2.nextMicrotask().then(() => this.notify_(newValue));
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Updates the signal's value based on its previous value.
|
|
237
|
+
*
|
|
238
|
+
* This method is particularly useful for state transitions that depend on the current value,
|
|
239
|
+
* especially for objects or arrays, as it promotes an immutable update pattern.
|
|
240
|
+
*
|
|
241
|
+
* @param updater A function that receives the current value and returns the new value.
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* // For a counter
|
|
245
|
+
* counterSignal.update(current => current + 1);
|
|
246
|
+
*
|
|
247
|
+
* // For an object state
|
|
248
|
+
* userSignal.update(currentUser => ({ ...currentUser, loggedIn: true }));
|
|
249
|
+
*/
|
|
250
|
+
update(updater) {
|
|
251
|
+
this.logger_.logMethod?.("update");
|
|
252
|
+
this.checkDestroyed_();
|
|
253
|
+
this.set(updater(this.value__));
|
|
226
254
|
}
|
|
227
255
|
/**
|
|
228
256
|
* Subscribes a listener to this signal.
|
|
@@ -237,11 +265,8 @@ var StateSignal = class extends SignalBase {
|
|
|
237
265
|
subscribe(callback, options = {}) {
|
|
238
266
|
this.logger_.logMethodArgs?.("subscribe", { options });
|
|
239
267
|
this.checkDestroyed_();
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
delay2.nextMicrotask().then(() => callback(this.value__)).catch((err) => {
|
|
243
|
-
this.logger_.error("subscribe", "run_callback_immediate_failed", err);
|
|
244
|
-
});
|
|
268
|
+
if (options.receivePrevious !== false) {
|
|
269
|
+
delay2.nextMicrotask().then(() => callback(this.value__)).catch((err) => this.logger_.error("subscribe", "immediate_callback_failed", err));
|
|
245
270
|
if (options.once) {
|
|
246
271
|
return { unsubscribe: () => {
|
|
247
272
|
} };
|
|
@@ -254,22 +279,25 @@ var StateSignal = class extends SignalBase {
|
|
|
254
279
|
* This is crucial for memory management to prevent leaks.
|
|
255
280
|
*/
|
|
256
281
|
destroy() {
|
|
257
|
-
super.destroy();
|
|
258
282
|
this.value__ = null;
|
|
283
|
+
super.destroy();
|
|
259
284
|
}
|
|
260
285
|
};
|
|
261
286
|
|
|
262
|
-
// src/computed-signal.ts
|
|
287
|
+
// src/core/computed-signal.ts
|
|
263
288
|
import { delay as delay3 } from "@alwatr/delay";
|
|
264
289
|
import { createLogger as createLogger3 } from "@alwatr/logger";
|
|
265
290
|
var ComputedSignal = class {
|
|
266
|
-
/**
|
|
267
|
-
* Initializes a new `ComputedSignal`.
|
|
268
|
-
* @param config The configuration, including dependencies (`deps`) and the getter function (`get`).
|
|
269
|
-
*/
|
|
270
291
|
constructor(config_) {
|
|
271
292
|
this.config_ = config_;
|
|
293
|
+
/**
|
|
294
|
+
* The unique identifier for this signal instance.
|
|
295
|
+
*/
|
|
272
296
|
this.signalId = this.config_.signalId;
|
|
297
|
+
/**
|
|
298
|
+
* The logger instance for this signal.
|
|
299
|
+
* @protected
|
|
300
|
+
*/
|
|
273
301
|
this.logger_ = createLogger3(`computed-signal: ${this.signalId}`);
|
|
274
302
|
/**
|
|
275
303
|
* The internal `StateSignal` that holds the computed value.
|
|
@@ -277,17 +305,23 @@ var ComputedSignal = class {
|
|
|
277
305
|
* @protected
|
|
278
306
|
*/
|
|
279
307
|
this.internalSignal_ = new StateSignal({
|
|
280
|
-
signalId: this.signalId
|
|
308
|
+
signalId: `${this.signalId}-internal`,
|
|
281
309
|
initialValue: this.config_.get()
|
|
282
310
|
});
|
|
283
|
-
|
|
311
|
+
/**
|
|
312
|
+
* A list of subscriptions to dependency signals.
|
|
313
|
+
* @private
|
|
314
|
+
*/
|
|
315
|
+
this.dependencySubscriptions__ = [];
|
|
316
|
+
/**
|
|
317
|
+
* A flag to prevent concurrent recalculations.
|
|
318
|
+
* @private
|
|
319
|
+
*/
|
|
284
320
|
this.isRecalculating__ = false;
|
|
285
|
-
this.subscribe = this.internalSignal_.subscribe.bind(this.internalSignal_);
|
|
286
|
-
this.untilNext = this.internalSignal_.untilNext.bind(this.internalSignal_);
|
|
287
321
|
this.logger_.logMethod?.("constructor");
|
|
288
322
|
this.recalculate_ = this.recalculate_.bind(this);
|
|
289
323
|
for (const signal of config_.deps) {
|
|
290
|
-
this.
|
|
324
|
+
this.dependencySubscriptions__.push(signal.subscribe(this.recalculate_, { receivePrevious: false }));
|
|
291
325
|
}
|
|
292
326
|
}
|
|
293
327
|
/**
|
|
@@ -308,6 +342,25 @@ var ComputedSignal = class {
|
|
|
308
342
|
get isDestroyed() {
|
|
309
343
|
return this.internalSignal_.isDestroyed;
|
|
310
344
|
}
|
|
345
|
+
/**
|
|
346
|
+
* Subscribes a listener to this signal.
|
|
347
|
+
* The listener will be called whenever the computed value changes.
|
|
348
|
+
*
|
|
349
|
+
* @param callback The function to be called with the new value.
|
|
350
|
+
* @param options Subscription options.
|
|
351
|
+
* @returns A `SubscribeResult` object with an `unsubscribe` method.
|
|
352
|
+
*/
|
|
353
|
+
subscribe(callback, options) {
|
|
354
|
+
return this.internalSignal_.subscribe(callback, options);
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Returns a Promise that resolves with the next computed value.
|
|
358
|
+
*
|
|
359
|
+
* @returns A Promise that resolves with the next value.
|
|
360
|
+
*/
|
|
361
|
+
untilNext() {
|
|
362
|
+
return this.internalSignal_.untilNext();
|
|
363
|
+
}
|
|
311
364
|
/**
|
|
312
365
|
* Permanently disposes of the computed signal.
|
|
313
366
|
*
|
|
@@ -319,15 +372,16 @@ var ComputedSignal = class {
|
|
|
319
372
|
*/
|
|
320
373
|
destroy() {
|
|
321
374
|
this.logger_.logMethod?.("destroy");
|
|
322
|
-
if (this.
|
|
375
|
+
if (this.isDestroyed) {
|
|
323
376
|
this.logger_.incident?.("destroy", "already_destroyed");
|
|
324
377
|
return;
|
|
325
378
|
}
|
|
326
|
-
for (const subscription of this.
|
|
379
|
+
for (const subscription of this.dependencySubscriptions__) {
|
|
327
380
|
subscription.unsubscribe();
|
|
328
381
|
}
|
|
329
|
-
this.
|
|
382
|
+
this.dependencySubscriptions__.length = 0;
|
|
330
383
|
this.internalSignal_.destroy();
|
|
384
|
+
this.config_.onDestroy?.();
|
|
331
385
|
this.config_ = null;
|
|
332
386
|
}
|
|
333
387
|
/**
|
|
@@ -339,23 +393,24 @@ var ComputedSignal = class {
|
|
|
339
393
|
* @protected
|
|
340
394
|
*/
|
|
341
395
|
async recalculate_() {
|
|
396
|
+
this.logger_.logMethod?.("recalculate_");
|
|
342
397
|
if (this.internalSignal_.isDestroyed) {
|
|
343
|
-
this.logger_.incident?.("
|
|
398
|
+
this.logger_.incident?.("recalculate_", "recalculate_on_destroyed_signal");
|
|
344
399
|
return;
|
|
345
400
|
}
|
|
346
401
|
if (this.isRecalculating__) {
|
|
347
|
-
this.logger_.
|
|
402
|
+
this.logger_.logStep?.("recalculate_", "skipping_recalculation_already_scheduled");
|
|
348
403
|
return;
|
|
349
404
|
}
|
|
350
|
-
this.logger_.logMethod?.("recalculate_//scheduled");
|
|
351
405
|
this.isRecalculating__ = true;
|
|
352
406
|
try {
|
|
353
407
|
await delay3.nextMacrotask();
|
|
354
|
-
if (this.
|
|
355
|
-
this.logger_.incident?.("
|
|
408
|
+
if (this.isDestroyed) {
|
|
409
|
+
this.logger_.incident?.("recalculate_", "destroyed_during_delay");
|
|
410
|
+
this.isRecalculating__ = false;
|
|
356
411
|
return;
|
|
357
412
|
}
|
|
358
|
-
this.logger_.
|
|
413
|
+
this.logger_.logStep?.("recalculate_", "recalculating_value");
|
|
359
414
|
this.internalSignal_.set(this.config_.get());
|
|
360
415
|
} catch (err) {
|
|
361
416
|
this.logger_.error("recalculate_", "recalculation_failed", err);
|
|
@@ -364,24 +419,40 @@ var ComputedSignal = class {
|
|
|
364
419
|
}
|
|
365
420
|
};
|
|
366
421
|
|
|
367
|
-
// src/effect-signal.ts
|
|
422
|
+
// src/core/effect-signal.ts
|
|
368
423
|
import { delay as delay4 } from "@alwatr/delay";
|
|
369
424
|
import { createLogger as createLogger4 } from "@alwatr/logger";
|
|
370
425
|
var EffectSignal = class {
|
|
371
|
-
/**
|
|
372
|
-
* Initializes a new `EffectSignal`.
|
|
373
|
-
* @param config The configuration, including dependencies (`deps`) and the `run` function.
|
|
374
|
-
*/
|
|
375
426
|
constructor(config_) {
|
|
376
427
|
this.config_ = config_;
|
|
377
|
-
|
|
378
|
-
|
|
428
|
+
/**
|
|
429
|
+
* The unique identifier for this signal instance.
|
|
430
|
+
*/
|
|
431
|
+
this.signalId = this.config_.signalId ? this.config_.signalId : `[${this.config_.deps.map((dep) => dep.signalId).join(", ")}]`;
|
|
432
|
+
/**
|
|
433
|
+
* The logger instance for this signal.
|
|
434
|
+
* @protected
|
|
435
|
+
*/
|
|
436
|
+
this.logger_ = createLogger4(`effect-signal: ${this.signalId}`);
|
|
437
|
+
/**
|
|
438
|
+
* A list of subscriptions to dependency signals.
|
|
439
|
+
* @private
|
|
440
|
+
*/
|
|
441
|
+
this.dependencySubscriptions__ = [];
|
|
442
|
+
/**
|
|
443
|
+
* A flag to prevent concurrent executions of the effect.
|
|
444
|
+
* @private
|
|
445
|
+
*/
|
|
379
446
|
this.isRunning__ = false;
|
|
447
|
+
/**
|
|
448
|
+
* A flag indicating whether the effect has been destroyed.
|
|
449
|
+
* @private
|
|
450
|
+
*/
|
|
380
451
|
this.isDestroyed__ = false;
|
|
381
452
|
this.logger_.logMethod?.("constructor");
|
|
382
453
|
this.run_ = this.run_.bind(this);
|
|
383
454
|
for (const signal of config_.deps) {
|
|
384
|
-
this.
|
|
455
|
+
this.dependencySubscriptions__.push(signal.subscribe(this.run_, { receivePrevious: false }));
|
|
385
456
|
}
|
|
386
457
|
if (config_.runImmediately === true) {
|
|
387
458
|
void this.run_();
|
|
@@ -389,7 +460,8 @@ var EffectSignal = class {
|
|
|
389
460
|
}
|
|
390
461
|
/**
|
|
391
462
|
* Indicates whether the effect signal has been destroyed.
|
|
392
|
-
* A destroyed signal
|
|
463
|
+
* A destroyed signal will no longer execute its effect and cannot be reused.
|
|
464
|
+
*
|
|
393
465
|
* @returns `true` if the signal is destroyed, `false` otherwise.
|
|
394
466
|
*/
|
|
395
467
|
get isDestroyed() {
|
|
@@ -404,29 +476,29 @@ var EffectSignal = class {
|
|
|
404
476
|
* @protected
|
|
405
477
|
*/
|
|
406
478
|
async run_() {
|
|
479
|
+
this.logger_.logMethod?.("run_");
|
|
407
480
|
if (this.isDestroyed__) {
|
|
408
481
|
this.logger_.incident?.("run_", "run_on_destroyed_signal");
|
|
409
482
|
return;
|
|
410
483
|
}
|
|
411
484
|
if (this.isRunning__) {
|
|
412
|
-
this.logger_.
|
|
485
|
+
this.logger_.logStep?.("run_", "skipped_because_already_running");
|
|
413
486
|
return;
|
|
414
487
|
}
|
|
415
|
-
this.logger_.logMethod?.("run_//scheduled");
|
|
416
488
|
this.isRunning__ = true;
|
|
417
489
|
try {
|
|
418
490
|
await delay4.nextMacrotask();
|
|
419
491
|
if (this.isDestroyed__) {
|
|
420
492
|
this.logger_.incident?.("run_", "destroyed_during_delay");
|
|
493
|
+
this.isRunning__ = false;
|
|
421
494
|
return;
|
|
422
495
|
}
|
|
423
|
-
this.logger_.
|
|
496
|
+
this.logger_.logStep?.("run_", "executing_effect");
|
|
424
497
|
await this.config_.run();
|
|
425
498
|
} catch (err) {
|
|
426
499
|
this.logger_.error("run_", "effect_failed", err);
|
|
427
|
-
} finally {
|
|
428
|
-
this.isRunning__ = false;
|
|
429
500
|
}
|
|
501
|
+
this.isRunning__ = false;
|
|
430
502
|
}
|
|
431
503
|
/**
|
|
432
504
|
* Permanently disposes of the effect signal.
|
|
@@ -442,18 +514,74 @@ var EffectSignal = class {
|
|
|
442
514
|
return;
|
|
443
515
|
}
|
|
444
516
|
this.isDestroyed__ = true;
|
|
445
|
-
for (const subscription of this.
|
|
517
|
+
for (const subscription of this.dependencySubscriptions__) {
|
|
446
518
|
subscription.unsubscribe();
|
|
447
519
|
}
|
|
448
|
-
this.
|
|
520
|
+
this.dependencySubscriptions__.length = 0;
|
|
521
|
+
this.config_.onDestroy?.();
|
|
449
522
|
this.config_ = null;
|
|
450
523
|
}
|
|
451
524
|
};
|
|
525
|
+
|
|
526
|
+
// src/creators/event.ts
|
|
527
|
+
function createEventSignal(config) {
|
|
528
|
+
return new EventSignal(config);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// src/creators/state.ts
|
|
532
|
+
function createStateSignal(config) {
|
|
533
|
+
return new StateSignal(config);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// src/creators/computed.ts
|
|
537
|
+
function createComputedSignal(config) {
|
|
538
|
+
return new ComputedSignal(config);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// src/creators/effect.ts
|
|
542
|
+
function createEffect(config) {
|
|
543
|
+
return new EffectSignal(config);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// src/operators/debounce.ts
|
|
547
|
+
import { createDebouncer } from "@alwatr/debounce";
|
|
548
|
+
function createDebouncedSignal(sourceSignal, config) {
|
|
549
|
+
const signalId = config.signalId ?? `${sourceSignal.signalId}-debounced`;
|
|
550
|
+
const internalSignal = new StateSignal({
|
|
551
|
+
signalId: `${signalId}-internal`,
|
|
552
|
+
initialValue: sourceSignal.value
|
|
553
|
+
});
|
|
554
|
+
const debouncer = createDebouncer({
|
|
555
|
+
...config,
|
|
556
|
+
func: (value) => {
|
|
557
|
+
internalSignal.set(value);
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
const subscription = sourceSignal.subscribe(debouncer.trigger);
|
|
561
|
+
return createComputedSignal({
|
|
562
|
+
signalId,
|
|
563
|
+
deps: [internalSignal],
|
|
564
|
+
get: () => internalSignal.value,
|
|
565
|
+
onDestroy: () => {
|
|
566
|
+
if (internalSignal.isDestroyed) return;
|
|
567
|
+
subscription.unsubscribe();
|
|
568
|
+
debouncer.cancel();
|
|
569
|
+
internalSignal.destroy();
|
|
570
|
+
config.onDestroy?.();
|
|
571
|
+
config = null;
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
}
|
|
452
575
|
export {
|
|
453
576
|
ComputedSignal,
|
|
454
577
|
EffectSignal,
|
|
455
578
|
EventSignal,
|
|
456
579
|
SignalBase,
|
|
457
|
-
StateSignal
|
|
580
|
+
StateSignal,
|
|
581
|
+
createComputedSignal,
|
|
582
|
+
createDebouncedSignal,
|
|
583
|
+
createEffect,
|
|
584
|
+
createEventSignal,
|
|
585
|
+
createStateSignal
|
|
458
586
|
};
|
|
459
587
|
//# sourceMappingURL=main.mjs.map
|