@andrew_l/toolkit 0.3.6 → 0.3.8

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.d.ts CHANGED
@@ -466,6 +466,33 @@ declare namespace assert {
466
466
  export { assert_array as array, assert_arrayNumbers as arrayNumbers, assert_arrayStrings as arrayStrings, assert_boolean as boolean, assert_date as date, assert_equal as equal, assert_fn as fn, assert_greaterThan as greaterThan, assert_lessThan as lessThan, assert_notEmpty as notEmpty, assert_notEmptyString as notEmptyString, assert_number as number, assert_object as object, assert_ok as ok, assert_string as string };
467
467
  }
468
468
 
469
+ /**
470
+ * Base62 encoder/decoder for binary data.
471
+ *
472
+ * @example Basic usage
473
+ * ```typescript
474
+ * const data = new Uint8Array([255, 128, 64]);
475
+ * const encoded = base62.encode(data);
476
+ * console.log(encoded);
477
+ *
478
+ * const decoded = base62.decode(encoded);
479
+ * console.log(decoded); // Uint8Array [255, 128, 64]
480
+ * ```
481
+ *
482
+ * @example Text encoding
483
+ * ```typescript
484
+ * const text = "Hello World!";
485
+ * const bytes = new TextEncoder().encode(text);
486
+ * const encoded = base62.encode(bytes);
487
+ * const decoded = base62.decode(encoded);
488
+ * const result = new TextDecoder().decode(decoded);
489
+ * console.log(result); // "Hello World!"
490
+ * ```
491
+ *
492
+ * @group Binary
493
+ */
494
+ declare const base62: BaseX;
495
+
469
496
  interface BaseX {
470
497
  /**
471
498
  * Base alphabet
@@ -512,33 +539,6 @@ interface BaseX {
512
539
  */
513
540
  declare function basex(alphabet: string): BaseX;
514
541
 
515
- /**
516
- * Base62 encoder/decoder for binary data.
517
- *
518
- * @example Basic usage
519
- * ```typescript
520
- * const data = new Uint8Array([255, 128, 64]);
521
- * const encoded = base62.encode(data);
522
- * console.log(encoded);
523
- *
524
- * const decoded = base62.decode(encoded);
525
- * console.log(decoded); // Uint8Array [255, 128, 64]
526
- * ```
527
- *
528
- * @example Text encoding
529
- * ```typescript
530
- * const text = "Hello World!";
531
- * const bytes = new TextEncoder().encode(text);
532
- * const encoded = base62.encode(bytes);
533
- * const decoded = base62.decode(encoded);
534
- * const result = new TextDecoder().decode(decoded);
535
- * console.log(result); // "Hello World!"
536
- * ```
537
- *
538
- * @group Binary
539
- */
540
- declare const base62: BaseX;
541
-
542
542
  /**
543
543
  * Base62-like encoder/decoder for binary data but **super fast**. Useful for human readable tokens generation
544
544
  *
@@ -670,6 +670,11 @@ type Base64ToBytesOptions = {
670
670
  * Whether to enforce strict Base64 decoding.
671
671
  */
672
672
  strict?: boolean;
673
+ /**
674
+ * Prefer to use native `Uint8Array.fromBase64` and `Uint8Array.fromBase64` when possible
675
+ * @default true
676
+ */
677
+ native?: boolean;
673
678
  };
674
679
  /**
675
680
  * Decodes a Base64 or Base64URL encoded string into a `Uint8Array`.
@@ -700,7 +705,7 @@ type Base64ToBytesOptions = {
700
705
  *
701
706
  * @group Binary
702
707
  */
703
- declare function base64ToBytes(data: string, { encoding, strict }?: Base64ToBytesOptions): Uint8Array;
708
+ declare function base64ToBytes(data: string, { encoding, strict, native }?: Base64ToBytesOptions): Uint8Array;
704
709
 
705
710
  /**
706
711
  * Converts a `bigint` value into a byte array (`Uint8Array`) in big-endian order.
@@ -947,7 +952,7 @@ interface Logger {
947
952
  error: (...args: unknown[]) => void;
948
953
  debug: (...args: unknown[]) => void;
949
954
  log: (...args: unknown[]) => void;
950
- extend: (...args: unknown[]) => void;
955
+ extend: (...args: unknown[]) => Logger;
951
956
  }
952
957
 
953
958
  declare namespace BitPack {
@@ -992,6 +997,31 @@ type Plan = {
992
997
  value?: unknown;
993
998
  child?: Plan;
994
999
  };
1000
+ /**
1001
+ * Define compact packed structure
1002
+ * @group Binary
1003
+ *
1004
+ * @example
1005
+ * ```typescript
1006
+ * const snowflake = bitPack({
1007
+ * totalBits: 64,
1008
+ * fields: [
1009
+ * { name: 'timestamp', bits: 42, take: 'low' },
1010
+ * { name: 'workerId', bits: 5, take: 'low' },
1011
+ * { name: 'processId', bits: 5, take: 'low' },
1012
+ * { name: 'increment', bits: 12, take: 'low' },
1013
+ * ],
1014
+ * optimize: true,
1015
+ * });
1016
+ *
1017
+ * const userId = snowflake.bigint({
1018
+ * timestamp: 1781295314562,
1019
+ * workerId: 1,
1020
+ * processId: 0,
1021
+ * increment: 0
1022
+ * }); // 7471294063048785920n
1023
+ * ```
1024
+ */
995
1025
  declare function bitPack<const TFields extends BitPack.Field[], TFieldNames extends string = BitPack.ExtractFieldNames<TFields>>(options: BitPack.Options<TFields>): BitPack.API<TFieldNames>;
996
1026
 
997
1027
  declare namespace BitUnpack {
@@ -1024,6 +1054,27 @@ declare namespace BitUnpack {
1024
1054
  [P in T]: number;
1025
1055
  };
1026
1056
  }
1057
+ /**
1058
+ * Define compact unpacked structure
1059
+ * @group Binary
1060
+ *
1061
+ * @example
1062
+ * ```typescript
1063
+ * const snowflake = bitUnpack({
1064
+ * totalBits: 64,
1065
+ * fields: [
1066
+ * { name: 'timestamp', bits: 42, take: 'low' },
1067
+ * { name: 'workerId', bits: 5, take: 'low' },
1068
+ * { name: 'processId', bits: 5, take: 'low' },
1069
+ * { name: 'increment', bits: 12, take: 'low' },
1070
+ * ],
1071
+ * });
1072
+ *
1073
+ * console.log(
1074
+ * snowflake.bigint(7471294063048785920n)
1075
+ * ); // { timestamp: 1781295314562, workerId: 1, processId: 0, increment: 0 }
1076
+ * ```
1077
+ */
1027
1078
  declare function bitUnpack<const TFields extends BitUnpack.Field[], TFieldNames extends string = BitUnpack.ExtractFieldNames<TFields>>(options: BitUnpack.Options<TFields>): BitUnpack.API<TFieldNames>;
1028
1079
 
1029
1080
  type BytesToBase64Options = {
@@ -1035,6 +1086,11 @@ type BytesToBase64Options = {
1035
1086
  * Whether or not to include padding (`=`) in the encoded result. Defaults to `true` for Base64, `false` for Base64URL.
1036
1087
  */
1037
1088
  padding?: boolean;
1089
+ /**
1090
+ * Prefer to use native `Uint8Array.toBase64` and `Uint8Array.toBase64` when possible
1091
+ * @default true
1092
+ */
1093
+ native?: boolean;
1038
1094
  };
1039
1095
  /**
1040
1096
  * Encodes a byte array (`Uint8Array`) into a Base64 or Base64URL encoded string.
@@ -1074,7 +1130,7 @@ type BytesToBase64Options = {
1074
1130
  *
1075
1131
  * @group Binary
1076
1132
  */
1077
- declare function bytesToBase64(data: Uint8Array, { encoding, padding }?: BytesToBase64Options): string;
1133
+ declare function bytesToBase64(data: Uint8Array, { encoding, padding, native }?: BytesToBase64Options): string;
1078
1134
 
1079
1135
  /**
1080
1136
  * Compares two `Uint8Array` instances to check if their contents are identical.
@@ -2810,19 +2866,19 @@ interface EnvParser {
2810
2866
  /**
2811
2867
  * NODE_ENV is `development`
2812
2868
  */
2813
- isDevelopment: boolean;
2869
+ readonly isDevelopment: boolean;
2814
2870
  /**
2815
2871
  * NODE_ENV is `production`
2816
2872
  */
2817
- isProduction: boolean;
2873
+ readonly isProduction: boolean;
2818
2874
  /**
2819
2875
  * NODE_ENV is `stage`
2820
2876
  */
2821
- isStage: boolean;
2877
+ readonly isStage: boolean;
2822
2878
  /**
2823
2879
  * NODE_ENV is `test`
2824
2880
  */
2825
- isTest: boolean;
2881
+ readonly isTest: boolean;
2826
2882
  /**
2827
2883
  * Returns `true` when environment key has set to `"true"`
2828
2884
  *
@@ -3487,7 +3543,12 @@ type LogLevel = Exclude<keyof Logger, 'extend'>;
3487
3543
  * Set global log level.
3488
3544
  * @group Utility Functions
3489
3545
  */
3490
- declare const loggerSetLevel: (level: LogLevel) => void;
3546
+ declare const setLoggerLevel: (level: LogLevel) => void;
3547
+ /**
3548
+ * Set global log level.
3549
+ * @group Utility Functions
3550
+ */
3551
+ declare const getLoggerLevel: () => LogLevel;
3491
3552
  /**
3492
3553
  * Create pretty simple `console.log` wrapper interface.
3493
3554
  *
@@ -5199,6 +5260,78 @@ declare class ResourcePool<T = unknown> extends SimpleEventEmitter<ResourcePoolE
5199
5260
  private resolveDestroyQueue;
5200
5261
  }
5201
5262
 
5263
+ declare const SCHEDULER_JOB_FLAGS: {
5264
+ readonly QUEUED: number;
5265
+ readonly ALLOW_RECURSE: number;
5266
+ readonly DISPOSED: number;
5267
+ };
5268
+ /**
5269
+ * Creates a microtask scheduler that batches jobs and flushes them in
5270
+ * priority order on the next tick.
5271
+ *
5272
+ * Jobs are functions queued via {@link Scheduler.queueJob}. Each job may carry
5273
+ * an optional numeric `id` used to order the queue — lower `id` runs first,
5274
+ * and jobs without an `id` run last. Re-queueing the same job within an
5275
+ * active flush cycle is a no-op unless `SCHEDULER_JOB_FLAGS.ALLOW_RECURSE`
5276
+ * is set on the job. Use {@link Scheduler.queueJobWait} when you need to
5277
+ * await a job's result through a {@link CancellablePromise}, and the
5278
+ * `onJob` / `onJobStart` / `onJobComplete` hooks to observe lifecycle.
5279
+ *
5280
+ * @example
5281
+ * ```typescript
5282
+ * const scheduler = createScheduler();
5283
+ *
5284
+ * const log = (msg: string) => () => console.log(msg);
5285
+ *
5286
+ * const first = log('first');
5287
+ * first.id = 1;
5288
+ * const second = log('second');
5289
+ * second.id = 2;
5290
+ *
5291
+ * scheduler.queueJob(second);
5292
+ * scheduler.queueJob(first);
5293
+ *
5294
+ * scheduler.nextTick().then(() => console.log('flushed'));
5295
+ * // → first
5296
+ * // → second
5297
+ * // → flushed
5298
+ * ```
5299
+ *
5300
+ * @group Promise
5301
+ */
5302
+ declare function createScheduler(): Scheduler;
5303
+ declare namespace Scheduler {
5304
+ type Job<T = any> = (() => T) & JobOptions;
5305
+ type JobOptions = {
5306
+ id?: number;
5307
+ /**
5308
+ * flags can technically be undefined, but it can still be used in bitwise
5309
+ * operations just like 0.
5310
+ */
5311
+ flags?: number;
5312
+ jobName?: string;
5313
+ };
5314
+ }
5315
+ declare class Scheduler {
5316
+ protected queue: Scheduler.Job[];
5317
+ protected flushIndex: number;
5318
+ protected resolvedPromise: Promise<any>;
5319
+ protected currentFlushPromise: Promise<void> | null;
5320
+ protected onJobCbs: ((job: Scheduler.JobOptions) => void)[];
5321
+ protected onJobStartCbs: ((job: Scheduler.JobOptions) => void)[];
5322
+ protected onJobCompleteCbs: ((job: Scheduler.JobOptions) => void)[];
5323
+ constructor();
5324
+ onJob(fn: (job: Scheduler.JobOptions) => void): void;
5325
+ onJobStart(fn: (job: Scheduler.JobOptions) => void): void;
5326
+ onJobComplete(fn: (job: Scheduler.JobOptions) => void): void;
5327
+ nextTick(fn?: () => void): Promise<void>;
5328
+ queueJob<T>(job: Scheduler.Job<T>, opts?: Scheduler.JobOptions): void;
5329
+ queueJobWait<T>(job: Scheduler.Job<T>, opts?: Scheduler.JobOptions): CancellablePromise<Awaited<T>>;
5330
+ protected findInsertionIndex(id: number): number;
5331
+ protected flushJobs(): Promise<void>;
5332
+ protected queueFlush(): void;
5333
+ }
5334
+
5202
5335
  /**
5203
5336
  * Throws an error if the provided promise or callback is not resolved within the specified timeout period.
5204
5337
  *
@@ -5848,4 +5981,4 @@ declare function wrapText(value: string, maxLength?: number): string;
5848
5981
  */
5849
5982
  declare function toError<T>(value: T, unknownMessage?: string): T extends Error ? T : Error;
5850
5983
 
5851
- export { type AnyFunction, AppError, type AppErrorOptions, type ArgumentsType, type Arrayable, AssertionError, AsyncIterableQueue, type Awaitable, type Base64ToBytesOptions, type BaseX, BitPack, BitUnpack, type BytesToBase64Options, CancellablePromise, type CatchErrorResult, Color, type ColorChannels, ColorParser, type Data, type DateObject, type DateObjectInput, type DebouncedFunction, type DeepPartial, type DeepReadonly, type Defer, instance as EJSON, EJSON as EJSONInstance, EJSONStream, type EJSONStreamOptions, type EJSONStreamOptionsWithPayload, type EJSONType, type EnvParser, type ExecResult, type ExecResultToSkip, type ExecResultToSuccess, type ExecSkip, type ExecSuccess, FindMean, FixedMap, FixedWeakMap, Fn, type FormatMoney, type FormatNumber, type FunctionArgs, type GenericObject, type IfAny, type IsAny, type LiteralUnion, type Logger, LruCache, type Nothing, type OverwriteWith, type Prettify, type Primitive, type PromisifyFn, Queue, type RandomizerOptions, ResourcePool, type ResourcePoolEventMap, type ResourcePoolOptions, type RetryOnErrorConfig, type SecureCustomizerOptions, type SelectOptionItem, type SelectOptions, type SimpleDefaultEventMap, SimpleEventEmitter, type SimpleEventMap, SortedArray, type SortedArrayCompareFn, _default as TWEMOJI_REGEX, type ThemeConfig, type ThrottledFunction, TimeBucket, type TimeBucketOptions, type TimeObject, type TimeObjectInput, TimeSpan, type TimeSpanUnit, type TimeString, type TimeValue, type TimestampMsInput, type TypeOf, type TypeOfMap, type ValuesOfObject, type WithCache, type WithCacheBucketBatchOptions, type WithCacheBucketOptions, type WithCacheFixedOptions, type WithCacheLruOptions, type WithCacheOptions, type WithCachePointer, type WithCacheResult, type WithCacheStorage, type WithCode, type WithCustomizer, type WithCustomizerFactory, type WithCustomizerValue, type WrrItem, alpha, arrayable, assert, asyncFilter, asyncFind, asyncForEach, asyncMap, avg, avgCircular, base62, base62Fast, base64, base64ToBytes, base64url, basex, bigIntBytes, bigIntFromBytes, bitPack, bitUnpack, 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, createFunction, 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, intersectionBy, isBigInt, isBoolean, isCached, isClient, isColorChannels, isCustomizerFactory, isDate, isDateObject, isDef, isEmpty, isEqual, isError, isFunction, isInfinity, isMap, isNode, 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, rleDecode, rleEncode, round2digits, secondsToHm, set, shuffle, snakeCase, sprintf, startCase, strAssign, sum, textDecoder, textEncoder, 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, withResolve, wrapText };
5984
+ export { type AnyFunction, AppError, type AppErrorOptions, type ArgumentsType, type Arrayable, AssertionError, AsyncIterableQueue, type Awaitable, type Base64ToBytesOptions, type BaseX, BitPack, BitUnpack, type BytesToBase64Options, CancellablePromise, type CatchErrorResult, Color, type ColorChannels, ColorParser, type Data, type DateObject, type DateObjectInput, type DebouncedFunction, type DeepPartial, type DeepReadonly, type Defer, instance as EJSON, EJSON as EJSONInstance, EJSONStream, type EJSONStreamOptions, type EJSONStreamOptionsWithPayload, type EJSONType, type EnvParser, type ExecResult, type ExecResultToSkip, type ExecResultToSuccess, type ExecSkip, type ExecSuccess, FindMean, FixedMap, FixedWeakMap, Fn, type FormatMoney, type FormatNumber, type FunctionArgs, type GenericObject, type IfAny, type IsAny, type LiteralUnion, type LogLevel, type Logger, LruCache, type Nothing, type OverwriteWith, type Prettify, type Primitive, type PromisifyFn, Queue, type RandomizerOptions, ResourcePool, type ResourcePoolEventMap, type ResourcePoolOptions, type RetryOnErrorConfig, SCHEDULER_JOB_FLAGS, Scheduler, type SecureCustomizerOptions, type SelectOptionItem, type SelectOptions, type SimpleDefaultEventMap, SimpleEventEmitter, type SimpleEventMap, SortedArray, type SortedArrayCompareFn, _default as TWEMOJI_REGEX, type ThemeConfig, type ThrottledFunction, TimeBucket, type TimeBucketOptions, type TimeObject, type TimeObjectInput, TimeSpan, type TimeSpanUnit, type TimeString, type TimeValue, type TimestampMsInput, type TypeOf, type TypeOfMap, type ValuesOfObject, type WithCache, type WithCacheBucketBatchOptions, type WithCacheBucketOptions, type WithCacheFixedOptions, type WithCacheLruOptions, type WithCacheOptions, type WithCachePointer, type WithCacheResult, type WithCacheStorage, type WithCode, type WithCustomizer, type WithCustomizerFactory, type WithCustomizerValue, type WrrItem, alpha, arrayable, assert, asyncFilter, asyncFind, asyncForEach, asyncMap, avg, avgCircular, base62, base62Fast, base64, base64ToBytes, base64url, basex, bigIntBytes, bigIntFromBytes, bitPack, bitUnpack, 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, createFunction, createRandomizer, createScheduler, 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, getLoggerLevel, getMostSpecificPaths, getRandomInt, getRandomTime, getWords, groupBy, has, hasOwn, hasProtocol, hex, hexToChannels, hmToSeconds, hslToChannels, humanFileSize, humanize, interpolateColor, intersection, intersectionBy, isBigInt, isBoolean, isCached, isClient, isColorChannels, isCustomizerFactory, isDate, isDateObject, isDef, isEmpty, isEqual, isError, isFunction, isInfinity, isMap, isNode, isNullOrUndefined, isNumber, isObject, isOneEmoji, isPlainObject, isPrimitive, isPromise, isRegExp, isSet, isSkip, isString, isSuccess, isSymbol, isTimeObject, isTimeString, isTimeValue, isValidWeekDay, isWeakMap, isWeakSet, isWithCache, isoToFlagEmoji, kebabCase, keyBy, logger, lowerCase, luminance, maskingEmail, maskingPhone, maskingWords, nextTickIteration, noop, objectId, omit, omitPrefixed, orderBy, parseAllNumbers, parseAlpha, parsePercentage, percentOf, pick, pickPrefixed, qs, rafPromise, randomString, removeVS16s, retryOnError, rgbToChannels, rleDecode, rleEncode, round2digits, secondsToHm, set, setLoggerLevel, shuffle, snakeCase, sprintf, startCase, strAssign, sum, textDecoder, textEncoder, 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, withResolve, wrapText };
package/dist/index.mjs CHANGED
@@ -1572,8 +1572,12 @@ class Base64Encoding {
1572
1572
  }
1573
1573
  this.alphabet = alphabet;
1574
1574
  this.padding = options?.padding ?? "=";
1575
- if (this.alphabet.includes(this.padding) || this.padding.length !== 1) {
1576
- throw new Error("Invalid padding");
1575
+ if (this.padding) {
1576
+ ok(
1577
+ !this.alphabet.includes(this.padding),
1578
+ "Padding cannot be a part of alphabet"
1579
+ );
1580
+ ok(this.padding.length === 1, "Padding length must be a 1");
1577
1581
  }
1578
1582
  for (let i = 0; i < alphabet.length; i++) {
1579
1583
  this.decodeMap.set(alphabet[i], i);
@@ -1592,26 +1596,24 @@ class Base64Encoding {
1592
1596
  * ```
1593
1597
  */
1594
1598
  encode(data, options) {
1599
+ const includePadding = options?.includePadding ?? true;
1595
1600
  let result = "";
1596
1601
  let buffer = 0;
1597
1602
  let shift = 0;
1598
- for (let i = 0; i < data.length; i++) {
1599
- buffer = buffer << 8 | data[i];
1603
+ for (const byte of data) {
1604
+ buffer = buffer << 8 | byte;
1600
1605
  shift += 8;
1601
1606
  while (shift >= 6) {
1602
- shift += -6;
1607
+ shift -= 6;
1603
1608
  result += this.alphabet[buffer >> shift & 63];
1604
1609
  }
1605
1610
  }
1606
1611
  if (shift > 0) {
1607
1612
  result += this.alphabet[buffer << 6 - shift & 63];
1608
1613
  }
1609
- const includePadding = options?.includePadding ?? true;
1610
- if (includePadding) {
1614
+ if (includePadding && this.padding) {
1611
1615
  const padCount = (4 - result.length % 4) % 4;
1612
- for (let i = 0; i < padCount; i++) {
1613
- result += "=";
1614
- }
1616
+ result += "=".repeat(padCount);
1615
1617
  }
1616
1618
  return result;
1617
1619
  }
@@ -1630,39 +1632,23 @@ class Base64Encoding {
1630
1632
  */
1631
1633
  decode(data, options) {
1632
1634
  const strict = options?.strict ?? true;
1633
- const chunkCount = Math.ceil(data.length / 4);
1634
1635
  const result = [];
1635
- for (let i = 0; i < chunkCount; i++) {
1636
- let padCount = 0;
1637
- let buffer = 0;
1638
- for (let j = 0; j < 4; j++) {
1639
- const encoded = data[i * 4 + j];
1640
- if (encoded === "=") {
1641
- if (i + 1 !== chunkCount) {
1642
- throw new Error(`Invalid character: ${encoded}`);
1643
- }
1644
- padCount += 1;
1645
- continue;
1646
- }
1647
- if (encoded === void 0) {
1648
- if (strict) {
1649
- throw new Error("Invalid data");
1650
- }
1651
- padCount += 1;
1652
- continue;
1653
- }
1654
- const value = this.decodeMap.get(encoded) ?? null;
1655
- if (value === null) {
1656
- throw new Error(`Invalid character: ${encoded}`);
1657
- }
1658
- buffer += value << 6 * (3 - j);
1659
- }
1660
- result.push(buffer >> 16 & 255);
1661
- if (padCount < 2) {
1662
- result.push(buffer >> 8 & 255);
1636
+ let buffer = 0;
1637
+ let bitsCollected = 0;
1638
+ if (this.padding && strict) {
1639
+ ok(data.length % 4 === 0, "Invalid Base64 data");
1640
+ }
1641
+ for (const char of data) {
1642
+ if (char === this.padding) break;
1643
+ const value = this.decodeMap.get(char);
1644
+ if (value === void 0) {
1645
+ throw new Error(`Invalid Base64 character: ${char}`);
1663
1646
  }
1664
- if (padCount < 1) {
1665
- result.push(buffer & 255);
1647
+ buffer = buffer << 6 | value;
1648
+ bitsCollected += 6;
1649
+ if (bitsCollected >= 8) {
1650
+ bitsCollected -= 8;
1651
+ result.push(buffer >> bitsCollected & 255);
1666
1652
  }
1667
1653
  }
1668
1654
  return Uint8Array.from(result);
@@ -1676,10 +1662,22 @@ const base64url = new Base64Encoding(
1676
1662
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
1677
1663
  );
1678
1664
 
1679
- function base64ToBytes(data, { encoding = "base64", strict } = {}) {
1665
+ function base64ToBytes(data, { encoding = "base64", strict, native = true } = {}) {
1680
1666
  if (encoding === "base64") {
1667
+ if (native && isFunction(Uint8Array.fromBase64)) {
1668
+ return Uint8Array.fromBase64(data, {
1669
+ alphabet: "base64",
1670
+ lastChunkHandling: strict ?? true ? "strict" : "loose"
1671
+ });
1672
+ }
1681
1673
  return base64.decode(data, { strict: strict ?? true });
1682
1674
  } else if (encoding === "base64url") {
1675
+ if (native && isFunction(Uint8Array.fromBase64)) {
1676
+ return Uint8Array.fromBase64(data, {
1677
+ alphabet: "base64url",
1678
+ lastChunkHandling: strict ?? false ? "strict" : "loose"
1679
+ });
1680
+ }
1683
1681
  return base64url.decode(data, { strict: strict ?? false });
1684
1682
  }
1685
1683
  ok(false, "Invalid encoding options: " + encoding);
@@ -2143,10 +2141,22 @@ function buildFieldsInfo(fields, totalBits) {
2143
2141
  return result;
2144
2142
  }
2145
2143
 
2146
- function bytesToBase64(data, { encoding = "base64", padding } = {}) {
2144
+ function bytesToBase64(data, { encoding = "base64", padding, native = true } = {}) {
2147
2145
  if (encoding === "base64") {
2146
+ if (native && isFunction(data.toBase64)) {
2147
+ return data.toBase64({
2148
+ alphabet: "base64",
2149
+ omitPadding: !(padding ?? true)
2150
+ });
2151
+ }
2148
2152
  return base64.encode(data, { includePadding: padding ?? true });
2149
2153
  } else if (encoding === "base64url") {
2154
+ if (native && isFunction(data.toBase64)) {
2155
+ return data.toBase64({
2156
+ alphabet: "base64url",
2157
+ omitPadding: !(padding ?? false)
2158
+ });
2159
+ }
2150
2160
  return base64url.encode(data, { includePadding: padding ?? false });
2151
2161
  }
2152
2162
  ok(false, "Invalid encoding options: " + encoding);
@@ -4587,10 +4597,18 @@ const env = (() => {
4587
4597
  })();
4588
4598
  function createEnvParser(targetObject) {
4589
4599
  return Object.freeze({
4590
- isDevelopment: targetObject.NODE_ENV === "development",
4591
- isProduction: targetObject.NODE_ENV === "production",
4592
- isStage: targetObject.NODE_ENV === "state",
4593
- isTest: targetObject.NODE_ENV === "test",
4600
+ get isDevelopment() {
4601
+ return targetObject.NODE_ENV === "development";
4602
+ },
4603
+ get isProduction() {
4604
+ return targetObject.NODE_ENV === "production";
4605
+ },
4606
+ get isStage() {
4607
+ return targetObject.NODE_ENV === "state";
4608
+ },
4609
+ get isTest() {
4610
+ return targetObject.NODE_ENV === "test";
4611
+ },
4594
4612
  bool(key, defaultValue = false) {
4595
4613
  if (!(key in targetObject)) {
4596
4614
  return defaultValue;
@@ -5197,17 +5215,28 @@ function throttle(func, throttleMs, { signal, edges = ["leading", "trailing"] }
5197
5215
  return throttled;
5198
5216
  }
5199
5217
 
5200
- const LEVEL_NUM = {
5218
+ const LEVEL_NAME_TO_NUM = {
5201
5219
  debug: 0,
5202
5220
  log: 1,
5203
5221
  info: 2,
5204
5222
  warn: 3,
5205
5223
  error: 4
5206
5224
  };
5207
- let currentLogLevel = LEVEL_NUM.log;
5208
- const loggerSetLevel = (level) => {
5209
- number$1(LEVEL_NUM[level], `Invalid log level: ${level}`);
5210
- currentLogLevel = LEVEL_NUM[level];
5225
+ const LEVEL_NUM_TO_NAME = {
5226
+ 0: "debug",
5227
+ 1: "log",
5228
+ 2: "info",
5229
+ 3: "warn",
5230
+ 4: "error"
5231
+ };
5232
+ const LOG_LEVEL = env.string("LOG_LEVEL", "info");
5233
+ let currentLogLevel = LOG_LEVEL in LEVEL_NAME_TO_NUM ? LEVEL_NAME_TO_NUM[LOG_LEVEL] : LEVEL_NAME_TO_NUM.log;
5234
+ const setLoggerLevel = (level) => {
5235
+ number$1(LEVEL_NAME_TO_NUM[level], `Invalid log level: ${level}`);
5236
+ currentLogLevel = LEVEL_NAME_TO_NUM[level];
5237
+ };
5238
+ const getLoggerLevel = () => {
5239
+ return LEVEL_NUM_TO_NAME[currentLogLevel];
5211
5240
  };
5212
5241
  const logger = (...baseArgs) => {
5213
5242
  if (isString(baseArgs[0]?.url)) {
@@ -5217,7 +5246,7 @@ const logger = (...baseArgs) => {
5217
5246
  baseArgs[0] = `[${baseArgs[0].split("/").at(-1).split("?", 1)[0]}]`;
5218
5247
  }
5219
5248
  const writeLog = (level, ...[pattern, ...args]) => {
5220
- const levelNum = LEVEL_NUM[level];
5249
+ const levelNum = LEVEL_NAME_TO_NUM[level];
5221
5250
  if (levelNum < currentLogLevel) {
5222
5251
  return;
5223
5252
  }
@@ -5945,6 +5974,135 @@ class ResourcePool extends SimpleEventEmitter {
5945
5974
  }
5946
5975
  }
5947
5976
 
5977
+ const SCHEDULER_JOB_FLAGS = {
5978
+ QUEUED: 1 << 0,
5979
+ ALLOW_RECURSE: 1 << 2,
5980
+ DISPOSED: 1 << 3
5981
+ };
5982
+ function createScheduler() {
5983
+ return new Scheduler();
5984
+ }
5985
+ class Scheduler {
5986
+ queue = [];
5987
+ flushIndex = -1;
5988
+ resolvedPromise = Promise.resolve();
5989
+ currentFlushPromise = null;
5990
+ onJobCbs = [];
5991
+ onJobStartCbs = [];
5992
+ onJobCompleteCbs = [];
5993
+ constructor() {
5994
+ for (const methodName of Object.getOwnPropertyNames(
5995
+ Object.getPrototypeOf(this)
5996
+ )) {
5997
+ this[methodName] = this[methodName].bind(this);
5998
+ }
5999
+ }
6000
+ onJob(fn) {
6001
+ this.onJobCbs.push(fn);
6002
+ }
6003
+ onJobStart(fn) {
6004
+ this.onJobStartCbs.push(fn);
6005
+ }
6006
+ onJobComplete(fn) {
6007
+ this.onJobCompleteCbs.push(fn);
6008
+ }
6009
+ nextTick(fn) {
6010
+ const p = this.currentFlushPromise || this.resolvedPromise;
6011
+ return fn ? p.then(this ? fn.bind(this) : fn) : p;
6012
+ }
6013
+ queueJob(job, opts) {
6014
+ if (opts) {
6015
+ Object.assign(job, opts);
6016
+ }
6017
+ if (!(job.flags & SCHEDULER_JOB_FLAGS.QUEUED)) {
6018
+ const jobId = getId(job);
6019
+ const lastJob = this.queue[this.queue.length - 1];
6020
+ if (!lastJob || jobId >= getId(lastJob)) {
6021
+ this.queue.push(job);
6022
+ } else {
6023
+ this.queue.splice(this.findInsertionIndex(jobId), 0, job);
6024
+ }
6025
+ job.flags |= SCHEDULER_JOB_FLAGS.QUEUED;
6026
+ this.queueFlush();
6027
+ for (const hookFn of this.onJobCbs) {
6028
+ hookFn(job);
6029
+ }
6030
+ }
6031
+ }
6032
+ queueJobWait(job, opts) {
6033
+ return new CancellablePromise((resolve, reject, onCancel) => {
6034
+ onCancel(() => {
6035
+ job.flags |= SCHEDULER_JOB_FLAGS.DISPOSED;
6036
+ reject(new Error("Canceled"));
6037
+ });
6038
+ const fn = () => {
6039
+ return Promise.resolve().then(() => job()).then(resolve).catch(reject);
6040
+ };
6041
+ fn.id = job.id;
6042
+ fn.flags = job.flags;
6043
+ this.queueJob(fn, opts);
6044
+ });
6045
+ }
6046
+ findInsertionIndex(id) {
6047
+ let start = this.flushIndex + 1;
6048
+ let end = this.queue.length;
6049
+ while (start < end) {
6050
+ const middle = start + end >>> 1;
6051
+ const middleJob = this.queue[middle];
6052
+ const middleJobId = getId(middleJob);
6053
+ if (middleJobId < id) {
6054
+ start = middle + 1;
6055
+ } else {
6056
+ end = middle;
6057
+ }
6058
+ }
6059
+ return start;
6060
+ }
6061
+ async flushJobs() {
6062
+ try {
6063
+ for (this.flushIndex = 0; this.flushIndex < this.queue.length; this.flushIndex++) {
6064
+ const job = this.queue[this.flushIndex];
6065
+ if (job && !(job.flags & SCHEDULER_JOB_FLAGS.DISPOSED)) {
6066
+ if (job.flags & SCHEDULER_JOB_FLAGS.ALLOW_RECURSE) {
6067
+ job.flags &= ~SCHEDULER_JOB_FLAGS.QUEUED;
6068
+ }
6069
+ for (const hookFn of this.onJobStartCbs) {
6070
+ hookFn(job);
6071
+ }
6072
+ await job();
6073
+ for (const hookFn of this.onJobCompleteCbs) {
6074
+ hookFn(job);
6075
+ }
6076
+ if (!(job.flags & SCHEDULER_JOB_FLAGS.ALLOW_RECURSE)) {
6077
+ job.flags &= ~SCHEDULER_JOB_FLAGS.QUEUED;
6078
+ }
6079
+ }
6080
+ }
6081
+ } finally {
6082
+ for (; this.flushIndex < this.queue.length; this.flushIndex++) {
6083
+ const job = this.queue[this.flushIndex];
6084
+ if (job) {
6085
+ job.flags &= ~SCHEDULER_JOB_FLAGS.QUEUED;
6086
+ }
6087
+ }
6088
+ this.flushIndex = -1;
6089
+ this.queue.length = 0;
6090
+ this.currentFlushPromise = null;
6091
+ if (this.queue.length) {
6092
+ return this.flushJobs();
6093
+ }
6094
+ }
6095
+ }
6096
+ queueFlush() {
6097
+ if (!this.currentFlushPromise) {
6098
+ this.currentFlushPromise = this.resolvedPromise.then(this.flushJobs);
6099
+ }
6100
+ }
6101
+ }
6102
+ function getId(job) {
6103
+ return job.id == null ? Infinity : job.id;
6104
+ }
6105
+
5948
6106
  function timeout(ms, promiseOrCallback, timeoutError = new AppError(408)) {
5949
6107
  const abortController = new AbortController();
5950
6108
  let taskResult;
@@ -6029,5 +6187,5 @@ function withResolve(fn, getCacheKey) {
6029
6187
  }
6030
6188
  }
6031
6189
 
6032
- export { AppError, AssertionError, AsyncIterableQueue, CancellablePromise, ColorParser, instance as EJSON, EJSON as EJSONInstance, EJSONStream, FindMean, FixedMap, FixedWeakMap, LruCache, Queue, ResourcePool, SimpleEventEmitter, SortedArray, TWEMOJI_REGEX, TimeBucket, TimeSpan, alpha, arrayable, assert, asyncFilter, asyncFind, asyncForEach, asyncMap, avg, avgCircular, base62, base62Fast, base64, base64ToBytes, base64url, basex, bigIntBytes, bigIntFromBytes, bitPack, bitUnpack, 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, createFunction, 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, intersectionBy, isBigInt, isBoolean, isCached, isClient, isColorChannels, isCustomizerFactory, isDate, isDateObject, isDef, isEmpty, isEqual, isError, isFunction, isInfinity, isMap, isNode, 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, rleDecode, rleEncode, round2digits, secondsToHm, set, shuffle, snakeCase, sprintf, startCase, strAssign, sum, textDecoder, textEncoder, 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, withResolve, wrapText };
6190
+ export { AppError, AssertionError, AsyncIterableQueue, CancellablePromise, ColorParser, instance as EJSON, EJSON as EJSONInstance, EJSONStream, FindMean, FixedMap, FixedWeakMap, LruCache, Queue, ResourcePool, SCHEDULER_JOB_FLAGS, Scheduler, SimpleEventEmitter, SortedArray, TWEMOJI_REGEX, TimeBucket, TimeSpan, alpha, arrayable, assert, asyncFilter, asyncFind, asyncForEach, asyncMap, avg, avgCircular, base62, base62Fast, base64, base64ToBytes, base64url, basex, bigIntBytes, bigIntFromBytes, bitPack, bitUnpack, 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, createFunction, createRandomizer, createScheduler, 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, getLoggerLevel, getMostSpecificPaths, getRandomInt, getRandomTime, getWords, groupBy, has, hasOwn, hasProtocol, hex, hexToChannels, hmToSeconds, hslToChannels, humanFileSize, humanize, interpolateColor, intersection, intersectionBy, isBigInt, isBoolean, isCached, isClient, isColorChannels, isCustomizerFactory, isDate, isDateObject, isDef, isEmpty, isEqual, isError, isFunction, isInfinity, isMap, isNode, isNullOrUndefined, isNumber, isObject, isOneEmoji, isPlainObject, isPrimitive, isPromise, isRegExp, isSet, isSkip, isString, isSuccess, isSymbol, isTimeObject, isTimeString, isTimeValue, isValidWeekDay, isWeakMap, isWeakSet, isWithCache, isoToFlagEmoji, kebabCase, keyBy, logger, lowerCase, luminance, maskingEmail, maskingPhone, maskingWords, nextTickIteration, noop, objectId, omit, omitPrefixed, orderBy, parseAllNumbers, parseAlpha, parsePercentage, percentOf, pick, pickPrefixed, qs, rafPromise, randomString, removeVS16s, retryOnError, rgbToChannels, rleDecode, rleEncode, round2digits, secondsToHm, set, setLoggerLevel, shuffle, snakeCase, sprintf, startCase, strAssign, sum, textDecoder, textEncoder, 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, withResolve, wrapText };
6033
6191
  //# sourceMappingURL=index.mjs.map