@oscarpalmer/atoms 0.117.0 → 0.118.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/dist/array/get.js +1 -0
- package/dist/array/sort.js +0 -1
- package/dist/atoms.full.js +72 -58
- package/dist/beacon.js +45 -33
- package/dist/index.js +1 -1
- package/dist/is.js +4 -1
- package/package.json +2 -2
- package/src/array/get.ts +4 -0
- package/src/array/sort.ts +1 -1
- package/src/beacon.ts +86 -39
- package/src/internal/math/aggregate.ts +2 -9
- package/src/is.ts +15 -6
- package/src/math.ts +7 -6
- package/src/models.ts +38 -26
- package/src/sized.ts +2 -2
- package/types/beacon.d.ts +14 -3
- package/types/internal/math/aggregate.d.ts +2 -8
- package/types/is.d.ts +5 -5
- package/types/math.d.ts +6 -6
- package/types/models.d.ts +19 -4
package/dist/array/get.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isPlainObject } from "../internal/is.js";
|
|
2
2
|
function getArray(value, indiced) {
|
|
3
3
|
if (Array.isArray(value)) return value;
|
|
4
|
+
if (value instanceof Map || value instanceof Set) return [...value.values()];
|
|
4
5
|
if (!isPlainObject(value)) return [value];
|
|
5
6
|
if (indiced !== true) return Object.values(value);
|
|
6
7
|
const keys = Object.keys(value);
|
package/dist/array/sort.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { isPlainObject } from "../internal/is.js";
|
|
2
2
|
import { compare } from "../internal/value/compare.js";
|
|
3
|
-
import "../is.js";
|
|
4
3
|
function getCallback(value, key, forObject) {
|
|
5
4
|
if (key != null) return;
|
|
6
5
|
if (forObject && typeof value.value === "function") return value.value;
|
package/dist/atoms.full.js
CHANGED
|
@@ -178,6 +178,7 @@ function flatten(array) {
|
|
|
178
178
|
}
|
|
179
179
|
function getArray(value, indiced) {
|
|
180
180
|
if (Array.isArray(value)) return value;
|
|
181
|
+
if (value instanceof Map || value instanceof Set) return [...value.values()];
|
|
181
182
|
if (!isPlainObject(value)) return [value];
|
|
182
183
|
if (indiced !== true) return Object.values(value);
|
|
183
184
|
const keys = Object.keys(value);
|
|
@@ -354,32 +355,6 @@ const comparators = {
|
|
|
354
355
|
number: compareNumbers,
|
|
355
356
|
symbol: compareSymbols
|
|
356
357
|
};
|
|
357
|
-
function isEmpty(value) {
|
|
358
|
-
const values = Object.values(value);
|
|
359
|
-
const { length } = values;
|
|
360
|
-
for (let index = 0; index < length; index += 1) if (values[index] != null) return false;
|
|
361
|
-
return true;
|
|
362
|
-
}
|
|
363
|
-
function isNullable(value) {
|
|
364
|
-
return value == null;
|
|
365
|
-
}
|
|
366
|
-
function isNullableOrEmpty(value) {
|
|
367
|
-
return value == null || getString(value) === "";
|
|
368
|
-
}
|
|
369
|
-
function isNullableOrWhitespace(value) {
|
|
370
|
-
return value == null || EXPRESSION_WHITESPACE.test(getString(value));
|
|
371
|
-
}
|
|
372
|
-
function isNumerical(value) {
|
|
373
|
-
return isNumber(value) || typeof value === "string" && value.trim().length > 0 && !Number.isNaN(+value);
|
|
374
|
-
}
|
|
375
|
-
function isObject(value) {
|
|
376
|
-
return typeof value === "object" && value !== null || typeof value === "function";
|
|
377
|
-
}
|
|
378
|
-
function isPrimitive(value) {
|
|
379
|
-
return value == null || EXPRESSION_PRIMITIVE.test(typeof value);
|
|
380
|
-
}
|
|
381
|
-
const EXPRESSION_PRIMITIVE = /^(bigint|boolean|number|string|symbol)$/;
|
|
382
|
-
const EXPRESSION_WHITESPACE = /^\s*$/;
|
|
383
358
|
function getCallback(value, key, forObject) {
|
|
384
359
|
if (key != null) return;
|
|
385
360
|
if (forObject && typeof value.value === "function") return value.value;
|
|
@@ -476,18 +451,21 @@ function unique(array, key) {
|
|
|
476
451
|
}
|
|
477
452
|
function noop() {}
|
|
478
453
|
var Beacon = class {
|
|
454
|
+
#options;
|
|
479
455
|
#state;
|
|
480
456
|
get active() {
|
|
481
457
|
return this.#state.active;
|
|
482
458
|
}
|
|
483
459
|
get observable() {
|
|
460
|
+
if (!this.#state.active) throw new Error(DESTROYED_BEACON);
|
|
484
461
|
return this.#state.observable;
|
|
485
462
|
}
|
|
486
463
|
get value() {
|
|
487
464
|
return this.#state.value;
|
|
488
465
|
}
|
|
489
|
-
constructor(value) {
|
|
466
|
+
constructor(value, options) {
|
|
490
467
|
const observers = /* @__PURE__ */ new Map();
|
|
468
|
+
this.#options = getBeaconOptions(options);
|
|
491
469
|
this.#state = {
|
|
492
470
|
observers,
|
|
493
471
|
value,
|
|
@@ -499,28 +477,30 @@ var Beacon = class {
|
|
|
499
477
|
finishBeacon(this.#state, false);
|
|
500
478
|
}
|
|
501
479
|
emit(value, finish) {
|
|
502
|
-
this.#on("next",
|
|
480
|
+
this.#on("next", value, finish);
|
|
503
481
|
}
|
|
504
482
|
error(error, finish) {
|
|
505
|
-
this.#on("error",
|
|
483
|
+
this.#on("error", error, finish);
|
|
506
484
|
}
|
|
507
485
|
finish() {
|
|
508
486
|
finishBeacon(this.#state, true);
|
|
509
487
|
}
|
|
510
|
-
#on(type,
|
|
511
|
-
if (this.#state.active)
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
488
|
+
#on(type, value, finish) {
|
|
489
|
+
if (!this.#state.active) return;
|
|
490
|
+
if (type === "next") {
|
|
491
|
+
if (this.#options.equal(this.#state.value, value)) return;
|
|
492
|
+
this.#state.value = value;
|
|
515
493
|
}
|
|
494
|
+
for (const [, observer] of this.#state.observers) observer[type]?.(value);
|
|
495
|
+
if (finish === true) finishBeacon(this.#state, true);
|
|
516
496
|
}
|
|
517
497
|
};
|
|
518
498
|
var Observable = class {
|
|
519
499
|
#state;
|
|
520
|
-
constructor(
|
|
500
|
+
constructor(instance, observers) {
|
|
521
501
|
this.#state = {
|
|
522
502
|
observers,
|
|
523
|
-
beacon:
|
|
503
|
+
beacon: instance,
|
|
524
504
|
closed: false
|
|
525
505
|
};
|
|
526
506
|
}
|
|
@@ -528,7 +508,7 @@ var Observable = class {
|
|
|
528
508
|
this.#state.closed = true;
|
|
529
509
|
}
|
|
530
510
|
subscribe(first, second, third) {
|
|
531
|
-
if (this.#state.closed) throw new Error(
|
|
511
|
+
if (this.#state.closed) throw new Error(DESTROYED_OBSERVABLE);
|
|
532
512
|
const observer = getObserver(first, second, third);
|
|
533
513
|
const instance = new Subscription(this.#state);
|
|
534
514
|
this.#state.observers.set(instance, observer);
|
|
@@ -557,40 +537,46 @@ var Subscription = class {
|
|
|
557
537
|
}
|
|
558
538
|
}
|
|
559
539
|
};
|
|
560
|
-
function beacon(value) {
|
|
561
|
-
return new Beacon(value);
|
|
540
|
+
function beacon(value, options) {
|
|
541
|
+
return new Beacon(value, options);
|
|
562
542
|
}
|
|
563
543
|
function finishBeacon(state, emit) {
|
|
564
|
-
if (state.active)
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
}
|
|
573
|
-
state.observable?.destroy();
|
|
574
|
-
state.observers.clear();
|
|
544
|
+
if (!state.active) return;
|
|
545
|
+
state.active = false;
|
|
546
|
+
const entries = [...state.observers.entries()];
|
|
547
|
+
const { length } = entries;
|
|
548
|
+
for (let index = 0; index < length; index += 1) {
|
|
549
|
+
const [subscription, observer] = entries[index];
|
|
550
|
+
if (emit) observer.complete?.();
|
|
551
|
+
subscription.destroy();
|
|
575
552
|
}
|
|
553
|
+
state.observable?.destroy();
|
|
554
|
+
state.observers.clear();
|
|
555
|
+
}
|
|
556
|
+
function getBeaconOptions(input) {
|
|
557
|
+
const options = isPlainObject(input) ? input : {};
|
|
558
|
+
options.equal = typeof options.equal === "function" ? options.equal : Object.is;
|
|
559
|
+
return options;
|
|
576
560
|
}
|
|
577
|
-
function
|
|
578
|
-
return typeof value === "function" ? value :
|
|
561
|
+
function getObservableCallback(value) {
|
|
562
|
+
return typeof value === "function" ? value : noop;
|
|
579
563
|
}
|
|
580
564
|
function getObserver(first, second, third) {
|
|
581
565
|
let observer = { next: noop };
|
|
582
566
|
if (typeof first === "function") observer = {
|
|
583
|
-
error:
|
|
584
|
-
next:
|
|
585
|
-
complete:
|
|
567
|
+
error: getObservableCallback(second),
|
|
568
|
+
next: getObservableCallback(first),
|
|
569
|
+
complete: getObservableCallback(third)
|
|
586
570
|
};
|
|
587
571
|
else if (typeof first === "object") {
|
|
588
|
-
observer.complete =
|
|
589
|
-
observer.error =
|
|
590
|
-
observer.next =
|
|
572
|
+
observer.complete = getObservableCallback(first?.complete);
|
|
573
|
+
observer.error = getObservableCallback(first?.error);
|
|
574
|
+
observer.next = getObservableCallback(first?.next);
|
|
591
575
|
}
|
|
592
576
|
return observer;
|
|
593
577
|
}
|
|
578
|
+
const DESTROYED_BEACON = "Cannot retrieve observable from a destroyed beacon";
|
|
579
|
+
const DESTROYED_OBSERVABLE = "Cannot subscribe to a destroyed observable";
|
|
594
580
|
const ALPHA_FULL_HEX_SHORT = "f";
|
|
595
581
|
const ALPHA_FULL_HEX_LONG = `${ALPHA_FULL_HEX_SHORT}${ALPHA_FULL_HEX_SHORT}`;
|
|
596
582
|
const ALPHA_FULL_VALUE = 1;
|
|
@@ -1287,6 +1273,34 @@ function throttle(callback, time) {
|
|
|
1287
1273
|
return throttler;
|
|
1288
1274
|
}
|
|
1289
1275
|
const DEFAULT_CACHE_SIZE = 65536;
|
|
1276
|
+
function isEmpty(value) {
|
|
1277
|
+
if (value == null) return true;
|
|
1278
|
+
if (typeof value === "string") return value.length === 0;
|
|
1279
|
+
const values = getArray(value);
|
|
1280
|
+
const { length } = values;
|
|
1281
|
+
for (let index = 0; index < length; index += 1) if (values[index] != null) return false;
|
|
1282
|
+
return true;
|
|
1283
|
+
}
|
|
1284
|
+
function isNullable(value) {
|
|
1285
|
+
return value == null;
|
|
1286
|
+
}
|
|
1287
|
+
function isNullableOrEmpty(value) {
|
|
1288
|
+
return value == null || getString(value) === "";
|
|
1289
|
+
}
|
|
1290
|
+
function isNullableOrWhitespace(value) {
|
|
1291
|
+
return value == null || EXPRESSION_WHITESPACE.test(getString(value));
|
|
1292
|
+
}
|
|
1293
|
+
function isNumerical(value) {
|
|
1294
|
+
return isNumber(value) || typeof value === "string" && value.trim().length > 0 && !Number.isNaN(+value);
|
|
1295
|
+
}
|
|
1296
|
+
function isObject(value) {
|
|
1297
|
+
return typeof value === "object" && value !== null || typeof value === "function";
|
|
1298
|
+
}
|
|
1299
|
+
function isPrimitive(value) {
|
|
1300
|
+
return value == null || EXPRESSION_PRIMITIVE.test(typeof value);
|
|
1301
|
+
}
|
|
1302
|
+
const EXPRESSION_PRIMITIVE = /^(bigint|boolean|number|string|symbol)$/;
|
|
1303
|
+
const EXPRESSION_WHITESPACE = /^\s*$/;
|
|
1290
1304
|
let enabled = true;
|
|
1291
1305
|
var Logger = class {
|
|
1292
1306
|
get debug() {
|
package/dist/beacon.js
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
|
+
import { isPlainObject } from "./internal/is.js";
|
|
1
2
|
import { noop } from "./internal/function.js";
|
|
2
3
|
var Beacon = class {
|
|
4
|
+
#options;
|
|
3
5
|
#state;
|
|
4
6
|
get active() {
|
|
5
7
|
return this.#state.active;
|
|
6
8
|
}
|
|
7
9
|
get observable() {
|
|
10
|
+
if (!this.#state.active) throw new Error(DESTROYED_BEACON);
|
|
8
11
|
return this.#state.observable;
|
|
9
12
|
}
|
|
10
13
|
get value() {
|
|
11
14
|
return this.#state.value;
|
|
12
15
|
}
|
|
13
|
-
constructor(value) {
|
|
16
|
+
constructor(value, options) {
|
|
14
17
|
const observers = /* @__PURE__ */ new Map();
|
|
18
|
+
this.#options = getBeaconOptions(options);
|
|
15
19
|
this.#state = {
|
|
16
20
|
observers,
|
|
17
21
|
value,
|
|
@@ -23,28 +27,30 @@ var Beacon = class {
|
|
|
23
27
|
finishBeacon(this.#state, false);
|
|
24
28
|
}
|
|
25
29
|
emit(value, finish) {
|
|
26
|
-
this.#on("next",
|
|
30
|
+
this.#on("next", value, finish);
|
|
27
31
|
}
|
|
28
32
|
error(error, finish) {
|
|
29
|
-
this.#on("error",
|
|
33
|
+
this.#on("error", error, finish);
|
|
30
34
|
}
|
|
31
35
|
finish() {
|
|
32
36
|
finishBeacon(this.#state, true);
|
|
33
37
|
}
|
|
34
|
-
#on(type,
|
|
35
|
-
if (this.#state.active)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
#on(type, value, finish) {
|
|
39
|
+
if (!this.#state.active) return;
|
|
40
|
+
if (type === "next") {
|
|
41
|
+
if (this.#options.equal(this.#state.value, value)) return;
|
|
42
|
+
this.#state.value = value;
|
|
39
43
|
}
|
|
44
|
+
for (const [, observer] of this.#state.observers) observer[type]?.(value);
|
|
45
|
+
if (finish === true) finishBeacon(this.#state, true);
|
|
40
46
|
}
|
|
41
47
|
};
|
|
42
48
|
var Observable = class {
|
|
43
49
|
#state;
|
|
44
|
-
constructor(
|
|
50
|
+
constructor(instance, observers) {
|
|
45
51
|
this.#state = {
|
|
46
52
|
observers,
|
|
47
|
-
beacon:
|
|
53
|
+
beacon: instance,
|
|
48
54
|
closed: false
|
|
49
55
|
};
|
|
50
56
|
}
|
|
@@ -52,7 +58,7 @@ var Observable = class {
|
|
|
52
58
|
this.#state.closed = true;
|
|
53
59
|
}
|
|
54
60
|
subscribe(first, second, third) {
|
|
55
|
-
if (this.#state.closed) throw new Error(
|
|
61
|
+
if (this.#state.closed) throw new Error(DESTROYED_OBSERVABLE);
|
|
56
62
|
const observer = getObserver(first, second, third);
|
|
57
63
|
const instance = new Subscription(this.#state);
|
|
58
64
|
this.#state.observers.set(instance, observer);
|
|
@@ -81,38 +87,44 @@ var Subscription = class {
|
|
|
81
87
|
}
|
|
82
88
|
}
|
|
83
89
|
};
|
|
84
|
-
function beacon(value) {
|
|
85
|
-
return new Beacon(value);
|
|
90
|
+
function beacon(value, options) {
|
|
91
|
+
return new Beacon(value, options);
|
|
86
92
|
}
|
|
87
93
|
function finishBeacon(state, emit) {
|
|
88
|
-
if (state.active)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
94
|
+
if (!state.active) return;
|
|
95
|
+
state.active = false;
|
|
96
|
+
const entries = [...state.observers.entries()];
|
|
97
|
+
const { length } = entries;
|
|
98
|
+
for (let index = 0; index < length; index += 1) {
|
|
99
|
+
const [subscription, observer] = entries[index];
|
|
100
|
+
if (emit) observer.complete?.();
|
|
101
|
+
subscription.destroy();
|
|
102
|
+
}
|
|
103
|
+
state.observable?.destroy();
|
|
104
|
+
state.observers.clear();
|
|
105
|
+
}
|
|
106
|
+
function getBeaconOptions(input) {
|
|
107
|
+
const options = isPlainObject(input) ? input : {};
|
|
108
|
+
options.equal = typeof options.equal === "function" ? options.equal : Object.is;
|
|
109
|
+
return options;
|
|
100
110
|
}
|
|
101
|
-
function
|
|
102
|
-
return typeof value === "function" ? value :
|
|
111
|
+
function getObservableCallback(value) {
|
|
112
|
+
return typeof value === "function" ? value : noop;
|
|
103
113
|
}
|
|
104
114
|
function getObserver(first, second, third) {
|
|
105
115
|
let observer = { next: noop };
|
|
106
116
|
if (typeof first === "function") observer = {
|
|
107
|
-
error:
|
|
108
|
-
next:
|
|
109
|
-
complete:
|
|
117
|
+
error: getObservableCallback(second),
|
|
118
|
+
next: getObservableCallback(first),
|
|
119
|
+
complete: getObservableCallback(third)
|
|
110
120
|
};
|
|
111
121
|
else if (typeof first === "object") {
|
|
112
|
-
observer.complete =
|
|
113
|
-
observer.error =
|
|
114
|
-
observer.next =
|
|
122
|
+
observer.complete = getObservableCallback(first?.complete);
|
|
123
|
+
observer.error = getObservableCallback(first?.error);
|
|
124
|
+
observer.next = getObservableCallback(first?.next);
|
|
115
125
|
}
|
|
116
126
|
return observer;
|
|
117
127
|
}
|
|
128
|
+
var DESTROYED_BEACON = "Cannot retrieve observable from a destroyed beacon";
|
|
129
|
+
var DESTROYED_OBSERVABLE = "Cannot subscribe to a destroyed observable";
|
|
118
130
|
export { beacon };
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,6 @@ import { push } from "./array/push.js";
|
|
|
15
15
|
import { max } from "./internal/math/aggregate.js";
|
|
16
16
|
import { getString, join, words } from "./internal/string.js";
|
|
17
17
|
import { compare } from "./internal/value/compare.js";
|
|
18
|
-
import { isEmpty, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumerical, isObject, isPrimitive } from "./is.js";
|
|
19
18
|
import { sort } from "./array/sort.js";
|
|
20
19
|
import { splice } from "./array/splice.js";
|
|
21
20
|
import { toMap } from "./array/to-map.js";
|
|
@@ -36,6 +35,7 @@ import { getColor } from "./color/index.js";
|
|
|
36
35
|
import frame_rate_default from "./internal/frame-rate.js";
|
|
37
36
|
import { SizedMap, SizedSet } from "./sized.js";
|
|
38
37
|
import { debounce, memoize, throttle } from "./function.js";
|
|
38
|
+
import { isEmpty, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumerical, isObject, isPrimitive } from "./is.js";
|
|
39
39
|
import { logger } from "./logger.js";
|
|
40
40
|
import { average, count, min, round, sum } from "./math.js";
|
|
41
41
|
import { setValue } from "./internal/value/set.js";
|
package/dist/is.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { isArrayOrPlainObject, isKey, isNumber, isPlainObject, isTypedArray } from "./internal/is.js";
|
|
2
|
+
import { getArray } from "./array/get.js";
|
|
2
3
|
import { getString } from "./internal/string.js";
|
|
3
4
|
function isEmpty(value) {
|
|
4
|
-
|
|
5
|
+
if (value == null) return true;
|
|
6
|
+
if (typeof value === "string") return value.length === 0;
|
|
7
|
+
const values = getArray(value);
|
|
5
8
|
const { length } = values;
|
|
6
9
|
for (let index = 0; index < length; index += 1) if (values[index] != null) return false;
|
|
7
10
|
return true;
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"jsdom": "^27.3",
|
|
11
11
|
"oxfmt": "^0.19",
|
|
12
12
|
"oxlint": "^1.34",
|
|
13
|
-
"rolldown": "1.0.0-beta.
|
|
13
|
+
"rolldown": "1.0.0-beta.56",
|
|
14
14
|
"tslib": "^2.8",
|
|
15
15
|
"typescript": "^5.9",
|
|
16
16
|
"vite": "8.0.0-beta.2",
|
|
@@ -101,5 +101,5 @@
|
|
|
101
101
|
},
|
|
102
102
|
"type": "module",
|
|
103
103
|
"types": "./types/index.d.ts",
|
|
104
|
-
"version": "0.
|
|
104
|
+
"version": "0.118.0"
|
|
105
105
|
}
|
package/src/array/get.ts
CHANGED
package/src/array/sort.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {compare} from '../internal/value/compare';
|
|
2
|
-
import {isPlainObject} from '../is';
|
|
2
|
+
import {isPlainObject} from '../internal/is';
|
|
3
3
|
import type {GenericCallback, PlainObject, Primitive} from '../models';
|
|
4
4
|
import type {CallbackSorter, KeySorter} from './models';
|
|
5
5
|
|
package/src/beacon.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {noop} from './internal/function';
|
|
2
|
+
import {isPlainObject} from './internal/is';
|
|
3
|
+
import type {PlainObject} from './models';
|
|
2
4
|
|
|
3
5
|
class Beacon<Value> {
|
|
6
|
+
readonly #options: Options;
|
|
4
7
|
readonly #state: BeaconState<Value>;
|
|
5
8
|
|
|
6
9
|
/**
|
|
@@ -14,6 +17,10 @@ class Beacon<Value> {
|
|
|
14
17
|
* The observable that can be subscribed to
|
|
15
18
|
*/
|
|
16
19
|
get observable(): Observable<Value> {
|
|
20
|
+
if (!this.#state.active) {
|
|
21
|
+
throw new Error(DESTROYED_BEACON);
|
|
22
|
+
}
|
|
23
|
+
|
|
17
24
|
return this.#state.observable;
|
|
18
25
|
}
|
|
19
26
|
|
|
@@ -24,9 +31,11 @@ class Beacon<Value> {
|
|
|
24
31
|
return this.#state.value;
|
|
25
32
|
}
|
|
26
33
|
|
|
27
|
-
constructor(value: Value) {
|
|
34
|
+
constructor(value: Value, options?: BeaconOptions<Value>) {
|
|
28
35
|
const observers = new Map<Subscription<Value>, Observer<Value>>();
|
|
29
36
|
|
|
37
|
+
this.#options = getBeaconOptions(options);
|
|
38
|
+
|
|
30
39
|
this.#state = {
|
|
31
40
|
observers,
|
|
32
41
|
value,
|
|
@@ -48,7 +57,7 @@ class Beacon<Value> {
|
|
|
48
57
|
* @param finish Finish the beacon after emitting? _(defaults to `false`)_
|
|
49
58
|
*/
|
|
50
59
|
emit(value: Value, finish?: boolean): void {
|
|
51
|
-
this.#on('next',
|
|
60
|
+
this.#on('next', value, finish);
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
/**
|
|
@@ -57,7 +66,7 @@ class Beacon<Value> {
|
|
|
57
66
|
* @param finish Finish the beacon after emitting? _(defaults to `false`)_
|
|
58
67
|
*/
|
|
59
68
|
error(error: Error, finish?: boolean): void {
|
|
60
|
-
this.#on('error',
|
|
69
|
+
this.#on('error', error, finish);
|
|
61
70
|
}
|
|
62
71
|
|
|
63
72
|
/**
|
|
@@ -67,23 +76,40 @@ class Beacon<Value> {
|
|
|
67
76
|
finishBeacon(this.#state, true);
|
|
68
77
|
}
|
|
69
78
|
|
|
70
|
-
#on(type: keyof Observer<never>,
|
|
71
|
-
if (this.#state.active) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
79
|
+
#on(type: keyof Observer<never>, value: Error | Value, finish?: boolean): void {
|
|
80
|
+
if (!this.#state.active) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
75
83
|
|
|
76
|
-
|
|
77
|
-
|
|
84
|
+
if (type === 'next') {
|
|
85
|
+
if (this.#options.equal(this.#state.value, value as Value)) {
|
|
86
|
+
return;
|
|
78
87
|
}
|
|
79
88
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
89
|
+
this.#state.value = value as Value;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for (const [, observer] of this.#state.observers) {
|
|
93
|
+
observer[type]?.(value as never);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (finish === true) {
|
|
97
|
+
finishBeacon(this.#state, true);
|
|
83
98
|
}
|
|
84
99
|
}
|
|
85
100
|
}
|
|
86
101
|
|
|
102
|
+
type BeaconOptions<Value> = {
|
|
103
|
+
/**
|
|
104
|
+
* Method for comparing values for equality
|
|
105
|
+
* @param first First value
|
|
106
|
+
* @param second Second value
|
|
107
|
+
* @returns `true` if the values are equal, otherwise `false`
|
|
108
|
+
* @default Object.is
|
|
109
|
+
*/
|
|
110
|
+
equal?: (first: Value, second: Value) => boolean;
|
|
111
|
+
};
|
|
112
|
+
|
|
87
113
|
type BeaconState<Value> = {
|
|
88
114
|
active: boolean;
|
|
89
115
|
observable: Observable<Value>;
|
|
@@ -94,10 +120,10 @@ type BeaconState<Value> = {
|
|
|
94
120
|
class Observable<Value> {
|
|
95
121
|
readonly #state: ObservableState<Value>;
|
|
96
122
|
|
|
97
|
-
constructor(
|
|
123
|
+
constructor(instance: Beacon<Value>, observers: Map<Subscription<Value>, Observer<Value>>) {
|
|
98
124
|
this.#state = {
|
|
99
125
|
observers,
|
|
100
|
-
beacon:
|
|
126
|
+
beacon: instance,
|
|
101
127
|
closed: false,
|
|
102
128
|
};
|
|
103
129
|
}
|
|
@@ -135,7 +161,7 @@ class Observable<Value> {
|
|
|
135
161
|
third?: () => void,
|
|
136
162
|
): Subscription<Value> {
|
|
137
163
|
if (this.#state.closed) {
|
|
138
|
-
throw new Error(
|
|
164
|
+
throw new Error(DESTROYED_OBSERVABLE);
|
|
139
165
|
}
|
|
140
166
|
|
|
141
167
|
const observer = getObserver(first, second, third);
|
|
@@ -170,6 +196,8 @@ type Observer<Value> = {
|
|
|
170
196
|
next?: (value: Value) => void;
|
|
171
197
|
};
|
|
172
198
|
|
|
199
|
+
type Options = Required<BeaconOptions<unknown>>;
|
|
200
|
+
|
|
173
201
|
class Subscription<Value> {
|
|
174
202
|
readonly #state: SubscriptionState<Value>;
|
|
175
203
|
|
|
@@ -214,40 +242,53 @@ type SubscriptionState<Value> = {
|
|
|
214
242
|
observers: Map<Subscription<Value>, Observer<Value>>;
|
|
215
243
|
};
|
|
216
244
|
|
|
245
|
+
//
|
|
246
|
+
|
|
217
247
|
/**
|
|
218
248
|
* Create a new beacon
|
|
219
249
|
* @param value Initial value
|
|
250
|
+
* @param options Beacon options
|
|
220
251
|
* @returns Beacon instance
|
|
221
252
|
*/
|
|
222
|
-
export function beacon<Value>(value: Value): Beacon<Value> {
|
|
223
|
-
return new Beacon(value);
|
|
253
|
+
export function beacon<Value>(value: Value, options?: BeaconOptions<Value>): Beacon<Value> {
|
|
254
|
+
return new Beacon(value, options);
|
|
224
255
|
}
|
|
225
256
|
|
|
226
257
|
function finishBeacon<Value>(state: BeaconState<Value>, emit: boolean): void {
|
|
227
|
-
if (state.active) {
|
|
228
|
-
|
|
258
|
+
if (!state.active) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
229
261
|
|
|
230
|
-
|
|
231
|
-
const {length} = entries;
|
|
262
|
+
state.active = false;
|
|
232
263
|
|
|
233
|
-
|
|
234
|
-
|
|
264
|
+
const entries = [...state.observers.entries()];
|
|
265
|
+
const {length} = entries;
|
|
235
266
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
267
|
+
for (let index = 0; index < length; index += 1) {
|
|
268
|
+
const [subscription, observer] = entries[index];
|
|
239
269
|
|
|
240
|
-
|
|
270
|
+
if (emit) {
|
|
271
|
+
observer.complete?.();
|
|
241
272
|
}
|
|
242
273
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
state.observers.clear();
|
|
274
|
+
subscription.destroy();
|
|
246
275
|
}
|
|
276
|
+
|
|
277
|
+
state.observable?.destroy();
|
|
278
|
+
|
|
279
|
+
state.observers.clear();
|
|
247
280
|
}
|
|
248
281
|
|
|
249
|
-
function
|
|
250
|
-
|
|
282
|
+
function getBeaconOptions(input?: BeaconOptions<never>): Options {
|
|
283
|
+
const options: Partial<Options> = isPlainObject(input) ? (input as PlainObject) : {};
|
|
284
|
+
|
|
285
|
+
options.equal = typeof options.equal === 'function' ? options.equal : Object.is;
|
|
286
|
+
|
|
287
|
+
return options as Options;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function getObservableCallback<Callback>(value: Callback): Callback {
|
|
291
|
+
return typeof value === 'function' ? value : (noop as Callback);
|
|
251
292
|
}
|
|
252
293
|
|
|
253
294
|
function getObserver<Value>(
|
|
@@ -261,17 +302,23 @@ function getObserver<Value>(
|
|
|
261
302
|
|
|
262
303
|
if (typeof first === 'function') {
|
|
263
304
|
observer = {
|
|
264
|
-
error:
|
|
265
|
-
next:
|
|
266
|
-
complete:
|
|
305
|
+
error: getObservableCallback(second),
|
|
306
|
+
next: getObservableCallback(first),
|
|
307
|
+
complete: getObservableCallback(third),
|
|
267
308
|
};
|
|
268
309
|
} else if (typeof first === 'object') {
|
|
269
|
-
observer.complete =
|
|
270
|
-
observer.error =
|
|
271
|
-
observer.next =
|
|
310
|
+
observer.complete = getObservableCallback(first?.complete);
|
|
311
|
+
observer.error = getObservableCallback(first?.error);
|
|
312
|
+
observer.next = getObservableCallback(first?.next);
|
|
272
313
|
}
|
|
273
314
|
|
|
274
315
|
return observer;
|
|
275
316
|
}
|
|
276
317
|
|
|
318
|
+
//
|
|
319
|
+
|
|
320
|
+
const DESTROYED_BEACON = 'Cannot retrieve observable from a destroyed beacon';
|
|
321
|
+
|
|
322
|
+
const DESTROYED_OBSERVABLE = 'Cannot subscribe to a destroyed observable';
|
|
323
|
+
|
|
277
324
|
export type {Beacon, Observable, Observer, Subscription};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {GenericCallback, PlainObject} from '../../models';
|
|
1
|
+
import type {GenericCallback, NumericalValues, PlainObject} from '../../models';
|
|
2
2
|
|
|
3
3
|
type Aggregation = {
|
|
4
4
|
count: number;
|
|
@@ -9,13 +9,6 @@ type AggregationCallback = (current: number, value: number, notNumber: boolean)
|
|
|
9
9
|
|
|
10
10
|
type AggregationType = 'average' | 'max' | 'min' | 'sum';
|
|
11
11
|
|
|
12
|
-
/**
|
|
13
|
-
* The numerical values of an object
|
|
14
|
-
*/
|
|
15
|
-
export type OnlyNumericalKeys<Item> = {
|
|
16
|
-
[Key in keyof Item as Item[Key] extends number ? Key : never]: Item[Key];
|
|
17
|
-
};
|
|
18
|
-
|
|
19
12
|
export function aggregate(type: AggregationType, array: unknown[], key: unknown): Aggregation {
|
|
20
13
|
const length = Array.isArray(array) ? array.length : 0;
|
|
21
14
|
|
|
@@ -73,7 +66,7 @@ export function max<Item extends PlainObject>(
|
|
|
73
66
|
*/
|
|
74
67
|
export function max<Item extends PlainObject>(
|
|
75
68
|
items: Item[],
|
|
76
|
-
key: keyof
|
|
69
|
+
key: keyof NumericalValues<Item>,
|
|
77
70
|
): number;
|
|
78
71
|
|
|
79
72
|
/**
|
package/src/is.ts
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
|
+
import {getArray} from './array/get';
|
|
1
2
|
import {isNumber} from './internal/is';
|
|
2
3
|
import {getString} from './internal/string';
|
|
3
|
-
import type {
|
|
4
|
+
import type {Primitive} from './models';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* Is the
|
|
7
|
-
* @param value
|
|
8
|
-
* @returns `true` if the
|
|
7
|
+
* Is the value empty, or only containing `null` or `undefined` values?
|
|
8
|
+
* @param value Object to check
|
|
9
|
+
* @returns `true` if the object is considered empty, otherwise `false`
|
|
9
10
|
*/
|
|
10
|
-
export function isEmpty(value:
|
|
11
|
-
|
|
11
|
+
export function isEmpty(value: unknown): boolean {
|
|
12
|
+
if (value == null) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (typeof value === 'string') {
|
|
17
|
+
return value.length === 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const values = getArray(value);
|
|
12
21
|
const {length} = values;
|
|
13
22
|
|
|
14
23
|
for (let index = 0; index < length; index += 1) {
|
package/src/math.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {aggregate
|
|
2
|
-
import type {PlainObject} from './models';
|
|
1
|
+
import {aggregate} from './internal/math/aggregate';
|
|
2
|
+
import type {NumericalValues, PlainObject} from './models';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Get the average value from a list of items
|
|
@@ -20,7 +20,7 @@ export function average<Item extends PlainObject>(
|
|
|
20
20
|
*/
|
|
21
21
|
export function average<Item extends PlainObject>(
|
|
22
22
|
items: Item[],
|
|
23
|
-
key: keyof
|
|
23
|
+
key: keyof NumericalValues<Item>,
|
|
24
24
|
): number;
|
|
25
25
|
|
|
26
26
|
/**
|
|
@@ -119,7 +119,7 @@ export function min<Item extends PlainObject>(
|
|
|
119
119
|
*/
|
|
120
120
|
export function min<Item extends PlainObject>(
|
|
121
121
|
items: Item[],
|
|
122
|
-
key: keyof
|
|
122
|
+
key: keyof NumericalValues<Item>,
|
|
123
123
|
): number;
|
|
124
124
|
|
|
125
125
|
/**
|
|
@@ -174,7 +174,7 @@ export function sum<Item extends PlainObject>(
|
|
|
174
174
|
*/
|
|
175
175
|
export function sum<Item extends PlainObject>(
|
|
176
176
|
items: Item[],
|
|
177
|
-
key: keyof
|
|
177
|
+
key: keyof NumericalValues<Item>,
|
|
178
178
|
): number;
|
|
179
179
|
|
|
180
180
|
/**
|
|
@@ -190,4 +190,5 @@ export function sum(array: unknown[], key?: unknown): number {
|
|
|
190
190
|
return aggregated.count > 0 ? aggregated.value : Number.NaN;
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
export {max
|
|
193
|
+
export {max} from './internal/math/aggregate';
|
|
194
|
+
export type {NumericalValues}
|
package/src/models.ts
CHANGED
|
@@ -38,6 +38,9 @@ export type KeyedValue<Item, Key extends keyof Item> = Item[Key] extends Propert
|
|
|
38
38
|
export type NestedArray<Value> =
|
|
39
39
|
Value extends Array<infer NestedValue> ? NestedArray<NestedValue> : Value;
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* All nested keys of an object as dot notation strings _(up to 5 levels deep)_
|
|
43
|
+
*/
|
|
41
44
|
export type NestedKeys<Value extends PlainObject> = _NestedKeys<Value>;
|
|
42
45
|
|
|
43
46
|
type _NestedKeys<Value, Depth extends number = 5> = Depth extends 0
|
|
@@ -47,11 +50,9 @@ type _NestedKeys<Value, Depth extends number = 5> = Depth extends 0
|
|
|
47
50
|
? // Tuple: extract actual indices
|
|
48
51
|
{
|
|
49
52
|
[Key in keyof Value]-?: Key extends `${number}`
|
|
50
|
-
? Value[Key] extends readonly any[]
|
|
51
|
-
? `${Key}` | `${Key}.${_NestedKeys<Value[Key]
|
|
52
|
-
:
|
|
53
|
-
? `${Key}` | `${Key}.${_NestedKeys<Value[Key], SubtractDepth<Depth>>}`
|
|
54
|
-
: `${Key}`
|
|
53
|
+
? NonNullable<Value[Key]> extends readonly any[] | PlainObject
|
|
54
|
+
? `${Key}` | `${Key}.${_NestedKeys<NonNullable<Value[Key]>, SubtractDepth<Depth>>}`
|
|
55
|
+
: `${Key}`
|
|
55
56
|
: never;
|
|
56
57
|
}[number]
|
|
57
58
|
: // Array: use no indices
|
|
@@ -59,11 +60,9 @@ type _NestedKeys<Value, Depth extends number = 5> = Depth extends 0
|
|
|
59
60
|
: Value extends PlainObject
|
|
60
61
|
? {
|
|
61
62
|
[Key in keyof Value]-?: Key extends number | string
|
|
62
|
-
? Value[Key] extends readonly any[]
|
|
63
|
-
? `${Key}` | `${Key}.${_NestedKeys<Value[Key]
|
|
64
|
-
:
|
|
65
|
-
? `${Key}` | `${Key}.${_NestedKeys<Value[Key], SubtractDepth<Depth>>}`
|
|
66
|
-
: `${Key}`
|
|
63
|
+
? NonNullable<Value[Key]> extends readonly any[] | PlainObject
|
|
64
|
+
? `${Key}` | `${Key}.${_NestedKeys<NonNullable<Value[Key]>, SubtractDepth<Depth>>}`
|
|
65
|
+
: `${Key}`
|
|
67
66
|
: never;
|
|
68
67
|
}[keyof Value]
|
|
69
68
|
: never;
|
|
@@ -75,30 +74,43 @@ export type NestedPartial<T> = {
|
|
|
75
74
|
[K in keyof T]?: T[K] extends object ? NestedPartial<T[K]> : T[K];
|
|
76
75
|
};
|
|
77
76
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
?
|
|
86
|
-
? _NestedValue<Value[Key], Rest>
|
|
87
|
-
: Key
|
|
88
|
-
|
|
89
|
-
? _NestedValue<Value[number], Rest>
|
|
90
|
-
: never
|
|
91
|
-
: never
|
|
92
|
-
: Path extends `${number}`
|
|
77
|
+
/**
|
|
78
|
+
* The value for a nested key of an object
|
|
79
|
+
*/
|
|
80
|
+
export type NestedValue<Value extends PlainObject, Path extends string> = _NestedValue<Value, Path>;
|
|
81
|
+
|
|
82
|
+
type _NestedValue<Value, Path extends string> = Path extends `${infer Key}.${infer Rest}`
|
|
83
|
+
? Key extends keyof Value
|
|
84
|
+
? undefined extends Value[Key]
|
|
85
|
+
? _NestedValue<Exclude<Value[Key], undefined>, Rest> | undefined
|
|
86
|
+
: _NestedValue<Value[Key], Rest>
|
|
87
|
+
: Key extends `${number}`
|
|
93
88
|
? Value extends readonly any[]
|
|
94
|
-
? Value[number]
|
|
89
|
+
? _NestedValue<Value[number], Rest>
|
|
95
90
|
: never
|
|
91
|
+
: never
|
|
92
|
+
: Path extends `${number}`
|
|
93
|
+
? Value extends readonly any[]
|
|
94
|
+
? Value[number]
|
|
95
|
+
: never
|
|
96
|
+
: Path extends keyof Value
|
|
97
|
+
? Value[Path]
|
|
96
98
|
: never;
|
|
97
99
|
|
|
100
|
+
/**
|
|
101
|
+
* The nested (keyed) values of an object _(up to 5 levels deep)_
|
|
102
|
+
*/
|
|
98
103
|
export type NestedValues<Value extends PlainObject> = {
|
|
99
104
|
[Path in NestedKeys<Value>]: NestedValue<Value, Path>;
|
|
100
105
|
};
|
|
101
106
|
|
|
107
|
+
/**
|
|
108
|
+
* The numerical values of an object
|
|
109
|
+
*/
|
|
110
|
+
export type NumericalValues<Item extends PlainObject> = {
|
|
111
|
+
[Key in keyof Item as Item[Key] extends number ? Key : never]: Item[Key];
|
|
112
|
+
};
|
|
113
|
+
|
|
102
114
|
/**
|
|
103
115
|
* A generic object
|
|
104
116
|
*/
|
package/src/sized.ts
CHANGED
|
@@ -206,6 +206,6 @@ function getMaximum(first?: unknown, second?: unknown): number {
|
|
|
206
206
|
|
|
207
207
|
//
|
|
208
208
|
|
|
209
|
-
const MAXIMUM_ABSOLUTE = 16_777_216;
|
|
209
|
+
const MAXIMUM_ABSOLUTE = 16_777_216; // 2^24
|
|
210
210
|
|
|
211
|
-
const MAXIMUM_DEFAULT = 1_048_576;
|
|
211
|
+
const MAXIMUM_DEFAULT = 1_048_576; // 2^20
|
package/types/beacon.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ declare class Beacon<Value> {
|
|
|
12
12
|
* The current value
|
|
13
13
|
*/
|
|
14
14
|
get value(): Value;
|
|
15
|
-
constructor(value: Value);
|
|
15
|
+
constructor(value: Value, options?: BeaconOptions<Value>);
|
|
16
16
|
/**
|
|
17
17
|
* Destroy the beacon
|
|
18
18
|
*/
|
|
@@ -34,9 +34,19 @@ declare class Beacon<Value> {
|
|
|
34
34
|
*/
|
|
35
35
|
finish(): void;
|
|
36
36
|
}
|
|
37
|
+
type BeaconOptions<Value> = {
|
|
38
|
+
/**
|
|
39
|
+
* Method for comparing values for equality
|
|
40
|
+
* @param first First value
|
|
41
|
+
* @param second Second value
|
|
42
|
+
* @returns `true` if the values are equal, otherwise `false`
|
|
43
|
+
* @default Object.is
|
|
44
|
+
*/
|
|
45
|
+
equal?: (first: Value, second: Value) => boolean;
|
|
46
|
+
};
|
|
37
47
|
declare class Observable<Value> {
|
|
38
48
|
#private;
|
|
39
|
-
constructor(
|
|
49
|
+
constructor(instance: Beacon<Value>, observers: Map<Subscription<Value>, Observer<Value>>);
|
|
40
50
|
/**
|
|
41
51
|
* Destroy the observable
|
|
42
52
|
*/
|
|
@@ -94,7 +104,8 @@ declare class Subscription<Value> {
|
|
|
94
104
|
/**
|
|
95
105
|
* Create a new beacon
|
|
96
106
|
* @param value Initial value
|
|
107
|
+
* @param options Beacon options
|
|
97
108
|
* @returns Beacon instance
|
|
98
109
|
*/
|
|
99
|
-
export declare function beacon<Value>(value: Value): Beacon<Value>;
|
|
110
|
+
export declare function beacon<Value>(value: Value, options?: BeaconOptions<Value>): Beacon<Value>;
|
|
100
111
|
export type { Beacon, Observable, Observer, Subscription };
|
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
import type { PlainObject } from '../../models';
|
|
1
|
+
import type { NumericalValues, PlainObject } from '../../models';
|
|
2
2
|
type Aggregation = {
|
|
3
3
|
count: number;
|
|
4
4
|
value: number;
|
|
5
5
|
};
|
|
6
6
|
type AggregationType = 'average' | 'max' | 'min' | 'sum';
|
|
7
|
-
/**
|
|
8
|
-
* The numerical values of an object
|
|
9
|
-
*/
|
|
10
|
-
export type OnlyNumericalKeys<Item> = {
|
|
11
|
-
[Key in keyof Item as Item[Key] extends number ? Key : never]: Item[Key];
|
|
12
|
-
};
|
|
13
7
|
export declare function aggregate(type: AggregationType, array: unknown[], key: unknown): Aggregation;
|
|
14
8
|
/**
|
|
15
9
|
* Get the maximum value from a list of items
|
|
@@ -24,7 +18,7 @@ export declare function max<Item extends PlainObject>(items: Item[], callback: (
|
|
|
24
18
|
* @param key Key to use for value
|
|
25
19
|
* @returns Maximum value, or `NaN` if no maximum can be found
|
|
26
20
|
*/
|
|
27
|
-
export declare function max<Item extends PlainObject>(items: Item[], key: keyof
|
|
21
|
+
export declare function max<Item extends PlainObject>(items: Item[], key: keyof NumericalValues<Item>): number;
|
|
28
22
|
/**
|
|
29
23
|
* Get the maximum value from a list of numbers
|
|
30
24
|
* @param values List of numbers
|
package/types/is.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Primitive } from './models';
|
|
2
2
|
/**
|
|
3
|
-
* Is the
|
|
4
|
-
* @param value
|
|
5
|
-
* @returns `true` if the
|
|
3
|
+
* Is the value empty, or only containing `null` or `undefined` values?
|
|
4
|
+
* @param value Object to check
|
|
5
|
+
* @returns `true` if the object is considered empty, otherwise `false`
|
|
6
6
|
*/
|
|
7
|
-
export declare function isEmpty(value:
|
|
7
|
+
export declare function isEmpty(value: unknown): boolean;
|
|
8
8
|
/**
|
|
9
9
|
* Is the value `undefined` or `null`?
|
|
10
10
|
* @param value Value to check
|
package/types/math.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { PlainObject } from './models';
|
|
1
|
+
import type { NumericalValues, PlainObject } from './models';
|
|
3
2
|
/**
|
|
4
3
|
* Get the average value from a list of items
|
|
5
4
|
* @param items List of items
|
|
@@ -13,7 +12,7 @@ export declare function average<Item extends PlainObject>(items: Item[], callbac
|
|
|
13
12
|
* @param key Key to use for value
|
|
14
13
|
* @returns Average value, or `NaN` if no average can be calculated
|
|
15
14
|
*/
|
|
16
|
-
export declare function average<Item extends PlainObject>(items: Item[], key: keyof
|
|
15
|
+
export declare function average<Item extends PlainObject>(items: Item[], key: keyof NumericalValues<Item>): number;
|
|
17
16
|
/**
|
|
18
17
|
* Get the average value from a list of numbers
|
|
19
18
|
* @param numbers List of numbers
|
|
@@ -55,7 +54,7 @@ export declare function min<Item extends PlainObject>(items: Item[], callback: (
|
|
|
55
54
|
* @param key Key to use for value
|
|
56
55
|
* @returns Minimum value, or `NaN` if no minimum can be found
|
|
57
56
|
*/
|
|
58
|
-
export declare function min<Item extends PlainObject>(items: Item[], key: keyof
|
|
57
|
+
export declare function min<Item extends PlainObject>(items: Item[], key: keyof NumericalValues<Item>): number;
|
|
59
58
|
/**
|
|
60
59
|
* Get the minimum value from a list of numbers
|
|
61
60
|
* @param values List of numbers
|
|
@@ -82,11 +81,12 @@ export declare function sum<Item extends PlainObject>(items: Item[], callback: (
|
|
|
82
81
|
* @param key Key to use for value
|
|
83
82
|
* @returns Sum of the values, or `NaN` if no sum can be calculated
|
|
84
83
|
*/
|
|
85
|
-
export declare function sum<Item extends PlainObject>(items: Item[], key: keyof
|
|
84
|
+
export declare function sum<Item extends PlainObject>(items: Item[], key: keyof NumericalValues<Item>): number;
|
|
86
85
|
/**
|
|
87
86
|
* Get the sum of a list of numbers
|
|
88
87
|
* @param values List of numbers
|
|
89
88
|
* @returns Sum of the numbers, or `NaN` if no sum can be calculated
|
|
90
89
|
*/
|
|
91
90
|
export declare function sum(values: number[]): number;
|
|
92
|
-
export { max
|
|
91
|
+
export { max } from './internal/math/aggregate';
|
|
92
|
+
export type { NumericalValues };
|
package/types/models.d.ts
CHANGED
|
@@ -28,11 +28,14 @@ export type KeyedValue<Item, Key extends keyof Item> = Item[Key] extends Propert
|
|
|
28
28
|
* A nested array
|
|
29
29
|
*/
|
|
30
30
|
export type NestedArray<Value> = Value extends Array<infer NestedValue> ? NestedArray<NestedValue> : Value;
|
|
31
|
+
/**
|
|
32
|
+
* All nested keys of an object as dot notation strings _(up to 5 levels deep)_
|
|
33
|
+
*/
|
|
31
34
|
export type NestedKeys<Value extends PlainObject> = _NestedKeys<Value>;
|
|
32
35
|
type _NestedKeys<Value, Depth extends number = 5> = Depth extends 0 ? never : Value extends readonly any[] ? Value extends readonly [any, ...any] ? {
|
|
33
|
-
[Key in keyof Value]-?: Key extends `${number}` ? Value[Key] extends readonly any[]
|
|
36
|
+
[Key in keyof Value]-?: Key extends `${number}` ? NonNullable<Value[Key]> extends readonly any[] | PlainObject ? `${Key}` | `${Key}.${_NestedKeys<NonNullable<Value[Key]>, SubtractDepth<Depth>>}` : `${Key}` : never;
|
|
34
37
|
}[number] : never : Value extends PlainObject ? {
|
|
35
|
-
[Key in keyof Value]-?: Key extends number | string ? Value[Key] extends readonly any[]
|
|
38
|
+
[Key in keyof Value]-?: Key extends number | string ? NonNullable<Value[Key]> extends readonly any[] | PlainObject ? `${Key}` | `${Key}.${_NestedKeys<NonNullable<Value[Key]>, SubtractDepth<Depth>>}` : `${Key}` : never;
|
|
36
39
|
}[keyof Value] : never;
|
|
37
40
|
/**
|
|
38
41
|
* An extended version of `Partial` that allows for nested properties to be optional
|
|
@@ -40,11 +43,23 @@ type _NestedKeys<Value, Depth extends number = 5> = Depth extends 0 ? never : Va
|
|
|
40
43
|
export type NestedPartial<T> = {
|
|
41
44
|
[K in keyof T]?: T[K] extends object ? NestedPartial<T[K]> : T[K];
|
|
42
45
|
};
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
/**
|
|
47
|
+
* The value for a nested key of an object
|
|
48
|
+
*/
|
|
49
|
+
export type NestedValue<Value extends PlainObject, Path extends string> = _NestedValue<Value, Path>;
|
|
50
|
+
type _NestedValue<Value, Path extends string> = Path extends `${infer Key}.${infer Rest}` ? Key extends keyof Value ? undefined extends Value[Key] ? _NestedValue<Exclude<Value[Key], undefined>, Rest> | undefined : _NestedValue<Value[Key], Rest> : Key extends `${number}` ? Value extends readonly any[] ? _NestedValue<Value[number], Rest> : never : never : Path extends `${number}` ? Value extends readonly any[] ? Value[number] : never : Path extends keyof Value ? Value[Path] : never;
|
|
51
|
+
/**
|
|
52
|
+
* The nested (keyed) values of an object _(up to 5 levels deep)_
|
|
53
|
+
*/
|
|
45
54
|
export type NestedValues<Value extends PlainObject> = {
|
|
46
55
|
[Path in NestedKeys<Value>]: NestedValue<Value, Path>;
|
|
47
56
|
};
|
|
57
|
+
/**
|
|
58
|
+
* The numerical values of an object
|
|
59
|
+
*/
|
|
60
|
+
export type NumericalValues<Item extends PlainObject> = {
|
|
61
|
+
[Key in keyof Item as Item[Key] extends number ? Key : never]: Item[Key];
|
|
62
|
+
};
|
|
48
63
|
/**
|
|
49
64
|
* A generic object
|
|
50
65
|
*/
|