prettier 3.8.5 → 3.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,7 +18,11 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
18
18
  throw Error('Dynamic require of "' + x + '" is not supported');
19
19
  });
20
20
  var __commonJS = (cb, mod) => function __require2() {
21
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
21
+ try {
22
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
23
+ } catch (e) {
24
+ throw mod = 0, e;
25
+ }
22
26
  };
23
27
  var __copyProps = (to, from, except, desc) => {
24
28
  if (from && typeof from === "object" || typeof from === "function") {
@@ -368,6 +372,11 @@ var require_vendors = __commonJS({
368
372
  env: "AGOLA_GIT_REF",
369
373
  pr: "AGOLA_PULL_REQUEST_ID"
370
374
  },
375
+ {
376
+ name: "Alpic",
377
+ constant: "ALPIC",
378
+ env: "ALPIC_HOST"
379
+ },
371
380
  {
372
381
  name: "Appcircle",
373
382
  constant: "APPCIRCLE",
@@ -820,7 +829,7 @@ var createMethodShim = (methodName, getImplementation) => (flags, object2, ...ar
820
829
  function stringOrArrayAt(index) {
821
830
  return this[index < 0 ? this.length + index : index];
822
831
  }
823
- var at = createMethodShim("at", function() {
832
+ var at = /* @__PURE__ */ createMethodShim("at", function() {
824
833
  if (Array.isArray(this) || typeof this === "string") {
825
834
  return stringOrArrayAt;
826
835
  }
@@ -1083,7 +1092,7 @@ var stringReplaceAll = String.prototype.replaceAll ?? function(pattern, replacem
1083
1092
  }
1084
1093
  return this.split(pattern).join(replacement);
1085
1094
  };
1086
- var replaceAll = createMethodShim("replaceAll", function() {
1095
+ var replaceAll = /* @__PURE__ */ createMethodShim("replaceAll", function() {
1087
1096
  if (typeof this === "string") {
1088
1097
  return stringReplaceAll;
1089
1098
  }
@@ -1233,34 +1242,97 @@ function camelCase(input, options) {
1233
1242
  import fs from "fs/promises";
1234
1243
  import path from "path";
1235
1244
 
1236
- // node_modules/sdbm/index.js
1237
- var textEncoder = new TextEncoder();
1238
- function sdbmHash(input, options) {
1239
- if (typeof input === "string") {
1240
- if (options?.bytes) {
1241
- input = textEncoder.encode(input);
1242
- } else {
1243
- let hash3 = 0n;
1244
- for (let index = 0; index < input.length; index++) {
1245
- hash3 = BigInt(input.charCodeAt(index)) + (hash3 << 6n) + (hash3 << 16n) - hash3;
1246
- }
1247
- return hash3;
1245
+ // node_modules/imurmurhash-esm/index.js
1246
+ var cache;
1247
+ function MurmurHash3(key, seed) {
1248
+ var m = this;
1249
+ if (!(this instanceof MurmurHash3)) {
1250
+ if (!cache) {
1251
+ cache ?? (cache = new MurmurHash3());
1248
1252
  }
1249
- } else if (!(input instanceof Uint8Array)) {
1250
- throw new TypeError("Expected a string or Uint8Array");
1253
+ m = cache;
1251
1254
  }
1252
- let hash2 = 0n;
1253
- for (const byte of input) {
1254
- hash2 = BigInt(byte) + (hash2 << 6n) + (hash2 << 16n) - hash2;
1255
+ m.reset(seed);
1256
+ if (typeof key === "string" && key.length > 0) {
1257
+ m.hash(key);
1258
+ }
1259
+ if (m !== this) {
1260
+ return m;
1255
1261
  }
1256
- return hash2;
1257
- }
1258
- function sdbm(input, options) {
1259
- return Number(BigInt.asUintN(32, sdbmHash(input, options)));
1260
1262
  }
1261
- sdbm.bigint = function(input, options) {
1262
- return BigInt.asUintN(64, sdbmHash(input, options));
1263
+ MurmurHash3.prototype.hash = function(key) {
1264
+ var h1, k1, i, top, len;
1265
+ len = key.length;
1266
+ this.len += len;
1267
+ k1 = this.k1;
1268
+ i = 0;
1269
+ switch (this.rem) {
1270
+ case 0:
1271
+ k1 ^= len > i ? key.charCodeAt(i++) & 65535 : 0;
1272
+ case 1:
1273
+ k1 ^= len > i ? (key.charCodeAt(i++) & 65535) << 8 : 0;
1274
+ case 2:
1275
+ k1 ^= len > i ? (key.charCodeAt(i++) & 65535) << 16 : 0;
1276
+ case 3:
1277
+ k1 ^= len > i ? (key.charCodeAt(i) & 255) << 24 : 0;
1278
+ k1 ^= len > i ? (key.charCodeAt(i++) & 65280) >> 8 : 0;
1279
+ }
1280
+ this.rem = len + this.rem & 3;
1281
+ len -= this.rem;
1282
+ if (len > 0) {
1283
+ h1 = this.h1;
1284
+ while (1) {
1285
+ k1 = k1 * 11601 + (k1 & 65535) * 3432906752 & 4294967295;
1286
+ k1 = k1 << 15 | k1 >>> 17;
1287
+ k1 = k1 * 13715 + (k1 & 65535) * 461832192 & 4294967295;
1288
+ h1 ^= k1;
1289
+ h1 = h1 << 13 | h1 >>> 19;
1290
+ h1 = h1 * 5 + 3864292196 & 4294967295;
1291
+ if (i >= len) {
1292
+ break;
1293
+ }
1294
+ k1 = key.charCodeAt(i++) & 65535 ^ (key.charCodeAt(i++) & 65535) << 8 ^ (key.charCodeAt(i++) & 65535) << 16;
1295
+ top = key.charCodeAt(i++);
1296
+ k1 ^= (top & 255) << 24 ^ (top & 65280) >> 8;
1297
+ }
1298
+ k1 = 0;
1299
+ switch (this.rem) {
1300
+ case 3:
1301
+ k1 ^= (key.charCodeAt(i + 2) & 65535) << 16;
1302
+ case 2:
1303
+ k1 ^= (key.charCodeAt(i + 1) & 65535) << 8;
1304
+ case 1:
1305
+ k1 ^= key.charCodeAt(i) & 65535;
1306
+ }
1307
+ this.h1 = h1;
1308
+ }
1309
+ this.k1 = k1;
1310
+ return this;
1263
1311
  };
1312
+ MurmurHash3.prototype.result = function() {
1313
+ var k1, h1;
1314
+ k1 = this.k1;
1315
+ h1 = this.h1;
1316
+ if (k1 > 0) {
1317
+ k1 = k1 * 11601 + (k1 & 65535) * 3432906752 & 4294967295;
1318
+ k1 = k1 << 15 | k1 >>> 17;
1319
+ k1 = k1 * 13715 + (k1 & 65535) * 461832192 & 4294967295;
1320
+ h1 ^= k1;
1321
+ }
1322
+ h1 ^= this.len;
1323
+ h1 ^= h1 >>> 16;
1324
+ h1 = h1 * 51819 + (h1 & 65535) * 2246770688 & 4294967295;
1325
+ h1 ^= h1 >>> 13;
1326
+ h1 = h1 * 44597 + (h1 & 65535) * 3266445312 & 4294967295;
1327
+ h1 ^= h1 >>> 16;
1328
+ return h1 >>> 0;
1329
+ };
1330
+ MurmurHash3.prototype.reset = function(seed) {
1331
+ this.h1 = typeof seed === "number" ? seed : 0;
1332
+ this.rem = this.k1 = this.len = 0;
1333
+ return this;
1334
+ };
1335
+ var imurmurhash_esm_default = MurmurHash3;
1264
1336
 
1265
1337
  // src/cli/utilities.js
1266
1338
  import { __internal as sharedWithCli2 } from "../index.mjs";
@@ -1281,8 +1353,8 @@ function pick(object2, keys2) {
1281
1353
  const entries = keys2.map((key) => [key, object2[key]]);
1282
1354
  return Object.fromEntries(entries);
1283
1355
  }
1284
- function createHash(source) {
1285
- return String(sdbm(source));
1356
+ function createHash(string) {
1357
+ return imurmurhash_esm_default(string).result().toString(36);
1286
1358
  }
1287
1359
  async function statSafe(filePath) {
1288
1360
  try {
@@ -1318,13 +1390,14 @@ var normalizeToPosix = path.sep === "\\" ? (filepath) => method_replace_all_defa
1318
1390
  "/"
1319
1391
  ) : (filepath) => filepath;
1320
1392
  var {
1321
- omit
1393
+ omit,
1394
+ getOrInsertComputed
1322
1395
  } = sharedWithCli2.utilities;
1323
1396
 
1324
1397
  // src/cli/options/create-minimist-options.js
1325
1398
  function createMinimistOptions(detailedOptions) {
1326
1399
  const booleanNames = [];
1327
- const stringNames = [];
1400
+ const stringNames = ["_"];
1328
1401
  const defaultValues = {};
1329
1402
  for (const option of detailedOptions) {
1330
1403
  const { name, alias, type } = option;
@@ -1426,7 +1499,7 @@ function parseArgv(rawArguments, detailedOptions, logger, keys2) {
1426
1499
  return [option.forwardToApi || camelCase(key), value];
1427
1500
  })
1428
1501
  ),
1429
- _: normalized._?.map(String),
1502
+ _: normalized._,
1430
1503
  get __raw() {
1431
1504
  return argv2;
1432
1505
  }
@@ -1503,7 +1576,7 @@ var Context = class {
1503
1576
  const {
1504
1577
  PRETTIER_PERF_REPEAT
1505
1578
  } = process.env;
1506
- if (PRETTIER_PERF_REPEAT && /^\d+$/u.test(PRETTIER_PERF_REPEAT)) {
1579
+ if (PRETTIER_PERF_REPEAT && /^\d+$/.test(PRETTIER_PERF_REPEAT)) {
1507
1580
  return {
1508
1581
  name: "PRETTIER_PERF_REPEAT (environment variable)",
1509
1582
  debugRepeat: Number(PRETTIER_PERF_REPEAT)
@@ -1765,11 +1838,11 @@ function escapePathForGlob(path13) {
1765
1838
  )
1766
1839
  // Workaround for fast-glob#262 (part 1)
1767
1840
  ),
1768
- "\\!",
1769
- "@(!)"
1841
+ "\0",
1842
+ "@(\\\\)"
1770
1843
  ),
1771
- "\0",
1772
- "@(\\\\)"
1844
+ '"',
1845
+ '@(\\")'
1773
1846
  );
1774
1847
  }
1775
1848
  var fixWindowsSlashes = normalizeToPosix;
@@ -1905,12 +1978,12 @@ var find_cache_file_default = findCacheFile;
1905
1978
  var import_fast_json_stable_stringify2 = __toESM(require_fast_json_stable_stringify(), 1);
1906
1979
  import fs7 from "fs";
1907
1980
 
1908
- // node_modules/file-entry-cache/dist/index.js
1981
+ // node_modules/file-entry-cache/dist/index.mjs
1909
1982
  import crypto2 from "crypto";
1910
1983
  import fs6 from "fs";
1911
1984
  import path11 from "path";
1912
1985
 
1913
- // node_modules/file-entry-cache/node_modules/flat-cache/dist/index.js
1986
+ // node_modules/file-entry-cache/node_modules/flat-cache/dist/index.mjs
1914
1987
  import fs5 from "fs";
1915
1988
  import path10 from "path";
1916
1989
 
@@ -2135,6 +2208,7 @@ var Eventified = class {
2135
2208
  }
2136
2209
  }
2137
2210
  }
2211
+ this.sendLog(event, arguments_);
2138
2212
  return result;
2139
2213
  }
2140
2214
  /**
@@ -2182,6 +2256,54 @@ var Eventified = class {
2182
2256
  }
2183
2257
  return result;
2184
2258
  }
2259
+ /**
2260
+ * Sends a log message using the configured logger based on the event name
2261
+ * @param {string | symbol} eventName - The event name that determines the log level
2262
+ * @param {unknown} data - The data to log
2263
+ */
2264
+ sendLog(eventName, data) {
2265
+ if (!this._logger) {
2266
+ return;
2267
+ }
2268
+ let message;
2269
+ if (typeof data === "string") {
2270
+ message = data;
2271
+ } else if (Array.isArray(data) && data.length > 0 && data[0] instanceof Error) {
2272
+ message = data[0].message;
2273
+ } else if (data instanceof Error) {
2274
+ message = data.message;
2275
+ } else if (Array.isArray(data) && data.length > 0 && typeof data[0]?.message === "string") {
2276
+ message = data[0].message;
2277
+ } else {
2278
+ message = JSON.stringify(data);
2279
+ }
2280
+ switch (eventName) {
2281
+ case "error": {
2282
+ this._logger.error?.(message, { event: eventName, data });
2283
+ break;
2284
+ }
2285
+ case "warn": {
2286
+ this._logger.warn?.(message, { event: eventName, data });
2287
+ break;
2288
+ }
2289
+ case "trace": {
2290
+ this._logger.trace?.(message, { event: eventName, data });
2291
+ break;
2292
+ }
2293
+ case "debug": {
2294
+ this._logger.debug?.(message, { event: eventName, data });
2295
+ break;
2296
+ }
2297
+ case "fatal": {
2298
+ this._logger.fatal?.(message, { event: eventName, data });
2299
+ break;
2300
+ }
2301
+ default: {
2302
+ this._logger.info?.(message, { event: eventName, data });
2303
+ break;
2304
+ }
2305
+ }
2306
+ }
2185
2307
  };
2186
2308
  var Hookified = class extends Eventified {
2187
2309
  _hooks;
@@ -2314,9 +2436,6 @@ var Hookified = class extends Eventified {
2314
2436
  const message = this._deprecatedHooks.get(event);
2315
2437
  const warningMessage = `Hook "${event}" is deprecated${message ? `: ${message}` : ""}`;
2316
2438
  this.emit("warn", { hook: event, message: warningMessage });
2317
- if (this.logger?.warn) {
2318
- this.logger.warn(warningMessage);
2319
- }
2320
2439
  return this._allowDeprecated;
2321
2440
  }
2322
2441
  return true;
@@ -2328,24 +2447,24 @@ var Hookified = class extends Eventified {
2328
2447
  * @returns {void}
2329
2448
  */
2330
2449
  onHook(event, handler) {
2331
- this.validateHookName(event);
2332
- if (!this.checkDeprecatedHook(event)) {
2333
- return;
2334
- }
2335
- const eventHandlers = this._hooks.get(event);
2336
- if (eventHandlers) {
2337
- eventHandlers.push(handler);
2338
- } else {
2339
- this._hooks.set(event, [handler]);
2340
- }
2450
+ this.onHookEntry({ event, handler });
2341
2451
  }
2342
2452
  /**
2343
- * Adds a handler function for a specific event that runs before all other handlers
2453
+ * Adds a handler function for a specific event
2344
2454
  * @param {HookEntry} hookEntry
2345
2455
  * @returns {void}
2346
2456
  */
2347
2457
  onHookEntry(hookEntry) {
2348
- this.onHook(hookEntry.event, hookEntry.handler);
2458
+ this.validateHookName(hookEntry.event);
2459
+ if (!this.checkDeprecatedHook(hookEntry.event)) {
2460
+ return;
2461
+ }
2462
+ const eventHandlers = this._hooks.get(hookEntry.event);
2463
+ if (eventHandlers) {
2464
+ eventHandlers.push(hookEntry.handler);
2465
+ } else {
2466
+ this._hooks.set(hookEntry.event, [hookEntry.handler]);
2467
+ }
2349
2468
  }
2350
2469
  /**
2351
2470
  * Alias for onHook. This is provided for compatibility with other libraries that use the `addHook` method.
@@ -2354,7 +2473,7 @@ var Hookified = class extends Eventified {
2354
2473
  * @returns {void}
2355
2474
  */
2356
2475
  addHook(event, handler) {
2357
- this.onHook(event, handler);
2476
+ this.onHookEntry({ event, handler });
2358
2477
  }
2359
2478
  /**
2360
2479
  * Adds a handler function for a specific event
@@ -2464,9 +2583,39 @@ var Hookified = class extends Eventified {
2464
2583
  } catch (error) {
2465
2584
  const message = `${event}: ${error.message}`;
2466
2585
  this.emit("error", new Error(message));
2467
- if (this.logger) {
2468
- this.logger.error(message);
2586
+ if (this._throwOnHookError) {
2587
+ throw new Error(message);
2469
2588
  }
2589
+ }
2590
+ }
2591
+ }
2592
+ }
2593
+ /**
2594
+ * Calls all synchronous handlers for a specific event.
2595
+ * Async handlers (declared with `async` keyword) are silently skipped.
2596
+ *
2597
+ * Note: The `hook` method is preferred as it executes both sync and async functions.
2598
+ * Use `hookSync` only when you specifically need synchronous execution.
2599
+ * @param {string} event
2600
+ * @param {T[]} arguments_
2601
+ * @returns {void}
2602
+ */
2603
+ hookSync(event, ...arguments_) {
2604
+ this.validateHookName(event);
2605
+ if (!this.checkDeprecatedHook(event)) {
2606
+ return;
2607
+ }
2608
+ const eventHandlers = this._hooks.get(event);
2609
+ if (eventHandlers) {
2610
+ for (const handler of eventHandlers) {
2611
+ if (handler.constructor.name === "AsyncFunction") {
2612
+ continue;
2613
+ }
2614
+ try {
2615
+ handler(...arguments_);
2616
+ } catch (error) {
2617
+ const message = `${event}: ${error.message}`;
2618
+ this.emit("error", new Error(message));
2470
2619
  if (this._throwOnHookError) {
2471
2620
  throw new Error(message);
2472
2621
  }
@@ -2522,6 +2671,103 @@ var Hookified = class extends Eventified {
2522
2671
  };
2523
2672
 
2524
2673
  // node_modules/hashery/dist/node/index.js
2674
+ var Cache = class {
2675
+ _enabled = true;
2676
+ _maxSize = 4e3;
2677
+ _store = /* @__PURE__ */ new Map();
2678
+ _keys = [];
2679
+ constructor(options) {
2680
+ if (options?.enabled !== void 0) {
2681
+ this._enabled = options.enabled;
2682
+ }
2683
+ if (options?.maxSize !== void 0) {
2684
+ this._maxSize = options.maxSize;
2685
+ }
2686
+ }
2687
+ /**
2688
+ * Gets whether the cache is enabled.
2689
+ */
2690
+ get enabled() {
2691
+ return this._enabled;
2692
+ }
2693
+ /**
2694
+ * Sets whether the cache is enabled.
2695
+ */
2696
+ set enabled(value) {
2697
+ this._enabled = value;
2698
+ }
2699
+ /**
2700
+ * Gets the maximum number of items the cache can hold.
2701
+ */
2702
+ get maxSize() {
2703
+ return this._maxSize;
2704
+ }
2705
+ /**
2706
+ * Sets the maximum number of items the cache can hold.
2707
+ */
2708
+ set maxSize(value) {
2709
+ this._maxSize = value;
2710
+ }
2711
+ /**
2712
+ * Gets the underlying Map store.
2713
+ */
2714
+ get store() {
2715
+ return this._store;
2716
+ }
2717
+ /**
2718
+ * Gets the current number of items in the cache.
2719
+ */
2720
+ get size() {
2721
+ return this._store.size;
2722
+ }
2723
+ /**
2724
+ * Gets a value from the cache.
2725
+ * @param key - The cache key
2726
+ * @returns The cached value, or undefined if not found
2727
+ */
2728
+ get(key) {
2729
+ return this._store.get(key);
2730
+ }
2731
+ /**
2732
+ * Sets a value in the cache with FIFO eviction.
2733
+ * If the cache is disabled, this method does nothing.
2734
+ * If the cache is at capacity, the oldest entry is removed before adding the new one.
2735
+ * @param key - The cache key
2736
+ * @param value - The value to cache
2737
+ */
2738
+ set(key, value) {
2739
+ if (!this._enabled) {
2740
+ return;
2741
+ }
2742
+ if (this._store.has(key)) {
2743
+ this._store.set(key, value);
2744
+ return;
2745
+ }
2746
+ if (this._store.size >= this._maxSize) {
2747
+ const oldestKey = this._keys.shift();
2748
+ if (oldestKey) {
2749
+ this._store.delete(oldestKey);
2750
+ }
2751
+ }
2752
+ this._keys.push(key);
2753
+ this._store.set(key, value);
2754
+ }
2755
+ /**
2756
+ * Checks if a key exists in the cache.
2757
+ * @param key - The cache key
2758
+ * @returns True if the key exists, false otherwise
2759
+ */
2760
+ has(key) {
2761
+ return this._store.has(key);
2762
+ }
2763
+ /**
2764
+ * Clears all entries from the cache.
2765
+ */
2766
+ clear() {
2767
+ this._store.clear();
2768
+ this._keys = [];
2769
+ }
2770
+ };
2525
2771
  var CRC = class {
2526
2772
  get name() {
2527
2773
  return "crc32";
@@ -2676,10 +2922,10 @@ var FNV1 = class {
2676
2922
  return this.toHashSync(data);
2677
2923
  }
2678
2924
  };
2679
- var Murmer = class {
2925
+ var Murmur = class {
2680
2926
  _seed;
2681
2927
  /**
2682
- * Creates a new Murmer instance.
2928
+ * Creates a new Murmur instance.
2683
2929
  *
2684
2930
  * @param seed - Optional seed value for the hash (default: 0)
2685
2931
  */
@@ -2690,7 +2936,7 @@ var Murmer = class {
2690
2936
  * The name identifier for this hash provider.
2691
2937
  */
2692
2938
  get name() {
2693
- return "murmer";
2939
+ return "murmur";
2694
2940
  }
2695
2941
  /**
2696
2942
  * Gets the current seed value used for hashing.
@@ -2699,16 +2945,16 @@ var Murmer = class {
2699
2945
  return this._seed;
2700
2946
  }
2701
2947
  /**
2702
- * Computes the Murmer 32-bit hash of the provided data synchronously.
2948
+ * Computes the Murmur 32-bit hash of the provided data synchronously.
2703
2949
  *
2704
2950
  * @param data - The data to hash (Uint8Array, ArrayBuffer, or DataView)
2705
2951
  * @returns An 8-character lowercase hexadecimal string
2706
2952
  *
2707
2953
  * @example
2708
2954
  * ```typescript
2709
- * const murmer = new Murmer();
2955
+ * const murmur = new Murmur();
2710
2956
  * const data = new TextEncoder().encode('hello');
2711
- * const hash = murmer.toHashSync(data);
2957
+ * const hash = murmur.toHashSync(data);
2712
2958
  * console.log(hash); // "248bfa47"
2713
2959
  * ```
2714
2960
  */
@@ -2766,16 +3012,16 @@ var Murmer = class {
2766
3012
  return hashHex;
2767
3013
  }
2768
3014
  /**
2769
- * Computes the Murmer 32-bit hash of the provided data.
3015
+ * Computes the Murmur 32-bit hash of the provided data.
2770
3016
  *
2771
3017
  * @param data - The data to hash (Uint8Array, ArrayBuffer, or DataView)
2772
3018
  * @returns A Promise resolving to an 8-character lowercase hexadecimal string
2773
3019
  *
2774
3020
  * @example
2775
3021
  * ```typescript
2776
- * const murmer = new Murmer();
3022
+ * const murmur = new Murmur();
2777
3023
  * const data = new TextEncoder().encode('hello');
2778
- * const hash = await murmer.toHash(data);
3024
+ * const hash = await murmur.toHash(data);
2779
3025
  * console.log(hash); // "248bfa47"
2780
3026
  * ```
2781
3027
  */
@@ -2962,6 +3208,7 @@ var Hashery = class extends Hookified {
2962
3208
  _providers = new HashProviders();
2963
3209
  _defaultAlgorithm = "SHA-256";
2964
3210
  _defaultAlgorithmSync = "djb2";
3211
+ _cache;
2965
3212
  constructor(options) {
2966
3213
  super(options);
2967
3214
  if (options?.parse) {
@@ -2976,6 +3223,7 @@ var Hashery = class extends Hookified {
2976
3223
  if (options?.defaultAlgorithmSync) {
2977
3224
  this._defaultAlgorithmSync = options.defaultAlgorithmSync;
2978
3225
  }
3226
+ this._cache = new Cache(options?.cache);
2979
3227
  this.loadProviders(options?.providers, {
2980
3228
  includeBase: options?.includeBase ?? true
2981
3229
  });
@@ -3060,7 +3308,7 @@ var Hashery = class extends Hookified {
3060
3308
  }
3061
3309
  /**
3062
3310
  * Sets the default synchronous hash algorithm to use when none is specified.
3063
- * @param value - The default synchronous algorithm to use (e.g., 'djb2', 'fnv1', 'murmer', 'crc32')
3311
+ * @param value - The default synchronous algorithm to use (e.g., 'djb2', 'fnv1', 'murmur', 'crc32')
3064
3312
  * @example
3065
3313
  * ```ts
3066
3314
  * const hashery = new Hashery();
@@ -3072,10 +3320,32 @@ var Hashery = class extends Hookified {
3072
3320
  set defaultAlgorithmSync(value) {
3073
3321
  this._defaultAlgorithmSync = value;
3074
3322
  }
3323
+ /**
3324
+ * Gets the cache instance used to store computed hash values.
3325
+ * @returns The Cache instance
3326
+ * @example
3327
+ * ```ts
3328
+ * const hashery = new Hashery({ cache: { enabled: true } });
3329
+ *
3330
+ * // Access the cache
3331
+ * hashery.cache.enabled; // true
3332
+ * hashery.cache.size; // number of cached items
3333
+ * hashery.cache.clear(); // clear all cached items
3334
+ * ```
3335
+ */
3336
+ get cache() {
3337
+ return this._cache;
3338
+ }
3075
3339
  /**
3076
3340
  * Generates a cryptographic hash of the provided data using the Web Crypto API.
3077
3341
  * The data is first stringified using the configured stringify function, then hashed.
3078
3342
  *
3343
+ * If an invalid algorithm is provided, a 'warn' event is emitted and the method falls back
3344
+ * to the default algorithm. You can listen to these warnings:
3345
+ * ```ts
3346
+ * hashery.on('warn', (message) => console.log(message));
3347
+ * ```
3348
+ *
3079
3349
  * @param data - The data to hash (will be stringified before hashing)
3080
3350
  * @param options - Optional configuration object
3081
3351
  * @param options.algorithm - The hash algorithm to use (defaults to 'SHA-256')
@@ -3100,15 +3370,36 @@ var Hashery = class extends Hookified {
3100
3370
  };
3101
3371
  await this.beforeHook("toHash", context);
3102
3372
  const stringified = this._stringify(context.data);
3373
+ const cacheKey = `${context.algorithm}:${stringified}`;
3374
+ if (this._cache.enabled) {
3375
+ const cached = this._cache.get(cacheKey);
3376
+ if (cached !== void 0) {
3377
+ let cachedHash = cached;
3378
+ if (options?.maxLength && cachedHash.length > options.maxLength) {
3379
+ cachedHash = cachedHash.substring(0, options.maxLength);
3380
+ }
3381
+ const result2 = {
3382
+ hash: cachedHash,
3383
+ data: context.data,
3384
+ algorithm: context.algorithm
3385
+ };
3386
+ await this.afterHook("toHash", result2);
3387
+ return result2.hash;
3388
+ }
3389
+ }
3103
3390
  const encoder = new TextEncoder();
3104
3391
  const dataBuffer = encoder.encode(stringified);
3105
3392
  let provider = this._providers.get(context.algorithm);
3106
3393
  if (!provider) {
3394
+ this.emit("warn", `Invalid algorithm '${context.algorithm}' not found. Falling back to default algorithm '${this._defaultAlgorithm}'.`);
3107
3395
  provider = new WebCrypto({
3108
3396
  algorithm: this._defaultAlgorithm
3109
3397
  });
3110
3398
  }
3111
3399
  let hash2 = await provider.toHash(dataBuffer);
3400
+ if (this._cache.enabled) {
3401
+ this._cache.set(cacheKey, hash2);
3402
+ }
3112
3403
  if (options?.maxLength && hash2.length > options?.maxLength) {
3113
3404
  hash2 = hash2.substring(0, options.maxLength);
3114
3405
  }
@@ -3169,9 +3460,15 @@ var Hashery = class extends Hookified {
3169
3460
  * Generates a hash of the provided data synchronously using a non-cryptographic hash algorithm.
3170
3461
  * The data is first stringified using the configured stringify function, then hashed.
3171
3462
  *
3172
- * Note: This method only works with synchronous hash providers (djb2, fnv1, murmer, crc32).
3463
+ * Note: This method only works with synchronous hash providers (djb2, fnv1, murmur, crc32).
3173
3464
  * WebCrypto algorithms (SHA-256, SHA-384, SHA-512) are not supported and will throw an error.
3174
3465
  *
3466
+ * If an invalid algorithm is provided, a 'warn' event is emitted and the method falls back
3467
+ * to the default synchronous algorithm. You can listen to these warnings:
3468
+ * ```ts
3469
+ * hashery.on('warn', (message) => console.log(message));
3470
+ * ```
3471
+ *
3175
3472
  * @param data - The data to hash (will be stringified before hashing)
3176
3473
  * @param options - Optional configuration object
3177
3474
  * @param options.algorithm - The hash algorithm to use (defaults to 'djb2')
@@ -3179,6 +3476,7 @@ var Hashery = class extends Hookified {
3179
3476
  * @returns The hexadecimal string representation of the hash
3180
3477
  *
3181
3478
  * @throws {Error} If the specified algorithm does not support synchronous hashing
3479
+ * @throws {Error} If the default algorithm is not found
3182
3480
  *
3183
3481
  * @example
3184
3482
  * ```ts
@@ -3196,19 +3494,43 @@ var Hashery = class extends Hookified {
3196
3494
  algorithm: options?.algorithm ?? this._defaultAlgorithmSync,
3197
3495
  maxLength: options?.maxLength
3198
3496
  };
3199
- this.beforeHook("toHashSync", context);
3497
+ this.hookSync("before:toHashSync", context);
3200
3498
  const algorithm = context.algorithm;
3201
3499
  const stringified = this._stringify(context.data);
3500
+ const cacheKey = `${algorithm}:${stringified}`;
3501
+ if (this._cache.enabled) {
3502
+ const cached = this._cache.get(cacheKey);
3503
+ if (cached !== void 0) {
3504
+ let cachedHash = cached;
3505
+ if (options?.maxLength && cachedHash.length > options.maxLength) {
3506
+ cachedHash = cachedHash.substring(0, options.maxLength);
3507
+ }
3508
+ const result2 = {
3509
+ hash: cachedHash,
3510
+ data: context.data,
3511
+ algorithm
3512
+ };
3513
+ this.hookSync("after:toHashSync", result2);
3514
+ return result2.hash;
3515
+ }
3516
+ }
3202
3517
  const encoder = new TextEncoder();
3203
3518
  const dataBuffer = encoder.encode(stringified);
3204
- const provider = this._providers.get(algorithm);
3519
+ let provider = this._providers.get(algorithm);
3205
3520
  if (!provider) {
3206
- throw new Error(`Hash provider '${algorithm}' not found`);
3521
+ this.emit("warn", `Invalid algorithm '${algorithm}' not found. Falling back to default algorithm '${this._defaultAlgorithmSync}'.`);
3522
+ provider = this._providers.get(this._defaultAlgorithmSync);
3523
+ if (!provider) {
3524
+ throw new Error(`Hash provider '${this._defaultAlgorithmSync}' (default) not found`);
3525
+ }
3207
3526
  }
3208
3527
  if (!provider.toHashSync) {
3209
- throw new Error(`Hash provider '${algorithm}' does not support synchronous hashing. Use toHash() instead or choose a different algorithm (djb2, fnv1, murmer, crc32).`);
3528
+ throw new Error(`Hash provider '${algorithm}' does not support synchronous hashing. Use toHash() instead or choose a different algorithm (djb2, fnv1, murmur, crc32).`);
3210
3529
  }
3211
3530
  let hash2 = provider.toHashSync(dataBuffer);
3531
+ if (this._cache.enabled) {
3532
+ this._cache.set(cacheKey, hash2);
3533
+ }
3212
3534
  if (options?.maxLength && hash2.length > options?.maxLength) {
3213
3535
  hash2 = hash2.substring(0, options.maxLength);
3214
3536
  }
@@ -3217,7 +3539,7 @@ var Hashery = class extends Hookified {
3217
3539
  data: context.data,
3218
3540
  algorithm: context.algorithm
3219
3541
  };
3220
- this.afterHook("toHashSync", result);
3542
+ this.hookSync("after:toHashSync", result);
3221
3543
  return result.hash;
3222
3544
  }
3223
3545
  /**
@@ -3225,7 +3547,7 @@ var Hashery = class extends Hookified {
3225
3547
  * This method uses the toHashSync function to create a consistent hash, then maps it to a number
3226
3548
  * between min and max (inclusive).
3227
3549
  *
3228
- * Note: This method only works with synchronous hash providers (djb2, fnv1, murmer, crc32).
3550
+ * Note: This method only works with synchronous hash providers (djb2, fnv1, murmur, crc32).
3229
3551
  *
3230
3552
  * @param data - The data to hash (will be stringified before hashing)
3231
3553
  * @param options - Configuration options (optional, defaults to min: 0, max: 100)
@@ -3291,79 +3613,58 @@ var Hashery = class extends Hookified {
3291
3613
  this.providers.add(new CRC());
3292
3614
  this.providers.add(new DJB2());
3293
3615
  this.providers.add(new FNV1());
3294
- this.providers.add(new Murmer());
3616
+ this.providers.add(new Murmur());
3295
3617
  }
3296
3618
  }
3297
3619
  };
3298
3620
 
3299
- // node_modules/@cacheable/utils/dist/index.js
3621
+ // node_modules/@cacheable/utils/dist/index.mjs
3300
3622
  var shorthandToMilliseconds = (shorthand) => {
3301
3623
  let milliseconds;
3302
- if (shorthand === void 0) {
3303
- return void 0;
3304
- }
3305
- if (typeof shorthand === "number") {
3306
- milliseconds = shorthand;
3307
- } else {
3308
- if (typeof shorthand !== "string") {
3309
- return void 0;
3310
- }
3624
+ if (shorthand === void 0) return;
3625
+ if (typeof shorthand === "number") milliseconds = shorthand;
3626
+ else {
3627
+ if (typeof shorthand !== "string") return;
3311
3628
  shorthand = shorthand.trim();
3312
3629
  if (Number.isNaN(Number(shorthand))) {
3313
3630
  const match = /^([\d.]+)\s*(ms|s|m|h|hr|d)$/i.exec(shorthand);
3314
- if (!match) {
3315
- throw new Error(
3316
- `Unsupported time format: "${shorthand}". Use 'ms', 's', 'm', 'h', 'hr', or 'd'.`
3317
- );
3318
- }
3631
+ if (!match) throw new Error(`Unsupported time format: "${shorthand}". Use 'ms', 's', 'm', 'h', 'hr', or 'd'.`);
3319
3632
  const [, value, unit] = match;
3320
3633
  const numericValue = Number.parseFloat(value);
3321
- const unitLower = unit.toLowerCase();
3322
- switch (unitLower) {
3323
- case "ms": {
3634
+ switch (unit.toLowerCase()) {
3635
+ case "ms":
3324
3636
  milliseconds = numericValue;
3325
3637
  break;
3326
- }
3327
- case "s": {
3638
+ case "s":
3328
3639
  milliseconds = numericValue * 1e3;
3329
3640
  break;
3330
- }
3331
- case "m": {
3641
+ case "m":
3332
3642
  milliseconds = numericValue * 1e3 * 60;
3333
3643
  break;
3334
- }
3335
- case "h": {
3644
+ case "h":
3336
3645
  milliseconds = numericValue * 1e3 * 60 * 60;
3337
3646
  break;
3338
- }
3339
- case "hr": {
3647
+ case "hr":
3340
3648
  milliseconds = numericValue * 1e3 * 60 * 60;
3341
3649
  break;
3342
- }
3343
- case "d": {
3650
+ case "d":
3344
3651
  milliseconds = numericValue * 1e3 * 60 * 60 * 24;
3345
3652
  break;
3346
- }
3347
3653
  /* v8 ignore next -- @preserve */
3348
- default: {
3654
+ default:
3349
3655
  milliseconds = Number(shorthand);
3350
- }
3351
3656
  }
3352
- } else {
3353
- milliseconds = Number(shorthand);
3354
- }
3657
+ } else milliseconds = Number(shorthand);
3355
3658
  }
3356
3659
  return milliseconds;
3357
3660
  };
3358
3661
  var shorthandToTime = (shorthand, fromDate) => {
3359
3662
  fromDate ?? (fromDate = /* @__PURE__ */ new Date());
3360
3663
  const milliseconds = shorthandToMilliseconds(shorthand);
3361
- if (milliseconds === void 0) {
3362
- return fromDate.getTime();
3363
- }
3664
+ if (milliseconds === void 0) return fromDate.getTime();
3364
3665
  return fromDate.getTime() + milliseconds;
3365
3666
  };
3366
- var HashAlgorithm = /* @__PURE__ */ ((HashAlgorithm2) => {
3667
+ var HashAlgorithm = /* @__PURE__ */ (function(HashAlgorithm2) {
3367
3668
  HashAlgorithm2["SHA256"] = "SHA-256";
3368
3669
  HashAlgorithm2["SHA384"] = "SHA-384";
3369
3670
  HashAlgorithm2["SHA512"] = "SHA-512";
@@ -3372,16 +3673,14 @@ var HashAlgorithm = /* @__PURE__ */ ((HashAlgorithm2) => {
3372
3673
  HashAlgorithm2["MURMER"] = "murmer";
3373
3674
  HashAlgorithm2["CRC32"] = "crc32";
3374
3675
  return HashAlgorithm2;
3375
- })(HashAlgorithm || {});
3676
+ })({});
3376
3677
  function hashSync(object2, options = {
3377
3678
  algorithm: "djb2",
3378
3679
  serialize: JSON.stringify
3379
3680
  }) {
3380
3681
  const algorithm = options?.algorithm ?? "djb2";
3381
- const serialize = options?.serialize ?? JSON.stringify;
3382
- const objectString = serialize(object2);
3383
- const hashery = new Hashery();
3384
- return hashery.toHashSync(objectString, { algorithm });
3682
+ const objectString = (options?.serialize ?? JSON.stringify)(object2);
3683
+ return new Hashery().toHashSync(objectString, { algorithm });
3385
3684
  }
3386
3685
  function hashToNumberSync(object2, options = {
3387
3686
  min: 0,
@@ -3394,14 +3693,9 @@ function hashToNumberSync(object2, options = {
3394
3693
  const algorithm = options?.algorithm ?? "djb2";
3395
3694
  const serialize = options?.serialize ?? JSON.stringify;
3396
3695
  const hashLength = options?.hashLength ?? 16;
3397
- if (min >= max) {
3398
- throw new Error(
3399
- `Invalid range: min (${min}) must be less than max (${max})`
3400
- );
3401
- }
3696
+ if (min >= max) throw new Error(`Invalid range: min (${min}) must be less than max (${max})`);
3402
3697
  const objectString = serialize(object2);
3403
- const hashery = new Hashery();
3404
- return hashery.toNumberSync(objectString, {
3698
+ return new Hashery().toNumberSync(objectString, {
3405
3699
  algorithm,
3406
3700
  min,
3407
3701
  max,
@@ -3409,217 +3703,733 @@ function hashToNumberSync(object2, options = {
3409
3703
  });
3410
3704
  }
3411
3705
  function wrapSync(function_, options) {
3412
- const { ttl, keyPrefix, cache, serialize } = options;
3706
+ const { ttl, keyPrefix, cache: cache2, serialize } = options;
3413
3707
  return (...arguments_) => {
3414
3708
  let cacheKey = createWrapKey(function_, arguments_, {
3415
3709
  keyPrefix,
3416
3710
  serialize
3417
3711
  });
3418
- if (options.createKey) {
3419
- cacheKey = options.createKey(function_, arguments_, options);
3420
- }
3421
- let value = cache.get(cacheKey);
3422
- if (value === void 0) {
3423
- try {
3424
- value = function_(...arguments_);
3425
- cache.set(cacheKey, value, ttl);
3426
- } catch (error) {
3427
- cache.emit("error", error);
3428
- if (options.cacheErrors) {
3429
- cache.set(cacheKey, error, ttl);
3430
- }
3431
- }
3712
+ if (options.createKey) cacheKey = options.createKey(function_, arguments_, options);
3713
+ let value = cache2.get(cacheKey);
3714
+ if (value === void 0) try {
3715
+ value = function_(...arguments_);
3716
+ cache2.set(cacheKey, value, ttl);
3717
+ } catch (error) {
3718
+ cache2.emit("error", error);
3719
+ if (options.cacheErrors) cache2.set(cacheKey, error, ttl);
3432
3720
  }
3433
3721
  return value;
3434
3722
  };
3435
3723
  }
3724
+ function getOrSetSync(key, function_, options) {
3725
+ const keyString = typeof key === "function" ? key(options) : key;
3726
+ let value;
3727
+ try {
3728
+ value = options.cache.get(keyString);
3729
+ } catch (error) {
3730
+ options.cache.emit("error", error);
3731
+ if (options.throwErrors === true || options.throwErrors === "store") throw error;
3732
+ }
3733
+ if (value === void 0) try {
3734
+ try {
3735
+ value = function_();
3736
+ } catch (error) {
3737
+ throw new ErrorEnvelope(error, "function");
3738
+ }
3739
+ try {
3740
+ options.cache.set(keyString, value, options.ttl);
3741
+ } catch (error) {
3742
+ throw new ErrorEnvelope(error, "store");
3743
+ }
3744
+ } catch (caught) {
3745
+ const errorType = caught instanceof ErrorEnvelope ? caught.context : void 0;
3746
+ const error = caught instanceof ErrorEnvelope ? caught.error : caught;
3747
+ options.cache.emit("error", error);
3748
+ if (options.cacheErrors && errorType === "function") try {
3749
+ options.cache.set(keyString, error, options.ttl);
3750
+ } catch (storeError) {
3751
+ options.cache.emit("error", storeError);
3752
+ }
3753
+ if (options.throwErrors === true || options.throwErrors === errorType) throw error;
3754
+ }
3755
+ return value;
3756
+ }
3436
3757
  function createWrapKey(function_, arguments_, options) {
3437
3758
  const { keyPrefix, serialize } = options || {};
3438
- if (!keyPrefix) {
3439
- return `${function_.name}::${hashSync(arguments_, { serialize })}`;
3440
- }
3759
+ if (!keyPrefix) return `${function_.name}::${hashSync(arguments_, { serialize })}`;
3441
3760
  return `${keyPrefix}::${function_.name}::${hashSync(arguments_, { serialize })}`;
3442
3761
  }
3443
-
3444
- // node_modules/@cacheable/memory/dist/index.js
3445
- var structuredClone = globalThis.structuredClone ?? ((value) => JSON.parse(JSON.stringify(value)));
3446
- var ListNode = class {
3447
- value;
3448
- prev = void 0;
3449
- next = void 0;
3450
- constructor(value) {
3451
- this.value = value;
3762
+ var ErrorEnvelope = class {
3763
+ error;
3764
+ context;
3765
+ constructor(error, context) {
3766
+ this.error = error;
3767
+ this.context = context;
3452
3768
  }
3453
3769
  };
3454
- var DoublyLinkedList = class {
3455
- head = void 0;
3456
- tail = void 0;
3457
- nodesMap = /* @__PURE__ */ new Map();
3458
- // Add a new node to the front (most recently used)
3459
- addToFront(value) {
3460
- const newNode = new ListNode(value);
3461
- if (this.head) {
3462
- newNode.next = this.head;
3463
- this.head.prev = newNode;
3464
- this.head = newNode;
3465
- } else {
3466
- this.head = this.tail = newNode;
3467
- }
3468
- this.nodesMap.set(value, newNode);
3770
+ var Stats = class {
3771
+ _counters = {
3772
+ hits: 0,
3773
+ misses: 0,
3774
+ gets: 0,
3775
+ sets: 0,
3776
+ deletes: 0,
3777
+ clears: 0,
3778
+ count: 0
3779
+ };
3780
+ _vsize = 0;
3781
+ _ksize = 0;
3782
+ _enabled = false;
3783
+ _lastUpdated;
3784
+ _lastReset;
3785
+ _subscriptions = [];
3786
+ /** Backing store for the public {@link trackedKeys} read-only view. */
3787
+ _trackedKeys = /* @__PURE__ */ new Map();
3788
+ _trackKeys = false;
3789
+ _maxTrackedKeys;
3790
+ constructor(options) {
3791
+ if (options?.enabled) this._enabled = options.enabled;
3792
+ if (options?.trackKeys) this._trackKeys = options.trackKeys;
3793
+ if (options?.maxTrackedKeys !== void 0) this._maxTrackedKeys = options.maxTrackedKeys;
3794
+ if (options?.emitter && options?.eventMap) this.subscribe(options.emitter, options.eventMap);
3469
3795
  }
3470
- // Move an existing node to the front (most recently used)
3471
- moveToFront(value) {
3472
- const node = this.nodesMap.get(value);
3473
- if (!node || this.head === node) {
3474
- return;
3475
- }
3476
- if (node.prev) {
3477
- node.prev.next = node.next;
3478
- }
3479
- if (node.next) {
3480
- node.next.prev = node.prev;
3481
- }
3482
- if (node === this.tail) {
3483
- this.tail = node.prev;
3484
- }
3485
- node.prev = void 0;
3486
- node.next = this.head;
3487
- if (this.head) {
3488
- this.head.prev = node;
3489
- }
3490
- this.head = node;
3491
- this.tail ?? (this.tail = node);
3796
+ /**
3797
+ * @returns {boolean} - Whether the stats are enabled
3798
+ */
3799
+ get enabled() {
3800
+ return this._enabled;
3492
3801
  }
3493
- // Get the oldest node (tail)
3494
- getOldest() {
3495
- return this.tail ? this.tail.value : void 0;
3802
+ /**
3803
+ * @param {boolean} enabled - Whether to enable the stats
3804
+ */
3805
+ set enabled(enabled) {
3806
+ this._enabled = enabled;
3496
3807
  }
3497
- // Remove the oldest node (tail)
3498
- removeOldest() {
3499
- if (!this.tail) {
3500
- return void 0;
3501
- }
3502
- const oldValue = this.tail.value;
3503
- if (this.tail.prev) {
3504
- this.tail = this.tail.prev;
3505
- this.tail.next = void 0;
3506
- } else {
3507
- this.head = this.tail = void 0;
3508
- }
3509
- this.nodesMap.delete(oldValue);
3510
- return oldValue;
3808
+ /**
3809
+ * @returns {boolean} - Whether per-key statistics are tracked
3810
+ */
3811
+ get trackKeys() {
3812
+ return this._trackKeys;
3511
3813
  }
3512
- get size() {
3513
- return this.nodesMap.size;
3814
+ /**
3815
+ * @param {boolean} trackKeys - Whether to track per-key statistics
3816
+ */
3817
+ set trackKeys(trackKeys) {
3818
+ this._trackKeys = trackKeys;
3514
3819
  }
3515
- };
3516
- var defaultStoreHashSize = 16;
3517
- var maximumMapSize = 16777216;
3518
- var CacheableMemory = class extends Hookified {
3519
- _lru = new DoublyLinkedList();
3520
- _storeHashSize = defaultStoreHashSize;
3521
- _storeHashAlgorithm = HashAlgorithm.DJB2;
3522
- // Default is djb2Hash
3523
- _store = Array.from(
3524
- { length: this._storeHashSize },
3525
- () => /* @__PURE__ */ new Map()
3526
- );
3527
- _ttl;
3528
- // Turned off by default
3529
- _useClone = true;
3530
- // Turned on by default
3531
- _lruSize = 0;
3532
- // Turned off by default
3533
- _checkInterval = 0;
3534
- // Turned off by default
3535
- _interval = 0;
3536
- // Turned off by default
3537
3820
  /**
3538
- * @constructor
3539
- * @param {CacheableMemoryOptions} [options] - The options for the CacheableMemory
3540
- */
3541
- constructor(options) {
3542
- super();
3543
- if (options?.ttl) {
3544
- this.setTtl(options.ttl);
3545
- }
3546
- if (options?.useClone !== void 0) {
3547
- this._useClone = options.useClone;
3548
- }
3549
- if (options?.storeHashSize && options.storeHashSize > 0) {
3550
- this._storeHashSize = options.storeHashSize;
3551
- }
3552
- if (options?.lruSize) {
3553
- if (options.lruSize > maximumMapSize) {
3554
- this.emit(
3555
- "error",
3556
- new Error(
3557
- `LRU size cannot be larger than ${maximumMapSize} due to Map limitations.`
3558
- )
3559
- );
3560
- } else {
3561
- this._lruSize = options.lruSize;
3821
+ * @returns {number | undefined} - The cap on unique keys tracked, or
3822
+ * `undefined` when unbounded
3823
+ */
3824
+ get maxTrackedKeys() {
3825
+ return this._maxTrackedKeys;
3826
+ }
3827
+ /**
3828
+ * @param {number | undefined} maxTrackedKeys - The cap on unique keys
3829
+ * tracked. Set `undefined` for unbounded.
3830
+ */
3831
+ set maxTrackedKeys(maxTrackedKeys) {
3832
+ this._maxTrackedKeys = maxTrackedKeys;
3833
+ }
3834
+ /**
3835
+ * Per-key statistics, keyed by cache key, holding each key's raw
3836
+ * `hits`/`misses`/`gets`/`sets`/`deletes` counters. Populated by
3837
+ * {@link recordKey} when {@link trackKeys} is enabled; read `trackedKeys.size`
3838
+ * for the number of unique keys currently tracked. The returned map is a
3839
+ * read-only view — mutate per-key stats via {@link recordKey} /
3840
+ * {@link clearKeys} / {@link reset}.
3841
+ * @returns {ReadonlyMap<string, Readonly<KeyCounters>>}
3842
+ * @readonly
3843
+ */
3844
+ get trackedKeys() {
3845
+ return this._trackedKeys;
3846
+ }
3847
+ /**
3848
+ * @returns {number} - The number of hits
3849
+ * @readonly
3850
+ */
3851
+ get hits() {
3852
+ return this._counters.hits;
3853
+ }
3854
+ /**
3855
+ * @returns {number} - The number of misses
3856
+ * @readonly
3857
+ */
3858
+ get misses() {
3859
+ return this._counters.misses;
3860
+ }
3861
+ /**
3862
+ * @returns {number} - The number of gets
3863
+ * @readonly
3864
+ */
3865
+ get gets() {
3866
+ return this._counters.gets;
3867
+ }
3868
+ /**
3869
+ * @returns {number} - The number of sets
3870
+ * @readonly
3871
+ */
3872
+ get sets() {
3873
+ return this._counters.sets;
3874
+ }
3875
+ /**
3876
+ * @returns {number} - The number of deletes
3877
+ * @readonly
3878
+ */
3879
+ get deletes() {
3880
+ return this._counters.deletes;
3881
+ }
3882
+ /**
3883
+ * @returns {number} - The number of clears
3884
+ * @readonly
3885
+ */
3886
+ get clears() {
3887
+ return this._counters.clears;
3888
+ }
3889
+ /**
3890
+ * @returns {number} - The vsize (value size) of the cache instance
3891
+ * @readonly
3892
+ */
3893
+ get vsize() {
3894
+ return this._vsize;
3895
+ }
3896
+ /**
3897
+ * @returns {number} - The ksize (key size) of the cache instance
3898
+ * @readonly
3899
+ */
3900
+ get ksize() {
3901
+ return this._ksize;
3902
+ }
3903
+ /**
3904
+ * @returns {number} - The count of the cache instance
3905
+ * @readonly
3906
+ */
3907
+ get count() {
3908
+ return this._counters.count;
3909
+ }
3910
+ /**
3911
+ * The ratio of hits to total lookups (hits + misses). Returns `0` when there
3912
+ * have been no lookups.
3913
+ * @returns {number} - A value between 0 and 1
3914
+ * @readonly
3915
+ */
3916
+ get hitRate() {
3917
+ const total = this._counters.hits + this._counters.misses;
3918
+ return total === 0 ? 0 : this._counters.hits / total;
3919
+ }
3920
+ /**
3921
+ * The ratio of misses to total lookups (hits + misses). Returns `0` when
3922
+ * there have been no lookups.
3923
+ * @returns {number} - A value between 0 and 1
3924
+ * @readonly
3925
+ */
3926
+ get missRate() {
3927
+ const total = this._counters.hits + this._counters.misses;
3928
+ return total === 0 ? 0 : this._counters.misses / total;
3929
+ }
3930
+ /**
3931
+ * The timestamp (ms since epoch) of the last mutation while enabled, or
3932
+ * `undefined` if there have been none since the last reset.
3933
+ * @returns {number | undefined}
3934
+ * @readonly
3935
+ */
3936
+ get lastUpdated() {
3937
+ return this._lastUpdated;
3938
+ }
3939
+ /**
3940
+ * The timestamp (ms since epoch) of the last {@link reset}/{@link clear}, or
3941
+ * `undefined` if it has never been reset.
3942
+ * @returns {number | undefined}
3943
+ * @readonly
3944
+ */
3945
+ get lastReset() {
3946
+ return this._lastReset;
3947
+ }
3948
+ /**
3949
+ * Increment a counter field by `amount` (default `1`). No-op when disabled.
3950
+ * @param {StatField} field - The counter to increment
3951
+ * @param {number} amount - The amount to add (default 1)
3952
+ */
3953
+ increment(field, amount = 1) {
3954
+ if (!this._enabled) return;
3955
+ this._counters[field] += amount;
3956
+ this.touch();
3957
+ }
3958
+ /**
3959
+ * Decrement a counter field by `amount` (default `1`). No-op when disabled.
3960
+ * @param {StatField} field - The counter to decrement
3961
+ * @param {number} amount - The amount to subtract (default 1)
3962
+ */
3963
+ decrement(field, amount = 1) {
3964
+ if (!this._enabled) return;
3965
+ this._counters[field] -= amount;
3966
+ this.touch();
3967
+ }
3968
+ incrementHits(amount = 1) {
3969
+ this.increment("hits", amount);
3970
+ }
3971
+ incrementMisses(amount = 1) {
3972
+ this.increment("misses", amount);
3973
+ }
3974
+ incrementGets(amount = 1) {
3975
+ this.increment("gets", amount);
3976
+ }
3977
+ incrementSets(amount = 1) {
3978
+ this.increment("sets", amount);
3979
+ }
3980
+ incrementDeletes(amount = 1) {
3981
+ this.increment("deletes", amount);
3982
+ }
3983
+ incrementClears(amount = 1) {
3984
+ this.increment("clears", amount);
3985
+ }
3986
+ incrementVSize(value) {
3987
+ if (!this._enabled) return;
3988
+ this._vsize += this.roughSizeOfObject(value);
3989
+ this.touch();
3990
+ }
3991
+ decreaseVSize(value) {
3992
+ if (!this._enabled) return;
3993
+ this._vsize = Math.max(0, this._vsize - this.roughSizeOfObject(value));
3994
+ this.touch();
3995
+ }
3996
+ incrementKSize(key) {
3997
+ if (!this._enabled) return;
3998
+ this._ksize += this.roughSizeOfString(key);
3999
+ this.touch();
4000
+ }
4001
+ decreaseKSize(key) {
4002
+ if (!this._enabled) return;
4003
+ this._ksize = Math.max(0, this._ksize - this.roughSizeOfString(key));
4004
+ this.touch();
4005
+ }
4006
+ incrementCount(amount = 1) {
4007
+ this.increment("count", amount);
4008
+ }
4009
+ decreaseCount(amount = 1) {
4010
+ if (!this._enabled) return;
4011
+ this._counters.count = Math.max(0, this._counters.count - amount);
4012
+ this.touch();
4013
+ }
4014
+ setCount(count) {
4015
+ if (!this._enabled) return;
4016
+ this._counters.count = count;
4017
+ this.touch();
4018
+ }
4019
+ roughSizeOfString(value) {
4020
+ return value.length * 2;
4021
+ }
4022
+ roughSizeOfObject(object2) {
4023
+ const objectList = [];
4024
+ const stack = [object2];
4025
+ let bytes = 0;
4026
+ while (stack.length > 0) {
4027
+ const value = stack.pop();
4028
+ if (typeof value === "boolean") bytes += 4;
4029
+ else if (typeof value === "string") bytes += value.length * 2;
4030
+ else if (typeof value === "number") bytes += 8;
4031
+ else {
4032
+ if (value === null || value === void 0) {
4033
+ bytes += 4;
4034
+ continue;
4035
+ }
4036
+ if (objectList.includes(value)) continue;
4037
+ objectList.push(value);
4038
+ for (const key in value) {
4039
+ bytes += key.length * 2;
4040
+ stack.push(value[key]);
4041
+ }
3562
4042
  }
3563
4043
  }
3564
- if (options?.checkInterval) {
3565
- this._checkInterval = options.checkInterval;
4044
+ return bytes;
4045
+ }
4046
+ /**
4047
+ * Enable stat tracking. Equivalent to setting {@link enabled} to `true`.
4048
+ */
4049
+ enable() {
4050
+ this._enabled = true;
4051
+ }
4052
+ /**
4053
+ * Disable stat tracking. Equivalent to setting {@link enabled} to `false`.
4054
+ */
4055
+ disable() {
4056
+ this._enabled = false;
4057
+ }
4058
+ /**
4059
+ * Reset all counters to zero and record the reset timestamp. Alias of
4060
+ * {@link reset}.
4061
+ */
4062
+ clear() {
4063
+ this.reset();
4064
+ }
4065
+ reset() {
4066
+ this._counters = {
4067
+ hits: 0,
4068
+ misses: 0,
4069
+ gets: 0,
4070
+ sets: 0,
4071
+ deletes: 0,
4072
+ clears: 0,
4073
+ count: 0
4074
+ };
4075
+ this._vsize = 0;
4076
+ this._ksize = 0;
4077
+ this._trackedKeys.clear();
4078
+ this._lastReset = Date.now();
4079
+ this._lastUpdated = void 0;
4080
+ }
4081
+ resetStoreValues() {
4082
+ this._vsize = 0;
4083
+ this._ksize = 0;
4084
+ this._counters.count = 0;
4085
+ }
4086
+ /**
4087
+ * @returns {StatsSnapshot} - A plain-object snapshot of the current stats,
4088
+ * including computed `hitRate`/`missRate` and timestamps.
4089
+ */
4090
+ toJSON() {
4091
+ return {
4092
+ enabled: this._enabled,
4093
+ hits: this._counters.hits,
4094
+ misses: this._counters.misses,
4095
+ gets: this._counters.gets,
4096
+ sets: this._counters.sets,
4097
+ deletes: this._counters.deletes,
4098
+ clears: this._counters.clears,
4099
+ vsize: this._vsize,
4100
+ ksize: this._ksize,
4101
+ count: this._counters.count,
4102
+ hitRate: this.hitRate,
4103
+ missRate: this.missRate,
4104
+ trackedKeys: this._trackedKeys.size,
4105
+ lastUpdated: this._lastUpdated,
4106
+ lastReset: this._lastReset
4107
+ };
4108
+ }
4109
+ /**
4110
+ * @returns {StatsSnapshot} - A plain-object snapshot of the current stats.
4111
+ * Alias of {@link toJSON}.
4112
+ */
4113
+ snapshot() {
4114
+ return this.toJSON();
4115
+ }
4116
+ /**
4117
+ * Record an operation against a specific key for per-key statistics. No-op
4118
+ * unless both {@link enabled} and {@link trackKeys} are `true`.
4119
+ * @param {string} key - The cache key the operation touched
4120
+ * @param {KeyStatField} field - The per-key counter to increment
4121
+ * @param {number} amount - The amount to add (default 1)
4122
+ */
4123
+ recordKey(key, field, amount = 1) {
4124
+ if (!this._enabled || !this._trackKeys) return;
4125
+ let counters = this._trackedKeys.get(key);
4126
+ if (!counters) {
4127
+ counters = {
4128
+ hits: 0,
4129
+ misses: 0,
4130
+ gets: 0,
4131
+ sets: 0,
4132
+ deletes: 0
4133
+ };
4134
+ this._trackedKeys.set(key, counters);
4135
+ this.pruneTrackedKeys(key);
4136
+ }
4137
+ counters[field] += amount;
4138
+ this.touch();
4139
+ }
4140
+ /**
4141
+ * The most-used keys, sorted descending. Sorts by total recorded operations,
4142
+ * or by a single field when `field` is provided. Ties order by key.
4143
+ * @param {number} limit - Maximum entries to return (default 100)
4144
+ * @param {KeyStatField} [field] - Optionally rank by one counter (e.g. "hits")
4145
+ * @returns {StatsKeyEntry[]}
4146
+ */
4147
+ mostUsedKeys(limit = 100, field) {
4148
+ return this.sortedKeyEntries(field, "desc").slice(0, limit);
4149
+ }
4150
+ /**
4151
+ * The least-used keys, sorted ascending. Sorts by total recorded operations,
4152
+ * or by a single field when `field` is provided. Ties order by key. Note:
4153
+ * only keys that have been recorded at least once can be ranked, and when
4154
+ * {@link maxTrackedKeys} pruning has occurred the true least-used keys may
4155
+ * have been evicted.
4156
+ * @param {number} limit - Maximum entries to return (default 100)
4157
+ * @param {KeyStatField} [field] - Optionally rank by one counter (e.g. "gets")
4158
+ * @returns {StatsKeyEntry[]}
4159
+ */
4160
+ leastUsedKeys(limit = 100, field) {
4161
+ return this.sortedKeyEntries(field, "asc").slice(0, limit);
4162
+ }
4163
+ /**
4164
+ * @param {string} key - The key to look up
4165
+ * @returns {StatsKeyEntry | undefined} - The per-key statistics, or
4166
+ * `undefined` if the key has not been recorded
4167
+ */
4168
+ keyStats(key) {
4169
+ const counters = this._trackedKeys.get(key);
4170
+ return counters ? this.toKeyEntry(key, counters) : void 0;
4171
+ }
4172
+ /**
4173
+ * Clear all per-key statistics without touching the aggregate counters.
4174
+ */
4175
+ clearKeys() {
4176
+ this._trackedKeys.clear();
4177
+ }
4178
+ totalOf(counters) {
4179
+ return counters.hits + counters.misses + counters.gets + counters.sets + counters.deletes;
4180
+ }
4181
+ toKeyEntry(key, counters) {
4182
+ const lookups = counters.hits + counters.misses;
4183
+ return {
4184
+ key,
4185
+ count: this.totalOf(counters),
4186
+ hits: counters.hits,
4187
+ misses: counters.misses,
4188
+ gets: counters.gets,
4189
+ sets: counters.sets,
4190
+ deletes: counters.deletes,
4191
+ hitRate: lookups === 0 ? 0 : counters.hits / lookups
4192
+ };
4193
+ }
4194
+ sortedKeyEntries(field, direction) {
4195
+ const entries = [];
4196
+ for (const [key, counters] of this._trackedKeys) entries.push(this.toKeyEntry(key, counters));
4197
+ const sign = direction === "asc" ? 1 : -1;
4198
+ entries.sort((a, b) => {
4199
+ const valueA = field ? a[field] : a.count;
4200
+ const valueB = field ? b[field] : b.count;
4201
+ if (valueA !== valueB) return (valueA - valueB) * sign;
4202
+ return a.key < b.key ? -1 : 1;
4203
+ });
4204
+ return entries;
4205
+ }
4206
+ /**
4207
+ * When over {@link maxTrackedKeys}, prune the lowest-count keys down to 90%
4208
+ * of the cap (batched so the sort cost amortizes across inserts). The key
4209
+ * that was just recorded is never pruned.
4210
+ */
4211
+ pruneTrackedKeys(protectedKey) {
4212
+ if (this._maxTrackedKeys === void 0 || this._trackedKeys.size <= this._maxTrackedKeys) return;
4213
+ const target = Math.max(1, Math.floor(this._maxTrackedKeys * 0.9));
4214
+ const sorted = [...this._trackedKeys.entries()].sort((a, b) => this.totalOf(a[1]) - this.totalOf(b[1]));
4215
+ for (const [key] of sorted) {
4216
+ if (this._trackedKeys.size <= target) break;
4217
+ if (key === protectedKey) continue;
4218
+ this._trackedKeys.delete(key);
4219
+ }
4220
+ }
4221
+ /**
4222
+ * Subscribe to an emitter so that matching events automatically update the
4223
+ * stats. Counting is gated by {@link enabled}, so you may subscribe first and
4224
+ * toggle enablement later. Call {@link unsubscribe} to detach.
4225
+ * @param {StatsEmitter} emitter - The emitter to listen on
4226
+ * @param {StatsEventMap} eventMap - The event-to-stat mapping (e.g.
4227
+ * {@link nodeCacheStatsEventMap} or a custom map)
4228
+ */
4229
+ subscribe(emitter, eventMap) {
4230
+ for (const [event, action] of Object.entries(eventMap)) {
4231
+ const listener = (...args) => {
4232
+ this.applyEvent(action, args);
4233
+ };
4234
+ emitter.on(event, listener);
4235
+ this._subscriptions.push({
4236
+ emitter,
4237
+ event,
4238
+ listener
4239
+ });
3566
4240
  }
3567
- if (options?.storeHashAlgorithm) {
3568
- this._storeHashAlgorithm = options.storeHashAlgorithm;
4241
+ }
4242
+ /**
4243
+ * Detach listeners previously attached via {@link subscribe}. When `emitter`
4244
+ * is provided, only that emitter's listeners are removed; otherwise all are.
4245
+ * @param {StatsEmitter} [emitter] - The emitter to detach from
4246
+ */
4247
+ unsubscribe(emitter) {
4248
+ const remaining = [];
4249
+ for (const sub of this._subscriptions) {
4250
+ if (emitter && sub.emitter !== emitter) {
4251
+ remaining.push(sub);
4252
+ continue;
4253
+ }
4254
+ (sub.emitter.off ?? sub.emitter.removeListener)?.call(sub.emitter, sub.event, sub.listener);
3569
4255
  }
3570
- this._store = Array.from(
3571
- { length: this._storeHashSize },
3572
- () => /* @__PURE__ */ new Map()
3573
- );
4256
+ this._subscriptions = remaining;
4257
+ }
4258
+ applyEvent(action, args) {
4259
+ if (!this._enabled) return;
4260
+ if (typeof action === "function") {
4261
+ action(this, ...args);
4262
+ return;
4263
+ }
4264
+ if (Array.isArray(action)) {
4265
+ for (const field of action) this.increment(field);
4266
+ return;
4267
+ }
4268
+ this.increment(action);
4269
+ }
4270
+ touch() {
4271
+ this._lastUpdated = Date.now();
4272
+ }
4273
+ };
4274
+
4275
+ // node_modules/@cacheable/memory/dist/index.mjs
4276
+ var structuredClone = globalThis.structuredClone ?? ((value) => JSON.parse(JSON.stringify(value)));
4277
+ var ListNode = class {
4278
+ value;
4279
+ prev = void 0;
4280
+ next = void 0;
4281
+ constructor(value) {
4282
+ this.value = value;
4283
+ }
4284
+ };
4285
+ var DoublyLinkedList = class {
4286
+ head = void 0;
4287
+ tail = void 0;
4288
+ nodesMap = /* @__PURE__ */ new Map();
4289
+ addToFront(value) {
4290
+ const newNode = new ListNode(value);
4291
+ if (this.head) {
4292
+ newNode.next = this.head;
4293
+ this.head.prev = newNode;
4294
+ this.head = newNode;
4295
+ } else this.head = this.tail = newNode;
4296
+ this.nodesMap.set(value, newNode);
4297
+ }
4298
+ moveToFront(value) {
4299
+ const node = this.nodesMap.get(value);
4300
+ if (!node || this.head === node) return;
4301
+ if (node.prev) node.prev.next = node.next;
4302
+ if (node.next) node.next.prev = node.prev;
4303
+ if (node === this.tail) this.tail = node.prev;
4304
+ node.prev = void 0;
4305
+ node.next = this.head;
4306
+ if (this.head) this.head.prev = node;
4307
+ this.head = node;
4308
+ this.tail ?? (this.tail = node);
4309
+ }
4310
+ getOldest() {
4311
+ return this.tail ? this.tail.value : void 0;
4312
+ }
4313
+ removeOldest() {
4314
+ if (!this.tail) return;
4315
+ const oldValue = this.tail.value;
4316
+ if (this.tail.prev) {
4317
+ this.tail = this.tail.prev;
4318
+ this.tail.next = void 0;
4319
+ } else
4320
+ this.head = this.tail = void 0;
4321
+ this.nodesMap.delete(oldValue);
4322
+ return oldValue;
4323
+ }
4324
+ remove(value) {
4325
+ const node = this.nodesMap.get(value);
4326
+ if (!node) return false;
4327
+ if (node.prev) node.prev.next = node.next;
4328
+ else {
4329
+ this.head = node.next;
4330
+ if (this.head) this.head.prev = void 0;
4331
+ }
4332
+ if (node.next) node.next.prev = node.prev;
4333
+ else {
4334
+ this.tail = node.prev;
4335
+ if (this.tail) this.tail.next = void 0;
4336
+ }
4337
+ this.nodesMap.delete(value);
4338
+ return true;
4339
+ }
4340
+ get size() {
4341
+ return this.nodesMap.size;
4342
+ }
4343
+ };
4344
+ var maximumMapSize = 16777216;
4345
+ var CacheableMemory = class extends Hookified {
4346
+ _lru = new DoublyLinkedList();
4347
+ _storeHashSize = 16;
4348
+ _storeHashAlgorithm = HashAlgorithm.DJB2;
4349
+ _store = Array.from({ length: this._storeHashSize }, () => /* @__PURE__ */ new Map());
4350
+ _ttl;
4351
+ _maxTtl;
4352
+ _useClone = true;
4353
+ _lruSize = 0;
4354
+ _checkInterval = 0;
4355
+ _interval = 0;
4356
+ _stats = new Stats({ enabled: false });
4357
+ /**
4358
+ * @constructor
4359
+ * @param {CacheableMemoryOptions} [options] - The options for the CacheableMemory
4360
+ */
4361
+ constructor(options) {
4362
+ super();
4363
+ if (options?.ttl) this.setTtl(options.ttl);
4364
+ if (options?.maxTtl !== void 0) this.setMaxTtl(options.maxTtl);
4365
+ if (options?.useClone !== void 0) this._useClone = options.useClone;
4366
+ if (options?.stats) this._stats.enabled = options.stats;
4367
+ if (options?.storeHashSize && options.storeHashSize > 0) this._storeHashSize = options.storeHashSize;
4368
+ if (options?.lruSize) if (options.lruSize > 16777216) this.emit("error", /* @__PURE__ */ new Error(`LRU size cannot be larger than ${maximumMapSize} due to Map limitations.`));
4369
+ else this._lruSize = options.lruSize;
4370
+ if (options?.checkInterval) this._checkInterval = options.checkInterval;
4371
+ if (options?.storeHashAlgorithm) this._storeHashAlgorithm = options.storeHashAlgorithm;
4372
+ this._store = Array.from({ length: this._storeHashSize }, () => /* @__PURE__ */ new Map());
3574
4373
  this.startIntervalCheck();
3575
4374
  }
3576
4375
  /**
3577
- * Gets the time-to-live
3578
- * @returns {number|string|undefined} - The time-to-live in miliseconds or a human-readable format. If undefined, it will not have a time-to-live.
3579
- */
4376
+ * Gets the time-to-live
4377
+ * @returns {number|string|undefined} - The time-to-live in miliseconds or a human-readable format. If undefined, it will not have a time-to-live.
4378
+ */
3580
4379
  get ttl() {
3581
4380
  return this._ttl;
3582
4381
  }
3583
4382
  /**
3584
- * Sets the time-to-live
3585
- * @param {number|string|undefined} value - The time-to-live in miliseconds or a human-readable format (example '1s' = 1 second, '1h' = 1 hour). If undefined, it will not have a time-to-live.
3586
- */
4383
+ * Sets the time-to-live
4384
+ * @param {number|string|undefined} value - The time-to-live in miliseconds or a human-readable format (example '1s' = 1 second, '1h' = 1 hour). If undefined, it will not have a time-to-live.
4385
+ */
3587
4386
  set ttl(value) {
3588
4387
  this.setTtl(value);
3589
4388
  }
3590
4389
  /**
3591
- * Gets whether to use clone
3592
- * @returns {boolean} - If true, it will clone the value before returning it. If false, it will return the value directly. Default is true.
3593
- */
4390
+ * Gets the maximum time-to-live. When set, any TTL that exceeds this value is capped to maxTtl.
4391
+ * Entries with no TTL will also be capped to maxTtl. Default is `undefined` (no maximum).
4392
+ * @returns {number|string|undefined} - The maximum TTL in milliseconds, human-readable format, or undefined.
4393
+ */
4394
+ get maxTtl() {
4395
+ return this._maxTtl;
4396
+ }
4397
+ /**
4398
+ * Sets the maximum time-to-live. When set, any TTL that exceeds this value is capped to maxTtl.
4399
+ * Entries with no TTL will also be capped to maxTtl.
4400
+ * @param {number|string|undefined} value - The maximum TTL in milliseconds or human-readable format (e.g. '1s', '1h'). If undefined, no maximum is enforced.
4401
+ */
4402
+ set maxTtl(value) {
4403
+ this.setMaxTtl(value);
4404
+ }
4405
+ /**
4406
+ * Gets whether to use clone
4407
+ * @returns {boolean} - If true, it will clone the value before returning it. If false, it will return the value directly. Default is true.
4408
+ */
3594
4409
  get useClone() {
3595
4410
  return this._useClone;
3596
4411
  }
3597
4412
  /**
3598
- * Sets whether to use clone
3599
- * @param {boolean} value - If true, it will clone the value before returning it. If false, it will return the value directly. Default is true.
3600
- */
4413
+ * Sets whether to use clone
4414
+ * @param {boolean} value - If true, it will clone the value before returning it. If false, it will return the value directly. Default is true.
4415
+ */
3601
4416
  set useClone(value) {
3602
4417
  this._useClone = value;
3603
4418
  }
3604
4419
  /**
3605
- * Gets the size of the LRU cache
3606
- * @returns {number} - The size of the LRU cache. If set to 0, it will not use LRU cache. Default is 0. If you are using LRU then the limit is based on Map() size 17mm.
3607
- */
4420
+ * Gets the size of the LRU cache
4421
+ * @returns {number} - The size of the LRU cache. If set to 0, it will not use LRU cache. Default is 0. If you are using LRU then the limit is based on Map() size 17mm.
4422
+ */
3608
4423
  get lruSize() {
3609
4424
  return this._lruSize;
3610
4425
  }
3611
4426
  /**
3612
- * Sets the size of the LRU cache
3613
- * @param {number} value - The size of the LRU cache. If set to 0, it will not use LRU cache. Default is 0. If you are using LRU then the limit is based on Map() size 17mm.
3614
- */
4427
+ * Sets the size of the LRU cache
4428
+ * @param {number} value - The size of the LRU cache. If set to 0, it will not use LRU cache. Default is 0. If you are using LRU then the limit is based on Map() size 17mm.
4429
+ */
3615
4430
  set lruSize(value) {
3616
- if (value > maximumMapSize) {
3617
- this.emit(
3618
- "error",
3619
- new Error(
3620
- `LRU size cannot be larger than ${maximumMapSize} due to Map limitations.`
3621
- )
3622
- );
4431
+ if (value > 16777216) {
4432
+ this.emit("error", /* @__PURE__ */ new Error(`LRU size cannot be larger than ${maximumMapSize} due to Map limitations.`));
3623
4433
  return;
3624
4434
  }
3625
4435
  this._lruSize = value;
@@ -3630,241 +4440,284 @@ var CacheableMemory = class extends Hookified {
3630
4440
  this.lruResize();
3631
4441
  }
3632
4442
  /**
3633
- * Gets the check interval
3634
- * @returns {number} - The interval to check for expired items. If set to 0, it will not check for expired items. Default is 0.
3635
- */
4443
+ * Gets the check interval
4444
+ * @returns {number} - The interval to check for expired items. If set to 0, it will not check for expired items. Default is 0.
4445
+ */
3636
4446
  get checkInterval() {
3637
4447
  return this._checkInterval;
3638
4448
  }
3639
4449
  /**
3640
- * Sets the check interval
3641
- * @param {number} value - The interval to check for expired items. If set to 0, it will not check for expired items. Default is 0.
3642
- */
4450
+ * Sets the check interval
4451
+ * @param {number} value - The interval to check for expired items. If set to 0, it will not check for expired items. Default is 0.
4452
+ */
3643
4453
  set checkInterval(value) {
3644
4454
  this._checkInterval = value;
3645
4455
  }
3646
4456
  /**
3647
- * Gets the size of the cache
3648
- * @returns {number} - The size of the cache
3649
- */
4457
+ * Gets the size of the cache
4458
+ * @returns {number} - The size of the cache
4459
+ */
3650
4460
  get size() {
3651
4461
  let size = 0;
3652
- for (const store of this._store) {
3653
- size += store.size;
3654
- }
4462
+ for (const store of this._store) size += store.size;
3655
4463
  return size;
3656
4464
  }
3657
4465
  /**
3658
- * Gets the number of hash stores
3659
- * @returns {number} - The number of hash stores
3660
- */
4466
+ * Gets the statistics of the cache. Statistics track aggregate counters such as `hits`, `misses`,
4467
+ * `gets`, `sets`, `deletes`, `clears`, `count`, `ksize`, and `vsize`. They are disabled by default;
4468
+ * enable them via the `stats` option or by setting `cache.stats.enabled = true`.
4469
+ * @returns {Stats} - The statistics for this CacheableMemory instance
4470
+ */
4471
+ get stats() {
4472
+ return this._stats;
4473
+ }
4474
+ /**
4475
+ * Gets the number of hash stores
4476
+ * @returns {number} - The number of hash stores
4477
+ */
3661
4478
  get storeHashSize() {
3662
4479
  return this._storeHashSize;
3663
4480
  }
3664
4481
  /**
3665
- * Sets the number of hash stores. This will recreate the store and all data will be cleared
3666
- * @param {number} value - The number of hash stores
3667
- */
4482
+ * Sets the number of hash stores. This will recreate the store and all data will be cleared
4483
+ * @param {number} value - The number of hash stores
4484
+ */
3668
4485
  set storeHashSize(value) {
3669
- if (value === this._storeHashSize) {
3670
- return;
3671
- }
4486
+ if (value === this._storeHashSize) return;
3672
4487
  this._storeHashSize = value;
3673
- this._store = Array.from(
3674
- { length: this._storeHashSize },
3675
- () => /* @__PURE__ */ new Map()
3676
- );
4488
+ this._store = Array.from({ length: this._storeHashSize }, () => /* @__PURE__ */ new Map());
4489
+ if (this._stats.enabled) this._stats.resetStoreValues();
3677
4490
  }
3678
4491
  /**
3679
- * Gets the store hash algorithm
3680
- * @returns {HashAlgorithm | StoreHashAlgorithmFunction} - The store hash algorithm
3681
- */
4492
+ * Gets the store hash algorithm
4493
+ * @returns {HashAlgorithm | StoreHashAlgorithmFunction} - The store hash algorithm
4494
+ */
3682
4495
  get storeHashAlgorithm() {
3683
4496
  return this._storeHashAlgorithm;
3684
4497
  }
3685
4498
  /**
3686
- * Sets the store hash algorithm. This will recreate the store and all data will be cleared
3687
- * @param {HashAlgorithm | HashAlgorithmFunction} value - The store hash algorithm
3688
- */
4499
+ * Sets the store hash algorithm. This will recreate the store and all data will be cleared
4500
+ * @param {HashAlgorithm | HashAlgorithmFunction} value - The store hash algorithm
4501
+ */
3689
4502
  set storeHashAlgorithm(value) {
3690
4503
  this._storeHashAlgorithm = value;
3691
4504
  }
3692
4505
  /**
3693
- * Gets the keys
3694
- * @returns {IterableIterator<string>} - The keys
3695
- */
4506
+ * Gets the keys
4507
+ * @returns {IterableIterator<string>} - The keys
4508
+ */
3696
4509
  get keys() {
3697
4510
  const keys2 = [];
3698
- for (const store of this._store) {
3699
- for (const key of store.keys()) {
3700
- const item = store.get(key);
3701
- if (item && this.hasExpired(item)) {
3702
- store.delete(key);
3703
- continue;
3704
- }
3705
- keys2.push(key);
4511
+ for (const store of this._store) for (const key of store.keys()) {
4512
+ const item = store.get(key);
4513
+ if (item && this.hasExpired(item)) {
4514
+ this.recordExpiration(item);
4515
+ store.delete(key);
4516
+ this.lruRemove(key);
4517
+ continue;
3706
4518
  }
4519
+ keys2.push(key);
3707
4520
  }
3708
4521
  return keys2.values();
3709
4522
  }
3710
4523
  /**
3711
- * Gets the items
3712
- * @returns {IterableIterator<CacheableStoreItem>} - The items
3713
- */
4524
+ * Gets the items
4525
+ * @returns {IterableIterator<CacheableStoreItem>} - The items
4526
+ */
3714
4527
  get items() {
3715
4528
  const items = [];
3716
- for (const store of this._store) {
3717
- for (const item of store.values()) {
3718
- if (this.hasExpired(item)) {
3719
- store.delete(item.key);
3720
- continue;
3721
- }
3722
- items.push(item);
4529
+ for (const store of this._store) for (const item of store.values()) {
4530
+ if (this.hasExpired(item)) {
4531
+ this.recordExpiration(item);
4532
+ store.delete(item.key);
4533
+ this.lruRemove(item.key);
4534
+ continue;
3723
4535
  }
4536
+ items.push(item);
3724
4537
  }
3725
4538
  return items.values();
3726
4539
  }
3727
4540
  /**
3728
- * Gets the store
3729
- * @returns {Array<Map<string, CacheableStoreItem>>} - The store
3730
- */
4541
+ * Gets the store
4542
+ * @returns {Array<Map<string, CacheableStoreItem>>} - The store
4543
+ */
3731
4544
  get store() {
3732
4545
  return this._store;
3733
4546
  }
3734
4547
  /**
3735
- * Gets the value of the key
3736
- * @param {string} key - The key to get the value
3737
- * @returns {T | undefined} - The value of the key
3738
- */
4548
+ * Gets the value of the key
4549
+ * @param {string} key - The key to get the value
4550
+ * @returns {T | undefined} - The value of the key
4551
+ */
3739
4552
  get(key) {
4553
+ this.hookSync("BEFORE_GET", key);
3740
4554
  const store = this.getStore(key);
3741
4555
  const item = store.get(key);
3742
4556
  if (!item) {
3743
- return void 0;
4557
+ this.recordRead(false);
4558
+ this.hookSync("AFTER_GET", {
4559
+ key,
4560
+ result: void 0
4561
+ });
4562
+ return;
3744
4563
  }
3745
4564
  if (item.expires && Date.now() > item.expires) {
4565
+ this.recordExpiration(item);
3746
4566
  store.delete(key);
3747
- return void 0;
4567
+ this.lruRemove(key);
4568
+ this.recordRead(false);
4569
+ this.hookSync("AFTER_GET", {
4570
+ key,
4571
+ result: void 0
4572
+ });
4573
+ return;
3748
4574
  }
3749
4575
  this.lruMoveToFront(key);
3750
- if (!this._useClone) {
3751
- return item.value;
3752
- }
3753
- return this.clone(item.value);
4576
+ let result;
4577
+ if (!this._useClone) result = item.value;
4578
+ else result = this.clone(item.value);
4579
+ this.recordRead(true);
4580
+ this.hookSync("AFTER_GET", {
4581
+ key,
4582
+ result
4583
+ });
4584
+ return result;
3754
4585
  }
3755
4586
  /**
3756
- * Gets the values of the keys
3757
- * @param {string[]} keys - The keys to get the values
3758
- * @returns {T[]} - The values of the keys
3759
- */
4587
+ * Gets the values of the keys
4588
+ * @param {string[]} keys - The keys to get the values
4589
+ * @returns {T[]} - The values of the keys
4590
+ */
3760
4591
  getMany(keys2) {
4592
+ this.hookSync("BEFORE_GET_MANY", keys2);
3761
4593
  const result = [];
3762
- for (const key of keys2) {
3763
- result.push(this.get(key));
3764
- }
4594
+ for (const key of keys2) result.push(this.get(key));
4595
+ this.hookSync("AFTER_GET_MANY", {
4596
+ keys: keys2,
4597
+ result
4598
+ });
3765
4599
  return result;
3766
4600
  }
3767
4601
  /**
3768
- * Gets the raw value of the key
3769
- * @param {string} key - The key to get the value
3770
- * @returns {CacheableStoreItem | undefined} - The raw value of the key
3771
- */
4602
+ * Gets the raw value of the key
4603
+ * @param {string} key - The key to get the value
4604
+ * @returns {CacheableStoreItem | undefined} - The raw value of the key
4605
+ */
3772
4606
  getRaw(key) {
3773
4607
  const store = this.getStore(key);
3774
4608
  const item = store.get(key);
3775
4609
  if (!item) {
3776
- return void 0;
4610
+ this.recordRead(false);
4611
+ return;
3777
4612
  }
3778
- if (item.expires && item.expires && Date.now() > item.expires) {
4613
+ if (item.expires && Date.now() > item.expires) {
4614
+ this.recordExpiration(item);
3779
4615
  store.delete(key);
3780
- return void 0;
4616
+ this.lruRemove(key);
4617
+ this.recordRead(false);
4618
+ return;
3781
4619
  }
3782
4620
  this.lruMoveToFront(key);
4621
+ this.recordRead(true);
3783
4622
  return item;
3784
4623
  }
3785
4624
  /**
3786
- * Gets the raw values of the keys
3787
- * @param {string[]} keys - The keys to get the values
3788
- * @returns {CacheableStoreItem[]} - The raw values of the keys
3789
- */
4625
+ * Gets the raw values of the keys
4626
+ * @param {string[]} keys - The keys to get the values
4627
+ * @returns {CacheableStoreItem[]} - The raw values of the keys
4628
+ */
3790
4629
  getManyRaw(keys2) {
3791
4630
  const result = [];
3792
- for (const key of keys2) {
3793
- result.push(this.getRaw(key));
3794
- }
4631
+ for (const key of keys2) result.push(this.getRaw(key));
3795
4632
  return result;
3796
4633
  }
3797
4634
  /**
3798
- * Sets the value of the key
3799
- * @param {string} key - The key to set the value
3800
- * @param {any} value - The value to set
3801
- * @param {number|string|SetOptions} [ttl] - Time to Live - If you set a number it is miliseconds, if you set a string it is a human-readable.
3802
- * If you want to set expire directly you can do that by setting the expire property in the SetOptions.
3803
- * If you set undefined, it will use the default time-to-live. If both are undefined then it will not have a time-to-live.
3804
- * @returns {void}
3805
- */
4635
+ * Sets the value of the key
4636
+ * @param {string} key - The key to set the value
4637
+ * @param {any} value - The value to set
4638
+ * @param {number|string|SetOptions} [ttl] - Time to Live - If you set a number it is miliseconds, if you set a string it is a human-readable.
4639
+ * If you want to set expire directly you can do that by setting the expire property in the SetOptions.
4640
+ * If you set undefined, it will use the default time-to-live. If both are undefined then it will not have a time-to-live.
4641
+ * @returns {void}
4642
+ */
3806
4643
  set(key, value, ttl) {
3807
- const store = this.getStore(key);
4644
+ const hookItem = {
4645
+ key,
4646
+ value,
4647
+ ttl
4648
+ };
4649
+ this.hookSync("BEFORE_SET", hookItem);
4650
+ const store = this.getStore(hookItem.key);
3808
4651
  let expires;
3809
- if (ttl !== void 0 || this._ttl !== void 0) {
3810
- if (typeof ttl === "object") {
3811
- if (ttl.expire) {
3812
- expires = typeof ttl.expire === "number" ? ttl.expire : ttl.expire.getTime();
3813
- }
3814
- if (ttl.ttl) {
3815
- const finalTtl = shorthandToTime(ttl.ttl);
3816
- if (finalTtl !== void 0) {
3817
- expires = finalTtl;
3818
- }
3819
- }
3820
- } else {
3821
- const finalTtl = shorthandToTime(ttl ?? this._ttl);
3822
- if (finalTtl !== void 0) {
3823
- expires = finalTtl;
4652
+ const effectiveTtl = hookItem.ttl;
4653
+ if (effectiveTtl !== void 0 || this._ttl !== void 0) if (typeof effectiveTtl === "object") {
4654
+ if (effectiveTtl.expire) expires = typeof effectiveTtl.expire === "number" ? effectiveTtl.expire : effectiveTtl.expire.getTime();
4655
+ if (effectiveTtl.ttl) {
4656
+ const finalTtl = shorthandToTime(effectiveTtl.ttl);
4657
+ if (finalTtl !== void 0) expires = finalTtl;
4658
+ }
4659
+ } else {
4660
+ const finalTtl = shorthandToTime(effectiveTtl ?? this._ttl);
4661
+ if (finalTtl !== void 0) expires = finalTtl;
4662
+ }
4663
+ if (this._maxTtl !== void 0) {
4664
+ const maxExpires = shorthandToTime(this._maxTtl);
4665
+ if (expires === void 0) expires = maxExpires;
4666
+ else if (expires > maxExpires) expires = maxExpires;
4667
+ }
4668
+ if (this._lruSize > 0) if (store.has(hookItem.key)) this.lruMoveToFront(hookItem.key);
4669
+ else {
4670
+ this.lruAddToFront(hookItem.key);
4671
+ if (this._lru.size > this._lruSize) {
4672
+ const oldestKey = this._lru.getOldest();
4673
+ if (oldestKey) {
4674
+ this._lru.removeOldest();
4675
+ this.delete(oldestKey);
3824
4676
  }
3825
4677
  }
3826
4678
  }
3827
- if (this._lruSize > 0) {
3828
- if (store.has(key)) {
3829
- this.lruMoveToFront(key);
3830
- } else {
3831
- this.lruAddToFront(key);
3832
- if (this._lru.size > this._lruSize) {
3833
- const oldestKey = this._lru.getOldest();
3834
- if (oldestKey) {
3835
- this._lru.removeOldest();
3836
- this.delete(oldestKey);
3837
- }
3838
- }
4679
+ if (this._stats.enabled) {
4680
+ const existing = store.get(hookItem.key);
4681
+ if (existing) this._stats.decreaseVSize(existing.value);
4682
+ else {
4683
+ this._stats.incrementKSize(hookItem.key);
4684
+ this._stats.incrementCount();
3839
4685
  }
4686
+ this._stats.incrementVSize(hookItem.value);
4687
+ this._stats.incrementSets();
3840
4688
  }
3841
- const item = { key, value, expires };
3842
- store.set(key, item);
4689
+ const item = {
4690
+ key: hookItem.key,
4691
+ value: hookItem.value,
4692
+ expires
4693
+ };
4694
+ store.set(hookItem.key, item);
4695
+ this.hookSync("AFTER_SET", hookItem);
3843
4696
  }
3844
4697
  /**
3845
- * Sets the values of the keys
3846
- * @param {CacheableItem[]} items - The items to set
3847
- * @returns {void}
3848
- */
4698
+ * Sets the values of the keys
4699
+ * @param {CacheableItem[]} items - The items to set
4700
+ * @returns {void}
4701
+ */
3849
4702
  setMany(items) {
3850
- for (const item of items) {
3851
- this.set(item.key, item.value, item.ttl);
3852
- }
4703
+ this.hookSync("BEFORE_SET_MANY", items);
4704
+ for (const item of items) this.set(item.key, item.value, item.ttl);
4705
+ this.hookSync("AFTER_SET_MANY", items);
3853
4706
  }
3854
4707
  /**
3855
- * Checks if the key exists
3856
- * @param {string} key - The key to check
3857
- * @returns {boolean} - If true, the key exists. If false, the key does not exist.
3858
- */
4708
+ * Checks if the key exists
4709
+ * @param {string} key - The key to check
4710
+ * @returns {boolean} - If true, the key exists. If false, the key does not exist.
4711
+ */
3859
4712
  has(key) {
3860
4713
  const item = this.get(key);
3861
4714
  return Boolean(item);
3862
4715
  }
3863
4716
  /**
3864
- * @function hasMany
3865
- * @param {string[]} keys - The keys to check
3866
- * @returns {boolean[]} - If true, the key exists. If false, the key does not exist.
3867
- */
4717
+ * @function hasMany
4718
+ * @param {string[]} keys - The keys to check
4719
+ * @returns {boolean[]} - If true, the key exists. If false, the key does not exist.
4720
+ */
3868
4721
  hasMany(keys2) {
3869
4722
  const result = [];
3870
4723
  for (const key of keys2) {
@@ -3874,65 +4727,76 @@ var CacheableMemory = class extends Hookified {
3874
4727
  return result;
3875
4728
  }
3876
4729
  /**
3877
- * Take will get the key and delete the entry from cache
3878
- * @param {string} key - The key to take
3879
- * @returns {T | undefined} - The value of the key
3880
- */
4730
+ * Take will get the key and delete the entry from cache
4731
+ * @param {string} key - The key to take
4732
+ * @returns {T | undefined} - The value of the key
4733
+ */
3881
4734
  take(key) {
3882
4735
  const item = this.get(key);
3883
- if (!item) {
3884
- return void 0;
3885
- }
4736
+ if (!item) return;
3886
4737
  this.delete(key);
3887
4738
  return item;
3888
4739
  }
3889
4740
  /**
3890
- * TakeMany will get the keys and delete the entries from cache
3891
- * @param {string[]} keys - The keys to take
3892
- * @returns {T[]} - The values of the keys
3893
- */
4741
+ * TakeMany will get the keys and delete the entries from cache
4742
+ * @param {string[]} keys - The keys to take
4743
+ * @returns {T[]} - The values of the keys
4744
+ */
3894
4745
  takeMany(keys2) {
3895
4746
  const result = [];
3896
- for (const key of keys2) {
3897
- result.push(this.take(key));
3898
- }
4747
+ for (const key of keys2) result.push(this.take(key));
3899
4748
  return result;
3900
4749
  }
3901
4750
  /**
3902
- * Delete the key
3903
- * @param {string} key - The key to delete
3904
- * @returns {void}
3905
- */
4751
+ * Delete the key
4752
+ * @param {string} key - The key to delete
4753
+ * @returns {void}
4754
+ */
3906
4755
  delete(key) {
4756
+ this.hookSync("BEFORE_DELETE", key);
3907
4757
  const store = this.getStore(key);
4758
+ if (this._stats.enabled) {
4759
+ const item = store.get(key);
4760
+ if (item) {
4761
+ this._stats.decreaseKSize(key);
4762
+ this._stats.decreaseVSize(item.value);
4763
+ this._stats.decreaseCount();
4764
+ this._stats.incrementDeletes();
4765
+ }
4766
+ }
3908
4767
  store.delete(key);
4768
+ this.lruRemove(key);
4769
+ this.hookSync("AFTER_DELETE", key);
3909
4770
  }
3910
4771
  /**
3911
- * Delete the keys
3912
- * @param {string[]} keys - The keys to delete
3913
- * @returns {void}
3914
- */
4772
+ * Delete the keys
4773
+ * @param {string[]} keys - The keys to delete
4774
+ * @returns {void}
4775
+ */
3915
4776
  deleteMany(keys2) {
3916
- for (const key of keys2) {
3917
- this.delete(key);
3918
- }
4777
+ this.hookSync("BEFORE_DELETE_MANY", keys2);
4778
+ for (const key of keys2) this.delete(key);
4779
+ this.hookSync("AFTER_DELETE_MANY", keys2);
3919
4780
  }
3920
4781
  /**
3921
- * Clear the cache
3922
- * @returns {void}
3923
- */
4782
+ * Clear the cache
4783
+ * @returns {void}
4784
+ */
3924
4785
  clear() {
3925
- this._store = Array.from(
3926
- { length: this._storeHashSize },
3927
- () => /* @__PURE__ */ new Map()
3928
- );
4786
+ this.hookSync("BEFORE_CLEAR");
4787
+ this._store = Array.from({ length: this._storeHashSize }, () => /* @__PURE__ */ new Map());
3929
4788
  this._lru = new DoublyLinkedList();
4789
+ if (this._stats.enabled) {
4790
+ this._stats.resetStoreValues();
4791
+ this._stats.incrementClears();
4792
+ }
4793
+ this.hookSync("AFTER_CLEAR");
3930
4794
  }
3931
4795
  /**
3932
- * Get the store based on the key (internal use)
3933
- * @param {string} key - The key to get the store
3934
- * @returns {CacheableHashStore} - The store
3935
- */
4796
+ * Get the store based on the key (internal use)
4797
+ * @param {string} key - The key to get the store
4798
+ * @returns {CacheableHashStore} - The store
4799
+ */
3936
4800
  getStore(key) {
3937
4801
  var _a;
3938
4802
  const hash2 = this.getKeyStoreHash(key);
@@ -3940,64 +4804,60 @@ var CacheableMemory = class extends Hookified {
3940
4804
  return this._store[hash2];
3941
4805
  }
3942
4806
  /**
3943
- * Hash the key for which store to go to (internal use)
3944
- * @param {string} key - The key to hash
3945
- * Available algorithms are: SHA256, SHA1, MD5, and djb2Hash.
3946
- * @returns {number} - The hashed key as a number
3947
- */
4807
+ * Hash the key for which store to go to (internal use)
4808
+ * @param {string} key - The key to hash
4809
+ * Available algorithms are: SHA256, SHA1, MD5, and djb2Hash.
4810
+ * @returns {number} - The hashed key as a number
4811
+ */
3948
4812
  getKeyStoreHash(key) {
3949
- if (this._store.length === 1) {
3950
- return 0;
3951
- }
3952
- if (typeof this._storeHashAlgorithm === "function") {
3953
- return this._storeHashAlgorithm(key, this._storeHashSize);
3954
- }
3955
- const storeHashSize = this._storeHashSize - 1;
3956
- const hash2 = hashToNumberSync(key, {
4813
+ if (this._store.length === 1) return 0;
4814
+ if (typeof this._storeHashAlgorithm === "function") return this._storeHashAlgorithm(key, this._storeHashSize);
4815
+ return hashToNumberSync(key, {
3957
4816
  min: 0,
3958
- max: storeHashSize,
4817
+ max: this._storeHashSize - 1,
3959
4818
  algorithm: this._storeHashAlgorithm
3960
4819
  });
3961
- return hash2;
3962
4820
  }
3963
4821
  /**
3964
- * Clone the value. This is for internal use
3965
- * @param {any} value - The value to clone
3966
- * @returns {any} - The cloned value
3967
- */
3968
- // biome-ignore lint/suspicious/noExplicitAny: type format
4822
+ * Clone the value. This is for internal use
4823
+ * @param {any} value - The value to clone
4824
+ * @returns {any} - The cloned value
4825
+ */
3969
4826
  clone(value) {
3970
- if (this.isPrimitive(value)) {
3971
- return value;
3972
- }
4827
+ if (this.isPrimitive(value)) return value;
3973
4828
  return structuredClone(value);
3974
4829
  }
3975
4830
  /**
3976
- * Add to the front of the LRU cache. This is for internal use
3977
- * @param {string} key - The key to add to the front
3978
- * @returns {void}
3979
- */
4831
+ * Add to the front of the LRU cache. This is for internal use
4832
+ * @param {string} key - The key to add to the front
4833
+ * @returns {void}
4834
+ */
3980
4835
  lruAddToFront(key) {
3981
- if (this._lruSize === 0) {
3982
- return;
3983
- }
4836
+ if (this._lruSize === 0) return;
3984
4837
  this._lru.addToFront(key);
3985
4838
  }
3986
4839
  /**
3987
- * Move to the front of the LRU cache. This is for internal use
3988
- * @param {string} key - The key to move to the front
3989
- * @returns {void}
3990
- */
4840
+ * Move to the front of the LRU cache. This is for internal use
4841
+ * @param {string} key - The key to move to the front
4842
+ * @returns {void}
4843
+ */
3991
4844
  lruMoveToFront(key) {
3992
- if (this._lruSize === 0) {
3993
- return;
3994
- }
4845
+ if (this._lruSize === 0) return;
3995
4846
  this._lru.moveToFront(key);
3996
4847
  }
3997
4848
  /**
3998
- * Resize the LRU cache. This is for internal use.
3999
- * @returns {void}
4000
- */
4849
+ * Remove a key from the LRU cache. This is for internal use
4850
+ * @param {string} key - The key to remove
4851
+ * @returns {void}
4852
+ */
4853
+ lruRemove(key) {
4854
+ if (this._lruSize === 0) return;
4855
+ this._lru.remove(key);
4856
+ }
4857
+ /**
4858
+ * Resize the LRU cache. This is for internal use.
4859
+ * @returns {void}
4860
+ */
4001
4861
  lruResize() {
4002
4862
  while (this._lru.size > this._lruSize) {
4003
4863
  const oldestKey = this._lru.getOldest();
@@ -4008,83 +4868,116 @@ var CacheableMemory = class extends Hookified {
4008
4868
  }
4009
4869
  }
4010
4870
  /**
4011
- * Check for expiration. This is for internal use
4012
- * @returns {void}
4013
- */
4871
+ * Check for expiration. This is for internal use
4872
+ * @returns {void}
4873
+ */
4014
4874
  checkExpiration() {
4015
- for (const store of this._store) {
4016
- for (const item of store.values()) {
4017
- if (item.expires && Date.now() > item.expires) {
4018
- store.delete(item.key);
4019
- }
4020
- }
4875
+ for (const store of this._store) for (const item of store.values()) if (item.expires && Date.now() > item.expires) {
4876
+ this.recordExpiration(item);
4877
+ store.delete(item.key);
4878
+ this.lruRemove(item.key);
4021
4879
  }
4022
4880
  }
4023
4881
  /**
4024
- * Start the interval check. This is for internal use
4025
- * @returns {void}
4026
- */
4882
+ * Start the interval check. This is for internal use
4883
+ * @returns {void}
4884
+ */
4027
4885
  startIntervalCheck() {
4028
4886
  if (this._checkInterval > 0) {
4029
- if (this._interval) {
4887
+ if (this._interval)
4030
4888
  clearInterval(this._interval);
4031
- }
4032
4889
  this._interval = setInterval(() => {
4033
4890
  this.checkExpiration();
4034
4891
  }, this._checkInterval).unref();
4035
4892
  }
4036
4893
  }
4037
4894
  /**
4038
- * Stop the interval check. This is for internal use
4039
- * @returns {void}
4040
- */
4895
+ * Stop the interval check. This is for internal use
4896
+ * @returns {void}
4897
+ */
4041
4898
  stopIntervalCheck() {
4042
- if (this._interval) {
4043
- clearInterval(this._interval);
4044
- }
4899
+ if (this._interval) clearInterval(this._interval);
4045
4900
  this._interval = 0;
4046
4901
  this._checkInterval = 0;
4047
4902
  }
4048
4903
  /**
4049
- * Wrap the function for caching
4050
- * @param {Function} function_ - The function to wrap
4051
- * @param {Object} [options] - The options to wrap
4052
- * @returns {Function} - The wrapped function
4053
- */
4054
- // biome-ignore lint/suspicious/noExplicitAny: type format
4904
+ * Wrap the function for caching
4905
+ * @param {Function} function_ - The function to wrap
4906
+ * @param {Object} [options] - The options to wrap
4907
+ * @returns {Function} - The wrapped function
4908
+ */
4055
4909
  wrap(function_, options) {
4056
- const wrapOptions = {
4910
+ return wrapSync(function_, {
4057
4911
  ttl: options?.ttl ?? this._ttl,
4058
4912
  keyPrefix: options?.keyPrefix,
4059
4913
  createKey: options?.createKey,
4060
4914
  cache: this
4061
- };
4062
- return wrapSync(function_, wrapOptions);
4915
+ });
4916
+ }
4917
+ /**
4918
+ * Gets the value of the key, or computes and stores it on a cache miss. This is the synchronous
4919
+ * cache-aside helper: if the key is present its value is returned, otherwise `function_` is
4920
+ * invoked, its result is stored, and that result is returned.
4921
+ *
4922
+ * The value is stored using `options.ttl`, falling back to the instance default `ttl`. Because
4923
+ * the cache is synchronous there is no request coalescing — concurrent callers cannot stampede
4924
+ * the setter the way they can with an async cache.
4925
+ * @param {GetOrSetSyncKey} key - The key to get or set. Can also be a function that returns the key.
4926
+ * @param {() => T} function_ - The function that computes the value on a cache miss.
4927
+ * @param {GetOrSetFunctionOptions} [options] - Options such as `ttl`, `cacheErrors`, and `throwErrors`.
4928
+ * @returns {T | undefined} - The cached or freshly computed value
4929
+ */
4930
+ getOrSet(key, function_, options) {
4931
+ return getOrSetSync(key, function_, {
4932
+ cache: this,
4933
+ ttl: options?.ttl ?? this._ttl,
4934
+ cacheErrors: options?.cacheErrors,
4935
+ throwErrors: options?.throwErrors
4936
+ });
4937
+ }
4938
+ /**
4939
+ * Records a single read against the statistics counters. Each read increments `gets` and either
4940
+ * `hits` or `misses`. No-op when statistics are disabled. This is for internal use.
4941
+ * @param {boolean} hit - Whether the read found a (non-expired) value
4942
+ * @returns {void}
4943
+ */
4944
+ recordRead(hit) {
4945
+ if (!this._stats.enabled) return;
4946
+ if (hit) this._stats.incrementHits();
4947
+ else this._stats.incrementMisses();
4948
+ this._stats.incrementGets();
4949
+ }
4950
+ /**
4951
+ * Decrements the size statistics (`count`, `ksize`, and `vsize`) for an entry that is being removed
4952
+ * because it expired. Expirations are not counted as `deletes` since they are not user-initiated.
4953
+ * No-op when statistics are disabled. This is for internal use.
4954
+ * @param {CacheableStoreItem} item - The expired item being removed from the store
4955
+ * @returns {void}
4956
+ */
4957
+ recordExpiration(item) {
4958
+ if (!this._stats.enabled) return;
4959
+ this._stats.decreaseKSize(item.key);
4960
+ this._stats.decreaseVSize(item.value);
4961
+ this._stats.decreaseCount();
4063
4962
  }
4064
- // biome-ignore lint/suspicious/noExplicitAny: type format
4065
4963
  isPrimitive(value) {
4066
4964
  const result = false;
4067
- if (value === null || value === void 0) {
4068
- return true;
4069
- }
4070
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
4071
- return true;
4072
- }
4965
+ if (value === null || value === void 0) return true;
4966
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return true;
4073
4967
  return result;
4074
4968
  }
4075
4969
  setTtl(ttl) {
4076
- if (typeof ttl === "string" || ttl === void 0) {
4077
- this._ttl = ttl;
4078
- } else if (ttl > 0) {
4079
- this._ttl = ttl;
4080
- } else {
4081
- this._ttl = void 0;
4082
- }
4970
+ if (typeof ttl === "string" || ttl === void 0) this._ttl = ttl;
4971
+ else if (ttl > 0) this._ttl = ttl;
4972
+ else this._ttl = void 0;
4973
+ }
4974
+ setMaxTtl(maxTtl) {
4975
+ if (typeof maxTtl === "string" || maxTtl === void 0) this._maxTtl = maxTtl;
4976
+ else if (maxTtl > 0) this._maxTtl = maxTtl;
4977
+ else this._maxTtl = void 0;
4083
4978
  }
4084
4979
  hasExpired(item) {
4085
- if (item.expires && Date.now() > item.expires) {
4086
- return true;
4087
- }
4980
+ if (item.expires && Date.now() > item.expires) return true;
4088
4981
  return false;
4089
4982
  }
4090
4983
  };
@@ -4099,26 +4992,21 @@ var object = "object";
4099
4992
  var noop = (_2, value) => value;
4100
4993
  var primitives = (value) => value instanceof Primitive ? Primitive(value) : value;
4101
4994
  var Primitives = (_2, value) => typeof value === primitive ? new Primitive(value) : value;
4102
- var revive = (input, parsed, output, $) => {
4103
- const lazy = [];
4995
+ var resolver = (input, lazy, parsed, $) => (output) => {
4104
4996
  for (let ke = keys(output), { length } = ke, y = 0; y < length; y++) {
4105
4997
  const k = ke[y];
4106
4998
  const value = output[k];
4107
4999
  if (value instanceof Primitive) {
4108
- const tmp = input[value];
5000
+ const tmp = input[+value];
4109
5001
  if (typeof tmp === object && !parsed.has(tmp)) {
4110
5002
  parsed.add(tmp);
4111
5003
  output[k] = ignore;
4112
- lazy.push({ k, a: [input, parsed, tmp, $] });
5004
+ lazy.push({ o: output, k, r: tmp });
4113
5005
  } else
4114
5006
  output[k] = $.call(output, k, tmp);
4115
5007
  } else if (output[k] !== ignore)
4116
5008
  output[k] = $.call(output, k, value);
4117
5009
  }
4118
- for (let { length } = lazy, i = 0; i < length; i++) {
4119
- const { k, a } = lazy[i];
4120
- output[k] = $.call(output, k, revive.apply(null, a));
4121
- }
4122
5010
  return output;
4123
5011
  };
4124
5012
  var set = (known, input, value) => {
@@ -4128,10 +5016,19 @@ var set = (known, input, value) => {
4128
5016
  };
4129
5017
  var parse = (text, reviver) => {
4130
5018
  const input = $parse(text, Primitives).map(primitives);
4131
- const value = input[0];
4132
5019
  const $ = reviver || noop;
4133
- const tmp = typeof value === object && value ? revive(input, /* @__PURE__ */ new Set(), value, $) : value;
4134
- return $.call({ "": tmp }, "", tmp);
5020
+ let value = input[0];
5021
+ if (typeof value === object && value) {
5022
+ const lazy = [];
5023
+ const revive = resolver(input, lazy, /* @__PURE__ */ new Set(), $);
5024
+ value = revive(value);
5025
+ let i = 0;
5026
+ while (i < lazy.length) {
5027
+ const { o, k, r } = lazy[i++];
5028
+ o[k] = $.call(o, k, revive(r));
5029
+ }
5030
+ }
5031
+ return $.call({ "": value }, "", value);
4135
5032
  };
4136
5033
  var stringify2 = (value, replacer, space) => {
4137
5034
  const $ = replacer && typeof replacer === object ? (k, v) => k === "" || -1 < replacer.indexOf(k) ? v : void 0 : replacer || noop;
@@ -4161,7 +5058,7 @@ var stringify2 = (value, replacer, space) => {
4161
5058
  }
4162
5059
  };
4163
5060
 
4164
- // node_modules/file-entry-cache/node_modules/flat-cache/dist/index.js
5061
+ // node_modules/file-entry-cache/node_modules/flat-cache/dist/index.mjs
4165
5062
  var FlatCache = class extends Hookified {
4166
5063
  _cache = new CacheableMemory();
4167
5064
  _cacheDir = ".cache";
@@ -4173,169 +5070,137 @@ var FlatCache = class extends Hookified {
4173
5070
  _stringify = stringify2;
4174
5071
  constructor(options) {
4175
5072
  super();
4176
- if (options) {
4177
- this._cache = new CacheableMemory({
4178
- ttl: options.ttl,
4179
- useClone: options.useClone,
4180
- lruSize: options.lruSize,
4181
- checkInterval: options.expirationInterval
4182
- });
4183
- }
4184
- if (options?.cacheDir) {
4185
- this._cacheDir = options.cacheDir;
4186
- }
4187
- if (options?.cacheId) {
4188
- this._cacheId = options.cacheId;
4189
- }
5073
+ if (options) this._cache = new CacheableMemory({
5074
+ ttl: options.ttl,
5075
+ useClone: options.useClone,
5076
+ lruSize: options.lruSize,
5077
+ checkInterval: options.expirationInterval
5078
+ });
5079
+ if (options?.cacheDir) this._cacheDir = options.cacheDir;
5080
+ if (options?.cacheId) this._cacheId = options.cacheId;
4190
5081
  if (options?.persistInterval) {
4191
5082
  this._persistInterval = options.persistInterval;
4192
5083
  this.startAutoPersist();
4193
5084
  }
4194
- if (options?.deserialize) {
4195
- this._parse = options.deserialize;
4196
- }
4197
- if (options?.serialize) {
4198
- this._stringify = options.serialize;
4199
- }
5085
+ if (options?.deserialize) this._parse = options.deserialize;
5086
+ if (options?.serialize) this._stringify = options.serialize;
4200
5087
  }
4201
5088
  /**
4202
- * The cache object
4203
- * @property cache
4204
- * @type {CacheableMemory}
4205
- */
5089
+ * The cache object
5090
+ * @property cache
5091
+ * @type {CacheableMemory}
5092
+ */
4206
5093
  get cache() {
4207
5094
  return this._cache;
4208
5095
  }
4209
5096
  /**
4210
- * The cache directory
4211
- * @property cacheDir
4212
- * @type {String}
4213
- * @default '.cache'
4214
- */
5097
+ * The cache directory
5098
+ * @property cacheDir
5099
+ * @type {String}
5100
+ * @default '.cache'
5101
+ */
4215
5102
  get cacheDir() {
4216
5103
  return this._cacheDir;
4217
5104
  }
4218
5105
  /**
4219
- * Set the cache directory
4220
- * @property cacheDir
4221
- * @type {String}
4222
- * @default '.cache'
4223
- */
5106
+ * Set the cache directory
5107
+ * @property cacheDir
5108
+ * @type {String}
5109
+ * @default '.cache'
5110
+ */
4224
5111
  set cacheDir(value) {
4225
5112
  this._cacheDir = value;
4226
5113
  }
4227
5114
  /**
4228
- * The cache id
4229
- * @property cacheId
4230
- * @type {String}
4231
- * @default 'cache1'
4232
- */
5115
+ * The cache id
5116
+ * @property cacheId
5117
+ * @type {String}
5118
+ * @default 'cache1'
5119
+ */
4233
5120
  get cacheId() {
4234
5121
  return this._cacheId;
4235
5122
  }
4236
5123
  /**
4237
- * Set the cache id
4238
- * @property cacheId
4239
- * @type {String}
4240
- * @default 'cache1'
4241
- */
5124
+ * Set the cache id
5125
+ * @property cacheId
5126
+ * @type {String}
5127
+ * @default 'cache1'
5128
+ */
4242
5129
  set cacheId(value) {
4243
5130
  this._cacheId = value;
4244
5131
  }
4245
5132
  /**
4246
- * The flag to indicate if there are changes since the last save
4247
- * @property changesSinceLastSave
4248
- * @type {Boolean}
4249
- * @default false
4250
- */
5133
+ * The flag to indicate if there are changes since the last save
5134
+ * @property changesSinceLastSave
5135
+ * @type {Boolean}
5136
+ * @default false
5137
+ */
4251
5138
  get changesSinceLastSave() {
4252
5139
  return this._changesSinceLastSave;
4253
5140
  }
4254
5141
  /**
4255
- * The interval to persist the cache to disk. 0 means no timed persistence
4256
- * @property persistInterval
4257
- * @type {Number}
4258
- * @default 0
4259
- */
5142
+ * The interval to persist the cache to disk. 0 means no timed persistence
5143
+ * @property persistInterval
5144
+ * @type {Number}
5145
+ * @default 0
5146
+ */
4260
5147
  get persistInterval() {
4261
5148
  return this._persistInterval;
4262
5149
  }
4263
5150
  /**
4264
- * Set the interval to persist the cache to disk. 0 means no timed persistence
4265
- * @property persistInterval
4266
- * @type {Number}
4267
- * @default 0
4268
- */
5151
+ * Set the interval to persist the cache to disk. 0 means no timed persistence
5152
+ * @property persistInterval
5153
+ * @type {Number}
5154
+ * @default 0
5155
+ */
4269
5156
  set persistInterval(value) {
4270
5157
  this._persistInterval = value;
4271
5158
  }
4272
5159
  /**
4273
- * Load a cache identified by the given Id. If the element does not exists, then initialize an empty
4274
- * cache storage. If specified `cacheDir` will be used as the directory to persist the data to. If omitted
4275
- * then the cache module directory `.cacheDir` will be used instead
4276
- *
4277
- * @method load
4278
- * @param cacheId {String} the id of the cache, would also be used as the name of the file cache
4279
- * @param cacheDir {String} directory for the cache entry
4280
- */
5160
+ * Load a cache identified by the given Id. If the element does not exists, then initialize an empty
5161
+ * cache storage. If specified `cacheDir` will be used as the directory to persist the data to. If omitted
5162
+ * then the cache module directory `.cacheDir` will be used instead
5163
+ *
5164
+ * @method load
5165
+ * @param cacheId {String} the id of the cache, would also be used as the name of the file cache
5166
+ * @param cacheDir {String} directory for the cache entry
5167
+ */
4281
5168
  load(cacheId, cacheDir) {
4282
5169
  try {
4283
- const filePath = path10.resolve(
4284
- `${cacheDir ?? this._cacheDir}/${cacheId ?? this._cacheId}`
4285
- );
5170
+ const filePath = path10.resolve(`${cacheDir ?? this._cacheDir}/${cacheId ?? this._cacheId}`);
4286
5171
  this.loadFile(filePath);
4287
- this.emit(
4288
- "load"
4289
- /* LOAD */
4290
- );
5172
+ this.emit("load");
4291
5173
  } catch (error) {
4292
5174
  this.emit("error", error);
4293
5175
  }
4294
5176
  }
4295
5177
  /**
4296
- * Load the cache from the provided file
4297
- * @method loadFile
4298
- * @param {String} pathToFile the path to the file containing the info for the cache
4299
- */
5178
+ * Load the cache from the provided file
5179
+ * @method loadFile
5180
+ * @param {String} pathToFile the path to the file containing the info for the cache
5181
+ */
4300
5182
  loadFile(pathToFile) {
4301
5183
  if (fs5.existsSync(pathToFile)) {
4302
5184
  const data = fs5.readFileSync(pathToFile, "utf8");
4303
5185
  const items = this._parse(data);
4304
5186
  if (Array.isArray(items)) {
4305
- for (const item of items) {
4306
- if (item && typeof item === "object" && "key" in item) {
4307
- if (item.expires) {
4308
- this._cache.set(item.key, item.value, { expire: item.expires });
4309
- } else if (item.timestamp) {
4310
- this._cache.set(item.key, item.value, { expire: item.timestamp });
4311
- } else {
4312
- this._cache.set(item.key, item.value);
4313
- }
4314
- }
4315
- }
4316
- } else {
4317
- for (const key of Object.keys(items)) {
4318
- const item = items[key];
4319
- if (item && typeof item === "object" && "key" in item) {
4320
- this._cache.set(item.key, item.value, {
4321
- expire: item.expires
4322
- });
4323
- } else {
4324
- if (item && typeof item === "object" && item.timestamp) {
4325
- this._cache.set(key, item, { expire: item.timestamp });
4326
- } else {
4327
- this._cache.set(key, item);
4328
- }
4329
- }
4330
- }
5187
+ for (const item of items) if (item && typeof item === "object" && "key" in item) if (item.expires) this._cache.set(item.key, item.value, { expire: item.expires });
5188
+ else if (item.timestamp)
5189
+ this._cache.set(item.key, item.value, { expire: item.timestamp });
5190
+ else this._cache.set(item.key, item.value);
5191
+ } else for (const key of Object.keys(items)) {
5192
+ const item = items[key];
5193
+ if (item && typeof item === "object" && "key" in item) this._cache.set(item.key, item.value, { expire: item.expires });
5194
+ else if (item && typeof item === "object" && item.timestamp)
5195
+ this._cache.set(key, item, { expire: item.timestamp });
5196
+ else this._cache.set(key, item);
4331
5197
  }
4332
5198
  this._changesSinceLastSave = true;
4333
5199
  }
4334
5200
  }
4335
5201
  loadFileStream(pathToFile, onProgress, onEnd, onError) {
4336
5202
  if (fs5.existsSync(pathToFile)) {
4337
- const stats = fs5.statSync(pathToFile);
4338
- const total = stats.size;
5203
+ const total = fs5.statSync(pathToFile).size;
4339
5204
  let loaded = 0;
4340
5205
  let streamData = "";
4341
5206
  const readStream = fs5.createReadStream(pathToFile, { encoding: "utf8" });
@@ -4346,179 +5211,158 @@ var FlatCache = class extends Hookified {
4346
5211
  });
4347
5212
  readStream.on("end", () => {
4348
5213
  const items = this._parse(streamData);
4349
- for (const key of Object.keys(items)) {
4350
- this._cache.set(items[key].key, items[key].value, {
4351
- expire: items[key].expires
4352
- });
4353
- }
5214
+ for (const key of Object.keys(items)) this._cache.set(items[key].key, items[key].value, { expire: items[key].expires });
4354
5215
  this._changesSinceLastSave = true;
4355
5216
  onEnd();
4356
5217
  });
4357
5218
  readStream.on("error", (error) => {
4358
5219
  this.emit("error", error);
4359
- if (onError) {
4360
- onError(error);
4361
- }
5220
+ if (onError) onError(error);
4362
5221
  });
4363
5222
  } else {
4364
- const error = new Error(`Cache file ${pathToFile} does not exist`);
5223
+ const error = /* @__PURE__ */ new Error(`Cache file ${pathToFile} does not exist`);
4365
5224
  this.emit("error", error);
4366
- if (onError) {
4367
- onError(error);
4368
- }
5225
+ if (onError) onError(error);
4369
5226
  }
4370
5227
  }
4371
5228
  /**
4372
- * Returns the entire persisted object
4373
- * @method all
4374
- * @returns {*}
4375
- */
5229
+ * Returns the entire persisted object
5230
+ * @method all
5231
+ * @returns {*}
5232
+ */
4376
5233
  all() {
4377
5234
  const result = {};
4378
5235
  const items = [...this._cache.items];
4379
- for (const item of items) {
4380
- result[item.key] = item.value;
4381
- }
5236
+ for (const item of items) result[item.key] = item.value;
4382
5237
  return result;
4383
5238
  }
4384
5239
  /**
4385
- * Returns an array with all the items in the cache { key, value, expires }
4386
- * @method items
4387
- * @returns {Array}
4388
- */
4389
- // biome-ignore lint/suspicious/noExplicitAny: cache items can store any value
5240
+ * Returns an array with all the items in the cache { key, value, expires }
5241
+ * @method items
5242
+ * @returns {Array}
5243
+ */
4390
5244
  get items() {
4391
5245
  return [...this._cache.items];
4392
5246
  }
4393
5247
  /**
4394
- * Returns the path to the file where the cache is persisted
4395
- * @method cacheFilePath
4396
- * @returns {String}
4397
- */
5248
+ * Returns the path to the file where the cache is persisted
5249
+ * @method cacheFilePath
5250
+ * @returns {String}
5251
+ */
4398
5252
  get cacheFilePath() {
4399
5253
  return path10.resolve(`${this._cacheDir}/${this._cacheId}`);
4400
5254
  }
4401
5255
  /**
4402
- * Returns the path to the cache directory
4403
- * @method cacheDirPath
4404
- * @returns {String}
4405
- */
5256
+ * Returns the path to the cache directory
5257
+ * @method cacheDirPath
5258
+ * @returns {String}
5259
+ */
4406
5260
  get cacheDirPath() {
4407
5261
  return path10.resolve(this._cacheDir);
4408
5262
  }
4409
5263
  /**
4410
- * Returns an array with all the keys in the cache
4411
- * @method keys
4412
- * @returns {Array}
4413
- */
5264
+ * Returns an array with all the keys in the cache
5265
+ * @method keys
5266
+ * @returns {Array}
5267
+ */
4414
5268
  keys() {
4415
5269
  return [...this._cache.keys];
4416
5270
  }
4417
5271
  /**
4418
- * (Legacy) set key method. This method will be deprecated in the future
4419
- * @method setKey
4420
- * @param key {string} the key to set
4421
- * @param value {object} the value of the key. Could be any object that can be serialized with JSON.stringify
4422
- */
4423
- // biome-ignore lint/suspicious/noExplicitAny: type format
5272
+ * (Legacy) set key method. This method will be deprecated in the future
5273
+ * @method setKey
5274
+ * @param key {string} the key to set
5275
+ * @param value {object} the value of the key. Could be any object that can be serialized with JSON.stringify
5276
+ */
4424
5277
  setKey(key, value, ttl) {
4425
5278
  this.set(key, value, ttl);
4426
5279
  }
4427
5280
  /**
4428
- * Sets a key to a given value
4429
- * @method set
4430
- * @param key {string} the key to set
4431
- * @param value {object} the value of the key. Could be any object that can be serialized with JSON.stringify
4432
- * @param [ttl] {number} the time to live in milliseconds
4433
- */
4434
- // biome-ignore lint/suspicious/noExplicitAny: type format
5281
+ * Sets a key to a given value
5282
+ * @method set
5283
+ * @param key {string} the key to set
5284
+ * @param value {object} the value of the key. Could be any object that can be serialized with JSON.stringify
5285
+ * @param [ttl] {number} the time to live in milliseconds
5286
+ */
4435
5287
  set(key, value, ttl) {
4436
5288
  this._cache.set(key, value, ttl);
4437
5289
  this._changesSinceLastSave = true;
4438
5290
  }
4439
5291
  /**
4440
- * (Legacy) Remove a given key from the cache. This method will be deprecated in the future
4441
- * @method removeKey
4442
- * @param key {String} the key to remove from the object
4443
- */
5292
+ * (Legacy) Remove a given key from the cache. This method will be deprecated in the future
5293
+ * @method removeKey
5294
+ * @param key {String} the key to remove from the object
5295
+ */
4444
5296
  removeKey(key) {
4445
5297
  this.delete(key);
4446
5298
  }
4447
5299
  /**
4448
- * Remove a given key from the cache
4449
- * @method delete
4450
- * @param key {String} the key to remove from the object
4451
- */
5300
+ * Remove a given key from the cache
5301
+ * @method delete
5302
+ * @param key {String} the key to remove from the object
5303
+ */
4452
5304
  delete(key) {
4453
5305
  this._cache.delete(key);
4454
5306
  this._changesSinceLastSave = true;
4455
5307
  this.emit("delete", key);
4456
5308
  }
4457
5309
  /**
4458
- * (Legacy) Return the value of the provided key. This method will be deprecated in the future
4459
- * @method getKey<T>
4460
- * @param key {String} the name of the key to retrieve
4461
- * @returns {*} at T the value from the key
4462
- */
5310
+ * (Legacy) Return the value of the provided key. This method will be deprecated in the future
5311
+ * @method getKey<T>
5312
+ * @param key {String} the name of the key to retrieve
5313
+ * @returns {*} at T the value from the key
5314
+ */
4463
5315
  getKey(key) {
4464
5316
  return this.get(key);
4465
5317
  }
4466
5318
  /**
4467
- * Return the value of the provided key
4468
- * @method get<T>
4469
- * @param key {String} the name of the key to retrieve
4470
- * @returns {*} at T the value from the key
4471
- */
5319
+ * Return the value of the provided key
5320
+ * @method get<T>
5321
+ * @param key {String} the name of the key to retrieve
5322
+ * @returns {*} at T the value from the key
5323
+ */
4472
5324
  get(key) {
4473
5325
  return this._cache.get(key);
4474
5326
  }
4475
5327
  /**
4476
- * Clear the cache and save the state to disk
4477
- * @method clear
4478
- */
5328
+ * Clear the cache and save the state to disk
5329
+ * @method clear
5330
+ */
4479
5331
  clear() {
4480
5332
  try {
4481
5333
  this._cache.clear();
4482
5334
  this._changesSinceLastSave = true;
4483
5335
  this.save();
4484
- this.emit(
4485
- "clear"
4486
- /* CLEAR */
4487
- );
5336
+ this.emit("clear");
4488
5337
  } catch (error) {
4489
5338
  this.emit("error", error);
4490
5339
  }
4491
5340
  }
4492
5341
  /**
4493
- * Save the state of the cache identified by the docId to disk
4494
- * as a JSON structure
4495
- * @method save
4496
- */
5342
+ * Save the state of the cache identified by the docId to disk
5343
+ * as a JSON structure
5344
+ * @method save
5345
+ */
4497
5346
  save(force = false) {
4498
5347
  try {
4499
5348
  if (this._changesSinceLastSave || force) {
4500
5349
  const filePath = this.cacheFilePath;
4501
5350
  const items = [...this._cache.items];
4502
5351
  const data = this._stringify(items);
4503
- if (!fs5.existsSync(this._cacheDir)) {
4504
- fs5.mkdirSync(this._cacheDir, { recursive: true });
4505
- }
5352
+ if (!fs5.existsSync(this._cacheDir)) fs5.mkdirSync(this._cacheDir, { recursive: true });
4506
5353
  fs5.writeFileSync(filePath, data);
4507
5354
  this._changesSinceLastSave = false;
4508
- this.emit(
4509
- "save"
4510
- /* SAVE */
4511
- );
5355
+ this.emit("save");
4512
5356
  }
4513
5357
  } catch (error) {
4514
5358
  this.emit("error", error);
4515
5359
  }
4516
5360
  }
4517
5361
  /**
4518
- * Remove the file where the cache is persisted
4519
- * @method removeCacheFile
4520
- * @return {Boolean} true or false if the file was successfully deleted
4521
- */
5362
+ * Remove the file where the cache is persisted
5363
+ * @method removeCacheFile
5364
+ * @return {Boolean} true or false if the file was successfully deleted
5365
+ */
4522
5366
  removeCacheFile() {
4523
5367
  try {
4524
5368
  if (fs5.existsSync(this.cacheFilePath)) {
@@ -4531,33 +5375,33 @@ var FlatCache = class extends Hookified {
4531
5375
  return false;
4532
5376
  }
4533
5377
  /**
4534
- * Destroy the cache. This will remove the directory, file, and memory cache
4535
- * @method destroy
4536
- * @param [includeCacheDir=false] {Boolean} if true, the cache directory will be removed
4537
- * @return {undefined}
4538
- */
5378
+ * Destroy the cache. This will remove the directory, file, and memory cache
5379
+ * @method destroy
5380
+ * @param [includeCacheDir=false] {Boolean} if true, the cache directory will be removed
5381
+ * @return {undefined}
5382
+ */
4539
5383
  destroy(includeCacheDirectory = false) {
4540
5384
  try {
4541
5385
  this._cache.clear();
4542
5386
  this.stopAutoPersist();
4543
- if (includeCacheDirectory) {
4544
- fs5.rmSync(this.cacheDirPath, { recursive: true, force: true });
4545
- } else {
4546
- fs5.rmSync(this.cacheFilePath, { recursive: true, force: true });
4547
- }
5387
+ if (includeCacheDirectory) fs5.rmSync(this.cacheDirPath, {
5388
+ recursive: true,
5389
+ force: true
5390
+ });
5391
+ else fs5.rmSync(this.cacheFilePath, {
5392
+ recursive: true,
5393
+ force: true
5394
+ });
4548
5395
  this._changesSinceLastSave = false;
4549
- this.emit(
4550
- "destroy"
4551
- /* DESTROY */
4552
- );
5396
+ this.emit("destroy");
4553
5397
  } catch (error) {
4554
5398
  this.emit("error", error);
4555
5399
  }
4556
5400
  }
4557
5401
  /**
4558
- * Start the auto persist interval
4559
- * @method startAutoPersist
4560
- */
5402
+ * Start the auto persist interval
5403
+ * @method startAutoPersist
5404
+ */
4561
5405
  startAutoPersist() {
4562
5406
  if (this._persistInterval > 0) {
4563
5407
  if (this._persistTimer) {
@@ -4570,9 +5414,9 @@ var FlatCache = class extends Hookified {
4570
5414
  }
4571
5415
  }
4572
5416
  /**
4573
- * Stop the auto persist interval
4574
- * @method stopAutoPersist
4575
- */
5417
+ * Stop the auto persist interval
5418
+ * @method stopAutoPersist
5419
+ */
4576
5420
  stopAutoPersist() {
4577
5421
  if (this._persistTimer) {
4578
5422
  clearInterval(this._persistTimer);
@@ -4581,16 +5425,14 @@ var FlatCache = class extends Hookified {
4581
5425
  }
4582
5426
  };
4583
5427
  function createFromFile(filePath, options) {
4584
- const cache = new FlatCache(options);
4585
- cache.loadFile(filePath);
4586
- return cache;
5428
+ const cache2 = new FlatCache(options);
5429
+ cache2.loadFile(filePath);
5430
+ return cache2;
4587
5431
  }
4588
5432
 
4589
- // node_modules/file-entry-cache/dist/index.js
5433
+ // node_modules/file-entry-cache/dist/index.mjs
4590
5434
  function createFromFile2(filePath, options) {
4591
- const fname = path11.basename(filePath);
4592
- const directory = path11.dirname(filePath);
4593
- return create(fname, directory, options);
5435
+ return create(path11.basename(filePath), path11.dirname(filePath), options);
4594
5436
  }
4595
5437
  function create(cacheId, cacheDirectory, options) {
4596
5438
  const opts = {
@@ -4603,8 +5445,11 @@ function create(cacheId, cacheDirectory, options) {
4603
5445
  const fileEntryCache = new FileEntryCache(opts);
4604
5446
  if (cacheDirectory) {
4605
5447
  const cachePath = `${cacheDirectory}/${cacheId}`;
4606
- if (fs6.existsSync(cachePath)) {
5448
+ if (fs6.existsSync(cachePath)) try {
4607
5449
  fileEntryCache.cache = createFromFile(cachePath, opts.cache);
5450
+ } catch (error) {
5451
+ if (error instanceof SyntaxError || error instanceof TypeError) fileEntryCache.cache = new FlatCache(opts.cache);
5452
+ else throw error;
4608
5453
  }
4609
5454
  }
4610
5455
  return fileEntryCache;
@@ -4623,239 +5468,249 @@ var FileEntryCache = class {
4623
5468
  _useAbsolutePathAsKey = false;
4624
5469
  _useModifiedTime = true;
4625
5470
  /**
4626
- * Create a new FileEntryCache instance
4627
- * @param options - The options for the FileEntryCache (all properties are optional with defaults)
4628
- */
5471
+ * Snapshot of the persisted meta for each key as of the last load/reconcile.
5472
+ * Change detection compares against this baseline (not the working cache) so
5473
+ * that repeated `getFileDescriptor()` calls keep reporting a file as changed
5474
+ * until the cache is reconciled. The set of keys also tracks which files were
5475
+ * visited during the current session so that `reconcile()` only updates those.
5476
+ */
5477
+ _originalMeta = /* @__PURE__ */ new Map();
5478
+ /**
5479
+ * Create a new FileEntryCache instance
5480
+ * @param options - The options for the FileEntryCache (all properties are optional with defaults)
5481
+ */
4629
5482
  constructor(options) {
4630
- if (options?.cache) {
4631
- this._cache = new FlatCache(options.cache);
4632
- }
4633
- if (options?.useCheckSum) {
4634
- this._useCheckSum = options.useCheckSum;
4635
- }
4636
- if (options?.hashAlgorithm) {
4637
- this._hashAlgorithm = options.hashAlgorithm;
4638
- }
4639
- if (options?.cwd) {
4640
- this._cwd = options.cwd;
4641
- }
4642
- if (options?.useModifiedTime !== void 0) {
4643
- this._useModifiedTime = options.useModifiedTime;
4644
- }
4645
- if (options?.restrictAccessToCwd !== void 0) {
4646
- this._restrictAccessToCwd = options.restrictAccessToCwd;
4647
- }
4648
- if (options?.useAbsolutePathAsKey !== void 0) {
4649
- this._useAbsolutePathAsKey = options.useAbsolutePathAsKey;
4650
- }
4651
- if (options?.logger) {
4652
- this._logger = options.logger;
4653
- }
4654
- }
4655
- /**
4656
- * Get the cache
4657
- * @returns {FlatCache} The cache
4658
- */
5483
+ if (options?.cache) this._cache = new FlatCache(options.cache);
5484
+ if (options?.useCheckSum) this._useCheckSum = options.useCheckSum;
5485
+ if (options?.hashAlgorithm) this._hashAlgorithm = options.hashAlgorithm;
5486
+ if (options?.cwd) this._cwd = options.cwd;
5487
+ if (options?.useModifiedTime !== void 0) this._useModifiedTime = options.useModifiedTime;
5488
+ if (options?.restrictAccessToCwd !== void 0) this._restrictAccessToCwd = options.restrictAccessToCwd;
5489
+ if (options?.useAbsolutePathAsKey !== void 0) this._useAbsolutePathAsKey = options.useAbsolutePathAsKey;
5490
+ if (options?.logger) this._logger = options.logger;
5491
+ }
5492
+ /**
5493
+ * Get the cache
5494
+ * @returns {FlatCache} The cache
5495
+ */
4659
5496
  get cache() {
4660
5497
  return this._cache;
4661
5498
  }
4662
5499
  /**
4663
- * Set the cache
4664
- * @param {FlatCache} cache - The cache to set
4665
- */
4666
- set cache(cache) {
4667
- this._cache = cache;
5500
+ * Set the cache
5501
+ * @param {FlatCache} cache - The cache to set
5502
+ */
5503
+ set cache(cache2) {
5504
+ this._cache = cache2;
5505
+ this._originalMeta = /* @__PURE__ */ new Map();
4668
5506
  }
4669
5507
  /**
4670
- * Get the logger
4671
- * @returns {ILogger | undefined} The logger instance
4672
- */
5508
+ * Get the logger
5509
+ * @returns {ILogger | undefined} The logger instance
5510
+ */
4673
5511
  get logger() {
4674
5512
  return this._logger;
4675
5513
  }
4676
5514
  /**
4677
- * Set the logger
4678
- * @param {ILogger | undefined} logger - The logger to set
4679
- */
5515
+ * Set the logger
5516
+ * @param {ILogger | undefined} logger - The logger to set
5517
+ */
4680
5518
  set logger(logger) {
4681
5519
  this._logger = logger;
4682
5520
  }
4683
5521
  /**
4684
- * Use the hash to check if the file has changed
4685
- * @returns {boolean} if the hash is used to check if the file has changed (default: false)
4686
- */
5522
+ * Use the hash to check if the file has changed
5523
+ * @returns {boolean} if the hash is used to check if the file has changed (default: false)
5524
+ */
4687
5525
  get useCheckSum() {
4688
5526
  return this._useCheckSum;
4689
5527
  }
4690
5528
  /**
4691
- * Set the useCheckSum value
4692
- * @param {boolean} value - The value to set
4693
- */
5529
+ * Set the useCheckSum value
5530
+ * @param {boolean} value - The value to set
5531
+ */
4694
5532
  set useCheckSum(value) {
4695
5533
  this._useCheckSum = value;
4696
5534
  }
4697
5535
  /**
4698
- * Get the hash algorithm
4699
- * @returns {string} The hash algorithm (default: 'md5')
4700
- */
5536
+ * Get the hash algorithm
5537
+ * @returns {string} The hash algorithm (default: 'md5')
5538
+ */
4701
5539
  get hashAlgorithm() {
4702
5540
  return this._hashAlgorithm;
4703
5541
  }
4704
5542
  /**
4705
- * Set the hash algorithm
4706
- * @param {string} value - The value to set
4707
- */
5543
+ * Set the hash algorithm
5544
+ * @param {string} value - The value to set
5545
+ */
4708
5546
  set hashAlgorithm(value) {
4709
5547
  this._hashAlgorithm = value;
4710
5548
  }
4711
5549
  /**
4712
- * Get the current working directory
4713
- * @returns {string} The current working directory (default: process.cwd())
4714
- */
5550
+ * Get the current working directory
5551
+ * @returns {string} The current working directory (default: process.cwd())
5552
+ */
4715
5553
  get cwd() {
4716
5554
  return this._cwd;
4717
5555
  }
4718
5556
  /**
4719
- * Set the current working directory
4720
- * @param {string} value - The value to set
4721
- */
5557
+ * Set the current working directory
5558
+ *
5559
+ * Note: when relative paths are used as cache keys (the default), `cwd` must
5560
+ * stay stable across a `getFileDescriptor()` / `reconcile()` cycle. Relative
5561
+ * keys are resolved against the *current* `cwd` each time, so changing it
5562
+ * mid-run can cause `reconcile()` to resolve a key to a different (missing)
5563
+ * path and drop the entry. Use absolute keys (`useAbsolutePathAsKey: true`)
5564
+ * if `cwd` must change during a run.
5565
+ * @param {string} value - The value to set
5566
+ */
4722
5567
  set cwd(value) {
4723
5568
  this._cwd = value;
4724
5569
  }
4725
5570
  /**
4726
- * Get whether to use modified time for change detection
4727
- * @returns {boolean} Whether modified time (mtime) is used for change detection (default: true)
4728
- */
5571
+ * Get whether to use modified time for change detection
5572
+ * @returns {boolean} Whether modified time (mtime) is used for change detection (default: true)
5573
+ */
4729
5574
  get useModifiedTime() {
4730
5575
  return this._useModifiedTime;
4731
5576
  }
4732
5577
  /**
4733
- * Set whether to use modified time for change detection
4734
- * @param {boolean} value - The value to set
4735
- */
5578
+ * Set whether to use modified time for change detection
5579
+ * @param {boolean} value - The value to set
5580
+ */
4736
5581
  set useModifiedTime(value) {
4737
5582
  this._useModifiedTime = value;
4738
5583
  }
4739
5584
  /**
4740
- * Get whether to restrict paths to cwd boundaries
4741
- * @returns {boolean} Whether strict path checking is enabled (default: true)
4742
- */
5585
+ * Get whether to restrict paths to cwd boundaries
5586
+ * @returns {boolean} Whether strict path checking is enabled (default: true)
5587
+ */
4743
5588
  get restrictAccessToCwd() {
4744
5589
  return this._restrictAccessToCwd;
4745
5590
  }
4746
5591
  /**
4747
- * Set whether to restrict paths to cwd boundaries
4748
- * @param {boolean} value - The value to set
4749
- */
5592
+ * Set whether to restrict paths to cwd boundaries
5593
+ * @param {boolean} value - The value to set
5594
+ */
4750
5595
  set restrictAccessToCwd(value) {
4751
5596
  this._restrictAccessToCwd = value;
4752
5597
  }
4753
5598
  /**
4754
- * Get whether to use absolute path as cache key
4755
- * @returns {boolean} Whether cache keys use absolute paths (default: false)
4756
- */
5599
+ * Get whether to use absolute path as cache key
5600
+ * @returns {boolean} Whether cache keys use absolute paths (default: false)
5601
+ */
4757
5602
  get useAbsolutePathAsKey() {
4758
5603
  return this._useAbsolutePathAsKey;
4759
5604
  }
4760
5605
  /**
4761
- * Set whether to use absolute path as cache key
4762
- * @param {boolean} value - The value to set
4763
- */
5606
+ * Set whether to use absolute path as cache key
5607
+ * @param {boolean} value - The value to set
5608
+ */
4764
5609
  set useAbsolutePathAsKey(value) {
4765
5610
  this._useAbsolutePathAsKey = value;
4766
5611
  }
4767
5612
  /**
4768
- * Given a buffer, calculate md5 hash of its content.
4769
- * @method getHash
4770
- * @param {Buffer} buffer buffer to calculate hash on
4771
- * @return {String} content hash digest
4772
- */
5613
+ * Given a buffer, calculate md5 hash of its content.
5614
+ * @method getHash
5615
+ * @param {Buffer} buffer buffer to calculate hash on
5616
+ * @return {String} content hash digest
5617
+ */
4773
5618
  getHash(buffer) {
4774
5619
  return crypto2.createHash(this._hashAlgorithm).update(buffer).digest("hex");
4775
5620
  }
4776
5621
  /**
4777
- * Create the key for the file path used for caching.
4778
- * @method createFileKey
4779
- * @param {String} filePath
4780
- * @return {String}
4781
- */
5622
+ * Create the key for the file path used for caching.
5623
+ * @method createFileKey
5624
+ * @param {String} filePath
5625
+ * @return {String}
5626
+ */
4782
5627
  createFileKey(filePath) {
4783
5628
  let result = filePath;
4784
- if (this._useAbsolutePathAsKey && this.isRelativePath(filePath)) {
4785
- result = this.getAbsolutePathWithCwd(filePath, this._cwd);
4786
- }
5629
+ if (this._useAbsolutePathAsKey && this.isRelativePath(filePath)) result = this.getAbsolutePathWithCwd(filePath, this._cwd);
4787
5630
  return result;
4788
5631
  }
4789
5632
  /**
4790
- * Check if the file path is a relative path
4791
- * @method isRelativePath
4792
- * @param filePath - The file path to check
4793
- * @returns {boolean} if the file path is a relative path, false otherwise
4794
- */
5633
+ * Check if the file path is a relative path
5634
+ * @method isRelativePath
5635
+ * @param filePath - The file path to check
5636
+ * @returns {boolean} if the file path is a relative path, false otherwise
5637
+ */
4795
5638
  isRelativePath(filePath) {
4796
5639
  return !path11.isAbsolute(filePath);
4797
5640
  }
4798
5641
  /**
4799
- * Delete the cache file from the disk
4800
- * @method deleteCacheFile
4801
- * @return {boolean} true if the file was deleted, false otherwise
4802
- */
5642
+ * Delete the cache file from the disk
5643
+ * @method deleteCacheFile
5644
+ * @return {boolean} true if the file was deleted, false otherwise
5645
+ */
4803
5646
  deleteCacheFile() {
4804
5647
  return this._cache.removeCacheFile();
4805
5648
  }
4806
5649
  /**
4807
- * Remove the cache from the file and clear the memory cache
4808
- * @method destroy
4809
- */
5650
+ * Remove the cache from the file and clear the memory cache
5651
+ * @method destroy
5652
+ */
4810
5653
  destroy() {
4811
5654
  this._cache.destroy();
5655
+ this._originalMeta = /* @__PURE__ */ new Map();
4812
5656
  }
4813
5657
  /**
4814
- * Remove and Entry From the Cache
4815
- * @method removeEntry
4816
- * @param filePath - The file path to remove from the cache
4817
- */
5658
+ * Remove and Entry From the Cache
5659
+ * @method removeEntry
5660
+ * @param filePath - The file path to remove from the cache
5661
+ */
4818
5662
  removeEntry(filePath) {
4819
5663
  const key = this.createFileKey(filePath);
4820
5664
  this._cache.removeKey(key);
5665
+ this._originalMeta.delete(key);
4821
5666
  }
4822
5667
  /**
4823
- * Reconcile the cache
4824
- * @method reconcile
4825
- */
5668
+ * Reconcile the cache
5669
+ * @method reconcile
5670
+ */
4826
5671
  reconcile() {
4827
- const { items } = this._cache;
4828
- for (const item of items) {
4829
- const fileDescriptor = this.getFileDescriptor(item.key);
4830
- if (fileDescriptor.notFound) {
4831
- this._cache.removeKey(item.key);
4832
- }
5672
+ for (const key of [...this._cache.keys()]) try {
5673
+ fs6.statSync(this.getAbsolutePath(key));
5674
+ } catch (error) {
5675
+ if (error.code === "ENOENT") {
5676
+ this._cache.removeKey(key);
5677
+ this._originalMeta.delete(key);
5678
+ } else this._logger?.error({
5679
+ key,
5680
+ error
5681
+ }, "reconcile: unable to stat file; keeping cached entry");
5682
+ }
5683
+ for (const key of [...this._originalMeta.keys()]) {
5684
+ const meta = this._cache.getKey(key);
5685
+ if (meta) this._originalMeta.set(key, { ...meta });
5686
+ else this._originalMeta.delete(key);
4833
5687
  }
4834
5688
  this._cache.save();
4835
5689
  }
4836
5690
  /**
4837
- * Check if the file has changed
4838
- * @method hasFileChanged
4839
- * @param filePath - The file path to check
4840
- * @returns {boolean} if the file has changed, false otherwise
4841
- */
5691
+ * Check if the file has changed
5692
+ * @method hasFileChanged
5693
+ * @param filePath - The file path to check
5694
+ * @returns {boolean} if the file has changed, false otherwise
5695
+ */
4842
5696
  hasFileChanged(filePath) {
4843
5697
  let result = false;
4844
5698
  const fileDescriptor = this.getFileDescriptor(filePath);
4845
- if ((!fileDescriptor.err || !fileDescriptor.notFound) && fileDescriptor.changed) {
4846
- result = true;
4847
- }
5699
+ if ((!fileDescriptor.err || !fileDescriptor.notFound) && fileDescriptor.changed) result = true;
4848
5700
  return result;
4849
5701
  }
4850
5702
  /**
4851
- * Get the file descriptor for the file path
4852
- * @method getFileDescriptor
4853
- * @param filePath - The file path to get the file descriptor for
4854
- * @param options - The options for getting the file descriptor
4855
- * @returns The file descriptor
4856
- */
5703
+ * Get the file descriptor for the file path
5704
+ * @method getFileDescriptor
5705
+ * @param filePath - The file path to get the file descriptor for
5706
+ * @param options - The options for getting the file descriptor
5707
+ * @returns The file descriptor
5708
+ */
4857
5709
  getFileDescriptor(filePath, options) {
4858
- this._logger?.debug({ filePath, options }, "Getting file descriptor");
5710
+ this._logger?.debug({
5711
+ filePath,
5712
+ options
5713
+ }, "Getting file descriptor");
4859
5714
  let fstat;
4860
5715
  const result = {
4861
5716
  key: this.createFileKey(filePath),
@@ -4864,39 +5719,33 @@ var FileEntryCache = class {
4864
5719
  };
4865
5720
  this._logger?.trace({ key: result.key }, "Created file key");
4866
5721
  const metaCache = this._cache.getKey(result.key);
4867
- if (metaCache) {
4868
- this._logger?.trace({ metaCache }, "Found cached meta");
4869
- } else {
4870
- this._logger?.trace("No cached meta found");
4871
- }
5722
+ if (metaCache) this._logger?.trace({ metaCache }, "Found cached meta");
5723
+ else this._logger?.trace("No cached meta found");
4872
5724
  result.meta = metaCache ? { ...metaCache } : {};
4873
5725
  const absolutePath = this.getAbsolutePath(filePath);
4874
5726
  this._logger?.trace({ absolutePath }, "Resolved absolute path");
4875
5727
  const useCheckSumValue = options?.useCheckSum ?? this._useCheckSum;
4876
- this._logger?.debug(
4877
- { useCheckSum: useCheckSumValue },
4878
- "Using checksum setting"
4879
- );
5728
+ this._logger?.debug({ useCheckSum: useCheckSumValue }, "Using checksum setting");
4880
5729
  const useModifiedTimeValue = options?.useModifiedTime ?? this.useModifiedTime;
4881
- this._logger?.debug(
4882
- { useModifiedTime: useModifiedTimeValue },
4883
- "Using modified time (mtime) setting"
4884
- );
5730
+ this._logger?.debug({ useModifiedTime: useModifiedTimeValue }, "Using modified time (mtime) setting");
4885
5731
  try {
4886
5732
  fstat = fs6.statSync(absolutePath);
4887
5733
  result.meta.size = fstat.size;
4888
5734
  result.meta.mtime = fstat.mtime.getTime();
4889
- this._logger?.trace(
4890
- { size: result.meta.size, mtime: result.meta.mtime },
4891
- "Read file stats"
4892
- );
5735
+ this._logger?.trace({
5736
+ size: result.meta.size,
5737
+ mtime: result.meta.mtime
5738
+ }, "Read file stats");
4893
5739
  if (useCheckSumValue) {
4894
5740
  const buffer = fs6.readFileSync(absolutePath);
4895
5741
  result.meta.hash = this.getHash(buffer);
4896
5742
  this._logger?.trace({ hash: result.meta.hash }, "Calculated file hash");
4897
5743
  }
4898
5744
  } catch (error) {
4899
- this._logger?.error({ filePath, error }, "Error reading file");
5745
+ this._logger?.error({
5746
+ filePath,
5747
+ error
5748
+ }, "Error reading file");
4900
5749
  this.removeEntry(filePath);
4901
5750
  let notFound = false;
4902
5751
  if (error.message.includes("ENOENT")) {
@@ -4910,47 +5759,49 @@ var FileEntryCache = class {
4910
5759
  meta: {}
4911
5760
  };
4912
5761
  }
4913
- if (!metaCache) {
5762
+ if (!this._originalMeta.has(result.key)) this._originalMeta.set(result.key, metaCache ? { ...metaCache } : void 0);
5763
+ const baseline = this._originalMeta.get(result.key);
5764
+ if (baseline === void 0) {
4914
5765
  result.changed = true;
4915
5766
  this._cache.setKey(result.key, result.meta);
4916
5767
  this._logger?.debug({ filePath }, "File not in cache, marked as changed");
4917
5768
  return result;
4918
5769
  }
4919
- if (useModifiedTimeValue && metaCache?.mtime !== result.meta?.mtime) {
5770
+ if (useModifiedTimeValue && baseline.mtime !== result.meta?.mtime) {
4920
5771
  result.changed = true;
4921
- this._logger?.debug(
4922
- { filePath, oldMtime: metaCache.mtime, newMtime: result.meta.mtime },
4923
- "File changed: mtime differs"
4924
- );
5772
+ this._logger?.debug({
5773
+ filePath,
5774
+ oldMtime: baseline.mtime,
5775
+ newMtime: result.meta.mtime
5776
+ }, "File changed: mtime differs");
4925
5777
  }
4926
- if (metaCache?.size !== result.meta?.size) {
5778
+ if (baseline.size !== result.meta?.size) {
4927
5779
  result.changed = true;
4928
- this._logger?.debug(
4929
- { filePath, oldSize: metaCache.size, newSize: result.meta.size },
4930
- "File changed: size differs"
4931
- );
5780
+ this._logger?.debug({
5781
+ filePath,
5782
+ oldSize: baseline.size,
5783
+ newSize: result.meta.size
5784
+ }, "File changed: size differs");
4932
5785
  }
4933
- if (useCheckSumValue && metaCache?.hash !== result.meta?.hash) {
5786
+ if (useCheckSumValue && baseline.hash !== result.meta?.hash) {
4934
5787
  result.changed = true;
4935
- this._logger?.debug(
4936
- { filePath, oldHash: metaCache.hash, newHash: result.meta.hash },
4937
- "File changed: hash differs"
4938
- );
5788
+ this._logger?.debug({
5789
+ filePath,
5790
+ oldHash: baseline.hash,
5791
+ newHash: result.meta.hash
5792
+ }, "File changed: hash differs");
4939
5793
  }
4940
5794
  this._cache.setKey(result.key, result.meta);
4941
- if (result.changed) {
4942
- this._logger?.info({ filePath }, "File has changed");
4943
- } else {
4944
- this._logger?.debug({ filePath }, "File unchanged");
4945
- }
5795
+ if (result.changed) this._logger?.info({ filePath }, "File has changed");
5796
+ else this._logger?.debug({ filePath }, "File unchanged");
4946
5797
  return result;
4947
5798
  }
4948
5799
  /**
4949
- * Get the file descriptors for the files
4950
- * @method normalizeEntries
4951
- * @param files?: string[] - The files to get the file descriptors for
4952
- * @returns The file descriptors
4953
- */
5800
+ * Get the file descriptors for the files
5801
+ * @method normalizeEntries
5802
+ * @param files?: string[] - The files to get the file descriptors for
5803
+ * @returns The file descriptors
5804
+ */
4954
5805
  normalizeEntries(files) {
4955
5806
  const result = [];
4956
5807
  if (files) {
@@ -4963,18 +5814,16 @@ var FileEntryCache = class {
4963
5814
  const keys2 = this.cache.keys();
4964
5815
  for (const key of keys2) {
4965
5816
  const fileDescriptor = this.getFileDescriptor(key);
4966
- if (!fileDescriptor.notFound && !fileDescriptor.err) {
4967
- result.push(fileDescriptor);
4968
- }
5817
+ if (!fileDescriptor.notFound && !fileDescriptor.err) result.push(fileDescriptor);
4969
5818
  }
4970
5819
  return result;
4971
5820
  }
4972
5821
  /**
4973
- * Analyze the files
4974
- * @method analyzeFiles
4975
- * @param files - The files to analyze
4976
- * @returns {AnalyzedFiles} The analysis of the files
4977
- */
5822
+ * Analyze the files
5823
+ * @method analyzeFiles
5824
+ * @param files - The files to analyze
5825
+ * @returns {AnalyzedFiles} The analysis of the files
5826
+ */
4978
5827
  analyzeFiles(files) {
4979
5828
  const result = {
4980
5829
  changedFiles: [],
@@ -4982,58 +5831,47 @@ var FileEntryCache = class {
4982
5831
  notChangedFiles: []
4983
5832
  };
4984
5833
  const fileDescriptors = this.normalizeEntries(files);
4985
- for (const fileDescriptor of fileDescriptors) {
4986
- if (fileDescriptor.notFound) {
4987
- result.notFoundFiles.push(fileDescriptor.key);
4988
- } else if (fileDescriptor.changed) {
4989
- result.changedFiles.push(fileDescriptor.key);
4990
- } else {
4991
- result.notChangedFiles.push(fileDescriptor.key);
4992
- }
4993
- }
5834
+ for (const fileDescriptor of fileDescriptors) if (fileDescriptor.notFound) result.notFoundFiles.push(fileDescriptor.key);
5835
+ else if (fileDescriptor.changed) result.changedFiles.push(fileDescriptor.key);
5836
+ else result.notChangedFiles.push(fileDescriptor.key);
4994
5837
  return result;
4995
5838
  }
4996
5839
  /**
4997
- * Get the updated files
4998
- * @method getUpdatedFiles
4999
- * @param files - The files to get the updated files for
5000
- * @returns {string[]} The updated files
5001
- */
5840
+ * Get the updated files
5841
+ * @method getUpdatedFiles
5842
+ * @param files - The files to get the updated files for
5843
+ * @returns {string[]} The updated files
5844
+ */
5002
5845
  getUpdatedFiles(files) {
5003
5846
  const result = [];
5004
5847
  const fileDescriptors = this.normalizeEntries(files);
5005
- for (const fileDescriptor of fileDescriptors) {
5006
- if (fileDescriptor.changed) {
5007
- result.push(fileDescriptor.key);
5008
- }
5009
- }
5848
+ for (const fileDescriptor of fileDescriptors) if (fileDescriptor.changed) result.push(fileDescriptor.key);
5010
5849
  return result;
5011
5850
  }
5012
5851
  /**
5013
- * Get the file descriptors by path prefix
5014
- * @method getFileDescriptorsByPath
5015
- * @param filePath - the path prefix to match
5016
- * @returns {FileDescriptor[]} The file descriptors
5017
- */
5852
+ * Get the file descriptors by path prefix
5853
+ * @method getFileDescriptorsByPath
5854
+ * @param filePath - the path prefix to match
5855
+ * @returns {FileDescriptor[]} The file descriptors
5856
+ */
5018
5857
  getFileDescriptorsByPath(filePath) {
5019
5858
  const result = [];
5020
5859
  const keys2 = this._cache.keys();
5021
- for (const key of keys2) {
5860
+ for (const key of keys2)
5022
5861
  if (key.startsWith(filePath)) {
5023
5862
  const fileDescriptor = this.getFileDescriptor(key);
5024
5863
  result.push(fileDescriptor);
5025
5864
  }
5026
- }
5027
5865
  return result;
5028
5866
  }
5029
5867
  /**
5030
- * Get the Absolute Path. If it is already absolute it will return the path as is.
5031
- * When restrictAccessToCwd is enabled, ensures the resolved path stays within cwd boundaries.
5032
- * @method getAbsolutePath
5033
- * @param filePath - The file path to get the absolute path for
5034
- * @returns {string}
5035
- * @throws {Error} When restrictAccessToCwd is true and path would resolve outside cwd
5036
- */
5868
+ * Get the Absolute Path. If it is already absolute it will return the path as is.
5869
+ * When restrictAccessToCwd is enabled, ensures the resolved path stays within cwd boundaries.
5870
+ * @method getAbsolutePath
5871
+ * @param filePath - The file path to get the absolute path for
5872
+ * @returns {string}
5873
+ * @throws {Error} When restrictAccessToCwd is true and path would resolve outside cwd
5874
+ */
5037
5875
  getAbsolutePath(filePath) {
5038
5876
  if (this.isRelativePath(filePath)) {
5039
5877
  const sanitizedPath = filePath.replace(/\0/g, "");
@@ -5041,26 +5879,21 @@ var FileEntryCache = class {
5041
5879
  if (this._restrictAccessToCwd) {
5042
5880
  const normalizedResolved = path11.normalize(resolved);
5043
5881
  const normalizedCwd = path11.normalize(this._cwd);
5044
- const isWithinCwd = normalizedResolved === normalizedCwd || normalizedResolved.startsWith(normalizedCwd + path11.sep);
5045
- if (!isWithinCwd) {
5046
- throw new Error(
5047
- `Path traversal attempt blocked: "${filePath}" resolves outside of working directory "${this._cwd}"`
5048
- );
5049
- }
5882
+ if (!(normalizedResolved === normalizedCwd || normalizedResolved.startsWith(normalizedCwd + path11.sep))) throw new Error(`Path traversal attempt blocked: "${filePath}" resolves outside of working directory "${this._cwd}"`);
5050
5883
  }
5051
5884
  return resolved;
5052
5885
  }
5053
5886
  return filePath;
5054
5887
  }
5055
5888
  /**
5056
- * Get the Absolute Path with a custom working directory. If it is already absolute it will return the path as is.
5057
- * When restrictAccessToCwd is enabled, ensures the resolved path stays within the provided cwd boundaries.
5058
- * @method getAbsolutePathWithCwd
5059
- * @param filePath - The file path to get the absolute path for
5060
- * @param cwd - The custom working directory to resolve relative paths from
5061
- * @returns {string}
5062
- * @throws {Error} When restrictAccessToCwd is true and path would resolve outside the provided cwd
5063
- */
5889
+ * Get the Absolute Path with a custom working directory. If it is already absolute it will return the path as is.
5890
+ * When restrictAccessToCwd is enabled, ensures the resolved path stays within the provided cwd boundaries.
5891
+ * @method getAbsolutePathWithCwd
5892
+ * @param filePath - The file path to get the absolute path for
5893
+ * @param cwd - The custom working directory to resolve relative paths from
5894
+ * @returns {string}
5895
+ * @throws {Error} When restrictAccessToCwd is true and path would resolve outside the provided cwd
5896
+ */
5064
5897
  getAbsolutePathWithCwd(filePath, cwd3) {
5065
5898
  if (this.isRelativePath(filePath)) {
5066
5899
  const sanitizedPath = filePath.replace(/\0/g, "");
@@ -5068,33 +5901,31 @@ var FileEntryCache = class {
5068
5901
  if (this._restrictAccessToCwd) {
5069
5902
  const normalizedResolved = path11.normalize(resolved);
5070
5903
  const normalizedCwd = path11.normalize(cwd3);
5071
- const isWithinCwd = normalizedResolved === normalizedCwd || normalizedResolved.startsWith(normalizedCwd + path11.sep);
5072
- if (!isWithinCwd) {
5073
- throw new Error(
5074
- `Path traversal attempt blocked: "${filePath}" resolves outside of working directory "${cwd3}"`
5075
- );
5076
- }
5904
+ if (!(normalizedResolved === normalizedCwd || normalizedResolved.startsWith(normalizedCwd + path11.sep))) throw new Error(`Path traversal attempt blocked: "${filePath}" resolves outside of working directory "${cwd3}"`);
5077
5905
  }
5078
5906
  return resolved;
5079
5907
  }
5080
5908
  return filePath;
5081
5909
  }
5082
5910
  /**
5083
- * Rename cache keys that start with a given path prefix.
5084
- * @method renameCacheKeys
5085
- * @param oldPath - The old path prefix to rename
5086
- * @param newPath - The new path prefix to rename to
5087
- */
5911
+ * Rename cache keys that start with a given path prefix.
5912
+ * @method renameCacheKeys
5913
+ * @param oldPath - The old path prefix to rename
5914
+ * @param newPath - The new path prefix to rename to
5915
+ */
5088
5916
  renameCacheKeys(oldPath, newPath) {
5089
5917
  const keys2 = this._cache.keys();
5090
- for (const key of keys2) {
5918
+ for (const key of keys2)
5091
5919
  if (key.startsWith(oldPath)) {
5092
5920
  const newKey = key.replace(oldPath, newPath);
5093
5921
  const meta = this._cache.getKey(key);
5094
5922
  this._cache.removeKey(key);
5095
5923
  this._cache.setKey(newKey, meta);
5924
+ if (this._originalMeta.has(key)) {
5925
+ this._originalMeta.set(newKey, this._originalMeta.get(key));
5926
+ this._originalMeta.delete(key);
5927
+ }
5096
5928
  }
5097
- }
5098
5929
  }
5099
5930
  };
5100
5931
 
@@ -5103,14 +5934,11 @@ import { version as prettierVersion } from "../index.mjs";
5103
5934
  var optionsHashCache = /* @__PURE__ */ new WeakMap();
5104
5935
  var nodeVersion = process.version;
5105
5936
  function getHashOfOptions(options) {
5106
- if (optionsHashCache.has(options)) {
5107
- return optionsHashCache.get(options);
5108
- }
5109
- const hash2 = createHash(
5110
- `${prettierVersion}_${nodeVersion}_${(0, import_fast_json_stable_stringify2.default)(options)}`
5937
+ return getOrInsertComputed(
5938
+ optionsHashCache,
5939
+ options,
5940
+ (options2) => createHash(`${prettierVersion}_${nodeVersion}_${(0, import_fast_json_stable_stringify2.default)(options2)}`)
5111
5941
  );
5112
- optionsHashCache.set(options, hash2);
5113
- return hash2;
5114
5942
  }
5115
5943
  function getMetadataFromFileDescriptor(fileDescriptor) {
5116
5944
  return fileDescriptor.meta;
@@ -5122,10 +5950,10 @@ var FormatResultsCache = class {
5122
5950
  * @param {string} cacheStrategy
5123
5951
  */
5124
5952
  constructor(cacheFileLocation, cacheStrategy) {
5125
- const useChecksum = cacheStrategy === "content";
5953
+ const useCheckSum = cacheStrategy === "content";
5126
5954
  const fileEntryCacheOptions = {
5127
- useChecksum,
5128
- useModifiedTime: !useChecksum,
5955
+ useCheckSum,
5956
+ useModifiedTime: !useCheckSum,
5129
5957
  restrictAccessToCwd: false
5130
5958
  };
5131
5959
  try {
@@ -5207,6 +6035,9 @@ function stripAnsi(string) {
5207
6035
  if (typeof string !== "string") {
5208
6036
  throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
5209
6037
  }
6038
+ if (!string.includes("\x1B") && !string.includes("\x9B")) {
6039
+ return string;
6040
+ }
5210
6041
  return string.replace(regex, "");
5211
6042
  }
5212
6043
 
@@ -5580,7 +6411,7 @@ function handleError(context, filename, error, printedFilename, ignoreUnknown) {
5580
6411
  return;
5581
6412
  }
5582
6413
  const isParseError = Boolean(error?.loc);
5583
- const isValidationError = /^Invalid \S+ value\./u.test(error?.message);
6414
+ const isValidationError = /^Invalid \S+ value\./.test(error?.message);
5584
6415
  if (isParseError) {
5585
6416
  context.logger.error(`${filename}: ${String(error)}`);
5586
6417
  } else if (isValidationError || error instanceof errors.ConfigError) {
@@ -5643,21 +6474,20 @@ async function format3(context, input, opt) {
5643
6474
  throw new DebugError(
5644
6475
  "prettier(input) !== prettier(prettier(input))\n" + diff(pp, pppp)
5645
6476
  );
5646
- } else {
5647
- const stringify5 = (obj) => JSON.stringify(obj, null, 2);
5648
- const ast = stringify5(
5649
- (await prettier.__debug.parse(input, opt, { massage: true })).ast
5650
- );
5651
- const past = stringify5(
5652
- (await prettier.__debug.parse(pp, opt, { massage: true })).ast
6477
+ }
6478
+ const stringify5 = (obj) => JSON.stringify(obj, null, 2);
6479
+ const ast = stringify5(
6480
+ (await prettier.__debug.parse(input, opt, { massage: true })).ast
6481
+ );
6482
+ const past = stringify5(
6483
+ (await prettier.__debug.parse(pp, opt, { massage: true })).ast
6484
+ );
6485
+ if (ast !== past) {
6486
+ const MAX_AST_SIZE = 2097152;
6487
+ const astDiff = ast.length > MAX_AST_SIZE || past.length > MAX_AST_SIZE ? "AST diff too large to render" : diff(ast, past);
6488
+ throw new DebugError(
6489
+ "ast(input) !== ast(prettier(input))\n" + astDiff + "\n" + diff(input, pp)
5653
6490
  );
5654
- if (ast !== past) {
5655
- const MAX_AST_SIZE = 2097152;
5656
- const astDiff = ast.length > MAX_AST_SIZE || past.length > MAX_AST_SIZE ? "AST diff too large to render" : diff(ast, past);
5657
- throw new DebugError(
5658
- "ast(input) !== ast(prettier(input))\n" + astDiff + "\n" + diff(input, pp)
5659
- );
5660
- }
5661
6491
  }
5662
6492
  return { formatted: pp, filepath: opt.filepath || "(stdin)\n" };
5663
6493
  }
@@ -5957,7 +6787,7 @@ function createLogger(logLevel = "log") {
5957
6787
  /* OPTIONAL_OBJECT: false */
5958
6788
  0,
5959
6789
  message,
5960
- /^/gmu,
6790
+ /^/gm,
5961
6791
  prefix
5962
6792
  ) + (options.newline ? "\n" : "");
5963
6793
  stream.write(message);
@@ -6030,7 +6860,7 @@ function indent(str, spaces) {
6030
6860
  /* OPTIONAL_OBJECT: false */
6031
6861
  0,
6032
6862
  str,
6033
- /^/gmu,
6863
+ /^/gm,
6034
6864
  " ".repeat(spaces)
6035
6865
  );
6036
6866
  }