qznt 1.0.37 → 2.0.1

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