@tally.paws/toolbox 1.2.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/README.md +5 -0
- package/dist/index.d.mts +368 -0
- package/dist/index.d.ts +368 -0
- package/dist/index.js +511 -0
- package/dist/index.mjs +445 -0
- package/package.json +23 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
// src/promises.ts
|
|
2
|
+
function sleep(ms2) {
|
|
3
|
+
return new Promise((resolve) => {
|
|
4
|
+
setTimeout(resolve, ms2);
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
var AsyncQueue = class {
|
|
8
|
+
queue = Promise.resolve();
|
|
9
|
+
run(fn) {
|
|
10
|
+
const res = this.queue.then(fn, fn);
|
|
11
|
+
this.queue = res.then(
|
|
12
|
+
() => {
|
|
13
|
+
},
|
|
14
|
+
() => {
|
|
15
|
+
}
|
|
16
|
+
);
|
|
17
|
+
return res;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
function deferred() {
|
|
21
|
+
let resolve = null;
|
|
22
|
+
let reject = null;
|
|
23
|
+
const promise = new Promise((res, rej) => {
|
|
24
|
+
resolve = res;
|
|
25
|
+
reject = rej;
|
|
26
|
+
});
|
|
27
|
+
return { promise, resolve, reject };
|
|
28
|
+
}
|
|
29
|
+
function timeoutPromise(promise, ms2, error = new Error("Timed out")) {
|
|
30
|
+
return Promise.race([
|
|
31
|
+
promise,
|
|
32
|
+
new Promise((_, reject) => setTimeout(() => reject(error), ms2))
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/functions.ts
|
|
37
|
+
function debounce(fn, delay = 300, options = {}) {
|
|
38
|
+
let timeout = null;
|
|
39
|
+
let lastArgs = null;
|
|
40
|
+
let lastThis;
|
|
41
|
+
let result;
|
|
42
|
+
const debounced = function(...args) {
|
|
43
|
+
lastArgs = args;
|
|
44
|
+
lastThis = this;
|
|
45
|
+
const callNow = options.immediate && !timeout;
|
|
46
|
+
if (timeout) clearTimeout(timeout);
|
|
47
|
+
timeout = setTimeout(() => {
|
|
48
|
+
timeout = null;
|
|
49
|
+
if (!options.immediate && lastArgs) {
|
|
50
|
+
result = fn.apply(lastThis, lastArgs);
|
|
51
|
+
lastArgs = null;
|
|
52
|
+
}
|
|
53
|
+
}, delay);
|
|
54
|
+
if (callNow) {
|
|
55
|
+
result = fn.apply(lastThis, lastArgs);
|
|
56
|
+
lastArgs = null;
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
};
|
|
60
|
+
debounced.cancel = () => {
|
|
61
|
+
if (timeout) clearTimeout(timeout);
|
|
62
|
+
timeout = null;
|
|
63
|
+
lastArgs = null;
|
|
64
|
+
};
|
|
65
|
+
debounced.flush = () => {
|
|
66
|
+
if (timeout) {
|
|
67
|
+
clearTimeout(timeout);
|
|
68
|
+
timeout = null;
|
|
69
|
+
if (lastArgs) {
|
|
70
|
+
fn.apply(lastThis, lastArgs);
|
|
71
|
+
lastArgs = null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
return debounced;
|
|
76
|
+
}
|
|
77
|
+
function throttle(fn, interval = 300) {
|
|
78
|
+
let last = 0;
|
|
79
|
+
let timeout = null;
|
|
80
|
+
return function(...args) {
|
|
81
|
+
const now = Date.now();
|
|
82
|
+
const remaining = interval - (now - last);
|
|
83
|
+
if (remaining <= 0) {
|
|
84
|
+
last = now;
|
|
85
|
+
fn.apply(this, args);
|
|
86
|
+
} else if (!timeout) {
|
|
87
|
+
timeout = setTimeout(() => {
|
|
88
|
+
last = Date.now();
|
|
89
|
+
timeout = null;
|
|
90
|
+
fn.apply(this, args);
|
|
91
|
+
}, remaining);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function deepEqual(a, b) {
|
|
96
|
+
if (Object.is(a, b)) return true;
|
|
97
|
+
if (typeof a !== "object" || typeof b !== "object" || !a || !b) return false;
|
|
98
|
+
const keysA = Object.keys(a);
|
|
99
|
+
if (keysA.length !== Object.keys(b).length) return false;
|
|
100
|
+
return keysA.every((k) => deepEqual(a[k], b[k]));
|
|
101
|
+
}
|
|
102
|
+
function once(fn) {
|
|
103
|
+
let called = false;
|
|
104
|
+
let result;
|
|
105
|
+
return function(...args) {
|
|
106
|
+
if (!called) {
|
|
107
|
+
called = true;
|
|
108
|
+
result = fn.apply(this, args);
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function pick(obj, keys) {
|
|
114
|
+
return Object.fromEntries(keys.map((k) => [k, obj[k]]));
|
|
115
|
+
}
|
|
116
|
+
function omit(obj, keys) {
|
|
117
|
+
const set = new Set(keys);
|
|
118
|
+
return Object.fromEntries(
|
|
119
|
+
Object.entries(obj).filter(([k]) => !set.has(k))
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
async function retry(fn, attempts, delayMs = 0) {
|
|
123
|
+
let lastError;
|
|
124
|
+
for (let i = 0; i < attempts; i++) {
|
|
125
|
+
try {
|
|
126
|
+
return await fn();
|
|
127
|
+
} catch (e) {
|
|
128
|
+
lastError = e;
|
|
129
|
+
if (delayMs) await sleep(delayMs);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
throw lastError;
|
|
133
|
+
}
|
|
134
|
+
var noop = () => {
|
|
135
|
+
};
|
|
136
|
+
function tryCatch(fn) {
|
|
137
|
+
try {
|
|
138
|
+
return [null, fn()];
|
|
139
|
+
} catch (e) {
|
|
140
|
+
return [e];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function tap(fn) {
|
|
144
|
+
return (v) => {
|
|
145
|
+
fn(v);
|
|
146
|
+
return v;
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function* range(end) {
|
|
150
|
+
let start = 0;
|
|
151
|
+
let step = 1;
|
|
152
|
+
let e = 0;
|
|
153
|
+
if (typeof end === "number") {
|
|
154
|
+
e = end;
|
|
155
|
+
} else {
|
|
156
|
+
start = end.start ?? 0;
|
|
157
|
+
step = end.step ?? 1;
|
|
158
|
+
e = end.end;
|
|
159
|
+
}
|
|
160
|
+
if (step === 0) throw new RangeError("step cannot be 0");
|
|
161
|
+
if (step > 0) {
|
|
162
|
+
for (let i = start; i < e; i += step) yield i;
|
|
163
|
+
} else {
|
|
164
|
+
for (let i = start; i > e; i += step) yield i;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function* cycle(iterable) {
|
|
168
|
+
const items = [...iterable];
|
|
169
|
+
if (!items.length) return;
|
|
170
|
+
while (true) {
|
|
171
|
+
for (const i of items) yield i;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function chunk(arr, size) {
|
|
175
|
+
const out = [];
|
|
176
|
+
for (let i = 0; i < arr.length; i += size) out.push(arr.slice(i, i + size));
|
|
177
|
+
return out;
|
|
178
|
+
}
|
|
179
|
+
function shuffle(arr) {
|
|
180
|
+
const a = [...arr];
|
|
181
|
+
for (let i = a.length - 1; i > 0; i--) {
|
|
182
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
183
|
+
[a[i], a[j]] = [a[j], a[i]];
|
|
184
|
+
}
|
|
185
|
+
return a;
|
|
186
|
+
}
|
|
187
|
+
function sample(arr) {
|
|
188
|
+
if (!arr.length) return void 0;
|
|
189
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
190
|
+
}
|
|
191
|
+
function rotate(arr, n) {
|
|
192
|
+
const len = arr.length;
|
|
193
|
+
n = (n % len + len) % len;
|
|
194
|
+
return [...arr.slice(n), ...arr.slice(0, n)];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// src/duration.ts
|
|
198
|
+
var msValues = {
|
|
199
|
+
ms: 1,
|
|
200
|
+
s: 1e3,
|
|
201
|
+
m: 1e3 * 60,
|
|
202
|
+
h: 1e3 * 60 * 60,
|
|
203
|
+
d: 1e3 * 60 * 60 * 24
|
|
204
|
+
};
|
|
205
|
+
function durationLong(initialMs = 0) {
|
|
206
|
+
let total = initialMs;
|
|
207
|
+
const add = (v, mult) => {
|
|
208
|
+
total += v * mult;
|
|
209
|
+
return builder;
|
|
210
|
+
};
|
|
211
|
+
const builder = {
|
|
212
|
+
toMilliseconds: () => total,
|
|
213
|
+
toSeconds: () => total / msValues.s,
|
|
214
|
+
toMinutes: () => total / msValues.m,
|
|
215
|
+
toHours: () => total / msValues.h,
|
|
216
|
+
toDays: () => total / msValues.d,
|
|
217
|
+
milliseconds: (v) => add(v, msValues.ms),
|
|
218
|
+
seconds: (v) => add(v, msValues.s),
|
|
219
|
+
minutes: (v) => add(v, msValues.m),
|
|
220
|
+
hours: (v) => add(v, msValues.h),
|
|
221
|
+
days: (v) => add(v, msValues.d)
|
|
222
|
+
};
|
|
223
|
+
return builder;
|
|
224
|
+
}
|
|
225
|
+
function durationShort(initialMs = 0) {
|
|
226
|
+
let total = initialMs;
|
|
227
|
+
const add = (v, mult) => {
|
|
228
|
+
total += v * mult;
|
|
229
|
+
return builder;
|
|
230
|
+
};
|
|
231
|
+
const builder = {
|
|
232
|
+
toMs: () => total,
|
|
233
|
+
toS: () => total / msValues.s,
|
|
234
|
+
toM: () => total / msValues.m,
|
|
235
|
+
toH: () => total / msValues.h,
|
|
236
|
+
toD: () => total / msValues.d,
|
|
237
|
+
ms: (v) => add(v, msValues.ms),
|
|
238
|
+
s: (v) => add(v, msValues.s),
|
|
239
|
+
m: (v) => add(v, msValues.m),
|
|
240
|
+
h: (v) => add(v, msValues.h),
|
|
241
|
+
d: (v) => add(v, msValues.d)
|
|
242
|
+
};
|
|
243
|
+
return builder;
|
|
244
|
+
}
|
|
245
|
+
function cS(unit) {
|
|
246
|
+
return (v) => durationShort()[unit](v);
|
|
247
|
+
}
|
|
248
|
+
function cL(unit) {
|
|
249
|
+
return (v) => durationLong()[unit](v);
|
|
250
|
+
}
|
|
251
|
+
var days = cL("days");
|
|
252
|
+
var hours = cL("hours");
|
|
253
|
+
var minutes = cL("minutes");
|
|
254
|
+
var seconds = cL("seconds");
|
|
255
|
+
var milliseconds = cL("milliseconds");
|
|
256
|
+
var d = cS("d");
|
|
257
|
+
var h = cS("h");
|
|
258
|
+
var m = cS("m");
|
|
259
|
+
var s = cS("s");
|
|
260
|
+
var ms = cS("ms");
|
|
261
|
+
|
|
262
|
+
// src/numbers.ts
|
|
263
|
+
function bigIntPower(one, two) {
|
|
264
|
+
if (two === 0n) return 1n;
|
|
265
|
+
const powerTwo = bigIntPower(one, two / 2n);
|
|
266
|
+
if (two % 2n === 0n) return powerTwo * powerTwo;
|
|
267
|
+
return one * powerTwo * powerTwo;
|
|
268
|
+
}
|
|
269
|
+
function convertBase(value, sourceBase, outBase, chars = convertBase.defaultChars) {
|
|
270
|
+
const range2 = [...chars];
|
|
271
|
+
if (sourceBase < 2 || sourceBase > range2.length)
|
|
272
|
+
throw new RangeError(`sourceBase must be between 2 and ${range2.length}`);
|
|
273
|
+
if (outBase < 2 || outBase > range2.length)
|
|
274
|
+
throw new RangeError(`outBase must be between 2 and ${range2.length}`);
|
|
275
|
+
const outBaseBig = BigInt(outBase);
|
|
276
|
+
let decValue = [...value].toReversed().reduce((carry, digit, loopIndex) => {
|
|
277
|
+
const biggestBaseIndex = range2.indexOf(digit);
|
|
278
|
+
if (biggestBaseIndex === -1 || biggestBaseIndex > sourceBase - 1)
|
|
279
|
+
throw new ReferenceError(
|
|
280
|
+
`Invalid digit ${digit} for base ${sourceBase}.`
|
|
281
|
+
);
|
|
282
|
+
return carry + BigInt(biggestBaseIndex) * bigIntPower(BigInt(sourceBase), BigInt(loopIndex));
|
|
283
|
+
}, 0n);
|
|
284
|
+
let output = "";
|
|
285
|
+
while (decValue > 0) {
|
|
286
|
+
output = `${range2[Number(decValue % outBaseBig)] ?? ""}${output}`;
|
|
287
|
+
decValue = (decValue - decValue % outBaseBig) / outBaseBig;
|
|
288
|
+
}
|
|
289
|
+
return output || "0";
|
|
290
|
+
}
|
|
291
|
+
convertBase.defaultChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-/=[];',.";
|
|
292
|
+
convertBase.MAX_BASE = convertBase.defaultChars.length;
|
|
293
|
+
function clamp(number, min, max) {
|
|
294
|
+
return Math.max(min, Math.min(max, number));
|
|
295
|
+
}
|
|
296
|
+
function randInt(min, max, inclusive = true) {
|
|
297
|
+
if (min > max) {
|
|
298
|
+
throw new RangeError("RandInt: min cannot be greater than max");
|
|
299
|
+
}
|
|
300
|
+
return Math.floor(Math.random() * (max - min + +inclusive)) + min;
|
|
301
|
+
}
|
|
302
|
+
function chance(probability) {
|
|
303
|
+
return Math.random() < probability;
|
|
304
|
+
}
|
|
305
|
+
function roundTo(n, decimals) {
|
|
306
|
+
const f = 10 ** decimals;
|
|
307
|
+
return Math.round(n * f) / f;
|
|
308
|
+
}
|
|
309
|
+
function lerp(a, b, t) {
|
|
310
|
+
return a + (b - a) * t;
|
|
311
|
+
}
|
|
312
|
+
function inRange(n, min, max) {
|
|
313
|
+
return n >= min && n <= max;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// src/class.ts
|
|
317
|
+
var TimedMap = class {
|
|
318
|
+
constructor(defaultTtlMs) {
|
|
319
|
+
this.defaultTtlMs = defaultTtlMs;
|
|
320
|
+
}
|
|
321
|
+
defaultTtlMs;
|
|
322
|
+
map = /* @__PURE__ */ new Map();
|
|
323
|
+
timers = /* @__PURE__ */ new Map();
|
|
324
|
+
set(key, value, ttlMs = this.defaultTtlMs) {
|
|
325
|
+
this.map.set(key, value);
|
|
326
|
+
const timer = setTimeout(() => {
|
|
327
|
+
this.map.delete(key);
|
|
328
|
+
this.timers.delete(key);
|
|
329
|
+
}, ttlMs);
|
|
330
|
+
this.timers.set(key, timer);
|
|
331
|
+
}
|
|
332
|
+
has(key) {
|
|
333
|
+
return this.map.has(key);
|
|
334
|
+
}
|
|
335
|
+
clear() {
|
|
336
|
+
for (const timer of this.timers.values()) {
|
|
337
|
+
clearTimeout(timer);
|
|
338
|
+
}
|
|
339
|
+
this.timers.clear();
|
|
340
|
+
this.map.clear();
|
|
341
|
+
}
|
|
342
|
+
get(key) {
|
|
343
|
+
return this.map.get(key);
|
|
344
|
+
}
|
|
345
|
+
delete(key) {
|
|
346
|
+
const timer = this.timers.get(key);
|
|
347
|
+
if (timer) clearTimeout(timer);
|
|
348
|
+
this.timers.delete(key);
|
|
349
|
+
return this.map.delete(key);
|
|
350
|
+
}
|
|
351
|
+
get size() {
|
|
352
|
+
return this.map.size;
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
var AccessMap = class {
|
|
356
|
+
constructor(defaultTtlMs) {
|
|
357
|
+
this.defaultTtlMs = defaultTtlMs;
|
|
358
|
+
}
|
|
359
|
+
defaultTtlMs;
|
|
360
|
+
map = /* @__PURE__ */ new Map();
|
|
361
|
+
timers = /* @__PURE__ */ new Map();
|
|
362
|
+
set(key, value, ttlMs = this.defaultTtlMs) {
|
|
363
|
+
this.map.set(key, value);
|
|
364
|
+
this.resetTimer(key, ttlMs);
|
|
365
|
+
}
|
|
366
|
+
has(key) {
|
|
367
|
+
return this.map.has(key);
|
|
368
|
+
}
|
|
369
|
+
clear() {
|
|
370
|
+
for (const timer of this.timers.values()) {
|
|
371
|
+
clearTimeout(timer);
|
|
372
|
+
}
|
|
373
|
+
this.timers.clear();
|
|
374
|
+
this.map.clear();
|
|
375
|
+
}
|
|
376
|
+
get(key) {
|
|
377
|
+
const value = this.map.get(key);
|
|
378
|
+
if (value !== void 0) {
|
|
379
|
+
this.resetTimer(key);
|
|
380
|
+
}
|
|
381
|
+
return value;
|
|
382
|
+
}
|
|
383
|
+
delete(key) {
|
|
384
|
+
const timer = this.timers.get(key);
|
|
385
|
+
if (timer) clearTimeout(timer);
|
|
386
|
+
this.timers.delete(key);
|
|
387
|
+
return this.map.delete(key);
|
|
388
|
+
}
|
|
389
|
+
get size() {
|
|
390
|
+
return this.map.size;
|
|
391
|
+
}
|
|
392
|
+
resetTimer(key, ttlMs = this.defaultTtlMs) {
|
|
393
|
+
const timer = this.timers.get(key);
|
|
394
|
+
if (timer) clearTimeout(timer);
|
|
395
|
+
const newTimer = setTimeout(() => {
|
|
396
|
+
this.map.delete(key);
|
|
397
|
+
this.timers.delete(key);
|
|
398
|
+
}, ttlMs);
|
|
399
|
+
this.timers.set(key, newTimer);
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
export {
|
|
403
|
+
AccessMap,
|
|
404
|
+
AsyncQueue,
|
|
405
|
+
TimedMap,
|
|
406
|
+
bigIntPower,
|
|
407
|
+
chance,
|
|
408
|
+
chunk,
|
|
409
|
+
clamp,
|
|
410
|
+
convertBase,
|
|
411
|
+
cycle,
|
|
412
|
+
d,
|
|
413
|
+
days,
|
|
414
|
+
debounce,
|
|
415
|
+
deepEqual,
|
|
416
|
+
deferred,
|
|
417
|
+
h,
|
|
418
|
+
hours,
|
|
419
|
+
inRange,
|
|
420
|
+
lerp,
|
|
421
|
+
m,
|
|
422
|
+
milliseconds,
|
|
423
|
+
minutes,
|
|
424
|
+
ms,
|
|
425
|
+
noop,
|
|
426
|
+
omit,
|
|
427
|
+
once,
|
|
428
|
+
pick,
|
|
429
|
+
randInt,
|
|
430
|
+
range,
|
|
431
|
+
retry,
|
|
432
|
+
rotate,
|
|
433
|
+
roundTo,
|
|
434
|
+
s,
|
|
435
|
+
sample,
|
|
436
|
+
seconds,
|
|
437
|
+
shuffle,
|
|
438
|
+
sleep,
|
|
439
|
+
tap,
|
|
440
|
+
throttle,
|
|
441
|
+
timeoutPromise,
|
|
442
|
+
tryCatch
|
|
443
|
+
};
|
|
444
|
+
//! days(12).h(5).s(4).toS();
|
|
445
|
+
//! d(12).hours(5).seconds(4).toS();
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tally.paws/toolbox",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Core utils and helpers for nodejs",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.mjs",
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsup src/index.ts --format esm,cjs --dts"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist", "README.md"
|
|
19
|
+
],
|
|
20
|
+
"keywords": ["utility", "debounce", "sleep"],
|
|
21
|
+
"author": "",
|
|
22
|
+
"license": "ISC"
|
|
23
|
+
}
|