@naturalcycles/js-lib 15.96.0 → 15.98.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/abort.d.ts +3 -3
- package/dist/abort.js +1 -1
- package/dist/analytics/analytics.model.d.ts +1 -1
- package/dist/array/array.util.d.ts +4 -4
- package/dist/browser/i18n/translation.service.d.ts +1 -1
- package/dist/datetime/localDate.d.ts +4 -4
- package/dist/datetime/localTime.d.ts +4 -4
- package/dist/decorators/decorator.util.d.ts +1 -1
- package/dist/decorators/timeout.decorator.js +5 -2
- package/dist/error/assert.d.ts +7 -1
- package/dist/error/assert.js +5 -0
- package/dist/error/error.model.d.ts +1 -1
- package/dist/http/fetcher.js +5 -4
- package/dist/http/http.model.d.ts +1 -1
- package/dist/log/commonLogger.d.ts +1 -1
- package/dist/math/math.util.d.ts +8 -8
- package/dist/math/math.util.js +2 -2
- package/dist/math/stack.util.d.ts +8 -3
- package/dist/math/stack.util.js +13 -6
- package/dist/number/number.util.d.ts +1 -1
- package/dist/object/keySortedMap.d.ts +1 -1
- package/dist/object/lazyKeySortedMap.d.ts +1 -1
- package/dist/object/object.util.d.ts +1 -1
- package/dist/object/sortObject.d.ts +1 -1
- package/dist/promise/pTimeout.js +1 -1
- package/dist/semver.d.ts +4 -4
- package/dist/string/pupa.d.ts +1 -1
- package/package.json +1 -1
- package/src/abort.ts +4 -4
- package/src/analytics/analytics.model.ts +1 -1
- package/src/array/array.util.ts +4 -4
- package/src/browser/i18n/translation.service.ts +1 -1
- package/src/browser/imageFitter.ts +1 -1
- package/src/datetime/localDate.ts +4 -4
- package/src/datetime/localTime.ts +4 -4
- package/src/decorators/decorator.util.ts +1 -1
- package/src/decorators/timeout.decorator.ts +5 -2
- package/src/error/assert.ts +19 -1
- package/src/error/error.model.ts +1 -1
- package/src/http/fetcher.ts +6 -5
- package/src/http/http.model.ts +1 -1
- package/src/log/commonLogger.ts +1 -1
- package/src/math/math.util.ts +13 -10
- package/src/math/stack.util.ts +16 -8
- package/src/number/number.util.ts +1 -1
- package/src/object/keySortedMap.ts +1 -1
- package/src/object/lazyKeySortedMap.ts +1 -1
- package/src/object/object.util.ts +5 -1
- package/src/object/sortObject.ts +1 -1
- package/src/promise/pMap.ts +2 -2
- package/src/promise/pTimeout.ts +1 -1
- package/src/semver.ts +4 -4
- package/src/string/pupa.ts +5 -1
- package/src/string/readingTime.ts +1 -1
- package/src/ua/ua.ts +1 -1
package/dist/abort.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export declare function polyfilledAbortSignalTimeout(ms: NumberOfMilliseconds):
|
|
|
40
40
|
* Returns AbortSignal.any(signals) is the array (after filtering undefined inputs) is not empty,
|
|
41
41
|
* otherwise undefined.
|
|
42
42
|
*/
|
|
43
|
-
export declare function abortSignalAnyOrUndefined(signals: (AbortSignal | undefined)[]): AbortSignal | undefined;
|
|
43
|
+
export declare function abortSignalAnyOrUndefined(signals: readonly (AbortSignal | undefined)[]): AbortSignal | undefined;
|
|
44
44
|
/**
|
|
45
45
|
* Returns an AbortSignal that aborts when any of the given signals abort.
|
|
46
46
|
* Uses native `AbortSignal.any()` when available, falls back to a polyfill.
|
|
@@ -50,5 +50,5 @@ export declare function abortSignalAnyOrUndefined(signals: (AbortSignal | undefi
|
|
|
50
50
|
*
|
|
51
51
|
* If only 1 signal is passed in the input array - that Signal is returned as-is.
|
|
52
52
|
*/
|
|
53
|
-
export declare function abortSignalAny(signals: AbortSignal[]): AbortSignal;
|
|
54
|
-
export declare function polyfilledAbortSignalAny(signals: AbortSignal[]): AbortSignal;
|
|
53
|
+
export declare function abortSignalAny(signals: readonly AbortSignal[]): AbortSignal;
|
|
54
|
+
export declare function polyfilledAbortSignalAny(signals: readonly AbortSignal[]): AbortSignal;
|
package/dist/abort.js
CHANGED
|
@@ -58,7 +58,7 @@ export function abortSignalAny(signals) {
|
|
|
58
58
|
return signals[0];
|
|
59
59
|
}
|
|
60
60
|
return typeof AbortSignal.any === 'function'
|
|
61
|
-
? AbortSignal.any(signals)
|
|
61
|
+
? AbortSignal.any(signals) // lib.dom types require a mutable array, but it is only read
|
|
62
62
|
: polyfilledAbortSignalAny(signals);
|
|
63
63
|
}
|
|
64
64
|
export function polyfilledAbortSignalAny(signals) {
|
|
@@ -60,7 +60,7 @@ export interface AnalyticsClientEvent {
|
|
|
60
60
|
userId?: AnalyticsDistinctId;
|
|
61
61
|
}
|
|
62
62
|
/** Canonical utm parameters. */
|
|
63
|
-
export declare const CANONICAL_UTM_PARAMS: string[];
|
|
63
|
+
export declare const CANONICAL_UTM_PARAMS: readonly string[];
|
|
64
64
|
/** Keyed by `initial_<canonical utm param>`, to avoid permanently saving non-standard ones. */
|
|
65
65
|
export type FirstTouchUtms = StringMap<string | null>;
|
|
66
66
|
/**
|
|
@@ -138,7 +138,7 @@ export declare function _countBy<T>(items: Iterable<T>, mapper: Mapper<T, any>):
|
|
|
138
138
|
* _intersection([2, 1], [2, 3])
|
|
139
139
|
* // [2]
|
|
140
140
|
*/
|
|
141
|
-
export declare function _intersection<T>(a1: T[], a2: T[] | Set<T>): T[];
|
|
141
|
+
export declare function _intersection<T>(a1: readonly T[], a2: readonly T[] | Set<T>): T[];
|
|
142
142
|
/**
|
|
143
143
|
* Returns true if there is at least 1 item common between 2 arrays.
|
|
144
144
|
* Otherwise returns false.
|
|
@@ -147,7 +147,7 @@ export declare function _intersection<T>(a1: T[], a2: T[] | Set<T>): T[];
|
|
|
147
147
|
*
|
|
148
148
|
* Passing second array as Set is more performant (it'll skip turning the array into Set in-place).
|
|
149
149
|
*/
|
|
150
|
-
export declare function _intersectsWith<T>(a1: T[], a2: T[] | Set<T>): boolean;
|
|
150
|
+
export declare function _intersectsWith<T>(a1: readonly T[], a2: readonly T[] | Set<T>): boolean;
|
|
151
151
|
/**
|
|
152
152
|
* Returns array1 minus array2.
|
|
153
153
|
*
|
|
@@ -157,11 +157,11 @@ export declare function _intersectsWith<T>(a1: T[], a2: T[] | Set<T>): boolean;
|
|
|
157
157
|
*
|
|
158
158
|
* Passing second array as Set is more performant (it'll skip turning the array into Set in-place).
|
|
159
159
|
*/
|
|
160
|
-
export declare function _difference<T>(a1: T[], a2: T[] | Set<T>): T[];
|
|
160
|
+
export declare function _difference<T>(a1: readonly T[], a2: readonly T[] | Set<T>): T[];
|
|
161
161
|
/**
|
|
162
162
|
* Does NOT mutate the array, returns a filtered array instead.
|
|
163
163
|
*/
|
|
164
|
-
export declare function _arrayRemove<T>(a: T[], itemToRemove: T): T[];
|
|
164
|
+
export declare function _arrayRemove<T>(a: readonly T[], itemToRemove: T): T[];
|
|
165
165
|
/**
|
|
166
166
|
* "Toggles" an item to be present or absent in the array,
|
|
167
167
|
* based on the predicate. Respects uniqueness.
|
|
@@ -37,7 +37,7 @@ export declare class TranslationService {
|
|
|
37
37
|
* Loads locale(s) (if not already cached) via configured TranslationLoader.
|
|
38
38
|
* Resolves promise when done (ready to be used).
|
|
39
39
|
*/
|
|
40
|
-
loadLocale(locale: string | string[]): Promise<void>;
|
|
40
|
+
loadLocale(locale: string | readonly string[]): Promise<void>;
|
|
41
41
|
/**
|
|
42
42
|
* Will invoke `missingTranslationHandler` on missing tranlation.
|
|
43
43
|
*
|
|
@@ -250,21 +250,21 @@ declare class LocalDateFactory {
|
|
|
250
250
|
/**
|
|
251
251
|
* Returns the earliest (min) LocalDate from the array, or undefined if the array is empty.
|
|
252
252
|
*/
|
|
253
|
-
minOrUndefined(items: LocalDateInputNullable[]): LocalDate | undefined;
|
|
253
|
+
minOrUndefined(items: readonly LocalDateInputNullable[]): LocalDate | undefined;
|
|
254
254
|
/**
|
|
255
255
|
* Returns the earliest LocalDate from the array.
|
|
256
256
|
* Throws if the array is empty.
|
|
257
257
|
*/
|
|
258
|
-
min(items: LocalDateInputNullable[]): LocalDate;
|
|
258
|
+
min(items: readonly LocalDateInputNullable[]): LocalDate;
|
|
259
259
|
/**
|
|
260
260
|
* Returns the latest (max) LocalDate from the array, or undefined if the array is empty.
|
|
261
261
|
*/
|
|
262
|
-
maxOrUndefined(items: LocalDateInputNullable[]): LocalDate | undefined;
|
|
262
|
+
maxOrUndefined(items: readonly LocalDateInputNullable[]): LocalDate | undefined;
|
|
263
263
|
/**
|
|
264
264
|
* Returns the latest LocalDate from the array.
|
|
265
265
|
* Throws if the array is empty.
|
|
266
266
|
*/
|
|
267
|
-
max(items: LocalDateInputNullable[]): LocalDate;
|
|
267
|
+
max(items: readonly LocalDateInputNullable[]): LocalDate;
|
|
268
268
|
/**
|
|
269
269
|
* Returns the range (array) of LocalDates between min and max.
|
|
270
270
|
* By default, min is included, max is excluded.
|
|
@@ -322,10 +322,10 @@ declare class LocalTimeFactory {
|
|
|
322
322
|
*/
|
|
323
323
|
isTimezoneValid(tz: string): boolean;
|
|
324
324
|
sort(items: LocalTime[], dir?: SortDirection, opt?: MutateOptions): LocalTime[];
|
|
325
|
-
minOrUndefined(items: LocalTimeInputNullable[]): LocalTime | undefined;
|
|
326
|
-
min(items: LocalTimeInputNullable[]): LocalTime;
|
|
327
|
-
maxOrUndefined(items: LocalTimeInputNullable[]): LocalTime | undefined;
|
|
328
|
-
max(items: LocalTimeInputNullable[]): LocalTime;
|
|
325
|
+
minOrUndefined(items: readonly LocalTimeInputNullable[]): LocalTime | undefined;
|
|
326
|
+
min(items: readonly LocalTimeInputNullable[]): LocalTime;
|
|
327
|
+
maxOrUndefined(items: readonly LocalTimeInputNullable[]): LocalTime | undefined;
|
|
328
|
+
max(items: readonly LocalTimeInputNullable[]): LocalTime;
|
|
329
329
|
}
|
|
330
330
|
interface LocalTimeFn extends LocalTimeFactory {
|
|
331
331
|
(d: LocalTimeInput): LocalTime;
|
|
@@ -21,4 +21,4 @@ export declare function _getTargetMethodSignature(target: AnyObject, keyStr: str
|
|
|
21
21
|
* returns:
|
|
22
22
|
* a, b, c
|
|
23
23
|
*/
|
|
24
|
-
export declare function _getArgsSignature(args?: any[], logArgs?: boolean): string;
|
|
24
|
+
export declare function _getArgsSignature(args?: readonly any[], logArgs?: boolean): string;
|
|
@@ -10,8 +10,11 @@ export function _Timeout(opt) {
|
|
|
10
10
|
const keyStr = String(key);
|
|
11
11
|
descriptor.value = async function (...args) {
|
|
12
12
|
const ctx = this;
|
|
13
|
-
|
|
14
|
-
return await pTimeout(() => originalFn.apply(this, args),
|
|
13
|
+
// Not mutating the shared decorator options, as the name depends on the instance (ctx)
|
|
14
|
+
return await pTimeout(() => originalFn.apply(this, args), {
|
|
15
|
+
...opt,
|
|
16
|
+
name: opt.name || _getMethodSignature(ctx, keyStr),
|
|
17
|
+
});
|
|
15
18
|
};
|
|
16
19
|
return descriptor;
|
|
17
20
|
};
|
package/dist/error/assert.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Class, UnixTimestamp } from '../types.js';
|
|
1
|
+
import type { Class, NonEmptyArray, UnixTimestamp } from '../types.js';
|
|
2
2
|
import type { BackendErrorResponseObject, ErrorData, ErrorObject } from './error.model.js';
|
|
3
3
|
/**
|
|
4
4
|
* Evaluates the `condition` (casts it to Boolean).
|
|
@@ -43,6 +43,12 @@ export declare function _assertIsErrorObject<DATA_TYPE extends ErrorData = Error
|
|
|
43
43
|
export declare function _assertIsBackendErrorResponseObject<DATA_TYPE extends ErrorData = ErrorData>(obj: any): asserts obj is BackendErrorResponseObject<DATA_TYPE>;
|
|
44
44
|
export declare function _assertIsString(v: any, message?: string): asserts v is string;
|
|
45
45
|
export declare function _assertIsNumber(v: any, message?: string): asserts v is number;
|
|
46
|
+
/**
|
|
47
|
+
* Asserts that the array has at least one element, narrowing it to NonEmptyArray.
|
|
48
|
+
* Readonly arrays are narrowed to `Readonly<NonEmptyArray<T>>`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function _assertIsNonEmptyArray<T>(arr: T[], message?: string): asserts arr is NonEmptyArray<T>;
|
|
51
|
+
export declare function _assertIsNonEmptyArray<T>(arr: readonly T[], message?: string): asserts arr is Readonly<NonEmptyArray<T>>;
|
|
46
52
|
export declare function _assertTypeOf<T>(v: any, expectedType: string, message?: string): asserts v is T;
|
|
47
53
|
/**
|
|
48
54
|
* Casts an arbitrary number as UnixTimestamp.
|
package/dist/error/assert.js
CHANGED
|
@@ -91,6 +91,11 @@ export function _assertIsString(v, message) {
|
|
|
91
91
|
export function _assertIsNumber(v, message) {
|
|
92
92
|
_assertTypeOf(v, 'number', message);
|
|
93
93
|
}
|
|
94
|
+
export function _assertIsNonEmptyArray(arr, message) {
|
|
95
|
+
if (!arr.length) {
|
|
96
|
+
throw new AssertionError(message || 'Expected non-empty array');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
94
99
|
export function _assertTypeOf(v, expectedType, message) {
|
|
95
100
|
if (typeof v !== expectedType) {
|
|
96
101
|
const msg = message || `Expected typeof ${expectedType}, actual typeof: ${typeof v}`;
|
package/dist/http/fetcher.js
CHANGED
|
@@ -706,10 +706,6 @@ export class Fetcher {
|
|
|
706
706
|
}
|
|
707
707
|
normalizeCfg(cfg) {
|
|
708
708
|
const { debug = false, logger = consoleLogger } = cfg;
|
|
709
|
-
if (cfg.baseUrl?.endsWith('/')) {
|
|
710
|
-
logger.warn(`Fetcher: baseUrl should not end with slash: ${cfg.baseUrl}`);
|
|
711
|
-
cfg.baseUrl = cfg.baseUrl.slice(0, cfg.baseUrl.length - 1);
|
|
712
|
-
}
|
|
713
709
|
const norm = _merge({
|
|
714
710
|
baseUrl: '',
|
|
715
711
|
name: this.getFetcherName(cfg),
|
|
@@ -746,6 +742,11 @@ export class Fetcher {
|
|
|
746
742
|
errorData: {},
|
|
747
743
|
}, _omit(cfg, ['method', 'credentials', 'headers', 'redirect', 'logger', 'name', 'keepalive']));
|
|
748
744
|
norm.init.headers = _mapKeys(norm.init.headers, k => k.toLowerCase());
|
|
745
|
+
// Normalizing `norm`, not the input `cfg`, to not mutate the input
|
|
746
|
+
if (norm.baseUrl.endsWith('/')) {
|
|
747
|
+
logger.warn(`Fetcher: baseUrl should not end with slash: ${norm.baseUrl}`);
|
|
748
|
+
norm.baseUrl = norm.baseUrl.slice(0, -1);
|
|
749
|
+
}
|
|
749
750
|
return norm;
|
|
750
751
|
}
|
|
751
752
|
getFetcherName(cfg) {
|
|
@@ -4,4 +4,4 @@ export type HttpStatusFamily = 5 | 4 | 3 | 2 | 1;
|
|
|
4
4
|
* Number, representing a valid Http status code (e.g 401, 500, etc)
|
|
5
5
|
*/
|
|
6
6
|
export type HttpStatusCode = number;
|
|
7
|
-
export declare const HTTP_METHODS: HttpMethod[];
|
|
7
|
+
export declare const HTTP_METHODS: readonly HttpMethod[];
|
|
@@ -74,4 +74,4 @@ export declare function createCommonLoggerAtLevel(logger?: CommonLogger, minLeve
|
|
|
74
74
|
/**
|
|
75
75
|
* Creates a "proxy" CommonLogger that pipes log entries to all provided sub-loggers.
|
|
76
76
|
*/
|
|
77
|
-
export declare function commonLoggerPipe(loggers: CommonLogger[]): CommonLogger;
|
|
77
|
+
export declare function commonLoggerPipe(loggers: readonly CommonLogger[]): CommonLogger;
|
package/dist/math/math.util.d.ts
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
* _average([1, 2, 3, 4])
|
|
7
7
|
* // 2.5
|
|
8
8
|
*/
|
|
9
|
-
export declare function _average(values: number[]): number;
|
|
9
|
+
export declare function _average(values: readonly number[]): number;
|
|
10
10
|
/**
|
|
11
11
|
* Same as _average, but safely returns null if input array is empty or nullish.
|
|
12
12
|
*/
|
|
13
|
-
export declare function _averageOrNull(values: number[] | undefined | null): number | null;
|
|
13
|
+
export declare function _averageOrNull(values: readonly number[] | undefined | null): number | null;
|
|
14
14
|
/**
|
|
15
15
|
* @returns Population standard deviation of the array of numbers
|
|
16
16
|
*
|
|
@@ -19,15 +19,15 @@ export declare function _averageOrNull(values: number[] | undefined | null): num
|
|
|
19
19
|
* _stdDev([2, 4, 4, 4, 5, 5, 7, 9])
|
|
20
20
|
* // 2
|
|
21
21
|
*/
|
|
22
|
-
export declare function _stdDev(values: number[]): number;
|
|
22
|
+
export declare function _stdDev(values: readonly number[]): number;
|
|
23
23
|
/**
|
|
24
24
|
* Same as _stdDev, but safely returns null if input array is empty or nullish.
|
|
25
25
|
*/
|
|
26
|
-
export declare function _stdDevOrNull(values: number[] | undefined | null): number | null;
|
|
26
|
+
export declare function _stdDevOrNull(values: readonly number[] | undefined | null): number | null;
|
|
27
27
|
/**
|
|
28
28
|
* valuesArray and weightsArray length is expected to be the same.
|
|
29
29
|
*/
|
|
30
|
-
export declare function _averageWeighted(values: number[], weights: number[]): number;
|
|
30
|
+
export declare function _averageWeighted(values: readonly number[], weights: readonly number[]): number;
|
|
31
31
|
/**
|
|
32
32
|
* @example
|
|
33
33
|
*
|
|
@@ -40,11 +40,11 @@ export declare function _averageWeighted(values: number[], weights: number[]): n
|
|
|
40
40
|
* _percentile([1, 2, 3], 100)
|
|
41
41
|
* // 3
|
|
42
42
|
*/
|
|
43
|
-
export declare function _percentile(values: number[], pc: number): number;
|
|
43
|
+
export declare function _percentile(values: readonly number[], pc: number): number;
|
|
44
44
|
/**
|
|
45
45
|
* A tiny bit more efficient function than calling _percentile individually.
|
|
46
46
|
*/
|
|
47
|
-
export declare function _percentiles(values: number[], pcs: number[]): Record<number, number>;
|
|
47
|
+
export declare function _percentiles(values: readonly number[], pcs: readonly number[]): Record<number, number>;
|
|
48
48
|
/**
|
|
49
49
|
* @example
|
|
50
50
|
*
|
|
@@ -54,4 +54,4 @@ export declare function _percentiles(values: number[], pcs: number[]): Record<nu
|
|
|
54
54
|
* _median([1, 2, 3, 4])
|
|
55
55
|
* // 2.5
|
|
56
56
|
*/
|
|
57
|
-
export declare function _median(values: number[]): number;
|
|
57
|
+
export declare function _median(values: readonly number[]): number;
|
package/dist/math/math.util.js
CHANGED
|
@@ -70,7 +70,7 @@ export function _averageWeighted(values, weights) {
|
|
|
70
70
|
* // 3
|
|
71
71
|
*/
|
|
72
72
|
export function _percentile(values, pc) {
|
|
73
|
-
const sorted = values.
|
|
73
|
+
const sorted = values.toSorted(comparators.numericAsc);
|
|
74
74
|
// Floating pos in the range of [0; length - 1]
|
|
75
75
|
const pos = ((values.length - 1) * pc) / 100;
|
|
76
76
|
const dec = pos % 1;
|
|
@@ -83,7 +83,7 @@ export function _percentile(values, pc) {
|
|
|
83
83
|
*/
|
|
84
84
|
export function _percentiles(values, pcs) {
|
|
85
85
|
const r = {};
|
|
86
|
-
const sorted = values.
|
|
86
|
+
const sorted = values.toSorted(comparators.numericAsc);
|
|
87
87
|
for (const pc of pcs) {
|
|
88
88
|
// Floating pos in the range of [0; length - 1]
|
|
89
89
|
const pos = ((values.length - 1) * pc) / 100;
|
|
@@ -13,7 +13,12 @@ export declare class Stack<T> {
|
|
|
13
13
|
* Currently this slot contains OLDEST item (if any).
|
|
14
14
|
*/
|
|
15
15
|
private nextIndex;
|
|
16
|
-
readonly
|
|
16
|
+
private readonly buffer;
|
|
17
|
+
/**
|
|
18
|
+
* Raw "items buffer" as-is (not ordered properly).
|
|
19
|
+
* Readonly, because mutating it (e.g sorting in-place) would corrupt the Stack.
|
|
20
|
+
*/
|
|
21
|
+
get items(): readonly T[];
|
|
17
22
|
push(item: T): this;
|
|
18
23
|
/**
|
|
19
24
|
* Fill (overwrite) the whole Stack (all its items) with the passed `item`.
|
|
@@ -23,7 +28,7 @@ export declare class Stack<T> {
|
|
|
23
28
|
* Returns last items in the right order.
|
|
24
29
|
* Unlike raw `items` property that returns "items buffer" as-is (not ordered properly).
|
|
25
30
|
*/
|
|
26
|
-
get itemsOrdered(): T[];
|
|
31
|
+
get itemsOrdered(): readonly T[];
|
|
27
32
|
}
|
|
28
33
|
/**
|
|
29
34
|
* Fixed-size FILO stack of Numbers.
|
|
@@ -46,5 +51,5 @@ export declare class NumberStack extends Stack<number> {
|
|
|
46
51
|
* Returns null if Stack is empty.
|
|
47
52
|
*/
|
|
48
53
|
percentileOrNull(pc: number): number | null;
|
|
49
|
-
percentiles(pcs: number[]): Record<number, number>;
|
|
54
|
+
percentiles(pcs: readonly number[]): Record<number, number>;
|
|
50
55
|
}
|
package/dist/math/stack.util.js
CHANGED
|
@@ -16,9 +16,16 @@ export class Stack {
|
|
|
16
16
|
* Currently this slot contains OLDEST item (if any).
|
|
17
17
|
*/
|
|
18
18
|
nextIndex = 0;
|
|
19
|
-
|
|
19
|
+
buffer = [];
|
|
20
|
+
/**
|
|
21
|
+
* Raw "items buffer" as-is (not ordered properly).
|
|
22
|
+
* Readonly, because mutating it (e.g sorting in-place) would corrupt the Stack.
|
|
23
|
+
*/
|
|
24
|
+
get items() {
|
|
25
|
+
return this.buffer;
|
|
26
|
+
}
|
|
20
27
|
push(item) {
|
|
21
|
-
this.
|
|
28
|
+
this.buffer[this.nextIndex] = item;
|
|
22
29
|
this.nextIndex = this.nextIndex === this.size - 1 ? 0 : this.nextIndex + 1;
|
|
23
30
|
return this;
|
|
24
31
|
}
|
|
@@ -27,7 +34,7 @@ export class Stack {
|
|
|
27
34
|
*/
|
|
28
35
|
fill(item) {
|
|
29
36
|
for (let i = 0; i < this.size; i++) {
|
|
30
|
-
this.
|
|
37
|
+
this.buffer[i] = item;
|
|
31
38
|
}
|
|
32
39
|
return this;
|
|
33
40
|
}
|
|
@@ -36,12 +43,12 @@ export class Stack {
|
|
|
36
43
|
* Unlike raw `items` property that returns "items buffer" as-is (not ordered properly).
|
|
37
44
|
*/
|
|
38
45
|
get itemsOrdered() {
|
|
39
|
-
if (this.
|
|
46
|
+
if (this.buffer.length < this.size) {
|
|
40
47
|
// Buffer is not filled yet, just return it as-is
|
|
41
|
-
return this.
|
|
48
|
+
return this.buffer;
|
|
42
49
|
}
|
|
43
50
|
// Buffer was filled and started to "overwrite itself", will need to return 2 slices
|
|
44
|
-
return [...this.
|
|
51
|
+
return [...this.buffer.slice(this.nextIndex), ...this.buffer.slice(0, this.nextIndex)];
|
|
45
52
|
}
|
|
46
53
|
}
|
|
47
54
|
/**
|
|
@@ -5,7 +5,7 @@ export declare function _randomInt(minIncl: number, maxIncl: number): number;
|
|
|
5
5
|
* Should be used on non-empty arrays! (otherwise will return undefined,
|
|
6
6
|
* which is not reflected in the output type)
|
|
7
7
|
*/
|
|
8
|
-
export declare function _randomArrayItem<T>(array: T[]): T;
|
|
8
|
+
export declare function _randomArrayItem<T>(array: readonly T[]): T;
|
|
9
9
|
/**
|
|
10
10
|
* Convenience function to "throttle" some code - run it less often.
|
|
11
11
|
*
|
|
@@ -24,7 +24,7 @@ export interface KeySortedMap<K, V> extends Map<K, V> {
|
|
|
24
24
|
export declare class KeySortedMap<K, V> {
|
|
25
25
|
#private;
|
|
26
26
|
private readonly map;
|
|
27
|
-
constructor(entries?: [K, V][], opt?: KeySortedMapOptions<K>);
|
|
27
|
+
constructor(entries?: readonly [K, V][], opt?: KeySortedMapOptions<K>);
|
|
28
28
|
/**
|
|
29
29
|
* Convenience way to create KeySortedMap from object.
|
|
30
30
|
*/
|
|
@@ -21,7 +21,7 @@ export declare class LazyKeySortedMap<K, V> {
|
|
|
21
21
|
private readonly map;
|
|
22
22
|
private readonly maybeSortedKeys;
|
|
23
23
|
private keysAreSorted;
|
|
24
|
-
constructor(entries?: [K, V][], opt?: LazyKeySortedMapOptions<K>);
|
|
24
|
+
constructor(entries?: readonly [K, V][], opt?: LazyKeySortedMapOptions<K>);
|
|
25
25
|
/**
|
|
26
26
|
* Convenience way to create KeySortedMap from object.
|
|
27
27
|
*/
|
|
@@ -28,7 +28,7 @@ export declare function _omitWithUndefined<T extends AnyObject, K extends keyof
|
|
|
28
28
|
* 'account.updated',
|
|
29
29
|
* ])
|
|
30
30
|
*/
|
|
31
|
-
export declare function _mask<T extends AnyObject>(obj: T, props: string[], opt?: MutateOptions): T;
|
|
31
|
+
export declare function _mask<T extends AnyObject>(obj: T, props: readonly string[], opt?: MutateOptions): T;
|
|
32
32
|
/**
|
|
33
33
|
* Removes "falsy" values from the object.
|
|
34
34
|
*/
|
|
@@ -4,4 +4,4 @@ import type { AnyObject } from '../types.js';
|
|
|
4
4
|
* All keys that are not listed in `keyOrder` go last.
|
|
5
5
|
* Does not mutate original object.
|
|
6
6
|
*/
|
|
7
|
-
export declare function _sortObject<T extends AnyObject>(obj: T, keyOrder: (keyof T)[]): T;
|
|
7
|
+
export declare function _sortObject<T extends AnyObject>(obj: T, keyOrder: readonly (keyof T)[]): T;
|
package/dist/promise/pTimeout.js
CHANGED
|
@@ -8,7 +8,7 @@ import { _typeCast } from '../types.js';
|
|
|
8
8
|
* If the Function rejects - passes this rejection further.
|
|
9
9
|
*/
|
|
10
10
|
export function pTimeoutFn(fn, opt) {
|
|
11
|
-
opt.name
|
|
11
|
+
opt = { ...opt, name: opt.name || fn.name }; // copy, to not mutate the input options
|
|
12
12
|
if (!opt.timeout) {
|
|
13
13
|
return fn;
|
|
14
14
|
}
|
package/dist/semver.d.ts
CHANGED
|
@@ -46,21 +46,21 @@ declare class SemverFactory {
|
|
|
46
46
|
/**
|
|
47
47
|
* Returns the highest (max) Semver from the array, or undefined if the array is empty.
|
|
48
48
|
*/
|
|
49
|
-
maxOrUndefined(items: SemverInputNullable[]): Semver | undefined;
|
|
49
|
+
maxOrUndefined(items: readonly SemverInputNullable[]): Semver | undefined;
|
|
50
50
|
/**
|
|
51
51
|
* Returns the highest Semver from the array.
|
|
52
52
|
* Throws if the array is empty.
|
|
53
53
|
*/
|
|
54
|
-
max(items: SemverInputNullable[]): Semver;
|
|
54
|
+
max(items: readonly SemverInputNullable[]): Semver;
|
|
55
55
|
/**
|
|
56
56
|
* Returns the lowest (min) Semver from the array, or undefined if the array is empty.
|
|
57
57
|
*/
|
|
58
|
-
minOrUndefined(items: SemverInputNullable[]): Semver | undefined;
|
|
58
|
+
minOrUndefined(items: readonly SemverInputNullable[]): Semver | undefined;
|
|
59
59
|
/**
|
|
60
60
|
* Returns the lowest Semver from the array.
|
|
61
61
|
* Throws if the array is empty.
|
|
62
62
|
*/
|
|
63
|
-
min(items: SemverInputNullable[]): Semver;
|
|
63
|
+
min(items: readonly SemverInputNullable[]): Semver;
|
|
64
64
|
/**
|
|
65
65
|
* Sorts an array of Semvers in `dir` order (ascending by default).
|
|
66
66
|
*/
|
package/dist/string/pupa.d.ts
CHANGED
|
@@ -19,4 +19,4 @@ export interface PupaOptions {
|
|
|
19
19
|
/**
|
|
20
20
|
* API: https://github.com/sindresorhus/pupa
|
|
21
21
|
*/
|
|
22
|
-
export declare function pupa(template: string, data: any[] | AnyObject, opt?: PupaOptions): string;
|
|
22
|
+
export declare function pupa(template: string, data: readonly any[] | AnyObject, opt?: PupaOptions): string;
|
package/package.json
CHANGED
package/src/abort.ts
CHANGED
|
@@ -67,7 +67,7 @@ export function polyfilledAbortSignalTimeout(ms: NumberOfMilliseconds): AbortSig
|
|
|
67
67
|
* otherwise undefined.
|
|
68
68
|
*/
|
|
69
69
|
export function abortSignalAnyOrUndefined(
|
|
70
|
-
signals: (AbortSignal | undefined)[],
|
|
70
|
+
signals: readonly (AbortSignal | undefined)[],
|
|
71
71
|
): AbortSignal | undefined {
|
|
72
72
|
const filtered = signals.filter(_isTruthy)
|
|
73
73
|
return filtered.length ? abortSignalAny(filtered) : undefined
|
|
@@ -82,17 +82,17 @@ export function abortSignalAnyOrUndefined(
|
|
|
82
82
|
*
|
|
83
83
|
* If only 1 signal is passed in the input array - that Signal is returned as-is.
|
|
84
84
|
*/
|
|
85
|
-
export function abortSignalAny(signals: AbortSignal[]): AbortSignal {
|
|
85
|
+
export function abortSignalAny(signals: readonly AbortSignal[]): AbortSignal {
|
|
86
86
|
if (signals.length === 1) {
|
|
87
87
|
return signals[0]!
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
return typeof AbortSignal.any === 'function'
|
|
91
|
-
? AbortSignal.any(signals)
|
|
91
|
+
? AbortSignal.any(signals as AbortSignal[]) // lib.dom types require a mutable array, but it is only read
|
|
92
92
|
: polyfilledAbortSignalAny(signals)
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
export function polyfilledAbortSignalAny(signals: AbortSignal[]): AbortSignal {
|
|
95
|
+
export function polyfilledAbortSignalAny(signals: readonly AbortSignal[]): AbortSignal {
|
|
96
96
|
const ac = new AbortController()
|
|
97
97
|
|
|
98
98
|
for (const signal of signals) {
|
package/src/array/array.util.ts
CHANGED
|
@@ -302,7 +302,7 @@ export function _countBy<T>(items: Iterable<T>, mapper: Mapper<T, any>): StringM
|
|
|
302
302
|
* _intersection([2, 1], [2, 3])
|
|
303
303
|
* // [2]
|
|
304
304
|
*/
|
|
305
|
-
export function _intersection<T>(a1: T[], a2: T[] | Set<T>): T[] {
|
|
305
|
+
export function _intersection<T>(a1: readonly T[], a2: readonly T[] | Set<T>): T[] {
|
|
306
306
|
const a2set = a2 instanceof Set ? a2 : new Set(a2)
|
|
307
307
|
return a1.filter(v => a2set.has(v))
|
|
308
308
|
}
|
|
@@ -315,7 +315,7 @@ export function _intersection<T>(a1: T[], a2: T[] | Set<T>): T[] {
|
|
|
315
315
|
*
|
|
316
316
|
* Passing second array as Set is more performant (it'll skip turning the array into Set in-place).
|
|
317
317
|
*/
|
|
318
|
-
export function _intersectsWith<T>(a1: T[], a2: T[] | Set<T>): boolean {
|
|
318
|
+
export function _intersectsWith<T>(a1: readonly T[], a2: readonly T[] | Set<T>): boolean {
|
|
319
319
|
const a2set = a2 instanceof Set ? a2 : new Set(a2)
|
|
320
320
|
return a1.some(v => a2set.has(v))
|
|
321
321
|
}
|
|
@@ -329,7 +329,7 @@ export function _intersectsWith<T>(a1: T[], a2: T[] | Set<T>): boolean {
|
|
|
329
329
|
*
|
|
330
330
|
* Passing second array as Set is more performant (it'll skip turning the array into Set in-place).
|
|
331
331
|
*/
|
|
332
|
-
export function _difference<T>(a1: T[], a2: T[] | Set<T>): T[] {
|
|
332
|
+
export function _difference<T>(a1: readonly T[], a2: readonly T[] | Set<T>): T[] {
|
|
333
333
|
const a2set = a2 instanceof Set ? a2 : new Set(a2)
|
|
334
334
|
return a1.filter(v => !a2set.has(v))
|
|
335
335
|
}
|
|
@@ -337,7 +337,7 @@ export function _difference<T>(a1: T[], a2: T[] | Set<T>): T[] {
|
|
|
337
337
|
/**
|
|
338
338
|
* Does NOT mutate the array, returns a filtered array instead.
|
|
339
339
|
*/
|
|
340
|
-
export function _arrayRemove<T>(a: T[], itemToRemove: T): T[] {
|
|
340
|
+
export function _arrayRemove<T>(a: readonly T[], itemToRemove: T): T[] {
|
|
341
341
|
return a.filter(r => r !== itemToRemove)
|
|
342
342
|
}
|
|
343
343
|
|
|
@@ -71,7 +71,7 @@ export class TranslationService {
|
|
|
71
71
|
* Loads locale(s) (if not already cached) via configured TranslationLoader.
|
|
72
72
|
* Resolves promise when done (ready to be used).
|
|
73
73
|
*/
|
|
74
|
-
async loadLocale(locale: string | string[]): Promise<void> {
|
|
74
|
+
async loadLocale(locale: string | readonly string[]): Promise<void> {
|
|
75
75
|
const locales = Array.isArray(locale) ? locale : [locale]
|
|
76
76
|
|
|
77
77
|
await pMap(locales, async locale => {
|
|
@@ -74,7 +74,7 @@ export class ImageFitter {
|
|
|
74
74
|
this.resizeObserver.disconnect()
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
private update(entries: ResizeObserverEntry[]): void {
|
|
77
|
+
private update(entries: readonly ResizeObserverEntry[]): void {
|
|
78
78
|
const width = Math.floor(entries[0]!.contentRect.width)
|
|
79
79
|
if (width === this.containerWidth) return // we're only interested in width changes
|
|
80
80
|
this.containerWidth = width
|
|
@@ -730,7 +730,7 @@ class LocalDateFactory {
|
|
|
730
730
|
/**
|
|
731
731
|
* Returns the earliest (min) LocalDate from the array, or undefined if the array is empty.
|
|
732
732
|
*/
|
|
733
|
-
minOrUndefined(items: LocalDateInputNullable[]): LocalDate | undefined {
|
|
733
|
+
minOrUndefined(items: readonly LocalDateInputNullable[]): LocalDate | undefined {
|
|
734
734
|
let min: LocalDate | undefined
|
|
735
735
|
for (const item of items) {
|
|
736
736
|
if (!item) continue
|
|
@@ -746,7 +746,7 @@ class LocalDateFactory {
|
|
|
746
746
|
* Returns the earliest LocalDate from the array.
|
|
747
747
|
* Throws if the array is empty.
|
|
748
748
|
*/
|
|
749
|
-
min(items: LocalDateInputNullable[]): LocalDate {
|
|
749
|
+
min(items: readonly LocalDateInputNullable[]): LocalDate {
|
|
750
750
|
const min = this.minOrUndefined(items)
|
|
751
751
|
_assert(min, 'localDate.min called on empty array')
|
|
752
752
|
return min
|
|
@@ -755,7 +755,7 @@ class LocalDateFactory {
|
|
|
755
755
|
/**
|
|
756
756
|
* Returns the latest (max) LocalDate from the array, or undefined if the array is empty.
|
|
757
757
|
*/
|
|
758
|
-
maxOrUndefined(items: LocalDateInputNullable[]): LocalDate | undefined {
|
|
758
|
+
maxOrUndefined(items: readonly LocalDateInputNullable[]): LocalDate | undefined {
|
|
759
759
|
let max: LocalDate | undefined
|
|
760
760
|
for (const item of items) {
|
|
761
761
|
if (!item) continue
|
|
@@ -771,7 +771,7 @@ class LocalDateFactory {
|
|
|
771
771
|
* Returns the latest LocalDate from the array.
|
|
772
772
|
* Throws if the array is empty.
|
|
773
773
|
*/
|
|
774
|
-
max(items: LocalDateInputNullable[]): LocalDate {
|
|
774
|
+
max(items: readonly LocalDateInputNullable[]): LocalDate {
|
|
775
775
|
const max = this.maxOrUndefined(items)
|
|
776
776
|
_assert(max, 'localDate.max called on empty array')
|
|
777
777
|
return max
|
|
@@ -1024,7 +1024,7 @@ class LocalTimeFactory {
|
|
|
1024
1024
|
return opt.mutate ? items.sort(cmp) : items.toSorted(cmp)
|
|
1025
1025
|
}
|
|
1026
1026
|
|
|
1027
|
-
minOrUndefined(items: LocalTimeInputNullable[]): LocalTime | undefined {
|
|
1027
|
+
minOrUndefined(items: readonly LocalTimeInputNullable[]): LocalTime | undefined {
|
|
1028
1028
|
let min: LocalTime | undefined
|
|
1029
1029
|
for (const item of items) {
|
|
1030
1030
|
if (!item) continue
|
|
@@ -1036,13 +1036,13 @@ class LocalTimeFactory {
|
|
|
1036
1036
|
return min
|
|
1037
1037
|
}
|
|
1038
1038
|
|
|
1039
|
-
min(items: LocalTimeInputNullable[]): LocalTime {
|
|
1039
|
+
min(items: readonly LocalTimeInputNullable[]): LocalTime {
|
|
1040
1040
|
const min = this.minOrUndefined(items)
|
|
1041
1041
|
_assert(min, 'localTime.min called on empty array')
|
|
1042
1042
|
return min
|
|
1043
1043
|
}
|
|
1044
1044
|
|
|
1045
|
-
maxOrUndefined(items: LocalTimeInputNullable[]): LocalTime | undefined {
|
|
1045
|
+
maxOrUndefined(items: readonly LocalTimeInputNullable[]): LocalTime | undefined {
|
|
1046
1046
|
let max: LocalTime | undefined
|
|
1047
1047
|
for (const item of items) {
|
|
1048
1048
|
if (!item) continue
|
|
@@ -1054,7 +1054,7 @@ class LocalTimeFactory {
|
|
|
1054
1054
|
return max
|
|
1055
1055
|
}
|
|
1056
1056
|
|
|
1057
|
-
max(items: LocalTimeInputNullable[]): LocalTime {
|
|
1057
|
+
max(items: readonly LocalTimeInputNullable[]): LocalTime {
|
|
1058
1058
|
const max = this.maxOrUndefined(items)
|
|
1059
1059
|
_assert(max, 'localTime.max called on empty array')
|
|
1060
1060
|
return max
|
|
@@ -34,7 +34,7 @@ export function _getTargetMethodSignature(target: AnyObject, keyStr: string): st
|
|
|
34
34
|
* returns:
|
|
35
35
|
* a, b, c
|
|
36
36
|
*/
|
|
37
|
-
export function _getArgsSignature(args: any[] = [], logArgs = true): string {
|
|
37
|
+
export function _getArgsSignature(args: readonly any[] = [], logArgs = true): string {
|
|
38
38
|
if (!logArgs) return ''
|
|
39
39
|
|
|
40
40
|
return args
|
|
@@ -14,8 +14,11 @@ export function _Timeout(opt: PTimeoutOptions): MethodDecorator {
|
|
|
14
14
|
|
|
15
15
|
descriptor.value = async function (this: typeof _target, ...args: any[]) {
|
|
16
16
|
const ctx = this
|
|
17
|
-
|
|
18
|
-
return await pTimeout(() => originalFn.apply(this, args),
|
|
17
|
+
// Not mutating the shared decorator options, as the name depends on the instance (ctx)
|
|
18
|
+
return await pTimeout(() => originalFn.apply(this, args), {
|
|
19
|
+
...opt,
|
|
20
|
+
name: opt.name || _getMethodSignature(ctx, keyStr),
|
|
21
|
+
})
|
|
19
22
|
} as any
|
|
20
23
|
|
|
21
24
|
return descriptor
|
package/src/error/assert.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _deepEquals } from '../object/deepEquals.js'
|
|
2
2
|
import { _stringify } from '../string/stringify.js'
|
|
3
|
-
import type { Class, UnixTimestamp } from '../types.js'
|
|
3
|
+
import type { Class, NonEmptyArray, UnixTimestamp } from '../types.js'
|
|
4
4
|
import type { BackendErrorResponseObject, ErrorData, ErrorObject } from './error.model.js'
|
|
5
5
|
import { _isBackendErrorResponseObject, _isErrorObject, AssertionError } from './error.util.js'
|
|
6
6
|
|
|
@@ -134,6 +134,24 @@ export function _assertIsNumber(v: any, message?: string): asserts v is number {
|
|
|
134
134
|
_assertTypeOf<number>(v, 'number', message)
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Asserts that the array has at least one element, narrowing it to NonEmptyArray.
|
|
139
|
+
* Readonly arrays are narrowed to `Readonly<NonEmptyArray<T>>`.
|
|
140
|
+
*/
|
|
141
|
+
export function _assertIsNonEmptyArray<T>(
|
|
142
|
+
arr: T[],
|
|
143
|
+
message?: string,
|
|
144
|
+
): asserts arr is NonEmptyArray<T>
|
|
145
|
+
export function _assertIsNonEmptyArray<T>(
|
|
146
|
+
arr: readonly T[],
|
|
147
|
+
message?: string,
|
|
148
|
+
): asserts arr is Readonly<NonEmptyArray<T>>
|
|
149
|
+
export function _assertIsNonEmptyArray(arr: readonly unknown[], message?: string): void {
|
|
150
|
+
if (!arr.length) {
|
|
151
|
+
throw new AssertionError(message || 'Expected non-empty array')
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
137
155
|
export function _assertTypeOf<T>(v: any, expectedType: string, message?: string): asserts v is T {
|
|
138
156
|
if (typeof v !== expectedType) {
|
|
139
157
|
const msg = message || `Expected typeof ${expectedType}, actual typeof: ${typeof v}`
|
package/src/error/error.model.ts
CHANGED
package/src/http/fetcher.ts
CHANGED
|
@@ -848,11 +848,6 @@ export class Fetcher {
|
|
|
848
848
|
private normalizeCfg(cfg: FetcherCfg & FetcherOptions): FetcherNormalizedCfg {
|
|
849
849
|
const { debug = false, logger = consoleLogger } = cfg
|
|
850
850
|
|
|
851
|
-
if (cfg.baseUrl?.endsWith('/')) {
|
|
852
|
-
logger.warn(`Fetcher: baseUrl should not end with slash: ${cfg.baseUrl}`)
|
|
853
|
-
cfg.baseUrl = cfg.baseUrl.slice(0, cfg.baseUrl.length - 1)
|
|
854
|
-
}
|
|
855
|
-
|
|
856
851
|
const norm: FetcherNormalizedCfg = _merge(
|
|
857
852
|
{
|
|
858
853
|
baseUrl: '',
|
|
@@ -894,6 +889,12 @@ export class Fetcher {
|
|
|
894
889
|
|
|
895
890
|
norm.init.headers = _mapKeys(norm.init.headers, k => k.toLowerCase())
|
|
896
891
|
|
|
892
|
+
// Normalizing `norm`, not the input `cfg`, to not mutate the input
|
|
893
|
+
if (norm.baseUrl.endsWith('/')) {
|
|
894
|
+
logger.warn(`Fetcher: baseUrl should not end with slash: ${norm.baseUrl}`)
|
|
895
|
+
norm.baseUrl = norm.baseUrl.slice(0, -1)
|
|
896
|
+
}
|
|
897
|
+
|
|
897
898
|
return norm
|
|
898
899
|
}
|
|
899
900
|
|
package/src/http/http.model.ts
CHANGED
|
@@ -8,4 +8,4 @@ export type HttpStatusFamily = 5 | 4 | 3 | 2 | 1
|
|
|
8
8
|
*/
|
|
9
9
|
export type HttpStatusCode = number
|
|
10
10
|
|
|
11
|
-
export const HTTP_METHODS: HttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD']
|
|
11
|
+
export const HTTP_METHODS: readonly HttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD']
|
package/src/log/commonLogger.ts
CHANGED
|
@@ -142,7 +142,7 @@ export function createCommonLoggerAtLevel(
|
|
|
142
142
|
/**
|
|
143
143
|
* Creates a "proxy" CommonLogger that pipes log entries to all provided sub-loggers.
|
|
144
144
|
*/
|
|
145
|
-
export function commonLoggerPipe(loggers: CommonLogger[]): CommonLogger {
|
|
145
|
+
export function commonLoggerPipe(loggers: readonly CommonLogger[]): CommonLogger {
|
|
146
146
|
return {
|
|
147
147
|
debug: (...args) => loggers.forEach(logger => logger.debug(...args)),
|
|
148
148
|
log: (...args) => loggers.forEach(logger => logger.log(...args)),
|
package/src/math/math.util.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { _assert } from '../error/assert.js'
|
|
|
9
9
|
* _average([1, 2, 3, 4])
|
|
10
10
|
* // 2.5
|
|
11
11
|
*/
|
|
12
|
-
export function _average(values: number[]): number {
|
|
12
|
+
export function _average(values: readonly number[]): number {
|
|
13
13
|
_assert(values.length, '_average is called on empty array')
|
|
14
14
|
let total = 0
|
|
15
15
|
for (const n of values) total += n
|
|
@@ -19,7 +19,7 @@ export function _average(values: number[]): number {
|
|
|
19
19
|
/**
|
|
20
20
|
* Same as _average, but safely returns null if input array is empty or nullish.
|
|
21
21
|
*/
|
|
22
|
-
export function _averageOrNull(values: number[] | undefined | null): number | null {
|
|
22
|
+
export function _averageOrNull(values: readonly number[] | undefined | null): number | null {
|
|
23
23
|
return values?.length ? _average(values) : null
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -31,7 +31,7 @@ export function _averageOrNull(values: number[] | undefined | null): number | nu
|
|
|
31
31
|
* _stdDev([2, 4, 4, 4, 5, 5, 7, 9])
|
|
32
32
|
* // 2
|
|
33
33
|
*/
|
|
34
|
-
export function _stdDev(values: number[]): number {
|
|
34
|
+
export function _stdDev(values: readonly number[]): number {
|
|
35
35
|
_assert(values.length, '_stdDev is called on empty array')
|
|
36
36
|
const avg = _average(values)
|
|
37
37
|
let sumSquaredDiff = 0
|
|
@@ -45,14 +45,14 @@ export function _stdDev(values: number[]): number {
|
|
|
45
45
|
/**
|
|
46
46
|
* Same as _stdDev, but safely returns null if input array is empty or nullish.
|
|
47
47
|
*/
|
|
48
|
-
export function _stdDevOrNull(values: number[] | undefined | null): number | null {
|
|
48
|
+
export function _stdDevOrNull(values: readonly number[] | undefined | null): number | null {
|
|
49
49
|
return values?.length ? _stdDev(values) : null
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
53
|
* valuesArray and weightsArray length is expected to be the same.
|
|
54
54
|
*/
|
|
55
|
-
export function _averageWeighted(values: number[], weights: number[]): number {
|
|
55
|
+
export function _averageWeighted(values: readonly number[], weights: readonly number[]): number {
|
|
56
56
|
let numerator = 0
|
|
57
57
|
let denominator = 0
|
|
58
58
|
for (let i = 0; i < values.length; i++) {
|
|
@@ -74,8 +74,8 @@ export function _averageWeighted(values: number[], weights: number[]): number {
|
|
|
74
74
|
* _percentile([1, 2, 3], 100)
|
|
75
75
|
* // 3
|
|
76
76
|
*/
|
|
77
|
-
export function _percentile(values: number[], pc: number): number {
|
|
78
|
-
const sorted = values.
|
|
77
|
+
export function _percentile(values: readonly number[], pc: number): number {
|
|
78
|
+
const sorted = values.toSorted(comparators.numericAsc)
|
|
79
79
|
|
|
80
80
|
// Floating pos in the range of [0; length - 1]
|
|
81
81
|
const pos = ((values.length - 1) * pc) / 100
|
|
@@ -89,10 +89,13 @@ export function _percentile(values: number[], pc: number): number {
|
|
|
89
89
|
/**
|
|
90
90
|
* A tiny bit more efficient function than calling _percentile individually.
|
|
91
91
|
*/
|
|
92
|
-
export function _percentiles(
|
|
92
|
+
export function _percentiles(
|
|
93
|
+
values: readonly number[],
|
|
94
|
+
pcs: readonly number[],
|
|
95
|
+
): Record<number, number> {
|
|
93
96
|
const r = {} as Record<number, number>
|
|
94
97
|
|
|
95
|
-
const sorted = values.
|
|
98
|
+
const sorted = values.toSorted(comparators.numericAsc)
|
|
96
99
|
|
|
97
100
|
for (const pc of pcs) {
|
|
98
101
|
// Floating pos in the range of [0; length - 1]
|
|
@@ -116,7 +119,7 @@ export function _percentiles(values: number[], pcs: number[]): Record<number, nu
|
|
|
116
119
|
* _median([1, 2, 3, 4])
|
|
117
120
|
* // 2.5
|
|
118
121
|
*/
|
|
119
|
-
export function _median(values: number[]): number {
|
|
122
|
+
export function _median(values: readonly number[]): number {
|
|
120
123
|
const sorted = values.toSorted(comparators.numericAsc)
|
|
121
124
|
const len = sorted.length
|
|
122
125
|
const mid = Math.floor(len / 2)
|
package/src/math/stack.util.ts
CHANGED
|
@@ -16,10 +16,18 @@ export class Stack<T> {
|
|
|
16
16
|
*/
|
|
17
17
|
private nextIndex = 0
|
|
18
18
|
|
|
19
|
-
readonly
|
|
19
|
+
private readonly buffer: T[] = []
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Raw "items buffer" as-is (not ordered properly).
|
|
23
|
+
* Readonly, because mutating it (e.g sorting in-place) would corrupt the Stack.
|
|
24
|
+
*/
|
|
25
|
+
get items(): readonly T[] {
|
|
26
|
+
return this.buffer
|
|
27
|
+
}
|
|
20
28
|
|
|
21
29
|
push(item: T): this {
|
|
22
|
-
this.
|
|
30
|
+
this.buffer[this.nextIndex] = item
|
|
23
31
|
this.nextIndex = this.nextIndex === this.size - 1 ? 0 : this.nextIndex + 1
|
|
24
32
|
return this
|
|
25
33
|
}
|
|
@@ -29,7 +37,7 @@ export class Stack<T> {
|
|
|
29
37
|
*/
|
|
30
38
|
fill(item: T): this {
|
|
31
39
|
for (let i = 0; i < this.size; i++) {
|
|
32
|
-
this.
|
|
40
|
+
this.buffer[i] = item
|
|
33
41
|
}
|
|
34
42
|
return this
|
|
35
43
|
}
|
|
@@ -38,14 +46,14 @@ export class Stack<T> {
|
|
|
38
46
|
* Returns last items in the right order.
|
|
39
47
|
* Unlike raw `items` property that returns "items buffer" as-is (not ordered properly).
|
|
40
48
|
*/
|
|
41
|
-
get itemsOrdered(): T[] {
|
|
42
|
-
if (this.
|
|
49
|
+
get itemsOrdered(): readonly T[] {
|
|
50
|
+
if (this.buffer.length < this.size) {
|
|
43
51
|
// Buffer is not filled yet, just return it as-is
|
|
44
|
-
return this.
|
|
52
|
+
return this.buffer
|
|
45
53
|
}
|
|
46
54
|
|
|
47
55
|
// Buffer was filled and started to "overwrite itself", will need to return 2 slices
|
|
48
|
-
return [...this.
|
|
56
|
+
return [...this.buffer.slice(this.nextIndex), ...this.buffer.slice(0, this.nextIndex)]
|
|
49
57
|
}
|
|
50
58
|
}
|
|
51
59
|
|
|
@@ -90,7 +98,7 @@ export class NumberStack extends Stack<number> {
|
|
|
90
98
|
return this.items.length === 0 ? null : _percentile(this.items, pc)
|
|
91
99
|
}
|
|
92
100
|
|
|
93
|
-
percentiles(pcs: number[]): Record<number, number> {
|
|
101
|
+
percentiles(pcs: readonly number[]): Record<number, number> {
|
|
94
102
|
return _percentiles(this.items, pcs)
|
|
95
103
|
}
|
|
96
104
|
}
|
|
@@ -9,7 +9,7 @@ export function _randomInt(minIncl: number, maxIncl: number): number {
|
|
|
9
9
|
* Should be used on non-empty arrays! (otherwise will return undefined,
|
|
10
10
|
* which is not reflected in the output type)
|
|
11
11
|
*/
|
|
12
|
-
export function _randomArrayItem<T>(array: T[]): T {
|
|
12
|
+
export function _randomArrayItem<T>(array: readonly T[]): T {
|
|
13
13
|
return array[_randomInt(0, array.length - 1)]!
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -29,7 +29,7 @@ export class KeySortedMap<K, V> {
|
|
|
29
29
|
private readonly map: Map<K, V>
|
|
30
30
|
readonly #sortedKeys: K[]
|
|
31
31
|
|
|
32
|
-
constructor(entries: [K, V][] = [], opt: KeySortedMapOptions<K> = {}) {
|
|
32
|
+
constructor(entries: readonly [K, V][] = [], opt: KeySortedMapOptions<K> = {}) {
|
|
33
33
|
this.#comparator = opt.comparator
|
|
34
34
|
this.map = new Map(entries)
|
|
35
35
|
this.#sortedKeys = Array.from(this.map.keys())
|
|
@@ -25,7 +25,7 @@ export class LazyKeySortedMap<K, V> {
|
|
|
25
25
|
private readonly maybeSortedKeys: K[]
|
|
26
26
|
private keysAreSorted = false
|
|
27
27
|
|
|
28
|
-
constructor(entries: [K, V][] = [], opt: LazyKeySortedMapOptions<K> = {}) {
|
|
28
|
+
constructor(entries: readonly [K, V][] = [], opt: LazyKeySortedMapOptions<K> = {}) {
|
|
29
29
|
this.#comparator = opt.comparator
|
|
30
30
|
this.map = new Map(entries)
|
|
31
31
|
this.maybeSortedKeys = Array.from(this.map.keys())
|
|
@@ -101,7 +101,11 @@ export function _omitWithUndefined<T extends AnyObject, K extends keyof T>(
|
|
|
101
101
|
* 'account.updated',
|
|
102
102
|
* ])
|
|
103
103
|
*/
|
|
104
|
-
export function _mask<T extends AnyObject>(
|
|
104
|
+
export function _mask<T extends AnyObject>(
|
|
105
|
+
obj: T,
|
|
106
|
+
props: readonly string[],
|
|
107
|
+
opt: MutateOptions = {},
|
|
108
|
+
): T {
|
|
105
109
|
const r = opt.mutate ? obj : _deepCopy(obj)
|
|
106
110
|
for (const k of props) {
|
|
107
111
|
_unset(r, k)
|
package/src/object/sortObject.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { AnyObject } from '../types.js'
|
|
|
5
5
|
* All keys that are not listed in `keyOrder` go last.
|
|
6
6
|
* Does not mutate original object.
|
|
7
7
|
*/
|
|
8
|
-
export function _sortObject<T extends AnyObject>(obj: T, keyOrder: (keyof T)[]): T {
|
|
8
|
+
export function _sortObject<T extends AnyObject>(obj: T, keyOrder: readonly (keyof T)[]): T {
|
|
9
9
|
const r = {} as T
|
|
10
10
|
|
|
11
11
|
// First, go over ordered keys
|
package/src/promise/pMap.ts
CHANGED
|
@@ -166,7 +166,7 @@ export async function pMap<IN, OUT>(
|
|
|
166
166
|
pMap with serial (non-concurrent) execution.
|
|
167
167
|
*/
|
|
168
168
|
async function pMap1<IN, OUT>(
|
|
169
|
-
items: IN[],
|
|
169
|
+
items: readonly IN[],
|
|
170
170
|
mapper: AbortableAsyncMapper<IN, OUT>,
|
|
171
171
|
errorMode: ErrorMode,
|
|
172
172
|
logger: CommonLogger | null,
|
|
@@ -202,7 +202,7 @@ async function pMap1<IN, OUT>(
|
|
|
202
202
|
pMap with fully concurrent execution, like Promise.all
|
|
203
203
|
*/
|
|
204
204
|
async function pMapAll<IN, OUT>(
|
|
205
|
-
items: IN[],
|
|
205
|
+
items: readonly IN[],
|
|
206
206
|
mapper: AbortableAsyncMapper<IN, OUT>,
|
|
207
207
|
errorMode: ErrorMode,
|
|
208
208
|
logger: CommonLogger | null,
|
package/src/promise/pTimeout.ts
CHANGED
|
@@ -47,7 +47,7 @@ export interface PTimeoutOptions {
|
|
|
47
47
|
* If the Function rejects - passes this rejection further.
|
|
48
48
|
*/
|
|
49
49
|
export function pTimeoutFn<T extends AnyAsyncFunction>(fn: T, opt: PTimeoutOptions): T {
|
|
50
|
-
opt.name
|
|
50
|
+
opt = { ...opt, name: opt.name || fn.name } // copy, to not mutate the input options
|
|
51
51
|
|
|
52
52
|
if (!opt.timeout) {
|
|
53
53
|
return fn
|
package/src/semver.ts
CHANGED
|
@@ -88,7 +88,7 @@ class SemverFactory {
|
|
|
88
88
|
/**
|
|
89
89
|
* Returns the highest (max) Semver from the array, or undefined if the array is empty.
|
|
90
90
|
*/
|
|
91
|
-
maxOrUndefined(items: SemverInputNullable[]): Semver | undefined {
|
|
91
|
+
maxOrUndefined(items: readonly SemverInputNullable[]): Semver | undefined {
|
|
92
92
|
let max: Semver | undefined
|
|
93
93
|
for (const item of items) {
|
|
94
94
|
const input = this.fromInputOrUndefined(item)
|
|
@@ -103,7 +103,7 @@ class SemverFactory {
|
|
|
103
103
|
* Returns the highest Semver from the array.
|
|
104
104
|
* Throws if the array is empty.
|
|
105
105
|
*/
|
|
106
|
-
max(items: SemverInputNullable[]): Semver {
|
|
106
|
+
max(items: readonly SemverInputNullable[]): Semver {
|
|
107
107
|
const max = this.maxOrUndefined(items)
|
|
108
108
|
_assert(max, 'semver.max called on empty array')
|
|
109
109
|
return max
|
|
@@ -112,7 +112,7 @@ class SemverFactory {
|
|
|
112
112
|
/**
|
|
113
113
|
* Returns the lowest (min) Semver from the array, or undefined if the array is empty.
|
|
114
114
|
*/
|
|
115
|
-
minOrUndefined(items: SemverInputNullable[]): Semver | undefined {
|
|
115
|
+
minOrUndefined(items: readonly SemverInputNullable[]): Semver | undefined {
|
|
116
116
|
let min: Semver | undefined
|
|
117
117
|
for (const item of items) {
|
|
118
118
|
const input = this.fromInputOrUndefined(item)
|
|
@@ -127,7 +127,7 @@ class SemverFactory {
|
|
|
127
127
|
* Returns the lowest Semver from the array.
|
|
128
128
|
* Throws if the array is empty.
|
|
129
129
|
*/
|
|
130
|
-
min(items: SemverInputNullable[]): Semver {
|
|
130
|
+
min(items: readonly SemverInputNullable[]): Semver {
|
|
131
131
|
const min = this.minOrUndefined(items)
|
|
132
132
|
_assert(min, 'semver.min called on empty array')
|
|
133
133
|
return min
|
package/src/string/pupa.ts
CHANGED
|
@@ -36,7 +36,11 @@ export interface PupaOptions {
|
|
|
36
36
|
/**
|
|
37
37
|
* API: https://github.com/sindresorhus/pupa
|
|
38
38
|
*/
|
|
39
|
-
export function pupa(
|
|
39
|
+
export function pupa(
|
|
40
|
+
template: string,
|
|
41
|
+
data: readonly any[] | AnyObject,
|
|
42
|
+
opt: PupaOptions = {},
|
|
43
|
+
): string {
|
|
40
44
|
if (typeof template !== 'string') {
|
|
41
45
|
throw new TypeError(`Expected a \`string\` in the first argument, got \`${typeof template}\``)
|
|
42
46
|
}
|
|
@@ -41,7 +41,7 @@ export interface ReadingTimeResult extends ReadingTimeStats {
|
|
|
41
41
|
|
|
42
42
|
type WordBoundFunction = (char: string) => boolean
|
|
43
43
|
|
|
44
|
-
function codeIsInRanges(num: number, arrayOfRanges: number[][]): boolean {
|
|
44
|
+
function codeIsInRanges(num: number, arrayOfRanges: readonly number[][]): boolean {
|
|
45
45
|
return arrayOfRanges.some(([lowerBound, upperBound]) => lowerBound! <= num && num <= upperBound!)
|
|
46
46
|
}
|
|
47
47
|
|
package/src/ua/ua.ts
CHANGED
|
@@ -379,7 +379,7 @@ function mergeMapEntries(
|
|
|
379
379
|
function rgxMapper(
|
|
380
380
|
target: UABrowser | UACpu | UADevice | UAEngine | UAOS,
|
|
381
381
|
ua: string,
|
|
382
|
-
arrays: UARegexMapEntry[],
|
|
382
|
+
arrays: readonly UARegexMapEntry[],
|
|
383
383
|
): void {
|
|
384
384
|
const t = target as unknown as Record<string, string | undefined>
|
|
385
385
|
let matches: RegExpExecArray | null = null
|