@lodestar/utils 1.35.0-dev.98d359db41 → 1.35.0-dev.b42a298a7c
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/package.json +7 -5
- package/lib/assert.d.ts.map +0 -1
- package/lib/base64.d.ts.map +0 -1
- package/lib/bytes/browser.d.ts.map +0 -1
- package/lib/bytes/index.d.ts.map +0 -1
- package/lib/bytes/nodejs.d.ts.map +0 -1
- package/lib/bytes.d.ts.map +0 -1
- package/lib/command.d.ts.map +0 -1
- package/lib/diff.d.ts.map +0 -1
- package/lib/err.d.ts.map +0 -1
- package/lib/errors.d.ts.map +0 -1
- package/lib/ethConversion.d.ts.map +0 -1
- package/lib/fetch.d.ts.map +0 -1
- package/lib/format.d.ts.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/iterator.d.ts.map +0 -1
- package/lib/logger.d.ts.map +0 -1
- package/lib/map.d.ts.map +0 -1
- package/lib/math.d.ts.map +0 -1
- package/lib/metrics.d.ts.map +0 -1
- package/lib/notNullish.d.ts.map +0 -1
- package/lib/objects.d.ts.map +0 -1
- package/lib/promise.d.ts.map +0 -1
- package/lib/retry.d.ts.map +0 -1
- package/lib/sleep.d.ts.map +0 -1
- package/lib/sort.d.ts.map +0 -1
- package/lib/timeout.d.ts.map +0 -1
- package/lib/types.d.ts.map +0 -1
- package/lib/url.d.ts.map +0 -1
- package/lib/verifyMerkleBranch.d.ts.map +0 -1
- package/lib/waitFor.d.ts.map +0 -1
- package/lib/yaml/index.d.ts.map +0 -1
- package/lib/yaml/int.d.ts.map +0 -1
- package/lib/yaml/schema.d.ts.map +0 -1
- package/src/assert.ts +0 -86
- package/src/base64.ts +0 -9
- package/src/bytes/browser.ts +0 -123
- package/src/bytes/index.ts +0 -29
- package/src/bytes/nodejs.ts +0 -63
- package/src/bytes.ts +0 -84
- package/src/command.ts +0 -74
- package/src/diff.ts +0 -234
- package/src/err.ts +0 -105
- package/src/errors.ts +0 -73
- package/src/ethConversion.ts +0 -12
- package/src/fetch.ts +0 -188
- package/src/format.ts +0 -119
- package/src/index.ts +0 -28
- package/src/iterator.ts +0 -10
- package/src/logger.ts +0 -20
- package/src/map.ts +0 -108
- package/src/math.ts +0 -55
- package/src/metrics.ts +0 -73
- package/src/notNullish.ts +0 -11
- package/src/objects.ts +0 -102
- package/src/promise.ts +0 -163
- package/src/retry.ts +0 -75
- package/src/sleep.ts +0 -32
- package/src/sort.ts +0 -9
- package/src/timeout.ts +0 -27
- package/src/types.ts +0 -48
- package/src/url.ts +0 -29
- package/src/verifyMerkleBranch.ts +0 -27
- package/src/waitFor.ts +0 -87
- package/src/yaml/index.ts +0 -12
- package/src/yaml/int.ts +0 -190
- package/src/yaml/schema.ts +0 -8
package/src/format.ts
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import {toRootHex} from "./bytes/index.js";
|
|
2
|
-
import {ETH_TO_WEI} from "./ethConversion.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Format bytes as `0x1234…1234`
|
|
6
|
-
* 4 bytes can represent 4294967296 values, so the chance of collision is low
|
|
7
|
-
*/
|
|
8
|
-
export function prettyBytes(root: Uint8Array | string): string {
|
|
9
|
-
const str = typeof root === "string" ? root : toRootHex(root);
|
|
10
|
-
return `${str.slice(0, 6)}…${str.slice(-4)}`;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Format bytes as `0x1234…`
|
|
15
|
-
* Paired with block numbers or slots, it can still act as a decent identify-able format
|
|
16
|
-
*/
|
|
17
|
-
export function prettyBytesShort(root: Uint8Array | string): string {
|
|
18
|
-
const str = typeof root === "string" ? root : toRootHex(root);
|
|
19
|
-
return `${str.slice(0, 6)}…`;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Truncate and format bytes as `0x123456789abc`
|
|
24
|
-
* 6 bytes is sufficient to avoid collisions and it allows to easily look up
|
|
25
|
-
* values on explorers like beaconcha.in while improving readability of logs
|
|
26
|
-
*/
|
|
27
|
-
export function truncBytes(root: Uint8Array | string): string {
|
|
28
|
-
const str = typeof root === "string" ? root : toRootHex(root);
|
|
29
|
-
return str.slice(0, 14);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Format a bigint value as a decimal string
|
|
34
|
-
*/
|
|
35
|
-
export function formatBigDecimal(numerator: bigint, denominator: bigint, maxDecimalFactor: bigint): string {
|
|
36
|
-
const full = numerator / denominator;
|
|
37
|
-
const fraction = ((numerator - full * denominator) * maxDecimalFactor) / denominator;
|
|
38
|
-
|
|
39
|
-
// zeros to be added post decimal are number of zeros in maxDecimalFactor - number of digits in fraction
|
|
40
|
-
const zerosPostDecimal = String(maxDecimalFactor).length - 1 - String(fraction).length;
|
|
41
|
-
return `${full}.${"0".repeat(zerosPostDecimal)}${fraction}`;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// display upto 5 decimal places
|
|
45
|
-
const MAX_DECIMAL_FACTOR = BigInt("100000");
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Format wei as ETH, with up to 5 decimals
|
|
49
|
-
*/
|
|
50
|
-
export function formatWeiToEth(wei: bigint): string {
|
|
51
|
-
return formatBigDecimal(wei, ETH_TO_WEI, MAX_DECIMAL_FACTOR);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Format wei as ETH, with up to 5 decimals and append ' ETH'
|
|
56
|
-
*/
|
|
57
|
-
export function prettyWeiToEth(wei: bigint): string {
|
|
58
|
-
return `${formatWeiToEth(wei)} ETH`;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Format milliseconds to time format HH:MM:SS.ms
|
|
63
|
-
*/
|
|
64
|
-
export function prettyMsToTime(timeMs: number): string {
|
|
65
|
-
const date = new Date(0, 0, 0, 0, 0, 0, timeMs);
|
|
66
|
-
return `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}.${date.getMilliseconds()}`;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Remove 0x prefix from a string
|
|
71
|
-
*/
|
|
72
|
-
export function strip0xPrefix(hex: string): string {
|
|
73
|
-
return hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function groupSequentialIndices(indices: number[]): string[] {
|
|
77
|
-
if (indices.length === 0) {
|
|
78
|
-
return [];
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Get unique values and sort them
|
|
82
|
-
const uniqueValues = Array.from(new Set(indices)).sort((a, b) => a - b);
|
|
83
|
-
|
|
84
|
-
const result: string[] = [];
|
|
85
|
-
let start = uniqueValues[0];
|
|
86
|
-
let end = uniqueValues[0];
|
|
87
|
-
|
|
88
|
-
for (let i = 1; i < uniqueValues.length; i++) {
|
|
89
|
-
const current = uniqueValues[i];
|
|
90
|
-
|
|
91
|
-
if (current === end + 1) {
|
|
92
|
-
end = current; // extend the range
|
|
93
|
-
} else {
|
|
94
|
-
result.push(start === end ? `${start}` : `${start}-${end}`);
|
|
95
|
-
start = current;
|
|
96
|
-
end = current;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Push the last range
|
|
101
|
-
result.push(start === end ? `${start}` : `${start}-${end}`);
|
|
102
|
-
|
|
103
|
-
return result;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Pretty print indices from an array of numbers.
|
|
108
|
-
*
|
|
109
|
-
* example:
|
|
110
|
-
* ```ts
|
|
111
|
-
* const indices = [1, 3, 109, 110, 111, 112, 113, 127];
|
|
112
|
-
* console.log(prettyPrintIndices(indices));
|
|
113
|
-
* // `1,3,110-113,127`
|
|
114
|
-
* ```
|
|
115
|
-
*/
|
|
116
|
-
export function prettyPrintIndices(indices: number[]): string {
|
|
117
|
-
const increments = groupSequentialIndices(indices);
|
|
118
|
-
return `[${increments.join(", ")}]`;
|
|
119
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export * from "./assert.js";
|
|
2
|
-
export * from "./base64.js";
|
|
3
|
-
export * from "./bytes/index.js";
|
|
4
|
-
export * from "./bytes.js";
|
|
5
|
-
export * from "./command.js";
|
|
6
|
-
export * from "./diff.js";
|
|
7
|
-
export * from "./err.js";
|
|
8
|
-
export * from "./errors.js";
|
|
9
|
-
export * from "./ethConversion.js";
|
|
10
|
-
export * from "./fetch.js";
|
|
11
|
-
export * from "./format.js";
|
|
12
|
-
export * from "./iterator.js";
|
|
13
|
-
export * from "./logger.js";
|
|
14
|
-
export * from "./map.js";
|
|
15
|
-
export * from "./math.js";
|
|
16
|
-
export * from "./metrics.js";
|
|
17
|
-
export * from "./notNullish.js";
|
|
18
|
-
export * from "./objects.js";
|
|
19
|
-
export * from "./promise.js";
|
|
20
|
-
export {type RetryOptions, retry} from "./retry.js";
|
|
21
|
-
export * from "./sleep.js";
|
|
22
|
-
export * from "./sort.js";
|
|
23
|
-
export * from "./timeout.js";
|
|
24
|
-
export {type RecursivePartial, type RequiredSelective, bnToNum} from "./types.js";
|
|
25
|
-
export * from "./url.js";
|
|
26
|
-
export * from "./verifyMerkleBranch.js";
|
|
27
|
-
export * from "./waitFor.js";
|
|
28
|
-
export * from "./yaml/index.js";
|
package/src/iterator.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// ES2024 onward we have Array.fromAsync which does exactly this
|
|
2
|
-
// This function is here as wrapper to be deleted later when we upgrade
|
|
3
|
-
// minimum nodejs requirement to > 22
|
|
4
|
-
export async function fromAsync<T>(iter: AsyncIterable<T>): Promise<T[]> {
|
|
5
|
-
const arr: T[] = [];
|
|
6
|
-
for await (const v of iter) {
|
|
7
|
-
arr.push(v);
|
|
8
|
-
}
|
|
9
|
-
return arr;
|
|
10
|
-
}
|
package/src/logger.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interface of a generic Lodestar logger. For implementations, see `@lodestar/logger`
|
|
3
|
-
*/
|
|
4
|
-
export type Logger = Record<Exclude<LogLevel, LogLevel.trace>, LogHandler>;
|
|
5
|
-
|
|
6
|
-
export enum LogLevel {
|
|
7
|
-
error = "error",
|
|
8
|
-
warn = "warn",
|
|
9
|
-
info = "info",
|
|
10
|
-
verbose = "verbose",
|
|
11
|
-
debug = "debug",
|
|
12
|
-
trace = "trace",
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const LogLevels = Object.values(LogLevel);
|
|
16
|
-
|
|
17
|
-
export type LogHandler = (message: string, context?: LogData, error?: Error) => void;
|
|
18
|
-
|
|
19
|
-
export type LogDataBasic = string | number | bigint | boolean | null | undefined;
|
|
20
|
-
export type LogData = LogDataBasic | Record<string, LogDataBasic> | LogDataBasic[] | Record<string, LogDataBasic>[];
|
package/src/map.ts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
export class MapDef<K, V> extends Map<K, V> {
|
|
2
|
-
constructor(private readonly getDefault: () => V) {
|
|
3
|
-
super();
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
getOrDefault(key: K): V {
|
|
7
|
-
let value = super.get(key);
|
|
8
|
-
if (value === undefined) {
|
|
9
|
-
value = this.getDefault();
|
|
10
|
-
this.set(key, value);
|
|
11
|
-
}
|
|
12
|
-
return value;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Extends MapDef but ensures that there always a max of `maxKeys` keys
|
|
18
|
-
*/
|
|
19
|
-
export class MapDefMax<K, V> {
|
|
20
|
-
private readonly map = new Map<K, V>();
|
|
21
|
-
|
|
22
|
-
constructor(
|
|
23
|
-
private readonly getDefault: () => V,
|
|
24
|
-
private readonly maxKeys: number
|
|
25
|
-
) {}
|
|
26
|
-
|
|
27
|
-
getOrDefault(key: K): V {
|
|
28
|
-
let value = this.map.get(key);
|
|
29
|
-
if (value === undefined) {
|
|
30
|
-
value = this.getDefault();
|
|
31
|
-
this.map.set(key, value);
|
|
32
|
-
pruneSetToMax(this.map, this.maxKeys);
|
|
33
|
-
}
|
|
34
|
-
return value;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
get(key: K): V | undefined {
|
|
38
|
-
return this.map.get(key);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* 2 dimensions Es6 Map
|
|
44
|
-
*/
|
|
45
|
-
export class Map2d<K1, K2, V> {
|
|
46
|
-
readonly map = new Map<K1, Map<K2, V>>();
|
|
47
|
-
|
|
48
|
-
get(k1: K1, k2: K2): V | undefined {
|
|
49
|
-
return this.map.get(k1)?.get(k2);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
set(k1: K1, k2: K2, v: V): void {
|
|
53
|
-
let map2 = this.map.get(k1);
|
|
54
|
-
if (!map2) {
|
|
55
|
-
map2 = new Map<K2, V>();
|
|
56
|
-
this.map.set(k1, map2);
|
|
57
|
-
}
|
|
58
|
-
map2.set(k2, v);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* 2 dimensions Es6 Map + regular array
|
|
64
|
-
*/
|
|
65
|
-
export class Map2dArr<K1, V> {
|
|
66
|
-
readonly map = new Map<K1, V[]>();
|
|
67
|
-
|
|
68
|
-
get(k1: K1, idx: number): V | undefined {
|
|
69
|
-
return this.map.get(k1)?.[idx];
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
set(k1: K1, idx: number, v: V): void {
|
|
73
|
-
let arr = this.map.get(k1);
|
|
74
|
-
if (!arr) {
|
|
75
|
-
arr = [];
|
|
76
|
-
this.map.set(k1, arr);
|
|
77
|
-
}
|
|
78
|
-
arr[idx] = v;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Prune an arbitrary set removing the first keys to have a set.size === maxItems.
|
|
84
|
-
* Returns the count of deleted items.
|
|
85
|
-
*
|
|
86
|
-
* Keys can be sorted by `compareFn` to get more control over which items to prune first
|
|
87
|
-
*/
|
|
88
|
-
export function pruneSetToMax<T>(
|
|
89
|
-
set: Set<T> | Map<T, unknown>,
|
|
90
|
-
maxItems: number,
|
|
91
|
-
compareFn?: (a: T, b: T) => number
|
|
92
|
-
): number {
|
|
93
|
-
let itemsToDelete = set.size - maxItems;
|
|
94
|
-
const deletedItems = Math.max(0, itemsToDelete);
|
|
95
|
-
|
|
96
|
-
if (itemsToDelete > 0) {
|
|
97
|
-
const keys = compareFn ? Array.from(set.keys()).sort(compareFn) : set.keys();
|
|
98
|
-
for (const key of keys) {
|
|
99
|
-
set.delete(key);
|
|
100
|
-
itemsToDelete--;
|
|
101
|
-
if (itemsToDelete <= 0) {
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return deletedItems;
|
|
108
|
-
}
|
package/src/math.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Return the min number between two big numbers.
|
|
3
|
-
*/
|
|
4
|
-
export function bigIntMin(a: bigint, b: bigint): bigint {
|
|
5
|
-
return a < b ? a : b;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Return the max number between two big numbers.
|
|
10
|
-
*/
|
|
11
|
-
export function bigIntMax(a: bigint, b: bigint): bigint {
|
|
12
|
-
return a > b ? a : b;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function intDiv(dividend: number, divisor: number): number {
|
|
16
|
-
return Math.floor(dividend / divisor);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Calculate the largest integer k such that k**2 <= n.
|
|
21
|
-
*/
|
|
22
|
-
export function intSqrt(n: number): number {
|
|
23
|
-
let x = n;
|
|
24
|
-
let y = intDiv(x + 1, 2);
|
|
25
|
-
while (y < x) {
|
|
26
|
-
x = y;
|
|
27
|
-
y = intDiv(x + intDiv(n, x), 2);
|
|
28
|
-
}
|
|
29
|
-
return x;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function bigIntSqrt(n: bigint): bigint {
|
|
33
|
-
let x = n;
|
|
34
|
-
let y = (x + BigInt(1)) / BigInt(2);
|
|
35
|
-
while (y < x) {
|
|
36
|
-
x = y;
|
|
37
|
-
y = (x + n / x) / BigInt(2);
|
|
38
|
-
}
|
|
39
|
-
return x;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Regenerates a random integer between min (included) and max (excluded).
|
|
44
|
-
*/
|
|
45
|
-
export function randBetween(min: number, max: number): number {
|
|
46
|
-
return Math.floor(Math.random() * (max - min)) + min;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Wraps randBetween and returns a bigNumber.
|
|
51
|
-
* @returns {bigint}
|
|
52
|
-
*/
|
|
53
|
-
export function randBetweenBigInt(min: number, max: number): bigint {
|
|
54
|
-
return BigInt(randBetween(min, max));
|
|
55
|
-
}
|
package/src/metrics.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import {NonEmptyArray} from "./types.js";
|
|
2
|
-
|
|
3
|
-
export type NoLabels = Record<string, never>;
|
|
4
|
-
export type LabelsGeneric = Record<string, string | number>;
|
|
5
|
-
export type LabelKeys<Labels extends LabelsGeneric> = Extract<keyof Labels, string>;
|
|
6
|
-
export type CollectFn<Labels extends LabelsGeneric> = (metric: Gauge<Labels>) => void;
|
|
7
|
-
|
|
8
|
-
export interface Gauge<Labels extends LabelsGeneric = NoLabels> {
|
|
9
|
-
inc: NoLabels extends Labels ? (value?: number) => void : (labels: Labels, value?: number) => void;
|
|
10
|
-
dec: NoLabels extends Labels ? (value?: number) => void : (labels: Labels, value?: number) => void;
|
|
11
|
-
set: NoLabels extends Labels ? (value: number) => void : (labels: Labels, value: number) => void;
|
|
12
|
-
|
|
13
|
-
collect?(): void;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface GaugeExtra<Labels extends LabelsGeneric = NoLabels> extends Omit<Gauge<Labels>, "collect"> {
|
|
17
|
-
addCollect(collectFn: CollectFn<Labels>): void;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface Histogram<Labels extends LabelsGeneric = NoLabels> {
|
|
21
|
-
startTimer(): NoLabels extends Labels ? () => number : (labels: Labels) => number;
|
|
22
|
-
startTimer<L extends Partial<Labels>>(
|
|
23
|
-
labels?: NoLabels extends Labels ? never : L
|
|
24
|
-
): keyof Omit<Labels, keyof L> extends never ? () => number : (labels: Omit<Labels, keyof L>) => number;
|
|
25
|
-
|
|
26
|
-
observe: NoLabels extends Labels ? (value: number) => void : (labels: Labels, value: number) => void;
|
|
27
|
-
|
|
28
|
-
reset(): void;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface AvgMinMax<Labels extends LabelsGeneric = NoLabels> {
|
|
32
|
-
addGetValuesFn(getValuesFn: () => number[]): void;
|
|
33
|
-
|
|
34
|
-
set: NoLabels extends Labels ? (values: number[]) => void : (labels: Labels, values: number[]) => void;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface Counter<Labels extends LabelsGeneric = NoLabels> {
|
|
38
|
-
inc: NoLabels extends Labels ? (value?: number) => void : (labels: Labels, value?: number) => void;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export type GaugeConfig<Labels extends LabelsGeneric> = {
|
|
42
|
-
name: string;
|
|
43
|
-
help: string;
|
|
44
|
-
} & (NoLabels extends Labels ? {labelNames?: never} : {labelNames: NonEmptyArray<LabelKeys<Labels>>});
|
|
45
|
-
|
|
46
|
-
export type HistogramConfig<Labels extends LabelsGeneric> = GaugeConfig<Labels> & {
|
|
47
|
-
buckets: number[];
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export type AvgMinMaxConfig<Labels extends LabelsGeneric> = GaugeConfig<Labels>;
|
|
51
|
-
|
|
52
|
-
export type CounterConfig<Labels extends LabelsGeneric> = GaugeConfig<Labels>;
|
|
53
|
-
|
|
54
|
-
export type StaticConfig<Labels extends LabelsGeneric> = {
|
|
55
|
-
name: GaugeConfig<Labels>["name"];
|
|
56
|
-
help: GaugeConfig<Labels>["help"];
|
|
57
|
-
value: Record<LabelKeys<Labels>, string>;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
export interface MetricsRegister {
|
|
61
|
-
gauge<Labels extends LabelsGeneric = NoLabels>(config: GaugeConfig<Labels>): Gauge<Labels>;
|
|
62
|
-
histogram<Labels extends LabelsGeneric = NoLabels>(config: HistogramConfig<Labels>): Histogram<Labels>;
|
|
63
|
-
counter<Labels extends LabelsGeneric = NoLabels>(config: CounterConfig<Labels>): Counter<Labels>;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface MetricsRegisterExtra extends MetricsRegister {
|
|
67
|
-
gauge<Labels extends LabelsGeneric = NoLabels>(config: GaugeConfig<Labels>): GaugeExtra<Labels>;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export interface MetricsRegisterCustom extends MetricsRegisterExtra {
|
|
71
|
-
avgMinMax<Labels extends LabelsGeneric = NoLabels>(config: AvgMinMaxConfig<Labels>): AvgMinMax<Labels>;
|
|
72
|
-
static<Labels extends LabelsGeneric = NoLabels>(config: StaticConfig<Labels>): void;
|
|
73
|
-
}
|
package/src/notNullish.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type-safe helper to filter out nullist values from an array
|
|
3
|
-
* ```js
|
|
4
|
-
* const array: (string | null)[] = ['foo', null];
|
|
5
|
-
* const filteredArray: string[] = array.filter(notEmpty);
|
|
6
|
-
* ```
|
|
7
|
-
* @param value
|
|
8
|
-
*/
|
|
9
|
-
export function notNullish<TValue>(value: TValue | null | undefined): value is TValue {
|
|
10
|
-
return value !== null && value !== undefined;
|
|
11
|
-
}
|
package/src/objects.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import Case from "case";
|
|
2
|
-
|
|
3
|
-
export type KeyCase =
|
|
4
|
-
| "snake"
|
|
5
|
-
| "constant"
|
|
6
|
-
| "camel"
|
|
7
|
-
| "param"
|
|
8
|
-
| "header"
|
|
9
|
-
| "pascal" //Same as squish
|
|
10
|
-
| "dot"
|
|
11
|
-
| "notransform";
|
|
12
|
-
|
|
13
|
-
export function toExpectedCase(
|
|
14
|
-
value: string,
|
|
15
|
-
expectedCase: KeyCase = "camel",
|
|
16
|
-
customCasingMap?: Record<string, string>
|
|
17
|
-
): string {
|
|
18
|
-
if (expectedCase === "notransform") return value;
|
|
19
|
-
if (customCasingMap?.[value]) return customCasingMap[value];
|
|
20
|
-
switch (expectedCase) {
|
|
21
|
-
case "param":
|
|
22
|
-
return Case.kebab(value);
|
|
23
|
-
case "dot":
|
|
24
|
-
return Case.lower(value, ".", true);
|
|
25
|
-
default:
|
|
26
|
-
return Case[expectedCase](value);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function isObjectObject(val: unknown): val is object {
|
|
31
|
-
return val != null && typeof val === "object" && Array.isArray(val) === false;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function isPlainObject(o: unknown): o is object {
|
|
35
|
-
if (isObjectObject(o) === false) return false;
|
|
36
|
-
|
|
37
|
-
// If has modified constructor
|
|
38
|
-
const ctor = (o as Record<string, unknown>).constructor;
|
|
39
|
-
if (typeof ctor !== "function") return false;
|
|
40
|
-
|
|
41
|
-
// If has modified prototype
|
|
42
|
-
const prot = ctor.prototype;
|
|
43
|
-
if (isObjectObject(prot) === false) return false;
|
|
44
|
-
|
|
45
|
-
// If constructor does not have an Object-specific method
|
|
46
|
-
if (Object.prototype.hasOwnProperty.call(prot, "isPrototypeOf") === false) {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Most likely a plain Object
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function isEmptyObject(value: unknown): boolean {
|
|
55
|
-
return isObjectObject(value) && Object.keys(value).length === 0;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Creates an object with the same keys as object and values generated by running each own enumerable
|
|
60
|
-
* string keyed property of object thru iteratee.
|
|
61
|
-
*
|
|
62
|
-
* Inspired on lodash.mapValues, see https://lodash.com/docs/4.17.15#mapValues
|
|
63
|
-
*/
|
|
64
|
-
// biome-ignore lint/suspicious/noExplicitAny: We need to use `any` type here
|
|
65
|
-
export function mapValues<T extends {[K: string]: any}, R>(
|
|
66
|
-
obj: T,
|
|
67
|
-
iteratee: (value: T[keyof T], key: keyof T) => R
|
|
68
|
-
): {[K in keyof T]: R} {
|
|
69
|
-
const output = {} as {[K in keyof T]: R};
|
|
70
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
71
|
-
output[key as keyof T] = iteratee(value, key);
|
|
72
|
-
}
|
|
73
|
-
return output;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function objectToExpectedCase<T extends Record<string, unknown> | Record<string, unknown>[] | unknown[]>(
|
|
77
|
-
obj: T,
|
|
78
|
-
expectedCase: "snake" | "constant" | "camel" | "param" | "header" | "pascal" | "dot" | "notransform" = "camel"
|
|
79
|
-
): T {
|
|
80
|
-
if (Array.isArray(obj)) {
|
|
81
|
-
const newArr: unknown[] = [];
|
|
82
|
-
for (let i = 0; i < obj.length; i++) {
|
|
83
|
-
newArr[i] = objectToExpectedCase(obj[i] as T, expectedCase);
|
|
84
|
-
}
|
|
85
|
-
return newArr as unknown as T;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (Object(obj) === obj) {
|
|
89
|
-
const newObj: Record<string, unknown> = {};
|
|
90
|
-
for (const name of Object.getOwnPropertyNames(obj)) {
|
|
91
|
-
const newName = toExpectedCase(name, expectedCase);
|
|
92
|
-
if (newName !== name && Object.prototype.hasOwnProperty.call(obj, newName)) {
|
|
93
|
-
throw new Error(`object already has a ${newName} property`);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
newObj[newName] = objectToExpectedCase(obj[name] as Record<string, unknown>, expectedCase);
|
|
97
|
-
}
|
|
98
|
-
return newObj as T;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return obj;
|
|
102
|
-
}
|
package/src/promise.ts
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import {ErrorAborted, TimeoutError} from "./errors.js";
|
|
2
|
-
import {sleep} from "./sleep.js";
|
|
3
|
-
import {ArrayToTuple, NonEmptyArray} from "./types.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* While promise t is not finished, call function `fn` per `interval`
|
|
7
|
-
*/
|
|
8
|
-
export async function callFnWhenAwait<T>(
|
|
9
|
-
p: Promise<T>,
|
|
10
|
-
fn: () => void,
|
|
11
|
-
interval: number,
|
|
12
|
-
signal?: AbortSignal
|
|
13
|
-
): Promise<T> {
|
|
14
|
-
let done = false;
|
|
15
|
-
const logFn = async (): Promise<void> => {
|
|
16
|
-
while (!done) {
|
|
17
|
-
await sleep(interval, signal);
|
|
18
|
-
if (!done) fn();
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const t = await Promise.race([p, logFn()]).finally(() => {
|
|
23
|
-
done = true;
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
return t as T;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Create a deferred promise
|
|
31
|
-
*/
|
|
32
|
-
export function defer<T>() {
|
|
33
|
-
let resolve!: (v: T) => void;
|
|
34
|
-
let reject!: (e: unknown) => void;
|
|
35
|
-
const promise = new Promise<T>((res, rej) => {
|
|
36
|
-
resolve = res;
|
|
37
|
-
reject = rej;
|
|
38
|
-
});
|
|
39
|
-
return {promise, resolve, reject};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export type PromiseResult<T> = {
|
|
43
|
-
promise: Promise<T>;
|
|
44
|
-
} & (
|
|
45
|
-
| {
|
|
46
|
-
status: "pending";
|
|
47
|
-
}
|
|
48
|
-
| {
|
|
49
|
-
status: "fulfilled";
|
|
50
|
-
value: T;
|
|
51
|
-
durationMs: number;
|
|
52
|
-
}
|
|
53
|
-
| {
|
|
54
|
-
status: "rejected";
|
|
55
|
-
reason: Error;
|
|
56
|
-
durationMs: number;
|
|
57
|
-
}
|
|
58
|
-
);
|
|
59
|
-
export type PromiseFulfilledResult<T> = PromiseResult<T> & {status: "fulfilled"};
|
|
60
|
-
export type PromiseRejectedResult<T> = PromiseResult<T> & {status: "rejected"};
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Wrap a promise to an object to track the status and value of the promise
|
|
64
|
-
*/
|
|
65
|
-
export function wrapPromise<T>(promise: PromiseLike<T>): PromiseResult<T> {
|
|
66
|
-
const startedAt = Date.now();
|
|
67
|
-
|
|
68
|
-
const result = {
|
|
69
|
-
promise: promise.then(
|
|
70
|
-
(value) => {
|
|
71
|
-
result.status = "fulfilled";
|
|
72
|
-
(result as PromiseFulfilledResult<T>).value = value;
|
|
73
|
-
(result as PromiseFulfilledResult<T>).durationMs = Date.now() - startedAt;
|
|
74
|
-
return value;
|
|
75
|
-
},
|
|
76
|
-
(reason: unknown) => {
|
|
77
|
-
result.status = "rejected";
|
|
78
|
-
(result as PromiseRejectedResult<T>).reason = reason as Error;
|
|
79
|
-
(result as PromiseRejectedResult<T>).durationMs = Date.now() - startedAt;
|
|
80
|
-
throw reason;
|
|
81
|
-
}
|
|
82
|
-
),
|
|
83
|
-
status: "pending",
|
|
84
|
-
} as PromiseResult<T>;
|
|
85
|
-
|
|
86
|
-
return result;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
type ReturnPromiseWithTuple<Tuple extends NonEmptyArray<PromiseLike<unknown>>> = {
|
|
90
|
-
[Index in keyof ArrayToTuple<Tuple>]: PromiseResult<Awaited<Tuple[Index]>>;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Two phased approach for resolving promises:
|
|
95
|
-
* - first wait `resolveTimeoutMs` or until all promises settle
|
|
96
|
-
* - then wait `raceTimeoutMs - resolveTimeoutMs` or until at least a single promise resolves
|
|
97
|
-
*
|
|
98
|
-
* Returns a list of promise results, see `PromiseResult`
|
|
99
|
-
*/
|
|
100
|
-
export async function resolveOrRacePromises<T extends NonEmptyArray<PromiseLike<unknown>>>(
|
|
101
|
-
promises: T,
|
|
102
|
-
{
|
|
103
|
-
resolveTimeoutMs,
|
|
104
|
-
raceTimeoutMs,
|
|
105
|
-
signal,
|
|
106
|
-
}: {
|
|
107
|
-
resolveTimeoutMs: number;
|
|
108
|
-
raceTimeoutMs: number;
|
|
109
|
-
signal?: AbortSignal;
|
|
110
|
-
}
|
|
111
|
-
): Promise<ReturnPromiseWithTuple<T>> | never {
|
|
112
|
-
if (raceTimeoutMs <= resolveTimeoutMs) {
|
|
113
|
-
throw new Error("Race time must be greater than resolve time");
|
|
114
|
-
}
|
|
115
|
-
const resolveTimeoutError = new TimeoutError(
|
|
116
|
-
`Given promises can't be resolved within resolveTimeoutMs=${resolveTimeoutMs}`
|
|
117
|
-
);
|
|
118
|
-
const raceTimeoutError = new TimeoutError(
|
|
119
|
-
`Not a any single promise be resolved in given raceTimeoutMs=${raceTimeoutMs}`
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
const promiseResults = promises.map((p) => wrapPromise(p)) as ReturnPromiseWithTuple<T>;
|
|
123
|
-
// We intentionally want an array of promises here
|
|
124
|
-
promises = (promiseResults as PromiseResult<T>[]).map((p) => p.promise) as unknown as T;
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
await Promise.race([
|
|
128
|
-
Promise.allSettled(promises),
|
|
129
|
-
sleep(resolveTimeoutMs, signal).then(() => {
|
|
130
|
-
throw resolveTimeoutError;
|
|
131
|
-
}),
|
|
132
|
-
]);
|
|
133
|
-
|
|
134
|
-
return promiseResults;
|
|
135
|
-
} catch (err) {
|
|
136
|
-
if (err instanceof ErrorAborted) {
|
|
137
|
-
return promiseResults;
|
|
138
|
-
}
|
|
139
|
-
if (err !== resolveTimeoutError) {
|
|
140
|
-
throw err;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
try {
|
|
145
|
-
await Promise.race([
|
|
146
|
-
Promise.any(promises),
|
|
147
|
-
sleep(raceTimeoutMs - resolveTimeoutMs, signal).then(() => {
|
|
148
|
-
throw raceTimeoutError;
|
|
149
|
-
}),
|
|
150
|
-
]);
|
|
151
|
-
|
|
152
|
-
return promiseResults;
|
|
153
|
-
} catch (err) {
|
|
154
|
-
if (err instanceof ErrorAborted) {
|
|
155
|
-
return promiseResults;
|
|
156
|
-
}
|
|
157
|
-
if (err !== raceTimeoutError && !(err instanceof AggregateError)) {
|
|
158
|
-
throw err;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return promiseResults;
|
|
163
|
-
}
|