@andrew_l/toolkit 0.2.8 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -37,6 +37,7 @@ const isError = (val) => val instanceof Error || //@ts-expect-error
37
37
  isObject(val) && isString(val.message) && isString(val.stack);
38
38
  const isSymbol = (val) => typeof val == "symbol";
39
39
  const isSet = (val) => val instanceof Set;
40
+ const isRegExp = (val) => val instanceof RegExp;
40
41
  const isWeakSet = (val) => val instanceof WeakSet;
41
42
  const isMap = (val) => val instanceof Map;
42
43
  const isWeakMap = (val) => val instanceof WeakMap;
@@ -160,7 +161,7 @@ const isEmpty = (obj) => {
160
161
  return false;
161
162
  };
162
163
  function isPromise(value) {
163
- return value && typeof value === "object" && "then" in value && "catch" in value && typeof value.then === "function" && typeof value.catch === "function";
164
+ return value instanceof Promise || !!value && typeof value === "object" && "then" in value && "catch" in value && typeof value.then === "function" && typeof value.catch === "function";
164
165
  }
165
166
  const primitiveTypeofSet = Object.freeze(
166
167
  /* @__PURE__ */ new Set(["string", "number", "boolean", "bigint", "symbol", "undefined"])
@@ -393,9 +394,9 @@ function equal(actual, expected, message) {
393
394
  });
394
395
  }
395
396
  }
396
- function empty$1(value, message) {
397
- if (isEmpty(value)) {
398
- throw toError$1(empty$1, value, message, "Expected not empty value.");
397
+ function notEmpty(value, message) {
398
+ if (!isEmpty(value)) {
399
+ throw toError$1(notEmpty, value, message, "Expected not empty value.");
399
400
  }
400
401
  }
401
402
  function object(value, message) {
@@ -434,7 +435,7 @@ function date(value, message) {
434
435
  }
435
436
  }
436
437
  function fn(value, message) {
437
- if (!isNumber(value)) {
438
+ if (!isFunction(value)) {
438
439
  throw toError$1(fn, value, message, "Expected function value.");
439
440
  }
440
441
  }
@@ -492,11 +493,11 @@ const assert = {
492
493
  arrayStrings: arrayStrings,
493
494
  boolean: boolean,
494
495
  date: date,
495
- empty: empty$1,
496
496
  equal: equal,
497
497
  fn: fn,
498
498
  greaterThan: greaterThan,
499
499
  lessThan: lessThan,
500
+ notEmpty: notEmpty,
500
501
  notEmptyString: notEmptyString,
501
502
  number: number$1,
502
503
  object: object,
@@ -3253,28 +3254,84 @@ function parseDecimal(value, dights) {
3253
3254
  }
3254
3255
 
3255
3256
  const CODE_TO_MESSAGE = Object.freeze({
3257
+ 100: "Continue",
3256
3258
  101: "Switching Protocols",
3257
3259
  102: "Processing",
3258
- 200: "Ok",
3260
+ 103: "Early Hints",
3261
+ 200: "OK",
3259
3262
  201: "Created",
3263
+ 202: "Accepted",
3264
+ 203: "Non-Authoritative Information",
3260
3265
  204: "No Content",
3266
+ 205: "Reset Content",
3267
+ 206: "Partial Content",
3268
+ 300: "Multiple Choices",
3261
3269
  301: "Moved Permanently",
3270
+ 302: "Found",
3271
+ 303: "See Other",
3272
+ 304: "Not Modified",
3273
+ 305: "Use Proxy",
3274
+ 307: "Temporary Redirect",
3275
+ 308: "Permanent Redirect",
3262
3276
  400: "Bad Request",
3263
3277
  401: "Unauthorized",
3278
+ 402: "Payment Required",
3264
3279
  403: "Forbidden",
3265
3280
  404: "Not Found",
3266
- 409: "Already Exists",
3267
- 500: "Internal Server Error"
3281
+ 405: "Method Not Allowed",
3282
+ 406: "Not Acceptable",
3283
+ 407: "Proxy Authentication Required",
3284
+ 408: "Request Timeout",
3285
+ 409: "Conflict",
3286
+ 410: "Gone",
3287
+ 411: "Length Required",
3288
+ 412: "Precondition Failed",
3289
+ 413: "Payload Too Large",
3290
+ 414: "URI Too Long",
3291
+ 415: "Unsupported Media Type",
3292
+ 416: "Range Not Satisfiable",
3293
+ 417: "Expectation Failed",
3294
+ 418: "I'm a teapot",
3295
+ 422: "Unprocessable Entity",
3296
+ 425: "Too Early",
3297
+ 426: "Upgrade Required",
3298
+ 428: "Precondition Required",
3299
+ 429: "Too Many Requests",
3300
+ 431: "Request Header Fields Too Large",
3301
+ 500: "Internal Server Error",
3302
+ 501: "Not Implemented",
3303
+ 502: "Bad Gateway",
3304
+ 503: "Service Unavailable",
3305
+ 504: "Gateway Timeout",
3306
+ 505: "HTTP Version Not Supported",
3307
+ 506: "Variant Also Negotiates",
3308
+ 507: "Insufficient Storage",
3309
+ 508: "Loop Detected",
3310
+ 510: "Not Extended",
3311
+ 511: "Network Authentication Required"
3268
3312
  });
3269
3313
  class AppError extends Error {
3314
+ /**
3315
+ * HTTP valid status code
3316
+ */
3317
+ statusCode;
3318
+ /**
3319
+ * Custom error code
3320
+ */
3270
3321
  code;
3271
- constructor(messageOrCode, code = 500, options) {
3322
+ constructor(...args) {
3272
3323
  let message = "Unknown error";
3273
- if (isNumber(messageOrCode)) {
3274
- code = messageOrCode;
3275
- message = CODE_TO_MESSAGE[code] || "Unknown error";
3324
+ let statusCode = 500;
3325
+ let code = "ERR_UNKNOWN";
3326
+ let options;
3327
+ if (isNumber(args[0])) {
3328
+ statusCode = args[0];
3329
+ message = CODE_TO_MESSAGE[statusCode] || message;
3330
+ options = args[1];
3276
3331
  } else {
3277
- message = messageOrCode || CODE_TO_MESSAGE[code] || "Unknown error";
3332
+ message = args[0] || CODE_TO_MESSAGE[statusCode] || message;
3333
+ statusCode = isNumber(args[1]) ? args[1] : statusCode;
3334
+ options = args[2];
3278
3335
  }
3279
3336
  super(message, options);
3280
3337
  if (typeof Error.captureStackTrace !== "function") {
@@ -3282,13 +3339,8 @@ class AppError extends Error {
3282
3339
  } else {
3283
3340
  Error.captureStackTrace(this, AppError);
3284
3341
  }
3285
- this.code = code;
3286
- }
3287
- /**
3288
- * alias for `code` property
3289
- */
3290
- get statusCode() {
3291
- return this.code;
3342
+ this.statusCode = statusCode;
3343
+ this.code = options?.code ?? code;
3292
3344
  }
3293
3345
  get name() {
3294
3346
  return "AppError";
@@ -3334,13 +3386,6 @@ const BrowserAssertionError$1 = {
3334
3386
  BrowserAssertionError: BrowserAssertionError
3335
3387
  };
3336
3388
 
3337
- function isSuccess(value) {
3338
- return value.success === true;
3339
- }
3340
- function isSkip(value) {
3341
- return value.skip === true;
3342
- }
3343
-
3344
3389
  function getFileExtension(name, withDot = true) {
3345
3390
  if (!isString(name)) {
3346
3391
  return null;
@@ -3396,432 +3441,327 @@ function humanFileSize(bytes, digits = 1, withSpace = true) {
3396
3441
  return bytes.toFixed(digits) + (withSpace ? " " : "") + units[u];
3397
3442
  }
3398
3443
 
3399
- function sprintf(line, args, unusedArgs = []) {
3400
- let result = "";
3401
- const argsLen = args.length;
3402
- const lineLen = line.length;
3403
- let opened = false;
3404
- let currentChar = -1;
3405
- let lastPos = 0;
3406
- let argsIndex = 0;
3407
- for (let idx = 0; idx < lineLen; idx++) {
3408
- currentChar = line.charCodeAt(idx);
3409
- if (currentChar === 37) {
3410
- opened = true;
3411
- continue;
3412
- }
3413
- if (!opened) continue;
3414
- opened = false;
3415
- switch (currentChar) {
3416
- // 'd'
3417
- case 100:
3418
- // 'f'
3419
- case 102: {
3420
- result += line.slice(lastPos, idx - 1);
3421
- result += Number(args[argsIndex]);
3422
- lastPos = idx + 1;
3423
- argsIndex++;
3424
- break;
3425
- }
3426
- // 'i'
3427
- case 105: {
3428
- result += line.slice(lastPos, idx - 1);
3429
- result += Math.floor(Number(args[argsIndex]));
3430
- lastPos = idx + 1;
3431
- argsIndex++;
3432
- break;
3433
- }
3434
- // 'O'
3435
- case 79:
3436
- // 'o'
3437
- case 111:
3438
- // 'j'
3439
- case 106: {
3440
- result += line.slice(lastPos, idx - 1);
3441
- result += tryStringify(args[argsIndex]);
3442
- lastPos = idx + 1;
3443
- argsIndex++;
3444
- break;
3445
- }
3446
- // 's'
3447
- case 115: {
3448
- result += line.slice(lastPos, idx - 1);
3449
- result += String(args[argsIndex]);
3450
- lastPos = idx + 1;
3451
- argsIndex++;
3452
- break;
3453
- }
3454
- }
3455
- if (argsIndex >= argsLen) break;
3456
- }
3457
- if (lastPos < lineLen) {
3458
- result += line.slice(lastPos, lineLen);
3459
- }
3460
- if (argsIndex < argsLen) {
3461
- unusedArgs.push(...args.slice(argsIndex, argsLen));
3462
- }
3463
- return result;
3464
- }
3465
- function tryStringify(o) {
3466
- switch (typeof o) {
3467
- case "function": {
3468
- return o.name || "<anonymous>";
3469
- }
3470
- case "string": {
3471
- return "'" + o + "'";
3444
+ function debounce(func, debounceMs, { signal, edges } = {}) {
3445
+ let pendingThis = void 0;
3446
+ let pendingArgs = null;
3447
+ const leading = edges != null && edges.includes("leading");
3448
+ const trailing = edges == null || edges.includes("trailing");
3449
+ const invoke = () => {
3450
+ if (pendingArgs !== null) {
3451
+ func.apply(pendingThis, pendingArgs);
3452
+ pendingThis = void 0;
3453
+ pendingArgs = null;
3472
3454
  }
3473
- default: {
3474
- try {
3475
- return JSON.stringify(o);
3476
- } catch (e) {
3477
- return '"[Circular]"';
3478
- }
3479
- }
3480
- }
3481
- }
3482
-
3483
- const LEVEL_NUM = {
3484
- debug: 0,
3485
- log: 1,
3486
- info: 2,
3487
- warn: 3,
3488
- error: 4
3489
- };
3490
- let currentLogLevel = LEVEL_NUM.log;
3491
- const loggerSetLevel = (level) => {
3492
- number$1(LEVEL_NUM[level], `Invalid log level: ${level}`);
3493
- currentLogLevel = LEVEL_NUM[level];
3494
- };
3495
- const logger = (...baseArgs) => {
3496
- if (isString(baseArgs[0]?.url)) {
3497
- baseArgs[0] = baseArgs[0]?.url;
3498
- }
3499
- if (typeof baseArgs[0] === "string" && baseArgs[0][0] !== "[") {
3500
- baseArgs[0] = `[${baseArgs[0].split("/").at(-1).split("?", 1)[0]}]`;
3501
- }
3502
- const writeLog = (level, ...[pattern, ...args]) => {
3503
- const levelNum = LEVEL_NUM[level];
3504
- if (levelNum < currentLogLevel) {
3505
- return;
3455
+ };
3456
+ const onTimerEnd = () => {
3457
+ if (trailing) {
3458
+ invoke();
3506
3459
  }
3507
- if (!isString(pattern)) {
3508
- console[level](...baseArgs, pattern, ...args);
3509
- return;
3460
+ cancel();
3461
+ };
3462
+ let timeoutId = null;
3463
+ const schedule = () => {
3464
+ if (timeoutId != null) {
3465
+ clearTimeout(timeoutId);
3466
+ }
3467
+ timeoutId = setTimeout(() => {
3468
+ timeoutId = null;
3469
+ onTimerEnd();
3470
+ }, debounceMs);
3471
+ };
3472
+ const cancelTimer = () => {
3473
+ if (timeoutId !== null) {
3474
+ clearTimeout(timeoutId);
3475
+ timeoutId = null;
3510
3476
  }
3511
- const unusedArgs = [];
3512
- const formatted = sprintf(pattern, args, unusedArgs);
3513
- console[level](...baseArgs, formatted, ...unusedArgs);
3514
3477
  };
3515
- const log = writeLog.bind(null, "log");
3516
- const info = writeLog.bind(null, "info");
3517
- const warn = writeLog.bind(null, "warn");
3518
- const error = writeLog.bind(null, "error");
3519
- const debug = writeLog.bind(null, "debug");
3520
- const extend = (...args) => {
3521
- return logger(...baseArgs, ...args);
3478
+ const cancel = () => {
3479
+ cancelTimer();
3480
+ pendingThis = void 0;
3481
+ pendingArgs = null;
3522
3482
  };
3523
- const instance = {
3524
- log,
3525
- info,
3526
- warn,
3527
- error,
3528
- debug,
3529
- extend
3483
+ const flush = () => {
3484
+ cancelTimer();
3485
+ invoke();
3530
3486
  };
3531
- return instance;
3532
- };
3533
-
3534
- async function asyncFilter(array, predicate) {
3535
- const result = [];
3536
- const cooldown = nextTickIteration(10);
3537
- for (let idx = 0; idx < array.length; idx++) {
3538
- await cooldown();
3539
- const value = array[idx];
3540
- const valid = await predicate(value, idx, array);
3541
- if (valid) {
3542
- result.push(value);
3487
+ const debounced = function(...args) {
3488
+ if (signal?.aborted) {
3489
+ return;
3543
3490
  }
3544
- }
3545
- return result;
3491
+ pendingThis = this;
3492
+ pendingArgs = args;
3493
+ const isFirstCall = timeoutId == null;
3494
+ schedule();
3495
+ if (leading && isFirstCall) {
3496
+ invoke();
3497
+ }
3498
+ };
3499
+ debounced.schedule = schedule;
3500
+ debounced.cancel = cancel;
3501
+ debounced.flush = flush;
3502
+ signal?.addEventListener("abort", cancel, { once: true });
3503
+ return debounced;
3546
3504
  }
3547
3505
 
3548
- const defaultWindow$1 = globalThis?.window;
3549
- const idle = (() => {
3550
- if (defaultWindow$1?.requestIdleCallback) {
3551
- return defaultWindow$1.requestIdleCallback;
3552
- } else if (defaultWindow$1?.requestAnimationFrame) {
3553
- return defaultWindow$1.requestAnimationFrame;
3554
- } else if (isFunction(process?.nextTick)) {
3555
- return process.nextTick;
3556
- } else {
3557
- return (fn) => setTimeout(fn, 0);
3558
- }
3559
- })();
3560
- function fastIdle(callback) {
3561
- return idle(callback);
3506
+ function isSuccess(value) {
3507
+ return value.success === true;
3562
3508
  }
3563
- function fastIdlePromise() {
3564
- return new Promise((resolve) => idle(resolve));
3509
+ function isSkip(value) {
3510
+ return value.skip === true;
3565
3511
  }
3566
3512
 
3567
- function nextTickIteration(amount, delay = "tick") {
3568
- let counter = 0;
3569
- const tickInterval = delay === "tick";
3570
- return () => {
3571
- counter++;
3572
- if (counter >= amount) {
3573
- counter = 0;
3574
- return new Promise((resolve) => {
3575
- if (tickInterval) {
3576
- fastIdle(resolve);
3577
- } else {
3578
- setTimeout(resolve, delay);
3579
- }
3580
- });
3513
+ function typeOf(value) {
3514
+ const type = typeof value;
3515
+ switch (type) {
3516
+ case "number":
3517
+ return isNumber(value) ? "number" : "unknown";
3518
+ case "object": {
3519
+ if (value === null) return "null";
3520
+ if (Array.isArray(value)) return "array";
3521
+ if (isSet(value)) return "set";
3522
+ if (isWeakSet(value)) return "weakset";
3523
+ if (isMap(value)) return "map";
3524
+ if (isWeakMap(value)) return "weakmap";
3525
+ if (isDate(value)) return "date";
3526
+ if (isObject(value)) return "object";
3527
+ return "unknown";
3581
3528
  }
3582
- return Promise.resolve();
3583
- };
3584
- }
3585
-
3586
- async function asyncFind(array, callbackfn) {
3587
- const cooldown = nextTickIteration(10);
3588
- let i = 0;
3589
- while (i < array.length) {
3590
- await cooldown();
3591
- const result = await callbackfn(array[i], i, array);
3592
- if (Boolean(result)) {
3593
- return array[i];
3529
+ default: {
3530
+ return type;
3594
3531
  }
3595
- i++;
3596
- }
3597
- return void 0;
3598
- }
3599
-
3600
- async function asyncForEach(array, callbackfn, { concurrency = 1 } = {}) {
3601
- const cooldown = nextTickIteration(10);
3602
- let i = 0;
3603
- const handle = (value, index) => {
3604
- return callbackfn(value, i + index, array);
3605
- };
3606
- while (i < array.length) {
3607
- await cooldown();
3608
- const batch = await Promise.all(
3609
- array.slice(i, i + concurrency).map(handle)
3610
- );
3611
- i += batch.length;
3612
3532
  }
3613
3533
  }
3614
3534
 
3615
- function defer() {
3616
- let resolve;
3617
- let reject;
3618
- const promise = new Promise((_resolve, _reject) => {
3619
- resolve = _resolve;
3620
- reject = _reject;
3621
- });
3622
- return {
3623
- resolve,
3624
- reject,
3625
- promise
3626
- };
3627
- }
3628
-
3629
- const onError = (error) => {
3630
- console.error(error);
3535
+ const qs = {
3536
+ toParams,
3537
+ stringify,
3538
+ stringifyValue,
3539
+ parse,
3540
+ parseValue,
3541
+ merge
3631
3542
  };
3632
- class SimpleEventEmitter {
3633
- #listeners = /* @__PURE__ */ new Map();
3634
- constructor() {
3635
- this.on("error", onError);
3636
- }
3637
- static once(emitter, eventName) {
3638
- const q = defer();
3639
- emitter.once(eventName, (...args) => q.resolve(args));
3640
- return q.promise;
3641
- }
3642
- emit(eventName, ...args) {
3643
- const set = this.#listeners.get(eventName);
3644
- if (!set) return false;
3645
- set.forEach((fn) => {
3646
- try {
3647
- const result = fn();
3648
- if (isPromise(result)) {
3649
- result.catch((err) => {
3650
- this.emit("error", err);
3651
- });
3543
+ function merge(...values) {
3544
+ const result = {};
3545
+ for (const filter of values) {
3546
+ for (const [key, value] of Object.entries(filter)) {
3547
+ const currentValue = result[key];
3548
+ const currentType = typeOf(currentValue);
3549
+ const filterType = typeOf(value);
3550
+ if (currentType !== filterType) {
3551
+ result[key] = value;
3552
+ continue;
3553
+ }
3554
+ switch (currentType) {
3555
+ case "array": {
3556
+ result[key] = Array.from(/* @__PURE__ */ new Set([...currentValue, ...value]));
3557
+ break;
3558
+ }
3559
+ case "object": {
3560
+ result[key] = {};
3561
+ deepAssign(result[key], currentValue);
3562
+ deepAssign(result[key], value);
3563
+ break;
3564
+ }
3565
+ case "map": {
3566
+ result[key] = new Map([
3567
+ ...Array.from(currentValue.entries()),
3568
+ ...Array.from(value.entries())
3569
+ ]);
3570
+ break;
3571
+ }
3572
+ case "set": {
3573
+ result[key] = /* @__PURE__ */ new Set([
3574
+ ...Array.from(currentValue),
3575
+ ...Array.from(value)
3576
+ ]);
3577
+ break;
3578
+ }
3579
+ default: {
3580
+ result[key] = value;
3652
3581
  }
3653
- } catch (err) {
3654
- this.emit("error", err);
3655
3582
  }
3656
- });
3657
- return true;
3658
- }
3659
- on(eventName, listener) {
3660
- if (!this.#listeners.has(eventName)) {
3661
- this.#listeners.set(eventName, /* @__PURE__ */ new Set());
3662
3583
  }
3663
- const set = this.#listeners.get(eventName);
3664
- set.add(listener);
3665
- return this;
3666
- }
3667
- once(eventName, listener) {
3668
- const wrapped = (...args) => {
3669
- this.off(eventName, wrapped);
3670
- listener(...args);
3671
- };
3672
- this.on(eventName, wrapped);
3673
- return this;
3674
3584
  }
3675
- off(eventName, listener) {
3676
- const set = this.#listeners.get(eventName);
3677
- if (set) {
3678
- set.delete(listener);
3679
- if (set.size === 0) {
3680
- this.#listeners.delete(eventName);
3681
- }
3585
+ return result;
3586
+ }
3587
+ function stringify(obj, options) {
3588
+ return new URLSearchParams(toParams(obj, options)).toString();
3589
+ }
3590
+ function toParams(obj, options) {
3591
+ const result = {};
3592
+ const excludeEmpty = options?.excludeEmpty !== false;
3593
+ const excludeDefaults = options?.excludeDefaults;
3594
+ for (const [key, value] of Object.entries(obj)) {
3595
+ if (excludeEmpty && isEmpty(value)) continue;
3596
+ if (excludeDefaults && key in excludeDefaults) {
3597
+ const defValue = excludeDefaults[key];
3598
+ if (isEqual(value, defValue)) continue;
3682
3599
  }
3683
- return this;
3684
- }
3685
- removeAllListeners(eventName) {
3686
- if (eventName === void 0) {
3687
- this.#listeners.clear();
3688
- return this;
3600
+ const strValue = stringifyValue(value);
3601
+ if (excludeEmpty && strValue === "") {
3602
+ continue;
3689
3603
  }
3690
- this.#listeners.delete(eventName);
3691
- return this;
3604
+ result[key] = strValue;
3692
3605
  }
3606
+ return result;
3693
3607
  }
3694
-
3695
- class Queue {
3696
- items = [];
3697
- #limit;
3698
- #events = new SimpleEventEmitter();
3699
- constructor(limit) {
3700
- this.#limit = limit;
3701
- }
3702
- async get() {
3703
- if (this.items.length === 0) {
3704
- await SimpleEventEmitter.once(this.#events, "put");
3705
- }
3706
- const item = this.items.shift();
3707
- this.#events.emit("get");
3708
- return item;
3608
+ function parse(value, defaults) {
3609
+ const objValue = isString(value) ? Object.fromEntries(new URLSearchParams(value).entries()) : value;
3610
+ if (!defaults) {
3611
+ return { ...objValue };
3709
3612
  }
3710
- async put(item) {
3711
- if (this.#limit && this.items.length >= this.#limit) {
3712
- await SimpleEventEmitter.once(this.#events, "get");
3613
+ const result = {};
3614
+ for (const [key, defValue] of Object.entries(defaults)) {
3615
+ const defType = typeOf(defValue);
3616
+ let parsedValue = parseValue(objValue[key], defType);
3617
+ if (parsedValue !== void 0 || defType === "undefined") {
3618
+ if (defType === "array" && defValue[0] !== void 0) {
3619
+ const itemValue = typeOf(defValue[0]);
3620
+ parsedValue = parsedValue.map((v) => parseValue(v, itemValue));
3621
+ }
3622
+ result[key] = parsedValue;
3623
+ } else {
3624
+ result[key] = defValue;
3713
3625
  }
3714
- this.items.push(item);
3715
- this.#events.emit("put");
3716
3626
  }
3627
+ return result;
3717
3628
  }
3718
-
3719
- class AsyncIterableQueue {
3720
- _queue;
3721
- _closed = false;
3722
- static QUEUE_END_MARKER = Symbol("QUEUE_END_MARKER");
3723
- constructor() {
3724
- this._queue = new Queue();
3725
- }
3726
- get closed() {
3727
- return this._closed;
3728
- }
3729
- put(item) {
3730
- if (this._closed) {
3731
- throw new Error("Queue is closed");
3629
+ function stringifyValue(value) {
3630
+ const valueType = typeOf(value);
3631
+ switch (valueType) {
3632
+ case "undefined": {
3633
+ return "";
3732
3634
  }
3733
- this._queue.put(item);
3734
- }
3735
- close() {
3736
- if (this._closed) return;
3737
- this._closed = true;
3738
- this._queue.put(AsyncIterableQueue.QUEUE_END_MARKER);
3739
- }
3740
- [Symbol.asyncIterator]() {
3741
- return {
3742
- next: async () => {
3743
- if (this._closed && this._queue.items.length === 0) {
3744
- return { value: void 0, done: true };
3745
- }
3746
- const item = await this._queue.get();
3747
- if (item === AsyncIterableQueue.QUEUE_END_MARKER && this._closed) {
3748
- return { value: void 0, done: true };
3635
+ case "null": {
3636
+ return "";
3637
+ }
3638
+ case "array": {
3639
+ let result = "";
3640
+ let sep = "";
3641
+ for (const item of value) {
3642
+ if (item === void 0) continue;
3643
+ if (isObject(item) || Array.isArray(item) || isString(item) && item.includes(",")) {
3644
+ result = JSON.stringify(value);
3645
+ break;
3646
+ } else {
3647
+ result += sep + stringifyValue(item);
3648
+ sep = ",";
3749
3649
  }
3750
- return { value: item, done: false };
3751
3650
  }
3752
- };
3753
- }
3754
- }
3755
-
3756
- async function asyncMap(array, callbackfn, { concurrency = 1 } = {}) {
3757
- let result = [];
3758
- concurrency = Math.max(concurrency, 1);
3759
- const cooldown = nextTickIteration(10);
3760
- let i = 0;
3761
- const handle = (value, index) => {
3762
- return callbackfn(value, i + index, array);
3763
- };
3764
- while (i < array.length) {
3765
- await cooldown();
3766
- const batch = await Promise.all(
3767
- array.slice(i, i + concurrency).map(handle)
3768
- );
3769
- result = result.concat(batch);
3770
- i += batch.length;
3651
+ return result;
3652
+ }
3653
+ case "date": {
3654
+ return value.toISOString();
3655
+ }
3656
+ case "map": {
3657
+ return JSON.stringify(Array.from(value.entries()));
3658
+ }
3659
+ case "set": {
3660
+ return JSON.stringify(Array.from(value.values()));
3661
+ }
3662
+ case "boolean":
3663
+ case "number":
3664
+ case "string":
3665
+ case "bigint": {
3666
+ return String(value);
3667
+ }
3668
+ case "object": {
3669
+ return JSON.stringify(value);
3670
+ }
3671
+ case "unknown": {
3672
+ if (isFunction(value?.toString)) {
3673
+ return value.toString();
3674
+ }
3675
+ }
3676
+ default: {
3677
+ throw new Error("Attempt to stringify unsupported type: " + valueType);
3678
+ }
3771
3679
  }
3772
- return result;
3773
3680
  }
3774
-
3775
- class CancellablePromise {
3776
- #promise;
3777
- #cancelFns;
3778
- #isCancelled = false;
3779
- #error = null;
3780
- constructor(executor) {
3781
- this.#cancelFns = [];
3782
- this.#promise = new Promise((resolve, reject) => {
3783
- executor(
3784
- resolve,
3785
- (reason) => {
3786
- this.#error = toError(reason, "Unknown rejection reason.");
3787
- reject(reason);
3788
- },
3789
- (fn) => {
3790
- this.#cancelFns.push(fn);
3791
- }
3792
- );
3793
- });
3794
- }
3795
- get [Symbol.toStringTag]() {
3796
- return this.#promise[Symbol.toStringTag] + (this.isCancelled ? " (Cancelled)" : "");
3797
- }
3798
- get isCancelled() {
3799
- return this.#isCancelled;
3800
- }
3801
- get error() {
3802
- return this.#error;
3803
- }
3804
- then(onfulfilled, onrejected) {
3805
- return this.#promise.then(onfulfilled, onrejected);
3806
- }
3807
- catch(onrejected) {
3808
- return this.#promise.catch(onrejected);
3809
- }
3810
- finally(onfinally) {
3811
- return this.#promise.finally(onfinally);
3681
+ function parseValue(value, asType) {
3682
+ const type = typeOf(value);
3683
+ if (type === asType) {
3684
+ return value;
3685
+ } else if (type !== "string") {
3686
+ return void 0;
3812
3687
  }
3813
- cancel() {
3814
- if (this.#isCancelled) return;
3815
- this.#isCancelled = true;
3816
- for (const fn of this.#cancelFns) {
3817
- catchError(fn);
3688
+ try {
3689
+ switch (asType) {
3690
+ case "undefined": {
3691
+ return void 0;
3692
+ }
3693
+ case "array": {
3694
+ if (value.startsWith("[") && value.endsWith("]")) {
3695
+ return JSON.parse(value);
3696
+ }
3697
+ return value.split(",");
3698
+ }
3699
+ case "boolean": {
3700
+ return value === "true";
3701
+ }
3702
+ case "date": {
3703
+ const parsed = new Date(value);
3704
+ return isDate(parsed) ? parsed : void 0;
3705
+ }
3706
+ case "map": {
3707
+ return new Map(JSON.parse(value));
3708
+ }
3709
+ case "number": {
3710
+ const parsed = parseFloat(value);
3711
+ return isNumber(parsed) ? parsed : void 0;
3712
+ }
3713
+ case "object": {
3714
+ return JSON.parse(value);
3715
+ }
3716
+ case "set": {
3717
+ return new Set(JSON.parse(value));
3718
+ }
3719
+ case "null": {
3720
+ return value === "" || value === void 0 ? null : void 0;
3721
+ }
3722
+ case "string": {
3723
+ return value;
3724
+ }
3725
+ case "bigint": {
3726
+ return BigInt(value);
3727
+ }
3818
3728
  }
3729
+ } catch (_) {
3819
3730
  }
3820
- static from(promise) {
3821
- return new CancellablePromise((resolve, reject) => {
3822
- promise.then(resolve).catch(reject);
3823
- });
3731
+ return void 0;
3732
+ }
3733
+
3734
+ function defer() {
3735
+ let resolve;
3736
+ let reject;
3737
+ const promise = new Promise((_resolve, _reject) => {
3738
+ resolve = _resolve;
3739
+ reject = _reject;
3740
+ });
3741
+ return {
3742
+ resolve,
3743
+ reject,
3744
+ promise
3745
+ };
3746
+ }
3747
+
3748
+ const defaultWindow$1 = globalThis?.window;
3749
+ const idle = (() => {
3750
+ if (defaultWindow$1?.requestIdleCallback) {
3751
+ return defaultWindow$1.requestIdleCallback;
3752
+ } else if (defaultWindow$1?.requestAnimationFrame) {
3753
+ return defaultWindow$1.requestAnimationFrame;
3754
+ } else if (isFunction(process?.nextTick)) {
3755
+ return process.nextTick;
3756
+ } else {
3757
+ return (fn) => setTimeout(fn, 0);
3824
3758
  }
3759
+ })();
3760
+ function fastIdle(callback) {
3761
+ return idle(callback);
3762
+ }
3763
+ function fastIdlePromise() {
3764
+ return new Promise((resolve) => idle(resolve));
3825
3765
  }
3826
3766
 
3827
3767
  function delay(amount = "tick") {
@@ -3834,352 +3774,546 @@ function delay(amount = "tick") {
3834
3774
  return d.promise;
3835
3775
  }
3836
3776
 
3837
- const FAST_RAF_TIMEOUT_FALLBACK_MS = 300;
3838
- const defaultWindow = globalThis?.window;
3839
- const raf = defaultWindow?.requestAnimationFrame || ((cb) => setTimeout(cb, 0));
3840
- let fastRafCallbacks;
3841
- let fastRafFallbackCallbacks;
3842
- let fastRafFallbackTimeout;
3843
- function fastRaf(callback, withTimeoutFallback = false) {
3844
- if (!fastRafCallbacks) {
3845
- fastRafCallbacks = /* @__PURE__ */ new Set([callback]);
3846
- raf(() => {
3847
- const currentCallbacks = fastRafCallbacks;
3848
- fastRafCallbacks = void 0;
3849
- fastRafFallbackCallbacks = void 0;
3850
- if (fastRafFallbackTimeout) {
3851
- clearTimeout(fastRafFallbackTimeout);
3852
- fastRafFallbackTimeout = void 0;
3853
- }
3854
- currentCallbacks.forEach((cb) => cb());
3855
- });
3856
- } else {
3857
- fastRafCallbacks.add(callback);
3858
- }
3859
- if (withTimeoutFallback) {
3860
- if (!fastRafFallbackCallbacks) {
3861
- fastRafFallbackCallbacks = /* @__PURE__ */ new Set([callback]);
3862
- } else {
3863
- fastRafFallbackCallbacks.add(callback);
3777
+ const noopShouldRetryBasedOnError = () => true;
3778
+ function retryOnError({
3779
+ beforeRetryCallback,
3780
+ shouldRetryBasedOnError = noopShouldRetryBasedOnError,
3781
+ maxRetriesNumber,
3782
+ delayFactor = 0,
3783
+ delayMaxMs = 1e3,
3784
+ delayMinMs = 100
3785
+ }, fn) {
3786
+ let retryCount = maxRetriesNumber;
3787
+ let delayMs = 0;
3788
+ delayMinMs = Math.max(delayMinMs, 1);
3789
+ delayMaxMs = Math.max(delayMaxMs, 1);
3790
+ const run = async (...args) => {
3791
+ if (delayFactor >= 1 && delayMs > 0) {
3792
+ await delay(delayMs);
3864
3793
  }
3865
- if (!fastRafFallbackTimeout) {
3866
- fastRafFallbackTimeout = setTimeout(() => {
3867
- const currentTimeoutCallbacks = fastRafFallbackCallbacks;
3868
- if (fastRafCallbacks) {
3869
- currentTimeoutCallbacks.forEach(
3870
- fastRafCallbacks.delete,
3871
- fastRafCallbacks
3794
+ const currentAttempt = 1 + maxRetriesNumber - retryCount;
3795
+ try {
3796
+ const res = await fn(...args);
3797
+ return res;
3798
+ } catch (e) {
3799
+ if (retryCount > 1 && shouldRetryBasedOnError(e, currentAttempt)) {
3800
+ retryCount--;
3801
+ delayMs = Math.floor(
3802
+ Math.min(Math.max(delayMs, delayMinMs) * delayFactor, delayMaxMs)
3803
+ );
3804
+ if (beforeRetryCallback) {
3805
+ const newParams = await beforeRetryCallback(
3806
+ currentAttempt,
3807
+ retryCount === 0
3872
3808
  );
3809
+ if (newParams) {
3810
+ return run(newParams);
3811
+ }
3873
3812
  }
3874
- fastRafFallbackCallbacks = void 0;
3875
- if (fastRafFallbackTimeout) {
3876
- clearTimeout(fastRafFallbackTimeout);
3877
- fastRafFallbackTimeout = void 0;
3878
- }
3879
- currentTimeoutCallbacks.forEach((cb) => cb());
3880
- }, FAST_RAF_TIMEOUT_FALLBACK_MS);
3813
+ return run(...args);
3814
+ }
3815
+ throw e;
3881
3816
  }
3882
- }
3883
- }
3884
- function rafPromise() {
3885
- return new Promise((resolve) => {
3886
- fastRaf(resolve);
3887
- });
3817
+ };
3818
+ return run;
3888
3819
  }
3889
3820
 
3890
- function timeout(ms, promiseOrCallback, timeoutError = new Error("Timeout")) {
3891
- const abortController = new AbortController();
3892
- let taskResult;
3893
- if (isFunction(promiseOrCallback)) {
3894
- taskResult = promiseOrCallback(abortController.signal);
3895
- } else if (isPromise(promiseOrCallback)) {
3896
- taskResult = promiseOrCallback;
3897
- } else {
3898
- throw new TypeError(
3899
- "Expected promise or callback as second argument, received: " + String(promiseOrCallback)
3900
- );
3901
- }
3902
- if (!isPromise(taskResult)) {
3903
- return Promise.resolve(taskResult);
3904
- }
3905
- let timer;
3906
- return Promise.race([
3907
- taskResult,
3908
- new Promise((_, reject) => {
3909
- timer = setTimeout(() => {
3910
- abortController.abort();
3911
- reject(timeoutError);
3912
- }, ms);
3913
- })
3914
- ]).finally(() => {
3915
- timer && clearTimeout(timer);
3916
- timer = void 0;
3917
- });
3821
+ function throttle(func, throttleMs, { signal, edges = ["leading", "trailing"] } = {}) {
3822
+ let pendingAt = null;
3823
+ const debounced = debounce(func, throttleMs, { signal, edges });
3824
+ const throttled = function(...args) {
3825
+ if (pendingAt == null) {
3826
+ pendingAt = Date.now();
3827
+ } else {
3828
+ if (Date.now() - pendingAt >= throttleMs) {
3829
+ pendingAt = Date.now();
3830
+ debounced.cancel();
3831
+ debounced(...args);
3832
+ }
3833
+ }
3834
+ debounced(...args);
3835
+ };
3836
+ throttled.cancel = debounced.cancel;
3837
+ throttled.flush = debounced.flush;
3838
+ return throttled;
3918
3839
  }
3919
3840
 
3920
- function typeOf(value) {
3921
- const type = typeof value;
3922
- switch (type) {
3923
- case "number":
3924
- return isNumber(value) ? "number" : "unknown";
3925
- case "object": {
3926
- if (value === null) return "null";
3927
- if (Array.isArray(value)) return "array";
3928
- if (isSet(value)) return "set";
3929
- if (isWeakSet(value)) return "weakset";
3930
- if (isMap(value)) return "map";
3931
- if (isWeakMap(value)) return "weakmap";
3932
- if (isDate(value)) return "date";
3933
- if (isObject(value)) return "object";
3934
- return "unknown";
3935
- }
3936
- default: {
3937
- return type;
3841
+ function sprintf(line, args, unusedArgs = []) {
3842
+ let result = "";
3843
+ const argsLen = args.length;
3844
+ const lineLen = line.length;
3845
+ let opened = false;
3846
+ let currentChar = -1;
3847
+ let lastPos = 0;
3848
+ let argsIndex = 0;
3849
+ for (let idx = 0; idx < lineLen; idx++) {
3850
+ currentChar = line.charCodeAt(idx);
3851
+ if (currentChar === 37) {
3852
+ opened = true;
3853
+ continue;
3938
3854
  }
3939
- }
3940
- }
3941
-
3942
- const qs = {
3943
- toParams,
3944
- stringify,
3945
- stringifyValue,
3946
- parse,
3947
- parseValue,
3948
- merge
3949
- };
3950
- function merge(...values) {
3951
- const result = {};
3952
- for (const filter of values) {
3953
- for (const [key, value] of Object.entries(filter)) {
3954
- const currentValue = result[key];
3955
- const currentType = typeOf(currentValue);
3956
- const filterType = typeOf(value);
3957
- if (currentType !== filterType) {
3958
- result[key] = value;
3959
- continue;
3855
+ if (!opened) continue;
3856
+ opened = false;
3857
+ switch (currentChar) {
3858
+ // 'd'
3859
+ case 100:
3860
+ // 'f'
3861
+ case 102: {
3862
+ result += line.slice(lastPos, idx - 1);
3863
+ result += Number(args[argsIndex]);
3864
+ lastPos = idx + 1;
3865
+ argsIndex++;
3866
+ break;
3960
3867
  }
3961
- switch (currentType) {
3962
- case "array": {
3963
- result[key] = Array.from(/* @__PURE__ */ new Set([...currentValue, ...value]));
3964
- break;
3965
- }
3966
- case "object": {
3967
- result[key] = {};
3968
- deepAssign(result[key], currentValue);
3969
- deepAssign(result[key], value);
3970
- break;
3971
- }
3972
- case "map": {
3973
- result[key] = new Map([
3974
- ...Array.from(currentValue.entries()),
3975
- ...Array.from(value.entries())
3976
- ]);
3977
- break;
3978
- }
3979
- case "set": {
3980
- result[key] = /* @__PURE__ */ new Set([
3981
- ...Array.from(currentValue),
3982
- ...Array.from(value)
3983
- ]);
3984
- break;
3985
- }
3986
- default: {
3987
- result[key] = value;
3988
- }
3868
+ // 'i'
3869
+ case 105: {
3870
+ result += line.slice(lastPos, idx - 1);
3871
+ result += Math.floor(Number(args[argsIndex]));
3872
+ lastPos = idx + 1;
3873
+ argsIndex++;
3874
+ break;
3875
+ }
3876
+ // 'O'
3877
+ case 79:
3878
+ // 'o'
3879
+ case 111:
3880
+ // 'j'
3881
+ case 106: {
3882
+ result += line.slice(lastPos, idx - 1);
3883
+ result += tryStringify(args[argsIndex]);
3884
+ lastPos = idx + 1;
3885
+ argsIndex++;
3886
+ break;
3887
+ }
3888
+ // 's'
3889
+ case 115: {
3890
+ result += line.slice(lastPos, idx - 1);
3891
+ result += String(args[argsIndex]);
3892
+ lastPos = idx + 1;
3893
+ argsIndex++;
3894
+ break;
3989
3895
  }
3990
3896
  }
3897
+ if (argsIndex >= argsLen) break;
3898
+ }
3899
+ if (lastPos < lineLen) {
3900
+ result += line.slice(lastPos, lineLen);
3901
+ }
3902
+ if (argsIndex < argsLen) {
3903
+ unusedArgs.push(...args.slice(argsIndex, argsLen));
3991
3904
  }
3992
3905
  return result;
3993
3906
  }
3994
- function stringify(obj, options) {
3995
- return new URLSearchParams(toParams(obj, options)).toString();
3996
- }
3997
- function toParams(obj, options) {
3998
- const result = {};
3999
- const excludeEmpty = options?.excludeEmpty !== false;
4000
- const excludeDefaults = options?.excludeDefaults;
4001
- for (const [key, value] of Object.entries(obj)) {
4002
- if (excludeEmpty && isEmpty(value)) continue;
4003
- if (excludeDefaults && key in excludeDefaults) {
4004
- const defValue = excludeDefaults[key];
4005
- if (isEqual(value, defValue)) continue;
3907
+ function tryStringify(o) {
3908
+ switch (typeof o) {
3909
+ case "function": {
3910
+ return o.name || "<anonymous>";
4006
3911
  }
4007
- const strValue = stringifyValue(value);
4008
- if (excludeEmpty && strValue === "") {
4009
- continue;
3912
+ case "string": {
3913
+ return "'" + o + "'";
3914
+ }
3915
+ default: {
3916
+ try {
3917
+ return JSON.stringify(o);
3918
+ } catch (e) {
3919
+ return '"[Circular]"';
3920
+ }
4010
3921
  }
4011
- result[key] = strValue;
4012
3922
  }
4013
- return result;
4014
3923
  }
4015
- function parse(value, defaults) {
4016
- const objValue = isString(value) ? Object.fromEntries(new URLSearchParams(value).entries()) : value;
4017
- if (!defaults) {
4018
- return { ...objValue };
3924
+
3925
+ const LEVEL_NUM = {
3926
+ debug: 0,
3927
+ log: 1,
3928
+ info: 2,
3929
+ warn: 3,
3930
+ error: 4
3931
+ };
3932
+ let currentLogLevel = LEVEL_NUM.log;
3933
+ const loggerSetLevel = (level) => {
3934
+ number$1(LEVEL_NUM[level], `Invalid log level: ${level}`);
3935
+ currentLogLevel = LEVEL_NUM[level];
3936
+ };
3937
+ const logger = (...baseArgs) => {
3938
+ if (isString(baseArgs[0]?.url)) {
3939
+ baseArgs[0] = baseArgs[0]?.url;
4019
3940
  }
4020
- const result = {};
4021
- for (const [key, defValue] of Object.entries(defaults)) {
4022
- const defType = typeOf(defValue);
4023
- let parsedValue = parseValue(objValue[key], defType);
4024
- if (parsedValue !== void 0 || defType === "undefined") {
4025
- if (defType === "array" && defValue[0] !== void 0) {
4026
- const itemValue = typeOf(defValue[0]);
4027
- parsedValue = parsedValue.map((v) => parseValue(v, itemValue));
4028
- }
4029
- result[key] = parsedValue;
4030
- } else {
4031
- result[key] = defValue;
3941
+ if (typeof baseArgs[0] === "string" && baseArgs[0][0] !== "[") {
3942
+ baseArgs[0] = `[${baseArgs[0].split("/").at(-1).split("?", 1)[0]}]`;
3943
+ }
3944
+ const writeLog = (level, ...[pattern, ...args]) => {
3945
+ const levelNum = LEVEL_NUM[level];
3946
+ if (levelNum < currentLogLevel) {
3947
+ return;
3948
+ }
3949
+ if (!isString(pattern)) {
3950
+ console[level](...baseArgs, pattern, ...args);
3951
+ return;
3952
+ }
3953
+ const unusedArgs = [];
3954
+ const formatted = sprintf(pattern, args, unusedArgs);
3955
+ console[level](...baseArgs, formatted, ...unusedArgs);
3956
+ };
3957
+ const log = writeLog.bind(null, "log");
3958
+ const info = writeLog.bind(null, "info");
3959
+ const warn = writeLog.bind(null, "warn");
3960
+ const error = writeLog.bind(null, "error");
3961
+ const debug = writeLog.bind(null, "debug");
3962
+ const extend = (...args) => {
3963
+ return logger(...baseArgs, ...args);
3964
+ };
3965
+ const instance = {
3966
+ log,
3967
+ info,
3968
+ warn,
3969
+ error,
3970
+ debug,
3971
+ extend
3972
+ };
3973
+ return instance;
3974
+ };
3975
+
3976
+ async function asyncFilter(array, predicate) {
3977
+ const result = [];
3978
+ const cooldown = nextTickIteration(10);
3979
+ for (let idx = 0; idx < array.length; idx++) {
3980
+ await cooldown();
3981
+ const value = array[idx];
3982
+ const valid = await predicate(value, idx, array);
3983
+ if (valid) {
3984
+ result.push(value);
4032
3985
  }
4033
3986
  }
4034
3987
  return result;
4035
3988
  }
4036
- function stringifyValue(value) {
4037
- const valueType = typeOf(value);
4038
- switch (valueType) {
4039
- case "undefined": {
4040
- return "";
4041
- }
4042
- case "null": {
4043
- return "";
4044
- }
4045
- case "array": {
4046
- let result = "";
4047
- let sep = "";
4048
- for (const item of value) {
4049
- if (item === void 0) continue;
4050
- if (isObject(item) || Array.isArray(item) || isString(item) && item.includes(",")) {
4051
- result = JSON.stringify(value);
4052
- break;
3989
+
3990
+ function nextTickIteration(amount, delay = "tick") {
3991
+ let counter = 0;
3992
+ const tickInterval = delay === "tick";
3993
+ return () => {
3994
+ counter++;
3995
+ if (counter >= amount) {
3996
+ counter = 0;
3997
+ return new Promise((resolve) => {
3998
+ if (tickInterval) {
3999
+ fastIdle(resolve);
4053
4000
  } else {
4054
- result += sep + stringifyValue(item);
4055
- sep = ",";
4001
+ setTimeout(resolve, delay);
4056
4002
  }
4057
- }
4058
- return result;
4059
- }
4060
- case "date": {
4061
- return value.toISOString();
4003
+ });
4062
4004
  }
4063
- case "map": {
4064
- return JSON.stringify(Array.from(value.entries()));
4005
+ return Promise.resolve();
4006
+ };
4007
+ }
4008
+
4009
+ async function asyncFind(array, callbackfn) {
4010
+ const cooldown = nextTickIteration(10);
4011
+ let i = 0;
4012
+ while (i < array.length) {
4013
+ await cooldown();
4014
+ const result = await callbackfn(array[i], i, array);
4015
+ if (Boolean(result)) {
4016
+ return array[i];
4065
4017
  }
4066
- case "set": {
4067
- return JSON.stringify(Array.from(value.values()));
4018
+ i++;
4019
+ }
4020
+ return void 0;
4021
+ }
4022
+
4023
+ async function asyncForEach(array, callbackfn, { concurrency = 1 } = {}) {
4024
+ const cooldown = nextTickIteration(10);
4025
+ let i = 0;
4026
+ const handle = (value, index) => {
4027
+ return callbackfn(value, i + index, array);
4028
+ };
4029
+ while (i < array.length) {
4030
+ await cooldown();
4031
+ const batch = await Promise.all(
4032
+ array.slice(i, i + concurrency).map(handle)
4033
+ );
4034
+ i += batch.length;
4035
+ }
4036
+ }
4037
+
4038
+ const onError = (error) => {
4039
+ console.error(error);
4040
+ };
4041
+ class SimpleEventEmitter {
4042
+ #listeners = /* @__PURE__ */ new Map();
4043
+ constructor() {
4044
+ this.on("error", onError);
4045
+ }
4046
+ static once(emitter, eventName) {
4047
+ const q = defer();
4048
+ emitter.once(eventName, (...args) => q.resolve(args));
4049
+ return q.promise;
4050
+ }
4051
+ emit(eventName, ...args) {
4052
+ const set = this.#listeners.get(eventName);
4053
+ if (!set) return false;
4054
+ set.forEach((fn) => {
4055
+ try {
4056
+ const result = fn();
4057
+ if (isPromise(result)) {
4058
+ result.catch((err) => {
4059
+ this.emit("error", err);
4060
+ });
4061
+ }
4062
+ } catch (err) {
4063
+ this.emit("error", err);
4064
+ }
4065
+ });
4066
+ return true;
4067
+ }
4068
+ on(eventName, listener) {
4069
+ if (!this.#listeners.has(eventName)) {
4070
+ this.#listeners.set(eventName, /* @__PURE__ */ new Set());
4068
4071
  }
4069
- case "boolean":
4070
- case "number":
4071
- case "string":
4072
- case "bigint": {
4073
- return String(value);
4072
+ const set = this.#listeners.get(eventName);
4073
+ set.add(listener);
4074
+ return this;
4075
+ }
4076
+ once(eventName, listener) {
4077
+ const wrapped = (...args) => {
4078
+ this.off(eventName, wrapped);
4079
+ listener(...args);
4080
+ };
4081
+ this.on(eventName, wrapped);
4082
+ return this;
4083
+ }
4084
+ off(eventName, listener) {
4085
+ const set = this.#listeners.get(eventName);
4086
+ if (set) {
4087
+ set.delete(listener);
4088
+ if (set.size === 0) {
4089
+ this.#listeners.delete(eventName);
4090
+ }
4074
4091
  }
4075
- case "object": {
4076
- return JSON.stringify(value);
4092
+ return this;
4093
+ }
4094
+ removeAllListeners(eventName) {
4095
+ if (eventName === void 0) {
4096
+ this.#listeners.clear();
4097
+ return this;
4077
4098
  }
4078
- case "unknown": {
4079
- if (isFunction(value?.toString)) {
4080
- return value.toString();
4081
- }
4099
+ this.#listeners.delete(eventName);
4100
+ return this;
4101
+ }
4102
+ }
4103
+
4104
+ class Queue {
4105
+ items = [];
4106
+ #limit;
4107
+ #events = new SimpleEventEmitter();
4108
+ constructor(limit) {
4109
+ this.#limit = limit;
4110
+ }
4111
+ async get() {
4112
+ if (this.items.length === 0) {
4113
+ await SimpleEventEmitter.once(this.#events, "put");
4082
4114
  }
4083
- default: {
4084
- throw new Error("Attempt to stringify unsupported type: " + valueType);
4115
+ const item = this.items.shift();
4116
+ this.#events.emit("get");
4117
+ return item;
4118
+ }
4119
+ async put(item) {
4120
+ if (this.#limit && this.items.length >= this.#limit) {
4121
+ await SimpleEventEmitter.once(this.#events, "get");
4085
4122
  }
4123
+ this.items.push(item);
4124
+ this.#events.emit("put");
4086
4125
  }
4087
4126
  }
4088
- function parseValue(value, asType) {
4089
- const type = typeOf(value);
4090
- if (type === asType) {
4091
- return value;
4092
- } else if (type !== "string") {
4093
- return void 0;
4127
+
4128
+ class AsyncIterableQueue {
4129
+ _queue;
4130
+ _closed = false;
4131
+ static QUEUE_END_MARKER = Symbol("QUEUE_END_MARKER");
4132
+ constructor() {
4133
+ this._queue = new Queue();
4094
4134
  }
4095
- try {
4096
- switch (asType) {
4097
- case "undefined": {
4098
- return void 0;
4099
- }
4100
- case "array": {
4101
- if (value.startsWith("[") && value.endsWith("]")) {
4102
- return JSON.parse(value);
4135
+ get closed() {
4136
+ return this._closed;
4137
+ }
4138
+ put(item) {
4139
+ if (this._closed) {
4140
+ throw new Error("Queue is closed");
4141
+ }
4142
+ this._queue.put(item);
4143
+ }
4144
+ close() {
4145
+ if (this._closed) return;
4146
+ this._closed = true;
4147
+ this._queue.put(AsyncIterableQueue.QUEUE_END_MARKER);
4148
+ }
4149
+ [Symbol.asyncIterator]() {
4150
+ return {
4151
+ next: async () => {
4152
+ if (this._closed && this._queue.items.length === 0) {
4153
+ return { value: void 0, done: true };
4103
4154
  }
4104
- return value.split(",");
4105
- }
4106
- case "boolean": {
4107
- return value === "true";
4108
- }
4109
- case "date": {
4110
- const parsed = new Date(value);
4111
- return isDate(parsed) ? parsed : void 0;
4112
- }
4113
- case "map": {
4114
- return new Map(JSON.parse(value));
4115
- }
4116
- case "number": {
4117
- const parsed = parseFloat(value);
4118
- return isNumber(parsed) ? parsed : void 0;
4119
- }
4120
- case "object": {
4121
- return JSON.parse(value);
4122
- }
4123
- case "set": {
4124
- return new Set(JSON.parse(value));
4125
- }
4126
- case "null": {
4127
- return value === "" || value === void 0 ? null : void 0;
4128
- }
4129
- case "string": {
4130
- return value;
4131
- }
4132
- case "bigint": {
4133
- return BigInt(value);
4155
+ const item = await this._queue.get();
4156
+ if (item === AsyncIterableQueue.QUEUE_END_MARKER && this._closed) {
4157
+ return { value: void 0, done: true };
4158
+ }
4159
+ return { value: item, done: false };
4134
4160
  }
4161
+ };
4162
+ }
4163
+ }
4164
+
4165
+ async function asyncMap(array, callbackfn, { concurrency = 1 } = {}) {
4166
+ let result = [];
4167
+ concurrency = Math.max(concurrency, 1);
4168
+ const cooldown = nextTickIteration(10);
4169
+ let i = 0;
4170
+ const handle = (value, index) => {
4171
+ return callbackfn(value, i + index, array);
4172
+ };
4173
+ while (i < array.length) {
4174
+ await cooldown();
4175
+ const batch = await Promise.all(
4176
+ array.slice(i, i + concurrency).map(handle)
4177
+ );
4178
+ result = result.concat(batch);
4179
+ i += batch.length;
4180
+ }
4181
+ return result;
4182
+ }
4183
+
4184
+ class CancellablePromise {
4185
+ #promise;
4186
+ #cancelFns;
4187
+ #isCancelled = false;
4188
+ #error = null;
4189
+ constructor(executor) {
4190
+ this.#cancelFns = [];
4191
+ this.#promise = new Promise((resolve, reject) => {
4192
+ executor(
4193
+ resolve,
4194
+ (reason) => {
4195
+ this.#error = toError(reason, "Unknown rejection reason.");
4196
+ reject(reason);
4197
+ },
4198
+ (fn) => {
4199
+ this.#cancelFns.push(fn);
4200
+ }
4201
+ );
4202
+ });
4203
+ }
4204
+ get [Symbol.toStringTag]() {
4205
+ return this.#promise[Symbol.toStringTag] + (this.isCancelled ? " (Cancelled)" : "");
4206
+ }
4207
+ get isCancelled() {
4208
+ return this.#isCancelled;
4209
+ }
4210
+ get error() {
4211
+ return this.#error;
4212
+ }
4213
+ then(onfulfilled, onrejected) {
4214
+ return this.#promise.then(onfulfilled, onrejected);
4215
+ }
4216
+ catch(onrejected) {
4217
+ return this.#promise.catch(onrejected);
4218
+ }
4219
+ finally(onfinally) {
4220
+ return this.#promise.finally(onfinally);
4221
+ }
4222
+ cancel() {
4223
+ if (this.#isCancelled) return;
4224
+ this.#isCancelled = true;
4225
+ for (const fn of this.#cancelFns) {
4226
+ catchError(fn);
4135
4227
  }
4136
- } catch (_) {
4137
4228
  }
4138
- return void 0;
4229
+ static from(promise) {
4230
+ return new CancellablePromise((resolve, reject) => {
4231
+ promise.then(resolve).catch(reject);
4232
+ });
4233
+ }
4139
4234
  }
4140
4235
 
4141
- const noopShouldRetryBasedOnError = () => true;
4142
- function retryOnError({
4143
- beforeRetryCallback,
4144
- shouldRetryBasedOnError = noopShouldRetryBasedOnError,
4145
- maxRetriesNumber,
4146
- delayFactor = 0,
4147
- delayMaxMs = 1e3,
4148
- delayMinMs = 100
4149
- }, fn) {
4150
- let retryCount = maxRetriesNumber;
4151
- let delayMs = 0;
4152
- delayMinMs = Math.max(delayMinMs, 1);
4153
- delayMaxMs = Math.max(delayMaxMs, 1);
4154
- const run = async (...args) => {
4155
- if (delayFactor >= 1 && delayMs > 0) {
4156
- await delay(delayMs);
4236
+ const FAST_RAF_TIMEOUT_FALLBACK_MS = 300;
4237
+ const defaultWindow = globalThis?.window;
4238
+ const raf = defaultWindow?.requestAnimationFrame || ((cb) => setTimeout(cb, 0));
4239
+ let fastRafCallbacks;
4240
+ let fastRafFallbackCallbacks;
4241
+ let fastRafFallbackTimeout;
4242
+ function fastRaf(callback, withTimeoutFallback = false) {
4243
+ if (!fastRafCallbacks) {
4244
+ fastRafCallbacks = /* @__PURE__ */ new Set([callback]);
4245
+ raf(() => {
4246
+ const currentCallbacks = fastRafCallbacks;
4247
+ fastRafCallbacks = void 0;
4248
+ fastRafFallbackCallbacks = void 0;
4249
+ if (fastRafFallbackTimeout) {
4250
+ clearTimeout(fastRafFallbackTimeout);
4251
+ fastRafFallbackTimeout = void 0;
4252
+ }
4253
+ currentCallbacks.forEach((cb) => cb());
4254
+ });
4255
+ } else {
4256
+ fastRafCallbacks.add(callback);
4257
+ }
4258
+ if (withTimeoutFallback) {
4259
+ if (!fastRafFallbackCallbacks) {
4260
+ fastRafFallbackCallbacks = /* @__PURE__ */ new Set([callback]);
4261
+ } else {
4262
+ fastRafFallbackCallbacks.add(callback);
4157
4263
  }
4158
- const currentAttempt = 1 + maxRetriesNumber - retryCount;
4159
- try {
4160
- const res = await fn(...args);
4161
- return res;
4162
- } catch (e) {
4163
- if (retryCount > 1 && shouldRetryBasedOnError(e, currentAttempt)) {
4164
- retryCount--;
4165
- delayMs = Math.floor(
4166
- Math.min(Math.max(delayMs, delayMinMs) * delayFactor, delayMaxMs)
4167
- );
4168
- if (beforeRetryCallback) {
4169
- const newParams = await beforeRetryCallback(
4170
- currentAttempt,
4171
- retryCount === 0
4264
+ if (!fastRafFallbackTimeout) {
4265
+ fastRafFallbackTimeout = setTimeout(() => {
4266
+ const currentTimeoutCallbacks = fastRafFallbackCallbacks;
4267
+ if (fastRafCallbacks) {
4268
+ currentTimeoutCallbacks.forEach(
4269
+ fastRafCallbacks.delete,
4270
+ fastRafCallbacks
4172
4271
  );
4173
- if (newParams) {
4174
- return run(newParams);
4175
- }
4176
4272
  }
4177
- return run(...args);
4178
- }
4179
- throw e;
4273
+ fastRafFallbackCallbacks = void 0;
4274
+ if (fastRafFallbackTimeout) {
4275
+ clearTimeout(fastRafFallbackTimeout);
4276
+ fastRafFallbackTimeout = void 0;
4277
+ }
4278
+ currentTimeoutCallbacks.forEach((cb) => cb());
4279
+ }, FAST_RAF_TIMEOUT_FALLBACK_MS);
4180
4280
  }
4181
- };
4182
- return run;
4281
+ }
4282
+ }
4283
+ function rafPromise() {
4284
+ return new Promise((resolve) => {
4285
+ fastRaf(resolve);
4286
+ });
4287
+ }
4288
+
4289
+ function timeout(ms, promiseOrCallback, timeoutError = new AppError(408)) {
4290
+ const abortController = new AbortController();
4291
+ let taskResult;
4292
+ if (isFunction(promiseOrCallback)) {
4293
+ taskResult = promiseOrCallback(abortController.signal);
4294
+ } else if (isPromise(promiseOrCallback)) {
4295
+ taskResult = promiseOrCallback;
4296
+ } else {
4297
+ throw new TypeError(
4298
+ "Expected promise or callback as second argument, received: " + String(promiseOrCallback)
4299
+ );
4300
+ }
4301
+ if (!isPromise(taskResult)) {
4302
+ return Promise.resolve(taskResult);
4303
+ }
4304
+ let timer;
4305
+ return Promise.race([
4306
+ taskResult,
4307
+ new Promise((_, reject) => {
4308
+ timer = setTimeout(() => {
4309
+ abortController.abort();
4310
+ reject(timeoutError);
4311
+ }, ms);
4312
+ })
4313
+ ]).finally(() => {
4314
+ timer && clearTimeout(timer);
4315
+ timer = void 0;
4316
+ });
4183
4317
  }
4184
4318
 
4185
4319
  function capitalize(str) {
@@ -4418,5 +4552,5 @@ function wrapText(value, maxLength = 30) {
4418
4552
  return value;
4419
4553
  }
4420
4554
 
4421
- export { AppError, AsyncIterableQueue, BrowserAssertionError, CancellablePromise, ColorParser, instance as EJSON, EJSONStream, FindMean, FixedMap, FixedWeakMap, LruCache, Queue, SimpleEventEmitter, TWEMOJI_REGEX, TimeBucket, TimeSpan, alpha, arrayable, assert, asyncFilter, asyncFind, asyncForEach, asyncMap, avg, base64ToBytes, bigIntBytes, bigIntFromBytes, blendColors, buildCssColor, bytesToBase64, cache, cacheBucket, cacheFixed, cacheLRU, camelCase, capitalize, captureStackTrace, catchError, channelsToHSL, channelsToHex, channelsToRGB, checkBitmask, chunk, chunkSeries, clamp, cleanEmpty, cleanObject, colorToChannels, compareBytes, concatenateBytes, contrastRatio, convertToUnit, crc32, createCustomizer, createCustomizerFactory, createDateObject, createDeepCloneWith, createEJSON, createEJSONStream, createEnvParser, createRandomizer, createSecureCustomizer, createTimeObject, createTimeSpan, createWithCache, cssVariable, dateInDays, dateInSeconds, deepAssign, deepClone, deepCloneWith, deepDefaults, deepFreeze, def, defer, delay, difference, dropCache, env, escapeHtml, escapeNumeric, escapeRegExp, fastIdle, fastIdlePromise, fastRaf, findMean, flagsToMap, flatten, formatMoney, formatNumber, get, getFileExtension, getFileName, getInitials, getMostSpecificPaths, getRandomInt, getRandomTime, getWords, groupBy, has, hasOwn, hasProtocol, hex, hexToChannels, hmToSeconds, hslToChannels, humanFileSize, humanize, interpolateColor, intersection, isBigInt, isBoolean, isCached, isClient, isColorChannels, isCustomizerFactory, isDate, isDateObject, isDef, isEmpty, isEqual, isError, isFunction, isInfinity, isMap, isNullOrUndefined, isNumber, isObject, isOneEmoji, isPlainObject, isPrimitive, isPromise, isSet, isSkip, isString, isSuccess, isSymbol, isTimeObject, isTimeString, isTimeValue, isValidWeekDay, isWeakMap, isWeakSet, isWithCache, isoToFlagEmoji, kebabCase, keyBy, logger, loggerSetLevel, lowerCase, luminance, maskingEmail, maskingPhone, maskingWords, nextTickIteration, noop, objectId, omit, omitPrefixed, orderBy, parseAllNumbers, parseAlpha, parsePercentage, percentOf, pick, pickPrefixed, qs, rafPromise, randomString, removeVS16s, retryOnError, rgbToChannels, round2digits, secondsToHm, set, shuffle, snakeCase, sprintf, startCase, strAssign, sum, timeFromMinutes, timeStringify, timeToMinutes, timeout, timestamp, timestampMs, timestampToDate, tintedTextColor, toError, toMap, truncate, typeOf, uint16ToUint8, uint32ToUint8, uint8ToUint16, uint8ToUint32, unflatten, union, uniq, uniqBy, unset, weeksInYear, weightedRoundRobin, withCache, withCacheBucket, withCacheBucketBatch, withCacheFixed, withCacheLRU, withDeepClone, withPointerCache, wrapText };
4555
+ export { AppError, AsyncIterableQueue, BrowserAssertionError, CancellablePromise, ColorParser, instance as EJSON, EJSONStream, FindMean, FixedMap, FixedWeakMap, LruCache, Queue, SimpleEventEmitter, TWEMOJI_REGEX, TimeBucket, TimeSpan, alpha, arrayable, assert, asyncFilter, asyncFind, asyncForEach, asyncMap, avg, base64ToBytes, bigIntBytes, bigIntFromBytes, blendColors, buildCssColor, bytesToBase64, cache, cacheBucket, cacheFixed, cacheLRU, camelCase, capitalize, captureStackTrace, catchError, channelsToHSL, channelsToHex, channelsToRGB, checkBitmask, chunk, chunkSeries, clamp, cleanEmpty, cleanObject, colorToChannels, compareBytes, concatenateBytes, contrastRatio, convertToUnit, crc32, createCustomizer, createCustomizerFactory, createDateObject, createDeepCloneWith, createEJSON, createEJSONStream, createEnvParser, createRandomizer, createSecureCustomizer, createTimeObject, createTimeSpan, createWithCache, cssVariable, dateInDays, dateInSeconds, debounce, deepAssign, deepClone, deepCloneWith, deepDefaults, deepFreeze, def, defer, delay, difference, dropCache, env, escapeHtml, escapeNumeric, escapeRegExp, fastIdle, fastIdlePromise, fastRaf, findMean, flagsToMap, flatten, formatMoney, formatNumber, get, getFileExtension, getFileName, getInitials, getMostSpecificPaths, getRandomInt, getRandomTime, getWords, groupBy, has, hasOwn, hasProtocol, hex, hexToChannels, hmToSeconds, hslToChannels, humanFileSize, humanize, interpolateColor, intersection, isBigInt, isBoolean, isCached, isClient, isColorChannels, isCustomizerFactory, isDate, isDateObject, isDef, isEmpty, isEqual, isError, isFunction, isInfinity, isMap, isNullOrUndefined, isNumber, isObject, isOneEmoji, isPlainObject, isPrimitive, isPromise, isRegExp, isSet, isSkip, isString, isSuccess, isSymbol, isTimeObject, isTimeString, isTimeValue, isValidWeekDay, isWeakMap, isWeakSet, isWithCache, isoToFlagEmoji, kebabCase, keyBy, logger, loggerSetLevel, lowerCase, luminance, maskingEmail, maskingPhone, maskingWords, nextTickIteration, noop, objectId, omit, omitPrefixed, orderBy, parseAllNumbers, parseAlpha, parsePercentage, percentOf, pick, pickPrefixed, qs, rafPromise, randomString, removeVS16s, retryOnError, rgbToChannels, round2digits, secondsToHm, set, shuffle, snakeCase, sprintf, startCase, strAssign, sum, throttle, timeFromMinutes, timeStringify, timeToMinutes, timeout, timestamp, timestampMs, timestampToDate, tintedTextColor, toError, toMap, truncate, typeOf, uint16ToUint8, uint32ToUint8, uint8ToUint16, uint8ToUint32, unflatten, union, uniq, uniqBy, unset, weeksInYear, weightedRoundRobin, withCache, withCacheBucket, withCacheBucketBatch, withCacheFixed, withCacheLRU, withDeepClone, withPointerCache, wrapText };
4422
4556
  //# sourceMappingURL=index.mjs.map