uneventful 0.0.11 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ext.d.ts +30 -43
- package/dist/ext.mjs +30 -22
- package/dist/shared.d.ts +1 -0
- package/dist/signals.d.ts +79 -35
- package/dist/signals.mjs +22 -9
- package/package.json +2 -2
package/dist/ext.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { P as PlainFunction } from './types-N2ua11te.js';
|
|
|
16
16
|
* @module uneventful/ext
|
|
17
17
|
*
|
|
18
18
|
* @experimental
|
|
19
|
-
*
|
|
19
|
+
* @disableGroups
|
|
20
20
|
* @summary Tools for extending objects with extra state and behavior, without
|
|
21
21
|
* directly modifying them.
|
|
22
22
|
*/
|
|
@@ -107,16 +107,12 @@ declare namespace Ext {
|
|
|
107
107
|
/**
|
|
108
108
|
* Get the type of extension that will be returned by the static API.
|
|
109
109
|
*
|
|
110
|
-
* Defaults to the subclass instance type, but can be
|
|
111
|
-
*
|
|
112
|
-
* {@link Ext.__new__ `__new__()`} method is also overridden to return that
|
|
113
|
-
* type.
|
|
110
|
+
* Defaults to the subclass instance type, but can be changed by overriding
|
|
111
|
+
* {@link Ext.__new__ `__new__()`} to return a different type.
|
|
114
112
|
*/
|
|
115
113
|
type Type<T extends Ext.Class> = InstanceType<T> extends {
|
|
116
|
-
|
|
114
|
+
__new__(ob: any): infer R;
|
|
117
115
|
} ? (unknown extends R ? InstanceType<T> : R) : InstanceType<T>;
|
|
118
|
-
/** The type of weakmap passed to {@link Ext.__new__ `__new__()`} */
|
|
119
|
-
type Map<Class extends Ext.Class> = WeakMap<Ext.Target<Class>, any>;
|
|
120
116
|
/**
|
|
121
117
|
* The type constraint for static generics in the API; you probably won't use this directly.
|
|
122
118
|
*/
|
|
@@ -160,28 +156,13 @@ declare abstract class Ext<Target extends WeakKey = WeakKey> {
|
|
|
160
156
|
*/
|
|
161
157
|
readonly of: Target;
|
|
162
158
|
/**
|
|
163
|
-
*
|
|
164
|
-
* interface's return type. For example, if a subclass does `declare readonly __type__:
|
|
165
|
-
* Promise<this>`, and overrides `__new__`() to return a promise, then the
|
|
166
|
-
* static APIs for the subclass (like `.for()`) will return promises instead
|
|
167
|
-
* of instances. (See the {@link __new__ `__new__`} method for more
|
|
168
|
-
* details.)
|
|
169
|
-
*
|
|
170
|
-
* Note: this property is not actually set by any code, so you can't do anything
|
|
171
|
-
* other than declare it. It's just a hack to work around TypeScript's limited
|
|
172
|
-
* type parameterization for static generics.
|
|
173
|
-
*
|
|
174
|
-
* @category Lifecycle Hooks
|
|
175
|
-
*/
|
|
176
|
-
readonly __type__: unknown;
|
|
177
|
-
/**
|
|
178
|
-
* @deprecated Use .for() instead!
|
|
159
|
+
* @deprecated Use `.for()` or `prototype.__inst__()` instead!
|
|
179
160
|
*
|
|
180
|
-
* Never directly call the constructor of an Ext subclass
|
|
181
|
-
* {@link __new__ `__new__()`}
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
161
|
+
* Never directly call the constructor of an Ext subclass. If you're
|
|
162
|
+
* creating an instance in {@link __new__ `__new__()`}, use the
|
|
163
|
+
* {@link __inst__ `__inst__()`} method instead. Otherwise,
|
|
164
|
+
* you should use the .for or .get methods, as they are properly typed
|
|
165
|
+
* and won't create multiple instances for the same target.
|
|
185
166
|
*/
|
|
186
167
|
constructor(of: Target);
|
|
187
168
|
/**
|
|
@@ -215,21 +196,15 @@ declare abstract class Ext<Target extends WeakKey = WeakKey> {
|
|
|
215
196
|
* behavior, e.g. to execute the constructor within a job, or create a
|
|
216
197
|
* promise for an extension instance to be asynchronously initiaized, etc.
|
|
217
198
|
*
|
|
218
|
-
*
|
|
219
|
-
* you must also redeclare the type of the {@link __type__ `__type__`}
|
|
220
|
-
* property. For example:
|
|
199
|
+
* For example:
|
|
221
200
|
*
|
|
222
201
|
* ```ts
|
|
223
|
-
* class AsyncExt extends Ext {
|
|
224
|
-
* declare readonly __type__: Job<this>
|
|
225
|
-
*
|
|
202
|
+
* class AsyncExt extends Ext<SomeType> {
|
|
226
203
|
* // simulate slow initialization
|
|
227
204
|
* *setup() { yield *sleep(100); return this; }
|
|
228
205
|
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
* ) {
|
|
232
|
-
* const ext = new this(tgt);
|
|
206
|
+
* __new__(tgt: SomeType): Job<this> {
|
|
207
|
+
* const ext = this.__inst__(tgt);
|
|
233
208
|
* map.set(tgt, root.start(ext.setup()) as Ext.Type<Class>);
|
|
234
209
|
* }
|
|
235
210
|
* }
|
|
@@ -239,13 +214,25 @@ declare abstract class Ext<Target extends WeakKey = WeakKey> {
|
|
|
239
214
|
* extension whose `setup()` has finished. (And subclasses of `AsyncExt`
|
|
240
215
|
* will share the same behavior, while being subtyped appropriately.)
|
|
241
216
|
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
217
|
+
* @remarks Note that while this is technically an instance method, it's
|
|
218
|
+
* actually called with the class *prototype*, so you should not use any
|
|
219
|
+
* properties or methods of `this` other than `__inst__`. Think of it
|
|
220
|
+
* as a function that's just on the class as a convenient way of configuring
|
|
221
|
+
* it.
|
|
222
|
+
*
|
|
223
|
+
* @category Lifecycle Hooks
|
|
224
|
+
*/
|
|
225
|
+
__new__<C extends Ext>(this: C, tgt: C["of"]): unknown;
|
|
226
|
+
/**
|
|
227
|
+
* Given a target, create an extension instance.
|
|
228
|
+
*
|
|
229
|
+
* You do not need to override this, nor should you: it's just a type-safe
|
|
230
|
+
* way to construct an extension instance, since an Ext subclass's
|
|
231
|
+
* constructor may accept a wider type than the class actually requires.
|
|
245
232
|
*
|
|
246
233
|
* @category Lifecycle Hooks
|
|
247
234
|
*/
|
|
248
|
-
|
|
235
|
+
__inst__<T extends Ext>(this: T, tgt: T["of"]): T;
|
|
249
236
|
/**
|
|
250
237
|
* This method is called by {@link delete}() if it finds an existing
|
|
251
238
|
* extension for the target. You can override it in a subclass to do any
|
package/dist/ext.mjs
CHANGED
|
@@ -9,13 +9,13 @@ function method(factory, map = /* @__PURE__ */ new WeakMap()) {
|
|
|
9
9
|
const classMap = /* @__PURE__ */ ext((cls) => /* @__PURE__ */ new WeakMap());
|
|
10
10
|
class Ext {
|
|
11
11
|
/**
|
|
12
|
-
* @deprecated Use
|
|
12
|
+
* @deprecated Use `.for()` or `prototype.__inst__()` instead!
|
|
13
13
|
*
|
|
14
|
-
* Never directly call the constructor of an Ext subclass
|
|
15
|
-
* {@link __new__ `__new__()`}
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
14
|
+
* Never directly call the constructor of an Ext subclass. If you're
|
|
15
|
+
* creating an instance in {@link __new__ `__new__()`}, use the
|
|
16
|
+
* {@link __inst__ `__inst__()`} method instead. Otherwise,
|
|
17
|
+
* you should use the .for or .get methods, as they are properly typed
|
|
18
|
+
* and won't create multiple instances for the same target.
|
|
19
19
|
*/
|
|
20
20
|
constructor(of) {
|
|
21
21
|
this.of = of;
|
|
@@ -26,7 +26,7 @@ class Ext {
|
|
|
26
26
|
*/
|
|
27
27
|
static for(tgt) {
|
|
28
28
|
const map = classMap(this);
|
|
29
|
-
return map.get(tgt) ?? (
|
|
29
|
+
return map.get(tgt) ?? setMap(map, tgt, this.prototype.__new__(tgt));
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* Get the current extension instance for the given target, or `undefined`
|
|
@@ -64,21 +64,15 @@ class Ext {
|
|
|
64
64
|
* behavior, e.g. to execute the constructor within a job, or create a
|
|
65
65
|
* promise for an extension instance to be asynchronously initiaized, etc.
|
|
66
66
|
*
|
|
67
|
-
*
|
|
68
|
-
* you must also redeclare the type of the {@link __type__ `__type__`}
|
|
69
|
-
* property. For example:
|
|
67
|
+
* For example:
|
|
70
68
|
*
|
|
71
69
|
* ```ts
|
|
72
|
-
* class AsyncExt extends Ext {
|
|
73
|
-
* declare readonly __type__: Job<this>
|
|
74
|
-
*
|
|
70
|
+
* class AsyncExt extends Ext<SomeType> {
|
|
75
71
|
* // simulate slow initialization
|
|
76
72
|
* *setup() { yield *sleep(100); return this; }
|
|
77
73
|
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* ) {
|
|
81
|
-
* const ext = new this(tgt);
|
|
74
|
+
* __new__(tgt: SomeType): Job<this> {
|
|
75
|
+
* const ext = this.__inst__(tgt);
|
|
82
76
|
* map.set(tgt, root.start(ext.setup()) as Ext.Type<Class>);
|
|
83
77
|
* }
|
|
84
78
|
* }
|
|
@@ -88,14 +82,28 @@ class Ext {
|
|
|
88
82
|
* extension whose `setup()` has finished. (And subclasses of `AsyncExt`
|
|
89
83
|
* will share the same behavior, while being subtyped appropriately.)
|
|
90
84
|
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
85
|
+
* @remarks Note that while this is technically an instance method, it's
|
|
86
|
+
* actually called with the class *prototype*, so you should not use any
|
|
87
|
+
* properties or methods of `this` other than `__inst__`. Think of it
|
|
88
|
+
* as a function that's just on the class as a convenient way of configuring
|
|
89
|
+
* it.
|
|
90
|
+
*
|
|
91
|
+
* @category Lifecycle Hooks
|
|
92
|
+
*/
|
|
93
|
+
__new__(tgt) {
|
|
94
|
+
return this.__inst__(tgt);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Given a target, create an extension instance.
|
|
98
|
+
*
|
|
99
|
+
* You do not need to override this, nor should you: it's just a type-safe
|
|
100
|
+
* way to construct an extension instance, since an Ext subclass's
|
|
101
|
+
* constructor may accept a wider type than the class actually requires.
|
|
94
102
|
*
|
|
95
103
|
* @category Lifecycle Hooks
|
|
96
104
|
*/
|
|
97
|
-
|
|
98
|
-
|
|
105
|
+
__inst__(tgt) {
|
|
106
|
+
return new this.constructor(tgt);
|
|
99
107
|
}
|
|
100
108
|
/**
|
|
101
109
|
* This method is called by {@link delete}() if it finds an existing
|
package/dist/shared.d.ts
CHANGED
package/dist/signals.d.ts
CHANGED
|
@@ -194,7 +194,7 @@ interface RuleFactory {
|
|
|
194
194
|
*
|
|
195
195
|
* @returns A function that can be called to terminate the rule.
|
|
196
196
|
*
|
|
197
|
-
* @category
|
|
197
|
+
* @category none
|
|
198
198
|
* @function
|
|
199
199
|
*/
|
|
200
200
|
declare const rule: ((fn: () => OptionalCleanup) => DisposeFn) & RuleFactory;
|
|
@@ -214,7 +214,7 @@ declare const rule: ((fn: () => OptionalCleanup) => DisposeFn) & RuleFactory;
|
|
|
214
214
|
* factory you wish to run pending rules for. If not given, the default
|
|
215
215
|
* {@link rule}() factory is targeted.
|
|
216
216
|
*
|
|
217
|
-
* @category
|
|
217
|
+
* @category Scheduling
|
|
218
218
|
*/
|
|
219
219
|
declare function runRules(scheduleFn?: SchedulerFn): void;
|
|
220
220
|
/**
|
|
@@ -246,34 +246,6 @@ declare class WriteConflict extends Error {
|
|
|
246
246
|
*/
|
|
247
247
|
declare class CircularDependency extends Error {
|
|
248
248
|
}
|
|
249
|
-
/**
|
|
250
|
-
* Keep an expression's old value unless there's a semantic change
|
|
251
|
-
*
|
|
252
|
-
* By default, reactive values (i.e. {@link cached}(), or {@link value}() with a
|
|
253
|
-
* {@link Configurable.setf setf}()) are considered to have "changed" (and thus
|
|
254
|
-
* trigger recalculation of their dependents) when they are different according
|
|
255
|
-
* to `===` comparison.
|
|
256
|
-
*
|
|
257
|
-
* This works well for primitive values, but for arrays and objects it's not
|
|
258
|
-
* always ideal, because two arrays can have the exact same elements and still
|
|
259
|
-
* be different according to `===`. So this function lets you substitute a
|
|
260
|
-
* different comparison function (like a deep-equal or shallow-equal) instead.
|
|
261
|
-
* (The default is {@link arrayEq}() if no compare function is supplied.)
|
|
262
|
-
*
|
|
263
|
-
* Specifically, if your reactive expression returns `unchangedIf(newVal,
|
|
264
|
-
* compare)`, then the expression's previous value will be kept if the compare
|
|
265
|
-
* function returns true when called with the old and new values. Otherwise, the
|
|
266
|
-
* new value will be used.
|
|
267
|
-
*
|
|
268
|
-
* @remarks
|
|
269
|
-
* - If the reactive expression's last "value" was an error, the new value is
|
|
270
|
-
* returned
|
|
271
|
-
* - An error will be thrown if this function is called outside a reactive
|
|
272
|
-
* expression or from within a {@link peek}() call or {@link action} wrapper.
|
|
273
|
-
*
|
|
274
|
-
* @category Reactive Values
|
|
275
|
-
*/
|
|
276
|
-
declare function unchangedIf<T>(newVal: T, equals?: (v1: T, v2: T) => boolean): T;
|
|
277
249
|
|
|
278
250
|
/**
|
|
279
251
|
* The Signals API for uneventful.
|
|
@@ -377,7 +349,7 @@ interface Configurable<T> extends Writable<T> {
|
|
|
377
349
|
/**
|
|
378
350
|
* Create a {@link Configurable} signal with the given inital value
|
|
379
351
|
*
|
|
380
|
-
* @category
|
|
352
|
+
* @category none
|
|
381
353
|
*/
|
|
382
354
|
declare function value<T>(val?: T): Configurable<T>;
|
|
383
355
|
/**
|
|
@@ -389,7 +361,7 @@ declare function value<T>(val?: T): Configurable<T>;
|
|
|
389
361
|
* calling signature below will apply, even if TypeScript doesn't see it that
|
|
390
362
|
* way!)
|
|
391
363
|
*
|
|
392
|
-
* @category
|
|
364
|
+
* @category none
|
|
393
365
|
*/
|
|
394
366
|
declare function cached<T>(compute: () => T): Signal<T>;
|
|
395
367
|
/**
|
|
@@ -430,7 +402,7 @@ declare function cached<T extends Signal<any>>(signal: T): T;
|
|
|
430
402
|
*
|
|
431
403
|
* @returns The result of calling `fn(..args)`
|
|
432
404
|
*
|
|
433
|
-
* @category
|
|
405
|
+
* @category Dependency Tracking
|
|
434
406
|
*/
|
|
435
407
|
declare function peek<F extends PlainFunction>(fn: F, ...args: Parameters<F>): ReturnType<F>;
|
|
436
408
|
/**
|
|
@@ -472,7 +444,7 @@ declare function peek<F extends PlainFunction>(fn: F, ...args: Parameters<F>): R
|
|
|
472
444
|
* to the original function, while running with dependency tracking suppressed
|
|
473
445
|
* (as with {@link peek}()).
|
|
474
446
|
*
|
|
475
|
-
* @category
|
|
447
|
+
* @category Dependency Tracking
|
|
476
448
|
*/
|
|
477
449
|
declare function action<F extends AnyFunction>(fn: F): F;
|
|
478
450
|
/** @hidden TC39 Decorator protocol */
|
|
@@ -483,6 +455,78 @@ declare function action<F extends AnyFunction>(fn: F, ctx: {
|
|
|
483
455
|
declare function action<F extends AnyFunction, D extends {
|
|
484
456
|
value?: F;
|
|
485
457
|
}>(clsOrProto: any, name: string | symbol, desc: D): D;
|
|
458
|
+
/**
|
|
459
|
+
* Keep an expression's old value unless there's a semantic change
|
|
460
|
+
*
|
|
461
|
+
* By default, reactive values (i.e. {@link cached}(), or {@link value}() with a
|
|
462
|
+
* {@link Configurable.setf setf}()) are considered to have "changed" (and thus
|
|
463
|
+
* trigger recalculation of their dependents) when they are different according
|
|
464
|
+
* to `===` comparison.
|
|
465
|
+
*
|
|
466
|
+
* This works well for primitive values, but for arrays and objects it's not
|
|
467
|
+
* always ideal, because two arrays can have the exact same elements and still
|
|
468
|
+
* be different according to `===`. So this function lets you substitute a
|
|
469
|
+
* different comparison function (like a deep-equal or shallow-equal) instead.
|
|
470
|
+
*
|
|
471
|
+
* Specifically, if your reactive expression returns `stable(compare, newVal)`,
|
|
472
|
+
* then the expression's previous value will be kept if the `compare` function
|
|
473
|
+
* returns true when called with the old and new values. Otherwise, the new
|
|
474
|
+
* value will be used.
|
|
475
|
+
*
|
|
476
|
+
* @remarks
|
|
477
|
+
* - If the reactive expression's last "value" was an error, the new value is
|
|
478
|
+
* returned.
|
|
479
|
+
* - An error will be thrown if this function is called outside a reactive
|
|
480
|
+
* expression or from within a {@link peek}() call or {@link action} wrapper.
|
|
481
|
+
* - You can use the {@link stabilizer}() function to create custom functions
|
|
482
|
+
* similar to {@link stableJSON}. or {@link stableArray}().
|
|
483
|
+
*
|
|
484
|
+
* @category Dependency Tracking
|
|
485
|
+
*/
|
|
486
|
+
declare function stable<T>(equals: (v1: T, v2: T) => boolean, newVal: T): T;
|
|
487
|
+
/**
|
|
488
|
+
* @deprecated This is {@link stable}() but with swapped arguments. Please switch
|
|
489
|
+
* to using stable(), stableArray(), or a stabilizer(), as this function will be removed
|
|
490
|
+
* in a future release.
|
|
491
|
+
*
|
|
492
|
+
* @hidden
|
|
493
|
+
*/
|
|
494
|
+
declare function unchangedIf<T>(newVal: T, equals?: (v1: T, v2: T) => boolean): T;
|
|
495
|
+
/**
|
|
496
|
+
* Create a shorthand version of {@link stable}(), pre-bound to a specific comparison
|
|
497
|
+
* function.
|
|
498
|
+
*
|
|
499
|
+
* @param equals The comparison function to use
|
|
500
|
+
* @template T The type of value the comparison function works on
|
|
501
|
+
*
|
|
502
|
+
* @category Dependency Tracking
|
|
503
|
+
*/
|
|
504
|
+
declare function stabilizer<T>(equals: <T>(v1: T, v2: T) => boolean): <R extends T>(newVal: R) => R;
|
|
505
|
+
/**
|
|
506
|
+
* Keep an expression's old value if the new value is an array with the same
|
|
507
|
+
* contents.
|
|
508
|
+
*
|
|
509
|
+
* (Shorthand for {@link stable}({@link arrayEq}, ...).)
|
|
510
|
+
*
|
|
511
|
+
* @function
|
|
512
|
+
* @category Dependency Tracking
|
|
513
|
+
*/
|
|
514
|
+
declare const stableArray: <R extends unknown[]>(newVal: R) => R;
|
|
515
|
+
/**
|
|
516
|
+
* Keep an expression's old value if its JSON string is the same as the new one.
|
|
517
|
+
*
|
|
518
|
+
* (Shorthand for {@link stable}() with a JSON-string comparison function.)
|
|
519
|
+
*
|
|
520
|
+
* Note that JSON string comparison is slow and memory intensive for more
|
|
521
|
+
* complex data structures, is order-sensitive for object keys, and doesn't
|
|
522
|
+
* support maps or sets. If you need any of those things, you should probably
|
|
523
|
+
* use a {@link stabilizer}() based on
|
|
524
|
+
* [fast-equals](https://github.com/planttheidea/fast-equals) instead.
|
|
525
|
+
*
|
|
526
|
+
* @function
|
|
527
|
+
* @category Dependency Tracking
|
|
528
|
+
*/
|
|
529
|
+
declare const stableJSON: <R extends any>(newVal: R) => R;
|
|
486
530
|
/**
|
|
487
531
|
* Wait for and return the next truthy value (or error) from a data source (when
|
|
488
532
|
* processed with `yield *` within a {@link Job}).
|
|
@@ -514,4 +558,4 @@ declare function action<F extends AnyFunction, D extends {
|
|
|
514
558
|
*/
|
|
515
559
|
declare function until<T>(source: UntilMethod<T> | Stream<T> | (() => T)): Yielding<T>;
|
|
516
560
|
|
|
517
|
-
export { CircularDependency, type Configurable, type GenericMethodDecorator, type RuleFactory, type SchedulerFn, type Signal, type Writable, WriteConflict, action, cached, peek, rule, runRules, unchangedIf, until, value };
|
|
561
|
+
export { CircularDependency, type Configurable, type GenericMethodDecorator, type RuleFactory, type SchedulerFn, type Signal, type Writable, WriteConflict, action, cached, peek, rule, runRules, stabilizer, stable, stableArray, stableJSON, unchangedIf, until, value };
|
package/dist/signals.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { F as pushCtx, G as popCtx, w as makeJob, c as root, f as isError, e as markHandled, g as getJob, x as detached, k as currentCell, o as reject, b as resolve } from './jobutils-Dvu-e99o.mjs';
|
|
2
2
|
import { b as backpressure, I as IsStream, a as callOrWait } from './call-or-wait-EzXJX5Dq.mjs';
|
|
3
|
-
import { e as batch,
|
|
3
|
+
import { e as batch, d as defer, c as apply, s as setMap, C as CallableObject, f as arrayEq } from './utils-cyEhnyp7.mjs';
|
|
4
4
|
|
|
5
5
|
const ruleQueues = /* @__PURE__ */ new WeakMap();
|
|
6
6
|
function ruleQueue(scheduleFn = defer) {
|
|
@@ -478,6 +478,9 @@ class Cell {
|
|
|
478
478
|
this.flags &= ~8 /* Peeking */;
|
|
479
479
|
}
|
|
480
480
|
}
|
|
481
|
+
unchangedIf(newVal, equals) {
|
|
482
|
+
return this.flags & 16 /* Error */ || !equals(this.value, newVal) ? newVal : this.value;
|
|
483
|
+
}
|
|
481
484
|
recalcWhen(fnOrKey, fn) {
|
|
482
485
|
if (this.flags & 8 /* Peeking */)
|
|
483
486
|
return;
|
|
@@ -514,13 +517,12 @@ class Cell {
|
|
|
514
517
|
return stop;
|
|
515
518
|
}
|
|
516
519
|
}
|
|
517
|
-
function
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
}
|
|
520
|
+
function getCell(f = "") {
|
|
521
|
+
if (!currentCell || currentCell.flags & 8 /* Peeking */)
|
|
522
|
+
throw new Error(
|
|
523
|
+
`${f}must be called from a reactive expression`
|
|
524
|
+
);
|
|
525
|
+
return currentCell;
|
|
524
526
|
}
|
|
525
527
|
|
|
526
528
|
class RF extends CallableObject {
|
|
@@ -685,6 +687,17 @@ function action(fn, _ctx, desc) {
|
|
|
685
687
|
return currentCell ? currentCell.peek(fn, this, args) : apply(fn, this, args);
|
|
686
688
|
};
|
|
687
689
|
}
|
|
690
|
+
function stable(equals, newVal) {
|
|
691
|
+
return getCell("stabilizers ").unchangedIf(newVal, equals);
|
|
692
|
+
}
|
|
693
|
+
function unchangedIf(newVal, equals = arrayEq) {
|
|
694
|
+
return stable(equals, newVal);
|
|
695
|
+
}
|
|
696
|
+
function stabilizer(equals) {
|
|
697
|
+
return stable.bind(null, equals);
|
|
698
|
+
}
|
|
699
|
+
const stableArray = /* @__PURE__ */ stabilizer(arrayEq);
|
|
700
|
+
const stableJSON = /* @__PURE__ */ stabilizer((a, b) => JSON.stringify(a) === JSON.stringify(b));
|
|
688
701
|
function until(source) {
|
|
689
702
|
return callOrWait(source, "uneventful.until", waitTruthy, recache);
|
|
690
703
|
}
|
|
@@ -695,4 +708,4 @@ function waitTruthy(job, v) {
|
|
|
695
708
|
v && job.return(v);
|
|
696
709
|
}
|
|
697
710
|
|
|
698
|
-
export { CircularDependency, ConfigurableImpl, SignalImpl, WritableImpl, WriteConflict, action, cached, peek, rule, runRules, unchangedIf, until, value };
|
|
711
|
+
export { CircularDependency, ConfigurableImpl, SignalImpl, WritableImpl, WriteConflict, action, cached, peek, rule, runRules, stabilizer, stable, stableArray, stableJSON, unchangedIf, until, value };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uneventful",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"description": "Declarative, event-driven reactivity: signals, streams, structured concurrency, and easy resource cleanup",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"signals",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"ts-expect": "^1.3.0",
|
|
94
94
|
"ts-node": "^10.9.1",
|
|
95
95
|
"tsx": "^4.6.1",
|
|
96
|
-
"typedoc": "0.28.
|
|
96
|
+
"typedoc": "0.28.2",
|
|
97
97
|
"typescript": "^5.4.5"
|
|
98
98
|
}
|
|
99
99
|
}
|