@naturalcycles/js-lib 14.249.0 → 14.251.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/array.util.js +52 -42
- package/dist/datetime/localDate.js +30 -17
- package/dist/datetime/localTime.js +31 -18
- package/dist/error/assert.js +2 -1
- package/dist/http/fetcher.js +5 -5
- package/dist/json-schema/jsonSchemaBuilder.js +2 -2
- package/dist/math/math.util.js +14 -4
- package/dist/math/sma.js +4 -1
- package/dist/number/createDeterministicRandom.js +1 -1
- package/dist/number/number.util.js +2 -2
- package/dist/object/object.util.d.ts +11 -2
- package/dist/object/object.util.js +89 -38
- package/dist/object/sortObject.js +10 -7
- package/dist/object/sortObjectDeep.js +6 -9
- package/dist/promise/pDelay.d.ts +3 -3
- package/dist/promise/pDelay.js +1 -1
- package/dist/semver.js +22 -13
- package/dist/string/case.js +15 -6
- package/dist/string/lodash/words.js +1 -0
- package/dist/string/safeJsonStringify.js +1 -1
- package/dist-esm/array/array.util.js +52 -42
- package/dist-esm/datetime/localDate.js +30 -17
- package/dist-esm/datetime/localTime.js +31 -18
- package/dist-esm/error/assert.js +2 -1
- package/dist-esm/http/fetcher.js +5 -5
- package/dist-esm/json-schema/jsonSchemaBuilder.js +2 -2
- package/dist-esm/math/math.util.js +14 -4
- package/dist-esm/math/sma.js +4 -1
- package/dist-esm/number/createDeterministicRandom.js +1 -1
- package/dist-esm/number/number.util.js +2 -2
- package/dist-esm/object/object.util.js +88 -39
- package/dist-esm/object/sortObject.js +10 -7
- package/dist-esm/object/sortObjectDeep.js +6 -9
- package/dist-esm/promise/pDelay.js +1 -1
- package/dist-esm/semver.js +22 -13
- package/dist-esm/string/case.js +15 -6
- package/dist-esm/string/lodash/words.js +1 -0
- package/dist-esm/string/safeJsonStringify.js +1 -1
- package/package.json +1 -1
- package/src/array/array.util.ts +48 -40
- package/src/datetime/localDate.ts +34 -19
- package/src/datetime/localTime.ts +34 -21
- package/src/error/assert.ts +2 -1
- package/src/http/fetcher.ts +8 -6
- package/src/json-schema/jsonSchemaBuilder.ts +2 -2
- package/src/math/math.util.ts +13 -6
- package/src/math/sma.ts +3 -1
- package/src/number/createDeterministicRandom.ts +1 -1
- package/src/number/number.util.ts +4 -2
- package/src/object/object.util.ts +112 -53
- package/src/object/sortObject.ts +9 -7
- package/src/object/sortObjectDeep.ts +6 -12
- package/src/promise/pDelay.ts +6 -3
- package/src/semver.ts +22 -13
- package/src/string/case.ts +15 -12
- package/src/string/leven.ts +1 -1
- package/src/string/lodash/words.ts +1 -0
- package/src/string/safeJsonStringify.ts +1 -1
- package/src/string/string.util.ts +2 -2
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { _assert } from '../error/assert';
|
|
2
|
-
import { _isTruthy } from '../is.util';
|
|
3
2
|
import { _ms } from '../time/time.util';
|
|
4
3
|
import { localDate } from './localDate';
|
|
5
4
|
import { WallTime } from './wallTime';
|
|
@@ -673,7 +672,7 @@ class LocalTimeFactory {
|
|
|
673
672
|
if (input instanceof LocalTime)
|
|
674
673
|
return true;
|
|
675
674
|
if (input instanceof Date)
|
|
676
|
-
return !isNaN(input.getDate());
|
|
675
|
+
return !Number.isNaN(input.getDate());
|
|
677
676
|
// We currently don't validate Unixtimestamp input, treat it as always valid
|
|
678
677
|
if (typeof input === 'number')
|
|
679
678
|
return true;
|
|
@@ -694,7 +693,7 @@ class LocalTimeFactory {
|
|
|
694
693
|
if (input instanceof LocalTime)
|
|
695
694
|
return input;
|
|
696
695
|
if (input instanceof Date) {
|
|
697
|
-
if (isNaN(input.getDate()))
|
|
696
|
+
if (Number.isNaN(input.getDate()))
|
|
698
697
|
return;
|
|
699
698
|
return new LocalTime(input);
|
|
700
699
|
}
|
|
@@ -758,7 +757,7 @@ class LocalTimeFactory {
|
|
|
758
757
|
return;
|
|
759
758
|
// Attempt to parse with Date constructor
|
|
760
759
|
const d = new Date(s);
|
|
761
|
-
return isNaN(d.getDate()) ? undefined : d;
|
|
760
|
+
return Number.isNaN(d.getDate()) ? undefined : d;
|
|
762
761
|
}
|
|
763
762
|
const o = {
|
|
764
763
|
year: Number(m[1]),
|
|
@@ -786,7 +785,7 @@ class LocalTimeFactory {
|
|
|
786
785
|
return hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59 && second >= 0 && second <= 59;
|
|
787
786
|
}
|
|
788
787
|
fromDate(date) {
|
|
789
|
-
_assert(!isNaN(date.getDate()),
|
|
788
|
+
_assert(!Number.isNaN(date.getDate()), 'localTime.fromDate is called on Date object that is invalid');
|
|
790
789
|
return new LocalTime(date);
|
|
791
790
|
}
|
|
792
791
|
fromUnix(ts) {
|
|
@@ -841,24 +840,38 @@ class LocalTimeFactory {
|
|
|
841
840
|
});
|
|
842
841
|
}
|
|
843
842
|
minOrUndefined(items) {
|
|
844
|
-
|
|
843
|
+
let min;
|
|
844
|
+
for (const item of items) {
|
|
845
|
+
if (!item)
|
|
846
|
+
continue;
|
|
847
|
+
const lt = this.fromInput(item);
|
|
848
|
+
if (!min || lt.$date.valueOf() < min.$date.valueOf()) {
|
|
849
|
+
min = lt;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
return min;
|
|
845
853
|
}
|
|
846
854
|
min(items) {
|
|
847
|
-
const
|
|
848
|
-
_assert(
|
|
849
|
-
return
|
|
850
|
-
.map(i => this.fromInput(i))
|
|
851
|
-
.reduce((min, item) => (min.$date.valueOf() <= item.$date.valueOf() ? min : item));
|
|
855
|
+
const min = this.minOrUndefined(items);
|
|
856
|
+
_assert(min, 'localTime.min called on empty array');
|
|
857
|
+
return min;
|
|
852
858
|
}
|
|
853
859
|
maxOrUndefined(items) {
|
|
854
|
-
|
|
860
|
+
let max;
|
|
861
|
+
for (const item of items) {
|
|
862
|
+
if (!item)
|
|
863
|
+
continue;
|
|
864
|
+
const lt = this.fromInput(item);
|
|
865
|
+
if (!max || lt.$date.valueOf() > max.$date.valueOf()) {
|
|
866
|
+
max = lt;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
return max;
|
|
855
870
|
}
|
|
856
871
|
max(items) {
|
|
857
|
-
const
|
|
858
|
-
_assert(
|
|
859
|
-
return
|
|
860
|
-
.map(i => this.fromInput(i))
|
|
861
|
-
.reduce((max, item) => (max.$date.valueOf() >= item.$date.valueOf() ? max : item));
|
|
872
|
+
const max = this.maxOrUndefined(items);
|
|
873
|
+
_assert(max, 'localTime.max called on empty array');
|
|
874
|
+
return max;
|
|
862
875
|
}
|
|
863
876
|
}
|
|
864
877
|
// based on: https://github.com/date-fns/date-fns/blob/master/src/getISOWeek/index.ts
|
|
@@ -894,7 +907,7 @@ function getWeekYear(date) {
|
|
|
894
907
|
if (date.getTime() >= startOfNextYear.getTime()) {
|
|
895
908
|
return year + 1;
|
|
896
909
|
}
|
|
897
|
-
|
|
910
|
+
if (date.getTime() >= startOfThisYear.getTime()) {
|
|
898
911
|
return year;
|
|
899
912
|
}
|
|
900
913
|
return year - 1;
|
package/dist-esm/error/assert.js
CHANGED
|
@@ -49,7 +49,7 @@ export function _assertEquals(actual, expected, message, errorData) {
|
|
|
49
49
|
export function _assertDeepEquals(actual, expected, message, errorData) {
|
|
50
50
|
if (!_deepEquals(actual, expected)) {
|
|
51
51
|
const msg = message ||
|
|
52
|
-
[
|
|
52
|
+
['not deeply equal', `expected: ${_stringify(expected)}`, `got : ${_stringify(actual)}`]
|
|
53
53
|
.filter(Boolean)
|
|
54
54
|
.join('\n');
|
|
55
55
|
throw new AssertionError(msg, {
|
|
@@ -85,6 +85,7 @@ export function _assertIsNumber(v, message) {
|
|
|
85
85
|
_assertTypeOf(v, 'number', message);
|
|
86
86
|
}
|
|
87
87
|
export function _assertTypeOf(v, expectedType, message) {
|
|
88
|
+
// biome-ignore lint/suspicious/useValidTypeof: ok
|
|
88
89
|
if (typeof v !== expectedType) {
|
|
89
90
|
const msg = message || `Expected typeof ${expectedType}, actual typeof: ${typeof v}`;
|
|
90
91
|
throw new AssertionError(msg);
|
package/dist-esm/http/fetcher.js
CHANGED
|
@@ -34,7 +34,7 @@ const defRetryOptions = {
|
|
|
34
34
|
export class Fetcher {
|
|
35
35
|
constructor(cfg = {}) {
|
|
36
36
|
if (typeof globalThis.fetch !== 'function') {
|
|
37
|
-
throw new TypeError(
|
|
37
|
+
throw new TypeError('globalThis.fetch is not available');
|
|
38
38
|
}
|
|
39
39
|
this.cfg = this.normalizeCfg(cfg);
|
|
40
40
|
// Dynamically create all helper methods
|
|
@@ -281,7 +281,7 @@ export class Fetcher {
|
|
|
281
281
|
res.body = res.fetchResponse.body;
|
|
282
282
|
if (res.body === null) {
|
|
283
283
|
// Error is to be handled upstream
|
|
284
|
-
throw new Error(
|
|
284
|
+
throw new Error('fetchResponse.body is null');
|
|
285
285
|
}
|
|
286
286
|
}
|
|
287
287
|
res.retryStatus.retryStopped = true;
|
|
@@ -410,13 +410,13 @@ export class Fetcher {
|
|
|
410
410
|
}
|
|
411
411
|
else {
|
|
412
412
|
const date = new Date(retryAfterStr);
|
|
413
|
-
if (!isNaN(date)) {
|
|
413
|
+
if (!Number.isNaN(date)) {
|
|
414
414
|
timeout = Number(date) - Date.now();
|
|
415
415
|
}
|
|
416
416
|
}
|
|
417
417
|
this.cfg.logger.log(`retry-after: ${retryAfterStr}`);
|
|
418
418
|
if (!timeout) {
|
|
419
|
-
this.cfg.logger.warn(
|
|
419
|
+
this.cfg.logger.warn('retry-after could not be parsed');
|
|
420
420
|
}
|
|
421
421
|
}
|
|
422
422
|
}
|
|
@@ -570,7 +570,7 @@ export class Fetcher {
|
|
|
570
570
|
const baseUrl = opt.baseUrl || this.cfg.baseUrl;
|
|
571
571
|
if (baseUrl) {
|
|
572
572
|
if (req.fullUrl.startsWith('/')) {
|
|
573
|
-
console.warn(
|
|
573
|
+
console.warn('Fetcher: url should not start with / when baseUrl is specified');
|
|
574
574
|
req.fullUrl = req.fullUrl.slice(1);
|
|
575
575
|
}
|
|
576
576
|
req.fullUrl = `${baseUrl}/${req.inputUrl}`;
|
|
@@ -141,7 +141,7 @@ export class JsonSchemaAnyBuilder {
|
|
|
141
141
|
this.schema.optionalField = true;
|
|
142
142
|
}
|
|
143
143
|
else {
|
|
144
|
-
|
|
144
|
+
this.schema.optionalField = undefined;
|
|
145
145
|
}
|
|
146
146
|
return this;
|
|
147
147
|
}
|
|
@@ -275,7 +275,7 @@ export class JsonSchemaObjectBuilder extends JsonSchemaAnyBuilder {
|
|
|
275
275
|
this.schema.required.push(k);
|
|
276
276
|
}
|
|
277
277
|
else {
|
|
278
|
-
|
|
278
|
+
schema.optionalField = undefined;
|
|
279
279
|
}
|
|
280
280
|
this.schema.properties[k] = schema;
|
|
281
281
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { _assert } from '../error/assert';
|
|
1
2
|
import { _sortNumbers } from '../number/number.util';
|
|
2
3
|
/**
|
|
3
4
|
* @returns Average of the array of numbers
|
|
@@ -8,20 +9,29 @@ import { _sortNumbers } from '../number/number.util';
|
|
|
8
9
|
* // 2.5
|
|
9
10
|
*/
|
|
10
11
|
export function _average(values) {
|
|
11
|
-
|
|
12
|
+
_assert(values.length, '_average is called on empty array');
|
|
13
|
+
let total = 0;
|
|
14
|
+
for (const n of values)
|
|
15
|
+
total += n;
|
|
16
|
+
return total / values.length;
|
|
12
17
|
}
|
|
13
18
|
/**
|
|
14
19
|
* Same as _average, but safely returns null if input array is empty or nullish.
|
|
15
20
|
*/
|
|
16
21
|
export function _averageOrNull(values) {
|
|
17
|
-
return values?.length ? values
|
|
22
|
+
return values?.length ? _average(values) : null;
|
|
18
23
|
}
|
|
19
24
|
/**
|
|
20
25
|
* valuesArray and weightsArray length is expected to be the same.
|
|
21
26
|
*/
|
|
22
27
|
export function _averageWeighted(values, weights) {
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
let numerator = 0;
|
|
29
|
+
let denominator = 0;
|
|
30
|
+
// eslint-disable-next-line unicorn/no-for-loop
|
|
31
|
+
for (let i = 0; i < values.length; i++) {
|
|
32
|
+
numerator += values[i] * weights[i];
|
|
33
|
+
denominator += weights[i];
|
|
34
|
+
}
|
|
25
35
|
return numerator / denominator;
|
|
26
36
|
}
|
|
27
37
|
/**
|
package/dist-esm/math/sma.js
CHANGED
|
@@ -17,7 +17,10 @@ export class SimpleMovingAverage {
|
|
|
17
17
|
get avg() {
|
|
18
18
|
if (this.data.length === 0)
|
|
19
19
|
return 0;
|
|
20
|
-
|
|
20
|
+
let total = 0;
|
|
21
|
+
for (const n of this.data)
|
|
22
|
+
total += n;
|
|
23
|
+
return total / this.data.length;
|
|
21
24
|
}
|
|
22
25
|
/**
|
|
23
26
|
* Push new value.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export function _createDeterministicRandom() {
|
|
8
8
|
let seed = 0x2f6e2b1;
|
|
9
|
-
return
|
|
9
|
+
return () => {
|
|
10
10
|
// Robert Jenkins’ 32 bit integer hash function
|
|
11
11
|
seed = (seed + 0x7ed55d16 + (seed << 12)) & 0xffffffff;
|
|
12
12
|
seed = (seed ^ 0xc761c23c ^ (seed >>> 19)) & 0xffffffff;
|
|
@@ -36,10 +36,10 @@ export function _isBetween(x, min, max, incl = '[)') {
|
|
|
36
36
|
if (incl === '[)') {
|
|
37
37
|
return x >= min && x < max;
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
if (incl === '[]') {
|
|
40
40
|
return x >= min && x <= max;
|
|
41
41
|
}
|
|
42
|
-
|
|
42
|
+
if (incl === '(]') {
|
|
43
43
|
return x > min && x <= max;
|
|
44
44
|
}
|
|
45
45
|
return x > min && x < max;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { _isEmpty, _isObject } from '../is.util';
|
|
2
|
-
import { _objectEntries, SKIP } from '../types';
|
|
2
|
+
import { _objectEntries, SKIP, } from '../types';
|
|
3
3
|
/**
|
|
4
4
|
* Returns clone of `obj` with only `props` preserved.
|
|
5
5
|
* Opposite of Omit.
|
|
@@ -7,28 +7,61 @@ import { _objectEntries, SKIP } from '../types';
|
|
|
7
7
|
export function _pick(obj, props, mutate = false) {
|
|
8
8
|
if (mutate) {
|
|
9
9
|
// Start as original object (mutable), DELETE properties that are not whitelisted
|
|
10
|
-
|
|
11
|
-
if (!props.includes(
|
|
12
|
-
delete
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
for (const k of Object.keys(obj)) {
|
|
11
|
+
if (!props.includes(k))
|
|
12
|
+
delete obj[k];
|
|
13
|
+
}
|
|
14
|
+
return obj;
|
|
15
15
|
}
|
|
16
16
|
// Start as empty object, pick/add needed properties
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
17
|
+
const r = {};
|
|
18
|
+
for (const k of props) {
|
|
19
|
+
if (k in obj)
|
|
20
|
+
r[k] = obj[k];
|
|
21
|
+
}
|
|
22
|
+
return r;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Sets all properties of an object except passed ones to `undefined`.
|
|
26
|
+
* This is a more performant alternative to `_pick` that does picking/deleting.
|
|
27
|
+
*/
|
|
28
|
+
export function _pickWithUndefined(obj, props, mutate = false) {
|
|
29
|
+
const r = mutate ? obj : { ...obj };
|
|
30
|
+
for (const k of Object.keys(r)) {
|
|
31
|
+
if (!props.includes(k)) {
|
|
32
|
+
r[k] = undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return r;
|
|
22
36
|
}
|
|
23
37
|
/**
|
|
24
38
|
* Returns clone of `obj` with `props` omitted.
|
|
25
39
|
* Opposite of Pick.
|
|
26
40
|
*/
|
|
27
41
|
export function _omit(obj, props, mutate = false) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
42
|
+
if (mutate) {
|
|
43
|
+
for (const k of props) {
|
|
44
|
+
delete obj[k];
|
|
45
|
+
}
|
|
46
|
+
return obj;
|
|
47
|
+
}
|
|
48
|
+
const r = {};
|
|
49
|
+
for (const k of Object.keys(obj)) {
|
|
50
|
+
if (!props.includes(k))
|
|
51
|
+
r[k] = obj[k];
|
|
52
|
+
}
|
|
53
|
+
return r;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Sets all passed properties of an object to `undefined`.
|
|
57
|
+
* This is a more performant alternative to `_omit` that does picking/deleting.
|
|
58
|
+
*/
|
|
59
|
+
export function _omitWithUndefined(obj, props, mutate = false) {
|
|
60
|
+
const r = mutate ? obj : { ...obj };
|
|
61
|
+
for (const k of props) {
|
|
62
|
+
r[k] = undefined;
|
|
63
|
+
}
|
|
64
|
+
return r;
|
|
32
65
|
}
|
|
33
66
|
/**
|
|
34
67
|
* Returns object with filtered keys from `props` array.
|
|
@@ -39,10 +72,11 @@ export function _omit(obj, props, mutate = false) {
|
|
|
39
72
|
* ])
|
|
40
73
|
*/
|
|
41
74
|
export function _mask(obj, props, mutate = false) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
75
|
+
const r = mutate ? obj : _deepCopy(obj);
|
|
76
|
+
for (const k of props) {
|
|
77
|
+
_unset(r, k);
|
|
78
|
+
}
|
|
79
|
+
return r;
|
|
46
80
|
}
|
|
47
81
|
/**
|
|
48
82
|
* Removes "falsy" values from the object.
|
|
@@ -71,11 +105,21 @@ export function _filterEmptyArrays(obj, mutate = false) {
|
|
|
71
105
|
* Allows filtering by both key and value.
|
|
72
106
|
*/
|
|
73
107
|
export function _filterObject(obj, predicate, mutate = false) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
108
|
+
if (mutate) {
|
|
109
|
+
for (const [k, v] of _objectEntries(obj)) {
|
|
110
|
+
if (!predicate(k, v, obj)) {
|
|
111
|
+
delete obj[k];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return obj;
|
|
115
|
+
}
|
|
116
|
+
const r = {};
|
|
117
|
+
for (const [k, v] of _objectEntries(obj)) {
|
|
118
|
+
if (predicate(k, v, obj)) {
|
|
119
|
+
r[k] = v;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return r;
|
|
79
123
|
}
|
|
80
124
|
/**
|
|
81
125
|
* var users = {
|
|
@@ -89,10 +133,11 @@ export function _filterObject(obj, predicate, mutate = false) {
|
|
|
89
133
|
* To skip some key-value pairs - use _mapObject instead.
|
|
90
134
|
*/
|
|
91
135
|
export function _mapValues(obj, mapper, mutate = false) {
|
|
92
|
-
|
|
136
|
+
const map = mutate ? obj : {};
|
|
137
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
93
138
|
map[k] = mapper(k, v, obj);
|
|
94
|
-
|
|
95
|
-
|
|
139
|
+
}
|
|
140
|
+
return map;
|
|
96
141
|
}
|
|
97
142
|
/**
|
|
98
143
|
* _.mapKeys({ 'a': 1, 'b': 2 }, (key, value) => key + value)
|
|
@@ -103,10 +148,11 @@ export function _mapValues(obj, mapper, mutate = false) {
|
|
|
103
148
|
* To skip some key-value pairs - use _mapObject instead.
|
|
104
149
|
*/
|
|
105
150
|
export function _mapKeys(obj, mapper) {
|
|
106
|
-
|
|
151
|
+
const map = {};
|
|
152
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
107
153
|
map[mapper(k, v, obj)] = v;
|
|
108
|
-
|
|
109
|
-
|
|
154
|
+
}
|
|
155
|
+
return map;
|
|
110
156
|
}
|
|
111
157
|
/**
|
|
112
158
|
* Maps object through predicate - a function that receives (k, v, obj)
|
|
@@ -125,13 +171,14 @@ export function _mapKeys(obj, mapper) {
|
|
|
125
171
|
* Non-string keys are passed via String(...)
|
|
126
172
|
*/
|
|
127
173
|
export function _mapObject(obj, mapper) {
|
|
128
|
-
|
|
174
|
+
const map = {};
|
|
175
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
129
176
|
const r = mapper(k, v, obj);
|
|
130
|
-
if (r
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
177
|
+
if (r === SKIP)
|
|
178
|
+
continue;
|
|
179
|
+
map[r[0]] = r[1];
|
|
180
|
+
}
|
|
181
|
+
return map;
|
|
135
182
|
}
|
|
136
183
|
export function _findKeyByValue(obj, v) {
|
|
137
184
|
return Object.entries(obj).find(([_, value]) => value === v)?.[0];
|
|
@@ -219,7 +266,7 @@ export function _deepTrim(o) {
|
|
|
219
266
|
if (typeof o === 'string') {
|
|
220
267
|
return o.trim();
|
|
221
268
|
}
|
|
222
|
-
|
|
269
|
+
if (typeof o === 'object') {
|
|
223
270
|
Object.keys(o).forEach(k => {
|
|
224
271
|
o[k] = _deepTrim(o[k]);
|
|
225
272
|
});
|
|
@@ -273,10 +320,11 @@ export function _invertMap(m) {
|
|
|
273
320
|
* _get(obj, 'unknown.path') // undefined
|
|
274
321
|
*/
|
|
275
322
|
export function _get(obj = {}, path = '') {
|
|
276
|
-
return path
|
|
323
|
+
return (path
|
|
277
324
|
.replaceAll(/\[([^\]]+)]/g, '.$1')
|
|
278
325
|
.split('.')
|
|
279
|
-
|
|
326
|
+
// eslint-disable-next-line unicorn/no-array-reduce
|
|
327
|
+
.reduce((o, p) => o?.[p], obj));
|
|
280
328
|
}
|
|
281
329
|
/**
|
|
282
330
|
* Sets the value at path of object. If a portion of path doesn’t exist it’s created. Arrays are created for
|
|
@@ -299,6 +347,7 @@ export function _set(obj, path, value) {
|
|
|
299
347
|
else if (!path.length) {
|
|
300
348
|
return obj;
|
|
301
349
|
}
|
|
350
|
+
// eslint-disable-next-line unicorn/no-array-reduce
|
|
302
351
|
;
|
|
303
352
|
path.slice(0, -1).reduce((a, c, i) => Object(a[c]) === a[c] // Does the key exist and is its value an object?
|
|
304
353
|
? // Yes: then follow that path
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { _omit } from '../index';
|
|
2
1
|
/**
|
|
3
2
|
* Returns new object with keys sorder in the given order.
|
|
4
3
|
* All keys that are not listed in `keyOrder` go last.
|
|
@@ -6,13 +5,17 @@ import { _omit } from '../index';
|
|
|
6
5
|
*/
|
|
7
6
|
export function _sortObject(obj, keyOrder) {
|
|
8
7
|
const r = {};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
// First, go over ordered keys
|
|
9
|
+
for (const k of keyOrder) {
|
|
10
|
+
if (k in obj) {
|
|
11
|
+
r[k] = obj[k];
|
|
12
12
|
}
|
|
13
|
-
}
|
|
14
|
-
|
|
13
|
+
}
|
|
14
|
+
// Second, go over all other keys
|
|
15
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
16
|
+
if (keyOrder.includes(k))
|
|
17
|
+
continue;
|
|
15
18
|
r[k] = v;
|
|
16
|
-
}
|
|
19
|
+
}
|
|
17
20
|
return r;
|
|
18
21
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { _isObject } from '..';
|
|
2
1
|
/**
|
|
3
2
|
* based on: https://github.com/IndigoUnited/js-deep-sort-object
|
|
4
3
|
*/
|
|
@@ -7,14 +6,12 @@ export function _sortObjectDeep(o) {
|
|
|
7
6
|
if (Array.isArray(o)) {
|
|
8
7
|
return o.map(_sortObjectDeep);
|
|
9
8
|
}
|
|
10
|
-
if (
|
|
11
|
-
const
|
|
12
|
-
Object.keys(o)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
});
|
|
17
|
-
return out;
|
|
9
|
+
if (o && typeof o === 'object') {
|
|
10
|
+
const r = {};
|
|
11
|
+
for (const k of Object.keys(o).sort((a, b) => a.localeCompare(b))) {
|
|
12
|
+
r[k] = _sortObjectDeep(o[k]);
|
|
13
|
+
}
|
|
14
|
+
return r;
|
|
18
15
|
}
|
|
19
16
|
return o;
|
|
20
17
|
}
|
|
@@ -18,7 +18,7 @@ export async function pDelay(ms = 0, value) {
|
|
|
18
18
|
*
|
|
19
19
|
* On abort() - clears the Timeout and immediately resolves the Promise with void.
|
|
20
20
|
*/
|
|
21
|
-
export function pDelayFn(ms
|
|
21
|
+
export function pDelayFn(ms, fn) {
|
|
22
22
|
const p = pDefer();
|
|
23
23
|
const timer = setTimeout(async () => {
|
|
24
24
|
try {
|
package/dist-esm/semver.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { _range } from './array/range';
|
|
2
2
|
import { _assert } from './error/assert';
|
|
3
|
-
import { _isTruthy } from './is.util';
|
|
4
3
|
/**
|
|
5
4
|
* Simple Semver implementation.
|
|
6
5
|
*
|
|
@@ -75,35 +74,45 @@ class SemverFactory {
|
|
|
75
74
|
* Returns the highest (max) Semver from the array, or undefined if the array is empty.
|
|
76
75
|
*/
|
|
77
76
|
maxOrUndefined(items) {
|
|
78
|
-
|
|
77
|
+
let max;
|
|
78
|
+
for (const item of items) {
|
|
79
|
+
const input = this.fromInputOrUndefined(item);
|
|
80
|
+
if (!max || input?.isAfter(max)) {
|
|
81
|
+
max = input;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return max;
|
|
79
85
|
}
|
|
80
86
|
/**
|
|
81
87
|
* Returns the highest Semver from the array.
|
|
82
88
|
* Throws if the array is empty.
|
|
83
89
|
*/
|
|
84
90
|
max(items) {
|
|
85
|
-
const
|
|
86
|
-
_assert(
|
|
87
|
-
return
|
|
88
|
-
.map(i => this.fromInput(i))
|
|
89
|
-
.reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
|
|
91
|
+
const max = this.maxOrUndefined(items);
|
|
92
|
+
_assert(max, 'semver.max called on empty array');
|
|
93
|
+
return max;
|
|
90
94
|
}
|
|
91
95
|
/**
|
|
92
96
|
* Returns the lowest (min) Semver from the array, or undefined if the array is empty.
|
|
93
97
|
*/
|
|
94
98
|
minOrUndefined(items) {
|
|
95
|
-
|
|
99
|
+
let min;
|
|
100
|
+
for (const item of items) {
|
|
101
|
+
const input = this.fromInputOrUndefined(item);
|
|
102
|
+
if (!min || input?.isBefore(min)) {
|
|
103
|
+
min = input;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return min;
|
|
96
107
|
}
|
|
97
108
|
/**
|
|
98
109
|
* Returns the lowest Semver from the array.
|
|
99
110
|
* Throws if the array is empty.
|
|
100
111
|
*/
|
|
101
112
|
min(items) {
|
|
102
|
-
const
|
|
103
|
-
_assert(
|
|
104
|
-
return
|
|
105
|
-
.map(i => this.fromInput(i))
|
|
106
|
-
.reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
|
|
113
|
+
const min = this.minOrUndefined(items);
|
|
114
|
+
_assert(min, 'semver.min called on empty array');
|
|
115
|
+
return min;
|
|
107
116
|
}
|
|
108
117
|
/**
|
|
109
118
|
* Sorts an array of Semvers in `dir` order (ascending by default).
|
package/dist-esm/string/case.js
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import { words } from './lodash/words';
|
|
2
2
|
import { _upperFirst } from './string.util';
|
|
3
3
|
export function _camelCase(s) {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
let r = '';
|
|
5
|
+
for (let word of words(s.replaceAll(/['\u2019]/g, ''))) {
|
|
6
6
|
word = word.toLowerCase();
|
|
7
|
-
|
|
8
|
-
}
|
|
7
|
+
r += r ? _upperFirst(word) : word;
|
|
8
|
+
}
|
|
9
|
+
return r;
|
|
9
10
|
}
|
|
10
11
|
export function _snakeCase(s) {
|
|
11
|
-
|
|
12
|
+
let r = '';
|
|
13
|
+
for (const word of words(s.replaceAll(/['\u2019]/g, ''))) {
|
|
14
|
+
r += (r ? '_' : '') + word.toLowerCase();
|
|
15
|
+
}
|
|
16
|
+
return r;
|
|
12
17
|
}
|
|
13
18
|
export function _kebabCase(s) {
|
|
14
|
-
|
|
19
|
+
let r = '';
|
|
20
|
+
for (const word of words(s.replaceAll(/['\u2019]/g, ''))) {
|
|
21
|
+
r += (r ? '-' : '') + word.toLowerCase();
|
|
22
|
+
}
|
|
23
|
+
return r;
|
|
15
24
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { unicodeWords } from './unicodeWords';
|
|
4
4
|
const hasUnicodeWord = RegExp.prototype.test.bind(/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/);
|
|
5
5
|
/** Used to match words composed of alphanumeric characters. */
|
|
6
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: ok
|
|
6
7
|
const reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
|
|
7
8
|
function asciiWords(s) {
|
|
8
9
|
return s.match(reAsciiWord);
|
|
@@ -17,7 +17,7 @@ export function _safeJsonStringify(obj, replacer, spaces, cycleReplacer) {
|
|
|
17
17
|
function serializer(replacer, cycleReplacer) {
|
|
18
18
|
const stack = [];
|
|
19
19
|
const keys = [];
|
|
20
|
-
cycleReplacer ?? (cycleReplacer =
|
|
20
|
+
cycleReplacer ?? (cycleReplacer = (key, value) => {
|
|
21
21
|
if (stack[0] === value)
|
|
22
22
|
return '[Circular ~]';
|
|
23
23
|
return '[Circular ~.' + keys.slice(0, stack.indexOf(value)).join('.') + ']';
|