speexjs-core 0.7.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +117 -0
  2. package/CONTRIBUTING.md +55 -0
  3. package/PUBLISH.md +45 -0
  4. package/README.md +174 -0
  5. package/ROADMAP.md +72 -0
  6. package/SECURITY.md +35 -0
  7. package/SUMMARY.md +321 -0
  8. package/dist/async/index.d.ts +232 -0
  9. package/dist/async/index.js +366 -0
  10. package/dist/async/index.js.map +1 -0
  11. package/dist/collection/index.d.ts +230 -0
  12. package/dist/collection/index.js +375 -0
  13. package/dist/collection/index.js.map +1 -0
  14. package/dist/color/index.d.ts +128 -0
  15. package/dist/color/index.js +167 -0
  16. package/dist/color/index.js.map +1 -0
  17. package/dist/core/index.d.ts +119 -0
  18. package/dist/core/index.js +324 -0
  19. package/dist/core/index.js.map +1 -0
  20. package/dist/crypto/index.d.ts +84 -0
  21. package/dist/crypto/index.js +144 -0
  22. package/dist/crypto/index.js.map +1 -0
  23. package/dist/date/index.d.ts +588 -0
  24. package/dist/date/index.js +737 -0
  25. package/dist/date/index.js.map +1 -0
  26. package/dist/dep-exray/analyzer/index.d.ts +7 -0
  27. package/dist/dep-exray/analyzer/index.js +68 -0
  28. package/dist/dep-exray/analyzer/index.js.map +1 -0
  29. package/dist/dep-exray/cli.d.ts +1 -0
  30. package/dist/dep-exray/cli.js +441 -0
  31. package/dist/dep-exray/cli.js.map +1 -0
  32. package/dist/dep-exray/index.d.ts +5 -0
  33. package/dist/dep-exray/index.js +454 -0
  34. package/dist/dep-exray/index.js.map +1 -0
  35. package/dist/dep-exray/known-mappings.d.ts +17 -0
  36. package/dist/dep-exray/known-mappings.js +122 -0
  37. package/dist/dep-exray/known-mappings.js.map +1 -0
  38. package/dist/dep-exray/reporter/index.d.ts +5 -0
  39. package/dist/dep-exray/reporter/index.js +89 -0
  40. package/dist/dep-exray/reporter/index.js.map +1 -0
  41. package/dist/dep-exray/scanner/index.d.ts +5 -0
  42. package/dist/dep-exray/scanner/index.js +299 -0
  43. package/dist/dep-exray/scanner/index.js.map +1 -0
  44. package/dist/dep-exray/types.d.ts +38 -0
  45. package/dist/dep-exray/types.js +1 -0
  46. package/dist/dep-exray/types.js.map +1 -0
  47. package/dist/error/index.d.ts +148 -0
  48. package/dist/error/index.js +115 -0
  49. package/dist/error/index.js.map +1 -0
  50. package/dist/index-BgG21uJC.d.ts +166 -0
  51. package/dist/index.d.ts +19 -0
  52. package/dist/index.js +4378 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/io/index.d.ts +39 -0
  55. package/dist/io/index.js +111 -0
  56. package/dist/io/index.js.map +1 -0
  57. package/dist/logger/index.d.ts +1 -0
  58. package/dist/logger/index.js +214 -0
  59. package/dist/logger/index.js.map +1 -0
  60. package/dist/logger/transports.d.ts +1 -0
  61. package/dist/logger/transports.js +122 -0
  62. package/dist/logger/transports.js.map +1 -0
  63. package/dist/math/index.d.ts +362 -0
  64. package/dist/math/index.js +372 -0
  65. package/dist/math/index.js.map +1 -0
  66. package/dist/path/index.d.ts +81 -0
  67. package/dist/path/index.js +134 -0
  68. package/dist/path/index.js.map +1 -0
  69. package/dist/string/index.d.ts +234 -0
  70. package/dist/string/index.js +411 -0
  71. package/dist/string/index.js.map +1 -0
  72. package/dist/type/index.d.ts +85 -0
  73. package/dist/type/index.js +107 -0
  74. package/dist/type/index.js.map +1 -0
  75. package/dist/validation/index.d.ts +203 -0
  76. package/dist/validation/index.js +402 -0
  77. package/dist/validation/index.js.map +1 -0
  78. package/package.json +172 -0
package/dist/index.js ADDED
@@ -0,0 +1,4378 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/core/index.ts
9
+ function isPlainObject(value) {
10
+ if (value === null || typeof value !== "object") return false;
11
+ const proto = Object.getPrototypeOf(value);
12
+ return proto === Object.prototype || proto === null;
13
+ }
14
+ function getType(value) {
15
+ return Object.prototype.toString.call(value);
16
+ }
17
+ function clone(value, seen) {
18
+ if (value === null || typeof value !== "object") return value;
19
+ if (seen.has(value)) return seen.get(value);
20
+ const tag = getType(value);
21
+ if (tag === "[object Date]") {
22
+ const cloned = new Date(value.getTime());
23
+ seen.set(value, cloned);
24
+ return cloned;
25
+ }
26
+ if (tag === "[object RegExp]") {
27
+ const regExp = value;
28
+ const cloned = new RegExp(regExp.source, regExp.flags);
29
+ cloned.lastIndex = regExp.lastIndex;
30
+ seen.set(value, cloned);
31
+ return cloned;
32
+ }
33
+ if (tag === "[object Map]") {
34
+ const cloned = /* @__PURE__ */ new Map();
35
+ seen.set(value, cloned);
36
+ value.forEach((v, k) => {
37
+ cloned.set(clone(k, seen), clone(v, seen));
38
+ });
39
+ return cloned;
40
+ }
41
+ if (tag === "[object Set]") {
42
+ const cloned = /* @__PURE__ */ new Set();
43
+ seen.set(value, cloned);
44
+ value.forEach((v) => {
45
+ cloned.add(clone(v, seen));
46
+ });
47
+ return cloned;
48
+ }
49
+ if (Array.isArray(value)) {
50
+ const cloned = [];
51
+ seen.set(value, cloned);
52
+ for (let i = 0; i < value.length; i++) {
53
+ cloned[i] = clone(value[i], seen);
54
+ }
55
+ return cloned;
56
+ }
57
+ if (tag === "[object Object]") {
58
+ const cloned = {};
59
+ seen.set(value, cloned);
60
+ const keys = Object.keys(value);
61
+ for (let i = 0; i < keys.length; i++) {
62
+ const key = keys[i];
63
+ cloned[key] = clone(value[key], seen);
64
+ }
65
+ return cloned;
66
+ }
67
+ return value;
68
+ }
69
+ function deepClone(value) {
70
+ const seen = /* @__PURE__ */ new WeakMap();
71
+ return clone(value, seen);
72
+ }
73
+ function deepMerge(...objects) {
74
+ const result = {};
75
+ for (let i = 0; i < objects.length; i++) {
76
+ const obj = objects[i];
77
+ if (obj === null || obj === void 0) continue;
78
+ const keys = Object.keys(obj);
79
+ for (let j = 0; j < keys.length; j++) {
80
+ const key = keys[j];
81
+ if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
82
+ const val = obj[key];
83
+ const existing = result[key];
84
+ if (val !== void 0 && isPlainObject(val) && isPlainObject(existing)) {
85
+ result[key] = deepMerge(
86
+ existing,
87
+ val
88
+ );
89
+ } else if (val !== void 0) {
90
+ result[key] = val;
91
+ }
92
+ }
93
+ }
94
+ return result;
95
+ }
96
+ function debounce(fn, wait, options) {
97
+ const { leading = false, trailing = true, maxWait } = options ?? {};
98
+ let timer = null;
99
+ let maxTimer = null;
100
+ let lastArgs = null;
101
+ let lastCallTime = null;
102
+ let lastInvokeTime = 0;
103
+ function invoke(time) {
104
+ lastInvokeTime = time;
105
+ if (lastArgs) {
106
+ fn(...lastArgs);
107
+ lastArgs = null;
108
+ }
109
+ }
110
+ function startTimer(waitTime) {
111
+ if (timer) clearTimeout(timer);
112
+ timer = setTimeout(() => {
113
+ const now = Date.now();
114
+ if (lastArgs && trailing) {
115
+ invoke(now);
116
+ }
117
+ timer = null;
118
+ lastCallTime = null;
119
+ }, waitTime);
120
+ }
121
+ function startMaxTimer() {
122
+ if (maxWait === void 0 || maxTimer) return;
123
+ maxTimer = setTimeout(() => {
124
+ if (lastArgs) {
125
+ invoke(Date.now());
126
+ if (timer) {
127
+ clearTimeout(timer);
128
+ timer = null;
129
+ }
130
+ lastCallTime = null;
131
+ }
132
+ }, maxWait);
133
+ }
134
+ function clearAllTimers() {
135
+ if (timer) {
136
+ clearTimeout(timer);
137
+ timer = null;
138
+ }
139
+ if (maxTimer) {
140
+ clearTimeout(maxTimer);
141
+ maxTimer = null;
142
+ }
143
+ }
144
+ function shouldInvoke(time) {
145
+ if (lastCallTime === null) return true;
146
+ const timeSinceLastCall = time - lastCallTime;
147
+ const timeSinceLastInvoke = time - lastInvokeTime;
148
+ return timeSinceLastCall >= wait || maxWait !== void 0 && timeSinceLastInvoke >= maxWait;
149
+ }
150
+ const debounced = function(...args) {
151
+ const time = Date.now();
152
+ const isInvoking = shouldInvoke(time);
153
+ lastArgs = args;
154
+ lastCallTime = time;
155
+ if (isInvoking && !timer && leading) {
156
+ invoke(time);
157
+ }
158
+ if (!timer) {
159
+ startTimer(wait);
160
+ if (maxWait !== void 0) {
161
+ startMaxTimer();
162
+ }
163
+ }
164
+ };
165
+ debounced.cancel = () => {
166
+ clearAllTimers();
167
+ lastArgs = null;
168
+ lastCallTime = null;
169
+ lastInvokeTime = 0;
170
+ };
171
+ debounced.flush = () => {
172
+ if (timer && lastArgs) {
173
+ invoke(Date.now());
174
+ clearAllTimers();
175
+ lastCallTime = null;
176
+ }
177
+ };
178
+ return debounced;
179
+ }
180
+ function throttle(fn, wait) {
181
+ let lastTime = 0;
182
+ let timer = null;
183
+ let lastArgs = null;
184
+ const throttled = function(...args) {
185
+ const now = Date.now();
186
+ const remaining = wait - (now - lastTime);
187
+ if (remaining <= 0) {
188
+ if (timer) {
189
+ clearTimeout(timer);
190
+ timer = null;
191
+ }
192
+ lastTime = now;
193
+ lastArgs = null;
194
+ fn.apply(this, args);
195
+ } else {
196
+ lastArgs = args;
197
+ if (!timer) {
198
+ timer = setTimeout(() => {
199
+ lastTime = Date.now();
200
+ timer = null;
201
+ if (lastArgs) {
202
+ fn.apply(this, lastArgs);
203
+ lastArgs = null;
204
+ }
205
+ }, remaining);
206
+ }
207
+ }
208
+ };
209
+ return throttled;
210
+ }
211
+ function memoize(fn, resolver) {
212
+ const cache = /* @__PURE__ */ new Map();
213
+ const memoized = function(...args) {
214
+ const key = resolver ? resolver(...args) : String(args[0]);
215
+ if (cache.has(key)) {
216
+ return cache.get(key);
217
+ }
218
+ const result = fn.apply(this, args);
219
+ cache.set(key, result);
220
+ return result;
221
+ };
222
+ memoized.cache = cache;
223
+ return memoized;
224
+ }
225
+ function retry(fn, options) {
226
+ const {
227
+ attempts = 3,
228
+ baseDelay = 1e3,
229
+ maxDelay = 3e4,
230
+ shouldRetry = () => true
231
+ } = options ?? {};
232
+ let attempt = 0;
233
+ const execute = () => {
234
+ attempt++;
235
+ return fn().catch((error) => {
236
+ if (attempt >= attempts || !shouldRetry(error)) {
237
+ throw error;
238
+ }
239
+ const delay = Math.min(
240
+ baseDelay * Math.pow(2, attempt - 1) + Math.random() * baseDelay,
241
+ maxDelay
242
+ );
243
+ return new Promise((resolve2) => {
244
+ setTimeout(() => {
245
+ resolve2(execute());
246
+ }, delay);
247
+ });
248
+ });
249
+ };
250
+ return execute();
251
+ }
252
+ function noop() {
253
+ return void 0;
254
+ }
255
+ function identity(value) {
256
+ return value;
257
+ }
258
+ function once(fn) {
259
+ let called = false;
260
+ let result;
261
+ return function(...args) {
262
+ if (!called) {
263
+ called = true;
264
+ result = fn.apply(this, args);
265
+ }
266
+ return result;
267
+ };
268
+ }
269
+ function deepEqual(a, b) {
270
+ if (Object.is(a, b)) return true;
271
+ if (a === null || b === null || typeof a !== typeof b) return false;
272
+ if (typeof a !== "object") return false;
273
+ const aObj = a;
274
+ const bObj = b;
275
+ if (Array.isArray(a) && Array.isArray(b)) {
276
+ if (a.length !== b.length) return false;
277
+ for (let i = 0; i < a.length; i++) {
278
+ if (!deepEqual(a[i], b[i])) return false;
279
+ }
280
+ return true;
281
+ }
282
+ if (a instanceof Date && b instanceof Date) {
283
+ return a.getTime() === b.getTime();
284
+ }
285
+ if (a instanceof RegExp && b instanceof RegExp) {
286
+ return a.source === b.source && a.flags === b.flags;
287
+ }
288
+ if (a instanceof Map && b instanceof Map) {
289
+ if (a.size !== b.size) return false;
290
+ for (const [k, v] of a) {
291
+ if (!b.has(k) || !deepEqual(v, b.get(k))) return false;
292
+ }
293
+ return true;
294
+ }
295
+ if (a instanceof Set && b instanceof Set) {
296
+ if (a.size !== b.size) return false;
297
+ for (const v of a) {
298
+ if (!b.has(v)) return false;
299
+ }
300
+ return true;
301
+ }
302
+ const keysA = Object.keys(aObj);
303
+ const keysB = Object.keys(bObj);
304
+ if (keysA.length !== keysB.length) return false;
305
+ for (const key of keysA) {
306
+ if (!Object.prototype.hasOwnProperty.call(bObj, key)) return false;
307
+ if (!deepEqual(aObj[key], bObj[key])) return false;
308
+ }
309
+ return true;
310
+ }
311
+ function pipe(initial, ...fns) {
312
+ return fns.reduce((acc, fn) => fn(acc), initial);
313
+ }
314
+ function compose(...fns) {
315
+ return (initial) => fns.reduceRight((acc, fn) => fn(acc), initial);
316
+ }
317
+
318
+ // src/math/index.ts
319
+ var DivisionByZeroError = class extends Error {
320
+ constructor() {
321
+ super("Division by zero");
322
+ this.name = "DivisionByZeroError";
323
+ }
324
+ };
325
+ function getPrecision(value) {
326
+ if (!isFinite(value)) return 0;
327
+ const eIndex = String(value).indexOf("e");
328
+ if (eIndex > -1) {
329
+ const exp = parseInt(String(value).slice(eIndex + 1), 10);
330
+ if (exp < 0) return Math.abs(exp);
331
+ return 0;
332
+ }
333
+ const str = String(value);
334
+ const dot = str.indexOf(".");
335
+ return dot === -1 ? 0 : str.length - dot - 1;
336
+ }
337
+ function toPrecisionFactor(a, b) {
338
+ return Math.pow(10, Math.max(getPrecision(a), getPrecision(b)));
339
+ }
340
+ function add(a, b) {
341
+ const factor = toPrecisionFactor(a, b);
342
+ return (Math.round(a * factor) + Math.round(b * factor)) / factor;
343
+ }
344
+ function sub(a, b) {
345
+ const factor = toPrecisionFactor(a, b);
346
+ return (Math.round(a * factor) - Math.round(b * factor)) / factor;
347
+ }
348
+ function mul(a, b) {
349
+ const factorA = toPrecisionFactor(a, 1);
350
+ const factorB = toPrecisionFactor(1, b);
351
+ const result = Math.round(a * factorA) * Math.round(b * factorB) / (factorA * factorB);
352
+ return result;
353
+ }
354
+ function div(a, b) {
355
+ if (b === 0) throw new DivisionByZeroError();
356
+ const factor = toPrecisionFactor(a, b);
357
+ return Math.round(a * factor) / Math.round(b * factor);
358
+ }
359
+ function round(value, precision = 0) {
360
+ const factor = Math.pow(10, precision);
361
+ const shifted = Number((value * factor).toPrecision(15));
362
+ return Math.round(shifted) / factor;
363
+ }
364
+ function floor(value, precision = 0) {
365
+ const factor = Math.pow(10, precision);
366
+ return Math.floor(value * factor) / factor;
367
+ }
368
+ function ceil(value, precision = 0) {
369
+ const factor = Math.pow(10, precision);
370
+ return Math.ceil(value * factor) / factor;
371
+ }
372
+ function approxEqual(a, b, tolerance = Number.EPSILON) {
373
+ return Math.abs(a - b) <= tolerance;
374
+ }
375
+ function clamp(value, min, max) {
376
+ if (min > max) {
377
+ throw new RangeError("Minimum value cannot exceed maximum value");
378
+ }
379
+ return Math.min(Math.max(value, min), max);
380
+ }
381
+ function sum(values) {
382
+ let total = 0;
383
+ for (let i = 0; i < values.length; i++) {
384
+ total += values[i];
385
+ }
386
+ return total;
387
+ }
388
+ function average(values) {
389
+ if (values.length === 0) {
390
+ throw new RangeError("Cannot compute average of an empty array");
391
+ }
392
+ return sum(values) / values.length;
393
+ }
394
+ function randomInt(min, max) {
395
+ if (!Number.isInteger(min) || !Number.isInteger(max)) {
396
+ throw new RangeError("Arguments must be integers");
397
+ }
398
+ if (min > max) {
399
+ throw new RangeError("Minimum value cannot exceed maximum value");
400
+ }
401
+ return Math.floor(Math.random() * (max - min + 1)) + min;
402
+ }
403
+ function inRange(value, min, max) {
404
+ return value >= min && value <= max;
405
+ }
406
+ function median(values) {
407
+ if (values.length === 0) throw new RangeError("Cannot compute median of an empty array");
408
+ const sorted = [...values].sort((a, b) => a - b);
409
+ const mid = Math.floor(sorted.length / 2);
410
+ return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
411
+ }
412
+ function stddev(values) {
413
+ if (values.length < 2) throw new RangeError("Need at least 2 values for stddev");
414
+ const mean = sum(values) / values.length;
415
+ const sqDiffs = values.map((v) => (v - mean) ** 2);
416
+ return Math.sqrt(sqDiffs.reduce((a, b) => a + b, 0) / values.length);
417
+ }
418
+ function sampleStddev(values) {
419
+ if (values.length < 2) throw new RangeError("Need at least 2 values for sample stddev");
420
+ const mean = sum(values) / values.length;
421
+ const sqDiffs = values.map((v) => (v - mean) ** 2);
422
+ return Math.sqrt(sqDiffs.reduce((a, b) => a + b, 0) / (values.length - 1));
423
+ }
424
+ function percentile(values, p) {
425
+ if (values.length === 0) throw new RangeError("Cannot compute percentile of empty array");
426
+ if (p < 0 || p > 100) throw new RangeError("Percentile must be between 0 and 100");
427
+ const sorted = [...values].sort((a, b) => a - b);
428
+ const rank = p / 100 * (sorted.length - 1);
429
+ const lower = Math.floor(rank);
430
+ const upper = Math.ceil(rank);
431
+ if (lower === upper) return sorted[lower];
432
+ return sorted[lower] + (sorted[upper] - sorted[lower]) * (rank - lower);
433
+ }
434
+ function correlation(x, y) {
435
+ if (x.length !== y.length) throw new RangeError("Arrays must have the same length");
436
+ if (x.length < 2) throw new RangeError("Need at least 2 pairs for correlation");
437
+ const n = x.length;
438
+ const meanX = sum(x) / n;
439
+ const meanY = sum(y) / n;
440
+ let num = 0;
441
+ let denX = 0;
442
+ let denY = 0;
443
+ for (let i = 0; i < n; i++) {
444
+ const dx = x[i] - meanX;
445
+ const dy = y[i] - meanY;
446
+ num += dx * dy;
447
+ denX += dx * dx;
448
+ denY += dy * dy;
449
+ }
450
+ if (denX === 0 || denY === 0) return 0;
451
+ return num / Math.sqrt(denX * denY);
452
+ }
453
+ function formatCurrency(value, options) {
454
+ const locale = options?.locale ?? "id-ID";
455
+ const currency = options?.currency ?? "IDR";
456
+ const notation = options?.notation ?? "standard";
457
+ try {
458
+ return new Intl.NumberFormat(locale, {
459
+ style: "currency",
460
+ currency,
461
+ notation,
462
+ minimumFractionDigits: 0,
463
+ maximumFractionDigits: 2
464
+ }).format(value);
465
+ } catch {
466
+ return `${currency} ${value.toLocaleString(locale)}`;
467
+ }
468
+ }
469
+ function isEven(n) {
470
+ return n % 2 === 0;
471
+ }
472
+ function isOdd(n) {
473
+ return n % 2 !== 0;
474
+ }
475
+ function gcd(a, b) {
476
+ if (!Number.isInteger(a) || !Number.isInteger(b)) {
477
+ throw new RangeError("Arguments must be integers");
478
+ }
479
+ a = Math.abs(a);
480
+ b = Math.abs(b);
481
+ while (b !== 0) {
482
+ const t = b;
483
+ b = a % b;
484
+ a = t;
485
+ }
486
+ return a;
487
+ }
488
+ function lcm(a, b) {
489
+ if (!Number.isInteger(a) || !Number.isInteger(b)) {
490
+ throw new RangeError("Arguments must be integers");
491
+ }
492
+ if (a === 0 || b === 0) {
493
+ throw new RangeError("Arguments must be non-zero");
494
+ }
495
+ return Math.abs(a * b) / gcd(a, b);
496
+ }
497
+ function factorial(n) {
498
+ if (!Number.isInteger(n)) {
499
+ throw new RangeError("Argument must be an integer");
500
+ }
501
+ if (n < 0) {
502
+ throw new RangeError("Factorial is not defined for negative numbers");
503
+ }
504
+ let result = 1;
505
+ for (let i = 2; i <= n; i++) {
506
+ result *= i;
507
+ }
508
+ return result;
509
+ }
510
+ function isPrime(n) {
511
+ if (!Number.isInteger(n)) {
512
+ throw new RangeError("Argument must be an integer");
513
+ }
514
+ if (n < 2) return false;
515
+ if (n === 2 || n === 3) return true;
516
+ if (n % 2 === 0 || n % 3 === 0) return false;
517
+ const limit = Math.sqrt(n);
518
+ for (let i = 5; i <= limit; i += 6) {
519
+ if (n % i === 0 || n % (i + 2) === 0) return false;
520
+ }
521
+ return true;
522
+ }
523
+ function toRadians(degrees) {
524
+ return degrees * Math.PI / 180;
525
+ }
526
+ function toDegrees(radians) {
527
+ return radians * 180 / Math.PI;
528
+ }
529
+ function lerp(a, b, t) {
530
+ return a + (b - a) * t;
531
+ }
532
+ function percentageOf(value, total) {
533
+ if (total === 0) {
534
+ throw new RangeError("Total must be non-zero");
535
+ }
536
+ return value / total * 100;
537
+ }
538
+ function mapRange(value, inMin, inMax, outMin, outMax) {
539
+ if (inMin === inMax) {
540
+ throw new RangeError("Input range must not be zero");
541
+ }
542
+ return (value - inMin) / (inMax - inMin) * (outMax - outMin) + outMin;
543
+ }
544
+ function mode(values) {
545
+ if (values.length === 0) {
546
+ throw new RangeError("Cannot compute mode of an empty array");
547
+ }
548
+ const freq = /* @__PURE__ */ new Map();
549
+ let maxFreq = 0;
550
+ for (const v of values) {
551
+ const count = (freq.get(v) ?? 0) + 1;
552
+ freq.set(v, count);
553
+ if (count > maxFreq) maxFreq = count;
554
+ }
555
+ const result = [];
556
+ for (const [v, count] of freq) {
557
+ if (count === maxFreq) result.push(v);
558
+ }
559
+ return result;
560
+ }
561
+ function range(start, end, step) {
562
+ const dir = end >= start ? 1 : -1;
563
+ const s = step ?? dir;
564
+ if (s === 0) {
565
+ throw new RangeError("Step must not be zero");
566
+ }
567
+ if ((end - start) * s < 0) {
568
+ return [];
569
+ }
570
+ const result = [];
571
+ let i = start;
572
+ if (s > 0) {
573
+ while (i <= end) {
574
+ result.push(i);
575
+ i += s;
576
+ }
577
+ } else {
578
+ while (i >= end) {
579
+ result.push(i);
580
+ i += s;
581
+ }
582
+ }
583
+ return result;
584
+ }
585
+ function weightedAverage(values, weights) {
586
+ if (values.length === 0 || weights.length === 0) {
587
+ throw new RangeError("Arrays must not be empty");
588
+ }
589
+ if (values.length !== weights.length) {
590
+ throw new RangeError("Values and weights must have the same length");
591
+ }
592
+ let weightedSum = 0;
593
+ let weightSum = 0;
594
+ for (let i = 0; i < values.length; i++) {
595
+ weightedSum += values[i] * weights[i];
596
+ weightSum += weights[i];
597
+ }
598
+ if (weightSum === 0) {
599
+ throw new RangeError("Sum of weights must be non-zero");
600
+ }
601
+ return weightedSum / weightSum;
602
+ }
603
+ function geometricMean(values) {
604
+ if (values.length === 0) {
605
+ throw new RangeError("Cannot compute geometric mean of an empty array");
606
+ }
607
+ for (const v of values) {
608
+ if (v < 0) {
609
+ throw new RangeError("Values must be non-negative for geometric mean");
610
+ }
611
+ }
612
+ const logSum = values.reduce((acc, v) => v === 0 ? acc : acc + Math.log(v), 0);
613
+ if (logSum === -Infinity) return 0;
614
+ return Math.exp(logSum / values.length);
615
+ }
616
+ function combinations(n, k) {
617
+ if (!Number.isInteger(n) || !Number.isInteger(k)) {
618
+ throw new RangeError("Arguments must be integers");
619
+ }
620
+ if (n < 0 || k < 0) {
621
+ throw new RangeError("Arguments must be non-negative");
622
+ }
623
+ if (k > n) {
624
+ throw new RangeError("k must not exceed n");
625
+ }
626
+ if (k === 0 || k === n) return 1;
627
+ const r = Math.min(k, n - k);
628
+ let result = 1;
629
+ for (let i = 1; i <= r; i++) {
630
+ result = result * (n - r + i) / i;
631
+ }
632
+ return result;
633
+ }
634
+ function permutations(n, k) {
635
+ if (!Number.isInteger(n) || !Number.isInteger(k)) {
636
+ throw new RangeError("Arguments must be integers");
637
+ }
638
+ if (n < 0 || k < 0) {
639
+ throw new RangeError("Arguments must be non-negative");
640
+ }
641
+ if (k > n) {
642
+ throw new RangeError("k must not exceed n");
643
+ }
644
+ let result = 1;
645
+ for (let i = n; i > n - k; i--) {
646
+ result *= i;
647
+ }
648
+ return result;
649
+ }
650
+
651
+ // src/date/index.ts
652
+ var InvalidDateError = class extends Error {
653
+ constructor(input) {
654
+ super(`Invalid date: ${String(input)}`);
655
+ this.name = "InvalidDateError";
656
+ }
657
+ };
658
+ var MONTH_NAMES_SHORT = [
659
+ "Jan",
660
+ "Feb",
661
+ "Mar",
662
+ "Apr",
663
+ "May",
664
+ "Jun",
665
+ "Jul",
666
+ "Aug",
667
+ "Sep",
668
+ "Oct",
669
+ "Nov",
670
+ "Dec"
671
+ ];
672
+ var MONTH_NAMES_FULL = [
673
+ "January",
674
+ "February",
675
+ "March",
676
+ "April",
677
+ "May",
678
+ "June",
679
+ "July",
680
+ "August",
681
+ "September",
682
+ "October",
683
+ "November",
684
+ "December"
685
+ ];
686
+ var MONTH_MAP = {
687
+ jan: 0,
688
+ january: 0,
689
+ feb: 1,
690
+ february: 1,
691
+ mar: 2,
692
+ march: 2,
693
+ apr: 3,
694
+ april: 3,
695
+ may: 4,
696
+ jun: 5,
697
+ june: 5,
698
+ jul: 6,
699
+ july: 6,
700
+ aug: 7,
701
+ august: 7,
702
+ sep: 8,
703
+ september: 8,
704
+ oct: 9,
705
+ october: 9,
706
+ nov: 10,
707
+ november: 10,
708
+ dec: 11,
709
+ december: 11
710
+ };
711
+ function formatDate(date, format2 = "YYYY-MM-DD") {
712
+ const year = date.getFullYear();
713
+ const month = date.getMonth();
714
+ const day = date.getDate();
715
+ const hours = date.getHours();
716
+ const minutes = date.getMinutes();
717
+ const seconds = date.getSeconds();
718
+ const ms = date.getMilliseconds();
719
+ const pad2 = (n, len = 2) => String(n).padStart(len, "0");
720
+ return format2.replace(/YYYY/g, String(year)).replace(/YY/g, String(year).slice(-2)).replace(/MMMM/g, MONTH_NAMES_FULL[month]).replace(/MMM/g, MONTH_NAMES_SHORT[month]).replace(/MM/g, pad2(month + 1)).replace(/DD/g, pad2(day)).replace(/HH/g, pad2(hours)).replace(/mm/g, pad2(minutes)).replace(/ss/g, pad2(seconds)).replace(/SSS/g, pad2(ms, 3));
721
+ }
722
+ function parseDate(input) {
723
+ if (input instanceof Date) {
724
+ if (isNaN(input.getTime())) throw new InvalidDateError(input);
725
+ return new Date(input.getTime());
726
+ }
727
+ if (typeof input === "number") {
728
+ const d = new Date(input);
729
+ if (isNaN(d.getTime())) throw new InvalidDateError(input);
730
+ return d;
731
+ }
732
+ const trimmed = input.trim();
733
+ const isoMatch = trimmed.match(/^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?)?(?:Z|[+-]\d{2}:?\d{2})?$/);
734
+ if (isoMatch) {
735
+ const d = new Date(
736
+ parseInt(isoMatch[1], 10),
737
+ parseInt(isoMatch[2], 10) - 1,
738
+ parseInt(isoMatch[3], 10),
739
+ isoMatch[4] ? parseInt(isoMatch[4], 10) : 0,
740
+ isoMatch[5] ? parseInt(isoMatch[5], 10) : 0,
741
+ isoMatch[6] ? parseInt(isoMatch[6], 10) : 0,
742
+ isoMatch[7] ? parseInt(isoMatch[7].padEnd(3, "0"), 10) : 0
743
+ );
744
+ if (!isNaN(d.getTime())) return d;
745
+ }
746
+ const dmyMatch = trimmed.match(/^(\d{1,2})[\/-](\d{1,2})[\/-](\d{4})$/);
747
+ if (dmyMatch) {
748
+ const year = parseInt(dmyMatch[3], 10);
749
+ const month = parseInt(dmyMatch[2], 10) - 1;
750
+ const day = parseInt(dmyMatch[1], 10);
751
+ const d = new Date(year, month, day);
752
+ if (!isNaN(d.getTime()) && d.getMonth() === month && d.getDate() === day) return d;
753
+ }
754
+ const textMatch = trimmed.match(/^(\d{1,2})\s+([a-zA-Z]+)\s+(\d{4})$/);
755
+ if (textMatch) {
756
+ const monthIndex = MONTH_MAP[textMatch[2].toLowerCase()];
757
+ if (monthIndex !== void 0) {
758
+ const year = parseInt(textMatch[3], 10);
759
+ const day = parseInt(textMatch[1], 10);
760
+ const d = new Date(year, monthIndex, day);
761
+ if (!isNaN(d.getTime()) && d.getMonth() === monthIndex && d.getDate() === day) return d;
762
+ }
763
+ }
764
+ const numMatch = trimmed.match(/^-?\d+$/);
765
+ if (numMatch) {
766
+ const d = new Date(parseInt(numMatch[0], 10));
767
+ if (!isNaN(d.getTime())) return d;
768
+ }
769
+ const fallback = new Date(trimmed);
770
+ if (!isNaN(fallback.getTime())) return fallback;
771
+ throw new InvalidDateError(input);
772
+ }
773
+ function isValidDate(d) {
774
+ return d instanceof Date && !isNaN(d.getTime());
775
+ }
776
+ var MS_IN_SECOND = 1e3;
777
+ var MS_IN_MINUTE = 60 * MS_IN_SECOND;
778
+ var MS_IN_HOUR = 60 * MS_IN_MINUTE;
779
+ var MS_IN_DAY = 24 * MS_IN_HOUR;
780
+ function dateDiff(date1, date2) {
781
+ if (!isValidDate(date1) || !isValidDate(date2)) {
782
+ throw new InvalidDateError("Invalid date provided to dateDiff");
783
+ }
784
+ let years = date2.getFullYear() - date1.getFullYear();
785
+ let months = date2.getMonth() - date1.getMonth();
786
+ let days = date2.getDate() - date1.getDate();
787
+ if (days < 0) {
788
+ months -= 1;
789
+ const prevMonth = new Date(date2.getFullYear(), date2.getMonth(), 0);
790
+ days += prevMonth.getDate();
791
+ }
792
+ if (months < 0) {
793
+ years -= 1;
794
+ months += 12;
795
+ }
796
+ const msDiff = Math.abs(date2.getTime() - date1.getTime());
797
+ const totalSeconds = Math.floor(msDiff / MS_IN_SECOND);
798
+ const hours = Math.floor(msDiff % MS_IN_DAY / MS_IN_HOUR);
799
+ const minutes = Math.floor(msDiff % MS_IN_HOUR / MS_IN_MINUTE);
800
+ const seconds = totalSeconds % 60;
801
+ return { years, months, days, hours, minutes, seconds };
802
+ }
803
+ function addDays(date, days) {
804
+ if (!isValidDate(date)) throw new InvalidDateError(date);
805
+ const result = new Date(date.getTime());
806
+ result.setDate(result.getDate() + days);
807
+ return result;
808
+ }
809
+ function addMonths(date, months) {
810
+ if (!isValidDate(date)) throw new InvalidDateError(date);
811
+ const result = new Date(date.getTime());
812
+ const targetMonth = result.getMonth() + months;
813
+ result.setMonth(targetMonth);
814
+ if (result.getMonth() !== (targetMonth % 12 + 12) % 12) {
815
+ result.setDate(0);
816
+ }
817
+ return result;
818
+ }
819
+ function addYears(date, years) {
820
+ if (!isValidDate(date)) throw new InvalidDateError(date);
821
+ const result = new Date(date.getTime());
822
+ const targetYear = result.getFullYear() + years;
823
+ result.setFullYear(targetYear);
824
+ if (result.getFullYear() !== targetYear) {
825
+ result.setDate(0);
826
+ }
827
+ return result;
828
+ }
829
+ function startOfDay(date) {
830
+ if (!isValidDate(date)) throw new InvalidDateError(date);
831
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0);
832
+ }
833
+ function endOfDay(date) {
834
+ if (!isValidDate(date)) throw new InvalidDateError(date);
835
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);
836
+ }
837
+ function startOfMonth(date) {
838
+ if (!isValidDate(date)) throw new InvalidDateError(date);
839
+ return new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0, 0);
840
+ }
841
+ function endOfMonth(date) {
842
+ if (!isValidDate(date)) throw new InvalidDateError(date);
843
+ return new Date(date.getFullYear(), date.getMonth() + 1, 0, 23, 59, 59, 999);
844
+ }
845
+ function startOfYear(date) {
846
+ if (!isValidDate(date)) throw new InvalidDateError(date);
847
+ return new Date(date.getFullYear(), 0, 1, 0, 0, 0, 0);
848
+ }
849
+ function endOfYear(date) {
850
+ if (!isValidDate(date)) throw new InvalidDateError(date);
851
+ return new Date(date.getFullYear(), 12, 0, 23, 59, 59, 999);
852
+ }
853
+ function isWeekend(date) {
854
+ if (!isValidDate(date)) throw new InvalidDateError(date);
855
+ const day = date.getDay();
856
+ return day === 0 || day === 6;
857
+ }
858
+ function isLeapYear(year) {
859
+ return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
860
+ }
861
+ function isBefore(date1, date2) {
862
+ if (!isValidDate(date1) || !isValidDate(date2)) {
863
+ throw new InvalidDateError("Invalid date provided to isBefore");
864
+ }
865
+ return date1.getTime() < date2.getTime();
866
+ }
867
+ function isAfter(date1, date2) {
868
+ if (!isValidDate(date1) || !isValidDate(date2)) {
869
+ throw new InvalidDateError("Invalid date provided to isAfter");
870
+ }
871
+ return date1.getTime() > date2.getTime();
872
+ }
873
+ function isBetween(date, start, end) {
874
+ if (!isValidDate(date) || !isValidDate(start) || !isValidDate(end)) {
875
+ throw new InvalidDateError("Invalid date provided to isBetween");
876
+ }
877
+ return date.getTime() >= start.getTime() && date.getTime() <= end.getTime();
878
+ }
879
+ function isBusinessDay(date) {
880
+ return isValidDate(date) && !isWeekend(date);
881
+ }
882
+ function addBusinessDays(date, days) {
883
+ if (!isValidDate(date)) throw new InvalidDateError(date);
884
+ const result = new Date(date.getTime());
885
+ let remaining = Math.abs(days);
886
+ const step = days >= 0 ? 1 : -1;
887
+ while (remaining > 0) {
888
+ result.setDate(result.getDate() + step);
889
+ const day = result.getDay();
890
+ if (day !== 0 && day !== 6) {
891
+ remaining--;
892
+ }
893
+ }
894
+ return result;
895
+ }
896
+ function calculateAge(birthDate) {
897
+ if (!isValidDate(birthDate)) throw new InvalidDateError(birthDate);
898
+ const today = /* @__PURE__ */ new Date();
899
+ let age = today.getFullYear() - birthDate.getFullYear();
900
+ const monthDiff = today.getMonth() - birthDate.getMonth();
901
+ if (monthDiff < 0 || monthDiff === 0 && today.getDate() < birthDate.getDate()) {
902
+ age--;
903
+ }
904
+ return age;
905
+ }
906
+ var LOCALE_LABELS = {
907
+ id: {
908
+ years: { single: "tahun", plural: "tahun" },
909
+ months: { single: "bulan", plural: "bulan" },
910
+ weeks: { single: "minggu", plural: "minggu" },
911
+ days: { single: "hari", plural: "hari" },
912
+ hours: { single: "jam", plural: "jam" },
913
+ minutes: { single: "menit", plural: "menit" },
914
+ seconds: { single: "detik", plural: "detik" }
915
+ },
916
+ en: {
917
+ years: { single: "year", plural: "years" },
918
+ months: { single: "month", plural: "months" },
919
+ weeks: { single: "week", plural: "weeks" },
920
+ days: { single: "day", plural: "days" },
921
+ hours: { single: "hour", plural: "hours" },
922
+ minutes: { single: "minute", plural: "minutes" },
923
+ seconds: { single: "second", plural: "seconds" }
924
+ }
925
+ };
926
+ function getSuffix(diffMs, kind, locale) {
927
+ if (diffMs < 0) {
928
+ return locale === "en" ? "ago" : "yang lalu";
929
+ }
930
+ if (kind === "remaining") {
931
+ return locale === "en" ? "remaining" : "lagi";
932
+ }
933
+ return locale === "en" ? "ago" : "yang lalu";
934
+ }
935
+ function formatRelativeTime(absDiffMs, suffix, locale) {
936
+ const labels = LOCALE_LABELS[locale] ?? LOCALE_LABELS.id;
937
+ const seconds = Math.floor(absDiffMs / 1e3);
938
+ const minutes = Math.floor(seconds / 60);
939
+ const hours = Math.floor(minutes / 60);
940
+ const days = Math.floor(hours / 24);
941
+ const weeks = Math.floor(days / 7);
942
+ const months = Math.floor(days / 30.4375);
943
+ const years = Math.floor(days / 365.25);
944
+ let count;
945
+ let unit;
946
+ if (years >= 1) {
947
+ count = years;
948
+ unit = "years";
949
+ } else if (months >= 1) {
950
+ count = months;
951
+ unit = "months";
952
+ } else if (weeks >= 1) {
953
+ count = weeks;
954
+ unit = "weeks";
955
+ } else if (days >= 1) {
956
+ count = days;
957
+ unit = "days";
958
+ } else if (hours >= 1) {
959
+ count = hours;
960
+ unit = "hours";
961
+ } else if (minutes >= 1) {
962
+ count = minutes;
963
+ unit = "minutes";
964
+ } else {
965
+ count = Math.max(1, seconds);
966
+ unit = "seconds";
967
+ }
968
+ const label = count === 1 ? labels[unit].single : labels[unit].plural;
969
+ return `${count} ${label} ${suffix}`;
970
+ }
971
+ function timeAgo(date, options) {
972
+ const diff = Date.now() - date.getTime();
973
+ const locale = options?.locale ?? "id";
974
+ const suffix = getSuffix(diff, "ago", locale);
975
+ return formatRelativeTime(Math.abs(diff), suffix, locale);
976
+ }
977
+ function timeRemaining(target, options) {
978
+ const diff = target.getTime() - Date.now();
979
+ const locale = options?.locale ?? "id";
980
+ const suffix = getSuffix(diff, "remaining", locale);
981
+ return formatRelativeTime(Math.abs(diff), suffix, locale);
982
+ }
983
+ function formatDuration(duration, options) {
984
+ const locale = options?.locale ?? "id";
985
+ const labels = LOCALE_LABELS[locale] ?? LOCALE_LABELS.id;
986
+ const parts = [];
987
+ const entries = [
988
+ ["years", duration.years],
989
+ ["months", duration.months],
990
+ ["days", duration.days],
991
+ ["hours", duration.hours],
992
+ ["minutes", duration.minutes],
993
+ ["seconds", duration.seconds]
994
+ ];
995
+ for (const [key, value] of entries) {
996
+ if (value > 0) {
997
+ const label = value === 1 ? labels[key].single : labels[key].plural;
998
+ parts.push(`${value} ${label}`);
999
+ }
1000
+ }
1001
+ if (parts.length === 0) {
1002
+ const label = labels.seconds.plural;
1003
+ return `0 ${label}`;
1004
+ }
1005
+ return parts.join(" ");
1006
+ }
1007
+ var TIMEZONE_WIB = 7;
1008
+ var TIMEZONE_WITA = 8;
1009
+ var TIMEZONE_WIT = 9;
1010
+ function toTimezone(date, offsetHours) {
1011
+ if (!isValidDate(date)) throw new InvalidDateError(date);
1012
+ const utcMs = date.getTime() + date.getTimezoneOffset() * 6e4;
1013
+ return new Date(utcMs + offsetHours * 36e5);
1014
+ }
1015
+ function formatInTimezone(date, format2, offsetHours) {
1016
+ return formatDate(toTimezone(date, offsetHours), format2);
1017
+ }
1018
+ function isToday(date) {
1019
+ if (!isValidDate(date)) throw new InvalidDateError(date);
1020
+ const now = /* @__PURE__ */ new Date();
1021
+ return date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate();
1022
+ }
1023
+ function isYesterday(date) {
1024
+ if (!isValidDate(date)) throw new InvalidDateError(date);
1025
+ const yesterday = /* @__PURE__ */ new Date();
1026
+ yesterday.setDate(yesterday.getDate() - 1);
1027
+ return date.getFullYear() === yesterday.getFullYear() && date.getMonth() === yesterday.getMonth() && date.getDate() === yesterday.getDate();
1028
+ }
1029
+ function isTomorrow(date) {
1030
+ if (!isValidDate(date)) throw new InvalidDateError(date);
1031
+ const tomorrow = /* @__PURE__ */ new Date();
1032
+ tomorrow.setDate(tomorrow.getDate() + 1);
1033
+ return date.getFullYear() === tomorrow.getFullYear() && date.getMonth() === tomorrow.getMonth() && date.getDate() === tomorrow.getDate();
1034
+ }
1035
+ function isPast(date) {
1036
+ if (!isValidDate(date)) throw new InvalidDateError(date);
1037
+ return date.getTime() < Date.now();
1038
+ }
1039
+ function isFuture(date) {
1040
+ if (!isValidDate(date)) throw new InvalidDateError(date);
1041
+ return date.getTime() > Date.now();
1042
+ }
1043
+ function isSameDay(date1, date2) {
1044
+ if (!isValidDate(date1) || !isValidDate(date2)) {
1045
+ throw new InvalidDateError("Invalid date provided to isSameDay");
1046
+ }
1047
+ return date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && date1.getDate() === date2.getDate();
1048
+ }
1049
+ function daysInMonth(date) {
1050
+ if (!isValidDate(date)) throw new InvalidDateError(date);
1051
+ return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
1052
+ }
1053
+ function dayOfYear(date) {
1054
+ if (!isValidDate(date)) throw new InvalidDateError(date);
1055
+ const start = new Date(date.getFullYear(), 0, 0);
1056
+ return Math.floor((date.getTime() - start.getTime()) / MS_IN_DAY);
1057
+ }
1058
+ function weekOfYear(date) {
1059
+ if (!isValidDate(date)) throw new InvalidDateError(date);
1060
+ const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
1061
+ const dayNum = d.getUTCDay() || 7;
1062
+ d.setUTCDate(d.getUTCDate() + 4 - dayNum);
1063
+ const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
1064
+ const weekNum = Math.ceil(((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7);
1065
+ return weekNum;
1066
+ }
1067
+ function quarter(date) {
1068
+ if (!isValidDate(date)) throw new InvalidDateError(date);
1069
+ return Math.floor(date.getMonth() / 3) + 1;
1070
+ }
1071
+ function maxDate(dates) {
1072
+ if (dates.length === 0) throw new Error("maxDate requires at least one date");
1073
+ const ms = Math.max(...dates.map((d) => {
1074
+ if (!isValidDate(d)) throw new InvalidDateError(d);
1075
+ return d.getTime();
1076
+ }));
1077
+ return new Date(ms);
1078
+ }
1079
+ function minDate(dates) {
1080
+ if (dates.length === 0) throw new Error("minDate requires at least one date");
1081
+ const ms = Math.min(...dates.map((d) => {
1082
+ if (!isValidDate(d)) throw new InvalidDateError(d);
1083
+ return d.getTime();
1084
+ }));
1085
+ return new Date(ms);
1086
+ }
1087
+ function getNextWeekday(date, targetDay) {
1088
+ if (!isValidDate(date)) throw new InvalidDateError(date);
1089
+ const result = new Date(date);
1090
+ const currentDay = result.getDay();
1091
+ let diff = targetDay - currentDay;
1092
+ if (diff <= 0) diff += 7;
1093
+ result.setDate(result.getDate() + diff);
1094
+ return result;
1095
+ }
1096
+ function getLastWeekday(date, targetDay) {
1097
+ if (!isValidDate(date)) throw new InvalidDateError(date);
1098
+ const result = new Date(date);
1099
+ const currentDay = result.getDay();
1100
+ let diff = currentDay - targetDay;
1101
+ if (diff <= 0) diff += 7;
1102
+ result.setDate(result.getDate() - diff);
1103
+ return result;
1104
+ }
1105
+ function nextMonday(date) {
1106
+ return getNextWeekday(date, 1);
1107
+ }
1108
+ function nextTuesday(date) {
1109
+ return getNextWeekday(date, 2);
1110
+ }
1111
+ function nextWednesday(date) {
1112
+ return getNextWeekday(date, 3);
1113
+ }
1114
+ function nextThursday(date) {
1115
+ return getNextWeekday(date, 4);
1116
+ }
1117
+ function nextFriday(date) {
1118
+ return getNextWeekday(date, 5);
1119
+ }
1120
+ function nextSaturday(date) {
1121
+ return getNextWeekday(date, 6);
1122
+ }
1123
+ function nextSunday(date) {
1124
+ return getNextWeekday(date, 0);
1125
+ }
1126
+ function lastMonday(date) {
1127
+ return getLastWeekday(date, 1);
1128
+ }
1129
+ function lastTuesday(date) {
1130
+ return getLastWeekday(date, 2);
1131
+ }
1132
+ function lastWednesday(date) {
1133
+ return getLastWeekday(date, 3);
1134
+ }
1135
+ function lastThursday(date) {
1136
+ return getLastWeekday(date, 4);
1137
+ }
1138
+ function lastFriday(date) {
1139
+ return getLastWeekday(date, 5);
1140
+ }
1141
+ function lastSaturday(date) {
1142
+ return getLastWeekday(date, 6);
1143
+ }
1144
+ function lastSunday(date) {
1145
+ return getLastWeekday(date, 0);
1146
+ }
1147
+ function parseDuration(input) {
1148
+ const regex = /(\d+)\s*([wdhms])/g;
1149
+ let ms = 0;
1150
+ let match;
1151
+ while ((match = regex.exec(input)) !== null) {
1152
+ const val = parseInt(match[1], 10);
1153
+ switch (match[2]) {
1154
+ case "w":
1155
+ ms += val * 7 * MS_IN_DAY;
1156
+ break;
1157
+ case "d":
1158
+ ms += val * MS_IN_DAY;
1159
+ break;
1160
+ case "h":
1161
+ ms += val * MS_IN_HOUR;
1162
+ break;
1163
+ case "m":
1164
+ ms += val * MS_IN_MINUTE;
1165
+ break;
1166
+ case "s":
1167
+ ms += val * MS_IN_SECOND;
1168
+ break;
1169
+ }
1170
+ }
1171
+ return ms;
1172
+ }
1173
+ var INDONESIAN_FIXED_HOLIDAYS = [
1174
+ { name: "New Year", month: 0, day: 1 },
1175
+ { name: "Labor Day", month: 4, day: 1 },
1176
+ { name: "Pancasila Day", month: 5, day: 1 },
1177
+ { name: "Independence Day", month: 7, day: 17 },
1178
+ { name: "National Awakening Day", month: 4, day: 20 },
1179
+ { name: "National Heroes Day", month: 10, day: 10 },
1180
+ { name: "Christmas", month: 11, day: 25 }
1181
+ ];
1182
+ function computeEaster(year) {
1183
+ const a = year % 19;
1184
+ const b = Math.floor(year / 100);
1185
+ const c = year % 100;
1186
+ const d = Math.floor(b / 4);
1187
+ const e = b % 4;
1188
+ const f = Math.floor((b + 8) / 25);
1189
+ const g = Math.floor((b - f + 1) / 3);
1190
+ const h = (19 * a + b - d - g + 15) % 30;
1191
+ const i = Math.floor(c / 4);
1192
+ const k = c % 4;
1193
+ const l = (32 + 2 * e + 2 * i - h - k) % 7;
1194
+ const m = Math.floor((a + 11 * h + 22 * l) / 451);
1195
+ const month = Math.floor((h + l - 7 * m + 114) / 31);
1196
+ const day = (h + l - 7 * m + 114) % 31 + 1;
1197
+ return new Date(year, month - 1, day);
1198
+ }
1199
+ var CHINESE_NEW_YEAR = {
1200
+ 2024: { month: 1, day: 10 },
1201
+ 2025: { month: 0, day: 29 },
1202
+ 2026: { month: 1, day: 17 },
1203
+ 2027: { month: 1, day: 6 },
1204
+ 2028: { month: 0, day: 26 },
1205
+ 2029: { month: 1, day: 13 },
1206
+ 2030: { month: 2, day: 3 }
1207
+ };
1208
+ var NYEPI = {
1209
+ 2024: { month: 2, day: 11 },
1210
+ 2025: { month: 2, day: 29 },
1211
+ 2026: { month: 2, day: 19 },
1212
+ 2027: { month: 2, day: 7 },
1213
+ 2028: { month: 2, day: 26 },
1214
+ 2029: { month: 2, day: 15 },
1215
+ 2030: { month: 2, day: 5 }
1216
+ };
1217
+ var VESAK = {
1218
+ 2024: { month: 4, day: 23 },
1219
+ 2025: { month: 4, day: 12 },
1220
+ 2026: { month: 4, day: 31 },
1221
+ 2027: { month: 4, day: 20 },
1222
+ 2028: { month: 4, day: 9 },
1223
+ 2029: { month: 4, day: 28 },
1224
+ 2030: { month: 4, day: 18 }
1225
+ };
1226
+ var EID_AL_FITR = {
1227
+ 2024: [{ month: 3, day: 10 }, { month: 3, day: 11 }],
1228
+ 2025: [{ month: 2, day: 31 }, { month: 3, day: 1 }],
1229
+ 2026: [{ month: 2, day: 21 }, { month: 2, day: 22 }],
1230
+ 2027: [{ month: 2, day: 10 }, { month: 2, day: 11 }],
1231
+ 2028: [{ month: 2, day: 28 }, { month: 2, day: 29 }],
1232
+ 2029: [{ month: 2, day: 17 }, { month: 2, day: 18 }],
1233
+ 2030: [{ month: 2, day: 7 }, { month: 2, day: 8 }]
1234
+ };
1235
+ var EID_AL_ADHA = {
1236
+ 2024: { month: 5, day: 17 },
1237
+ 2025: { month: 5, day: 7 },
1238
+ 2026: { month: 4, day: 27 },
1239
+ 2027: { month: 4, day: 17 },
1240
+ 2028: { month: 5, day: 5 },
1241
+ 2029: { month: 4, day: 25 },
1242
+ 2030: { month: 4, day: 15 }
1243
+ };
1244
+ var ISLAMIC_NEW_YEAR = {
1245
+ 2024: { month: 6, day: 7 },
1246
+ 2025: { month: 5, day: 27 },
1247
+ 2026: { month: 5, day: 16 },
1248
+ 2027: { month: 5, day: 6 },
1249
+ 2028: { month: 6, day: 24 },
1250
+ 2029: { month: 6, day: 13 },
1251
+ 2030: { month: 6, day: 3 }
1252
+ };
1253
+ var PROPHETS_BIRTHDAY = {
1254
+ 2024: { month: 8, day: 16 },
1255
+ 2025: { month: 8, day: 5 },
1256
+ 2026: { month: 7, day: 26 },
1257
+ 2027: { month: 7, day: 16 },
1258
+ 2028: { month: 8, day: 3 },
1259
+ 2029: { month: 7, day: 23 },
1260
+ 2030: { month: 7, day: 13 }
1261
+ };
1262
+ var ISRA_MIRAJ = {
1263
+ 2024: { month: 1, day: 8 },
1264
+ 2025: { month: 0, day: 28 },
1265
+ 2026: { month: 0, day: 17 },
1266
+ 2027: { month: 0, day: 6 },
1267
+ 2028: { month: 0, day: 26 },
1268
+ 2029: { month: 1, day: 14 },
1269
+ 2030: { month: 1, day: 3 }
1270
+ };
1271
+ function addHolidayEntry(entries, name, month, day) {
1272
+ entries.push({ name, month, day });
1273
+ }
1274
+ function getIndonesianHolidaysForYear(year) {
1275
+ const holidays = [...INDONESIAN_FIXED_HOLIDAYS];
1276
+ const easter = computeEaster(year);
1277
+ addHolidayEntry(holidays, "Good Friday", easter.getMonth(), easter.getDate() - 2);
1278
+ addHolidayEntry(holidays, "Easter", easter.getMonth(), easter.getDate());
1279
+ const ascension = new Date(easter);
1280
+ ascension.setDate(ascension.getDate() + 39);
1281
+ addHolidayEntry(holidays, "Ascension of Jesus Christ", ascension.getMonth(), ascension.getDate());
1282
+ const cny = CHINESE_NEW_YEAR[year];
1283
+ if (cny) addHolidayEntry(holidays, "Chinese New Year", cny.month, cny.day);
1284
+ const nyepi = NYEPI[year];
1285
+ if (nyepi) addHolidayEntry(holidays, "Nyepi (Day of Silence)", nyepi.month, nyepi.day);
1286
+ const vesak = VESAK[year];
1287
+ if (vesak) addHolidayEntry(holidays, "Vesak (Buddha's Birthday)", vesak.month, vesak.day);
1288
+ const eidDays = EID_AL_FITR[year];
1289
+ if (eidDays) {
1290
+ eidDays.forEach((entry, idx) => {
1291
+ addHolidayEntry(holidays, idx === 0 ? "Eid al-Fitr" : "Eid al-Fitr (Day 2)", entry.month, entry.day);
1292
+ });
1293
+ }
1294
+ const eidAdha = EID_AL_ADHA[year];
1295
+ if (eidAdha) addHolidayEntry(holidays, "Eid al-Adha", eidAdha.month, eidAdha.day);
1296
+ const islNewYear = ISLAMIC_NEW_YEAR[year];
1297
+ if (islNewYear) addHolidayEntry(holidays, "Islamic New Year", islNewYear.month, islNewYear.day);
1298
+ const prophetBday = PROPHETS_BIRTHDAY[year];
1299
+ if (prophetBday) addHolidayEntry(holidays, "Prophet Muhammad's Birthday", prophetBday.month, prophetBday.day);
1300
+ const isra = ISRA_MIRAJ[year];
1301
+ if (isra) addHolidayEntry(holidays, "Isra' Mi'raj (Ascension of Prophet Muhammad)", isra.month, isra.day);
1302
+ return holidays;
1303
+ }
1304
+ function isHolidayIndonesia(date) {
1305
+ if (!isValidDate(date)) throw new InvalidDateError(date);
1306
+ const year = date.getFullYear();
1307
+ const holidays = getIndonesianHolidaysForYear(year);
1308
+ for (const h of holidays) {
1309
+ if (h.month === date.getMonth() && h.day === date.getDate()) {
1310
+ return true;
1311
+ }
1312
+ }
1313
+ return false;
1314
+ }
1315
+ function getIndonesianHolidayNames(date) {
1316
+ if (!isValidDate(date)) throw new InvalidDateError(date);
1317
+ const year = date.getFullYear();
1318
+ const holidays = getIndonesianHolidaysForYear(year);
1319
+ const names = [];
1320
+ for (const h of holidays) {
1321
+ if (h.month === date.getMonth() && h.day === date.getDate()) {
1322
+ names.push(h.name);
1323
+ }
1324
+ }
1325
+ return names;
1326
+ }
1327
+
1328
+ // src/crypto/index.ts
1329
+ function hash(str) {
1330
+ let h = 5381;
1331
+ for (let i = 0; i < str.length; i++) {
1332
+ h = (h << 5) + h + str.charCodeAt(i) | 0;
1333
+ }
1334
+ return h >>> 0;
1335
+ }
1336
+ function simpleHash(str) {
1337
+ let h1 = 1732584193;
1338
+ let h2 = 4023233417;
1339
+ let h3 = 2562383102;
1340
+ let h4 = 271733878;
1341
+ for (let i = 0; i < str.length; i++) {
1342
+ const c = str.charCodeAt(i);
1343
+ h1 = h1 + c | 0;
1344
+ h2 = h2 + (c << 3) + i | 0;
1345
+ h3 = h3 ^ c | 0;
1346
+ h4 = h4 + (c << 5) + (c << 1) | 0;
1347
+ }
1348
+ const toHex = (n) => (n >>> 0).toString(16).padStart(8, "0");
1349
+ return toHex(h1) + toHex(h2) + toHex(h3) + toHex(h4);
1350
+ }
1351
+ function getRandomBytes(size) {
1352
+ if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
1353
+ const bytes = new Uint8Array(size);
1354
+ crypto.getRandomValues(bytes);
1355
+ return bytes;
1356
+ }
1357
+ throw new Error("Crypto API unavailable. Cannot generate secure random bytes.");
1358
+ }
1359
+ function randomHex(size = 16) {
1360
+ const bytes = getRandomBytes(size);
1361
+ let result = "";
1362
+ for (let i = 0; i < bytes.length; i++) {
1363
+ result += bytes[i].toString(16).padStart(2, "0");
1364
+ }
1365
+ return result;
1366
+ }
1367
+ function utf8ToBytes(str) {
1368
+ if (typeof TextEncoder !== "undefined") {
1369
+ return new TextEncoder().encode(str);
1370
+ }
1371
+ const bytes = new Uint8Array(str.length);
1372
+ for (let i = 0; i < str.length; i++) {
1373
+ bytes[i] = str.charCodeAt(i);
1374
+ }
1375
+ return bytes;
1376
+ }
1377
+ function bytesToUtf8(bytes) {
1378
+ if (typeof TextDecoder !== "undefined") {
1379
+ return new TextDecoder().decode(bytes);
1380
+ }
1381
+ let result = "";
1382
+ for (let i = 0; i < bytes.length; i++) {
1383
+ result += String.fromCharCode(bytes[i]);
1384
+ }
1385
+ return result;
1386
+ }
1387
+ function bytesToBase64(bytes) {
1388
+ let binary = "";
1389
+ for (let i = 0; i < bytes.length; i++) {
1390
+ binary += String.fromCharCode(bytes[i]);
1391
+ }
1392
+ if (typeof btoa === "function") {
1393
+ return btoa(binary);
1394
+ }
1395
+ return Buffer.from(binary, "latin1").toString("base64");
1396
+ }
1397
+ function base64ToBytes(str) {
1398
+ let binary;
1399
+ if (typeof atob === "function") {
1400
+ binary = atob(str);
1401
+ } else {
1402
+ binary = Buffer.from(str, "base64").toString("latin1");
1403
+ }
1404
+ const bytes = new Uint8Array(binary.length);
1405
+ for (let i = 0; i < binary.length; i++) {
1406
+ bytes[i] = binary.charCodeAt(i);
1407
+ }
1408
+ return bytes;
1409
+ }
1410
+ function base64Encode(str) {
1411
+ const bytes = utf8ToBytes(str);
1412
+ return bytesToBase64(bytes);
1413
+ }
1414
+ function base64Decode(str) {
1415
+ const bytes = base64ToBytes(str);
1416
+ return bytesToUtf8(bytes);
1417
+ }
1418
+ function generateToken(bytes = 32) {
1419
+ return randomHex(bytes);
1420
+ }
1421
+ function generateOTP(length = 6) {
1422
+ const bytes = getRandomBytes(length);
1423
+ let otp = "";
1424
+ for (let i = 0; i < length; i++) {
1425
+ otp += (bytes[i] % 10).toString();
1426
+ }
1427
+ return otp;
1428
+ }
1429
+ function xorCipher(str, key) {
1430
+ let result = "";
1431
+ for (let i = 0; i < str.length; i++) {
1432
+ const code = str.charCodeAt(i) ^ key.charCodeAt(i % key.length);
1433
+ result += String.fromCharCode(code);
1434
+ }
1435
+ return result;
1436
+ }
1437
+ function checksum(input) {
1438
+ let crc = 4294967295;
1439
+ for (let i = 0; i < input.length; i++) {
1440
+ crc ^= input.charCodeAt(i);
1441
+ for (let j = 0; j < 8; j++) {
1442
+ if (crc & 1) {
1443
+ crc = crc >>> 1 ^ 3988292384;
1444
+ } else {
1445
+ crc = crc >>> 1;
1446
+ }
1447
+ }
1448
+ }
1449
+ return ((crc ^ 4294967295) >>> 0).toString(16).padStart(8, "0");
1450
+ }
1451
+ function constantTimeEqual(a, b) {
1452
+ if (a.length !== b.length) return false;
1453
+ let result = 0;
1454
+ for (let i = 0; i < a.length; i++) {
1455
+ result |= a.charCodeAt(i) ^ b.charCodeAt(i);
1456
+ }
1457
+ return result === 0;
1458
+ }
1459
+
1460
+ // src/path/index.ts
1461
+ var SEP = "/";
1462
+ function join(...segments) {
1463
+ const parts = [];
1464
+ for (const seg of segments) {
1465
+ if (seg === "") continue;
1466
+ const split = seg.split(/[\\/]/);
1467
+ for (const part of split) {
1468
+ if (part === "" || part === ".") continue;
1469
+ if (part === "..") {
1470
+ if (parts.length > 0 && parts[parts.length - 1] !== "..") {
1471
+ parts.pop();
1472
+ } else {
1473
+ parts.push("..");
1474
+ }
1475
+ } else {
1476
+ parts.push(part);
1477
+ }
1478
+ }
1479
+ }
1480
+ if (parts.length === 0) return ".";
1481
+ const result = parts.join(SEP);
1482
+ if (segments.length > 0 && segments[0].startsWith("/")) {
1483
+ return SEP + result;
1484
+ }
1485
+ return result;
1486
+ }
1487
+ function resolve(...segments) {
1488
+ let resolved = "";
1489
+ let isAbs = false;
1490
+ for (const seg of segments) {
1491
+ if (seg.startsWith("/")) {
1492
+ resolved = seg;
1493
+ isAbs = true;
1494
+ } else if (isAbs) {
1495
+ resolved = join(resolved, seg);
1496
+ } else {
1497
+ resolved = resolved ? join(resolved, seg) : seg;
1498
+ }
1499
+ }
1500
+ if (!isAbs) {
1501
+ resolved = join(SEP, resolved);
1502
+ }
1503
+ return normalize(resolved);
1504
+ }
1505
+ function basename(p, ext) {
1506
+ const normalized = p.replace(/[\\/]+$/, "");
1507
+ const idx = normalized.lastIndexOf(SEP);
1508
+ let base = idx === -1 ? normalized : normalized.slice(idx + 1);
1509
+ if (ext && base.endsWith(ext)) {
1510
+ base = base.slice(0, -ext.length);
1511
+ }
1512
+ return base;
1513
+ }
1514
+ function dirname(p) {
1515
+ if (p === SEP) return SEP;
1516
+ const normalized = p.replace(/[\\/]+$/, "");
1517
+ if (normalized === "") return ".";
1518
+ const idx = normalized.lastIndexOf(SEP);
1519
+ if (idx === -1) return ".";
1520
+ if (idx === 0) return SEP;
1521
+ return normalized.slice(0, idx);
1522
+ }
1523
+ function extname(p) {
1524
+ const base = basename(p);
1525
+ const idx = base.lastIndexOf(".");
1526
+ if (idx === -1 || idx === 0) return "";
1527
+ return base.slice(idx);
1528
+ }
1529
+ function normalize(p) {
1530
+ const parts = p.split(/[\\/]+/);
1531
+ const stack = [];
1532
+ let isAbs = p.startsWith("/");
1533
+ for (const part of parts) {
1534
+ if (part === "" || part === ".") continue;
1535
+ if (part === "..") {
1536
+ if (stack.length > 0 && stack[stack.length - 1] !== "..") {
1537
+ stack.pop();
1538
+ } else if (!isAbs) {
1539
+ stack.push("..");
1540
+ }
1541
+ } else {
1542
+ stack.push(part);
1543
+ }
1544
+ }
1545
+ const result = stack.join(SEP);
1546
+ if (isAbs) return SEP + result;
1547
+ if (result === "") return ".";
1548
+ return result;
1549
+ }
1550
+ function isAbsolute(p) {
1551
+ return p.startsWith("/");
1552
+ }
1553
+ function relative(from, to) {
1554
+ const fromParts = normalize(from).split(SEP);
1555
+ const toParts = normalize(to).split(SEP);
1556
+ let i = 0;
1557
+ while (i < fromParts.length && i < toParts.length && fromParts[i] === toParts[i]) {
1558
+ i++;
1559
+ }
1560
+ const up = fromParts.slice(i).map(() => "..");
1561
+ const down = toParts.slice(i);
1562
+ const result = [...up, ...down].join(SEP);
1563
+ return result || ".";
1564
+ }
1565
+ function parse(p) {
1566
+ const root = p.startsWith(SEP) ? SEP : "";
1567
+ const base = basename(p);
1568
+ const ext = extname(base);
1569
+ const name = ext ? base.slice(0, -ext.length) : base;
1570
+ const dir = root ? dirname(p) : dirname(p) === "." ? "" : dirname(p);
1571
+ return { root, dir, base, name, ext };
1572
+ }
1573
+ function format(parsed) {
1574
+ const { root = "", dir = "", base = "", name = "", ext = "" } = parsed;
1575
+ const baseName = base || name + ext;
1576
+ if (dir) {
1577
+ return dir + SEP + baseName;
1578
+ }
1579
+ return root + baseName;
1580
+ }
1581
+
1582
+ // src/collection/index.ts
1583
+ function groupBy(items, keyFn) {
1584
+ const result = {};
1585
+ for (const item of items) {
1586
+ const key = keyFn(item);
1587
+ if (!result[key]) result[key] = [];
1588
+ result[key].push(item);
1589
+ }
1590
+ return result;
1591
+ }
1592
+ function keyBy(items, keyFn) {
1593
+ const result = {};
1594
+ for (const item of items) {
1595
+ const key = keyFn(item);
1596
+ result[key] = item;
1597
+ }
1598
+ return result;
1599
+ }
1600
+ function omit(obj, keys) {
1601
+ const result = { ...obj };
1602
+ for (const key of keys) {
1603
+ delete result[key];
1604
+ }
1605
+ return result;
1606
+ }
1607
+ function pick(obj, keys) {
1608
+ const result = {};
1609
+ for (const key of keys) {
1610
+ if (key in obj) {
1611
+ result[key] = obj[key];
1612
+ }
1613
+ }
1614
+ return result;
1615
+ }
1616
+ function pluck(items, key) {
1617
+ return items.map((item) => item[key]);
1618
+ }
1619
+ function shuffle(items) {
1620
+ const result = [...items];
1621
+ for (let i = result.length - 1; i > 0; i--) {
1622
+ const j = Math.floor(Math.random() * (i + 1));
1623
+ const temp = result[i];
1624
+ result[i] = result[j];
1625
+ result[j] = temp;
1626
+ }
1627
+ return result;
1628
+ }
1629
+ function sample(items) {
1630
+ return items.length > 0 ? items[Math.floor(Math.random() * items.length)] : void 0;
1631
+ }
1632
+ function sampleSize(items, size) {
1633
+ if (size <= 0 || items.length === 0) return [];
1634
+ const pool = shuffle(items);
1635
+ return pool.slice(0, Math.min(size, items.length));
1636
+ }
1637
+ function chunk(items, size) {
1638
+ if (size <= 0 || items.length === 0) return [];
1639
+ const result = [];
1640
+ for (let i = 0; i < items.length; i += size) {
1641
+ result.push(items.slice(i, i + size));
1642
+ }
1643
+ return result;
1644
+ }
1645
+ function compareValues(a, b) {
1646
+ if (a === b) return 0;
1647
+ if (a == null) return -1;
1648
+ if (b == null) return 1;
1649
+ if (typeof a === "string" && typeof b === "string") return a < b ? -1 : 1;
1650
+ if (typeof a === "number" && typeof b === "number") return a < b ? -1 : 1;
1651
+ return String(a) < String(b) ? -1 : 1;
1652
+ }
1653
+ function sortBy(items, ...criteria) {
1654
+ return [...items].sort((a, b) => {
1655
+ for (const criterion of criteria) {
1656
+ const cmp = compareValues(criterion(a), criterion(b));
1657
+ if (cmp !== 0) return cmp;
1658
+ }
1659
+ return 0;
1660
+ });
1661
+ }
1662
+ function orderBy(items, key, direction = "asc") {
1663
+ return [...items].sort((a, b) => {
1664
+ const cmp = compareValues(key(a), key(b));
1665
+ return direction === "asc" ? cmp : -cmp;
1666
+ });
1667
+ }
1668
+ function uniqueBy(items, keyFn) {
1669
+ const seen = /* @__PURE__ */ new Set();
1670
+ return items.filter((item) => {
1671
+ const key = keyFn(item);
1672
+ if (seen.has(key)) return false;
1673
+ seen.add(key);
1674
+ return true;
1675
+ });
1676
+ }
1677
+ function flatten(items) {
1678
+ const result = [];
1679
+ for (const sub2 of items) {
1680
+ for (const item of sub2) {
1681
+ result.push(item);
1682
+ }
1683
+ }
1684
+ return result;
1685
+ }
1686
+ function uniq(items) {
1687
+ return [...new Set(items)];
1688
+ }
1689
+ function first(items) {
1690
+ return items[0];
1691
+ }
1692
+ function last(items) {
1693
+ return items[items.length - 1];
1694
+ }
1695
+ function isEmpty(value) {
1696
+ if (Array.isArray(value)) return value.length === 0;
1697
+ if (typeof value === "string") return value.length === 0;
1698
+ if (value instanceof Map || value instanceof Set) return value.size === 0;
1699
+ if (value !== null && typeof value === "object") return Object.keys(value).length === 0;
1700
+ return false;
1701
+ }
1702
+ function topoSort(items) {
1703
+ const adj = /* @__PURE__ */ new Map();
1704
+ const inDegree = /* @__PURE__ */ new Map();
1705
+ const itemMap = /* @__PURE__ */ new Map();
1706
+ for (const item of items) {
1707
+ itemMap.set(item.id, item);
1708
+ if (!adj.has(item.id)) adj.set(item.id, []);
1709
+ if (!inDegree.has(item.id)) inDegree.set(item.id, 0);
1710
+ }
1711
+ for (const item of items) {
1712
+ if (item.dependencies) {
1713
+ for (const depId of item.dependencies) {
1714
+ adj.get(depId)?.push(item.id);
1715
+ inDegree.set(item.id, (inDegree.get(item.id) ?? 0) + 1);
1716
+ }
1717
+ }
1718
+ }
1719
+ const queue = [];
1720
+ for (const [id, degree] of inDegree) {
1721
+ if (degree === 0) queue.push(id);
1722
+ }
1723
+ const sorted = [];
1724
+ while (queue.length > 0) {
1725
+ const id = queue.shift();
1726
+ sorted.push(id);
1727
+ for (const neighbor of adj.get(id) ?? []) {
1728
+ const newDegree = (inDegree.get(neighbor) ?? 1) - 1;
1729
+ inDegree.set(neighbor, newDegree);
1730
+ if (newDegree === 0) queue.push(neighbor);
1731
+ }
1732
+ }
1733
+ if (sorted.length !== items.length) {
1734
+ throw new Error("Circular dependency detected");
1735
+ }
1736
+ return sorted.map((id) => itemMap.get(id));
1737
+ }
1738
+ function slidingWindows(items, size, step = 1) {
1739
+ if (size <= 0 || items.length === 0 || step <= 0) return [];
1740
+ const result = [];
1741
+ for (let i = 0; i + size <= items.length; i += step) {
1742
+ result.push(items.slice(i, i + size));
1743
+ }
1744
+ return result;
1745
+ }
1746
+ function tumblingWindows(items, size) {
1747
+ if (size <= 0 || items.length === 0) return [];
1748
+ const result = [];
1749
+ for (let i = 0; i < items.length; i += size) {
1750
+ result.push(items.slice(i, i + size));
1751
+ }
1752
+ return result;
1753
+ }
1754
+ function deepGet(obj, path, default_) {
1755
+ const keys = path.split(".");
1756
+ let current = obj;
1757
+ for (const key of keys) {
1758
+ if (current === null || current === void 0) return default_;
1759
+ if (typeof current !== "object") return default_;
1760
+ const curObj = current;
1761
+ if (!(key in curObj)) return default_;
1762
+ current = curObj[key];
1763
+ }
1764
+ return current ?? default_;
1765
+ }
1766
+ function deepSet(obj, path, value) {
1767
+ const keys = path.split(".");
1768
+ const PROTO_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
1769
+ for (const key of keys) {
1770
+ if (PROTO_KEYS.has(key)) {
1771
+ return { ...obj };
1772
+ }
1773
+ }
1774
+ const result = { ...obj };
1775
+ let current = result;
1776
+ for (let i = 0; i < keys.length - 1; i++) {
1777
+ const key = keys[i];
1778
+ const next = current[key];
1779
+ if (next === null || next === void 0 || typeof next !== "object") {
1780
+ const isArray2 = /^\d+$/.test(keys[i + 1]);
1781
+ current[key] = isArray2 ? [] : {};
1782
+ }
1783
+ current = current[key];
1784
+ }
1785
+ current[keys[keys.length - 1]] = value;
1786
+ return result;
1787
+ }
1788
+ function partition(items, predicate) {
1789
+ const pass = [];
1790
+ const fail = [];
1791
+ for (const item of items) {
1792
+ if (predicate(item)) pass.push(item);
1793
+ else fail.push(item);
1794
+ }
1795
+ return [pass, fail];
1796
+ }
1797
+ function compact(items) {
1798
+ return items.filter(Boolean);
1799
+ }
1800
+ function difference(a, b) {
1801
+ const setB = new Set(b);
1802
+ return a.filter((item) => !setB.has(item));
1803
+ }
1804
+ function intersection(a, b) {
1805
+ const setB = new Set(b);
1806
+ return a.filter((item) => setB.has(item));
1807
+ }
1808
+ function union(...arrays) {
1809
+ const set = /* @__PURE__ */ new Set();
1810
+ for (const arr of arrays) {
1811
+ for (const item of arr) {
1812
+ set.add(item);
1813
+ }
1814
+ }
1815
+ return [...set];
1816
+ }
1817
+ function zip(...arrays) {
1818
+ if (arrays.length === 0) return [];
1819
+ const minLen = Math.min(...arrays.map((a) => a.length));
1820
+ const result = [];
1821
+ for (let i = 0; i < minLen; i++) {
1822
+ const tuple = [];
1823
+ for (const arr of arrays) {
1824
+ tuple.push(arr[i]);
1825
+ }
1826
+ result.push(tuple);
1827
+ }
1828
+ return result;
1829
+ }
1830
+ function unzip(paired) {
1831
+ if (paired.length === 0) return [];
1832
+ const tupleLen = paired.reduce((max, t) => Math.max(max, t.length), 0);
1833
+ const result = Array.from({ length: tupleLen }, () => []);
1834
+ for (const tuple of paired) {
1835
+ for (let i = 0; i < tupleLen; i++) {
1836
+ result[i].push(tuple[i]);
1837
+ }
1838
+ }
1839
+ return result;
1840
+ }
1841
+ function countBy(items, keyFn) {
1842
+ const result = {};
1843
+ for (const item of items) {
1844
+ const key = keyFn(item);
1845
+ result[key] = (result[key] ?? 0) + 1;
1846
+ }
1847
+ return result;
1848
+ }
1849
+ function maxBy(items, keyFn) {
1850
+ if (items.length === 0) return void 0;
1851
+ let maxItem = items[0];
1852
+ let maxVal = keyFn(maxItem);
1853
+ for (let i = 1; i < items.length; i++) {
1854
+ const val = keyFn(items[i]);
1855
+ if (val > maxVal) {
1856
+ maxVal = val;
1857
+ maxItem = items[i];
1858
+ }
1859
+ }
1860
+ return maxItem;
1861
+ }
1862
+ function minBy(items, keyFn) {
1863
+ if (items.length === 0) return void 0;
1864
+ let minItem = items[0];
1865
+ let minVal = keyFn(minItem);
1866
+ for (let i = 1; i < items.length; i++) {
1867
+ const val = keyFn(items[i]);
1868
+ if (val < minVal) {
1869
+ minVal = val;
1870
+ minItem = items[i];
1871
+ }
1872
+ }
1873
+ return minItem;
1874
+ }
1875
+ function sumBy(items, keyFn) {
1876
+ let total = 0;
1877
+ for (const item of items) {
1878
+ total += keyFn(item);
1879
+ }
1880
+ return total;
1881
+ }
1882
+ function findIndex(items, predicate, fromIndex = 0) {
1883
+ for (let i = fromIndex; i < items.length; i++) {
1884
+ if (predicate(items[i])) return i;
1885
+ }
1886
+ return -1;
1887
+ }
1888
+ function findLast(items, predicate) {
1889
+ for (let i = items.length - 1; i >= 0; i--) {
1890
+ if (predicate(items[i])) return items[i];
1891
+ }
1892
+ return void 0;
1893
+ }
1894
+ function drop(items, n = 1) {
1895
+ return items.slice(Math.max(0, n));
1896
+ }
1897
+ function dropRight(items, n = 1) {
1898
+ return items.slice(0, Math.max(0, items.length - n));
1899
+ }
1900
+ function take(items, n = 1) {
1901
+ return items.slice(0, Math.max(0, n));
1902
+ }
1903
+ function takeRight(items, n = 1) {
1904
+ return items.slice(Math.max(0, items.length - n));
1905
+ }
1906
+ function without(items, ...values) {
1907
+ const exclude = new Set(values);
1908
+ return items.filter((item) => !exclude.has(item));
1909
+ }
1910
+ function nth(items, index) {
1911
+ return index < 0 ? items[items.length + index] : items[index];
1912
+ }
1913
+
1914
+ // src/string/index.ts
1915
+ var WORD_SPLIT_RE = /[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|\d|\b)|\d+/g;
1916
+ function splitWords(str) {
1917
+ return str.match(WORD_SPLIT_RE) ?? [];
1918
+ }
1919
+ function capitalize(str) {
1920
+ if (str.length === 0) return str;
1921
+ return str[0].toUpperCase() + str.slice(1).toLowerCase();
1922
+ }
1923
+ function camelCase(str) {
1924
+ const words2 = splitWords(str);
1925
+ if (words2.length === 0) return "";
1926
+ const [firstWord, ...rest] = words2;
1927
+ return firstWord.toLowerCase() + rest.map((w) => w[0].toUpperCase() + w.slice(1).toLowerCase()).join("");
1928
+ }
1929
+ function kebabCase(str) {
1930
+ return splitWords(str).map((w) => w.toLowerCase()).join("-");
1931
+ }
1932
+ function snakeCase(str) {
1933
+ return splitWords(str).map((w) => w.toLowerCase()).join("_");
1934
+ }
1935
+ function pascalCase(str) {
1936
+ return splitWords(str).map((w) => w[0].toUpperCase() + w.slice(1).toLowerCase()).join("");
1937
+ }
1938
+ function truncate(str, maxLength, suffix = "...") {
1939
+ if (str.length <= maxLength) return str;
1940
+ return str.slice(0, Math.max(0, maxLength - suffix.length)) + suffix;
1941
+ }
1942
+ function template(str, data) {
1943
+ return str.replace(/\{\{(\w+)\}\}/g, (_2, key) => {
1944
+ if (key === "__proto__" || key === "constructor" || key === "prototype") return `{{${key}}}`;
1945
+ const value = data[key];
1946
+ return value !== void 0 ? String(value) : `{{${key}}}`;
1947
+ });
1948
+ }
1949
+ function uuid() {
1950
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
1951
+ return crypto.randomUUID();
1952
+ }
1953
+ const hex = "0123456789abcdef";
1954
+ const chars = [];
1955
+ for (let i = 0; i < 36; i++) {
1956
+ if (i === 8 || i === 13 || i === 18 || i === 23) {
1957
+ chars.push("-");
1958
+ } else if (i === 14) {
1959
+ chars.push("4");
1960
+ } else if (i === 19) {
1961
+ chars.push(hex[Math.floor(Math.random() * 4) + 8]);
1962
+ } else {
1963
+ chars.push(hex[Math.floor(Math.random() * 16)]);
1964
+ }
1965
+ }
1966
+ return chars.join("");
1967
+ }
1968
+ function nanoid(size = 21, alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-") {
1969
+ const len = alphabet.length;
1970
+ const bytes = new Uint8Array(size);
1971
+ if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
1972
+ crypto.getRandomValues(bytes);
1973
+ } else {
1974
+ throw new Error("Crypto API unavailable. Cannot generate secure random ID.");
1975
+ }
1976
+ let result = "";
1977
+ for (let i = 0; i < size; i++) {
1978
+ result += alphabet[bytes[i] % len];
1979
+ }
1980
+ return result;
1981
+ }
1982
+ var HTML_ESCAPE_MAP = {
1983
+ "&": "&amp;",
1984
+ "<": "&lt;",
1985
+ ">": "&gt;",
1986
+ '"': "&quot;",
1987
+ "'": "&#39;",
1988
+ "`": "&#96;",
1989
+ "/": "&#x2F;"
1990
+ };
1991
+ var HTML_UNESCAPE_MAP = {
1992
+ "&amp;": "&",
1993
+ "&lt;": "<",
1994
+ "&gt;": ">",
1995
+ "&quot;": '"',
1996
+ "&#39;": "'",
1997
+ "&#x27;": "'",
1998
+ "&#96;": "`",
1999
+ "&#x2F;": "/"
2000
+ };
2001
+ function escapeHtml(str) {
2002
+ return str.replace(/[&<>"'`\/]/g, (ch) => HTML_ESCAPE_MAP[ch] ?? ch);
2003
+ }
2004
+ function unescapeHtml(str) {
2005
+ return str.replace(/&(?:amp|lt|gt|quot|#39|#x27|#96|#x2F);/g, (entity) => HTML_UNESCAPE_MAP[entity] ?? entity);
2006
+ }
2007
+ function trim(str) {
2008
+ return str.trim();
2009
+ }
2010
+ function trimStart(str) {
2011
+ return str.trimStart();
2012
+ }
2013
+ function trimEnd(str) {
2014
+ return str.trimEnd();
2015
+ }
2016
+ function pad(str, length, char = " ") {
2017
+ const totalPadding = Math.max(0, length - str.length);
2018
+ const leftPad = Math.floor(totalPadding / 2);
2019
+ const rightPad = totalPadding - leftPad;
2020
+ return char.repeat(leftPad) + str + char.repeat(rightPad);
2021
+ }
2022
+ function padStart(str, length, char = " ") {
2023
+ return str.padStart(length, char);
2024
+ }
2025
+ function padEnd(str, length, char = " ") {
2026
+ return str.padEnd(length, char);
2027
+ }
2028
+ function reverse(str) {
2029
+ return str.split("").reverse().join("");
2030
+ }
2031
+ function words(str) {
2032
+ return splitWords(str);
2033
+ }
2034
+ function slugify(str) {
2035
+ return str.toLowerCase().replace(/[^\w\s-]/g, "").replace(/[\s_]+/g, "-").replace(/-+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
2036
+ }
2037
+ function countOccurrences(str, substring) {
2038
+ if (substring.length === 0 || str.length === 0) return 0;
2039
+ let count = 0;
2040
+ let pos = 0;
2041
+ while ((pos = str.indexOf(substring, pos)) !== -1) {
2042
+ count++;
2043
+ pos += substring.length;
2044
+ }
2045
+ return count;
2046
+ }
2047
+ function levenshtein(a, b) {
2048
+ const an = a.length;
2049
+ const bn = b.length;
2050
+ if (an === 0) return bn;
2051
+ if (bn === 0) return an;
2052
+ if (an < bn) return levenshtein(b, a);
2053
+ let prev = new Uint32Array(bn + 1);
2054
+ let curr = new Uint32Array(bn + 1);
2055
+ for (let j = 0; j <= bn; j++) prev[j] = j;
2056
+ for (let i = 1; i <= an; i++) {
2057
+ curr[0] = i;
2058
+ for (let j = 1; j <= bn; j++) {
2059
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
2060
+ curr[j] = Math.min(
2061
+ prev[j] + 1,
2062
+ curr[j - 1] + 1,
2063
+ prev[j - 1] + cost
2064
+ );
2065
+ }
2066
+ ;
2067
+ [prev, curr] = [curr, prev];
2068
+ }
2069
+ return prev[bn];
2070
+ }
2071
+ function fuzzyMatch(str, query) {
2072
+ if (query.length === 0) return true;
2073
+ if (str.length === 0) return false;
2074
+ const sl = str.toLowerCase();
2075
+ const ql = query.toLowerCase();
2076
+ let si = 0;
2077
+ for (let qi = 0; qi < ql.length; qi++) {
2078
+ si = sl.indexOf(ql[qi], si);
2079
+ if (si === -1) return false;
2080
+ si++;
2081
+ }
2082
+ return true;
2083
+ }
2084
+ function maskString(str, options) {
2085
+ if (str.length === 0) return str;
2086
+ const maskChar = options?.char ?? "*";
2087
+ const start = options?.start ?? Math.ceil(str.length * 0.25);
2088
+ const end = options?.end ?? Math.floor(str.length * 0.75);
2089
+ if (start >= end || start < 0) return str;
2090
+ const clampedStart = Math.max(0, start);
2091
+ const clampedEnd = Math.min(str.length, end);
2092
+ return str.slice(0, clampedStart) + maskChar.repeat(clampedEnd - clampedStart) + str.slice(clampedEnd);
2093
+ }
2094
+ var SATUAN = ["", "satu", "dua", "tiga", "empat", "lima", "enam", "tujuh", "delapan", "sembilan"];
2095
+ var BELASAN = ["sepuluh", "sebelas", "dua belas", "tiga belas", "empat belas", "lima belas", "enam belas", "tujuh belas", "delapan belas", "sembilan belas"];
2096
+ var PULUHAN = ["", "", "dua puluh", "tiga puluh", "empat puluh", "lima puluh", "enam puluh", "tujuh puluh", "delapan puluh", "sembilan puluh"];
2097
+ function _terbilang(n) {
2098
+ if (n < 0) return "minus " + _terbilang(-n);
2099
+ if (n === 0) return "nol";
2100
+ if (n < 10) return SATUAN[n];
2101
+ if (n < 20) return n === 10 ? "sepuluh" : n === 11 ? "sebelas" : BELASAN[n - 10];
2102
+ if (n < 100) {
2103
+ const pul = Math.floor(n / 10);
2104
+ const sat = n % 10;
2105
+ return PULUHAN[pul] + (sat > 0 ? " " + SATUAN[sat] : "");
2106
+ }
2107
+ if (n < 1e3) {
2108
+ const ratus = Math.floor(n / 100);
2109
+ const sis2 = n % 100;
2110
+ const ratusStr = ratus === 1 ? "seratus" : SATUAN[ratus] + " ratus";
2111
+ return ratusStr + (sis2 > 0 ? " " + _terbilang(sis2) : "");
2112
+ }
2113
+ if (n < 1e6) {
2114
+ const rib = Math.floor(n / 1e3);
2115
+ const sis2 = n % 1e3;
2116
+ const ribStr = rib === 1 ? "seribu" : _terbilang(rib) + " ribu";
2117
+ return ribStr + (sis2 > 0 ? " " + _terbilang(sis2) : "");
2118
+ }
2119
+ if (n < 1e9) {
2120
+ const jut = Math.floor(n / 1e6);
2121
+ const sis2 = n % 1e6;
2122
+ return _terbilang(jut) + " juta" + (sis2 > 0 ? " " + _terbilang(sis2) : "");
2123
+ }
2124
+ if (n < 1e12) {
2125
+ const mil = Math.floor(n / 1e9);
2126
+ const sis2 = n % 1e9;
2127
+ return _terbilang(mil) + " miliar" + (sis2 > 0 ? " " + _terbilang(sis2) : "");
2128
+ }
2129
+ const tril = Math.floor(n / 1e12);
2130
+ const sis = n % 1e12;
2131
+ return _terbilang(tril) + " triliun" + (sis > 0 ? " " + _terbilang(sis) : "");
2132
+ }
2133
+ function terbilang(value) {
2134
+ if (!Number.isFinite(value)) throw new RangeError("Input must be a finite number");
2135
+ if (value > Number.MAX_SAFE_INTEGER) throw new RangeError("Input terlalu besar");
2136
+ return _terbilang(Math.floor(Math.abs(value)));
2137
+ }
2138
+ function formatRupiah(value, options) {
2139
+ return formatCurrency(value, { locale: "id-ID", currency: "IDR", notation: options?.notation });
2140
+ }
2141
+ function formatBytes(bytes, options) {
2142
+ if (bytes === 0) return "0 B";
2143
+ if (!Number.isFinite(bytes) || bytes < 0) return "0 B";
2144
+ const k = 1024;
2145
+ const sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB"];
2146
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
2147
+ const dm = options?.decimals ?? (i === 0 ? 0 : 1);
2148
+ const index = Math.min(i, sizes.length - 1);
2149
+ return parseFloat((bytes / Math.pow(k, index)).toFixed(dm)) + " " + sizes[index];
2150
+ }
2151
+ function randomString(length = 16) {
2152
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
2153
+ const bytes = new Uint8Array(length);
2154
+ if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
2155
+ crypto.getRandomValues(bytes);
2156
+ } else {
2157
+ throw new Error("Crypto API unavailable. Cannot generate secure random string.");
2158
+ }
2159
+ let result = "";
2160
+ for (let i = 0; i < length; i++) {
2161
+ result += chars[bytes[i] % chars.length];
2162
+ }
2163
+ return result;
2164
+ }
2165
+ function randomBoolean() {
2166
+ return Math.random() >= 0.5;
2167
+ }
2168
+ function pluralize(count, singular) {
2169
+ if (count === 1) return singular;
2170
+ const last2 = singular[singular.length - 1];
2171
+ const lastTwo = singular.slice(-2);
2172
+ if (last2 === "s" || last2 === "x" || last2 === "z" || lastTwo === "ch" || lastTwo === "sh") {
2173
+ return singular + "es";
2174
+ }
2175
+ if (last2 === "y" && singular.length > 2 && !"aeiou".includes(singular[singular.length - 2])) {
2176
+ return singular.slice(0, -1) + "ies";
2177
+ }
2178
+ return singular + "s";
2179
+ }
2180
+ function stripHtml(str) {
2181
+ return str.replace(/<[^>]*>/g, "");
2182
+ }
2183
+ function truncateWords(str, count, suffix = "...") {
2184
+ const words2 = str.split(/\s+/).filter(Boolean);
2185
+ if (words2.length <= count) return str;
2186
+ return words2.slice(0, count).join(" ") + suffix;
2187
+ }
2188
+ function isPalindrome(str) {
2189
+ const cleaned = str.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
2190
+ if (cleaned.length <= 1) return true;
2191
+ let left = 0;
2192
+ let right = cleaned.length - 1;
2193
+ while (left < right) {
2194
+ if (cleaned[left] !== cleaned[right]) return false;
2195
+ left++;
2196
+ right--;
2197
+ }
2198
+ return true;
2199
+ }
2200
+ function isAnagram(str1, str2) {
2201
+ const clean = (s) => s.replace(/\s/g, "").toLowerCase().split("").sort().join("");
2202
+ return clean(str1) === clean(str2);
2203
+ }
2204
+ function similarity(a, b) {
2205
+ if (a === b) return 1;
2206
+ if (a.length < 2 || b.length < 2) return 0;
2207
+ const bigrams = /* @__PURE__ */ new Map();
2208
+ for (let i = 0; i < a.length - 1; i++) {
2209
+ const bg = a.slice(i, i + 2);
2210
+ bigrams.set(bg, (bigrams.get(bg) ?? 0) + 1);
2211
+ }
2212
+ let intersection2 = 0;
2213
+ for (let i = 0; i < b.length - 1; i++) {
2214
+ const bg = b.slice(i, i + 2);
2215
+ const count = bigrams.get(bg) ?? 0;
2216
+ if (count > 0) {
2217
+ bigrams.set(bg, count - 1);
2218
+ intersection2++;
2219
+ }
2220
+ }
2221
+ return 2 * intersection2 / (a.length + b.length - 2);
2222
+ }
2223
+ function dedent(str) {
2224
+ const lines = str.split("\n");
2225
+ if (lines.length === 0) return str;
2226
+ const indent = lines.reduce((min, line) => {
2227
+ if (line.trim().length === 0) return min;
2228
+ const leading = line.match(/^[ \t]*/)?.[0]?.length ?? 0;
2229
+ return min === null ? leading : Math.min(min, leading);
2230
+ }, null);
2231
+ if (indent === null || indent === 0) return str;
2232
+ return lines.map((line) => line.slice(indent)).join("\n");
2233
+ }
2234
+ function wordCount(str) {
2235
+ const match = str.match(/[a-zA-Z0-9]+(?:['\u2019][a-zA-Z]+)?/g);
2236
+ return match ? match.length : 0;
2237
+ }
2238
+ function swapCase(str) {
2239
+ let result = "";
2240
+ for (let i = 0; i < str.length; i++) {
2241
+ const ch = str[i];
2242
+ if (ch >= "a" && ch <= "z") {
2243
+ result += ch.toUpperCase();
2244
+ } else if (ch >= "A" && ch <= "Z") {
2245
+ result += ch.toLowerCase();
2246
+ } else {
2247
+ result += ch;
2248
+ }
2249
+ }
2250
+ return result;
2251
+ }
2252
+ function toCobolCase(str) {
2253
+ const words2 = splitWords(str);
2254
+ return words2.map((w) => w.toUpperCase()).join("_");
2255
+ }
2256
+ function charCount(str) {
2257
+ const result = {};
2258
+ for (let i = 0; i < str.length; i++) {
2259
+ const ch = str[i];
2260
+ result[ch] = (result[ch] ?? 0) + 1;
2261
+ }
2262
+ return result;
2263
+ }
2264
+
2265
+ // src/async/queue.ts
2266
+ var Queue = class {
2267
+ _tasks = [];
2268
+ _running = 0;
2269
+ _paused = false;
2270
+ _idleResolve = null;
2271
+ _maxConcurrency;
2272
+ constructor(options) {
2273
+ this._maxConcurrency = options?.concurrency ?? 1;
2274
+ if (this._maxConcurrency < 1) this._maxConcurrency = 1;
2275
+ }
2276
+ get pending() {
2277
+ return this._tasks.length;
2278
+ }
2279
+ get running() {
2280
+ return this._running;
2281
+ }
2282
+ add(task, options) {
2283
+ return new Promise((resolve2, reject) => {
2284
+ this._tasks.push({
2285
+ priority: options?.priority ?? 0,
2286
+ task,
2287
+ resolve: resolve2,
2288
+ reject
2289
+ });
2290
+ this._tasks.sort((a, b) => b.priority - a.priority);
2291
+ this._process();
2292
+ });
2293
+ }
2294
+ pause() {
2295
+ this._paused = true;
2296
+ }
2297
+ resume() {
2298
+ this._paused = false;
2299
+ this._process();
2300
+ }
2301
+ clear() {
2302
+ const err = new Error("Queue cleared");
2303
+ for (const t of this._tasks) t.reject(err);
2304
+ this._tasks = [];
2305
+ }
2306
+ onIdle() {
2307
+ if (this._running === 0 && this._tasks.length === 0) return Promise.resolve();
2308
+ return new Promise((resolve2) => {
2309
+ this._idleResolve = resolve2;
2310
+ });
2311
+ }
2312
+ _process() {
2313
+ if (this._paused) return;
2314
+ while (this._running < this._maxConcurrency && this._tasks.length > 0) {
2315
+ const item = this._tasks.shift();
2316
+ this._running++;
2317
+ item.task().then((result) => item.resolve(result)).catch((err) => item.reject(err)).finally(() => {
2318
+ this._running--;
2319
+ this._process();
2320
+ if (this._running === 0 && this._tasks.length === 0 && this._idleResolve) {
2321
+ this._idleResolve();
2322
+ this._idleResolve = null;
2323
+ }
2324
+ });
2325
+ }
2326
+ }
2327
+ };
2328
+
2329
+ // src/async/semaphore.ts
2330
+ var Semaphore = class {
2331
+ _available;
2332
+ _waiting = [];
2333
+ constructor(concurrency) {
2334
+ if (concurrency < 1) throw new RangeError("Semaphore concurrency must be >= 1");
2335
+ this._available = concurrency;
2336
+ }
2337
+ get available() {
2338
+ return this._available;
2339
+ }
2340
+ acquire() {
2341
+ if (this._available > 0) {
2342
+ this._available--;
2343
+ return Promise.resolve(this._release.bind(this));
2344
+ }
2345
+ return new Promise((resolve2) => {
2346
+ this._waiting.push(() => {
2347
+ this._available--;
2348
+ resolve2(this._release.bind(this));
2349
+ });
2350
+ });
2351
+ }
2352
+ async use(fn) {
2353
+ const release = await this.acquire();
2354
+ try {
2355
+ return await fn();
2356
+ } finally {
2357
+ release();
2358
+ }
2359
+ }
2360
+ _release() {
2361
+ this._available++;
2362
+ if (this._waiting.length > 0) {
2363
+ const next = this._waiting.shift();
2364
+ if (next) next();
2365
+ }
2366
+ }
2367
+ };
2368
+
2369
+ // src/async/memoize.ts
2370
+ function memoizeAsync(fn, options) {
2371
+ const {
2372
+ ttl = 6e4,
2373
+ staleWhileRevalidate = false,
2374
+ maxSize = 100,
2375
+ resolver = (...args) => JSON.stringify(args)
2376
+ } = options ?? {};
2377
+ const cache = /* @__PURE__ */ new Map();
2378
+ const memoized = (async (...args) => {
2379
+ const key = resolver(...args);
2380
+ const now = Date.now();
2381
+ const entry = cache.get(key);
2382
+ if (entry && now - entry.timestamp < ttl) {
2383
+ return entry.value;
2384
+ }
2385
+ if (entry && staleWhileRevalidate && now - entry.timestamp >= ttl) {
2386
+ if (entry.promise) {
2387
+ return entry.value;
2388
+ }
2389
+ entry.promise = fn(...args).then((result2) => {
2390
+ entry.value = result2;
2391
+ entry.timestamp = now;
2392
+ entry.promise = void 0;
2393
+ return result2;
2394
+ }).catch((err) => {
2395
+ entry.promise = void 0;
2396
+ throw err;
2397
+ });
2398
+ return entry.value;
2399
+ }
2400
+ const result = await fn(...args);
2401
+ cache.set(key, { value: result, timestamp: now });
2402
+ if (cache.size > maxSize) {
2403
+ const firstKey = cache.keys().next().value;
2404
+ if (firstKey !== void 0) cache.delete(firstKey);
2405
+ }
2406
+ return result;
2407
+ });
2408
+ memoized.cache = cache;
2409
+ memoized.clear = () => cache.clear();
2410
+ return memoized;
2411
+ }
2412
+
2413
+ // src/async/ratelimit.ts
2414
+ var RateLimiter = class {
2415
+ _maxRequests;
2416
+ _perWindow;
2417
+ _timestamps = [];
2418
+ constructor(options) {
2419
+ if (options.maxRequests < 1) throw new RangeError("maxRequests must be >= 1");
2420
+ if (options.perWindow < 1) throw new RangeError("perWindow must be >= 1");
2421
+ this._maxRequests = options.maxRequests;
2422
+ this._perWindow = options.perWindow;
2423
+ }
2424
+ _prune() {
2425
+ const now = Date.now();
2426
+ const cutoff = now - this._perWindow;
2427
+ while (this._timestamps.length > 0) {
2428
+ const ts = this._timestamps[0];
2429
+ if (ts === void 0 || ts > cutoff) break;
2430
+ this._timestamps.shift();
2431
+ }
2432
+ }
2433
+ /**
2434
+ * Check if a request is allowed without waiting.
2435
+ */
2436
+ tryAcquire() {
2437
+ this._prune();
2438
+ if (this._timestamps.length < this._maxRequests) {
2439
+ this._timestamps.push(Date.now());
2440
+ return true;
2441
+ }
2442
+ return false;
2443
+ }
2444
+ /**
2445
+ * Wait until a request is allowed.
2446
+ */
2447
+ async acquire() {
2448
+ while (true) {
2449
+ this._prune();
2450
+ if (this._timestamps.length < this._maxRequests) {
2451
+ this._timestamps.push(Date.now());
2452
+ return;
2453
+ }
2454
+ const oldest = this._timestamps[0] ?? Date.now();
2455
+ const waitMs = oldest + this._perWindow - Date.now();
2456
+ if (waitMs > 0) {
2457
+ await new Promise((resolve2) => setTimeout(resolve2, waitMs));
2458
+ }
2459
+ }
2460
+ }
2461
+ /**
2462
+ * Current number of pending requests in the window.
2463
+ */
2464
+ get pending() {
2465
+ this._prune();
2466
+ return this._timestamps.length;
2467
+ }
2468
+ };
2469
+
2470
+ // src/async/mutex.ts
2471
+ var Mutex = class {
2472
+ _locked = false;
2473
+ _waiting = [];
2474
+ /**
2475
+ * Acquire the lock. Returns a release function to be called when done.
2476
+ */
2477
+ acquire() {
2478
+ if (!this._locked) {
2479
+ this._locked = true;
2480
+ return Promise.resolve(this._release.bind(this));
2481
+ }
2482
+ return new Promise((resolve2) => {
2483
+ this._waiting.push(() => {
2484
+ resolve2(this._release.bind(this));
2485
+ });
2486
+ });
2487
+ }
2488
+ /**
2489
+ * Run a function with the lock held and automatically release it.
2490
+ */
2491
+ async use(fn) {
2492
+ const release = await this.acquire();
2493
+ try {
2494
+ return await fn();
2495
+ } finally {
2496
+ release();
2497
+ }
2498
+ }
2499
+ /**
2500
+ * Whether the mutex is currently locked.
2501
+ */
2502
+ get locked() {
2503
+ return this._locked;
2504
+ }
2505
+ _release() {
2506
+ if (this._waiting.length > 0) {
2507
+ const next = this._waiting.shift();
2508
+ if (next) next();
2509
+ } else {
2510
+ this._locked = false;
2511
+ }
2512
+ }
2513
+ };
2514
+
2515
+ // src/async/batch.ts
2516
+ async function batch(items, batchSize, fn) {
2517
+ if (batchSize < 1) throw new RangeError("batchSize must be >= 1");
2518
+ const results = [];
2519
+ for (let i = 0; i < items.length; i += batchSize) {
2520
+ const chunk2 = items.slice(i, i + batchSize);
2521
+ const batchResults = await fn(chunk2);
2522
+ results.push(...batchResults);
2523
+ }
2524
+ return results;
2525
+ }
2526
+
2527
+ // src/async/waterfall.ts
2528
+ async function waterfall(tasks, initial) {
2529
+ let result = initial;
2530
+ for (const task of tasks) {
2531
+ result = await task(result);
2532
+ }
2533
+ return result;
2534
+ }
2535
+
2536
+ // src/async/index.ts
2537
+ function sleep(ms) {
2538
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
2539
+ }
2540
+ async function timeout(promise, ms, errorMessage) {
2541
+ let timer;
2542
+ const timeoutPromise = new Promise((_2, reject) => {
2543
+ timer = setTimeout(() => reject(new Error(errorMessage ?? `Promise timed out after ${ms}ms`)), ms);
2544
+ });
2545
+ try {
2546
+ return await Promise.race([promise, timeoutPromise]);
2547
+ } finally {
2548
+ if (timer !== void 0) clearTimeout(timer);
2549
+ }
2550
+ }
2551
+ async function raceWithTimeout(promise, ms) {
2552
+ let timer;
2553
+ const timeoutPromise = new Promise((resolve2) => {
2554
+ timer = setTimeout(() => resolve2("timeout"), ms);
2555
+ });
2556
+ try {
2557
+ return await Promise.race([promise, timeoutPromise]);
2558
+ } finally {
2559
+ if (timer !== void 0) clearTimeout(timer);
2560
+ }
2561
+ }
2562
+ async function allSettledMap(items, fn) {
2563
+ return await Promise.allSettled(items.map(fn));
2564
+ }
2565
+ async function parallelMap(items, fn, concurrency = Number.POSITIVE_INFINITY) {
2566
+ if (concurrency === Number.POSITIVE_INFINITY) {
2567
+ return await Promise.all(items.map(fn));
2568
+ }
2569
+ const results = [];
2570
+ const queue = [...items];
2571
+ const worker = async () => {
2572
+ while (queue.length > 0) {
2573
+ const item = queue.shift();
2574
+ results.push(await fn(item));
2575
+ }
2576
+ };
2577
+ const workerCount = Math.min(concurrency, items.length);
2578
+ const workers = Array.from({ length: workerCount }, () => worker());
2579
+ await Promise.all(workers);
2580
+ return results;
2581
+ }
2582
+ async function retryAsync(fn, options) {
2583
+ const { attempts = 3, baseDelay = 1e3, maxDelay = 3e4, shouldRetry = () => true } = options ?? {};
2584
+ let lastError;
2585
+ for (let attempt = 0; attempt < attempts; attempt++) {
2586
+ try {
2587
+ return await fn();
2588
+ } catch (error) {
2589
+ lastError = error;
2590
+ if (!shouldRetry(error) || attempt >= attempts - 1) break;
2591
+ const delay = Math.min(baseDelay * 2 ** attempt + Math.random() * baseDelay, maxDelay);
2592
+ await sleep(delay);
2593
+ }
2594
+ }
2595
+ throw lastError;
2596
+ }
2597
+ async function pipeline(initial, ...fns) {
2598
+ let result = initial;
2599
+ for (const fn of fns) {
2600
+ result = await fn(result);
2601
+ }
2602
+ return result;
2603
+ }
2604
+ function deferred() {
2605
+ let resolve2;
2606
+ let reject;
2607
+ const promise = new Promise((res, rej) => {
2608
+ resolve2 = res;
2609
+ reject = rej;
2610
+ });
2611
+ return { promise, resolve: resolve2, reject };
2612
+ }
2613
+
2614
+ // src/io/index.ts
2615
+ function parseCsv(input, options) {
2616
+ const { delimiter = ",", header = true, skipEmptyLines = true } = options ?? {};
2617
+ const lines = input.split(/\r?\n/);
2618
+ const rows = [];
2619
+ for (const line of lines) {
2620
+ const trimmed = line.trim();
2621
+ if (skipEmptyLines && trimmed.length === 0) continue;
2622
+ const values = parseCsvLine(trimmed, delimiter);
2623
+ rows.push(values);
2624
+ }
2625
+ if (rows.length === 0) return [];
2626
+ if (header) {
2627
+ const [head, ...body] = rows;
2628
+ if (head === void 0) return [];
2629
+ return body.map((row) => {
2630
+ const record = {};
2631
+ for (let i = 0; i < head.length; i++) {
2632
+ if (head[i] === "__proto__" || head[i] === "constructor" || head[i] === "prototype") continue;
2633
+ record[head[i]] = row[i] ?? "";
2634
+ }
2635
+ return record;
2636
+ });
2637
+ }
2638
+ return rows.map((row) => {
2639
+ const record = {};
2640
+ for (let i = 0; i < row.length; i++) {
2641
+ record[String(i)] = row[i];
2642
+ }
2643
+ return record;
2644
+ });
2645
+ }
2646
+ function parseCsvLine(line, delimiter) {
2647
+ const result = [];
2648
+ let current = "";
2649
+ let inQuotes = false;
2650
+ for (let i = 0; i < line.length; i++) {
2651
+ const ch = line[i];
2652
+ if (inQuotes) {
2653
+ if (ch === '"') {
2654
+ if (line[i + 1] === '"') {
2655
+ current += '"';
2656
+ i++;
2657
+ } else {
2658
+ inQuotes = false;
2659
+ }
2660
+ } else {
2661
+ current += ch;
2662
+ }
2663
+ } else {
2664
+ if (ch === '"') {
2665
+ inQuotes = true;
2666
+ } else if (ch === delimiter) {
2667
+ result.push(current);
2668
+ current = "";
2669
+ } else {
2670
+ current += ch;
2671
+ }
2672
+ }
2673
+ }
2674
+ result.push(current);
2675
+ return result;
2676
+ }
2677
+ function stringifyCsv(data, options) {
2678
+ const { delimiter = "," } = options ?? {};
2679
+ if (data.length === 0) return "";
2680
+ const headers = Object.keys(data[0]);
2681
+ const lines = [headers.map((v) => escapeCsvField(v, delimiter)).join(delimiter)];
2682
+ for (const record of data) {
2683
+ const row = headers.map((h) => escapeCsvField(String(record[h] ?? ""), delimiter));
2684
+ lines.push(row.join(delimiter));
2685
+ }
2686
+ return lines.join("\n");
2687
+ }
2688
+ function escapeCsvField(value, delimiter) {
2689
+ if (value.includes('"') || value.includes(delimiter) || value.includes("\n") || value.includes("\r")) {
2690
+ return '"' + value.replace(/"/g, '""') + '"';
2691
+ }
2692
+ return value;
2693
+ }
2694
+ function safeJsonParse(input, default_) {
2695
+ try {
2696
+ return JSON.parse(input);
2697
+ } catch {
2698
+ return default_ ?? null;
2699
+ }
2700
+ }
2701
+ function env(name, default_) {
2702
+ const value = process.env[name];
2703
+ return value ?? default_ ?? "";
2704
+ }
2705
+ function envInt(name, default_) {
2706
+ const value = process.env[name];
2707
+ if (value === void 0 || value === "") return default_ ?? 0;
2708
+ const parsed = Number.parseInt(value, 10);
2709
+ return Number.isNaN(parsed) ? default_ ?? 0 : parsed;
2710
+ }
2711
+ function envBool(name, default_) {
2712
+ const value = process.env[name];
2713
+ if (value === void 0 || value === "") return default_ ?? false;
2714
+ return value === "true" || value === "1" || value === "yes";
2715
+ }
2716
+
2717
+ // src/type/index.ts
2718
+ function isString(value) {
2719
+ return typeof value === "string";
2720
+ }
2721
+ function isNumber(value) {
2722
+ return typeof value === "number" && Number.isFinite(value);
2723
+ }
2724
+ function isBoolean(value) {
2725
+ return typeof value === "boolean";
2726
+ }
2727
+ function isObject(value) {
2728
+ return value !== null && typeof value === "object" && !Array.isArray(value);
2729
+ }
2730
+ function isArray(value) {
2731
+ return Array.isArray(value);
2732
+ }
2733
+ function isFunction(value) {
2734
+ return typeof value === "function";
2735
+ }
2736
+ function isDate(value) {
2737
+ return value instanceof Date && !Number.isNaN(value.getTime());
2738
+ }
2739
+ function isRegExp(value) {
2740
+ return value instanceof RegExp;
2741
+ }
2742
+ function isMap(value) {
2743
+ return value instanceof Map;
2744
+ }
2745
+ function isSet(value) {
2746
+ return value instanceof Set;
2747
+ }
2748
+ function isPromise(value) {
2749
+ return value instanceof Promise;
2750
+ }
2751
+ function isNull(value) {
2752
+ return value === null;
2753
+ }
2754
+ function isUndefined(value) {
2755
+ return value === void 0;
2756
+ }
2757
+ function isNil(value) {
2758
+ return value === null || value === void 0;
2759
+ }
2760
+ function assertDefined(value, message) {
2761
+ if (value === null || value === void 0) {
2762
+ throw new Error(message ?? "Expected value to be defined");
2763
+ }
2764
+ }
2765
+ function assertType(value, guard, message) {
2766
+ if (!guard(value)) {
2767
+ throw new Error(message ?? "Value does not match expected type");
2768
+ }
2769
+ }
2770
+ function ensureArray(value) {
2771
+ return Array.isArray(value) ? value : [value];
2772
+ }
2773
+ var castArray = ensureArray;
2774
+ function getType2(value) {
2775
+ if (value === null) return "null";
2776
+ if (value === void 0) return "undefined";
2777
+ if (typeof value === "string") return "string";
2778
+ if (typeof value === "boolean") return "boolean";
2779
+ if (typeof value === "function") return "function";
2780
+ if (typeof value === "number") {
2781
+ if (Number.isNaN(value)) return "nan";
2782
+ if (!Number.isFinite(value)) return "infinity";
2783
+ return "number";
2784
+ }
2785
+ if (Array.isArray(value)) return "array";
2786
+ if (value instanceof Date) return "date";
2787
+ if (value instanceof RegExp) return "regexp";
2788
+ if (value instanceof Map) return "map";
2789
+ if (value instanceof Set) return "set";
2790
+ if (value instanceof Promise) return "promise";
2791
+ return "object";
2792
+ }
2793
+
2794
+ // src/dep-exray/scanner/index.ts
2795
+ import { readFileSync, readdirSync, existsSync } from "fs";
2796
+ import { join as join2, basename as basename2 } from "path";
2797
+
2798
+ // src/dep-exray/known-mappings.ts
2799
+ var KNOWN_MAPPINGS = [
2800
+ {
2801
+ name: "lodash",
2802
+ size: "4.2 MB",
2803
+ replacement: "jscore-core",
2804
+ confidence: "high",
2805
+ autoPrReady: true,
2806
+ reason: "Most lodash functions have direct replacements in jscore-core with 99% API compatibility",
2807
+ detectionPattern: `from ['"]lodash['"]|require\\(['"]lodash['"]\\)`
2808
+ },
2809
+ {
2810
+ name: "moment",
2811
+ size: "2.5 MB",
2812
+ replacement: "jscore-core/date",
2813
+ confidence: "high",
2814
+ autoPrReady: true,
2815
+ reason: "date utilities in jscore-core cover 95% of common moment use cases",
2816
+ detectionPattern: `from ['"]moment['"]|require\\(['"]moment['"]\\)`
2817
+ },
2818
+ {
2819
+ name: "date-fns",
2820
+ size: "1.2 MB (tree-shaked ~50KB)",
2821
+ replacement: "jscore-core/date",
2822
+ confidence: "medium",
2823
+ autoPrReady: false,
2824
+ reason: "Partially overlapping \u2014 jscore-core covers basic date ops but not all locale support",
2825
+ detectionPattern: `from ['"]date-fns['"]|require\\(['"]date-fns['"]\\)`
2826
+ },
2827
+ {
2828
+ name: "axios",
2829
+ size: "1.6 MB",
2830
+ replacement: "native fetch + jscore-core/async/retry",
2831
+ confidence: "medium",
2832
+ autoPrReady: false,
2833
+ reason: "Native fetch covers most use cases; needs manual review for interceptors",
2834
+ detectionPattern: `from ['"]axios['"]|require\\(['"]axios['"]\\)`
2835
+ },
2836
+ {
2837
+ name: "uuid",
2838
+ size: "30 KB",
2839
+ replacement: "crypto.randomUUID() (native)",
2840
+ confidence: "high",
2841
+ autoPrReady: true,
2842
+ reason: "crypto.randomUUID() is available in all modern Node.js and browsers",
2843
+ detectionPattern: `from ['"]uuid['"]|require\\(['"]uuid['"]\\)`
2844
+ },
2845
+ {
2846
+ name: "deepmerge",
2847
+ size: "15 KB",
2848
+ replacement: "jscore-core",
2849
+ confidence: "high",
2850
+ autoPrReady: true,
2851
+ reason: "jscore-core provides deepMerge out of the box",
2852
+ detectionPattern: `from ['"]deepmerge['"]|require\\(['"]deepmerge['"]\\)`
2853
+ },
2854
+ {
2855
+ name: "lodash.merge",
2856
+ size: "25 KB",
2857
+ replacement: "jscore-core",
2858
+ confidence: "high",
2859
+ autoPrReady: true,
2860
+ reason: "jscore-core provides deepMerge out of the box",
2861
+ detectionPattern: `from ['"]lodash\\.(merge|clone|pick|omit|get|set)['"]`
2862
+ },
2863
+ {
2864
+ name: "chalk",
2865
+ size: "45 KB",
2866
+ replacement: "picocolors",
2867
+ confidence: "medium",
2868
+ autoPrReady: false,
2869
+ reason: "picocolors is 3KB vs chalk's 45KB with same API",
2870
+ detectionPattern: `from ['"]chalk['"]|require\\(['"]chalk['"]\\)`
2871
+ },
2872
+ {
2873
+ name: "nanoid",
2874
+ size: "8 KB",
2875
+ replacement: "jscore-core/string (nanoid)",
2876
+ confidence: "high",
2877
+ autoPrReady: true,
2878
+ reason: "jscore-core provides nanoid with same API",
2879
+ detectionPattern: `from ['"]nanoid['"]|require\\(['"]nanoid['"]\\)`
2880
+ },
2881
+ {
2882
+ name: "dayjs",
2883
+ size: "50 KB",
2884
+ replacement: "jscore-core/date",
2885
+ confidence: "medium",
2886
+ autoPrReady: false,
2887
+ reason: "Partially overlapping \u2014 covers basics but not all plugins",
2888
+ detectionPattern: `from ['"]dayjs['"]|require\\(['"]dayjs['"]\\)`
2889
+ },
2890
+ {
2891
+ name: "clsx",
2892
+ size: "5 KB",
2893
+ replacement: "native template literals",
2894
+ confidence: "high",
2895
+ autoPrReady: true,
2896
+ reason: "Can be replaced with simple template literal conditional pattern",
2897
+ detectionPattern: `from ['"]clsx['"]|require\\(['"]clsx['"]\\)`
2898
+ }
2899
+ ];
2900
+ var KNOWN_CVES = {
2901
+ "ansi-regex": [
2902
+ { cve: "CVE-2021-3807", severity: "high", fix: "Update to ansi-regex@6.0.1 or later" }
2903
+ ],
2904
+ "semver": [
2905
+ { cve: "CVE-2022-25883", severity: "medium", fix: "Update to semver@7.5.2 or later" }
2906
+ ],
2907
+ "json5": [
2908
+ { cve: "CVE-2022-46175", severity: "high", fix: "Update to json5@2.2.3 or later" }
2909
+ ],
2910
+ "lodash": [
2911
+ { cve: "CVE-2020-28502", severity: "high", fix: "Update to lodash@4.17.21 or later" },
2912
+ { cve: "CVE-2020-8203", severity: "medium", fix: "Update to lodash@4.17.21 or later" }
2913
+ ]
2914
+ };
2915
+
2916
+ // src/dep-exray/scanner/index.ts
2917
+ function parsePackageJson(path) {
2918
+ const raw = readFileSync(path, "utf-8");
2919
+ const json = JSON.parse(raw);
2920
+ return {
2921
+ name: json.name ?? basename2(join2(path, "..")),
2922
+ dependencies: json.dependencies ?? {},
2923
+ devDependencies: json.devDependencies ?? {}
2924
+ };
2925
+ }
2926
+ function parseLockfile(projectPath) {
2927
+ const lockPath = join2(projectPath, "package-lock.json");
2928
+ if (!existsSync(lockPath)) return null;
2929
+ try {
2930
+ const raw = readFileSync(lockPath, "utf-8");
2931
+ const json = JSON.parse(raw);
2932
+ const packages = {};
2933
+ if (json.packages) {
2934
+ for (const [key, val] of Object.entries(json.packages)) {
2935
+ if (key) {
2936
+ packages[key] = val;
2937
+ }
2938
+ }
2939
+ }
2940
+ if (json.dependencies && Object.keys(packages).length === 0) {
2941
+ for (const [key, val] of Object.entries(json.dependencies)) {
2942
+ packages[key] = { version: val.version, dependencies: val.requires };
2943
+ }
2944
+ }
2945
+ return { packages };
2946
+ } catch {
2947
+ return null;
2948
+ }
2949
+ }
2950
+ function detectImportInFile(filePath, regex) {
2951
+ try {
2952
+ const content = readFileSync(filePath, "utf-8");
2953
+ return regex.test(content);
2954
+ } catch {
2955
+ return false;
2956
+ }
2957
+ }
2958
+ function detectImportsInSrc(projectPath, mapping) {
2959
+ const regex = new RegExp(mapping.detectionPattern);
2960
+ const srcDir = join2(projectPath, "src");
2961
+ if (!existsSync(srcDir)) return false;
2962
+ try {
2963
+ const files = collectSourceFiles(srcDir);
2964
+ for (const file of files) {
2965
+ if (detectImportInFile(file, regex)) return true;
2966
+ }
2967
+ } catch {
2968
+ return false;
2969
+ }
2970
+ return false;
2971
+ }
2972
+ function collectSourceFiles(dir) {
2973
+ const results = [];
2974
+ try {
2975
+ const entries = readdirSync(dir, { withFileTypes: true });
2976
+ for (const entry of entries) {
2977
+ if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git" || entry.name === "coverage" || entry.name === ".tsup") {
2978
+ continue;
2979
+ }
2980
+ const full = join2(dir, entry.name);
2981
+ if (entry.isDirectory()) {
2982
+ results.push(...collectSourceFiles(full));
2983
+ } else if (entry.isFile()) {
2984
+ const ext = entry.name.split(".").pop();
2985
+ if (ext === "ts" || ext === "tsx" || ext === "js" || ext === "jsx" || ext === "mjs" || ext === "cjs") {
2986
+ results.push(full);
2987
+ }
2988
+ }
2989
+ }
2990
+ } catch {
2991
+ }
2992
+ return results;
2993
+ }
2994
+ function estimateTransitiveCount(lockfile, directNames) {
2995
+ if (!lockfile) return 0;
2996
+ let count = 0;
2997
+ for (const key of Object.keys(lockfile.packages)) {
2998
+ if (!key || key === "") continue;
2999
+ const name = key.startsWith("node_modules/") ? key.slice("node_modules/".length) : key;
3000
+ const rootName = name.startsWith("@") ? `${name.split("/")[0]}/${name.split("/")[1]}` : name.split("/")[0];
3001
+ if (rootName && !directNames.has(rootName)) {
3002
+ count++;
3003
+ }
3004
+ }
3005
+ return count;
3006
+ }
3007
+ function parseSize(value) {
3008
+ const cleaned = value.replace(/\(.*?\)/g, "").trim();
3009
+ const match = cleaned.match(/^([\d.]+)\s*(KB|MB)/i);
3010
+ if (!match) return 0;
3011
+ const num = Number.parseFloat(match[1]);
3012
+ if (!match[2]) return 0;
3013
+ if (match[2].toUpperCase() === "MB") return num * 1024;
3014
+ return num;
3015
+ }
3016
+ async function scanProject(config) {
3017
+ const projectPath = config.path ?? ".";
3018
+ const pkgPath = join2(projectPath, "package.json");
3019
+ if (!existsSync(pkgPath)) {
3020
+ throw new Error(`No package.json found at ${projectPath}. Run dep-exray in a JavaScript/TypeScript project directory.`);
3021
+ }
3022
+ const pkg = parsePackageJson(pkgPath);
3023
+ const lockfile = parseLockfile(projectPath);
3024
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
3025
+ const directNames = new Set(Object.keys(allDeps));
3026
+ const transitiveCount = estimateTransitiveCount(lockfile, directNames);
3027
+ const highImpactReplacements = [];
3028
+ const mediumImpactReplacements = [];
3029
+ const securityIssues = [];
3030
+ const sizeMap = {};
3031
+ for (const m of KNOWN_MAPPINGS) {
3032
+ sizeMap[m.name] = m.size;
3033
+ }
3034
+ for (const mapping of KNOWN_MAPPINGS) {
3035
+ const isDirect = directNames.has(mapping.name);
3036
+ if (!isDirect) continue;
3037
+ const isUsed = detectImportsInSrc(projectPath, mapping);
3038
+ if (!isUsed && !config.verbose) continue;
3039
+ const mappingSize = parseSize(sizeMap[mapping.name] ?? "0 KB");
3040
+ const replacementSize = mapping.replacement.startsWith("native") ? 0 : 5;
3041
+ const reductionStr = mappingSize > 1024 ? `${(mappingSize / 1024).toFixed(1)} MB \u2192 ${replacementSize} KB` : `${mappingSize.toFixed(0)} KB \u2192 ${replacementSize} KB`;
3042
+ const suggestion = {
3043
+ packageName: mapping.name,
3044
+ reason: mapping.reason,
3045
+ replacement: mapping.replacement,
3046
+ estimatedSizeReduction: reductionStr,
3047
+ confidence: mapping.confidence,
3048
+ autoPrReady: mapping.autoPrReady
3049
+ };
3050
+ if (mapping.confidence === "high") {
3051
+ highImpactReplacements.push(suggestion);
3052
+ } else {
3053
+ mediumImpactReplacements.push(suggestion);
3054
+ }
3055
+ }
3056
+ for (const [name, cves] of Object.entries(KNOWN_CVES)) {
3057
+ if (directNames.has(name)) {
3058
+ for (const cveItem of cves) {
3059
+ securityIssues.push({
3060
+ packageName: name,
3061
+ cveId: cveItem.cve,
3062
+ severity: cveItem.severity,
3063
+ fix: cveItem.fix
3064
+ });
3065
+ }
3066
+ }
3067
+ }
3068
+ let totalSizeKB = 0;
3069
+ for (const depName of directNames) {
3070
+ const sizeStr = sizeMap[depName];
3071
+ if (sizeStr) {
3072
+ totalSizeKB += parseSize(sizeStr);
3073
+ } else {
3074
+ totalSizeKB += 50;
3075
+ }
3076
+ }
3077
+ totalSizeKB += transitiveCount * 30;
3078
+ const totalSizeStr = totalSizeKB > 1024 ? `${(totalSizeKB / 1024).toFixed(1)} MB` : `${totalSizeKB.toFixed(0)} KB`;
3079
+ return {
3080
+ projectName: pkg.name,
3081
+ directDeps: directNames.size,
3082
+ transitiveDeps: transitiveCount,
3083
+ totalEstimatedSize: totalSizeStr,
3084
+ highImpactReplacements,
3085
+ mediumImpactReplacements,
3086
+ securityIssues
3087
+ };
3088
+ }
3089
+
3090
+ // src/dep-exray/reporter/index.ts
3091
+ var _ = {
3092
+ reset: "\x1B[0m",
3093
+ bold: "\x1B[1m",
3094
+ dim: "\x1B[2m",
3095
+ red: "\x1B[31m",
3096
+ green: "\x1B[32m",
3097
+ yellow: "\x1B[33m",
3098
+ blue: "\x1B[34m",
3099
+ cyan: "\x1B[36m",
3100
+ white: "\x1B[37m"
3101
+ };
3102
+ function style(text, codes) {
3103
+ return codes.join("") + text + _.reset;
3104
+ }
3105
+ function severityColor(severity) {
3106
+ switch (severity) {
3107
+ case "critical":
3108
+ return style(severity.toUpperCase(), [_.bold, _.red]);
3109
+ case "high":
3110
+ return style(severity.toUpperCase(), [_.red]);
3111
+ case "medium":
3112
+ return style(severity.toUpperCase(), [_.yellow]);
3113
+ case "low":
3114
+ return style(severity.toUpperCase(), [_.dim]);
3115
+ }
3116
+ }
3117
+ function confidenceIcon(confidence) {
3118
+ switch (confidence) {
3119
+ case "high":
3120
+ return style("\u25CF", [_.green]);
3121
+ case "medium":
3122
+ return style("\u25CF", [_.yellow]);
3123
+ case "low":
3124
+ return style("\u25CF", [_.red]);
3125
+ }
3126
+ }
3127
+ function generateReport(result, jsonOutput) {
3128
+ if (jsonOutput) {
3129
+ return JSON.stringify(result, null, 2);
3130
+ }
3131
+ const lines = [];
3132
+ const t = (text, codes = [_.cyan]) => style(text, [_.bold, ...codes]);
3133
+ lines.push(t(`\u250C${"\u2500".repeat(58)}\u2510`));
3134
+ lines.push(t(`\u2502${" ".repeat(18)}dep-exray Report${" ".repeat(21)}\u2502`));
3135
+ lines.push(t(`\u251C${"\u2500".repeat(58)}\u2524`));
3136
+ lines.push(t(`\u2502 ${style("\u{1F4E6} PROJECT:", [_.white])} ${style(result.projectName, [_.bold])}${" ".repeat(Math.max(1, 47 - result.projectName.length))}\u2502`));
3137
+ lines.push(t(`\u2502 ${style("\u{1F4CA} DEPENDENCIES:", [_.white])} ${style(String(result.directDeps), [_.bold])} direct + ${style(String(result.transitiveDeps), [_.bold])} transitive${" ".repeat(Math.max(1, 27 - String(result.transitiveDeps).length))}\u2502`));
3138
+ lines.push(t(`\u2502 ${style("\u{1F4BE} TOTAL SIZE:", [_.white])} ${style(result.totalEstimatedSize, [_.bold])}${" ".repeat(Math.max(1, 42 - result.totalEstimatedSize.length))}\u2502`));
3139
+ lines.push(t(`\u251C${"\u2500".repeat(58)}\u2524`));
3140
+ if (result.highImpactReplacements.length > 0) {
3141
+ lines.push(t(`\u2502 ${style("\u{1F7E2}", [_.green])} ${style("HIGH IMPACT REPLACEMENTS", [_.bold, _.green])}${" ".repeat(23)}\u2502`));
3142
+ for (const item of result.highImpactReplacements) {
3143
+ const autoPr = item.autoPrReady ? style("\u2713 Auto-PR ready", [_.green]) : style("Manual review needed", [_.dim]);
3144
+ const confIcon = confidenceIcon(item.confidence);
3145
+ lines.push(t(`\u251C${"\u2500".repeat(58)}\u2524`));
3146
+ lines.push(t(`\u2502 ${style("\u2717", [_.red])} ${style(item.packageName, [_.bold])} (${item.estimatedSizeReduction})${" ".repeat(Math.max(1, 38 - item.estimatedSizeReduction.length))}\u2502`));
3147
+ lines.push(t(`\u2502 ${style("\u2192", [_.dim])} ${style(item.replacement, [_.cyan])}${" ".repeat(Math.max(1, 51 - item.replacement.length))}\u2502`));
3148
+ lines.push(t(`\u2502 ${style("\u2514\u2500", [_.dim])} ${autoPr} ${confIcon} ${item.confidence}${" ".repeat(Math.max(1, 35))}\u2502`));
3149
+ }
3150
+ }
3151
+ if (result.mediumImpactReplacements.length > 0) {
3152
+ lines.push(t(`\u251C${"\u2500".repeat(58)}\u2524`));
3153
+ lines.push(t(`\u2502 ${style("\u{1F7E1}", [_.yellow])} ${style("MEDIUM IMPACT REPLACEMENTS", [_.bold, _.yellow])}${" ".repeat(20)}\u2502`));
3154
+ for (const item of result.mediumImpactReplacements) {
3155
+ const autoPr = item.autoPrReady ? style("\u2713 Auto-PR ready", [_.green]) : style("Manual review needed", [_.dim]);
3156
+ const confIcon = confidenceIcon(item.confidence);
3157
+ lines.push(t(`\u251C${"\u2500".repeat(58)}\u2524`));
3158
+ lines.push(t(`\u2502 ${style("\u2717", [_.red])} ${style(item.packageName, [_.bold])} (${item.estimatedSizeReduction})${" ".repeat(Math.max(1, 38 - item.estimatedSizeReduction.length))}\u2502`));
3159
+ lines.push(t(`\u2502 ${style("\u2192", [_.dim])} ${style(item.replacement, [_.cyan])}${" ".repeat(Math.max(1, 51 - item.replacement.length))}\u2502`));
3160
+ lines.push(t(`\u2502 ${style("\u2514\u2500", [_.dim])} ${autoPr} ${confIcon} ${item.confidence}${" ".repeat(Math.max(1, 35))}\u2502`));
3161
+ }
3162
+ }
3163
+ if (result.securityIssues.length > 0) {
3164
+ lines.push(t(`\u251C${"\u2500".repeat(58)}\u2524`));
3165
+ lines.push(t(`\u2502 ${style("\u{1F534}", [_.red])} ${style("SECURITY ISSUES", [_.bold, _.red])}${" ".repeat(33)}\u2502`));
3166
+ for (const issue of result.securityIssues) {
3167
+ lines.push(t(`\u251C${"\u2500".repeat(58)}\u2524`));
3168
+ lines.push(t(`\u2502 ${severityColor(issue.severity)} ${style(issue.cveId, [_.bold])} in ${issue.packageName}${" ".repeat(Math.max(1, 40 - issue.packageName.length))}\u2502`));
3169
+ lines.push(t(`\u2502 ${style("\u2192", [_.dim])} ${issue.fix}${" ".repeat(Math.max(1, 52 - issue.fix.length))}\u2502`));
3170
+ }
3171
+ }
3172
+ lines.push(t(`\u2514${"\u2500".repeat(58)}\u2518`));
3173
+ return lines.join("\n");
3174
+ }
3175
+
3176
+ // src/dep-exray/analyzer/index.ts
3177
+ import { readFileSync as readFileSync2 } from "fs";
3178
+ import { readdirSync as readdirSync2, statSync } from "fs";
3179
+ import { join as join3, extname as extname2 } from "path";
3180
+ var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
3181
+ function isSourceFile(file) {
3182
+ return SOURCE_EXTENSIONS.has(extname2(file));
3183
+ }
3184
+ function collectSourceFiles2(dir) {
3185
+ const results = [];
3186
+ try {
3187
+ const entries = readdirSync2(dir, { withFileTypes: true });
3188
+ for (const entry of entries) {
3189
+ const fullPath = join3(dir, entry.name);
3190
+ if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git" || entry.name === "coverage" || entry.name === ".tsup") {
3191
+ continue;
3192
+ }
3193
+ if (entry.isDirectory()) {
3194
+ results.push(...collectSourceFiles2(fullPath));
3195
+ } else if (entry.isFile() && isSourceFile(entry.name)) {
3196
+ results.push(fullPath);
3197
+ }
3198
+ }
3199
+ } catch {
3200
+ }
3201
+ return results;
3202
+ }
3203
+ function escapeRegex(str) {
3204
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3205
+ }
3206
+ async function analyzeUsage(projectPath, packageName) {
3207
+ const importLocations = [];
3208
+ const escaped = escapeRegex(packageName);
3209
+ const importRegex = new RegExp(
3210
+ `(?:from\\s+['"]${escaped}(?:/['"]|['"])|require\\(\\s*['"]${escaped}(?:/|['"]))`,
3211
+ "g"
3212
+ );
3213
+ const srcDir = join3(projectPath, "src");
3214
+ let files;
3215
+ try {
3216
+ if (statSync(srcDir).isDirectory()) {
3217
+ files = collectSourceFiles2(srcDir);
3218
+ } else {
3219
+ files = collectSourceFiles2(projectPath);
3220
+ }
3221
+ } catch {
3222
+ files = collectSourceFiles2(projectPath);
3223
+ }
3224
+ for (const file of files) {
3225
+ try {
3226
+ const content = readFileSync2(file, "utf-8");
3227
+ importRegex.lastIndex = 0;
3228
+ if (importRegex.test(content)) {
3229
+ importLocations.push(file);
3230
+ }
3231
+ } catch {
3232
+ }
3233
+ }
3234
+ return {
3235
+ isUsed: importLocations.length > 0,
3236
+ importCount: importLocations.length,
3237
+ importLocations
3238
+ };
3239
+ }
3240
+
3241
+ // src/validation/isNIK.ts
3242
+ function isNIK(value) {
3243
+ const digits = value.replace(/\D/g, "");
3244
+ if (digits.length !== 16) return false;
3245
+ const rawDay = Number.parseInt(digits.slice(6, 8), 10);
3246
+ const month = Number.parseInt(digits.slice(8, 10), 10);
3247
+ const year = Number.parseInt(digits.slice(10, 12), 10);
3248
+ if (rawDay < 1 || rawDay > 71) return false;
3249
+ if (month < 1 || month > 12) return false;
3250
+ let day = rawDay;
3251
+ if (day >= 41) day -= 40;
3252
+ const fullYear = year < 70 ? 2e3 + year : 1900 + year;
3253
+ const date = new Date(fullYear, month - 1, day);
3254
+ return date.getFullYear() === fullYear && date.getMonth() === month - 1 && date.getDate() === day;
3255
+ }
3256
+
3257
+ // src/validation/isNPWP.ts
3258
+ function isNPWP(value) {
3259
+ const digits = value.replace(/\D/g, "");
3260
+ if (digits.length !== 15 && digits.length !== 16) return false;
3261
+ const nums = [];
3262
+ for (let i = 0; i < digits.length; i++) {
3263
+ nums.push(Number.parseInt(digits[i], 10));
3264
+ }
3265
+ const checkDigit = nums[nums.length - 1];
3266
+ let sum2 = 0;
3267
+ for (let i = 0; i < nums.length - 1; i++) {
3268
+ sum2 += nums[i] * [3, 7, 1][i % 3];
3269
+ }
3270
+ const computed = (11 - sum2 % 11) % 10;
3271
+ return computed === checkDigit;
3272
+ }
3273
+
3274
+ // src/validation/isPhone.ts
3275
+ var INDONESIAN_PREFIXES = [
3276
+ [11, 19],
3277
+ [21, 29],
3278
+ [51, 59],
3279
+ [77, 79],
3280
+ [95, 99]
3281
+ ];
3282
+ function isValidIndonesianPrefix(prefix) {
3283
+ for (const [min, max] of INDONESIAN_PREFIXES) {
3284
+ if (prefix >= min && prefix <= max) return true;
3285
+ }
3286
+ return false;
3287
+ }
3288
+ function isPhone(value, country = "id") {
3289
+ const digits = value.replace(/\D/g, "");
3290
+ if (country === "any") {
3291
+ return digits.length >= 10 && digits.length <= 15;
3292
+ }
3293
+ if (digits.length < 10) return false;
3294
+ let normalized;
3295
+ if (digits.startsWith("62")) {
3296
+ normalized = digits.slice(2);
3297
+ } else if (digits.startsWith("0")) {
3298
+ normalized = digits.slice(1);
3299
+ } else {
3300
+ normalized = digits;
3301
+ }
3302
+ if (normalized.length < 10 || normalized.length > 13) return false;
3303
+ if (!normalized.startsWith("8")) return false;
3304
+ const prefix = Number.parseInt(normalized.slice(1, 3), 10);
3305
+ return isValidIndonesianPrefix(prefix);
3306
+ }
3307
+
3308
+ // src/validation/isEmail.ts
3309
+ var LOCAL_SPECIAL = "!#$%&'*+/=?^_`{|}~-";
3310
+ function isQuotedLocalPart(local) {
3311
+ if (local.length < 2) return false;
3312
+ let i = 1;
3313
+ while (i < local.length - 1) {
3314
+ const ch = local[i];
3315
+ if (ch === "\\") {
3316
+ i++;
3317
+ if (i >= local.length - 1) return false;
3318
+ } else if (ch === '"') {
3319
+ return false;
3320
+ }
3321
+ i++;
3322
+ }
3323
+ return true;
3324
+ }
3325
+ function isUnquotedLocalPart(local) {
3326
+ if (local.length === 0 || local.startsWith(".") || local.endsWith(".")) return false;
3327
+ for (let i = 0; i < local.length; i++) {
3328
+ const ch = local[i];
3329
+ if (ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "." || LOCAL_SPECIAL.includes(ch)) {
3330
+ continue;
3331
+ }
3332
+ return false;
3333
+ }
3334
+ for (let i = 1; i < local.length; i++) {
3335
+ if (local[i] === "." && local[i - 1] === ".") return false;
3336
+ }
3337
+ return true;
3338
+ }
3339
+ function isValidDomain(domain) {
3340
+ if (domain.length === 0 || domain.startsWith(".") || domain.endsWith(".")) return false;
3341
+ const labels = domain.split(".");
3342
+ if (labels.length < 2) return false;
3343
+ for (const label of labels) {
3344
+ if (label.length === 0 || label.length > 63) return false;
3345
+ if (label.startsWith("-") || label.endsWith("-")) return false;
3346
+ for (let i = 0; i < label.length; i++) {
3347
+ const ch = label[i];
3348
+ if (!(ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "-")) {
3349
+ return false;
3350
+ }
3351
+ }
3352
+ }
3353
+ return true;
3354
+ }
3355
+ function isEmail(value) {
3356
+ if (value.length > 254) return false;
3357
+ const atIndex = value.lastIndexOf("@");
3358
+ if (atIndex < 1 || atIndex === value.length - 1) return false;
3359
+ const localPart = value.slice(0, atIndex);
3360
+ const domainPart = value.slice(atIndex + 1);
3361
+ if (localPart.length > 64) return false;
3362
+ if (domainPart.length > 255) return false;
3363
+ if (localPart.startsWith('"') && localPart.endsWith('"')) {
3364
+ if (!isQuotedLocalPart(localPart)) return false;
3365
+ } else {
3366
+ if (!isUnquotedLocalPart(localPart)) return false;
3367
+ }
3368
+ return isValidDomain(domainPart);
3369
+ }
3370
+
3371
+ // src/validation/isURL.ts
3372
+ var IPV4_OCTET = /^(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/;
3373
+ function isValidIPv4(hostname) {
3374
+ const octets = hostname.split(".");
3375
+ if (octets.length !== 4) return false;
3376
+ return octets.every((octet) => IPV4_OCTET.test(octet));
3377
+ }
3378
+ function isValidDNSHostname(hostname) {
3379
+ if (hostname.startsWith(".") || hostname.endsWith(".")) return false;
3380
+ const labels = hostname.split(".");
3381
+ if (labels.length < 2) return false;
3382
+ for (const label of labels) {
3383
+ if (label.length === 0 || label.length > 63) return false;
3384
+ if (label.startsWith("-") || label.endsWith("-")) return false;
3385
+ for (let i = 0; i < label.length; i++) {
3386
+ const ch = label[i];
3387
+ if (!(ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "-")) {
3388
+ return false;
3389
+ }
3390
+ }
3391
+ }
3392
+ return true;
3393
+ }
3394
+ function isValidHostname(hostname) {
3395
+ if (hostname.length === 0) return false;
3396
+ if (hostname.startsWith("[") && hostname.endsWith("]")) {
3397
+ return hostname.length > 2;
3398
+ }
3399
+ if (/^\d/.test(hostname) || /\d$/.test(hostname)) {
3400
+ if (isValidIPv4(hostname)) return true;
3401
+ }
3402
+ if (hostname === "localhost") return true;
3403
+ return isValidDNSHostname(hostname);
3404
+ }
3405
+ function isURL(value) {
3406
+ try {
3407
+ const url = new URL(value);
3408
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
3409
+ return false;
3410
+ }
3411
+ return isValidHostname(url.hostname);
3412
+ } catch {
3413
+ return false;
3414
+ }
3415
+ }
3416
+
3417
+ // src/validation/parseNIK.ts
3418
+ function parseNIK(value) {
3419
+ const digits = value.replace(/\D/g, "");
3420
+ const info = {
3421
+ nik: value,
3422
+ valid: false,
3423
+ gender: null,
3424
+ birthDate: null,
3425
+ province: null,
3426
+ provinceCode: null,
3427
+ city: null,
3428
+ cityCode: null,
3429
+ district: null,
3430
+ districtCode: null,
3431
+ uniqueCode: null
3432
+ };
3433
+ if (digits.length !== 16) return info;
3434
+ const provinceCode = digits.slice(0, 2);
3435
+ const cityCode = digits.slice(2, 4);
3436
+ const districtCode = digits.slice(4, 6);
3437
+ const rawDay = Number.parseInt(digits.slice(6, 8), 10);
3438
+ const month = Number.parseInt(digits.slice(8, 10), 10);
3439
+ const year = Number.parseInt(digits.slice(10, 12), 10);
3440
+ const uniqueCode = digits.slice(12, 16);
3441
+ if (rawDay < 1 || rawDay > 71 || month < 1 || month > 12) return info;
3442
+ const gender = rawDay >= 41 ? "PEREMPUAN" : "LAKI-LAKI";
3443
+ let day = rawDay;
3444
+ if (day >= 41) day -= 40;
3445
+ const fullYear = year < 70 ? 2e3 + year : 1900 + year;
3446
+ const birthDate = new Date(fullYear, month - 1, day);
3447
+ if (birthDate.getFullYear() !== fullYear || birthDate.getMonth() !== month - 1 || birthDate.getDate() !== day) {
3448
+ return info;
3449
+ }
3450
+ return {
3451
+ nik: value,
3452
+ valid: true,
3453
+ gender,
3454
+ birthDate,
3455
+ province: PROVINCE_CODES[provinceCode] ?? null,
3456
+ provinceCode,
3457
+ city: null,
3458
+ cityCode,
3459
+ district: null,
3460
+ districtCode,
3461
+ uniqueCode
3462
+ };
3463
+ }
3464
+ var PROVINCE_CODES = {
3465
+ "11": "ACEH",
3466
+ "12": "SUMATERA UTARA",
3467
+ "13": "SUMATERA BARAT",
3468
+ "14": "RIAU",
3469
+ "15": "JAMBI",
3470
+ "16": "SUMATERA SELATAN",
3471
+ "17": "BENGKULU",
3472
+ "18": "LAMPUNG",
3473
+ "19": "KEPULAUAN BANGKA BELITUNG",
3474
+ "21": "KEPULAUAN RIAU",
3475
+ "31": "DKI JAKARTA",
3476
+ "32": "JAWA BARAT",
3477
+ "33": "JAWA TENGAH",
3478
+ "34": "DI YOGYAKARTA",
3479
+ "35": "JAWA TIMUR",
3480
+ "36": "BANTEN",
3481
+ "51": "BALI",
3482
+ "52": "NUSA TENGGARA BARAT",
3483
+ "53": "NUSA TENGGARA TIMUR",
3484
+ "61": "KALIMANTAN BARAT",
3485
+ "62": "KALIMANTAN TENGAH",
3486
+ "63": "KALIMANTAN SELATAN",
3487
+ "64": "KALIMANTAN TIMUR",
3488
+ "65": "KALIMANTAN UTARA",
3489
+ "71": "SULAWESI UTARA",
3490
+ "72": "SULAWESI TENGAH",
3491
+ "73": "SULAWESI SELATAN",
3492
+ "74": "SULAWESI TENGGARA",
3493
+ "75": "GORONTALO",
3494
+ "76": "SULAWESI BARAT",
3495
+ "81": "MALUKU",
3496
+ "82": "MALUKU UTARA",
3497
+ "91": "PAPUA",
3498
+ "92": "PAPUA BARAT",
3499
+ "93": "PAPUA SELATAN",
3500
+ "94": "PAPUA TENGAH",
3501
+ "95": "PAPUA PEGUNUNGAN"
3502
+ };
3503
+
3504
+ // src/validation/isPlatNomor.ts
3505
+ function isPlatNomor(value) {
3506
+ const trimmed = value.trim().toUpperCase();
3507
+ const regex = /^([A-Z]{1,2})\s*(\d{1,4})\s*([A-Z]{0,3})$/;
3508
+ const match = trimmed.match(regex);
3509
+ if (!match) return false;
3510
+ const kodeDepan = match[1];
3511
+ const angka = parseInt(match[2], 10);
3512
+ const kodeBelakang = match[3] || "";
3513
+ if (!KODE_DAERAH.includes(kodeDepan)) return false;
3514
+ if (angka < 1 || angka > 9999) return false;
3515
+ if (kodeBelakang.length > 3) return false;
3516
+ return true;
3517
+ }
3518
+ var KODE_DAERAH = [
3519
+ "A",
3520
+ "AA",
3521
+ "AB",
3522
+ "AD",
3523
+ "AE",
3524
+ "AG",
3525
+ "B",
3526
+ "BA",
3527
+ "BB",
3528
+ "BD",
3529
+ "BE",
3530
+ "BG",
3531
+ "BH",
3532
+ "BK",
3533
+ "BL",
3534
+ "BM",
3535
+ "BN",
3536
+ "BP",
3537
+ "BR",
3538
+ "BT",
3539
+ "BU",
3540
+ "BV",
3541
+ "BW",
3542
+ "D",
3543
+ "DA",
3544
+ "DB",
3545
+ "DC",
3546
+ "DD",
3547
+ "DE",
3548
+ "DF",
3549
+ "DG",
3550
+ "DH",
3551
+ "DK",
3552
+ "DL",
3553
+ "DM",
3554
+ "DN",
3555
+ "DP",
3556
+ "DR",
3557
+ "DT",
3558
+ "DU",
3559
+ "DW",
3560
+ "E",
3561
+ "EA",
3562
+ "EB",
3563
+ "ED",
3564
+ "EE",
3565
+ "F",
3566
+ "G",
3567
+ "H",
3568
+ "K",
3569
+ "KB",
3570
+ "KH",
3571
+ "KI",
3572
+ "KU",
3573
+ "KT",
3574
+ "L",
3575
+ "M",
3576
+ "N",
3577
+ "NB",
3578
+ "NG",
3579
+ "NK",
3580
+ "NM",
3581
+ "P",
3582
+ "PA",
3583
+ "PB",
3584
+ "R",
3585
+ "S",
3586
+ "ST",
3587
+ "T",
3588
+ "W",
3589
+ "Z"
3590
+ ];
3591
+
3592
+ // src/validation/isKodepos.ts
3593
+ function isKodepos(value) {
3594
+ if (value.length !== 5) return false;
3595
+ return /^\d{5}$/.test(value);
3596
+ }
3597
+
3598
+ // src/validation/isNoRekening.ts
3599
+ function isNoRekening(value) {
3600
+ const digits = value.replace(/\D/g, "");
3601
+ if (digits.length < 8 || digits.length > 16) return false;
3602
+ return true;
3603
+ }
3604
+
3605
+ // src/validation/isNoSIM.ts
3606
+ function isNoSIM(value) {
3607
+ const digits = value.replace(/\D/g, "");
3608
+ return digits.length === 12;
3609
+ }
3610
+
3611
+ // src/validation/isPassport.ts
3612
+ function isPassport(value) {
3613
+ return /^[A-Za-z]{2}\d{7}$/.test(value.trim());
3614
+ }
3615
+
3616
+ // src/validation/isNoBPJS.ts
3617
+ function isNoBPJS(value) {
3618
+ const digits = value.replace(/\D/g, "");
3619
+ return digits.length === 13;
3620
+ }
3621
+
3622
+ // src/validation/isNoKK.ts
3623
+ function isNoKK(value) {
3624
+ const digits = value.replace(/\D/g, "");
3625
+ return digits.length === 16;
3626
+ }
3627
+
3628
+ // src/error/createError.ts
3629
+ var defaultStatus = {
3630
+ "BAD_REQUEST": 400,
3631
+ "UNAUTHORIZED": 401,
3632
+ "FORBIDDEN": 403,
3633
+ "NOT_FOUND": 404,
3634
+ "CONFLICT": 409,
3635
+ "VALIDATION_ERROR": 422,
3636
+ "TOO_MANY": 429,
3637
+ "INTERNAL": 500,
3638
+ "BAD_GATEWAY": 502,
3639
+ "UNAVAILABLE": 503
3640
+ };
3641
+ var TypedError = class extends Error {
3642
+ code;
3643
+ status;
3644
+ details;
3645
+ constructor(code, message, options) {
3646
+ super(message, { cause: options?.cause });
3647
+ this.name = "TypedError";
3648
+ this.code = code;
3649
+ this.status = options?.status ?? defaultStatus[code] ?? 500;
3650
+ this.details = options?.details;
3651
+ Object.setPrototypeOf(this, new.target.prototype);
3652
+ }
3653
+ /**
3654
+ * Serialize the error to a plain JSON-safe object.
3655
+ */
3656
+ toJSON() {
3657
+ return {
3658
+ name: this.name,
3659
+ message: this.message,
3660
+ code: this.code,
3661
+ status: this.status,
3662
+ details: this.details,
3663
+ cause: this.cause,
3664
+ ...this.stack ? { stack: this.stack } : {}
3665
+ };
3666
+ }
3667
+ toString() {
3668
+ return `${this.name} [${this.code}]: ${this.message}`;
3669
+ }
3670
+ };
3671
+ function createError(code, message, options) {
3672
+ return new TypedError(code, message, options);
3673
+ }
3674
+ function isTypedError(error) {
3675
+ return error instanceof TypedError;
3676
+ }
3677
+
3678
+ // src/error/MultiError.ts
3679
+ var MultiError = class extends Error {
3680
+ errors;
3681
+ constructor(errors, message) {
3682
+ const joined = errors.map((e) => e.message).join("; ");
3683
+ super(message ?? joined);
3684
+ this.name = "MultiError";
3685
+ this.errors = [...errors];
3686
+ Object.setPrototypeOf(this, new.target.prototype);
3687
+ }
3688
+ /** Number of collected errors. */
3689
+ get length() {
3690
+ return this.errors.length;
3691
+ }
3692
+ /**
3693
+ * Check if any collected error satisfies `predicate`.
3694
+ *
3695
+ * @example
3696
+ * ```ts
3697
+ * if (err.some(e => e.message.includes('timeout'))) { … }
3698
+ * ```
3699
+ */
3700
+ some(predicate) {
3701
+ return this.errors.some(predicate);
3702
+ }
3703
+ /** Array of all error messages. */
3704
+ get messages() {
3705
+ return this.errors.map((e) => e.message);
3706
+ }
3707
+ /**
3708
+ * Serialize to a plain JSON-safe object.
3709
+ */
3710
+ toJSON() {
3711
+ return {
3712
+ name: this.name,
3713
+ message: this.message,
3714
+ errors: this.errors.map((e) => ({
3715
+ name: e.name,
3716
+ message: e.message,
3717
+ ...e.stack ? { stack: e.stack } : {}
3718
+ })),
3719
+ ...this.stack ? { stack: this.stack } : {}
3720
+ };
3721
+ }
3722
+ toString() {
3723
+ return `${this.name}: ${this.message}`;
3724
+ }
3725
+ };
3726
+ function collectErrors(fn) {
3727
+ try {
3728
+ return { result: fn(), errors: [] };
3729
+ } catch (err) {
3730
+ return {
3731
+ errors: [err instanceof Error ? err : new Error(String(err))]
3732
+ };
3733
+ }
3734
+ }
3735
+
3736
+ // src/logger/logger.ts
3737
+ var LEVEL_ORDER = { debug: 0, info: 1, warn: 2, error: 3 };
3738
+ var Logger = class _Logger {
3739
+ _level;
3740
+ _name;
3741
+ _transport;
3742
+ _extraMeta;
3743
+ constructor(options) {
3744
+ this._level = options?.level ?? "info";
3745
+ this._name = options?.name;
3746
+ this._transport = options?.transport ?? consoleTransport;
3747
+ this._extraMeta = /* @__PURE__ */ Object.create(null);
3748
+ }
3749
+ _shouldLog(target) {
3750
+ return LEVEL_ORDER[this._level] <= LEVEL_ORDER[target];
3751
+ }
3752
+ _log(level, message, meta) {
3753
+ if (level !== "error" && !this._shouldLog(level)) return;
3754
+ const merged = /* @__PURE__ */ Object.create(null);
3755
+ for (const key of Object.keys(this._extraMeta)) {
3756
+ merged[key] = this._extraMeta[key];
3757
+ }
3758
+ if (meta !== void 0) {
3759
+ for (const key of Object.keys(meta)) {
3760
+ merged[key] = meta[key];
3761
+ }
3762
+ }
3763
+ const label = this._name !== void 0 ? `[${this._name}] ${message}` : message;
3764
+ const finalMeta = Object.keys(merged).length > 0 ? merged : void 0;
3765
+ this._transport.log(level, label, finalMeta);
3766
+ }
3767
+ /** Log at `debug` level. Only emitted when the current level is `'debug'`. */
3768
+ debug = (message, meta) => this._log("debug", message, meta);
3769
+ /** Log at `info` level. Emitted when level is `'debug'` or `'info'`. */
3770
+ info = (message, meta) => this._log("info", message, meta);
3771
+ /** Log at `warn` level. Emitted when level is `'debug'`, `'info'`, or `'warn'`. */
3772
+ warn = (message, meta) => this._log("warn", message, meta);
3773
+ /** Log at `error` level. Always emitted regardless of current level. */
3774
+ error = (message, meta) => this._log("error", message, meta);
3775
+ /**
3776
+ * Creates a child logger that inherits the parent's level, name, and transport,
3777
+ * but merges `extraMeta` into every log call. Child metadata is shallow-merged
3778
+ * on top of the parent's inherited metadata.
3779
+ *
3780
+ * @param extraMeta - Additional context to include in every log entry.
3781
+ */
3782
+ child(extraMeta) {
3783
+ const child = new _Logger({
3784
+ level: this._level,
3785
+ name: this._name,
3786
+ transport: this._transport
3787
+ });
3788
+ const inherited = /* @__PURE__ */ Object.create(null);
3789
+ for (const key of Object.keys(this._extraMeta)) {
3790
+ inherited[key] = this._extraMeta[key];
3791
+ }
3792
+ for (const key of Object.keys(extraMeta)) {
3793
+ inherited[key] = extraMeta[key];
3794
+ }
3795
+ child._extraMeta = inherited;
3796
+ return child;
3797
+ }
3798
+ /** Updates the minimum log level for this instance. */
3799
+ setLevel(level) {
3800
+ this._level = level;
3801
+ }
3802
+ /** Returns the current minimum log level. */
3803
+ getLevel() {
3804
+ return this._level;
3805
+ }
3806
+ /**
3807
+ * Creates a new named Logger.
3808
+ * Convenience shorthand for `new Logger({ ...options, name })`.
3809
+ *
3810
+ * @param name - The name tag shown in log output.
3811
+ * @param options - Additional configuration.
3812
+ */
3813
+ static create(name, options) {
3814
+ return new _Logger({ ...options, name });
3815
+ }
3816
+ };
3817
+ var consoleTransport = {
3818
+ log(level, message, meta) {
3819
+ const metaStr = meta !== void 0 && Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : "";
3820
+ console.log(`[${level.toUpperCase()}] ${message}${metaStr}`);
3821
+ }
3822
+ };
3823
+ var logger = new Logger();
3824
+
3825
+ // src/logger/transports.ts
3826
+ var LEVEL_COLORS = {
3827
+ debug: "\x1B[90m",
3828
+ info: "\x1B[34m",
3829
+ warn: "\x1B[33m",
3830
+ error: "\x1B[31m"
3831
+ };
3832
+ var RESET = "\x1B[0m";
3833
+ function createConsoleTransport(options) {
3834
+ const useColors = options?.colors !== false;
3835
+ const showTimestamp = options?.timestamp ?? false;
3836
+ return {
3837
+ log(level, message, meta) {
3838
+ const parts = [];
3839
+ if (showTimestamp) {
3840
+ parts.push((/* @__PURE__ */ new Date()).toISOString());
3841
+ }
3842
+ if (useColors) {
3843
+ const color = LEVEL_COLORS[level];
3844
+ parts.push(`${color}[${level.toUpperCase()}]${RESET}`);
3845
+ } else {
3846
+ parts.push(`[${level.toUpperCase()}]`);
3847
+ }
3848
+ parts.push(message);
3849
+ if (meta !== void 0 && Object.keys(meta).length > 0) {
3850
+ parts.push(JSON.stringify(meta));
3851
+ }
3852
+ console.log(parts.join(" "));
3853
+ }
3854
+ };
3855
+ }
3856
+ function createJsonTransport(options) {
3857
+ const writeStream = options?.stream ?? (typeof process !== "undefined" && typeof process.stdout !== "undefined" && typeof process.stdout.write === "function" ? process.stdout : void 0);
3858
+ return {
3859
+ log(level, message, meta) {
3860
+ const entry = {
3861
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3862
+ level,
3863
+ message
3864
+ };
3865
+ if (meta !== void 0 && Object.keys(meta).length > 0) {
3866
+ entry.meta = meta;
3867
+ }
3868
+ const line = JSON.stringify(entry);
3869
+ if (writeStream !== void 0) {
3870
+ writeStream.write(line + "\n");
3871
+ } else {
3872
+ console.log(line);
3873
+ }
3874
+ }
3875
+ };
3876
+ }
3877
+ function createFileTransport(filename, _options) {
3878
+ let fs = null;
3879
+ try {
3880
+ if (typeof process !== "undefined" && process.versions?.node) {
3881
+ const m = __require("fs");
3882
+ fs = m;
3883
+ }
3884
+ } catch {
3885
+ }
3886
+ return {
3887
+ log(level, message, meta) {
3888
+ if (fs === null) return;
3889
+ const metaStr = meta !== void 0 && Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : "";
3890
+ const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [${level.toUpperCase()}] ${message}${metaStr}
3891
+ `;
3892
+ try {
3893
+ fs.appendFileSync(filename, line);
3894
+ } catch {
3895
+ }
3896
+ }
3897
+ };
3898
+ }
3899
+ function createBufferedTransport(transport, options) {
3900
+ const maxSize = options?.maxSize ?? 100;
3901
+ const flushIntervalMs = options?.flushIntervalMs ?? 5e3;
3902
+ const buffer = [];
3903
+ let timer;
3904
+ function flush() {
3905
+ if (timer !== void 0) {
3906
+ clearTimeout(timer);
3907
+ timer = void 0;
3908
+ }
3909
+ for (let i = 0; i < buffer.length; i++) {
3910
+ const entry = buffer[i];
3911
+ transport.log(entry.level, entry.message, entry.meta);
3912
+ }
3913
+ buffer.length = 0;
3914
+ }
3915
+ function scheduleFlush() {
3916
+ if (timer !== void 0 || flushIntervalMs <= 0) return;
3917
+ timer = setTimeout(() => {
3918
+ timer = void 0;
3919
+ flush();
3920
+ }, flushIntervalMs);
3921
+ }
3922
+ return {
3923
+ log(level, message, meta) {
3924
+ buffer.push({ level, message, meta });
3925
+ if (buffer.length >= maxSize) {
3926
+ flush();
3927
+ } else {
3928
+ scheduleFlush();
3929
+ }
3930
+ }
3931
+ };
3932
+ }
3933
+
3934
+ // src/color/index.ts
3935
+ function hexToRgb(hex) {
3936
+ let h = hex.replace("#", "");
3937
+ if (h.length === 3) h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2];
3938
+ if (h.length !== 6) return null;
3939
+ const num = Number.parseInt(h, 16);
3940
+ if (isNaN(num)) return null;
3941
+ return {
3942
+ r: num >> 16 & 255,
3943
+ g: num >> 8 & 255,
3944
+ b: num & 255
3945
+ };
3946
+ }
3947
+ function rgbToHex(r, g, b) {
3948
+ const toHex = (n) => Math.max(0, Math.min(255, Math.round(n))).toString(16).padStart(2, "0");
3949
+ return "#" + toHex(r) + toHex(g) + toHex(b);
3950
+ }
3951
+ function lighten(hex, percent) {
3952
+ const rgb = hexToRgb(hex);
3953
+ if (!rgb) return hex;
3954
+ const factor = percent / 100;
3955
+ return rgbToHex(
3956
+ rgb.r + (255 - rgb.r) * factor,
3957
+ rgb.g + (255 - rgb.g) * factor,
3958
+ rgb.b + (255 - rgb.b) * factor
3959
+ );
3960
+ }
3961
+ function darken(hex, percent) {
3962
+ const rgb = hexToRgb(hex);
3963
+ if (!rgb) return hex;
3964
+ const factor = percent / 100;
3965
+ return rgbToHex(
3966
+ rgb.r * (1 - factor),
3967
+ rgb.g * (1 - factor),
3968
+ rgb.b * (1 - factor)
3969
+ );
3970
+ }
3971
+ function contrastRatio(hex1, hex2) {
3972
+ const lum1 = relativeLuminance(hex1);
3973
+ const lum2 = relativeLuminance(hex2);
3974
+ const lighter = Math.max(lum1, lum2);
3975
+ const darker = Math.min(lum1, lum2);
3976
+ return Number(((lighter + 0.05) / (darker + 0.05)).toFixed(2));
3977
+ }
3978
+ function relativeLuminance(hex) {
3979
+ const rgb = hexToRgb(hex);
3980
+ if (!rgb) return 0;
3981
+ const vals = [rgb.r / 255, rgb.g / 255, rgb.b / 255].map((c) => {
3982
+ return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
3983
+ });
3984
+ return 0.2126 * vals[0] + 0.7152 * vals[1] + 0.0722 * vals[2];
3985
+ }
3986
+ function meetsWCAG(hex1, hex2, level) {
3987
+ const ratio = contrastRatio(hex1, hex2);
3988
+ const threshold = level === "AAA" ? 7 : 4.5;
3989
+ return ratio >= threshold;
3990
+ }
3991
+ function isValidHex(value) {
3992
+ return /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value);
3993
+ }
3994
+ function hexToHsl(hex) {
3995
+ const rgb = hexToRgb(hex);
3996
+ if (!rgb) return null;
3997
+ const r = rgb.r / 255;
3998
+ const g = rgb.g / 255;
3999
+ const b = rgb.b / 255;
4000
+ const max = Math.max(r, g, b);
4001
+ const min = Math.min(r, g, b);
4002
+ const l = (max + min) / 2;
4003
+ if (max === min) return { h: 0, s: 0, l: Math.round(l * 100) };
4004
+ const d = max - min;
4005
+ const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
4006
+ let h = 0;
4007
+ switch (max) {
4008
+ case r:
4009
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
4010
+ break;
4011
+ case g:
4012
+ h = ((b - r) / d + 2) / 6;
4013
+ break;
4014
+ case b:
4015
+ h = ((r - g) / d + 4) / 6;
4016
+ break;
4017
+ }
4018
+ return {
4019
+ h: Math.round(h * 360),
4020
+ s: Math.round(s * 100),
4021
+ l: Math.round(l * 100)
4022
+ };
4023
+ }
4024
+ function hslToHex(h, s, l) {
4025
+ const hue = h / 360;
4026
+ const sat = s / 100;
4027
+ const lig = l / 100;
4028
+ if (sat === 0) {
4029
+ const val = Math.round(lig * 255);
4030
+ return rgbToHex(val, val, val);
4031
+ }
4032
+ const hue2rgb = (p2, q2, t) => {
4033
+ let tt = t;
4034
+ if (tt < 0) tt += 1;
4035
+ if (tt > 1) tt -= 1;
4036
+ if (tt < 1 / 6) return p2 + (q2 - p2) * 6 * tt;
4037
+ if (tt < 1 / 2) return q2;
4038
+ if (tt < 2 / 3) return p2 + (q2 - p2) * (2 / 3 - tt) * 6;
4039
+ return p2;
4040
+ };
4041
+ const q = lig < 0.5 ? lig * (1 + sat) : lig + sat - lig * sat;
4042
+ const p = 2 * lig - q;
4043
+ return rgbToHex(
4044
+ Math.round(hue2rgb(p, q, hue + 1 / 3) * 255),
4045
+ Math.round(hue2rgb(p, q, hue) * 255),
4046
+ Math.round(hue2rgb(p, q, hue - 1 / 3) * 255)
4047
+ );
4048
+ }
4049
+ function mix(color1, color2, weight = 0.5) {
4050
+ const rgb1 = hexToRgb(color1);
4051
+ const rgb2 = hexToRgb(color2);
4052
+ if (!rgb1 || !rgb2) return color1;
4053
+ const w = Math.max(0, Math.min(1, weight));
4054
+ const lerp2 = (a, b) => Math.floor(a + (b - a) * w);
4055
+ return rgbToHex(lerp2(rgb1.r, rgb2.r), lerp2(rgb1.g, rgb2.g), lerp2(rgb1.b, rgb2.b));
4056
+ }
4057
+ function randomColor() {
4058
+ const r = Math.floor(Math.random() * 256);
4059
+ const g = Math.floor(Math.random() * 256);
4060
+ const b = Math.floor(Math.random() * 256);
4061
+ return rgbToHex(r, g, b);
4062
+ }
4063
+ function isLight(hex) {
4064
+ const rgb = hexToRgb(hex);
4065
+ if (!rgb) return false;
4066
+ return (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255 > 0.5;
4067
+ }
4068
+ function isDark(hex) {
4069
+ return !isLight(hex);
4070
+ }
4071
+ function complementary(hex) {
4072
+ const hsl = hexToHsl(hex);
4073
+ if (!hsl) return hex;
4074
+ return hslToHex((hsl.h + 180) % 360, hsl.s, hsl.l);
4075
+ }
4076
+ function alpha(hex, opacity) {
4077
+ const rgb = hexToRgb(hex);
4078
+ if (!rgb) return hex;
4079
+ const a = Math.max(0, Math.min(1, opacity));
4080
+ const alphaHex = Math.round(a * 255).toString(16).padStart(2, "0");
4081
+ return rgbToHex(rgb.r, rgb.g, rgb.b) + alphaHex;
4082
+ }
4083
+ export {
4084
+ DivisionByZeroError,
4085
+ InvalidDateError,
4086
+ KNOWN_CVES,
4087
+ KNOWN_MAPPINGS,
4088
+ Logger,
4089
+ MultiError,
4090
+ Mutex,
4091
+ Queue,
4092
+ RateLimiter,
4093
+ Semaphore,
4094
+ TIMEZONE_WIB,
4095
+ TIMEZONE_WIT,
4096
+ TIMEZONE_WITA,
4097
+ TypedError,
4098
+ add,
4099
+ addBusinessDays,
4100
+ addDays,
4101
+ addMonths,
4102
+ addYears,
4103
+ allSettledMap,
4104
+ alpha,
4105
+ analyzeUsage,
4106
+ approxEqual,
4107
+ assertDefined,
4108
+ assertType,
4109
+ average,
4110
+ base64Decode,
4111
+ base64Encode,
4112
+ basename,
4113
+ batch,
4114
+ calculateAge,
4115
+ camelCase,
4116
+ capitalize,
4117
+ castArray,
4118
+ ceil,
4119
+ charCount,
4120
+ checksum,
4121
+ chunk,
4122
+ clamp,
4123
+ collectErrors,
4124
+ combinations,
4125
+ compact,
4126
+ complementary,
4127
+ compose,
4128
+ consoleTransport,
4129
+ constantTimeEqual,
4130
+ contrastRatio,
4131
+ correlation,
4132
+ countBy,
4133
+ countOccurrences,
4134
+ createBufferedTransport,
4135
+ createConsoleTransport,
4136
+ createError,
4137
+ createFileTransport,
4138
+ createJsonTransport,
4139
+ darken,
4140
+ dateDiff,
4141
+ dayOfYear,
4142
+ daysInMonth,
4143
+ debounce,
4144
+ dedent,
4145
+ deepClone,
4146
+ deepEqual,
4147
+ deepGet,
4148
+ deepMerge,
4149
+ deepSet,
4150
+ deferred,
4151
+ difference,
4152
+ dirname,
4153
+ div,
4154
+ drop,
4155
+ dropRight,
4156
+ endOfDay,
4157
+ endOfMonth,
4158
+ endOfYear,
4159
+ ensureArray,
4160
+ env,
4161
+ envBool,
4162
+ envInt,
4163
+ escapeHtml,
4164
+ extname,
4165
+ factorial,
4166
+ findIndex,
4167
+ findLast,
4168
+ first,
4169
+ flatten,
4170
+ floor,
4171
+ format,
4172
+ formatBytes,
4173
+ formatCurrency,
4174
+ formatDate,
4175
+ formatDuration,
4176
+ formatInTimezone,
4177
+ formatRupiah,
4178
+ fuzzyMatch,
4179
+ gcd,
4180
+ generateOTP,
4181
+ generateReport,
4182
+ generateToken,
4183
+ geometricMean,
4184
+ getIndonesianHolidayNames,
4185
+ getType2 as getType,
4186
+ groupBy,
4187
+ hash,
4188
+ hexToHsl,
4189
+ hexToRgb,
4190
+ hslToHex,
4191
+ identity,
4192
+ inRange,
4193
+ intersection,
4194
+ isAbsolute,
4195
+ isAfter,
4196
+ isAnagram,
4197
+ isArray,
4198
+ isBefore,
4199
+ isBetween,
4200
+ isBoolean,
4201
+ isBusinessDay,
4202
+ isDark,
4203
+ isDate,
4204
+ isEmail,
4205
+ isEmpty,
4206
+ isEven,
4207
+ isFunction,
4208
+ isFuture,
4209
+ isHolidayIndonesia,
4210
+ isKodepos,
4211
+ isLeapYear,
4212
+ isLight,
4213
+ isMap,
4214
+ isNIK,
4215
+ isNPWP,
4216
+ isNil,
4217
+ isNoBPJS,
4218
+ isNoKK,
4219
+ isNoRekening,
4220
+ isNoSIM,
4221
+ isNull,
4222
+ isNumber,
4223
+ isObject,
4224
+ isOdd,
4225
+ isPalindrome,
4226
+ isPassport,
4227
+ isPast,
4228
+ isPhone,
4229
+ isPlatNomor,
4230
+ isPrime,
4231
+ isPromise,
4232
+ isRegExp,
4233
+ isSameDay,
4234
+ isSet,
4235
+ isString,
4236
+ isToday,
4237
+ isTomorrow,
4238
+ isTypedError,
4239
+ isURL,
4240
+ isUndefined,
4241
+ isValidHex,
4242
+ isWeekend,
4243
+ isYesterday,
4244
+ join,
4245
+ kebabCase,
4246
+ keyBy,
4247
+ last,
4248
+ lastFriday,
4249
+ lastMonday,
4250
+ lastSaturday,
4251
+ lastSunday,
4252
+ lastThursday,
4253
+ lastTuesday,
4254
+ lastWednesday,
4255
+ lcm,
4256
+ lerp,
4257
+ levenshtein,
4258
+ lighten,
4259
+ logger,
4260
+ mapRange,
4261
+ maskString,
4262
+ maxBy,
4263
+ maxDate,
4264
+ median,
4265
+ meetsWCAG,
4266
+ memoize,
4267
+ memoizeAsync,
4268
+ minBy,
4269
+ minDate,
4270
+ mix,
4271
+ mode,
4272
+ mul,
4273
+ nanoid,
4274
+ nextFriday,
4275
+ nextMonday,
4276
+ nextSaturday,
4277
+ nextSunday,
4278
+ nextThursday,
4279
+ nextTuesday,
4280
+ nextWednesday,
4281
+ noop,
4282
+ normalize,
4283
+ nth,
4284
+ omit,
4285
+ once,
4286
+ orderBy,
4287
+ pad,
4288
+ padEnd,
4289
+ padStart,
4290
+ parallelMap,
4291
+ parse,
4292
+ parseCsv,
4293
+ parseDate,
4294
+ parseDuration,
4295
+ parseNIK,
4296
+ partition,
4297
+ pascalCase,
4298
+ percentageOf,
4299
+ percentile,
4300
+ permutations,
4301
+ pick,
4302
+ pipe,
4303
+ pipeline,
4304
+ pluck,
4305
+ pluralize,
4306
+ quarter,
4307
+ raceWithTimeout,
4308
+ randomBoolean,
4309
+ randomColor,
4310
+ randomHex,
4311
+ randomInt,
4312
+ randomString,
4313
+ range,
4314
+ relative,
4315
+ resolve,
4316
+ retry,
4317
+ retryAsync,
4318
+ reverse,
4319
+ rgbToHex,
4320
+ round,
4321
+ safeJsonParse,
4322
+ sample,
4323
+ sampleSize,
4324
+ sampleStddev,
4325
+ scanProject,
4326
+ shuffle,
4327
+ similarity,
4328
+ simpleHash,
4329
+ sleep,
4330
+ slidingWindows,
4331
+ slugify,
4332
+ snakeCase,
4333
+ sortBy,
4334
+ startOfDay,
4335
+ startOfMonth,
4336
+ startOfYear,
4337
+ stddev,
4338
+ stringifyCsv,
4339
+ stripHtml,
4340
+ sub,
4341
+ sum,
4342
+ sumBy,
4343
+ swapCase,
4344
+ take,
4345
+ takeRight,
4346
+ template,
4347
+ terbilang,
4348
+ throttle,
4349
+ timeAgo,
4350
+ timeRemaining,
4351
+ timeout,
4352
+ toCobolCase,
4353
+ toDegrees,
4354
+ toRadians,
4355
+ toTimezone,
4356
+ topoSort,
4357
+ trim,
4358
+ trimEnd,
4359
+ trimStart,
4360
+ truncate,
4361
+ truncateWords,
4362
+ tumblingWindows,
4363
+ unescapeHtml,
4364
+ union,
4365
+ uniq,
4366
+ uniqueBy,
4367
+ unzip,
4368
+ uuid,
4369
+ waterfall,
4370
+ weekOfYear,
4371
+ weightedAverage,
4372
+ without,
4373
+ wordCount,
4374
+ words,
4375
+ xorCipher,
4376
+ zip
4377
+ };
4378
+ //# sourceMappingURL=index.js.map