@welshman/lib 0.0.32 → 0.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -8
- package/build/src/Context.cjs +17 -0
- package/build/src/Context.cjs.map +1 -1
- package/build/src/Context.d.ts +17 -0
- package/build/src/Context.mjs +17 -0
- package/build/src/Context.mjs.map +1 -1
- package/build/src/Deferred.cjs +9 -0
- package/build/src/Deferred.cjs.map +1 -1
- package/build/src/Deferred.d.ts +11 -0
- package/build/src/Deferred.mjs +9 -0
- package/build/src/Deferred.mjs.map +1 -1
- package/build/src/Emitter.cjs +9 -0
- package/build/src/Emitter.cjs.map +1 -1
- package/build/src/Emitter.d.ts +9 -0
- package/build/src/Emitter.mjs +9 -0
- package/build/src/Emitter.mjs.map +1 -1
- package/build/src/LRUCache.cjs +16 -0
- package/build/src/LRUCache.cjs.map +1 -1
- package/build/src/LRUCache.d.ts +16 -0
- package/build/src/LRUCache.mjs +16 -0
- package/build/src/LRUCache.mjs.map +1 -1
- package/build/src/Tools.cjs +478 -12
- package/build/src/Tools.cjs.map +1 -1
- package/build/src/Tools.d.ts +465 -18
- package/build/src/Tools.mjs +471 -9
- package/build/src/Tools.mjs.map +1 -1
- package/build/src/Worker.cjs +27 -1
- package/build/src/Worker.cjs.map +1 -1
- package/build/src/Worker.d.ts +25 -0
- package/build/src/Worker.mjs +27 -1
- package/build/src/Worker.mjs.map +1 -1
- package/build/src/index.cjs +0 -1
- package/build/src/index.cjs.map +1 -1
- package/build/src/index.d.ts +0 -1
- package/build/src/index.mjs +0 -1
- package/build/src/index.mjs.map +1 -1
- package/package.json +1 -1
- package/build/src/Fluent.cjs +0 -47
- package/build/src/Fluent.cjs.map +0 -1
- package/build/src/Fluent.d.ts +0 -34
- package/build/src/Fluent.mjs +0 -43
- package/build/src/Fluent.mjs.map +0 -1
package/build/src/Tools.mjs
CHANGED
|
@@ -1,31 +1,103 @@
|
|
|
1
1
|
import { bech32, utf8 } from "@scure/base";
|
|
2
|
+
/** Checks if a value is null or undefined */
|
|
2
3
|
export const isNil = (x) => [null, undefined].includes(x);
|
|
4
|
+
/**
|
|
5
|
+
* Executes a function if the value is defined
|
|
6
|
+
* @param x - The value to check
|
|
7
|
+
* @param f - Function to execute if x is defined
|
|
8
|
+
* @returns Result of f(x) if x is defined, undefined otherwise
|
|
9
|
+
*/
|
|
3
10
|
export const ifLet = (x, f) => x === undefined ? undefined : f(x);
|
|
4
|
-
|
|
11
|
+
/** Function that does nothing and returns undefined */
|
|
5
12
|
export const noop = (...args) => undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Returns the first element of an array
|
|
15
|
+
* @param xs - The array
|
|
16
|
+
* @returns First element or undefined
|
|
17
|
+
*/
|
|
6
18
|
export const first = (xs, ...args) => xs[0];
|
|
19
|
+
/**
|
|
20
|
+
* Returns the first element of the first array in a nested array
|
|
21
|
+
* @param xs - Array of arrays
|
|
22
|
+
* @returns First element of first array or undefined
|
|
23
|
+
*/
|
|
7
24
|
export const ffirst = (xs, ...args) => xs[0][0];
|
|
25
|
+
/**
|
|
26
|
+
* Returns the last element of an array
|
|
27
|
+
* @param xs - The array
|
|
28
|
+
* @returns Last element or undefined
|
|
29
|
+
*/
|
|
8
30
|
export const last = (xs, ...args) => xs[xs.length - 1];
|
|
31
|
+
/**
|
|
32
|
+
* Returns the input value unchanged
|
|
33
|
+
* @param x - Any value
|
|
34
|
+
* @returns The same value
|
|
35
|
+
*/
|
|
9
36
|
export const identity = (x, ...args) => x;
|
|
37
|
+
/**
|
|
38
|
+
* Creates a function that always returns the same value
|
|
39
|
+
* @param x - Value to return
|
|
40
|
+
* @returns Function that returns x
|
|
41
|
+
*/
|
|
10
42
|
export const always = (x, ...args) => () => x;
|
|
43
|
+
/**
|
|
44
|
+
* Returns the logical NOT of a value
|
|
45
|
+
* @param x - Value to negate
|
|
46
|
+
* @returns !x
|
|
47
|
+
*/
|
|
11
48
|
export const not = (x, ...args) => !x;
|
|
49
|
+
/** Returns a function that returns the boolean negation of the given function */
|
|
50
|
+
export const complement = (f) => (...args) => !f(...args);
|
|
51
|
+
/** Converts a Maybe<number> to a number, defaulting to 0 */
|
|
12
52
|
export const num = (x) => x || 0;
|
|
53
|
+
/** Adds two numbers, handling undefined values */
|
|
13
54
|
export const add = (x, y) => num(x) + num(y);
|
|
55
|
+
/** Subtracts two numbers, handling undefined values */
|
|
14
56
|
export const sub = (x, y) => num(x) - num(y);
|
|
57
|
+
/** Multiplies two numbers, handling undefined values */
|
|
15
58
|
export const mul = (x, y) => num(x) * num(y);
|
|
59
|
+
/** Divides two numbers, handling undefined values */
|
|
16
60
|
export const div = (x, y) => num(x) / y;
|
|
61
|
+
/** Increments a number by 1, handling undefined values */
|
|
17
62
|
export const inc = (x) => add(x, 1);
|
|
63
|
+
/** Decrements a number by 1, handling undefined values */
|
|
18
64
|
export const dec = (x) => sub(x, 1);
|
|
65
|
+
/** Less than comparison, handling undefined values */
|
|
19
66
|
export const lt = (x, y) => num(x) < num(y);
|
|
67
|
+
/** Less than or equal comparison, handling undefined values */
|
|
20
68
|
export const lte = (x, y) => num(x) <= num(y);
|
|
69
|
+
/** Greater than comparison, handling undefined values */
|
|
21
70
|
export const gt = (x, y) => num(x) > num(y);
|
|
71
|
+
/** Greater than or equal comparison, handling undefined values */
|
|
22
72
|
export const gte = (x, y) => num(x) >= num(y);
|
|
73
|
+
/** Returns maximum value in array, handling undefined values */
|
|
23
74
|
export const max = (xs) => xs.reduce((a, b) => Math.max(num(a), num(b)), 0);
|
|
75
|
+
/** Returns minimum value in array, handling undefined values */
|
|
24
76
|
export const min = (xs) => xs.reduce((a, b) => Math.min(num(a), num(b)), 0);
|
|
77
|
+
/** Returns sum of array values, handling undefined values */
|
|
25
78
|
export const sum = (xs) => xs.reduce((a, b) => add(a, b), 0);
|
|
79
|
+
/** Returns average of array values, handling undefined values */
|
|
26
80
|
export const avg = (xs) => sum(xs) / xs.length;
|
|
81
|
+
/**
|
|
82
|
+
* Returns array with first n elements removed
|
|
83
|
+
* @param n - Number of elements to drop
|
|
84
|
+
* @param xs - Input array
|
|
85
|
+
* @returns Array with first n elements removed
|
|
86
|
+
*/
|
|
27
87
|
export const drop = (n, xs) => xs.slice(n);
|
|
88
|
+
/**
|
|
89
|
+
* Returns first n elements of array
|
|
90
|
+
* @param n - Number of elements to take
|
|
91
|
+
* @param xs - Input array
|
|
92
|
+
* @returns Array of first n elements
|
|
93
|
+
*/
|
|
28
94
|
export const take = (n, xs) => xs.slice(0, n);
|
|
95
|
+
/**
|
|
96
|
+
* Creates new object with specified keys removed
|
|
97
|
+
* @param ks - Keys to remove
|
|
98
|
+
* @param x - Source object
|
|
99
|
+
* @returns New object without specified keys
|
|
100
|
+
*/
|
|
29
101
|
export const omit = (ks, x) => {
|
|
30
102
|
const r = { ...x };
|
|
31
103
|
for (const k of ks) {
|
|
@@ -33,6 +105,12 @@ export const omit = (ks, x) => {
|
|
|
33
105
|
}
|
|
34
106
|
return r;
|
|
35
107
|
};
|
|
108
|
+
/**
|
|
109
|
+
* Creates new object excluding entries with specified values
|
|
110
|
+
* @param xs - Values to exclude
|
|
111
|
+
* @param x - Source object
|
|
112
|
+
* @returns New object without entries containing specified values
|
|
113
|
+
*/
|
|
36
114
|
export const omitVals = (xs, x) => {
|
|
37
115
|
const r = {};
|
|
38
116
|
for (const [k, v] of Object.entries(x)) {
|
|
@@ -42,6 +120,12 @@ export const omitVals = (xs, x) => {
|
|
|
42
120
|
}
|
|
43
121
|
return r;
|
|
44
122
|
};
|
|
123
|
+
/**
|
|
124
|
+
* Creates new object with only specified keys
|
|
125
|
+
* @param ks - Keys to keep
|
|
126
|
+
* @param x - Source object
|
|
127
|
+
* @returns New object with only specified keys
|
|
128
|
+
*/
|
|
45
129
|
export const pick = (ks, x) => {
|
|
46
130
|
const r = { ...x };
|
|
47
131
|
for (const k of Object.keys(x)) {
|
|
@@ -51,11 +135,24 @@ export const pick = (ks, x) => {
|
|
|
51
135
|
}
|
|
52
136
|
return r;
|
|
53
137
|
};
|
|
138
|
+
/**
|
|
139
|
+
* Generates sequence of numbers from a to b
|
|
140
|
+
* @param a - Start number (inclusive)
|
|
141
|
+
* @param b - End number (exclusive)
|
|
142
|
+
* @param step - Increment between numbers
|
|
143
|
+
* @yields Numbers in sequence
|
|
144
|
+
*/
|
|
54
145
|
export function* range(a, b, step = 1) {
|
|
55
146
|
for (let i = a; i < b; i += step) {
|
|
56
147
|
yield i;
|
|
57
148
|
}
|
|
58
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Creates new object with transformed keys
|
|
152
|
+
* @param f - Function to transform keys
|
|
153
|
+
* @param x - Source object
|
|
154
|
+
* @returns Object with transformed keys
|
|
155
|
+
*/
|
|
59
156
|
export const mapKeys = (f, x) => {
|
|
60
157
|
const r = {};
|
|
61
158
|
for (const [k, v] of Object.entries(x)) {
|
|
@@ -63,6 +160,12 @@ export const mapKeys = (f, x) => {
|
|
|
63
160
|
}
|
|
64
161
|
return r;
|
|
65
162
|
};
|
|
163
|
+
/**
|
|
164
|
+
* Creates new object with transformed values
|
|
165
|
+
* @param f - Function to transform values
|
|
166
|
+
* @param x - Source object
|
|
167
|
+
* @returns Object with transformed values
|
|
168
|
+
*/
|
|
66
169
|
export const mapVals = (f, x) => {
|
|
67
170
|
const r = {};
|
|
68
171
|
for (const [k, v] of Object.entries(x)) {
|
|
@@ -70,42 +173,171 @@ export const mapVals = (f, x) => {
|
|
|
70
173
|
}
|
|
71
174
|
return r;
|
|
72
175
|
};
|
|
176
|
+
/**
|
|
177
|
+
* Merges two objects, with left object taking precedence
|
|
178
|
+
* @param a - Left object
|
|
179
|
+
* @param b - Right object
|
|
180
|
+
* @returns Merged object with a's properties overriding b's
|
|
181
|
+
*/
|
|
73
182
|
export const mergeLeft = (a, b) => ({ ...b, ...a });
|
|
183
|
+
/**
|
|
184
|
+
* Merges two objects, with right object taking precedence
|
|
185
|
+
* @param a - Left object
|
|
186
|
+
* @param b - Right object
|
|
187
|
+
* @returns Merged object with b's properties overriding a's
|
|
188
|
+
*/
|
|
74
189
|
export const mergeRight = (a, b) => ({ ...a, ...b });
|
|
190
|
+
/**
|
|
191
|
+
* Checks if a number is between two values (exclusive)
|
|
192
|
+
* @param bounds - Lower and upper bounds
|
|
193
|
+
* @param n - Number to check
|
|
194
|
+
* @returns True if n is between low and high
|
|
195
|
+
*/
|
|
75
196
|
export const between = ([low, high], n) => n > low && n < high;
|
|
197
|
+
/**
|
|
198
|
+
* Checks if a number is between two values (inclusive)
|
|
199
|
+
* @param bounds - Lower and upper bounds
|
|
200
|
+
* @param n - Number to check
|
|
201
|
+
* @returns True if n is between low and high
|
|
202
|
+
*/
|
|
203
|
+
export const within = ([low, high], n) => n >= low && n <= high;
|
|
204
|
+
/**
|
|
205
|
+
* Generates random integer between min and max (inclusive)
|
|
206
|
+
* @param min - Minimum value
|
|
207
|
+
* @param max - Maximum value
|
|
208
|
+
* @returns Random integer
|
|
209
|
+
*/
|
|
76
210
|
export const randomInt = (min = 0, max = 9) => min + Math.round(Math.random() * (max - min));
|
|
211
|
+
/**
|
|
212
|
+
* Generates random string ID
|
|
213
|
+
* @returns Random string suitable for use as an ID
|
|
214
|
+
*/
|
|
77
215
|
export const randomId = () => Math.random().toString().slice(2);
|
|
216
|
+
/**
|
|
217
|
+
* Removes protocol (http://, https://, etc) from URL
|
|
218
|
+
* @param url - URL to process
|
|
219
|
+
* @returns URL without protocol
|
|
220
|
+
*/
|
|
78
221
|
export const stripProtocol = (url) => url.replace(/.*:\/\//, "");
|
|
222
|
+
/**
|
|
223
|
+
* Formats URL for display by removing protocol, www, and trailing slash
|
|
224
|
+
* @param url - URL to format
|
|
225
|
+
* @returns Formatted URL
|
|
226
|
+
*/
|
|
79
227
|
export const displayUrl = (url) => stripProtocol(url).replace(/^(www\.)?/i, "").replace(/\/$/, "");
|
|
228
|
+
/**
|
|
229
|
+
* Extracts and formats domain from URL
|
|
230
|
+
* @param url - URL to process
|
|
231
|
+
* @returns Formatted domain name
|
|
232
|
+
*/
|
|
80
233
|
export const displayDomain = (url) => displayUrl(first(url.split(/[\/\?]/)));
|
|
234
|
+
/**
|
|
235
|
+
* Creates a promise that resolves after specified time
|
|
236
|
+
* @param t - Time in milliseconds
|
|
237
|
+
* @returns Promise that resolves after t milliseconds
|
|
238
|
+
*/
|
|
81
239
|
export const sleep = (t) => new Promise(resolve => setTimeout(resolve, t));
|
|
82
|
-
|
|
240
|
+
/**
|
|
241
|
+
* Concatenates multiple arrays, filtering out null/undefined
|
|
242
|
+
* @param xs - Arrays to concatenate
|
|
243
|
+
* @returns Combined array
|
|
244
|
+
*/
|
|
245
|
+
export const concat = (...xs) => xs.flatMap(x => isNil(x) ? [] : x);
|
|
246
|
+
/**
|
|
247
|
+
* Appends element to array
|
|
248
|
+
* @param x - Element to append
|
|
249
|
+
* @param xs - Array to append to
|
|
250
|
+
* @returns New array with element appended
|
|
251
|
+
*/
|
|
83
252
|
export const append = (x, xs) => concat(xs, [x]);
|
|
253
|
+
/**
|
|
254
|
+
* Creates union of two arrays
|
|
255
|
+
* @param a - First array
|
|
256
|
+
* @param b - Second array
|
|
257
|
+
* @returns Array containing unique elements from both arrays
|
|
258
|
+
*/
|
|
84
259
|
export const union = (a, b) => uniq([...a, ...b]);
|
|
260
|
+
/**
|
|
261
|
+
* Returns elements common to both arrays
|
|
262
|
+
* @param a - First array
|
|
263
|
+
* @param b - Second array
|
|
264
|
+
* @returns Array of elements present in both inputs
|
|
265
|
+
*/
|
|
85
266
|
export const intersection = (a, b) => {
|
|
86
267
|
const s = new Set(b);
|
|
87
268
|
return a.filter(x => s.has(x));
|
|
88
269
|
};
|
|
270
|
+
/**
|
|
271
|
+
* Returns elements in first array not present in second
|
|
272
|
+
* @param a - Source array
|
|
273
|
+
* @param b - Array of elements to exclude
|
|
274
|
+
* @returns Array containing elements unique to first array
|
|
275
|
+
*/
|
|
89
276
|
export const difference = (a, b) => {
|
|
90
277
|
const s = new Set(b);
|
|
91
278
|
return a.filter(x => !s.has(x));
|
|
92
279
|
};
|
|
280
|
+
/**
|
|
281
|
+
* Removes all instances of an element from array
|
|
282
|
+
* @param a - Element to remove
|
|
283
|
+
* @param xs - Source array
|
|
284
|
+
* @returns New array with element removed
|
|
285
|
+
*/
|
|
93
286
|
export const remove = (a, xs) => xs.filter(x => x !== a);
|
|
287
|
+
/**
|
|
288
|
+
* Returns elements from second array not present in first
|
|
289
|
+
* @param a - Array of elements to exclude
|
|
290
|
+
* @param b - Source array
|
|
291
|
+
* @returns Filtered array
|
|
292
|
+
*/
|
|
94
293
|
export const without = (a, b) => b.filter(x => !a.includes(x));
|
|
294
|
+
/**
|
|
295
|
+
* Toggles presence of element in array
|
|
296
|
+
* @param x - Element to toggle
|
|
297
|
+
* @param xs - Source array
|
|
298
|
+
* @returns New array with element added or removed
|
|
299
|
+
*/
|
|
95
300
|
export const toggle = (x, xs) => xs.includes(x) ? remove(x, xs) : append(x, xs);
|
|
301
|
+
/**
|
|
302
|
+
* Constrains number between min and max values
|
|
303
|
+
* @param bounds - Minimum and maximum allowed values
|
|
304
|
+
* @param n - Number to clamp
|
|
305
|
+
* @returns Clamped value
|
|
306
|
+
*/
|
|
96
307
|
export const clamp = ([min, max], n) => Math.min(max, Math.max(min, n));
|
|
308
|
+
/**
|
|
309
|
+
* Safely parses JSON string
|
|
310
|
+
* @param json - JSON string to parse
|
|
311
|
+
* @returns Parsed object or null if invalid
|
|
312
|
+
*/
|
|
97
313
|
export const parseJson = (json) => {
|
|
98
314
|
if (!json)
|
|
99
|
-
return
|
|
315
|
+
return undefined;
|
|
100
316
|
try {
|
|
101
317
|
return JSON.parse(json);
|
|
102
318
|
}
|
|
103
319
|
catch (e) {
|
|
104
|
-
return
|
|
320
|
+
return undefined;
|
|
105
321
|
}
|
|
106
322
|
};
|
|
323
|
+
/**
|
|
324
|
+
* Gets and parses JSON from localStorage
|
|
325
|
+
* @param k - Storage key
|
|
326
|
+
* @returns Parsed value or undefined if invalid/missing
|
|
327
|
+
*/
|
|
107
328
|
export const getJson = (k) => parseJson(localStorage.getItem(k) || "");
|
|
329
|
+
/**
|
|
330
|
+
* Stringifies and stores value in localStorage
|
|
331
|
+
* @param k - Storage key
|
|
332
|
+
* @param v - Value to store
|
|
333
|
+
*/
|
|
108
334
|
export const setJson = (k, v) => localStorage.setItem(k, JSON.stringify(v));
|
|
335
|
+
/**
|
|
336
|
+
* Safely executes function and handles errors
|
|
337
|
+
* @param f - Function to execute
|
|
338
|
+
* @param onError - Optional error handler
|
|
339
|
+
* @returns Function result or undefined if error
|
|
340
|
+
*/
|
|
109
341
|
export const tryCatch = (f, onError) => {
|
|
110
342
|
try {
|
|
111
343
|
const r = f();
|
|
@@ -119,6 +351,13 @@ export const tryCatch = (f, onError) => {
|
|
|
119
351
|
}
|
|
120
352
|
return undefined;
|
|
121
353
|
};
|
|
354
|
+
/**
|
|
355
|
+
* Truncates string to length, breaking at word boundaries
|
|
356
|
+
* @param s - String to truncate
|
|
357
|
+
* @param l - Maximum length
|
|
358
|
+
* @param suffix - String to append if truncated
|
|
359
|
+
* @returns Truncated string
|
|
360
|
+
*/
|
|
122
361
|
export const ellipsize = (s, l, suffix = '...') => {
|
|
123
362
|
if (s.length < l * 1.1) {
|
|
124
363
|
return s;
|
|
@@ -128,12 +367,23 @@ export const ellipsize = (s, l, suffix = '...') => {
|
|
|
128
367
|
}
|
|
129
368
|
return s + suffix;
|
|
130
369
|
};
|
|
370
|
+
/**
|
|
371
|
+
* Checks if value is a plain object
|
|
372
|
+
* @param obj - Value to check
|
|
373
|
+
* @returns True if value is a plain object
|
|
374
|
+
*/
|
|
131
375
|
export const isPojo = (obj) => {
|
|
132
376
|
if (obj === null || typeof obj !== "object") {
|
|
133
377
|
return false;
|
|
134
378
|
}
|
|
135
379
|
return Object.getPrototypeOf(obj) === Object.prototype;
|
|
136
380
|
};
|
|
381
|
+
/**
|
|
382
|
+
* Deep equality comparison
|
|
383
|
+
* @param a - First value
|
|
384
|
+
* @param b - Second value
|
|
385
|
+
* @returns True if values are deeply equal
|
|
386
|
+
*/
|
|
137
387
|
export const equals = (a, b) => {
|
|
138
388
|
if (a === b)
|
|
139
389
|
return true;
|
|
@@ -177,24 +427,56 @@ export const equals = (a, b) => {
|
|
|
177
427
|
return false;
|
|
178
428
|
};
|
|
179
429
|
// Curried utils
|
|
430
|
+
/** Returns a function that gets the nth element of an array */
|
|
180
431
|
export const nth = (i) => (xs, ...args) => xs[i];
|
|
432
|
+
/** Returns a function that checks if nth element equals value */
|
|
181
433
|
export const nthEq = (i, v) => (xs, ...args) => xs[i] === v;
|
|
434
|
+
/** Returns a function that checks if nth element does not equal value */
|
|
182
435
|
export const nthNe = (i, v) => (xs, ...args) => xs[i] !== v;
|
|
436
|
+
/** Returns a function that checks if key/value pairs of x match all pairs in spec */
|
|
437
|
+
export const spec = (values) => (x) => {
|
|
438
|
+
for (const [k, v] of Object.entries(values)) {
|
|
439
|
+
if (x[k] !== v)
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
return true;
|
|
443
|
+
};
|
|
444
|
+
/** Returns a function that checks equality with value */
|
|
183
445
|
export const eq = (v) => (x) => x === v;
|
|
446
|
+
/** Returns a function that checks inequality with value */
|
|
184
447
|
export const ne = (v) => (x) => x !== v;
|
|
448
|
+
/** Returns a function that gets property value from object */
|
|
185
449
|
export const prop = (k) => (x) => x[k];
|
|
450
|
+
/** Returns a function that adds/updates property on object */
|
|
186
451
|
export const assoc = (k, v) => (o) => ({ ...o, [k]: v });
|
|
452
|
+
/** Generates a hash string from input string */
|
|
187
453
|
export const hash = (s) => Math.abs(s.split("").reduce((a, b) => ((a << 5) - a + b.charCodeAt(0)) | 0, 0)).toString();
|
|
188
454
|
// Collections
|
|
455
|
+
/** Splits array into two parts at index */
|
|
189
456
|
export const splitAt = (n, xs) => [xs.slice(0, n), xs.slice(n)];
|
|
457
|
+
/** Inserts element into array at index */
|
|
190
458
|
export const insert = (n, x, xs) => [...xs.slice(0, n), x, ...xs.slice(n)];
|
|
459
|
+
/** Returns random element from array */
|
|
191
460
|
export const choice = (xs) => xs[Math.floor(xs.length * Math.random())];
|
|
461
|
+
/** Returns shuffled copy of iterable */
|
|
192
462
|
export const shuffle = (xs) => Array.from(xs).sort(() => Math.random() > 0.5 ? 1 : -1);
|
|
463
|
+
/** Returns n random elements from array */
|
|
193
464
|
export const sample = (n, xs) => shuffle(xs).slice(0, n);
|
|
465
|
+
/** Checks if value is iterable */
|
|
194
466
|
export const isIterable = (x) => Symbol.iterator in Object(x);
|
|
467
|
+
/** Ensures value is iterable by wrapping in array if needed */
|
|
195
468
|
export const toIterable = (x) => isIterable(x) ? x : [x];
|
|
469
|
+
/** Ensures value is array by wrapping if needed */
|
|
196
470
|
export const ensurePlural = (x) => (x instanceof Array ? x : [x]);
|
|
471
|
+
/** Converts string or number to number */
|
|
197
472
|
export const ensureNumber = (x) => parseFloat(x);
|
|
473
|
+
/** Returns a function that gets property value from object */
|
|
474
|
+
export const pluck = (k, xs) => xs.map(x => x[k]);
|
|
475
|
+
/**
|
|
476
|
+
* Creates object from array of key-value pairs
|
|
477
|
+
* @param pairs - Array of [key, value] tuples
|
|
478
|
+
* @returns Object with keys and values from pairs
|
|
479
|
+
*/
|
|
198
480
|
export const fromPairs = (pairs) => {
|
|
199
481
|
const r = {};
|
|
200
482
|
for (const [k, v] of pairs) {
|
|
@@ -204,7 +486,18 @@ export const fromPairs = (pairs) => {
|
|
|
204
486
|
}
|
|
205
487
|
return r;
|
|
206
488
|
};
|
|
489
|
+
/**
|
|
490
|
+
* Flattens array of arrays into single array
|
|
491
|
+
* @param xs - Array of arrays to flatten
|
|
492
|
+
* @returns Flattened array
|
|
493
|
+
*/
|
|
207
494
|
export const flatten = (xs) => xs.flatMap(identity);
|
|
495
|
+
/**
|
|
496
|
+
* Splits array into two arrays based on predicate
|
|
497
|
+
* @param f - Function to test elements
|
|
498
|
+
* @param xs - Array to partition
|
|
499
|
+
* @returns Tuple of [matching, non-matching] arrays
|
|
500
|
+
*/
|
|
208
501
|
export const partition = (f, xs) => {
|
|
209
502
|
const a = [];
|
|
210
503
|
const b = [];
|
|
@@ -218,7 +511,18 @@ export const partition = (f, xs) => {
|
|
|
218
511
|
}
|
|
219
512
|
return [a, b];
|
|
220
513
|
};
|
|
514
|
+
/**
|
|
515
|
+
* Returns array with duplicate elements removed
|
|
516
|
+
* @param xs - Array with possible duplicates
|
|
517
|
+
* @returns Array with unique elements
|
|
518
|
+
*/
|
|
221
519
|
export const uniq = (xs) => Array.from(new Set(xs));
|
|
520
|
+
/**
|
|
521
|
+
* Returns array with elements unique by key function
|
|
522
|
+
* @param f - Function to generate key for each element
|
|
523
|
+
* @param xs - Input array
|
|
524
|
+
* @returns Array with elements unique by key
|
|
525
|
+
*/
|
|
222
526
|
export const uniqBy = (f, xs) => {
|
|
223
527
|
const s = new Set();
|
|
224
528
|
const r = [];
|
|
@@ -232,12 +536,29 @@ export const uniqBy = (f, xs) => {
|
|
|
232
536
|
}
|
|
233
537
|
return r;
|
|
234
538
|
};
|
|
539
|
+
/**
|
|
540
|
+
* Returns sorted copy of array
|
|
541
|
+
* @param xs - Array to sort
|
|
542
|
+
* @returns New sorted array
|
|
543
|
+
*/
|
|
235
544
|
export const sort = (xs) => [...xs].sort();
|
|
545
|
+
/**
|
|
546
|
+
* Returns array sorted by key function
|
|
547
|
+
* @param f - Function to generate sort key
|
|
548
|
+
* @param xs - Array to sort
|
|
549
|
+
* @returns Sorted array
|
|
550
|
+
*/
|
|
236
551
|
export const sortBy = (f, xs) => [...xs].sort((a, b) => {
|
|
237
552
|
const x = f(a);
|
|
238
553
|
const y = f(b);
|
|
239
554
|
return x < y ? -1 : x > y ? 1 : 0;
|
|
240
555
|
});
|
|
556
|
+
/**
|
|
557
|
+
* Groups array elements by key function
|
|
558
|
+
* @param f - Function to generate group key
|
|
559
|
+
* @param xs - Array to group
|
|
560
|
+
* @returns Map of groups
|
|
561
|
+
*/
|
|
241
562
|
export const groupBy = (f, xs) => {
|
|
242
563
|
const r = new Map();
|
|
243
564
|
for (const x of xs) {
|
|
@@ -251,6 +572,12 @@ export const groupBy = (f, xs) => {
|
|
|
251
572
|
}
|
|
252
573
|
return r;
|
|
253
574
|
};
|
|
575
|
+
/**
|
|
576
|
+
* Creates map from array using key function
|
|
577
|
+
* @param f - Function to generate key
|
|
578
|
+
* @param xs - Array to index
|
|
579
|
+
* @returns Map of values by key
|
|
580
|
+
*/
|
|
254
581
|
export const indexBy = (f, xs) => {
|
|
255
582
|
const r = new Map();
|
|
256
583
|
for (const x of xs) {
|
|
@@ -258,6 +585,12 @@ export const indexBy = (f, xs) => {
|
|
|
258
585
|
}
|
|
259
586
|
return r;
|
|
260
587
|
};
|
|
588
|
+
/**
|
|
589
|
+
* Creates array of specified length using generator function
|
|
590
|
+
* @param n - Length of array
|
|
591
|
+
* @param f - Function to generate each element
|
|
592
|
+
* @returns Generated array
|
|
593
|
+
*/
|
|
261
594
|
export const initArray = (n, f) => {
|
|
262
595
|
const result = [];
|
|
263
596
|
for (let i = 0; i < n; i++) {
|
|
@@ -265,6 +598,12 @@ export const initArray = (n, f) => {
|
|
|
265
598
|
}
|
|
266
599
|
return result;
|
|
267
600
|
};
|
|
601
|
+
/**
|
|
602
|
+
* Splits array into chunks of specified length
|
|
603
|
+
* @param chunkLength - Maximum length of each chunk
|
|
604
|
+
* @param xs - Array to split
|
|
605
|
+
* @returns Array of chunks
|
|
606
|
+
*/
|
|
268
607
|
export const chunk = (chunkLength, xs) => {
|
|
269
608
|
const result = [];
|
|
270
609
|
const current = [];
|
|
@@ -281,6 +620,12 @@ export const chunk = (chunkLength, xs) => {
|
|
|
281
620
|
}
|
|
282
621
|
return result;
|
|
283
622
|
};
|
|
623
|
+
/**
|
|
624
|
+
* Splits array into specified number of chunks
|
|
625
|
+
* @param n - Number of chunks
|
|
626
|
+
* @param xs - Array to split
|
|
627
|
+
* @returns Array of n chunks
|
|
628
|
+
*/
|
|
284
629
|
export const chunks = (n, xs) => {
|
|
285
630
|
const result = initArray(n, () => []);
|
|
286
631
|
for (let i = 0; i < xs.length; i++) {
|
|
@@ -288,6 +633,11 @@ export const chunks = (n, xs) => {
|
|
|
288
633
|
}
|
|
289
634
|
return result;
|
|
290
635
|
};
|
|
636
|
+
/**
|
|
637
|
+
* Creates function that only executes once
|
|
638
|
+
* @param f - Function to wrap
|
|
639
|
+
* @returns Function that executes f only on first call
|
|
640
|
+
*/
|
|
291
641
|
export const once = (f) => {
|
|
292
642
|
let called = false;
|
|
293
643
|
return (...args) => {
|
|
@@ -297,6 +647,11 @@ export const once = (f) => {
|
|
|
297
647
|
}
|
|
298
648
|
};
|
|
299
649
|
};
|
|
650
|
+
/**
|
|
651
|
+
* Memoizes function results based on arguments
|
|
652
|
+
* @param f - Function to memoize
|
|
653
|
+
* @returns Memoized function
|
|
654
|
+
*/
|
|
300
655
|
export const memoize = (f) => {
|
|
301
656
|
let prevArgs;
|
|
302
657
|
let result;
|
|
@@ -308,6 +663,12 @@ export const memoize = (f) => {
|
|
|
308
663
|
return result;
|
|
309
664
|
};
|
|
310
665
|
};
|
|
666
|
+
/**
|
|
667
|
+
* Creates throttled version of function
|
|
668
|
+
* @param ms - Minimum time between calls
|
|
669
|
+
* @param f - Function to throttle
|
|
670
|
+
* @returns Throttled function
|
|
671
|
+
*/
|
|
311
672
|
export const throttle = (ms, f) => {
|
|
312
673
|
if (ms === 0) {
|
|
313
674
|
return f;
|
|
@@ -332,6 +693,12 @@ export const throttle = (ms, f) => {
|
|
|
332
693
|
}
|
|
333
694
|
};
|
|
334
695
|
};
|
|
696
|
+
/**
|
|
697
|
+
* Creates throttled function that returns cached value
|
|
698
|
+
* @param ms - Minimum time between updates
|
|
699
|
+
* @param f - Function to throttle
|
|
700
|
+
* @returns Function returning latest value
|
|
701
|
+
*/
|
|
335
702
|
export const throttleWithValue = (ms, f) => {
|
|
336
703
|
let value;
|
|
337
704
|
const update = throttle(ms, () => {
|
|
@@ -342,6 +709,12 @@ export const throttleWithValue = (ms, f) => {
|
|
|
342
709
|
return value;
|
|
343
710
|
};
|
|
344
711
|
};
|
|
712
|
+
/**
|
|
713
|
+
* Creates batching function that collects items
|
|
714
|
+
* @param t - Time window for batching
|
|
715
|
+
* @param f - Function to process batch
|
|
716
|
+
* @returns Function that adds items to batch
|
|
717
|
+
*/
|
|
345
718
|
export const batch = (t, f) => {
|
|
346
719
|
const xs = [];
|
|
347
720
|
const cb = throttle(t, () => xs.length > 0 && f(xs.splice(0)));
|
|
@@ -350,6 +723,12 @@ export const batch = (t, f) => {
|
|
|
350
723
|
cb();
|
|
351
724
|
};
|
|
352
725
|
};
|
|
726
|
+
/**
|
|
727
|
+
* Creates batching function that returns results
|
|
728
|
+
* @param t - Time window for batching
|
|
729
|
+
* @param execute - Function to process batch
|
|
730
|
+
* @returns Function that returns promise of result
|
|
731
|
+
*/
|
|
353
732
|
export const batcher = (t, execute) => {
|
|
354
733
|
const queue = [];
|
|
355
734
|
const _execute = async () => {
|
|
@@ -367,39 +746,99 @@ export const batcher = (t, execute) => {
|
|
|
367
746
|
queue.push({ request, resolve });
|
|
368
747
|
});
|
|
369
748
|
};
|
|
749
|
+
/**
|
|
750
|
+
* Adds value to Set at key in object
|
|
751
|
+
* @param m - Object mapping keys to Sets
|
|
752
|
+
* @param k - Key to add to
|
|
753
|
+
* @param v - Value to add
|
|
754
|
+
*/
|
|
370
755
|
export const addToKey = (m, k, v) => {
|
|
371
756
|
const s = m[k] || new Set();
|
|
372
757
|
s.add(v);
|
|
373
758
|
m[k] = s;
|
|
374
759
|
};
|
|
760
|
+
/**
|
|
761
|
+
* Pushes value to array at key in object
|
|
762
|
+
* @param m - Object mapping keys to arrays
|
|
763
|
+
* @param k - Key to push to
|
|
764
|
+
* @param v - Value to push
|
|
765
|
+
*/
|
|
375
766
|
export const pushToKey = (m, k, v) => {
|
|
376
767
|
const a = m[k] || [];
|
|
377
768
|
a.push(v);
|
|
378
769
|
m[k] = a;
|
|
379
770
|
};
|
|
771
|
+
/**
|
|
772
|
+
* Adds value to Set at key in Map
|
|
773
|
+
* @param m - Map of Sets
|
|
774
|
+
* @param k - Key to add to
|
|
775
|
+
* @param v - Value to add
|
|
776
|
+
*/
|
|
380
777
|
export const addToMapKey = (m, k, v) => {
|
|
381
778
|
const s = m.get(k) || new Set();
|
|
382
779
|
s.add(v);
|
|
383
780
|
m.set(k, s);
|
|
384
781
|
};
|
|
782
|
+
/**
|
|
783
|
+
* Pushes value to array at key in Map
|
|
784
|
+
* @param m - Map of arrays
|
|
785
|
+
* @param k - Key to push to
|
|
786
|
+
* @param v - Value to push
|
|
787
|
+
*/
|
|
385
788
|
export const pushToMapKey = (m, k, v) => {
|
|
386
789
|
const a = m.get(k) || [];
|
|
387
790
|
a.push(v);
|
|
388
791
|
m.set(k, a);
|
|
389
792
|
};
|
|
793
|
+
/**
|
|
794
|
+
* Switches on key in object, with default fallback
|
|
795
|
+
* @param k - Key to look up
|
|
796
|
+
* @param m - Object with values and optional default
|
|
797
|
+
* @returns Value at key or default value
|
|
798
|
+
*/
|
|
390
799
|
export const switcher = (k, m) => m[k] === undefined ? m.default : m[k];
|
|
391
|
-
|
|
800
|
+
/** One minute in seconds */
|
|
392
801
|
export const MINUTE = 60;
|
|
802
|
+
/** One hour in seconds */
|
|
393
803
|
export const HOUR = 60 * MINUTE;
|
|
804
|
+
/** One day in seconds */
|
|
394
805
|
export const DAY = 24 * HOUR;
|
|
806
|
+
/** One week in seconds */
|
|
395
807
|
export const WEEK = 7 * DAY;
|
|
808
|
+
/** One month in seconds (approximate) */
|
|
396
809
|
export const MONTH = 30 * DAY;
|
|
810
|
+
/** One quarter in seconds (approximate) */
|
|
397
811
|
export const QUARTER = 90 * DAY;
|
|
812
|
+
/** One year in seconds (approximate) */
|
|
398
813
|
export const YEAR = 365 * DAY;
|
|
814
|
+
/**
|
|
815
|
+
* Multiplies time unit by count
|
|
816
|
+
* @param unit - Time unit in seconds
|
|
817
|
+
* @param count - Number of units
|
|
818
|
+
* @returns Total seconds
|
|
819
|
+
*/
|
|
399
820
|
export const int = (unit, count = 1) => unit * count;
|
|
821
|
+
/** Returns current Unix timestamp in seconds */
|
|
400
822
|
export const now = () => Math.round(Date.now() / 1000);
|
|
823
|
+
/**
|
|
824
|
+
* Returns Unix timestamp from specified time ago
|
|
825
|
+
* @param unit - Time unit in seconds
|
|
826
|
+
* @param count - Number of units
|
|
827
|
+
* @returns Timestamp in seconds
|
|
828
|
+
*/
|
|
401
829
|
export const ago = (unit, count = 1) => now() - int(unit, count);
|
|
830
|
+
/**
|
|
831
|
+
* Converts seconds to milliseconds
|
|
832
|
+
* @param seconds - Time in seconds
|
|
833
|
+
* @returns Time in milliseconds
|
|
834
|
+
*/
|
|
402
835
|
export const ms = (seconds) => seconds * 1000;
|
|
836
|
+
/**
|
|
837
|
+
* Fetches JSON from URL with options
|
|
838
|
+
* @param url - URL to fetch from
|
|
839
|
+
* @param opts - Fetch options
|
|
840
|
+
* @returns Promise of parsed JSON response
|
|
841
|
+
*/
|
|
403
842
|
export const fetchJson = async (url, opts = {}) => {
|
|
404
843
|
if (!opts.headers) {
|
|
405
844
|
opts.headers = {};
|
|
@@ -409,6 +848,13 @@ export const fetchJson = async (url, opts = {}) => {
|
|
|
409
848
|
const json = await res.json();
|
|
410
849
|
return json;
|
|
411
850
|
};
|
|
851
|
+
/**
|
|
852
|
+
* Posts JSON data to URL
|
|
853
|
+
* @param url - URL to post to
|
|
854
|
+
* @param data - Data to send
|
|
855
|
+
* @param opts - Additional fetch options
|
|
856
|
+
* @returns Promise of parsed JSON response
|
|
857
|
+
*/
|
|
412
858
|
export const postJson = async (url, data, opts = {}) => {
|
|
413
859
|
if (!opts.method) {
|
|
414
860
|
opts.method = "POST";
|
|
@@ -420,12 +866,28 @@ export const postJson = async (url, data, opts = {}) => {
|
|
|
420
866
|
opts.body = JSON.stringify(data);
|
|
421
867
|
return fetchJson(url, opts);
|
|
422
868
|
};
|
|
423
|
-
|
|
869
|
+
/**
|
|
870
|
+
* Uploads file to URL
|
|
871
|
+
* @param url - Upload URL
|
|
872
|
+
* @param file - File to upload
|
|
873
|
+
* @returns Promise of parsed JSON response
|
|
874
|
+
*/
|
|
875
|
+
export const uploadFile = (url, file) => {
|
|
424
876
|
const body = new FormData();
|
|
425
|
-
body.append("file",
|
|
877
|
+
body.append("file", file);
|
|
426
878
|
return fetchJson(url, { method: "POST", body });
|
|
427
879
|
};
|
|
428
|
-
|
|
429
|
-
|
|
880
|
+
/**
|
|
881
|
+
* Converts hex string to bech32 format
|
|
882
|
+
* @param prefix - Bech32 prefix
|
|
883
|
+
* @param hex - Hex string to convert
|
|
884
|
+
* @returns Bech32 encoded string
|
|
885
|
+
*/
|
|
886
|
+
export const hexToBech32 = (prefix, hex) => bech32.encode(prefix, bech32.toWords(utf8.decode(hex)), false);
|
|
887
|
+
/**
|
|
888
|
+
* Converts bech32 string to hex format
|
|
889
|
+
* @param b32 - Bech32 string to convert
|
|
890
|
+
* @returns Hex encoded string
|
|
891
|
+
*/
|
|
430
892
|
export const bech32ToHex = (b32) => utf8.encode(bech32.fromWords(bech32.decode(b32, false).words));
|
|
431
893
|
//# sourceMappingURL=Tools.mjs.map
|