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