qznt 1.0.36 → 2.0.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 +29 -58
- package/dist/index.cjs +493 -646
- package/dist/index.d.cts +670 -0
- package/dist/index.d.ts +368 -530
- package/dist/index.js +449 -607
- package/package.json +6 -8
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.mts +0 -832
- package/dist/index.js.map +0 -1
- package/dist/metafile-cjs.json +0 -1
- package/dist/metafile-esm.json +0 -1
package/dist/index.js
CHANGED
|
@@ -1,47 +1,251 @@
|
|
|
1
|
-
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
// src/Cache.ts
|
|
2
|
+
var Cache = class {
|
|
3
|
+
cache = /* @__PURE__ */ new Map();
|
|
4
|
+
interval;
|
|
5
|
+
/**
|
|
6
|
+
* A lightweight, high-performant in-memory cache.
|
|
7
|
+
* Uses Map for O(1) lookups and an optional cleanup interval.
|
|
8
|
+
* @param cleanupMs The interval in milliseconds to run the cleanup function. [default: 60000 (1 minute)]
|
|
9
|
+
*/
|
|
10
|
+
constructor(cleanupMs = 6e4) {
|
|
11
|
+
if (cleanupMs > 0) {
|
|
12
|
+
this.interval = setInterval(() => this.cleanup(), cleanupMs);
|
|
13
|
+
if (this.interval.unref) this.interval.unref();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
set(key, value, ttlMs) {
|
|
17
|
+
this.cache.set(key, {
|
|
18
|
+
value,
|
|
19
|
+
expiresAt: ttlMs ? Date.now() + ttlMs : null
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
get(key) {
|
|
23
|
+
const data = this.cache.get(key);
|
|
24
|
+
if (!data) return null;
|
|
25
|
+
if (data.expiresAt && Date.now() > data.expiresAt) {
|
|
26
|
+
this.cache.delete(key);
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return data.value;
|
|
30
|
+
}
|
|
31
|
+
cleanup() {
|
|
32
|
+
if (this.cache.size === 0) return;
|
|
33
|
+
const now = Date.now();
|
|
34
|
+
let keysProcessed = 0;
|
|
35
|
+
const maxKeysToScan = 20;
|
|
36
|
+
for (const [key, data] of this.cache) {
|
|
37
|
+
if (data.expiresAt && now > data.expiresAt) {
|
|
38
|
+
this.cache.delete(key);
|
|
39
|
+
}
|
|
40
|
+
keysProcessed++;
|
|
41
|
+
if (keysProcessed >= maxKeysToScan) break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
clear() {
|
|
45
|
+
this.cache.clear();
|
|
46
|
+
}
|
|
5
47
|
};
|
|
6
48
|
|
|
7
|
-
// src/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
49
|
+
// src/Loop.ts
|
|
50
|
+
import EventEmitter from "events";
|
|
51
|
+
var TypedEmitterBase = EventEmitter;
|
|
52
|
+
var Loop = class extends TypedEmitterBase {
|
|
53
|
+
_state = "stopped";
|
|
54
|
+
timeoutId = null;
|
|
55
|
+
delay;
|
|
56
|
+
fn;
|
|
57
|
+
startTime = 0;
|
|
58
|
+
remaining = 0;
|
|
59
|
+
async run() {
|
|
60
|
+
const currentState = this._state;
|
|
61
|
+
if (currentState === "stopped" || currentState === "paused") return;
|
|
62
|
+
try {
|
|
63
|
+
const result = await this.fn(this);
|
|
64
|
+
this.emit("tick", result);
|
|
65
|
+
} catch (err) {
|
|
66
|
+
this.emit("error", err);
|
|
67
|
+
}
|
|
68
|
+
if (this._state === "running") {
|
|
69
|
+
this.startTime = Date.now();
|
|
70
|
+
this.remaining = 0;
|
|
71
|
+
this.clearTimer();
|
|
72
|
+
this.timeoutId = setTimeout(() => this.run(), this.delay);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
clearTimer() {
|
|
76
|
+
if (this.timeoutId) {
|
|
77
|
+
clearTimeout(this.timeoutId);
|
|
78
|
+
this.timeoutId = null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Creates an interval. If the function is async, it will wait for it to complete before scheduling the next run.
|
|
83
|
+
* @param fn The function to run.
|
|
84
|
+
* @param delay The delay between runs in milliseconds.
|
|
85
|
+
* @param immediate Whether to start the loop immediately. [default: true]
|
|
86
|
+
*/
|
|
87
|
+
constructor(fn, delay, immediate = true) {
|
|
88
|
+
super();
|
|
89
|
+
this.fn = fn;
|
|
90
|
+
this.delay = delay;
|
|
91
|
+
if (immediate) this.start();
|
|
92
|
+
}
|
|
93
|
+
get state() {
|
|
94
|
+
return this._state;
|
|
95
|
+
}
|
|
96
|
+
/** Starts the loop. */
|
|
97
|
+
start() {
|
|
98
|
+
if (this._state !== "stopped") return;
|
|
99
|
+
this._state = "running";
|
|
100
|
+
this.emit("start");
|
|
101
|
+
this.run();
|
|
102
|
+
}
|
|
103
|
+
/** Resumes a paused loop. */
|
|
104
|
+
resume() {
|
|
105
|
+
if (this._state !== "paused") return;
|
|
106
|
+
this._state = "running";
|
|
107
|
+
this.emit("resume");
|
|
108
|
+
if (this.remaining <= 0) {
|
|
109
|
+
this.run();
|
|
110
|
+
} else {
|
|
111
|
+
this.timeoutId = setTimeout(() => this.run(), this.remaining);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/** Stops the loop. */
|
|
115
|
+
stop() {
|
|
116
|
+
const wasRunning = this._state !== "stopped";
|
|
117
|
+
this._state = "stopped";
|
|
118
|
+
this.remaining = 0;
|
|
119
|
+
this.clearTimer();
|
|
120
|
+
if (wasRunning) this.emit("stop");
|
|
121
|
+
}
|
|
122
|
+
/** Pauses the execution. */
|
|
123
|
+
pause() {
|
|
124
|
+
if (this._state !== "running") return;
|
|
125
|
+
this._state = "paused";
|
|
126
|
+
const elapsed = Date.now() - this.startTime;
|
|
127
|
+
this.remaining = Math.max(0, this.delay - elapsed);
|
|
128
|
+
this.emit("pause", { remaining: this.remaining });
|
|
129
|
+
this.clearTimer();
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Sets the delay between runs
|
|
133
|
+
* @param ms The new delay in milliseconds.
|
|
134
|
+
*/
|
|
135
|
+
setDelay(ms) {
|
|
136
|
+
this.delay = ms;
|
|
137
|
+
}
|
|
138
|
+
/** Manually trigger the function once without affecting the loop. */
|
|
139
|
+
async execute() {
|
|
140
|
+
await this.fn(this);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// src/Pipe.ts
|
|
145
|
+
function Pipe(value, ...fns) {
|
|
146
|
+
return fns.reduce((acc, fn) => fn(acc), value);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/Storage.ts
|
|
150
|
+
import fs from "fs";
|
|
151
|
+
import path from "path";
|
|
152
|
+
var Storage = class {
|
|
153
|
+
isNode = typeof window === "undefined";
|
|
154
|
+
filePath = null;
|
|
155
|
+
memoryCache = /* @__PURE__ */ new Map();
|
|
156
|
+
loadFromFile() {
|
|
157
|
+
if (this.filePath && fs.existsSync(this.filePath)) {
|
|
158
|
+
try {
|
|
159
|
+
const data = JSON.parse(fs.readFileSync(this.filePath, "utf-8"));
|
|
160
|
+
Object.entries(data).forEach(([k, v]) => this.memoryCache.set(k, JSON.stringify(v)));
|
|
161
|
+
} catch (err) {
|
|
162
|
+
console.error(`Store: Failed to load file '${this.filePath}'`, err);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
persist() {
|
|
167
|
+
if (this.isNode && this.filePath) {
|
|
168
|
+
const out = {};
|
|
169
|
+
this.memoryCache.forEach((v, k) => out[k] = JSON.parse(v));
|
|
170
|
+
fs.writeFileSync(this.filePath, JSON.stringify(out, null, 2));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* A lightweight, high-performant persistent storage system.
|
|
175
|
+
* Uses JSON files in Node.js, localStorage in the browser
|
|
176
|
+
* @param fileName Only used in Node.js to create a persistent .json file
|
|
177
|
+
* @param directory The directory for the file. Defaults to current working directory
|
|
178
|
+
*/
|
|
179
|
+
constructor(fileName, directory = process.cwd()) {
|
|
180
|
+
if (this.isNode && fileName) {
|
|
181
|
+
this.filePath = path.join(directory, fileName.endsWith(".json") ? fileName : `${fileName}.json`);
|
|
182
|
+
this.loadFromFile();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
has(key) {
|
|
186
|
+
if (!this.isNode && window.localStorage) {
|
|
187
|
+
return localStorage.getItem(key) !== null;
|
|
188
|
+
}
|
|
189
|
+
return this.memoryCache.has(key);
|
|
190
|
+
}
|
|
191
|
+
get(key) {
|
|
192
|
+
let raw = null;
|
|
193
|
+
if (!this.isNode && window.localStorage) {
|
|
194
|
+
raw = localStorage.getItem(key);
|
|
195
|
+
} else {
|
|
196
|
+
raw = this.memoryCache.get(key) || null;
|
|
197
|
+
}
|
|
198
|
+
if (!raw) return null;
|
|
199
|
+
const payload = JSON.parse(raw);
|
|
200
|
+
if (payload.expiry && Date.now() > payload.expiry) {
|
|
201
|
+
this.remove(key);
|
|
202
|
+
this.persist();
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
return payload.value;
|
|
206
|
+
}
|
|
207
|
+
set(key, value, ttl) {
|
|
208
|
+
const payload = {
|
|
209
|
+
value,
|
|
210
|
+
expiry: ttl ? Date.now() + ttl : null
|
|
211
|
+
};
|
|
212
|
+
const serialized = JSON.stringify(payload);
|
|
213
|
+
if (!this.isNode && window.localStorage) {
|
|
214
|
+
localStorage.setItem(key, serialized);
|
|
215
|
+
} else {
|
|
216
|
+
this.memoryCache.set(key, serialized);
|
|
217
|
+
this.persist();
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
remove(key) {
|
|
221
|
+
if (!this.isNode && window.localStorage) {
|
|
222
|
+
localStorage.removeItem(key);
|
|
223
|
+
} else {
|
|
224
|
+
this.memoryCache.delete(key);
|
|
225
|
+
this.persist();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
clear() {
|
|
229
|
+
if (!this.isNode && window.localStorage) {
|
|
230
|
+
localStorage.clear();
|
|
231
|
+
} else {
|
|
232
|
+
this.memoryCache.clear();
|
|
233
|
+
this.persist();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
};
|
|
21
237
|
|
|
22
|
-
// src/
|
|
23
|
-
var rnd_exports = {};
|
|
24
|
-
__export(rnd_exports, {
|
|
25
|
-
chance: () => chance,
|
|
26
|
-
choice: () => choice,
|
|
27
|
-
float: () => float,
|
|
28
|
-
index: () => index,
|
|
29
|
-
int: () => int,
|
|
30
|
-
prng: () => prng,
|
|
31
|
-
sampler: () => sampler,
|
|
32
|
-
str: () => str,
|
|
33
|
-
weighted: () => weighted
|
|
34
|
-
});
|
|
238
|
+
// src/random.ts
|
|
35
239
|
var LOWER = "abcdefghijklmnopqrstuvwxyz";
|
|
36
240
|
var UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
37
241
|
var NUM = "0123456789";
|
|
38
|
-
function
|
|
242
|
+
function rndChance(percent2 = 0.5, seed) {
|
|
39
243
|
if (percent2 <= 0) return false;
|
|
40
244
|
if (percent2 >= 1) return true;
|
|
41
245
|
const random = seed !== void 0 ? prng(seed) : Math.random;
|
|
42
246
|
return random() < percent2;
|
|
43
247
|
}
|
|
44
|
-
function
|
|
248
|
+
function rndChoice(array, options = {}) {
|
|
45
249
|
const { seed, not, maxRerolls = 10 } = options;
|
|
46
250
|
const random = seed !== void 0 ? prng(seed) : Math.random;
|
|
47
251
|
const rnd = () => array[Math.floor(random() * array.length)];
|
|
@@ -56,19 +260,19 @@ function choice(array, options = {}) {
|
|
|
56
260
|
}
|
|
57
261
|
return result;
|
|
58
262
|
}
|
|
59
|
-
function
|
|
263
|
+
function weightedRnd(array, predicate, seed) {
|
|
60
264
|
const random = seed !== void 0 ? prng(seed) : Math.random;
|
|
61
265
|
const cumulativeWeights = [];
|
|
62
266
|
let currentSum = 0;
|
|
63
267
|
for (const item of array) {
|
|
64
|
-
const weight =
|
|
268
|
+
const weight = predicate(item);
|
|
65
269
|
currentSum += weight;
|
|
66
270
|
cumulativeWeights.push(currentSum);
|
|
67
271
|
}
|
|
68
272
|
const decider = random() * currentSum;
|
|
69
|
-
let
|
|
273
|
+
let index;
|
|
70
274
|
if (array.length < 20) {
|
|
71
|
-
|
|
275
|
+
index = cumulativeWeights.findIndex((w) => w >= decider);
|
|
72
276
|
} else {
|
|
73
277
|
let low = 0;
|
|
74
278
|
let high = cumulativeWeights.length - 1;
|
|
@@ -80,16 +284,16 @@ function weighted(array, selector, seed) {
|
|
|
80
284
|
high = mid;
|
|
81
285
|
}
|
|
82
286
|
}
|
|
83
|
-
|
|
287
|
+
index = low;
|
|
84
288
|
}
|
|
85
|
-
return array[
|
|
289
|
+
return array[index];
|
|
86
290
|
}
|
|
87
|
-
function
|
|
291
|
+
function createSampler(items, predicate, seed) {
|
|
88
292
|
const callRandom = seed ? prng(seed) : void 0;
|
|
89
293
|
const len = items.length;
|
|
90
294
|
const prob = new Array(len);
|
|
91
295
|
const alias = new Array(len);
|
|
92
|
-
const weights = items.map(
|
|
296
|
+
const weights = items.map(predicate);
|
|
93
297
|
const totalWeight = weights.reduce((a, b) => a + b, 0);
|
|
94
298
|
const scaledWeights = weights.map((w) => w * len / totalWeight);
|
|
95
299
|
const small = [];
|
|
@@ -107,8 +311,8 @@ function sampler(items, selector, seed) {
|
|
|
107
311
|
while (small.length) prob[small.pop()] = 1;
|
|
108
312
|
return {
|
|
109
313
|
/**
|
|
110
|
-
* Returns a random item from the given array in O(1) time
|
|
111
|
-
* @param seed Optional seed for RNG
|
|
314
|
+
* Returns a random item from the given array in O(1) time
|
|
315
|
+
* @param seed Optional seed for RNG
|
|
112
316
|
*/
|
|
113
317
|
pick: (seed2) => {
|
|
114
318
|
const random = seed2 !== void 0 ? prng(seed2) : callRandom || Math.random;
|
|
@@ -125,11 +329,11 @@ function prng(seed) {
|
|
|
125
329
|
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
126
330
|
};
|
|
127
331
|
}
|
|
128
|
-
function
|
|
332
|
+
function rndFloat(min, max, seed) {
|
|
129
333
|
const random = seed !== void 0 ? prng(seed) : Math.random;
|
|
130
334
|
return random() * (max - min) + min;
|
|
131
335
|
}
|
|
132
|
-
function
|
|
336
|
+
function rndIndex(array, options = {}) {
|
|
133
337
|
const { seed, not, maxRerolls = 10 } = options;
|
|
134
338
|
const random = seed !== void 0 ? prng(seed) : Math.random;
|
|
135
339
|
const rnd = () => Math.floor(random() * array.length);
|
|
@@ -144,11 +348,11 @@ function index(array, options = {}) {
|
|
|
144
348
|
}
|
|
145
349
|
return result;
|
|
146
350
|
}
|
|
147
|
-
function
|
|
351
|
+
function rndInt(min, max, seed) {
|
|
148
352
|
const random = seed !== void 0 ? prng(seed) : Math.random;
|
|
149
353
|
return Math.floor(random() * (max - min + 1)) + min;
|
|
150
354
|
}
|
|
151
|
-
function
|
|
355
|
+
function rndString(len, mode, options = {}) {
|
|
152
356
|
const { casing = "lower", seed, customChars = "", exclude = "" } = options;
|
|
153
357
|
const random = seed !== void 0 ? prng(seed) : Math.random;
|
|
154
358
|
const alphaPool = { lower: LOWER, upper: UPPER, mixed: LOWER + UPPER }[casing];
|
|
@@ -217,7 +421,7 @@ function cluster(array, iteratee, maxChunkSize) {
|
|
|
217
421
|
}
|
|
218
422
|
return result;
|
|
219
423
|
}
|
|
220
|
-
function
|
|
424
|
+
function compactArray(array, mode = "nullable") {
|
|
221
425
|
if (mode === "falsy") {
|
|
222
426
|
return array.filter(Boolean);
|
|
223
427
|
}
|
|
@@ -226,7 +430,7 @@ function compact(array, mode = "nullable") {
|
|
|
226
430
|
function forceArray(item) {
|
|
227
431
|
return Array.isArray(item) ? item : [item];
|
|
228
432
|
}
|
|
229
|
-
function
|
|
433
|
+
function searchSorted(array, target, comparator = (a, b) => a > b ? 1 : a < b ? -1 : 0) {
|
|
230
434
|
let low = 0;
|
|
231
435
|
let high = array.length - 1;
|
|
232
436
|
while (low <= high) {
|
|
@@ -289,13 +493,8 @@ function unique(array, key) {
|
|
|
289
493
|
}
|
|
290
494
|
|
|
291
495
|
// src/async.ts
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
retry: () => retry,
|
|
295
|
-
wait: () => wait
|
|
296
|
-
});
|
|
297
|
-
async function retry(fn, options = {}) {
|
|
298
|
-
const { retries = 3, delay = 500, timeout, signal } = options;
|
|
496
|
+
async function retryPromise(fn, options = {}) {
|
|
497
|
+
const { attempts = 3, delay = 500, timeout, signal } = options;
|
|
299
498
|
if (signal?.aborted) throw new Error("Operation aborted");
|
|
300
499
|
const executeWithTimeout = async () => {
|
|
301
500
|
if (!timeout) return fn(signal);
|
|
@@ -314,7 +513,7 @@ async function retry(fn, options = {}) {
|
|
|
314
513
|
return await executeWithTimeout();
|
|
315
514
|
} catch (error) {
|
|
316
515
|
if (signal?.aborted) throw error;
|
|
317
|
-
if (
|
|
516
|
+
if (attempts <= 0) throw error;
|
|
318
517
|
const jitter = Math.random() * 200;
|
|
319
518
|
const totalDelay = delay + jitter;
|
|
320
519
|
await new Promise((resolve, reject) => {
|
|
@@ -328,51 +527,14 @@ async function retry(fn, options = {}) {
|
|
|
328
527
|
{ once: true }
|
|
329
528
|
);
|
|
330
529
|
});
|
|
331
|
-
return
|
|
530
|
+
return retryPromise(fn, { ...options, attempts: attempts - 1, delay: delay * 2 });
|
|
332
531
|
}
|
|
333
532
|
}
|
|
334
|
-
function wait(
|
|
335
|
-
return new Promise(
|
|
336
|
-
(resolve) => setTimeout(() => {
|
|
337
|
-
resolve(true);
|
|
338
|
-
}, ms2)
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// src/fn.ts
|
|
343
|
-
var fn_exports = {};
|
|
344
|
-
__export(fn_exports, {
|
|
345
|
-
memoize: () => memoize
|
|
346
|
-
});
|
|
347
|
-
function memoize(fn, options = {}) {
|
|
348
|
-
const cache = /* @__PURE__ */ new Map();
|
|
349
|
-
const { resolver, maxAge } = options;
|
|
350
|
-
const memoized = function(...args) {
|
|
351
|
-
const key = resolver ? resolver(...args) : JSON.stringify(args);
|
|
352
|
-
const now = Date.now();
|
|
353
|
-
const entry = cache.get(key);
|
|
354
|
-
if (entry) {
|
|
355
|
-
if (!maxAge || now - entry.timestamp < maxAge) {
|
|
356
|
-
return entry.value;
|
|
357
|
-
}
|
|
358
|
-
cache.delete(key);
|
|
359
|
-
}
|
|
360
|
-
const result = fn.apply(this, args);
|
|
361
|
-
cache.set(key, { value: result, timestamp: now });
|
|
362
|
-
return result;
|
|
363
|
-
};
|
|
364
|
-
memoized.clear = () => cache.clear();
|
|
365
|
-
return memoized;
|
|
533
|
+
function wait(ms) {
|
|
534
|
+
return new Promise((resolve) => setTimeout(() => resolve(true), ms));
|
|
366
535
|
}
|
|
367
536
|
|
|
368
537
|
// src/date.ts
|
|
369
|
-
var date_exports = {};
|
|
370
|
-
__export(date_exports, {
|
|
371
|
-
duration: () => duration,
|
|
372
|
-
eta: () => eta,
|
|
373
|
-
getAge: () => getAge,
|
|
374
|
-
parse: () => parse
|
|
375
|
-
});
|
|
376
538
|
var MS_MAP = {
|
|
377
539
|
ms: 1,
|
|
378
540
|
s: 1e3,
|
|
@@ -383,64 +545,18 @@ var MS_MAP = {
|
|
|
383
545
|
mth: 24192e5,
|
|
384
546
|
y: 31536e6
|
|
385
547
|
};
|
|
386
|
-
function duration(target, style = "hms", options = {}) {
|
|
387
|
-
const targetMs = target instanceof Date ? target.getTime() : Number(target);
|
|
388
|
-
const sinceMs = options.since instanceof Date ? options.since.getTime() : Number(options.since) || Date.now();
|
|
389
|
-
const diff = Math.abs(targetMs - sinceMs);
|
|
390
|
-
if (diff === 0) return style === "digital" ? "00:00" : "now";
|
|
391
|
-
const s = Math.floor(diff / 1e3) % 60;
|
|
392
|
-
const m = Math.floor(diff / 6e4) % 60;
|
|
393
|
-
const h = Math.floor(diff / 36e5) % 24;
|
|
394
|
-
const d = Math.floor(diff / 864e5);
|
|
395
|
-
if (style === "digital") {
|
|
396
|
-
const parts = [m, s].map((v) => String(v).padStart(2, "0"));
|
|
397
|
-
if (h > 0 || d > 0) parts.unshift(String(h).padStart(2, "0"));
|
|
398
|
-
if (d > 0) parts.unshift(String(d));
|
|
399
|
-
return parts.join(":");
|
|
400
|
-
}
|
|
401
|
-
const result = [];
|
|
402
|
-
const push = (val, label) => {
|
|
403
|
-
if (val > 0) result.push(`${val} ${label}${val === 1 ? "" : "s"}`);
|
|
404
|
-
};
|
|
405
|
-
if (style === "ymdhms") push(d, "day");
|
|
406
|
-
push(h, "hour");
|
|
407
|
-
push(m, "minute");
|
|
408
|
-
push(s, "second");
|
|
409
|
-
if (result.length === 0) return "0 seconds";
|
|
410
|
-
if (result.length === 1) return result[0];
|
|
411
|
-
const last = result.pop();
|
|
412
|
-
return `${result.join(", ")} and ${last}`;
|
|
413
|
-
}
|
|
414
|
-
function eta(date, locale) {
|
|
415
|
-
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });
|
|
416
|
-
const elapsed = (typeof date === "number" ? date : date.getTime()) - Date.now();
|
|
417
|
-
const units = [
|
|
418
|
-
{ unit: "year", ms: 31536e6 },
|
|
419
|
-
{ unit: "month", ms: 2628e6 },
|
|
420
|
-
{ unit: "day", ms: 864e5 },
|
|
421
|
-
{ unit: "hour", ms: 36e5 },
|
|
422
|
-
{ unit: "minute", ms: 6e4 },
|
|
423
|
-
{ unit: "second", ms: 1e3 }
|
|
424
|
-
];
|
|
425
|
-
for (const { unit, ms: ms2 } of units) {
|
|
426
|
-
if (Math.abs(elapsed) >= ms2 || unit === "second") {
|
|
427
|
-
return rtf.format(Math.round(elapsed / ms2), unit);
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
return "";
|
|
431
|
-
}
|
|
432
548
|
function getAge(birthdate) {
|
|
433
|
-
const
|
|
434
|
-
let age =
|
|
435
|
-
const monthDiff =
|
|
436
|
-
if (monthDiff < 0 || monthDiff === 0 &&
|
|
549
|
+
const today = /* @__PURE__ */ new Date();
|
|
550
|
+
let age = today.getFullYear() - birthdate.getFullYear();
|
|
551
|
+
const monthDiff = today.getMonth() - birthdate.getMonth();
|
|
552
|
+
if (monthDiff < 0 || monthDiff === 0 && today.getDate() < birthdate.getDate()) {
|
|
437
553
|
age--;
|
|
438
554
|
}
|
|
439
555
|
return age;
|
|
440
556
|
}
|
|
441
|
-
function
|
|
442
|
-
if (typeof
|
|
443
|
-
const matches =
|
|
557
|
+
function parseTime(str, options = {}) {
|
|
558
|
+
if (typeof str === "number") return str;
|
|
559
|
+
const matches = str.matchAll(/(-?\d+)([a-z]+)/gi);
|
|
444
560
|
let totalMs = 0;
|
|
445
561
|
let found = false;
|
|
446
562
|
for (const [_, value, unit] of matches) {
|
|
@@ -451,39 +567,85 @@ function parse(str2, options = {}) {
|
|
|
451
567
|
found = true;
|
|
452
568
|
}
|
|
453
569
|
}
|
|
454
|
-
if (!found) throw new Error(`parse: Invalid time format: "${
|
|
570
|
+
if (!found) throw new Error(`parse: Invalid time format: "${str}"`);
|
|
455
571
|
const result = options.unit === "s" ? totalMs / 1e3 : totalMs;
|
|
456
572
|
return options.fromNow ? Date.now() + result : result;
|
|
457
573
|
}
|
|
458
574
|
|
|
575
|
+
// src/exec.ts
|
|
576
|
+
function debounce(fn, wait2, options = {}) {
|
|
577
|
+
let timeoutId;
|
|
578
|
+
const leading = options.immediate ?? false;
|
|
579
|
+
const debounced = function(...args) {
|
|
580
|
+
const callNow = leading && !timeoutId;
|
|
581
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
582
|
+
timeoutId = setTimeout(() => {
|
|
583
|
+
timeoutId = void 0;
|
|
584
|
+
if (!leading) fn.apply(this, args);
|
|
585
|
+
}, wait2);
|
|
586
|
+
if (callNow) fn.apply(this, args);
|
|
587
|
+
};
|
|
588
|
+
debounced.cancel = () => {
|
|
589
|
+
if (timeoutId) {
|
|
590
|
+
clearTimeout(timeoutId);
|
|
591
|
+
timeoutId = void 0;
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
return debounced;
|
|
595
|
+
}
|
|
596
|
+
function throttle(fn, limit) {
|
|
597
|
+
let inThrottle = false;
|
|
598
|
+
return function(...args) {
|
|
599
|
+
if (!inThrottle) {
|
|
600
|
+
fn.apply(this, args);
|
|
601
|
+
inThrottle = true;
|
|
602
|
+
setTimeout(() => inThrottle = false, limit);
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// src/fn.ts
|
|
608
|
+
function memoize(fn, options = {}) {
|
|
609
|
+
const cache = /* @__PURE__ */ new Map();
|
|
610
|
+
const { resolver, maxAge } = options;
|
|
611
|
+
const memoized = function(...args) {
|
|
612
|
+
const key = resolver ? resolver(...args) : JSON.stringify(args);
|
|
613
|
+
const now = Date.now();
|
|
614
|
+
const entry = cache.get(key);
|
|
615
|
+
if (entry) {
|
|
616
|
+
if (!maxAge || now - entry.timestamp < maxAge) {
|
|
617
|
+
return entry.value;
|
|
618
|
+
}
|
|
619
|
+
cache.delete(key);
|
|
620
|
+
}
|
|
621
|
+
const result = fn.apply(this, args);
|
|
622
|
+
cache.set(key, { value: result, timestamp: now });
|
|
623
|
+
return result;
|
|
624
|
+
};
|
|
625
|
+
memoized.clear = () => cache.clear();
|
|
626
|
+
return memoized;
|
|
627
|
+
}
|
|
628
|
+
|
|
459
629
|
// src/format.ts
|
|
460
|
-
|
|
461
|
-
__export(format_exports, {
|
|
462
|
-
compactNumber: () => compactNumber,
|
|
463
|
-
currency: () => currency,
|
|
464
|
-
memory: () => memory,
|
|
465
|
-
number: () => number,
|
|
466
|
-
ordinal: () => ordinal
|
|
467
|
-
});
|
|
468
|
-
function currency(num, options = {}) {
|
|
630
|
+
function formatCurrency(num, options = {}) {
|
|
469
631
|
return new Intl.NumberFormat(options.locale, {
|
|
470
632
|
style: "currency",
|
|
471
633
|
currency: options.currency
|
|
472
634
|
}).format(num);
|
|
473
635
|
}
|
|
474
|
-
function
|
|
636
|
+
function formatNumber(num, options = {}) {
|
|
475
637
|
return new Intl.NumberFormat(options.locale, {
|
|
476
638
|
minimumFractionDigits: options.precision,
|
|
477
639
|
maximumFractionDigits: options.precision
|
|
478
640
|
}).format(num);
|
|
479
641
|
}
|
|
480
|
-
function
|
|
642
|
+
function formatMemory(bytes, decimals = 1, units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]) {
|
|
481
643
|
if (bytes <= 0) return `0 ${units[0]}`;
|
|
482
644
|
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
|
|
483
645
|
const val = bytes / Math.pow(1024, i);
|
|
484
646
|
return `${val.toFixed(i === 0 ? 0 : decimals)} ${units[i]}`;
|
|
485
647
|
}
|
|
486
|
-
function
|
|
648
|
+
function formatOrdinal(num, locale) {
|
|
487
649
|
const _num = Number(num);
|
|
488
650
|
if (isNaN(_num)) throw new TypeError("Invalid input");
|
|
489
651
|
const pr = new Intl.PluralRules(locale, { type: "ordinal" });
|
|
@@ -497,19 +659,61 @@ function ordinal(num, locale) {
|
|
|
497
659
|
const suffix = suffixes[rule] || "th";
|
|
498
660
|
return _num.toLocaleString(locale) + suffix;
|
|
499
661
|
}
|
|
500
|
-
function
|
|
662
|
+
function FormatNumberCompact(num, locale) {
|
|
501
663
|
return new Intl.NumberFormat(locale, {
|
|
502
664
|
notation: "compact",
|
|
503
665
|
compactDisplay: "short",
|
|
504
666
|
maximumFractionDigits: 1
|
|
505
667
|
}).format(num);
|
|
506
668
|
}
|
|
669
|
+
function formatDuration(target, style = "hms", options = {}) {
|
|
670
|
+
const targetMs = target instanceof Date ? target.getTime() : Number(target);
|
|
671
|
+
const sinceMs = options.since instanceof Date ? options.since.getTime() : Number(options.since) || Date.now();
|
|
672
|
+
const diff = Math.abs(targetMs - sinceMs);
|
|
673
|
+
if (diff === 0) return style === "digital" ? "00:00" : "now";
|
|
674
|
+
const s = Math.floor(diff / 1e3) % 60;
|
|
675
|
+
const m = Math.floor(diff / 6e4) % 60;
|
|
676
|
+
const h = Math.floor(diff / 36e5) % 24;
|
|
677
|
+
const d = Math.floor(diff / 864e5);
|
|
678
|
+
if (style === "digital") {
|
|
679
|
+
const parts = [m, s].map((v) => String(v).padStart(2, "0"));
|
|
680
|
+
if (h > 0 || d > 0) parts.unshift(String(h).padStart(2, "0"));
|
|
681
|
+
if (d > 0) parts.unshift(String(d));
|
|
682
|
+
return parts.join(":");
|
|
683
|
+
}
|
|
684
|
+
const result = [];
|
|
685
|
+
const push = (val, label) => {
|
|
686
|
+
if (val > 0) result.push(`${val} ${label}${val === 1 ? "" : "s"}`);
|
|
687
|
+
};
|
|
688
|
+
if (style === "ymdhms") push(d, "day");
|
|
689
|
+
push(h, "hour");
|
|
690
|
+
push(m, "minute");
|
|
691
|
+
push(s, "second");
|
|
692
|
+
if (result.length === 0) return "0 seconds";
|
|
693
|
+
if (result.length === 1) return result[0];
|
|
694
|
+
const last = result.pop();
|
|
695
|
+
return `${result.join(", ")} and ${last}`;
|
|
696
|
+
}
|
|
697
|
+
function formatETA(date, locale) {
|
|
698
|
+
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });
|
|
699
|
+
const elapsed = (typeof date === "number" ? date : date.getTime()) - Date.now();
|
|
700
|
+
const units = [
|
|
701
|
+
{ unit: "year", ms: 31536e6 },
|
|
702
|
+
{ unit: "month", ms: 2628e6 },
|
|
703
|
+
{ unit: "day", ms: 864e5 },
|
|
704
|
+
{ unit: "hour", ms: 36e5 },
|
|
705
|
+
{ unit: "minute", ms: 6e4 },
|
|
706
|
+
{ unit: "second", ms: 1e3 }
|
|
707
|
+
];
|
|
708
|
+
for (const { unit, ms } of units) {
|
|
709
|
+
if (Math.abs(elapsed) >= ms || unit === "second") {
|
|
710
|
+
return rtf.format(Math.round(elapsed / ms), unit);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
return "";
|
|
714
|
+
}
|
|
507
715
|
|
|
508
716
|
// src/fs.ts
|
|
509
|
-
var fs_exports = {};
|
|
510
|
-
__export(fs_exports, {
|
|
511
|
-
readDir: () => readDir
|
|
512
|
-
});
|
|
513
717
|
import _fs from "fs";
|
|
514
718
|
import { join } from "path";
|
|
515
719
|
function readDir(path2, options = {}) {
|
|
@@ -538,77 +742,58 @@ function readDir(path2, options = {}) {
|
|
|
538
742
|
}
|
|
539
743
|
|
|
540
744
|
// src/is.ts
|
|
541
|
-
|
|
542
|
-
__export(is_exports, {
|
|
543
|
-
defined: () => defined,
|
|
544
|
-
empty: () => empty,
|
|
545
|
-
inRange: () => inRange,
|
|
546
|
-
object: () => object,
|
|
547
|
-
sorted: () => sorted,
|
|
548
|
-
string: () => string,
|
|
549
|
-
today: () => today
|
|
550
|
-
});
|
|
551
|
-
function defined(val) {
|
|
745
|
+
function isDefined(val) {
|
|
552
746
|
return val !== void 0 && val !== null;
|
|
553
747
|
}
|
|
554
|
-
function
|
|
555
|
-
if (!
|
|
556
|
-
if (
|
|
557
|
-
if (
|
|
748
|
+
function isEmpty(val) {
|
|
749
|
+
if (!isDefined(val)) return true;
|
|
750
|
+
if (isString(val) || Array.isArray(val)) return val.length === 0;
|
|
751
|
+
if (isObject(val)) return Object.keys(val).length === 0;
|
|
558
752
|
return false;
|
|
559
753
|
}
|
|
560
|
-
function
|
|
754
|
+
function isObject(val) {
|
|
755
|
+
return val !== null && typeof val === "object" && !Array.isArray(val);
|
|
756
|
+
}
|
|
757
|
+
function isString(val) {
|
|
758
|
+
return typeof val === "string";
|
|
759
|
+
}
|
|
760
|
+
function isInRange(num, a, b) {
|
|
561
761
|
let min = b !== void 0 ? a : 0;
|
|
562
762
|
let max = b !== void 0 ? b : a;
|
|
563
763
|
if (min > max) [min, max] = [max, min];
|
|
564
764
|
return num >= min && num <= max;
|
|
565
765
|
}
|
|
566
|
-
function
|
|
567
|
-
return val !== null && typeof val === "object" && !Array.isArray(val);
|
|
568
|
-
}
|
|
569
|
-
function sorted(arr, comparator) {
|
|
766
|
+
function isSortedArray(arr, comparator) {
|
|
570
767
|
for (let i = 0; i < arr.length - 1; i++) {
|
|
571
768
|
const comp = comparator ? comparator(arr[i], arr[i + 1]) : arr[i] > arr[i + 1] ? 1 : -1;
|
|
572
769
|
if (comp > 0) return false;
|
|
573
770
|
}
|
|
574
771
|
return true;
|
|
575
772
|
}
|
|
576
|
-
function
|
|
577
|
-
return typeof val === "string";
|
|
578
|
-
}
|
|
579
|
-
function today(date) {
|
|
773
|
+
function isToday(date) {
|
|
580
774
|
const d = date instanceof Date ? date : new Date(date);
|
|
581
|
-
const
|
|
582
|
-
return d.getDate() ===
|
|
775
|
+
const today = /* @__PURE__ */ new Date();
|
|
776
|
+
return d.getDate() === today.getDate() && d.getMonth() === today.getMonth() && d.getFullYear() === today.getFullYear();
|
|
583
777
|
}
|
|
584
778
|
|
|
585
779
|
// src/math.ts
|
|
586
|
-
|
|
587
|
-
__export(math_exports, {
|
|
588
|
-
clamp: () => clamp,
|
|
589
|
-
invLerp: () => invLerp,
|
|
590
|
-
lerp: () => lerp,
|
|
591
|
-
ms: () => ms,
|
|
592
|
-
percent: () => percent,
|
|
593
|
-
remap: () => remap,
|
|
594
|
-
secs: () => secs,
|
|
595
|
-
sum: () => sum,
|
|
596
|
-
wrap: () => wrap
|
|
597
|
-
});
|
|
598
|
-
function clamp(num, a, b) {
|
|
780
|
+
function clampNumber(num, a, b) {
|
|
599
781
|
let min = b !== void 0 ? a : 0;
|
|
600
782
|
let max = b !== void 0 ? b : a;
|
|
601
783
|
if (min > max) [min, max] = [max, min];
|
|
602
784
|
return Math.max(min, Math.min(num, max));
|
|
603
785
|
}
|
|
604
|
-
function
|
|
786
|
+
function lerp(start, end, t) {
|
|
787
|
+
return start + (end - start) * t;
|
|
788
|
+
}
|
|
789
|
+
function inverseLerp(start, end, value) {
|
|
605
790
|
if (start === end) return 0;
|
|
606
791
|
return (value - start) / (end - start);
|
|
607
792
|
}
|
|
608
|
-
function
|
|
609
|
-
return
|
|
793
|
+
function msToSecs(num) {
|
|
794
|
+
return Math.floor(num / 1e3);
|
|
610
795
|
}
|
|
611
|
-
function
|
|
796
|
+
function secsToMs(num) {
|
|
612
797
|
return Math.floor(num * 1e3);
|
|
613
798
|
}
|
|
614
799
|
function percent(a, b, round = true) {
|
|
@@ -616,36 +801,19 @@ function percent(a, b, round = true) {
|
|
|
616
801
|
return round ? Math.floor(result) : result;
|
|
617
802
|
}
|
|
618
803
|
function remap(value, inMin, inMax, outMin, outMax) {
|
|
619
|
-
const t =
|
|
804
|
+
const t = inverseLerp(inMin, inMax, value);
|
|
620
805
|
return lerp(outMin, outMax, t);
|
|
621
806
|
}
|
|
622
|
-
function secs(num) {
|
|
623
|
-
return Math.floor(num / 1e3);
|
|
624
|
-
}
|
|
625
807
|
function sum(array, selector) {
|
|
626
808
|
const _array = selector ? array.map(selector) : array;
|
|
627
|
-
|
|
628
|
-
throw new TypeError(`sum: Array must only contain numbers.`);
|
|
629
|
-
}
|
|
630
|
-
return _array.reduce((a, b) => {
|
|
631
|
-
return (isNaN(b) ? 0 : b) < 0 ? a - -b : a + (b || 0);
|
|
632
|
-
}, 0);
|
|
809
|
+
return _array.reduce((a, b) => b < 0 ? a - -b : a + (b || 0), 0);
|
|
633
810
|
}
|
|
634
811
|
function wrap(num, max) {
|
|
635
812
|
return (num % max + max) % max;
|
|
636
813
|
}
|
|
637
814
|
|
|
638
815
|
// src/obj.ts
|
|
639
|
-
|
|
640
|
-
__export(obj_exports, {
|
|
641
|
-
get: () => get,
|
|
642
|
-
has: () => has,
|
|
643
|
-
merge: () => merge,
|
|
644
|
-
omit: () => omit,
|
|
645
|
-
pick: () => pick,
|
|
646
|
-
set: () => set
|
|
647
|
-
});
|
|
648
|
-
function get(obj, path2, defaultValue) {
|
|
816
|
+
function getProp(obj, path2, defaultValue) {
|
|
649
817
|
if (!obj) throw new Error("get: Target object is null or undefined");
|
|
650
818
|
const parts = path2.replace(/\[(\d+)\]/g, ".$1").split(".");
|
|
651
819
|
let current = obj;
|
|
@@ -664,7 +832,7 @@ function get(obj, path2, defaultValue) {
|
|
|
664
832
|
}
|
|
665
833
|
return current;
|
|
666
834
|
}
|
|
667
|
-
function
|
|
835
|
+
function hasProp(obj, path2) {
|
|
668
836
|
if (!obj || !path2) return false;
|
|
669
837
|
const parts = path2.replace(/\[(\d+)\]/g, ".$1").split(".");
|
|
670
838
|
let current = obj;
|
|
@@ -680,7 +848,7 @@ function has(obj, path2) {
|
|
|
680
848
|
}
|
|
681
849
|
return true;
|
|
682
850
|
}
|
|
683
|
-
function
|
|
851
|
+
function setProp(obj, path2, value) {
|
|
684
852
|
const parts = path2.replace(/\[(\d+)\]/g, ".$1").split(".");
|
|
685
853
|
let current = obj;
|
|
686
854
|
for (let i = 0; i < parts.length; i++) {
|
|
@@ -732,36 +900,32 @@ function omit(obj, keys) {
|
|
|
732
900
|
}
|
|
733
901
|
|
|
734
902
|
// src/str.ts
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
escapeRegex: () => escapeRegex,
|
|
738
|
-
getFlag: () => getFlag,
|
|
739
|
-
hasFlag: () => hasFlag,
|
|
740
|
-
toTitleCase: () => toTitleCase
|
|
741
|
-
});
|
|
742
|
-
function escapeRegex(str2) {
|
|
743
|
-
return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
903
|
+
function escapeRegex(str) {
|
|
904
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
744
905
|
}
|
|
745
|
-
function getFlag(
|
|
906
|
+
function getFlag(str, flag, length) {
|
|
746
907
|
const regex = flag instanceof RegExp ? flag : new RegExp(`${escapeRegex(flag)}\\b`, "g");
|
|
747
|
-
const match = regex.exec(
|
|
908
|
+
const match = regex.exec(str);
|
|
748
909
|
if (!match) return null;
|
|
749
910
|
const startIndex = match.index + match[0].length;
|
|
750
|
-
let result =
|
|
911
|
+
let result = str.slice(startIndex).trimStart();
|
|
751
912
|
if (length !== void 0) {
|
|
752
913
|
return result.split(/\s+/).slice(0, length).join(" ");
|
|
753
914
|
}
|
|
754
915
|
return result || null;
|
|
755
916
|
}
|
|
756
|
-
function hasFlag(
|
|
757
|
-
if (flag instanceof RegExp) return flag.test(
|
|
917
|
+
function hasFlag(str, flag) {
|
|
918
|
+
if (flag instanceof RegExp) return flag.test(str);
|
|
758
919
|
const pattern = new RegExp(`${escapeRegex(flag)}\\b`);
|
|
759
|
-
return pattern.test(
|
|
920
|
+
return pattern.test(str);
|
|
921
|
+
}
|
|
922
|
+
function pluralize(count, singular, plural = `${singular}s`) {
|
|
923
|
+
return count === 1 ? singular : plural;
|
|
760
924
|
}
|
|
761
|
-
function toTitleCase(
|
|
925
|
+
function toTitleCase(str, smart = true) {
|
|
762
926
|
const minorWords = /^(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v\.?|via)$/i;
|
|
763
|
-
return
|
|
764
|
-
if (smart &&
|
|
927
|
+
return str.replace(/\w\S*/g, (txt, index) => {
|
|
928
|
+
if (smart && index !== 0 && minorWords.test(txt)) {
|
|
765
929
|
return txt.toLowerCase();
|
|
766
930
|
}
|
|
767
931
|
if (smart && txt.length > 1 && txt === txt.toUpperCase()) {
|
|
@@ -770,392 +934,70 @@ function toTitleCase(str2, smart = true) {
|
|
|
770
934
|
return txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase();
|
|
771
935
|
});
|
|
772
936
|
}
|
|
773
|
-
|
|
774
|
-
// src/timing.ts
|
|
775
|
-
var timing_exports = {};
|
|
776
|
-
__export(timing_exports, {
|
|
777
|
-
debounce: () => debounce,
|
|
778
|
-
throttle: () => throttle
|
|
779
|
-
});
|
|
780
|
-
function debounce(fn, wait2, options = {}) {
|
|
781
|
-
let timeoutId;
|
|
782
|
-
const leading = options.immediate ?? false;
|
|
783
|
-
const debounced = function(...args) {
|
|
784
|
-
const callNow = leading && !timeoutId;
|
|
785
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
786
|
-
timeoutId = setTimeout(() => {
|
|
787
|
-
timeoutId = void 0;
|
|
788
|
-
if (!leading) fn.apply(this, args);
|
|
789
|
-
}, wait2);
|
|
790
|
-
if (callNow) fn.apply(this, args);
|
|
791
|
-
};
|
|
792
|
-
debounced.cancel = () => {
|
|
793
|
-
if (timeoutId) {
|
|
794
|
-
clearTimeout(timeoutId);
|
|
795
|
-
timeoutId = void 0;
|
|
796
|
-
}
|
|
797
|
-
};
|
|
798
|
-
return debounced;
|
|
799
|
-
}
|
|
800
|
-
function throttle(fn, limit) {
|
|
801
|
-
let inThrottle = false;
|
|
802
|
-
return function(...args) {
|
|
803
|
-
if (!inThrottle) {
|
|
804
|
-
fn.apply(this, args);
|
|
805
|
-
inThrottle = true;
|
|
806
|
-
setTimeout(() => inThrottle = false, limit);
|
|
807
|
-
}
|
|
808
|
-
};
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
// src/to.ts
|
|
812
|
-
var to_exports = {};
|
|
813
|
-
__export(to_exports, {
|
|
814
|
-
record: () => record
|
|
815
|
-
});
|
|
816
|
-
function record(array, callback) {
|
|
817
|
-
const result = {};
|
|
818
|
-
let lastValue = void 0;
|
|
819
|
-
for (let i = 0; i < array.length; i++) {
|
|
820
|
-
const { key, value } = callback(array[i], {
|
|
821
|
-
index: i,
|
|
822
|
-
lastValue,
|
|
823
|
-
// NOTE: This is a reference to the object currently being built
|
|
824
|
-
newRecord: result,
|
|
825
|
-
originalArray: array
|
|
826
|
-
});
|
|
827
|
-
result[key] = value;
|
|
828
|
-
lastValue = value;
|
|
829
|
-
}
|
|
830
|
-
return result;
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
// src/Pipe.ts
|
|
834
|
-
function Pipe(value, ...fns) {
|
|
835
|
-
return fns.reduce((acc, fn) => fn(acc), value);
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
// src/Storage.ts
|
|
839
|
-
import fs from "fs";
|
|
840
|
-
import path from "path";
|
|
841
|
-
var Storage = class {
|
|
842
|
-
isNode = typeof window === "undefined";
|
|
843
|
-
filePath = null;
|
|
844
|
-
memoryCache = /* @__PURE__ */ new Map();
|
|
845
|
-
loadFromFile() {
|
|
846
|
-
if (this.filePath && fs.existsSync(this.filePath)) {
|
|
847
|
-
try {
|
|
848
|
-
const data = JSON.parse(fs.readFileSync(this.filePath, "utf-8"));
|
|
849
|
-
Object.entries(data).forEach(([k, v]) => this.memoryCache.set(k, JSON.stringify(v)));
|
|
850
|
-
} catch (err) {
|
|
851
|
-
console.error(`Store: Failed to load file '${this.filePath}'`, err);
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
persist() {
|
|
856
|
-
if (this.isNode && this.filePath) {
|
|
857
|
-
const out = {};
|
|
858
|
-
this.memoryCache.forEach((v, k) => out[k] = JSON.parse(v));
|
|
859
|
-
fs.writeFileSync(this.filePath, JSON.stringify(out, null, 2));
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
/**
|
|
863
|
-
* A lightweight, high-performant persistent storage system.
|
|
864
|
-
* Uses JSON files in Node.js, localStorage in the browser.
|
|
865
|
-
* @param fileName Only used in Node.js to create a persistent .json file.
|
|
866
|
-
* @param directory The directory for the file. Defaults to current working directory.
|
|
867
|
-
*/
|
|
868
|
-
constructor(fileName, directory = process.cwd()) {
|
|
869
|
-
if (this.isNode && fileName) {
|
|
870
|
-
this.filePath = path.join(directory, fileName.endsWith(".json") ? fileName : `${fileName}.json`);
|
|
871
|
-
this.loadFromFile();
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
has(key) {
|
|
875
|
-
if (!this.isNode && window.localStorage) {
|
|
876
|
-
return localStorage.getItem(key) !== null;
|
|
877
|
-
}
|
|
878
|
-
return this.memoryCache.has(key);
|
|
879
|
-
}
|
|
880
|
-
get(key) {
|
|
881
|
-
let raw = null;
|
|
882
|
-
if (!this.isNode && window.localStorage) {
|
|
883
|
-
raw = localStorage.getItem(key);
|
|
884
|
-
} else {
|
|
885
|
-
raw = this.memoryCache.get(key) || null;
|
|
886
|
-
}
|
|
887
|
-
if (!raw) return null;
|
|
888
|
-
const payload = JSON.parse(raw);
|
|
889
|
-
if (payload.expiry && Date.now() > payload.expiry) {
|
|
890
|
-
this.remove(key);
|
|
891
|
-
this.persist();
|
|
892
|
-
return null;
|
|
893
|
-
}
|
|
894
|
-
return payload.value;
|
|
895
|
-
}
|
|
896
|
-
set(key, value, ttl) {
|
|
897
|
-
const payload = {
|
|
898
|
-
value,
|
|
899
|
-
expiry: ttl ? Date.now() + ttl : null
|
|
900
|
-
};
|
|
901
|
-
const serialized = JSON.stringify(payload);
|
|
902
|
-
if (!this.isNode && window.localStorage) {
|
|
903
|
-
localStorage.setItem(key, serialized);
|
|
904
|
-
} else {
|
|
905
|
-
this.memoryCache.set(key, serialized);
|
|
906
|
-
this.persist();
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
remove(key) {
|
|
910
|
-
if (!this.isNode && window.localStorage) {
|
|
911
|
-
localStorage.removeItem(key);
|
|
912
|
-
} else {
|
|
913
|
-
this.memoryCache.delete(key);
|
|
914
|
-
this.persist();
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
|
-
clear() {
|
|
918
|
-
if (!this.isNode && window.localStorage) {
|
|
919
|
-
localStorage.clear();
|
|
920
|
-
} else {
|
|
921
|
-
this.memoryCache.clear();
|
|
922
|
-
this.persist();
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
};
|
|
926
|
-
|
|
927
|
-
// src/Cache.ts
|
|
928
|
-
var Cache = class {
|
|
929
|
-
cache = /* @__PURE__ */ new Map();
|
|
930
|
-
interval;
|
|
931
|
-
/**
|
|
932
|
-
* A lightweight, high-performant in-memory cache.
|
|
933
|
-
* Uses Map for O(1) lookups and an optional cleanup interval.
|
|
934
|
-
* @param cleanupMs The interval in milliseconds to run the cleanup function. [default: 60000 (1 minute)]
|
|
935
|
-
*/
|
|
936
|
-
constructor(cleanupMs = 6e4) {
|
|
937
|
-
if (cleanupMs > 0) {
|
|
938
|
-
this.interval = setInterval(() => this.cleanup(), cleanupMs);
|
|
939
|
-
if (this.interval.unref) this.interval.unref();
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
set(key, value, ttlMs) {
|
|
943
|
-
this.cache.set(key, {
|
|
944
|
-
value,
|
|
945
|
-
expiresAt: ttlMs ? Date.now() + ttlMs : null
|
|
946
|
-
});
|
|
947
|
-
}
|
|
948
|
-
get(key) {
|
|
949
|
-
const data = this.cache.get(key);
|
|
950
|
-
if (!data) return null;
|
|
951
|
-
if (data.expiresAt && Date.now() > data.expiresAt) {
|
|
952
|
-
this.cache.delete(key);
|
|
953
|
-
return null;
|
|
954
|
-
}
|
|
955
|
-
return data.value;
|
|
956
|
-
}
|
|
957
|
-
cleanup() {
|
|
958
|
-
if (this.cache.size === 0) return;
|
|
959
|
-
const now = Date.now();
|
|
960
|
-
let keysProcessed = 0;
|
|
961
|
-
const maxKeysToScan = 20;
|
|
962
|
-
for (const [key, data] of this.cache) {
|
|
963
|
-
if (data.expiresAt && now > data.expiresAt) {
|
|
964
|
-
this.cache.delete(key);
|
|
965
|
-
}
|
|
966
|
-
keysProcessed++;
|
|
967
|
-
if (keysProcessed >= maxKeysToScan) break;
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
clear() {
|
|
971
|
-
this.cache.clear();
|
|
972
|
-
}
|
|
973
|
-
};
|
|
974
|
-
|
|
975
|
-
// src/Loop.ts
|
|
976
|
-
import EventEmitter from "events";
|
|
977
|
-
var TypedEmitterBase = EventEmitter;
|
|
978
|
-
var Loop = class extends TypedEmitterBase {
|
|
979
|
-
_state = "stopped";
|
|
980
|
-
timeoutId = null;
|
|
981
|
-
delay;
|
|
982
|
-
fn;
|
|
983
|
-
startTime = 0;
|
|
984
|
-
remaining = 0;
|
|
985
|
-
async run() {
|
|
986
|
-
const currentState = this._state;
|
|
987
|
-
if (currentState === "stopped" || currentState === "paused") return;
|
|
988
|
-
try {
|
|
989
|
-
const result = await this.fn(this);
|
|
990
|
-
this.emit("tick", result);
|
|
991
|
-
} catch (err) {
|
|
992
|
-
this.emit("error", err);
|
|
993
|
-
}
|
|
994
|
-
if (this._state === "running") {
|
|
995
|
-
this.startTime = Date.now();
|
|
996
|
-
this.remaining = 0;
|
|
997
|
-
this.clearTimer();
|
|
998
|
-
this.timeoutId = setTimeout(() => this.run(), this.delay);
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
clearTimer() {
|
|
1002
|
-
if (this.timeoutId) {
|
|
1003
|
-
clearTimeout(this.timeoutId);
|
|
1004
|
-
this.timeoutId = null;
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
/**
|
|
1008
|
-
* Creates an interval. If the function is async, it will wait for it to complete before scheduling the next run.
|
|
1009
|
-
* @param fn The function to run.
|
|
1010
|
-
* @param delay The delay between runs in milliseconds.
|
|
1011
|
-
* @param immediate Whether to start the loop immediately. [default: true]
|
|
1012
|
-
*/
|
|
1013
|
-
constructor(fn, delay, immediate = true) {
|
|
1014
|
-
super();
|
|
1015
|
-
this.fn = fn;
|
|
1016
|
-
this.delay = delay;
|
|
1017
|
-
if (immediate) this.start();
|
|
1018
|
-
}
|
|
1019
|
-
get state() {
|
|
1020
|
-
return this._state;
|
|
1021
|
-
}
|
|
1022
|
-
/** Starts the loop. */
|
|
1023
|
-
start() {
|
|
1024
|
-
if (this._state !== "stopped") return;
|
|
1025
|
-
this._state = "running";
|
|
1026
|
-
this.emit("start");
|
|
1027
|
-
this.run();
|
|
1028
|
-
}
|
|
1029
|
-
/** Resumes a paused loop. */
|
|
1030
|
-
resume() {
|
|
1031
|
-
if (this._state !== "paused") return;
|
|
1032
|
-
this._state = "running";
|
|
1033
|
-
this.emit("resume");
|
|
1034
|
-
if (this.remaining <= 0) {
|
|
1035
|
-
this.run();
|
|
1036
|
-
} else {
|
|
1037
|
-
this.timeoutId = setTimeout(() => this.run(), this.remaining);
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
/** Stops the loop. */
|
|
1041
|
-
stop() {
|
|
1042
|
-
const wasRunning = this._state !== "stopped";
|
|
1043
|
-
this._state = "stopped";
|
|
1044
|
-
this.remaining = 0;
|
|
1045
|
-
this.clearTimer();
|
|
1046
|
-
if (wasRunning) this.emit("stop");
|
|
1047
|
-
}
|
|
1048
|
-
/** Pauses the execution. */
|
|
1049
|
-
pause() {
|
|
1050
|
-
if (this._state !== "running") return;
|
|
1051
|
-
this._state = "paused";
|
|
1052
|
-
const elapsed = Date.now() - this.startTime;
|
|
1053
|
-
this.remaining = Math.max(0, this.delay - elapsed);
|
|
1054
|
-
this.emit("pause", { remaining: this.remaining });
|
|
1055
|
-
this.clearTimer();
|
|
1056
|
-
}
|
|
1057
|
-
/**
|
|
1058
|
-
* Sets the delay between runs
|
|
1059
|
-
* @param ms The new delay in milliseconds.
|
|
1060
|
-
*/
|
|
1061
|
-
setDelay(ms2) {
|
|
1062
|
-
this.delay = ms2;
|
|
1063
|
-
}
|
|
1064
|
-
/** Manually trigger the function once without affecting the loop. */
|
|
1065
|
-
async execute() {
|
|
1066
|
-
await this.fn(this);
|
|
1067
|
-
}
|
|
1068
|
-
};
|
|
1069
|
-
|
|
1070
|
-
// src/index.ts
|
|
1071
|
-
var qznt = {
|
|
1072
|
-
arr: arr_exports,
|
|
1073
|
-
async: async_exports,
|
|
1074
|
-
fn: fn_exports,
|
|
1075
|
-
date: date_exports,
|
|
1076
|
-
format: format_exports,
|
|
1077
|
-
fs: fs_exports,
|
|
1078
|
-
is: is_exports,
|
|
1079
|
-
math: math_exports,
|
|
1080
|
-
obj: obj_exports,
|
|
1081
|
-
timing: timing_exports,
|
|
1082
|
-
rnd: rnd_exports,
|
|
1083
|
-
str: str_exports,
|
|
1084
|
-
to: to_exports,
|
|
1085
|
-
Pipe,
|
|
1086
|
-
Storage,
|
|
1087
|
-
Cache,
|
|
1088
|
-
Loop
|
|
1089
|
-
};
|
|
1090
|
-
var $ = qznt;
|
|
1091
|
-
var index_default = qznt;
|
|
1092
937
|
export {
|
|
1093
|
-
$,
|
|
1094
938
|
Cache,
|
|
939
|
+
FormatNumberCompact,
|
|
1095
940
|
Loop,
|
|
1096
941
|
Pipe,
|
|
1097
942
|
Storage,
|
|
1098
|
-
chance,
|
|
1099
|
-
choice,
|
|
1100
943
|
chunk,
|
|
1101
944
|
chunkAdj,
|
|
1102
|
-
|
|
945
|
+
clampNumber,
|
|
1103
946
|
cluster,
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
currency,
|
|
947
|
+
compactArray,
|
|
948
|
+
createSampler,
|
|
1107
949
|
debounce,
|
|
1108
|
-
index_default as default,
|
|
1109
|
-
defined,
|
|
1110
|
-
duration,
|
|
1111
|
-
empty,
|
|
1112
950
|
escapeRegex,
|
|
1113
|
-
eta,
|
|
1114
|
-
float,
|
|
1115
951
|
forceArray,
|
|
1116
|
-
|
|
952
|
+
formatCurrency,
|
|
953
|
+
formatDuration,
|
|
954
|
+
formatETA,
|
|
955
|
+
formatMemory,
|
|
956
|
+
formatNumber,
|
|
957
|
+
formatOrdinal,
|
|
1117
958
|
getAge,
|
|
1118
959
|
getFlag,
|
|
1119
|
-
|
|
960
|
+
getProp,
|
|
1120
961
|
hasFlag,
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
962
|
+
hasProp,
|
|
963
|
+
inverseLerp,
|
|
964
|
+
isDefined,
|
|
965
|
+
isEmpty,
|
|
966
|
+
isInRange,
|
|
967
|
+
isObject,
|
|
968
|
+
isSortedArray,
|
|
969
|
+
isString,
|
|
970
|
+
isToday,
|
|
1125
971
|
lerp,
|
|
1126
972
|
memoize,
|
|
1127
|
-
memory,
|
|
1128
973
|
merge,
|
|
1129
|
-
|
|
1130
|
-
number,
|
|
1131
|
-
object,
|
|
974
|
+
msToSecs,
|
|
1132
975
|
omit,
|
|
1133
|
-
|
|
1134
|
-
parse,
|
|
976
|
+
parseTime,
|
|
1135
977
|
percent,
|
|
1136
978
|
pick,
|
|
979
|
+
pluralize,
|
|
1137
980
|
prng,
|
|
1138
981
|
readDir,
|
|
1139
|
-
record,
|
|
1140
982
|
remap,
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
983
|
+
retryPromise,
|
|
984
|
+
rndChance,
|
|
985
|
+
rndChoice,
|
|
986
|
+
rndFloat,
|
|
987
|
+
rndIndex,
|
|
988
|
+
rndInt,
|
|
989
|
+
rndString,
|
|
990
|
+
searchSorted,
|
|
991
|
+
secsToMs,
|
|
1145
992
|
seqMap,
|
|
1146
|
-
|
|
993
|
+
setProp,
|
|
1147
994
|
shuffle,
|
|
1148
995
|
sortBy,
|
|
1149
|
-
sorted,
|
|
1150
|
-
str,
|
|
1151
|
-
string,
|
|
1152
996
|
sum,
|
|
1153
997
|
throttle,
|
|
1154
998
|
toTitleCase,
|
|
1155
|
-
today,
|
|
1156
999
|
unique,
|
|
1157
1000
|
wait,
|
|
1158
|
-
|
|
1001
|
+
weightedRnd,
|
|
1159
1002
|
wrap
|
|
1160
1003
|
};
|
|
1161
|
-
//# sourceMappingURL=index.js.map
|