@softsky/utils 2.1.0 → 2.3.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/README.md +114 -0
- package/dist/control.d.ts +4 -2
- package/dist/control.js +1 -0
- package/dist/formatting.d.ts +23 -0
- package/dist/formatting.js +7 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/signals.d.ts +114 -0
- package/dist/signals.js +158 -0
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -183,6 +183,18 @@ ${\textsf{\color{CornflowerBlue}function}}$ log - Format logging
|
|
|
183
183
|
---
|
|
184
184
|
${\textsf{\color{CornflowerBlue}function}}$ capitalizeFirstLetter - Capitalize first letter
|
|
185
185
|
|
|
186
|
+
---
|
|
187
|
+
${\textsf{\color{CornflowerBlue}function}}$ pipe - pipe() can be called on one or more functions, each of which can take the return of previous value.
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
// Takes string, converts to int, calc sqrt, convert and return date
|
|
191
|
+
pipe(
|
|
192
|
+
(x: string) => Number.parseInt(x),
|
|
193
|
+
(x) => Math.sqrt(x),
|
|
194
|
+
(x) => new Date(x)
|
|
195
|
+
)('69')
|
|
196
|
+
```
|
|
197
|
+
|
|
186
198
|
---
|
|
187
199
|
|
|
188
200
|
|
|
@@ -254,6 +266,105 @@ this.registerSubclass()
|
|
|
254
266
|
---
|
|
255
267
|
|
|
256
268
|
|
|
269
|
+
## Signals
|
|
270
|
+
Reactive signals
|
|
271
|
+
|
|
272
|
+
${\textsf{\color{CornflowerBlue}function}}$ signal - __SIGNALS SYSTEM__
|
|
273
|
+
|
|
274
|
+
Signal can hold any data (except functions),
|
|
275
|
+
when this data has changed any effects containing
|
|
276
|
+
this signal will be rerun.
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
const $mySignal = signal<number|undefined>(1) // Create signal with initial value 1
|
|
280
|
+
$mySignal(5) // Set to 5
|
|
281
|
+
$mySignal(undefined) // Set to undefined
|
|
282
|
+
$mySignal(prev=>prev+1) // Increment
|
|
283
|
+
// Will print signal on change
|
|
284
|
+
effect(()=>{
|
|
285
|
+
console.log($mySignal())
|
|
286
|
+
})
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
${\textsf{\color{CornflowerBlue}function}}$ effect - __SIGNALS SYSTEM__
|
|
291
|
+
|
|
292
|
+
Effects are simplest way to react to signal changes.
|
|
293
|
+
Returned data from handler function will be passed to it on next signal change.
|
|
294
|
+
Returns a function that will clear the effect.
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
// Will print signal on change
|
|
298
|
+
effect(()=>{
|
|
299
|
+
console.log($mySignal())
|
|
300
|
+
})
|
|
301
|
+
// Use previous state as a reference
|
|
302
|
+
effect((last)=>{
|
|
303
|
+
const mySignal = $mySignal()
|
|
304
|
+
if(last>mySignal) console.log('Increment!')
|
|
305
|
+
return mySignal;
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
${\textsf{\color{CornflowerBlue}function}}$ untrack - __SIGNALS SYSTEM__
|
|
310
|
+
|
|
311
|
+
Untrack helps to not react to changes in effects.
|
|
312
|
+
```ts
|
|
313
|
+
const $a = signal(1)
|
|
314
|
+
const $b = signal(2)
|
|
315
|
+
// Will only run on changes to $b
|
|
316
|
+
effect(()=>{
|
|
317
|
+
console.log(untrack($a)+$b())
|
|
318
|
+
})
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
${\textsf{\color{CornflowerBlue}function}}$ derived - __SIGNALS SYSTEM__
|
|
323
|
+
|
|
324
|
+
Creates a derived reactive memoized signal.
|
|
325
|
+
|
|
326
|
+
```ts
|
|
327
|
+
// Sum of all changes of $a()
|
|
328
|
+
const { signal: $sumOfTwo, clear: clearSum } = derived((value) => value + $a(), 0)
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
${\textsf{\color{CornflowerBlue}function}}$ batch - __SIGNALS SYSTEM__
|
|
333
|
+
|
|
334
|
+
Batches multiple edits, so they don't call same effects multiple times
|
|
335
|
+
|
|
336
|
+
```ts
|
|
337
|
+
const $a = signal(1)
|
|
338
|
+
const $b = signal(2)
|
|
339
|
+
effect(()=>{
|
|
340
|
+
console.log($a()+$b())
|
|
341
|
+
})
|
|
342
|
+
$a(2); // Prints 4
|
|
343
|
+
$b(3); // Prints 5
|
|
344
|
+
// Prints only 10
|
|
345
|
+
batch(()=>{
|
|
346
|
+
$a(5);
|
|
347
|
+
$b(5);
|
|
348
|
+
})
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
${\textsf{\color{CornflowerBlue}function}}$ when - __SIGNALS SYSTEM__
|
|
353
|
+
|
|
354
|
+
Returns ImmediatePromise that is resolved when check function returns truthy value.
|
|
355
|
+
If you want to, you can resolve or reject promise beforehand.
|
|
356
|
+
|
|
357
|
+
```ts
|
|
358
|
+
await when(() => $a()>5)
|
|
359
|
+
// With timeout
|
|
360
|
+
const promise = when(() => $a() > 5)
|
|
361
|
+
const timeout = setTimeout(() => promise.reject('Timeout')}, 5000)
|
|
362
|
+
primise.then(() => clearTimeout(timeout))
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
|
|
257
368
|
## Time
|
|
258
369
|
Timers, CRON, etc.
|
|
259
370
|
|
|
@@ -289,6 +400,9 @@ Damn, I **love** TypeScript.
|
|
|
289
400
|
|
|
290
401
|
${\textsf{\color{Magenta}type}}$ Primitive - Values that are copied by value, not by reference
|
|
291
402
|
|
|
403
|
+
---
|
|
404
|
+
${\textsf{\color{Magenta}type}}$ AnyFunction - Function with any arguments or return type
|
|
405
|
+
|
|
292
406
|
---
|
|
293
407
|
${\textsf{\color{Magenta}type}}$ Falsy - Values that convert to false
|
|
294
408
|
|
package/dist/control.d.ts
CHANGED
|
@@ -31,11 +31,12 @@ export declare function createThrottledFunction<T, V extends unknown[]>(function
|
|
|
31
31
|
/** Create debounced function. Basically create function that will be called with delay,
|
|
32
32
|
* but if another call comes in, we reset the timer. */
|
|
33
33
|
export declare function createDelayedFunction<T, V extends unknown[]>(function_: (...arguments_: V) => T, time: number): (...arguments_: V) => Promise<T>;
|
|
34
|
+
type ResolveFunction<T> = undefined extends T ? (value?: T | PromiseLike<T>) => void : (value: T | PromiseLike<T>) => void;
|
|
34
35
|
/** Promise that accepts no callback, but exposes `resolve` and `reject` methods */
|
|
35
36
|
export declare class ImmediatePromise<T> extends Promise<T> {
|
|
36
|
-
resolve:
|
|
37
|
+
resolve: ResolveFunction<T>;
|
|
37
38
|
reject: (reason?: unknown) => void;
|
|
38
|
-
constructor(execute?: (resolve:
|
|
39
|
+
constructor(execute?: (resolve: ResolveFunction<T>, reject: (reason?: any) => void) => void);
|
|
39
40
|
}
|
|
40
41
|
/** Recursively resolves promises in objects and arrays */
|
|
41
42
|
export default function deepPromiseAll<T>(input: T): Promise<AwaitedObject<T>>;
|
|
@@ -45,3 +46,4 @@ export declare function wait(time: number): Promise<unknown>;
|
|
|
45
46
|
export declare function noop(): void;
|
|
46
47
|
/** Run array of async tasks concurrently */
|
|
47
48
|
export declare function concurrentRun<T>(tasks: (() => Promise<T>)[], concurrency?: number): Promise<T[]>;
|
|
49
|
+
export {};
|
package/dist/control.js
CHANGED
package/dist/formatting.d.ts
CHANGED
|
@@ -40,3 +40,26 @@ export declare function formatBytes(bytes: number): string;
|
|
|
40
40
|
export declare function log(...agrs: unknown[]): void;
|
|
41
41
|
/** Capitalize first letter */
|
|
42
42
|
export declare function capitalizeFirstLetter(value: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* pipe() can be called on one or more functions, each of which can take the return of previous value.
|
|
45
|
+
*
|
|
46
|
+
* ```ts
|
|
47
|
+
* // Takes string, converts to int, calc sqrt, convert and return date
|
|
48
|
+
* pipe(
|
|
49
|
+
* (x: string) => Number.parseInt(x),
|
|
50
|
+
* (x) => Math.sqrt(x),
|
|
51
|
+
* (x) => new Date(x)
|
|
52
|
+
* )('69')
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare function pipe(): <T>(x: T) => T;
|
|
56
|
+
export declare function pipe<T, A>(function1: (x: T) => A): (x: T) => A;
|
|
57
|
+
export declare function pipe<T, A, B>(function1: (x: T) => A, function2: (x: A) => B): (x: T) => B;
|
|
58
|
+
export declare function pipe<T, A, B, C>(function1: (x: T) => A, function2: (x: A) => B, function3: (x: B) => C): (x: T) => C;
|
|
59
|
+
export declare function pipe<T, A, B, C, D>(function1: (x: T) => A, function2: (x: A) => B, function3: (x: B) => C, function4: (x: C) => D): (x: T) => D;
|
|
60
|
+
export declare function pipe<T, A, B, C, D, E>(function1: (x: T) => A, function2: (x: A) => B, function3: (x: B) => C, function4: (x: C) => D, function5: (x: D) => E): (x: T) => E;
|
|
61
|
+
export declare function pipe<T, A, B, C, D, E, F>(function1: (x: T) => A, function2: (x: A) => B, function3: (x: B) => C, function4: (x: C) => D, function5: (x: D) => E, function6: (x: E) => F): (x: T) => F;
|
|
62
|
+
export declare function pipe<T, A, B, C, D, E, F, G>(function1: (x: T) => A, function2: (x: A) => B, function3: (x: B) => C, function4: (x: C) => D, function5: (x: D) => E, function6: (x: E) => F, function7: (x: F) => G): (x: T) => G;
|
|
63
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H>(function1: (x: T) => A, function2: (x: A) => B, function3: (x: B) => C, function4: (x: C) => D, function5: (x: D) => E, function6: (x: E) => F, function7: (x: F) => G, function8: (x: G) => H): (x: T) => H;
|
|
64
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H, I>(function1: (x: T) => A, function2: (x: A) => B, function3: (x: B) => C, function4: (x: C) => D, function5: (x: D) => E, function6: (x: E) => F, function7: (x: F) => G, function8: (x: G) => H, function9: (x: H) => I): (x: T) => I;
|
|
65
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H>(function1: (x: T) => A, function2: (x: A) => B, function3: (x: B) => C, function4: (x: C) => D, function5: (x: D) => E, function6: (x: E) => F, function7: (x: F) => G, function8: (x: G) => H, function9: (x: H) => unknown, ...fns: ((x: unknown) => unknown)[]): (x: T) => unknown;
|
package/dist/formatting.js
CHANGED
|
@@ -117,3 +117,10 @@ export function log(...agrs) {
|
|
|
117
117
|
export function capitalizeFirstLetter(value) {
|
|
118
118
|
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
119
119
|
}
|
|
120
|
+
export function pipe(...fns) {
|
|
121
|
+
return (input) => {
|
|
122
|
+
for (let index = 0; index < fns.length; index++)
|
|
123
|
+
input = fns[index](input);
|
|
124
|
+
return input;
|
|
125
|
+
};
|
|
126
|
+
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reactive signals
|
|
3
|
+
*/
|
|
4
|
+
import { ImmediatePromise } from './control';
|
|
5
|
+
import { AnyFunction } from './types';
|
|
6
|
+
export type Signal<T> = (setTo?: T | ((previous: T) => T)) => T;
|
|
7
|
+
/**
|
|
8
|
+
* __SIGNALS SYSTEM__
|
|
9
|
+
*
|
|
10
|
+
* Signal can hold any data (except functions),
|
|
11
|
+
* when this data has changed any effects containing
|
|
12
|
+
* this signal will be rerun.
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* const $mySignal = signal<number|undefined>(1) // Create signal with initial value 1
|
|
16
|
+
* $mySignal(5) // Set to 5
|
|
17
|
+
* $mySignal(undefined) // Set to undefined
|
|
18
|
+
* $mySignal(prev=>prev+1) // Increment
|
|
19
|
+
* // Will print signal on change
|
|
20
|
+
* effect(()=>{
|
|
21
|
+
* console.log($mySignal())
|
|
22
|
+
* })
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function signal<T>(): Signal<T | undefined>;
|
|
26
|
+
export declare function signal<T>(value: T): Signal<T>;
|
|
27
|
+
/**
|
|
28
|
+
* __SIGNALS SYSTEM__
|
|
29
|
+
*
|
|
30
|
+
* Effects are simplest way to react to signal changes.
|
|
31
|
+
* Returned data from handler function will be passed to it on next signal change.
|
|
32
|
+
* Returns a function that will clear the effect.
|
|
33
|
+
*
|
|
34
|
+
* ```ts
|
|
35
|
+
* // Will print signal on change
|
|
36
|
+
* effect(()=>{
|
|
37
|
+
* console.log($mySignal())
|
|
38
|
+
* })
|
|
39
|
+
* // Use previous state as a reference
|
|
40
|
+
* effect((last)=>{
|
|
41
|
+
* const mySignal = $mySignal()
|
|
42
|
+
* if(last>mySignal) console.log('Increment!')
|
|
43
|
+
* return mySignal;
|
|
44
|
+
* })
|
|
45
|
+
*/
|
|
46
|
+
export declare function effect<T>(handler: (argument: T | undefined) => T, initialValue?: T): () => void;
|
|
47
|
+
/**
|
|
48
|
+
* __SIGNALS SYSTEM__
|
|
49
|
+
*
|
|
50
|
+
* Untrack helps to not react to changes in effects.
|
|
51
|
+
* ```ts
|
|
52
|
+
* const $a = signal(1)
|
|
53
|
+
* const $b = signal(2)
|
|
54
|
+
* // Will only run on changes to $b
|
|
55
|
+
* effect(()=>{
|
|
56
|
+
* console.log(untrack($a)+$b())
|
|
57
|
+
* })
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function untrack<T>(handler: () => T): T;
|
|
61
|
+
/**
|
|
62
|
+
* __SIGNALS SYSTEM__
|
|
63
|
+
*
|
|
64
|
+
* Creates a derived reactive memoized signal.
|
|
65
|
+
*
|
|
66
|
+
* ```ts
|
|
67
|
+
* // Sum of all changes of $a()
|
|
68
|
+
* const { signal: $sumOfTwo, clear: clearSum } = derived((value) => value + $a(), 0)
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export declare function derived<T>(handler: (argument: T | undefined) => T): {
|
|
72
|
+
signal: Signal<T>;
|
|
73
|
+
clear: () => void;
|
|
74
|
+
};
|
|
75
|
+
export declare function derived<T>(handler: (argument: T) => T, initialValue: T): {
|
|
76
|
+
signal: Signal<T>;
|
|
77
|
+
clear: () => void;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* __SIGNALS SYSTEM__
|
|
81
|
+
*
|
|
82
|
+
* Batches multiple edits, so they don't call same effects multiple times
|
|
83
|
+
*
|
|
84
|
+
* ```ts
|
|
85
|
+
* const $a = signal(1)
|
|
86
|
+
* const $b = signal(2)
|
|
87
|
+
* effect(()=>{
|
|
88
|
+
* console.log($a()+$b())
|
|
89
|
+
* })
|
|
90
|
+
* $a(2); // Prints 4
|
|
91
|
+
* $b(3); // Prints 5
|
|
92
|
+
* // Prints only 10
|
|
93
|
+
* batch(()=>{
|
|
94
|
+
* $a(5);
|
|
95
|
+
* $b(5);
|
|
96
|
+
* })
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export declare function batch(handler: AnyFunction): void;
|
|
100
|
+
/**
|
|
101
|
+
* __SIGNALS SYSTEM__
|
|
102
|
+
*
|
|
103
|
+
* Returns ImmediatePromise that is resolved when check function returns truthy value.
|
|
104
|
+
* If you want to, you can resolve or reject promise beforehand.
|
|
105
|
+
*
|
|
106
|
+
* ```ts
|
|
107
|
+
* await when(() => $a()>5)
|
|
108
|
+
* // With timeout
|
|
109
|
+
* const promise = when(() => $a() > 5)
|
|
110
|
+
* const timeout = setTimeout(() => promise.reject('Timeout')}, 5000)
|
|
111
|
+
* primise.then(() => clearTimeout(timeout))
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export declare function when(check: () => unknown): ImmediatePromise<undefined>;
|
package/dist/signals.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reactive signals
|
|
3
|
+
*/
|
|
4
|
+
import { ImmediatePromise } from './control';
|
|
5
|
+
let currentEffect;
|
|
6
|
+
const effectsMap = new WeakMap();
|
|
7
|
+
let batchedEffects;
|
|
8
|
+
export function signal(value) {
|
|
9
|
+
const subscribers = new Set();
|
|
10
|
+
return (...arguments_) => {
|
|
11
|
+
if (arguments_.length === 1) {
|
|
12
|
+
const argument = arguments_[0];
|
|
13
|
+
value =
|
|
14
|
+
typeof argument === 'function'
|
|
15
|
+
? argument(value)
|
|
16
|
+
: argument;
|
|
17
|
+
if (batchedEffects)
|
|
18
|
+
for (const subscriber of subscribers)
|
|
19
|
+
batchedEffects.add(subscriber);
|
|
20
|
+
else
|
|
21
|
+
for (const subscriber of subscribers)
|
|
22
|
+
subscriber();
|
|
23
|
+
}
|
|
24
|
+
else if (currentEffect) {
|
|
25
|
+
subscribers.add(currentEffect);
|
|
26
|
+
// This is for clear() of effects
|
|
27
|
+
let effectSubscribers = effectsMap.get(currentEffect);
|
|
28
|
+
if (!effectSubscribers) {
|
|
29
|
+
effectSubscribers = new Set();
|
|
30
|
+
effectsMap.set(currentEffect, effectSubscribers);
|
|
31
|
+
}
|
|
32
|
+
effectSubscribers.add(subscribers);
|
|
33
|
+
}
|
|
34
|
+
return value;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function clearEffect(handler) {
|
|
38
|
+
const signalSubscribers = effectsMap.get(handler);
|
|
39
|
+
if (signalSubscribers)
|
|
40
|
+
for (const subscribers of signalSubscribers)
|
|
41
|
+
subscribers.delete(handler);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* __SIGNALS SYSTEM__
|
|
45
|
+
*
|
|
46
|
+
* Effects are simplest way to react to signal changes.
|
|
47
|
+
* Returned data from handler function will be passed to it on next signal change.
|
|
48
|
+
* Returns a function that will clear the effect.
|
|
49
|
+
*
|
|
50
|
+
* ```ts
|
|
51
|
+
* // Will print signal on change
|
|
52
|
+
* effect(()=>{
|
|
53
|
+
* console.log($mySignal())
|
|
54
|
+
* })
|
|
55
|
+
* // Use previous state as a reference
|
|
56
|
+
* effect((last)=>{
|
|
57
|
+
* const mySignal = $mySignal()
|
|
58
|
+
* if(last>mySignal) console.log('Increment!')
|
|
59
|
+
* return mySignal;
|
|
60
|
+
* })
|
|
61
|
+
*/
|
|
62
|
+
export function effect(handler, initialValue) {
|
|
63
|
+
let lastValue = initialValue;
|
|
64
|
+
const wrappedHandler = () => {
|
|
65
|
+
lastValue = handler(lastValue);
|
|
66
|
+
};
|
|
67
|
+
currentEffect = wrappedHandler;
|
|
68
|
+
wrappedHandler();
|
|
69
|
+
currentEffect = undefined;
|
|
70
|
+
return () => {
|
|
71
|
+
clearEffect(wrappedHandler);
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* __SIGNALS SYSTEM__
|
|
76
|
+
*
|
|
77
|
+
* Untrack helps to not react to changes in effects.
|
|
78
|
+
* ```ts
|
|
79
|
+
* const $a = signal(1)
|
|
80
|
+
* const $b = signal(2)
|
|
81
|
+
* // Will only run on changes to $b
|
|
82
|
+
* effect(()=>{
|
|
83
|
+
* console.log(untrack($a)+$b())
|
|
84
|
+
* })
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export function untrack(handler) {
|
|
88
|
+
const lastEffect = currentEffect;
|
|
89
|
+
currentEffect = undefined;
|
|
90
|
+
const data = handler();
|
|
91
|
+
currentEffect = lastEffect;
|
|
92
|
+
return data;
|
|
93
|
+
}
|
|
94
|
+
export function derived(handler, initialValue) {
|
|
95
|
+
const signal$ = signal(initialValue);
|
|
96
|
+
const wrappedHandler = () => signal$((value) => handler(value));
|
|
97
|
+
currentEffect = wrappedHandler;
|
|
98
|
+
wrappedHandler();
|
|
99
|
+
currentEffect = undefined;
|
|
100
|
+
return {
|
|
101
|
+
signal: signal$,
|
|
102
|
+
clear: () => {
|
|
103
|
+
clearEffect(wrappedHandler);
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* __SIGNALS SYSTEM__
|
|
109
|
+
*
|
|
110
|
+
* Batches multiple edits, so they don't call same effects multiple times
|
|
111
|
+
*
|
|
112
|
+
* ```ts
|
|
113
|
+
* const $a = signal(1)
|
|
114
|
+
* const $b = signal(2)
|
|
115
|
+
* effect(()=>{
|
|
116
|
+
* console.log($a()+$b())
|
|
117
|
+
* })
|
|
118
|
+
* $a(2); // Prints 4
|
|
119
|
+
* $b(3); // Prints 5
|
|
120
|
+
* // Prints only 10
|
|
121
|
+
* batch(()=>{
|
|
122
|
+
* $a(5);
|
|
123
|
+
* $b(5);
|
|
124
|
+
* })
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export function batch(handler) {
|
|
128
|
+
batchedEffects = new Set();
|
|
129
|
+
handler();
|
|
130
|
+
for (const effect of batchedEffects)
|
|
131
|
+
effect();
|
|
132
|
+
batchedEffects = undefined;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* __SIGNALS SYSTEM__
|
|
136
|
+
*
|
|
137
|
+
* Returns ImmediatePromise that is resolved when check function returns truthy value.
|
|
138
|
+
* If you want to, you can resolve or reject promise beforehand.
|
|
139
|
+
*
|
|
140
|
+
* ```ts
|
|
141
|
+
* await when(() => $a()>5)
|
|
142
|
+
* // With timeout
|
|
143
|
+
* const promise = when(() => $a() > 5)
|
|
144
|
+
* const timeout = setTimeout(() => promise.reject('Timeout')}, 5000)
|
|
145
|
+
* primise.then(() => clearTimeout(timeout))
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export function when(check) {
|
|
149
|
+
const promise = new ImmediatePromise();
|
|
150
|
+
const clear = effect(() => {
|
|
151
|
+
if (check())
|
|
152
|
+
promise.resolve();
|
|
153
|
+
});
|
|
154
|
+
void promise.finally(() => {
|
|
155
|
+
clear();
|
|
156
|
+
});
|
|
157
|
+
return promise;
|
|
158
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
/** Values that are copied by value, not by reference */
|
|
5
5
|
export type Primitive = string | number | bigint | boolean | symbol | null | undefined;
|
|
6
|
+
/** Function with any arguments or return type */
|
|
7
|
+
export type AnyFunction = (...arguments_: any[]) => any;
|
|
6
8
|
/** Values that convert to false */
|
|
7
9
|
export type Falsy = false | '' | 0 | null | undefined;
|
|
8
10
|
/** Make keys in object optional */
|