prettier 3.9.0 → 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.
@@ -1978,12 +1978,12 @@ var find_cache_file_default = findCacheFile;
1978
1978
  var import_fast_json_stable_stringify2 = __toESM(require_fast_json_stable_stringify(), 1);
1979
1979
  import fs7 from "fs";
1980
1980
 
1981
- // node_modules/file-entry-cache/dist/index.js
1981
+ // node_modules/file-entry-cache/dist/index.mjs
1982
1982
  import crypto2 from "crypto";
1983
1983
  import fs6 from "fs";
1984
1984
  import path11 from "path";
1985
1985
 
1986
- // 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
1987
1987
  import fs5 from "fs";
1988
1988
  import path10 from "path";
1989
1989
 
@@ -3618,74 +3618,53 @@ var Hashery = class extends Hookified {
3618
3618
  }
3619
3619
  };
3620
3620
 
3621
- // node_modules/@cacheable/utils/dist/index.js
3621
+ // node_modules/@cacheable/utils/dist/index.mjs
3622
3622
  var shorthandToMilliseconds = (shorthand) => {
3623
3623
  let milliseconds;
3624
- if (shorthand === void 0) {
3625
- return void 0;
3626
- }
3627
- if (typeof shorthand === "number") {
3628
- milliseconds = shorthand;
3629
- } else {
3630
- if (typeof shorthand !== "string") {
3631
- return void 0;
3632
- }
3624
+ if (shorthand === void 0) return;
3625
+ if (typeof shorthand === "number") milliseconds = shorthand;
3626
+ else {
3627
+ if (typeof shorthand !== "string") return;
3633
3628
  shorthand = shorthand.trim();
3634
3629
  if (Number.isNaN(Number(shorthand))) {
3635
3630
  const match = /^([\d.]+)\s*(ms|s|m|h|hr|d)$/i.exec(shorthand);
3636
- if (!match) {
3637
- throw new Error(
3638
- `Unsupported time format: "${shorthand}". Use 'ms', 's', 'm', 'h', 'hr', or 'd'.`
3639
- );
3640
- }
3631
+ if (!match) throw new Error(`Unsupported time format: "${shorthand}". Use 'ms', 's', 'm', 'h', 'hr', or 'd'.`);
3641
3632
  const [, value, unit] = match;
3642
3633
  const numericValue = Number.parseFloat(value);
3643
- const unitLower = unit.toLowerCase();
3644
- switch (unitLower) {
3645
- case "ms": {
3634
+ switch (unit.toLowerCase()) {
3635
+ case "ms":
3646
3636
  milliseconds = numericValue;
3647
3637
  break;
3648
- }
3649
- case "s": {
3638
+ case "s":
3650
3639
  milliseconds = numericValue * 1e3;
3651
3640
  break;
3652
- }
3653
- case "m": {
3641
+ case "m":
3654
3642
  milliseconds = numericValue * 1e3 * 60;
3655
3643
  break;
3656
- }
3657
- case "h": {
3644
+ case "h":
3658
3645
  milliseconds = numericValue * 1e3 * 60 * 60;
3659
3646
  break;
3660
- }
3661
- case "hr": {
3647
+ case "hr":
3662
3648
  milliseconds = numericValue * 1e3 * 60 * 60;
3663
3649
  break;
3664
- }
3665
- case "d": {
3650
+ case "d":
3666
3651
  milliseconds = numericValue * 1e3 * 60 * 60 * 24;
3667
3652
  break;
3668
- }
3669
3653
  /* v8 ignore next -- @preserve */
3670
- default: {
3654
+ default:
3671
3655
  milliseconds = Number(shorthand);
3672
- }
3673
3656
  }
3674
- } else {
3675
- milliseconds = Number(shorthand);
3676
- }
3657
+ } else milliseconds = Number(shorthand);
3677
3658
  }
3678
3659
  return milliseconds;
3679
3660
  };
3680
3661
  var shorthandToTime = (shorthand, fromDate) => {
3681
3662
  fromDate ?? (fromDate = /* @__PURE__ */ new Date());
3682
3663
  const milliseconds = shorthandToMilliseconds(shorthand);
3683
- if (milliseconds === void 0) {
3684
- return fromDate.getTime();
3685
- }
3664
+ if (milliseconds === void 0) return fromDate.getTime();
3686
3665
  return fromDate.getTime() + milliseconds;
3687
3666
  };
3688
- var HashAlgorithm = /* @__PURE__ */ ((HashAlgorithm2) => {
3667
+ var HashAlgorithm = /* @__PURE__ */ (function(HashAlgorithm2) {
3689
3668
  HashAlgorithm2["SHA256"] = "SHA-256";
3690
3669
  HashAlgorithm2["SHA384"] = "SHA-384";
3691
3670
  HashAlgorithm2["SHA512"] = "SHA-512";
@@ -3694,16 +3673,14 @@ var HashAlgorithm = /* @__PURE__ */ ((HashAlgorithm2) => {
3694
3673
  HashAlgorithm2["MURMER"] = "murmer";
3695
3674
  HashAlgorithm2["CRC32"] = "crc32";
3696
3675
  return HashAlgorithm2;
3697
- })(HashAlgorithm || {});
3676
+ })({});
3698
3677
  function hashSync(object2, options = {
3699
3678
  algorithm: "djb2",
3700
3679
  serialize: JSON.stringify
3701
3680
  }) {
3702
3681
  const algorithm = options?.algorithm ?? "djb2";
3703
- const serialize = options?.serialize ?? JSON.stringify;
3704
- const objectString = serialize(object2);
3705
- const hashery = new Hashery();
3706
- return hashery.toHashSync(objectString, { algorithm });
3682
+ const objectString = (options?.serialize ?? JSON.stringify)(object2);
3683
+ return new Hashery().toHashSync(objectString, { algorithm });
3707
3684
  }
3708
3685
  function hashToNumberSync(object2, options = {
3709
3686
  min: 0,
@@ -3716,14 +3693,9 @@ function hashToNumberSync(object2, options = {
3716
3693
  const algorithm = options?.algorithm ?? "djb2";
3717
3694
  const serialize = options?.serialize ?? JSON.stringify;
3718
3695
  const hashLength = options?.hashLength ?? 16;
3719
- if (min >= max) {
3720
- throw new Error(
3721
- `Invalid range: min (${min}) must be less than max (${max})`
3722
- );
3723
- }
3696
+ if (min >= max) throw new Error(`Invalid range: min (${min}) must be less than max (${max})`);
3724
3697
  const objectString = serialize(object2);
3725
- const hashery = new Hashery();
3726
- return hashery.toNumberSync(objectString, {
3698
+ return new Hashery().toNumberSync(objectString, {
3727
3699
  algorithm,
3728
3700
  min,
3729
3701
  max,
@@ -3737,33 +3709,570 @@ function wrapSync(function_, options) {
3737
3709
  keyPrefix,
3738
3710
  serialize
3739
3711
  });
3740
- if (options.createKey) {
3741
- cacheKey = options.createKey(function_, arguments_, options);
3742
- }
3712
+ if (options.createKey) cacheKey = options.createKey(function_, arguments_, options);
3743
3713
  let value = cache2.get(cacheKey);
3744
- if (value === void 0) {
3745
- try {
3746
- value = function_(...arguments_);
3747
- cache2.set(cacheKey, value, ttl);
3748
- } catch (error) {
3749
- cache2.emit("error", error);
3750
- if (options.cacheErrors) {
3751
- cache2.set(cacheKey, error, ttl);
3752
- }
3753
- }
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);
3754
3720
  }
3755
3721
  return value;
3756
3722
  };
3757
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
+ }
3758
3757
  function createWrapKey(function_, arguments_, options) {
3759
3758
  const { keyPrefix, serialize } = options || {};
3760
- if (!keyPrefix) {
3761
- return `${function_.name}::${hashSync(arguments_, { serialize })}`;
3762
- }
3759
+ if (!keyPrefix) return `${function_.name}::${hashSync(arguments_, { serialize })}`;
3763
3760
  return `${keyPrefix}::${function_.name}::${hashSync(arguments_, { serialize })}`;
3764
3761
  }
3762
+ var ErrorEnvelope = class {
3763
+ error;
3764
+ context;
3765
+ constructor(error, context) {
3766
+ this.error = error;
3767
+ this.context = context;
3768
+ }
3769
+ };
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);
3795
+ }
3796
+ /**
3797
+ * @returns {boolean} - Whether the stats are enabled
3798
+ */
3799
+ get enabled() {
3800
+ return this._enabled;
3801
+ }
3802
+ /**
3803
+ * @param {boolean} enabled - Whether to enable the stats
3804
+ */
3805
+ set enabled(enabled) {
3806
+ this._enabled = enabled;
3807
+ }
3808
+ /**
3809
+ * @returns {boolean} - Whether per-key statistics are tracked
3810
+ */
3811
+ get trackKeys() {
3812
+ return this._trackKeys;
3813
+ }
3814
+ /**
3815
+ * @param {boolean} trackKeys - Whether to track per-key statistics
3816
+ */
3817
+ set trackKeys(trackKeys) {
3818
+ this._trackKeys = trackKeys;
3819
+ }
3820
+ /**
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
+ }
4042
+ }
4043
+ }
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
+ });
4240
+ }
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);
4255
+ }
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
+ };
3765
4274
 
3766
- // node_modules/@cacheable/memory/dist/index.js
4275
+ // node_modules/@cacheable/memory/dist/index.mjs
3767
4276
  var structuredClone = globalThis.structuredClone ?? ((value) => JSON.parse(JSON.stringify(value)));
3768
4277
  var ListNode = class {
3769
4278
  value;
@@ -3777,81 +4286,53 @@ var DoublyLinkedList = class {
3777
4286
  head = void 0;
3778
4287
  tail = void 0;
3779
4288
  nodesMap = /* @__PURE__ */ new Map();
3780
- // Add a new node to the front (most recently used)
3781
4289
  addToFront(value) {
3782
4290
  const newNode = new ListNode(value);
3783
4291
  if (this.head) {
3784
4292
  newNode.next = this.head;
3785
4293
  this.head.prev = newNode;
3786
4294
  this.head = newNode;
3787
- } else {
3788
- this.head = this.tail = newNode;
3789
- }
4295
+ } else this.head = this.tail = newNode;
3790
4296
  this.nodesMap.set(value, newNode);
3791
4297
  }
3792
- // Move an existing node to the front (most recently used)
3793
4298
  moveToFront(value) {
3794
4299
  const node = this.nodesMap.get(value);
3795
- if (!node || this.head === node) {
3796
- return;
3797
- }
3798
- if (node.prev) {
3799
- node.prev.next = node.next;
3800
- }
3801
- if (node.next) {
3802
- node.next.prev = node.prev;
3803
- }
3804
- if (node === this.tail) {
3805
- this.tail = node.prev;
3806
- }
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;
3807
4304
  node.prev = void 0;
3808
4305
  node.next = this.head;
3809
- if (this.head) {
3810
- this.head.prev = node;
3811
- }
4306
+ if (this.head) this.head.prev = node;
3812
4307
  this.head = node;
3813
4308
  this.tail ?? (this.tail = node);
3814
4309
  }
3815
- // Get the oldest node (tail)
3816
4310
  getOldest() {
3817
4311
  return this.tail ? this.tail.value : void 0;
3818
4312
  }
3819
- // Remove the oldest node (tail)
3820
4313
  removeOldest() {
3821
- if (!this.tail) {
3822
- return void 0;
3823
- }
4314
+ if (!this.tail) return;
3824
4315
  const oldValue = this.tail.value;
3825
4316
  if (this.tail.prev) {
3826
4317
  this.tail = this.tail.prev;
3827
4318
  this.tail.next = void 0;
3828
- } else {
4319
+ } else
3829
4320
  this.head = this.tail = void 0;
3830
- }
3831
4321
  this.nodesMap.delete(oldValue);
3832
4322
  return oldValue;
3833
4323
  }
3834
- // Remove a specific node by value
3835
4324
  remove(value) {
3836
4325
  const node = this.nodesMap.get(value);
3837
- if (!node) {
3838
- return false;
3839
- }
3840
- if (node.prev) {
3841
- node.prev.next = node.next;
3842
- } else {
4326
+ if (!node) return false;
4327
+ if (node.prev) node.prev.next = node.next;
4328
+ else {
3843
4329
  this.head = node.next;
3844
- if (this.head) {
3845
- this.head.prev = void 0;
3846
- }
4330
+ if (this.head) this.head.prev = void 0;
3847
4331
  }
3848
- if (node.next) {
3849
- node.next.prev = node.prev;
3850
- } else {
4332
+ if (node.next) node.next.prev = node.prev;
4333
+ else {
3851
4334
  this.tail = node.prev;
3852
- if (this.tail) {
3853
- this.tail.next = void 0;
3854
- }
4335
+ if (this.tail) this.tail.next = void 0;
3855
4336
  }
3856
4337
  this.nodesMap.delete(value);
3857
4338
  return true;
@@ -3860,113 +4341,95 @@ var DoublyLinkedList = class {
3860
4341
  return this.nodesMap.size;
3861
4342
  }
3862
4343
  };
3863
- var defaultStoreHashSize = 16;
3864
4344
  var maximumMapSize = 16777216;
3865
4345
  var CacheableMemory = class extends Hookified {
3866
4346
  _lru = new DoublyLinkedList();
3867
- _storeHashSize = defaultStoreHashSize;
4347
+ _storeHashSize = 16;
3868
4348
  _storeHashAlgorithm = HashAlgorithm.DJB2;
3869
- // Default is djb2Hash
3870
- _store = Array.from(
3871
- { length: this._storeHashSize },
3872
- () => /* @__PURE__ */ new Map()
3873
- );
4349
+ _store = Array.from({ length: this._storeHashSize }, () => /* @__PURE__ */ new Map());
3874
4350
  _ttl;
3875
- // Turned off by default
4351
+ _maxTtl;
3876
4352
  _useClone = true;
3877
- // Turned on by default
3878
4353
  _lruSize = 0;
3879
- // Turned off by default
3880
4354
  _checkInterval = 0;
3881
- // Turned off by default
3882
4355
  _interval = 0;
3883
- // Turned off by default
4356
+ _stats = new Stats({ enabled: false });
3884
4357
  /**
3885
- * @constructor
3886
- * @param {CacheableMemoryOptions} [options] - The options for the CacheableMemory
3887
- */
4358
+ * @constructor
4359
+ * @param {CacheableMemoryOptions} [options] - The options for the CacheableMemory
4360
+ */
3888
4361
  constructor(options) {
3889
4362
  super();
3890
- if (options?.ttl) {
3891
- this.setTtl(options.ttl);
3892
- }
3893
- if (options?.useClone !== void 0) {
3894
- this._useClone = options.useClone;
3895
- }
3896
- if (options?.storeHashSize && options.storeHashSize > 0) {
3897
- this._storeHashSize = options.storeHashSize;
3898
- }
3899
- if (options?.lruSize) {
3900
- if (options.lruSize > maximumMapSize) {
3901
- this.emit(
3902
- "error",
3903
- new Error(
3904
- `LRU size cannot be larger than ${maximumMapSize} due to Map limitations.`
3905
- )
3906
- );
3907
- } else {
3908
- this._lruSize = options.lruSize;
3909
- }
3910
- }
3911
- if (options?.checkInterval) {
3912
- this._checkInterval = options.checkInterval;
3913
- }
3914
- if (options?.storeHashAlgorithm) {
3915
- this._storeHashAlgorithm = options.storeHashAlgorithm;
3916
- }
3917
- this._store = Array.from(
3918
- { length: this._storeHashSize },
3919
- () => /* @__PURE__ */ new Map()
3920
- );
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());
3921
4373
  this.startIntervalCheck();
3922
4374
  }
3923
4375
  /**
3924
- * Gets the time-to-live
3925
- * @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.
3926
- */
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
+ */
3927
4379
  get ttl() {
3928
4380
  return this._ttl;
3929
4381
  }
3930
4382
  /**
3931
- * Sets the time-to-live
3932
- * @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.
3933
- */
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
+ */
3934
4386
  set ttl(value) {
3935
4387
  this.setTtl(value);
3936
4388
  }
3937
4389
  /**
3938
- * Gets whether to use clone
3939
- * @returns {boolean} - If true, it will clone the value before returning it. If false, it will return the value directly. Default is true.
3940
- */
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
+ */
3941
4409
  get useClone() {
3942
4410
  return this._useClone;
3943
4411
  }
3944
4412
  /**
3945
- * Sets whether to use clone
3946
- * @param {boolean} value - If true, it will clone the value before returning it. If false, it will return the value directly. Default is true.
3947
- */
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
+ */
3948
4416
  set useClone(value) {
3949
4417
  this._useClone = value;
3950
4418
  }
3951
4419
  /**
3952
- * Gets the size of the LRU cache
3953
- * @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.
3954
- */
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
+ */
3955
4423
  get lruSize() {
3956
4424
  return this._lruSize;
3957
4425
  }
3958
4426
  /**
3959
- * Sets the size of the LRU cache
3960
- * @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.
3961
- */
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
+ */
3962
4430
  set lruSize(value) {
3963
- if (value > maximumMapSize) {
3964
- this.emit(
3965
- "error",
3966
- new Error(
3967
- `LRU size cannot be larger than ${maximumMapSize} due to Map limitations.`
3968
- )
3969
- );
4431
+ if (value > 16777216) {
4432
+ this.emit("error", /* @__PURE__ */ new Error(`LRU size cannot be larger than ${maximumMapSize} due to Map limitations.`));
3970
4433
  return;
3971
4434
  }
3972
4435
  this._lruSize = value;
@@ -3977,245 +4440,284 @@ var CacheableMemory = class extends Hookified {
3977
4440
  this.lruResize();
3978
4441
  }
3979
4442
  /**
3980
- * Gets the check interval
3981
- * @returns {number} - The interval to check for expired items. If set to 0, it will not check for expired items. Default is 0.
3982
- */
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
+ */
3983
4446
  get checkInterval() {
3984
4447
  return this._checkInterval;
3985
4448
  }
3986
4449
  /**
3987
- * Sets the check interval
3988
- * @param {number} value - The interval to check for expired items. If set to 0, it will not check for expired items. Default is 0.
3989
- */
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
+ */
3990
4453
  set checkInterval(value) {
3991
4454
  this._checkInterval = value;
3992
4455
  }
3993
4456
  /**
3994
- * Gets the size of the cache
3995
- * @returns {number} - The size of the cache
3996
- */
4457
+ * Gets the size of the cache
4458
+ * @returns {number} - The size of the cache
4459
+ */
3997
4460
  get size() {
3998
4461
  let size = 0;
3999
- for (const store of this._store) {
4000
- size += store.size;
4001
- }
4462
+ for (const store of this._store) size += store.size;
4002
4463
  return size;
4003
4464
  }
4004
4465
  /**
4005
- * Gets the number of hash stores
4006
- * @returns {number} - The number of hash stores
4007
- */
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
+ */
4008
4478
  get storeHashSize() {
4009
4479
  return this._storeHashSize;
4010
4480
  }
4011
4481
  /**
4012
- * Sets the number of hash stores. This will recreate the store and all data will be cleared
4013
- * @param {number} value - The number of hash stores
4014
- */
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
+ */
4015
4485
  set storeHashSize(value) {
4016
- if (value === this._storeHashSize) {
4017
- return;
4018
- }
4486
+ if (value === this._storeHashSize) return;
4019
4487
  this._storeHashSize = value;
4020
- this._store = Array.from(
4021
- { length: this._storeHashSize },
4022
- () => /* @__PURE__ */ new Map()
4023
- );
4488
+ this._store = Array.from({ length: this._storeHashSize }, () => /* @__PURE__ */ new Map());
4489
+ if (this._stats.enabled) this._stats.resetStoreValues();
4024
4490
  }
4025
4491
  /**
4026
- * Gets the store hash algorithm
4027
- * @returns {HashAlgorithm | StoreHashAlgorithmFunction} - The store hash algorithm
4028
- */
4492
+ * Gets the store hash algorithm
4493
+ * @returns {HashAlgorithm | StoreHashAlgorithmFunction} - The store hash algorithm
4494
+ */
4029
4495
  get storeHashAlgorithm() {
4030
4496
  return this._storeHashAlgorithm;
4031
4497
  }
4032
4498
  /**
4033
- * Sets the store hash algorithm. This will recreate the store and all data will be cleared
4034
- * @param {HashAlgorithm | HashAlgorithmFunction} value - The store hash algorithm
4035
- */
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
+ */
4036
4502
  set storeHashAlgorithm(value) {
4037
4503
  this._storeHashAlgorithm = value;
4038
4504
  }
4039
4505
  /**
4040
- * Gets the keys
4041
- * @returns {IterableIterator<string>} - The keys
4042
- */
4506
+ * Gets the keys
4507
+ * @returns {IterableIterator<string>} - The keys
4508
+ */
4043
4509
  get keys() {
4044
4510
  const keys2 = [];
4045
- for (const store of this._store) {
4046
- for (const key of store.keys()) {
4047
- const item = store.get(key);
4048
- if (item && this.hasExpired(item)) {
4049
- store.delete(key);
4050
- this.lruRemove(key);
4051
- continue;
4052
- }
4053
- 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;
4054
4518
  }
4519
+ keys2.push(key);
4055
4520
  }
4056
4521
  return keys2.values();
4057
4522
  }
4058
4523
  /**
4059
- * Gets the items
4060
- * @returns {IterableIterator<CacheableStoreItem>} - The items
4061
- */
4524
+ * Gets the items
4525
+ * @returns {IterableIterator<CacheableStoreItem>} - The items
4526
+ */
4062
4527
  get items() {
4063
4528
  const items = [];
4064
- for (const store of this._store) {
4065
- for (const item of store.values()) {
4066
- if (this.hasExpired(item)) {
4067
- store.delete(item.key);
4068
- this.lruRemove(item.key);
4069
- continue;
4070
- }
4071
- 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;
4072
4535
  }
4536
+ items.push(item);
4073
4537
  }
4074
4538
  return items.values();
4075
4539
  }
4076
4540
  /**
4077
- * Gets the store
4078
- * @returns {Array<Map<string, CacheableStoreItem>>} - The store
4079
- */
4541
+ * Gets the store
4542
+ * @returns {Array<Map<string, CacheableStoreItem>>} - The store
4543
+ */
4080
4544
  get store() {
4081
4545
  return this._store;
4082
4546
  }
4083
4547
  /**
4084
- * Gets the value of the key
4085
- * @param {string} key - The key to get the value
4086
- * @returns {T | undefined} - The value of the key
4087
- */
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
+ */
4088
4552
  get(key) {
4553
+ this.hookSync("BEFORE_GET", key);
4089
4554
  const store = this.getStore(key);
4090
4555
  const item = store.get(key);
4091
4556
  if (!item) {
4092
- return void 0;
4557
+ this.recordRead(false);
4558
+ this.hookSync("AFTER_GET", {
4559
+ key,
4560
+ result: void 0
4561
+ });
4562
+ return;
4093
4563
  }
4094
4564
  if (item.expires && Date.now() > item.expires) {
4565
+ this.recordExpiration(item);
4095
4566
  store.delete(key);
4096
4567
  this.lruRemove(key);
4097
- return void 0;
4568
+ this.recordRead(false);
4569
+ this.hookSync("AFTER_GET", {
4570
+ key,
4571
+ result: void 0
4572
+ });
4573
+ return;
4098
4574
  }
4099
4575
  this.lruMoveToFront(key);
4100
- if (!this._useClone) {
4101
- return item.value;
4102
- }
4103
- 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;
4104
4585
  }
4105
4586
  /**
4106
- * Gets the values of the keys
4107
- * @param {string[]} keys - The keys to get the values
4108
- * @returns {T[]} - The values of the keys
4109
- */
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
+ */
4110
4591
  getMany(keys2) {
4592
+ this.hookSync("BEFORE_GET_MANY", keys2);
4111
4593
  const result = [];
4112
- for (const key of keys2) {
4113
- result.push(this.get(key));
4114
- }
4594
+ for (const key of keys2) result.push(this.get(key));
4595
+ this.hookSync("AFTER_GET_MANY", {
4596
+ keys: keys2,
4597
+ result
4598
+ });
4115
4599
  return result;
4116
4600
  }
4117
4601
  /**
4118
- * Gets the raw value of the key
4119
- * @param {string} key - The key to get the value
4120
- * @returns {CacheableStoreItem | undefined} - The raw value of the key
4121
- */
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
+ */
4122
4606
  getRaw(key) {
4123
4607
  const store = this.getStore(key);
4124
4608
  const item = store.get(key);
4125
4609
  if (!item) {
4126
- return void 0;
4610
+ this.recordRead(false);
4611
+ return;
4127
4612
  }
4128
- if (item.expires && item.expires && Date.now() > item.expires) {
4613
+ if (item.expires && Date.now() > item.expires) {
4614
+ this.recordExpiration(item);
4129
4615
  store.delete(key);
4130
4616
  this.lruRemove(key);
4131
- return void 0;
4617
+ this.recordRead(false);
4618
+ return;
4132
4619
  }
4133
4620
  this.lruMoveToFront(key);
4621
+ this.recordRead(true);
4134
4622
  return item;
4135
4623
  }
4136
4624
  /**
4137
- * Gets the raw values of the keys
4138
- * @param {string[]} keys - The keys to get the values
4139
- * @returns {CacheableStoreItem[]} - The raw values of the keys
4140
- */
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
+ */
4141
4629
  getManyRaw(keys2) {
4142
4630
  const result = [];
4143
- for (const key of keys2) {
4144
- result.push(this.getRaw(key));
4145
- }
4631
+ for (const key of keys2) result.push(this.getRaw(key));
4146
4632
  return result;
4147
4633
  }
4148
4634
  /**
4149
- * Sets the value of the key
4150
- * @param {string} key - The key to set the value
4151
- * @param {any} value - The value to set
4152
- * @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.
4153
- * If you want to set expire directly you can do that by setting the expire property in the SetOptions.
4154
- * 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.
4155
- * @returns {void}
4156
- */
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
+ */
4157
4643
  set(key, value, ttl) {
4158
- 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);
4159
4651
  let expires;
4160
- if (ttl !== void 0 || this._ttl !== void 0) {
4161
- if (typeof ttl === "object") {
4162
- if (ttl.expire) {
4163
- expires = typeof ttl.expire === "number" ? ttl.expire : ttl.expire.getTime();
4164
- }
4165
- if (ttl.ttl) {
4166
- const finalTtl = shorthandToTime(ttl.ttl);
4167
- if (finalTtl !== void 0) {
4168
- expires = finalTtl;
4169
- }
4170
- }
4171
- } else {
4172
- const finalTtl = shorthandToTime(ttl ?? this._ttl);
4173
- if (finalTtl !== void 0) {
4174
- 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);
4175
4676
  }
4176
4677
  }
4177
4678
  }
4178
- if (this._lruSize > 0) {
4179
- if (store.has(key)) {
4180
- this.lruMoveToFront(key);
4181
- } else {
4182
- this.lruAddToFront(key);
4183
- if (this._lru.size > this._lruSize) {
4184
- const oldestKey = this._lru.getOldest();
4185
- if (oldestKey) {
4186
- this._lru.removeOldest();
4187
- this.delete(oldestKey);
4188
- }
4189
- }
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();
4190
4685
  }
4686
+ this._stats.incrementVSize(hookItem.value);
4687
+ this._stats.incrementSets();
4191
4688
  }
4192
- const item = { key, value, expires };
4193
- 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);
4194
4696
  }
4195
4697
  /**
4196
- * Sets the values of the keys
4197
- * @param {CacheableItem[]} items - The items to set
4198
- * @returns {void}
4199
- */
4698
+ * Sets the values of the keys
4699
+ * @param {CacheableItem[]} items - The items to set
4700
+ * @returns {void}
4701
+ */
4200
4702
  setMany(items) {
4201
- for (const item of items) {
4202
- this.set(item.key, item.value, item.ttl);
4203
- }
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);
4204
4706
  }
4205
4707
  /**
4206
- * Checks if the key exists
4207
- * @param {string} key - The key to check
4208
- * @returns {boolean} - If true, the key exists. If false, the key does not exist.
4209
- */
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
+ */
4210
4712
  has(key) {
4211
4713
  const item = this.get(key);
4212
4714
  return Boolean(item);
4213
4715
  }
4214
4716
  /**
4215
- * @function hasMany
4216
- * @param {string[]} keys - The keys to check
4217
- * @returns {boolean[]} - If true, the key exists. If false, the key does not exist.
4218
- */
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
+ */
4219
4721
  hasMany(keys2) {
4220
4722
  const result = [];
4221
4723
  for (const key of keys2) {
@@ -4225,66 +4727,76 @@ var CacheableMemory = class extends Hookified {
4225
4727
  return result;
4226
4728
  }
4227
4729
  /**
4228
- * Take will get the key and delete the entry from cache
4229
- * @param {string} key - The key to take
4230
- * @returns {T | undefined} - The value of the key
4231
- */
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
+ */
4232
4734
  take(key) {
4233
4735
  const item = this.get(key);
4234
- if (!item) {
4235
- return void 0;
4236
- }
4736
+ if (!item) return;
4237
4737
  this.delete(key);
4238
4738
  return item;
4239
4739
  }
4240
4740
  /**
4241
- * TakeMany will get the keys and delete the entries from cache
4242
- * @param {string[]} keys - The keys to take
4243
- * @returns {T[]} - The values of the keys
4244
- */
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
+ */
4245
4745
  takeMany(keys2) {
4246
4746
  const result = [];
4247
- for (const key of keys2) {
4248
- result.push(this.take(key));
4249
- }
4747
+ for (const key of keys2) result.push(this.take(key));
4250
4748
  return result;
4251
4749
  }
4252
4750
  /**
4253
- * Delete the key
4254
- * @param {string} key - The key to delete
4255
- * @returns {void}
4256
- */
4751
+ * Delete the key
4752
+ * @param {string} key - The key to delete
4753
+ * @returns {void}
4754
+ */
4257
4755
  delete(key) {
4756
+ this.hookSync("BEFORE_DELETE", key);
4258
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
+ }
4259
4767
  store.delete(key);
4260
4768
  this.lruRemove(key);
4769
+ this.hookSync("AFTER_DELETE", key);
4261
4770
  }
4262
4771
  /**
4263
- * Delete the keys
4264
- * @param {string[]} keys - The keys to delete
4265
- * @returns {void}
4266
- */
4772
+ * Delete the keys
4773
+ * @param {string[]} keys - The keys to delete
4774
+ * @returns {void}
4775
+ */
4267
4776
  deleteMany(keys2) {
4268
- for (const key of keys2) {
4269
- this.delete(key);
4270
- }
4777
+ this.hookSync("BEFORE_DELETE_MANY", keys2);
4778
+ for (const key of keys2) this.delete(key);
4779
+ this.hookSync("AFTER_DELETE_MANY", keys2);
4271
4780
  }
4272
4781
  /**
4273
- * Clear the cache
4274
- * @returns {void}
4275
- */
4782
+ * Clear the cache
4783
+ * @returns {void}
4784
+ */
4276
4785
  clear() {
4277
- this._store = Array.from(
4278
- { length: this._storeHashSize },
4279
- () => /* @__PURE__ */ new Map()
4280
- );
4786
+ this.hookSync("BEFORE_CLEAR");
4787
+ this._store = Array.from({ length: this._storeHashSize }, () => /* @__PURE__ */ new Map());
4281
4788
  this._lru = new DoublyLinkedList();
4789
+ if (this._stats.enabled) {
4790
+ this._stats.resetStoreValues();
4791
+ this._stats.incrementClears();
4792
+ }
4793
+ this.hookSync("AFTER_CLEAR");
4282
4794
  }
4283
4795
  /**
4284
- * Get the store based on the key (internal use)
4285
- * @param {string} key - The key to get the store
4286
- * @returns {CacheableHashStore} - The store
4287
- */
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
+ */
4288
4800
  getStore(key) {
4289
4801
  var _a;
4290
4802
  const hash2 = this.getKeyStoreHash(key);
@@ -4292,75 +4804,60 @@ var CacheableMemory = class extends Hookified {
4292
4804
  return this._store[hash2];
4293
4805
  }
4294
4806
  /**
4295
- * Hash the key for which store to go to (internal use)
4296
- * @param {string} key - The key to hash
4297
- * Available algorithms are: SHA256, SHA1, MD5, and djb2Hash.
4298
- * @returns {number} - The hashed key as a number
4299
- */
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
+ */
4300
4812
  getKeyStoreHash(key) {
4301
- if (this._store.length === 1) {
4302
- return 0;
4303
- }
4304
- if (typeof this._storeHashAlgorithm === "function") {
4305
- return this._storeHashAlgorithm(key, this._storeHashSize);
4306
- }
4307
- const storeHashSize = this._storeHashSize - 1;
4308
- 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, {
4309
4816
  min: 0,
4310
- max: storeHashSize,
4817
+ max: this._storeHashSize - 1,
4311
4818
  algorithm: this._storeHashAlgorithm
4312
4819
  });
4313
- return hash2;
4314
4820
  }
4315
4821
  /**
4316
- * Clone the value. This is for internal use
4317
- * @param {any} value - The value to clone
4318
- * @returns {any} - The cloned value
4319
- */
4320
- // 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
+ */
4321
4826
  clone(value) {
4322
- if (this.isPrimitive(value)) {
4323
- return value;
4324
- }
4827
+ if (this.isPrimitive(value)) return value;
4325
4828
  return structuredClone(value);
4326
4829
  }
4327
4830
  /**
4328
- * Add to the front of the LRU cache. This is for internal use
4329
- * @param {string} key - The key to add to the front
4330
- * @returns {void}
4331
- */
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
+ */
4332
4835
  lruAddToFront(key) {
4333
- if (this._lruSize === 0) {
4334
- return;
4335
- }
4836
+ if (this._lruSize === 0) return;
4336
4837
  this._lru.addToFront(key);
4337
4838
  }
4338
4839
  /**
4339
- * Move to the front of the LRU cache. This is for internal use
4340
- * @param {string} key - The key to move to the front
4341
- * @returns {void}
4342
- */
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
+ */
4343
4844
  lruMoveToFront(key) {
4344
- if (this._lruSize === 0) {
4345
- return;
4346
- }
4845
+ if (this._lruSize === 0) return;
4347
4846
  this._lru.moveToFront(key);
4348
4847
  }
4349
4848
  /**
4350
- * Remove a key from the LRU cache. This is for internal use
4351
- * @param {string} key - The key to remove
4352
- * @returns {void}
4353
- */
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
+ */
4354
4853
  lruRemove(key) {
4355
- if (this._lruSize === 0) {
4356
- return;
4357
- }
4854
+ if (this._lruSize === 0) return;
4358
4855
  this._lru.remove(key);
4359
4856
  }
4360
4857
  /**
4361
- * Resize the LRU cache. This is for internal use.
4362
- * @returns {void}
4363
- */
4858
+ * Resize the LRU cache. This is for internal use.
4859
+ * @returns {void}
4860
+ */
4364
4861
  lruResize() {
4365
4862
  while (this._lru.size > this._lruSize) {
4366
4863
  const oldestKey = this._lru.getOldest();
@@ -4371,84 +4868,116 @@ var CacheableMemory = class extends Hookified {
4371
4868
  }
4372
4869
  }
4373
4870
  /**
4374
- * Check for expiration. This is for internal use
4375
- * @returns {void}
4376
- */
4871
+ * Check for expiration. This is for internal use
4872
+ * @returns {void}
4873
+ */
4377
4874
  checkExpiration() {
4378
- for (const store of this._store) {
4379
- for (const item of store.values()) {
4380
- if (item.expires && Date.now() > item.expires) {
4381
- store.delete(item.key);
4382
- this.lruRemove(item.key);
4383
- }
4384
- }
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);
4385
4879
  }
4386
4880
  }
4387
4881
  /**
4388
- * Start the interval check. This is for internal use
4389
- * @returns {void}
4390
- */
4882
+ * Start the interval check. This is for internal use
4883
+ * @returns {void}
4884
+ */
4391
4885
  startIntervalCheck() {
4392
4886
  if (this._checkInterval > 0) {
4393
- if (this._interval) {
4887
+ if (this._interval)
4394
4888
  clearInterval(this._interval);
4395
- }
4396
4889
  this._interval = setInterval(() => {
4397
4890
  this.checkExpiration();
4398
4891
  }, this._checkInterval).unref();
4399
4892
  }
4400
4893
  }
4401
4894
  /**
4402
- * Stop the interval check. This is for internal use
4403
- * @returns {void}
4404
- */
4895
+ * Stop the interval check. This is for internal use
4896
+ * @returns {void}
4897
+ */
4405
4898
  stopIntervalCheck() {
4406
- if (this._interval) {
4407
- clearInterval(this._interval);
4408
- }
4899
+ if (this._interval) clearInterval(this._interval);
4409
4900
  this._interval = 0;
4410
4901
  this._checkInterval = 0;
4411
4902
  }
4412
4903
  /**
4413
- * Wrap the function for caching
4414
- * @param {Function} function_ - The function to wrap
4415
- * @param {Object} [options] - The options to wrap
4416
- * @returns {Function} - The wrapped function
4417
- */
4418
- // 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
+ */
4419
4909
  wrap(function_, options) {
4420
- const wrapOptions = {
4910
+ return wrapSync(function_, {
4421
4911
  ttl: options?.ttl ?? this._ttl,
4422
4912
  keyPrefix: options?.keyPrefix,
4423
4913
  createKey: options?.createKey,
4424
4914
  cache: this
4425
- };
4426
- 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();
4427
4962
  }
4428
- // biome-ignore lint/suspicious/noExplicitAny: type format
4429
4963
  isPrimitive(value) {
4430
4964
  const result = false;
4431
- if (value === null || value === void 0) {
4432
- return true;
4433
- }
4434
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
4435
- return true;
4436
- }
4965
+ if (value === null || value === void 0) return true;
4966
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return true;
4437
4967
  return result;
4438
4968
  }
4439
4969
  setTtl(ttl) {
4440
- if (typeof ttl === "string" || ttl === void 0) {
4441
- this._ttl = ttl;
4442
- } else if (ttl > 0) {
4443
- this._ttl = ttl;
4444
- } else {
4445
- this._ttl = void 0;
4446
- }
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;
4447
4978
  }
4448
4979
  hasExpired(item) {
4449
- if (item.expires && Date.now() > item.expires) {
4450
- return true;
4451
- }
4980
+ if (item.expires && Date.now() > item.expires) return true;
4452
4981
  return false;
4453
4982
  }
4454
4983
  };
@@ -4529,7 +5058,7 @@ var stringify2 = (value, replacer, space) => {
4529
5058
  }
4530
5059
  };
4531
5060
 
4532
- // 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
4533
5062
  var FlatCache = class extends Hookified {
4534
5063
  _cache = new CacheableMemory();
4535
5064
  _cacheDir = ".cache";
@@ -4541,169 +5070,137 @@ var FlatCache = class extends Hookified {
4541
5070
  _stringify = stringify2;
4542
5071
  constructor(options) {
4543
5072
  super();
4544
- if (options) {
4545
- this._cache = new CacheableMemory({
4546
- ttl: options.ttl,
4547
- useClone: options.useClone,
4548
- lruSize: options.lruSize,
4549
- checkInterval: options.expirationInterval
4550
- });
4551
- }
4552
- if (options?.cacheDir) {
4553
- this._cacheDir = options.cacheDir;
4554
- }
4555
- if (options?.cacheId) {
4556
- this._cacheId = options.cacheId;
4557
- }
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;
4558
5081
  if (options?.persistInterval) {
4559
5082
  this._persistInterval = options.persistInterval;
4560
5083
  this.startAutoPersist();
4561
5084
  }
4562
- if (options?.deserialize) {
4563
- this._parse = options.deserialize;
4564
- }
4565
- if (options?.serialize) {
4566
- this._stringify = options.serialize;
4567
- }
5085
+ if (options?.deserialize) this._parse = options.deserialize;
5086
+ if (options?.serialize) this._stringify = options.serialize;
4568
5087
  }
4569
5088
  /**
4570
- * The cache object
4571
- * @property cache
4572
- * @type {CacheableMemory}
4573
- */
5089
+ * The cache object
5090
+ * @property cache
5091
+ * @type {CacheableMemory}
5092
+ */
4574
5093
  get cache() {
4575
5094
  return this._cache;
4576
5095
  }
4577
5096
  /**
4578
- * The cache directory
4579
- * @property cacheDir
4580
- * @type {String}
4581
- * @default '.cache'
4582
- */
5097
+ * The cache directory
5098
+ * @property cacheDir
5099
+ * @type {String}
5100
+ * @default '.cache'
5101
+ */
4583
5102
  get cacheDir() {
4584
5103
  return this._cacheDir;
4585
5104
  }
4586
5105
  /**
4587
- * Set the cache directory
4588
- * @property cacheDir
4589
- * @type {String}
4590
- * @default '.cache'
4591
- */
5106
+ * Set the cache directory
5107
+ * @property cacheDir
5108
+ * @type {String}
5109
+ * @default '.cache'
5110
+ */
4592
5111
  set cacheDir(value) {
4593
5112
  this._cacheDir = value;
4594
5113
  }
4595
5114
  /**
4596
- * The cache id
4597
- * @property cacheId
4598
- * @type {String}
4599
- * @default 'cache1'
4600
- */
5115
+ * The cache id
5116
+ * @property cacheId
5117
+ * @type {String}
5118
+ * @default 'cache1'
5119
+ */
4601
5120
  get cacheId() {
4602
5121
  return this._cacheId;
4603
5122
  }
4604
5123
  /**
4605
- * Set the cache id
4606
- * @property cacheId
4607
- * @type {String}
4608
- * @default 'cache1'
4609
- */
5124
+ * Set the cache id
5125
+ * @property cacheId
5126
+ * @type {String}
5127
+ * @default 'cache1'
5128
+ */
4610
5129
  set cacheId(value) {
4611
5130
  this._cacheId = value;
4612
5131
  }
4613
5132
  /**
4614
- * The flag to indicate if there are changes since the last save
4615
- * @property changesSinceLastSave
4616
- * @type {Boolean}
4617
- * @default false
4618
- */
5133
+ * The flag to indicate if there are changes since the last save
5134
+ * @property changesSinceLastSave
5135
+ * @type {Boolean}
5136
+ * @default false
5137
+ */
4619
5138
  get changesSinceLastSave() {
4620
5139
  return this._changesSinceLastSave;
4621
5140
  }
4622
5141
  /**
4623
- * The interval to persist the cache to disk. 0 means no timed persistence
4624
- * @property persistInterval
4625
- * @type {Number}
4626
- * @default 0
4627
- */
5142
+ * The interval to persist the cache to disk. 0 means no timed persistence
5143
+ * @property persistInterval
5144
+ * @type {Number}
5145
+ * @default 0
5146
+ */
4628
5147
  get persistInterval() {
4629
5148
  return this._persistInterval;
4630
5149
  }
4631
5150
  /**
4632
- * Set the interval to persist the cache to disk. 0 means no timed persistence
4633
- * @property persistInterval
4634
- * @type {Number}
4635
- * @default 0
4636
- */
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
+ */
4637
5156
  set persistInterval(value) {
4638
5157
  this._persistInterval = value;
4639
5158
  }
4640
5159
  /**
4641
- * Load a cache identified by the given Id. If the element does not exists, then initialize an empty
4642
- * cache storage. If specified `cacheDir` will be used as the directory to persist the data to. If omitted
4643
- * then the cache module directory `.cacheDir` will be used instead
4644
- *
4645
- * @method load
4646
- * @param cacheId {String} the id of the cache, would also be used as the name of the file cache
4647
- * @param cacheDir {String} directory for the cache entry
4648
- */
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
+ */
4649
5168
  load(cacheId, cacheDir) {
4650
5169
  try {
4651
- const filePath = path10.resolve(
4652
- `${cacheDir ?? this._cacheDir}/${cacheId ?? this._cacheId}`
4653
- );
5170
+ const filePath = path10.resolve(`${cacheDir ?? this._cacheDir}/${cacheId ?? this._cacheId}`);
4654
5171
  this.loadFile(filePath);
4655
- this.emit(
4656
- "load"
4657
- /* LOAD */
4658
- );
5172
+ this.emit("load");
4659
5173
  } catch (error) {
4660
5174
  this.emit("error", error);
4661
5175
  }
4662
5176
  }
4663
5177
  /**
4664
- * Load the cache from the provided file
4665
- * @method loadFile
4666
- * @param {String} pathToFile the path to the file containing the info for the cache
4667
- */
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
+ */
4668
5182
  loadFile(pathToFile) {
4669
5183
  if (fs5.existsSync(pathToFile)) {
4670
5184
  const data = fs5.readFileSync(pathToFile, "utf8");
4671
5185
  const items = this._parse(data);
4672
5186
  if (Array.isArray(items)) {
4673
- for (const item of items) {
4674
- if (item && typeof item === "object" && "key" in item) {
4675
- if (item.expires) {
4676
- this._cache.set(item.key, item.value, { expire: item.expires });
4677
- } else if (item.timestamp) {
4678
- this._cache.set(item.key, item.value, { expire: item.timestamp });
4679
- } else {
4680
- this._cache.set(item.key, item.value);
4681
- }
4682
- }
4683
- }
4684
- } else {
4685
- for (const key of Object.keys(items)) {
4686
- const item = items[key];
4687
- if (item && typeof item === "object" && "key" in item) {
4688
- this._cache.set(item.key, item.value, {
4689
- expire: item.expires
4690
- });
4691
- } else {
4692
- if (item && typeof item === "object" && item.timestamp) {
4693
- this._cache.set(key, item, { expire: item.timestamp });
4694
- } else {
4695
- this._cache.set(key, item);
4696
- }
4697
- }
4698
- }
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);
4699
5197
  }
4700
5198
  this._changesSinceLastSave = true;
4701
5199
  }
4702
5200
  }
4703
5201
  loadFileStream(pathToFile, onProgress, onEnd, onError) {
4704
5202
  if (fs5.existsSync(pathToFile)) {
4705
- const stats = fs5.statSync(pathToFile);
4706
- const total = stats.size;
5203
+ const total = fs5.statSync(pathToFile).size;
4707
5204
  let loaded = 0;
4708
5205
  let streamData = "";
4709
5206
  const readStream = fs5.createReadStream(pathToFile, { encoding: "utf8" });
@@ -4714,179 +5211,158 @@ var FlatCache = class extends Hookified {
4714
5211
  });
4715
5212
  readStream.on("end", () => {
4716
5213
  const items = this._parse(streamData);
4717
- for (const key of Object.keys(items)) {
4718
- this._cache.set(items[key].key, items[key].value, {
4719
- expire: items[key].expires
4720
- });
4721
- }
5214
+ for (const key of Object.keys(items)) this._cache.set(items[key].key, items[key].value, { expire: items[key].expires });
4722
5215
  this._changesSinceLastSave = true;
4723
5216
  onEnd();
4724
5217
  });
4725
5218
  readStream.on("error", (error) => {
4726
5219
  this.emit("error", error);
4727
- if (onError) {
4728
- onError(error);
4729
- }
5220
+ if (onError) onError(error);
4730
5221
  });
4731
5222
  } else {
4732
- const error = new Error(`Cache file ${pathToFile} does not exist`);
5223
+ const error = /* @__PURE__ */ new Error(`Cache file ${pathToFile} does not exist`);
4733
5224
  this.emit("error", error);
4734
- if (onError) {
4735
- onError(error);
4736
- }
5225
+ if (onError) onError(error);
4737
5226
  }
4738
5227
  }
4739
5228
  /**
4740
- * Returns the entire persisted object
4741
- * @method all
4742
- * @returns {*}
4743
- */
5229
+ * Returns the entire persisted object
5230
+ * @method all
5231
+ * @returns {*}
5232
+ */
4744
5233
  all() {
4745
5234
  const result = {};
4746
5235
  const items = [...this._cache.items];
4747
- for (const item of items) {
4748
- result[item.key] = item.value;
4749
- }
5236
+ for (const item of items) result[item.key] = item.value;
4750
5237
  return result;
4751
5238
  }
4752
5239
  /**
4753
- * Returns an array with all the items in the cache { key, value, expires }
4754
- * @method items
4755
- * @returns {Array}
4756
- */
4757
- // 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
+ */
4758
5244
  get items() {
4759
5245
  return [...this._cache.items];
4760
5246
  }
4761
5247
  /**
4762
- * Returns the path to the file where the cache is persisted
4763
- * @method cacheFilePath
4764
- * @returns {String}
4765
- */
5248
+ * Returns the path to the file where the cache is persisted
5249
+ * @method cacheFilePath
5250
+ * @returns {String}
5251
+ */
4766
5252
  get cacheFilePath() {
4767
5253
  return path10.resolve(`${this._cacheDir}/${this._cacheId}`);
4768
5254
  }
4769
5255
  /**
4770
- * Returns the path to the cache directory
4771
- * @method cacheDirPath
4772
- * @returns {String}
4773
- */
5256
+ * Returns the path to the cache directory
5257
+ * @method cacheDirPath
5258
+ * @returns {String}
5259
+ */
4774
5260
  get cacheDirPath() {
4775
5261
  return path10.resolve(this._cacheDir);
4776
5262
  }
4777
5263
  /**
4778
- * Returns an array with all the keys in the cache
4779
- * @method keys
4780
- * @returns {Array}
4781
- */
5264
+ * Returns an array with all the keys in the cache
5265
+ * @method keys
5266
+ * @returns {Array}
5267
+ */
4782
5268
  keys() {
4783
5269
  return [...this._cache.keys];
4784
5270
  }
4785
5271
  /**
4786
- * (Legacy) set key method. This method will be deprecated in the future
4787
- * @method setKey
4788
- * @param key {string} the key to set
4789
- * @param value {object} the value of the key. Could be any object that can be serialized with JSON.stringify
4790
- */
4791
- // 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
+ */
4792
5277
  setKey(key, value, ttl) {
4793
5278
  this.set(key, value, ttl);
4794
5279
  }
4795
5280
  /**
4796
- * Sets a key to a given value
4797
- * @method set
4798
- * @param key {string} the key to set
4799
- * @param value {object} the value of the key. Could be any object that can be serialized with JSON.stringify
4800
- * @param [ttl] {number} the time to live in milliseconds
4801
- */
4802
- // 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
+ */
4803
5287
  set(key, value, ttl) {
4804
5288
  this._cache.set(key, value, ttl);
4805
5289
  this._changesSinceLastSave = true;
4806
5290
  }
4807
5291
  /**
4808
- * (Legacy) Remove a given key from the cache. This method will be deprecated in the future
4809
- * @method removeKey
4810
- * @param key {String} the key to remove from the object
4811
- */
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
+ */
4812
5296
  removeKey(key) {
4813
5297
  this.delete(key);
4814
5298
  }
4815
5299
  /**
4816
- * Remove a given key from the cache
4817
- * @method delete
4818
- * @param key {String} the key to remove from the object
4819
- */
5300
+ * Remove a given key from the cache
5301
+ * @method delete
5302
+ * @param key {String} the key to remove from the object
5303
+ */
4820
5304
  delete(key) {
4821
5305
  this._cache.delete(key);
4822
5306
  this._changesSinceLastSave = true;
4823
5307
  this.emit("delete", key);
4824
5308
  }
4825
5309
  /**
4826
- * (Legacy) Return the value of the provided key. This method will be deprecated in the future
4827
- * @method getKey<T>
4828
- * @param key {String} the name of the key to retrieve
4829
- * @returns {*} at T the value from the key
4830
- */
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
+ */
4831
5315
  getKey(key) {
4832
5316
  return this.get(key);
4833
5317
  }
4834
5318
  /**
4835
- * Return the value of the provided key
4836
- * @method get<T>
4837
- * @param key {String} the name of the key to retrieve
4838
- * @returns {*} at T the value from the key
4839
- */
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
+ */
4840
5324
  get(key) {
4841
5325
  return this._cache.get(key);
4842
5326
  }
4843
5327
  /**
4844
- * Clear the cache and save the state to disk
4845
- * @method clear
4846
- */
5328
+ * Clear the cache and save the state to disk
5329
+ * @method clear
5330
+ */
4847
5331
  clear() {
4848
5332
  try {
4849
5333
  this._cache.clear();
4850
5334
  this._changesSinceLastSave = true;
4851
5335
  this.save();
4852
- this.emit(
4853
- "clear"
4854
- /* CLEAR */
4855
- );
5336
+ this.emit("clear");
4856
5337
  } catch (error) {
4857
5338
  this.emit("error", error);
4858
5339
  }
4859
5340
  }
4860
5341
  /**
4861
- * Save the state of the cache identified by the docId to disk
4862
- * as a JSON structure
4863
- * @method save
4864
- */
5342
+ * Save the state of the cache identified by the docId to disk
5343
+ * as a JSON structure
5344
+ * @method save
5345
+ */
4865
5346
  save(force = false) {
4866
5347
  try {
4867
5348
  if (this._changesSinceLastSave || force) {
4868
5349
  const filePath = this.cacheFilePath;
4869
5350
  const items = [...this._cache.items];
4870
5351
  const data = this._stringify(items);
4871
- if (!fs5.existsSync(this._cacheDir)) {
4872
- fs5.mkdirSync(this._cacheDir, { recursive: true });
4873
- }
5352
+ if (!fs5.existsSync(this._cacheDir)) fs5.mkdirSync(this._cacheDir, { recursive: true });
4874
5353
  fs5.writeFileSync(filePath, data);
4875
5354
  this._changesSinceLastSave = false;
4876
- this.emit(
4877
- "save"
4878
- /* SAVE */
4879
- );
5355
+ this.emit("save");
4880
5356
  }
4881
5357
  } catch (error) {
4882
5358
  this.emit("error", error);
4883
5359
  }
4884
5360
  }
4885
5361
  /**
4886
- * Remove the file where the cache is persisted
4887
- * @method removeCacheFile
4888
- * @return {Boolean} true or false if the file was successfully deleted
4889
- */
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
+ */
4890
5366
  removeCacheFile() {
4891
5367
  try {
4892
5368
  if (fs5.existsSync(this.cacheFilePath)) {
@@ -4899,33 +5375,33 @@ var FlatCache = class extends Hookified {
4899
5375
  return false;
4900
5376
  }
4901
5377
  /**
4902
- * Destroy the cache. This will remove the directory, file, and memory cache
4903
- * @method destroy
4904
- * @param [includeCacheDir=false] {Boolean} if true, the cache directory will be removed
4905
- * @return {undefined}
4906
- */
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
+ */
4907
5383
  destroy(includeCacheDirectory = false) {
4908
5384
  try {
4909
5385
  this._cache.clear();
4910
5386
  this.stopAutoPersist();
4911
- if (includeCacheDirectory) {
4912
- fs5.rmSync(this.cacheDirPath, { recursive: true, force: true });
4913
- } else {
4914
- fs5.rmSync(this.cacheFilePath, { recursive: true, force: true });
4915
- }
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
+ });
4916
5395
  this._changesSinceLastSave = false;
4917
- this.emit(
4918
- "destroy"
4919
- /* DESTROY */
4920
- );
5396
+ this.emit("destroy");
4921
5397
  } catch (error) {
4922
5398
  this.emit("error", error);
4923
5399
  }
4924
5400
  }
4925
5401
  /**
4926
- * Start the auto persist interval
4927
- * @method startAutoPersist
4928
- */
5402
+ * Start the auto persist interval
5403
+ * @method startAutoPersist
5404
+ */
4929
5405
  startAutoPersist() {
4930
5406
  if (this._persistInterval > 0) {
4931
5407
  if (this._persistTimer) {
@@ -4938,9 +5414,9 @@ var FlatCache = class extends Hookified {
4938
5414
  }
4939
5415
  }
4940
5416
  /**
4941
- * Stop the auto persist interval
4942
- * @method stopAutoPersist
4943
- */
5417
+ * Stop the auto persist interval
5418
+ * @method stopAutoPersist
5419
+ */
4944
5420
  stopAutoPersist() {
4945
5421
  if (this._persistTimer) {
4946
5422
  clearInterval(this._persistTimer);
@@ -4954,11 +5430,9 @@ function createFromFile(filePath, options) {
4954
5430
  return cache2;
4955
5431
  }
4956
5432
 
4957
- // node_modules/file-entry-cache/dist/index.js
5433
+ // node_modules/file-entry-cache/dist/index.mjs
4958
5434
  function createFromFile2(filePath, options) {
4959
- const fname = path11.basename(filePath);
4960
- const directory = path11.dirname(filePath);
4961
- return create(fname, directory, options);
5435
+ return create(path11.basename(filePath), path11.dirname(filePath), options);
4962
5436
  }
4963
5437
  function create(cacheId, cacheDirectory, options) {
4964
5438
  const opts = {
@@ -4971,8 +5445,11 @@ function create(cacheId, cacheDirectory, options) {
4971
5445
  const fileEntryCache = new FileEntryCache(opts);
4972
5446
  if (cacheDirectory) {
4973
5447
  const cachePath = `${cacheDirectory}/${cacheId}`;
4974
- if (fs6.existsSync(cachePath)) {
5448
+ if (fs6.existsSync(cachePath)) try {
4975
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;
4976
5453
  }
4977
5454
  }
4978
5455
  return fileEntryCache;
@@ -4991,239 +5468,249 @@ var FileEntryCache = class {
4991
5468
  _useAbsolutePathAsKey = false;
4992
5469
  _useModifiedTime = true;
4993
5470
  /**
4994
- * Create a new FileEntryCache instance
4995
- * @param options - The options for the FileEntryCache (all properties are optional with defaults)
4996
- */
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
+ */
4997
5482
  constructor(options) {
4998
- if (options?.cache) {
4999
- this._cache = new FlatCache(options.cache);
5000
- }
5001
- if (options?.useCheckSum) {
5002
- this._useCheckSum = options.useCheckSum;
5003
- }
5004
- if (options?.hashAlgorithm) {
5005
- this._hashAlgorithm = options.hashAlgorithm;
5006
- }
5007
- if (options?.cwd) {
5008
- this._cwd = options.cwd;
5009
- }
5010
- if (options?.useModifiedTime !== void 0) {
5011
- this._useModifiedTime = options.useModifiedTime;
5012
- }
5013
- if (options?.restrictAccessToCwd !== void 0) {
5014
- this._restrictAccessToCwd = options.restrictAccessToCwd;
5015
- }
5016
- if (options?.useAbsolutePathAsKey !== void 0) {
5017
- this._useAbsolutePathAsKey = options.useAbsolutePathAsKey;
5018
- }
5019
- if (options?.logger) {
5020
- this._logger = options.logger;
5021
- }
5022
- }
5023
- /**
5024
- * Get the cache
5025
- * @returns {FlatCache} The cache
5026
- */
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
+ */
5027
5496
  get cache() {
5028
5497
  return this._cache;
5029
5498
  }
5030
5499
  /**
5031
- * Set the cache
5032
- * @param {FlatCache} cache - The cache to set
5033
- */
5500
+ * Set the cache
5501
+ * @param {FlatCache} cache - The cache to set
5502
+ */
5034
5503
  set cache(cache2) {
5035
5504
  this._cache = cache2;
5505
+ this._originalMeta = /* @__PURE__ */ new Map();
5036
5506
  }
5037
5507
  /**
5038
- * Get the logger
5039
- * @returns {ILogger | undefined} The logger instance
5040
- */
5508
+ * Get the logger
5509
+ * @returns {ILogger | undefined} The logger instance
5510
+ */
5041
5511
  get logger() {
5042
5512
  return this._logger;
5043
5513
  }
5044
5514
  /**
5045
- * Set the logger
5046
- * @param {ILogger | undefined} logger - The logger to set
5047
- */
5515
+ * Set the logger
5516
+ * @param {ILogger | undefined} logger - The logger to set
5517
+ */
5048
5518
  set logger(logger) {
5049
5519
  this._logger = logger;
5050
5520
  }
5051
5521
  /**
5052
- * Use the hash to check if the file has changed
5053
- * @returns {boolean} if the hash is used to check if the file has changed (default: false)
5054
- */
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
+ */
5055
5525
  get useCheckSum() {
5056
5526
  return this._useCheckSum;
5057
5527
  }
5058
5528
  /**
5059
- * Set the useCheckSum value
5060
- * @param {boolean} value - The value to set
5061
- */
5529
+ * Set the useCheckSum value
5530
+ * @param {boolean} value - The value to set
5531
+ */
5062
5532
  set useCheckSum(value) {
5063
5533
  this._useCheckSum = value;
5064
5534
  }
5065
5535
  /**
5066
- * Get the hash algorithm
5067
- * @returns {string} The hash algorithm (default: 'md5')
5068
- */
5536
+ * Get the hash algorithm
5537
+ * @returns {string} The hash algorithm (default: 'md5')
5538
+ */
5069
5539
  get hashAlgorithm() {
5070
5540
  return this._hashAlgorithm;
5071
5541
  }
5072
5542
  /**
5073
- * Set the hash algorithm
5074
- * @param {string} value - The value to set
5075
- */
5543
+ * Set the hash algorithm
5544
+ * @param {string} value - The value to set
5545
+ */
5076
5546
  set hashAlgorithm(value) {
5077
5547
  this._hashAlgorithm = value;
5078
5548
  }
5079
5549
  /**
5080
- * Get the current working directory
5081
- * @returns {string} The current working directory (default: process.cwd())
5082
- */
5550
+ * Get the current working directory
5551
+ * @returns {string} The current working directory (default: process.cwd())
5552
+ */
5083
5553
  get cwd() {
5084
5554
  return this._cwd;
5085
5555
  }
5086
5556
  /**
5087
- * Set the current working directory
5088
- * @param {string} value - The value to set
5089
- */
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
+ */
5090
5567
  set cwd(value) {
5091
5568
  this._cwd = value;
5092
5569
  }
5093
5570
  /**
5094
- * Get whether to use modified time for change detection
5095
- * @returns {boolean} Whether modified time (mtime) is used for change detection (default: true)
5096
- */
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
+ */
5097
5574
  get useModifiedTime() {
5098
5575
  return this._useModifiedTime;
5099
5576
  }
5100
5577
  /**
5101
- * Set whether to use modified time for change detection
5102
- * @param {boolean} value - The value to set
5103
- */
5578
+ * Set whether to use modified time for change detection
5579
+ * @param {boolean} value - The value to set
5580
+ */
5104
5581
  set useModifiedTime(value) {
5105
5582
  this._useModifiedTime = value;
5106
5583
  }
5107
5584
  /**
5108
- * Get whether to restrict paths to cwd boundaries
5109
- * @returns {boolean} Whether strict path checking is enabled (default: true)
5110
- */
5585
+ * Get whether to restrict paths to cwd boundaries
5586
+ * @returns {boolean} Whether strict path checking is enabled (default: true)
5587
+ */
5111
5588
  get restrictAccessToCwd() {
5112
5589
  return this._restrictAccessToCwd;
5113
5590
  }
5114
5591
  /**
5115
- * Set whether to restrict paths to cwd boundaries
5116
- * @param {boolean} value - The value to set
5117
- */
5592
+ * Set whether to restrict paths to cwd boundaries
5593
+ * @param {boolean} value - The value to set
5594
+ */
5118
5595
  set restrictAccessToCwd(value) {
5119
5596
  this._restrictAccessToCwd = value;
5120
5597
  }
5121
5598
  /**
5122
- * Get whether to use absolute path as cache key
5123
- * @returns {boolean} Whether cache keys use absolute paths (default: false)
5124
- */
5599
+ * Get whether to use absolute path as cache key
5600
+ * @returns {boolean} Whether cache keys use absolute paths (default: false)
5601
+ */
5125
5602
  get useAbsolutePathAsKey() {
5126
5603
  return this._useAbsolutePathAsKey;
5127
5604
  }
5128
5605
  /**
5129
- * Set whether to use absolute path as cache key
5130
- * @param {boolean} value - The value to set
5131
- */
5606
+ * Set whether to use absolute path as cache key
5607
+ * @param {boolean} value - The value to set
5608
+ */
5132
5609
  set useAbsolutePathAsKey(value) {
5133
5610
  this._useAbsolutePathAsKey = value;
5134
5611
  }
5135
5612
  /**
5136
- * Given a buffer, calculate md5 hash of its content.
5137
- * @method getHash
5138
- * @param {Buffer} buffer buffer to calculate hash on
5139
- * @return {String} content hash digest
5140
- */
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
+ */
5141
5618
  getHash(buffer) {
5142
5619
  return crypto2.createHash(this._hashAlgorithm).update(buffer).digest("hex");
5143
5620
  }
5144
5621
  /**
5145
- * Create the key for the file path used for caching.
5146
- * @method createFileKey
5147
- * @param {String} filePath
5148
- * @return {String}
5149
- */
5622
+ * Create the key for the file path used for caching.
5623
+ * @method createFileKey
5624
+ * @param {String} filePath
5625
+ * @return {String}
5626
+ */
5150
5627
  createFileKey(filePath) {
5151
5628
  let result = filePath;
5152
- if (this._useAbsolutePathAsKey && this.isRelativePath(filePath)) {
5153
- result = this.getAbsolutePathWithCwd(filePath, this._cwd);
5154
- }
5629
+ if (this._useAbsolutePathAsKey && this.isRelativePath(filePath)) result = this.getAbsolutePathWithCwd(filePath, this._cwd);
5155
5630
  return result;
5156
5631
  }
5157
5632
  /**
5158
- * Check if the file path is a relative path
5159
- * @method isRelativePath
5160
- * @param filePath - The file path to check
5161
- * @returns {boolean} if the file path is a relative path, false otherwise
5162
- */
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
+ */
5163
5638
  isRelativePath(filePath) {
5164
5639
  return !path11.isAbsolute(filePath);
5165
5640
  }
5166
5641
  /**
5167
- * Delete the cache file from the disk
5168
- * @method deleteCacheFile
5169
- * @return {boolean} true if the file was deleted, false otherwise
5170
- */
5642
+ * Delete the cache file from the disk
5643
+ * @method deleteCacheFile
5644
+ * @return {boolean} true if the file was deleted, false otherwise
5645
+ */
5171
5646
  deleteCacheFile() {
5172
5647
  return this._cache.removeCacheFile();
5173
5648
  }
5174
5649
  /**
5175
- * Remove the cache from the file and clear the memory cache
5176
- * @method destroy
5177
- */
5650
+ * Remove the cache from the file and clear the memory cache
5651
+ * @method destroy
5652
+ */
5178
5653
  destroy() {
5179
5654
  this._cache.destroy();
5655
+ this._originalMeta = /* @__PURE__ */ new Map();
5180
5656
  }
5181
5657
  /**
5182
- * Remove and Entry From the Cache
5183
- * @method removeEntry
5184
- * @param filePath - The file path to remove from the cache
5185
- */
5658
+ * Remove and Entry From the Cache
5659
+ * @method removeEntry
5660
+ * @param filePath - The file path to remove from the cache
5661
+ */
5186
5662
  removeEntry(filePath) {
5187
5663
  const key = this.createFileKey(filePath);
5188
5664
  this._cache.removeKey(key);
5665
+ this._originalMeta.delete(key);
5189
5666
  }
5190
5667
  /**
5191
- * Reconcile the cache
5192
- * @method reconcile
5193
- */
5668
+ * Reconcile the cache
5669
+ * @method reconcile
5670
+ */
5194
5671
  reconcile() {
5195
- const { items } = this._cache;
5196
- for (const item of items) {
5197
- const fileDescriptor = this.getFileDescriptor(item.key);
5198
- if (fileDescriptor.notFound) {
5199
- this._cache.removeKey(item.key);
5200
- }
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);
5201
5687
  }
5202
5688
  this._cache.save();
5203
5689
  }
5204
5690
  /**
5205
- * Check if the file has changed
5206
- * @method hasFileChanged
5207
- * @param filePath - The file path to check
5208
- * @returns {boolean} if the file has changed, false otherwise
5209
- */
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
+ */
5210
5696
  hasFileChanged(filePath) {
5211
5697
  let result = false;
5212
5698
  const fileDescriptor = this.getFileDescriptor(filePath);
5213
- if ((!fileDescriptor.err || !fileDescriptor.notFound) && fileDescriptor.changed) {
5214
- result = true;
5215
- }
5699
+ if ((!fileDescriptor.err || !fileDescriptor.notFound) && fileDescriptor.changed) result = true;
5216
5700
  return result;
5217
5701
  }
5218
5702
  /**
5219
- * Get the file descriptor for the file path
5220
- * @method getFileDescriptor
5221
- * @param filePath - The file path to get the file descriptor for
5222
- * @param options - The options for getting the file descriptor
5223
- * @returns The file descriptor
5224
- */
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
+ */
5225
5709
  getFileDescriptor(filePath, options) {
5226
- this._logger?.debug({ filePath, options }, "Getting file descriptor");
5710
+ this._logger?.debug({
5711
+ filePath,
5712
+ options
5713
+ }, "Getting file descriptor");
5227
5714
  let fstat;
5228
5715
  const result = {
5229
5716
  key: this.createFileKey(filePath),
@@ -5232,39 +5719,33 @@ var FileEntryCache = class {
5232
5719
  };
5233
5720
  this._logger?.trace({ key: result.key }, "Created file key");
5234
5721
  const metaCache = this._cache.getKey(result.key);
5235
- if (metaCache) {
5236
- this._logger?.trace({ metaCache }, "Found cached meta");
5237
- } else {
5238
- this._logger?.trace("No cached meta found");
5239
- }
5722
+ if (metaCache) this._logger?.trace({ metaCache }, "Found cached meta");
5723
+ else this._logger?.trace("No cached meta found");
5240
5724
  result.meta = metaCache ? { ...metaCache } : {};
5241
5725
  const absolutePath = this.getAbsolutePath(filePath);
5242
5726
  this._logger?.trace({ absolutePath }, "Resolved absolute path");
5243
5727
  const useCheckSumValue = options?.useCheckSum ?? this._useCheckSum;
5244
- this._logger?.debug(
5245
- { useCheckSum: useCheckSumValue },
5246
- "Using checksum setting"
5247
- );
5728
+ this._logger?.debug({ useCheckSum: useCheckSumValue }, "Using checksum setting");
5248
5729
  const useModifiedTimeValue = options?.useModifiedTime ?? this.useModifiedTime;
5249
- this._logger?.debug(
5250
- { useModifiedTime: useModifiedTimeValue },
5251
- "Using modified time (mtime) setting"
5252
- );
5730
+ this._logger?.debug({ useModifiedTime: useModifiedTimeValue }, "Using modified time (mtime) setting");
5253
5731
  try {
5254
5732
  fstat = fs6.statSync(absolutePath);
5255
5733
  result.meta.size = fstat.size;
5256
5734
  result.meta.mtime = fstat.mtime.getTime();
5257
- this._logger?.trace(
5258
- { size: result.meta.size, mtime: result.meta.mtime },
5259
- "Read file stats"
5260
- );
5735
+ this._logger?.trace({
5736
+ size: result.meta.size,
5737
+ mtime: result.meta.mtime
5738
+ }, "Read file stats");
5261
5739
  if (useCheckSumValue) {
5262
5740
  const buffer = fs6.readFileSync(absolutePath);
5263
5741
  result.meta.hash = this.getHash(buffer);
5264
5742
  this._logger?.trace({ hash: result.meta.hash }, "Calculated file hash");
5265
5743
  }
5266
5744
  } catch (error) {
5267
- this._logger?.error({ filePath, error }, "Error reading file");
5745
+ this._logger?.error({
5746
+ filePath,
5747
+ error
5748
+ }, "Error reading file");
5268
5749
  this.removeEntry(filePath);
5269
5750
  let notFound = false;
5270
5751
  if (error.message.includes("ENOENT")) {
@@ -5278,47 +5759,49 @@ var FileEntryCache = class {
5278
5759
  meta: {}
5279
5760
  };
5280
5761
  }
5281
- 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) {
5282
5765
  result.changed = true;
5283
5766
  this._cache.setKey(result.key, result.meta);
5284
5767
  this._logger?.debug({ filePath }, "File not in cache, marked as changed");
5285
5768
  return result;
5286
5769
  }
5287
- if (useModifiedTimeValue && metaCache?.mtime !== result.meta?.mtime) {
5770
+ if (useModifiedTimeValue && baseline.mtime !== result.meta?.mtime) {
5288
5771
  result.changed = true;
5289
- this._logger?.debug(
5290
- { filePath, oldMtime: metaCache.mtime, newMtime: result.meta.mtime },
5291
- "File changed: mtime differs"
5292
- );
5772
+ this._logger?.debug({
5773
+ filePath,
5774
+ oldMtime: baseline.mtime,
5775
+ newMtime: result.meta.mtime
5776
+ }, "File changed: mtime differs");
5293
5777
  }
5294
- if (metaCache?.size !== result.meta?.size) {
5778
+ if (baseline.size !== result.meta?.size) {
5295
5779
  result.changed = true;
5296
- this._logger?.debug(
5297
- { filePath, oldSize: metaCache.size, newSize: result.meta.size },
5298
- "File changed: size differs"
5299
- );
5780
+ this._logger?.debug({
5781
+ filePath,
5782
+ oldSize: baseline.size,
5783
+ newSize: result.meta.size
5784
+ }, "File changed: size differs");
5300
5785
  }
5301
- if (useCheckSumValue && metaCache?.hash !== result.meta?.hash) {
5786
+ if (useCheckSumValue && baseline.hash !== result.meta?.hash) {
5302
5787
  result.changed = true;
5303
- this._logger?.debug(
5304
- { filePath, oldHash: metaCache.hash, newHash: result.meta.hash },
5305
- "File changed: hash differs"
5306
- );
5788
+ this._logger?.debug({
5789
+ filePath,
5790
+ oldHash: baseline.hash,
5791
+ newHash: result.meta.hash
5792
+ }, "File changed: hash differs");
5307
5793
  }
5308
5794
  this._cache.setKey(result.key, result.meta);
5309
- if (result.changed) {
5310
- this._logger?.info({ filePath }, "File has changed");
5311
- } else {
5312
- this._logger?.debug({ filePath }, "File unchanged");
5313
- }
5795
+ if (result.changed) this._logger?.info({ filePath }, "File has changed");
5796
+ else this._logger?.debug({ filePath }, "File unchanged");
5314
5797
  return result;
5315
5798
  }
5316
5799
  /**
5317
- * Get the file descriptors for the files
5318
- * @method normalizeEntries
5319
- * @param files?: string[] - The files to get the file descriptors for
5320
- * @returns The file descriptors
5321
- */
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
+ */
5322
5805
  normalizeEntries(files) {
5323
5806
  const result = [];
5324
5807
  if (files) {
@@ -5331,18 +5814,16 @@ var FileEntryCache = class {
5331
5814
  const keys2 = this.cache.keys();
5332
5815
  for (const key of keys2) {
5333
5816
  const fileDescriptor = this.getFileDescriptor(key);
5334
- if (!fileDescriptor.notFound && !fileDescriptor.err) {
5335
- result.push(fileDescriptor);
5336
- }
5817
+ if (!fileDescriptor.notFound && !fileDescriptor.err) result.push(fileDescriptor);
5337
5818
  }
5338
5819
  return result;
5339
5820
  }
5340
5821
  /**
5341
- * Analyze the files
5342
- * @method analyzeFiles
5343
- * @param files - The files to analyze
5344
- * @returns {AnalyzedFiles} The analysis of the files
5345
- */
5822
+ * Analyze the files
5823
+ * @method analyzeFiles
5824
+ * @param files - The files to analyze
5825
+ * @returns {AnalyzedFiles} The analysis of the files
5826
+ */
5346
5827
  analyzeFiles(files) {
5347
5828
  const result = {
5348
5829
  changedFiles: [],
@@ -5350,58 +5831,47 @@ var FileEntryCache = class {
5350
5831
  notChangedFiles: []
5351
5832
  };
5352
5833
  const fileDescriptors = this.normalizeEntries(files);
5353
- for (const fileDescriptor of fileDescriptors) {
5354
- if (fileDescriptor.notFound) {
5355
- result.notFoundFiles.push(fileDescriptor.key);
5356
- } else if (fileDescriptor.changed) {
5357
- result.changedFiles.push(fileDescriptor.key);
5358
- } else {
5359
- result.notChangedFiles.push(fileDescriptor.key);
5360
- }
5361
- }
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);
5362
5837
  return result;
5363
5838
  }
5364
5839
  /**
5365
- * Get the updated files
5366
- * @method getUpdatedFiles
5367
- * @param files - The files to get the updated files for
5368
- * @returns {string[]} The updated files
5369
- */
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
+ */
5370
5845
  getUpdatedFiles(files) {
5371
5846
  const result = [];
5372
5847
  const fileDescriptors = this.normalizeEntries(files);
5373
- for (const fileDescriptor of fileDescriptors) {
5374
- if (fileDescriptor.changed) {
5375
- result.push(fileDescriptor.key);
5376
- }
5377
- }
5848
+ for (const fileDescriptor of fileDescriptors) if (fileDescriptor.changed) result.push(fileDescriptor.key);
5378
5849
  return result;
5379
5850
  }
5380
5851
  /**
5381
- * Get the file descriptors by path prefix
5382
- * @method getFileDescriptorsByPath
5383
- * @param filePath - the path prefix to match
5384
- * @returns {FileDescriptor[]} The file descriptors
5385
- */
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
+ */
5386
5857
  getFileDescriptorsByPath(filePath) {
5387
5858
  const result = [];
5388
5859
  const keys2 = this._cache.keys();
5389
- for (const key of keys2) {
5860
+ for (const key of keys2)
5390
5861
  if (key.startsWith(filePath)) {
5391
5862
  const fileDescriptor = this.getFileDescriptor(key);
5392
5863
  result.push(fileDescriptor);
5393
5864
  }
5394
- }
5395
5865
  return result;
5396
5866
  }
5397
5867
  /**
5398
- * Get the Absolute Path. If it is already absolute it will return the path as is.
5399
- * When restrictAccessToCwd is enabled, ensures the resolved path stays within cwd boundaries.
5400
- * @method getAbsolutePath
5401
- * @param filePath - The file path to get the absolute path for
5402
- * @returns {string}
5403
- * @throws {Error} When restrictAccessToCwd is true and path would resolve outside cwd
5404
- */
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
+ */
5405
5875
  getAbsolutePath(filePath) {
5406
5876
  if (this.isRelativePath(filePath)) {
5407
5877
  const sanitizedPath = filePath.replace(/\0/g, "");
@@ -5409,26 +5879,21 @@ var FileEntryCache = class {
5409
5879
  if (this._restrictAccessToCwd) {
5410
5880
  const normalizedResolved = path11.normalize(resolved);
5411
5881
  const normalizedCwd = path11.normalize(this._cwd);
5412
- const isWithinCwd = normalizedResolved === normalizedCwd || normalizedResolved.startsWith(normalizedCwd + path11.sep);
5413
- if (!isWithinCwd) {
5414
- throw new Error(
5415
- `Path traversal attempt blocked: "${filePath}" resolves outside of working directory "${this._cwd}"`
5416
- );
5417
- }
5882
+ if (!(normalizedResolved === normalizedCwd || normalizedResolved.startsWith(normalizedCwd + path11.sep))) throw new Error(`Path traversal attempt blocked: "${filePath}" resolves outside of working directory "${this._cwd}"`);
5418
5883
  }
5419
5884
  return resolved;
5420
5885
  }
5421
5886
  return filePath;
5422
5887
  }
5423
5888
  /**
5424
- * Get the Absolute Path with a custom working directory. If it is already absolute it will return the path as is.
5425
- * When restrictAccessToCwd is enabled, ensures the resolved path stays within the provided cwd boundaries.
5426
- * @method getAbsolutePathWithCwd
5427
- * @param filePath - The file path to get the absolute path for
5428
- * @param cwd - The custom working directory to resolve relative paths from
5429
- * @returns {string}
5430
- * @throws {Error} When restrictAccessToCwd is true and path would resolve outside the provided cwd
5431
- */
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
+ */
5432
5897
  getAbsolutePathWithCwd(filePath, cwd3) {
5433
5898
  if (this.isRelativePath(filePath)) {
5434
5899
  const sanitizedPath = filePath.replace(/\0/g, "");
@@ -5436,33 +5901,31 @@ var FileEntryCache = class {
5436
5901
  if (this._restrictAccessToCwd) {
5437
5902
  const normalizedResolved = path11.normalize(resolved);
5438
5903
  const normalizedCwd = path11.normalize(cwd3);
5439
- const isWithinCwd = normalizedResolved === normalizedCwd || normalizedResolved.startsWith(normalizedCwd + path11.sep);
5440
- if (!isWithinCwd) {
5441
- throw new Error(
5442
- `Path traversal attempt blocked: "${filePath}" resolves outside of working directory "${cwd3}"`
5443
- );
5444
- }
5904
+ if (!(normalizedResolved === normalizedCwd || normalizedResolved.startsWith(normalizedCwd + path11.sep))) throw new Error(`Path traversal attempt blocked: "${filePath}" resolves outside of working directory "${cwd3}"`);
5445
5905
  }
5446
5906
  return resolved;
5447
5907
  }
5448
5908
  return filePath;
5449
5909
  }
5450
5910
  /**
5451
- * Rename cache keys that start with a given path prefix.
5452
- * @method renameCacheKeys
5453
- * @param oldPath - The old path prefix to rename
5454
- * @param newPath - The new path prefix to rename to
5455
- */
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
+ */
5456
5916
  renameCacheKeys(oldPath, newPath) {
5457
5917
  const keys2 = this._cache.keys();
5458
- for (const key of keys2) {
5918
+ for (const key of keys2)
5459
5919
  if (key.startsWith(oldPath)) {
5460
5920
  const newKey = key.replace(oldPath, newPath);
5461
5921
  const meta = this._cache.getKey(key);
5462
5922
  this._cache.removeKey(key);
5463
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
+ }
5464
5928
  }
5465
- }
5466
5929
  }
5467
5930
  };
5468
5931
 
@@ -6153,7 +6616,6 @@ async function formatFiles(context) {
6153
6616
  }
6154
6617
  const isFileIgnored = isIgnored(filename);
6155
6618
  if (isFileIgnored && (context.argv.debugCheck || context.argv.write || context.argv.check || context.argv.listDifferent)) {
6156
- formatResultsCache?.removeFormatResultsCache(filename);
6157
6619
  continue;
6158
6620
  }
6159
6621
  const options = {