cacheable 2.1.0 → 2.1.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.
Files changed (3) hide show
  1. package/dist/index.cjs +1087 -1
  2. package/dist/index.js +1072 -1
  3. package/package.json +10 -10
package/dist/index.cjs CHANGED
@@ -1 +1,1087 @@
1
- "use strict";var A=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var G=Object.prototype.hasOwnProperty;var k=(d,t)=>{for(var i in t)A(d,i,{get:t[i],enumerable:!0})},x=(d,t,i,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of P(t))!G.call(d,s)&&s!==i&&A(d,s,{get:()=>t[s],enumerable:!(e=B(t,s))||e.enumerable});return d};var N=d=>x(A({},"__esModule",{value:!0}),d);var Y={};k(Y,{Cacheable:()=>M,CacheableEvents:()=>R,CacheableHooks:()=>E,CacheableMemory:()=>f.CacheableMemory,CacheableStats:()=>l.Stats,CacheableSync:()=>_,CacheableSyncEvents:()=>S,HashAlgorithm:()=>l.HashAlgorithm,Keyv:()=>v.Keyv,KeyvCacheableMemory:()=>f.KeyvCacheableMemory,KeyvHooks:()=>v.KeyvHooks,calculateTtlFromExpiration:()=>l.calculateTtlFromExpiration,createKeyv:()=>f.createKeyv,getCascadingTtl:()=>l.getCascadingTtl,getOrSet:()=>m.getOrSet,hash:()=>l.hash,shorthandToMilliseconds:()=>l.shorthandToMilliseconds,shorthandToTime:()=>l.shorthandToTime,wrap:()=>m.wrap,wrapSync:()=>m.wrapSync});module.exports=N(Y);var T=require("@cacheable/memoize"),K=require("@cacheable/memory"),o=require("@cacheable/utils"),F=require("hookified"),O=require("keyv");var E=(c=>(c.BEFORE_SET="BEFORE_SET",c.AFTER_SET="AFTER_SET",c.BEFORE_SET_MANY="BEFORE_SET_MANY",c.AFTER_SET_MANY="AFTER_SET_MANY",c.BEFORE_GET="BEFORE_GET",c.AFTER_GET="AFTER_GET",c.BEFORE_GET_MANY="BEFORE_GET_MANY",c.AFTER_GET_MANY="AFTER_GET_MANY",c.BEFORE_SECONDARY_SETS_PRIMARY="BEFORE_SECONDARY_SETS_PRIMARY",c))(E||{}),R=(e=>(e.ERROR="error",e.CACHE_HIT="cache:hit",e.CACHE_MISS="cache:miss",e))(R||{});var I=require("hookified"),g=require("qified"),S=(e=>(e.ERROR="error",e.SET="cache:set",e.DELETE="cache:delete",e))(S||{}),_=class extends I.Hookified{_qified=new g.Qified;constructor(t){super(t),this._qified=this.createQified(t.qified)}get qified(){return this._qified}set qified(t){this._qified=this.createQified(t)}async publish(t,i){await this._qified.publish(t,{id:crypto.randomUUID(),data:i})}subscribe(t,i){this._qified.subscribe("cache:set",{handler:async e=>{let s=e.data;s.cacheId!==i&&await t.set(s.key,s.value,s.ttl)}}),this._qified.subscribe("cache:delete",{handler:async e=>{let s=e.data;s.cacheId!==i&&await t.delete(s.key)}})}createQified(t){if(t instanceof g.Qified)return t;let i=Array.isArray(t)?t:[t];return new g.Qified({messageProviders:i})}};var m=require("@cacheable/memoize"),f=require("@cacheable/memory"),l=require("@cacheable/utils"),v=require("keyv"),M=class extends F.Hookified{_primary=(0,K.createKeyv)();_secondary;_nonBlocking=!1;_ttl;_stats=new o.Stats({enabled:!1});_namespace;_cacheId=Math.random().toString(36).slice(2);_sync;constructor(t){super(),t?.primary&&this.setPrimary(t.primary),t?.secondary&&this.setSecondary(t.secondary),t?.nonBlocking&&(this._nonBlocking=t.nonBlocking),t?.stats&&(this._stats.enabled=t.stats),t?.ttl&&this.setTtl(t.ttl),t?.cacheId&&(this._cacheId=t.cacheId),t?.namespace&&(this._namespace=t.namespace,this._primary.namespace=this.getNameSpace(),this._secondary&&(this._secondary.namespace=this.getNameSpace())),t?.sync&&(this._sync=t.sync instanceof _?t.sync:new _(t.sync),this._sync.subscribe(this._primary,this._cacheId))}get namespace(){return this._namespace}set namespace(t){this._namespace=t,this._primary.namespace=this.getNameSpace(),this._secondary&&(this._secondary.namespace=this.getNameSpace())}get stats(){return this._stats}get primary(){return this._primary}set primary(t){this._primary=t}get secondary(){return this._secondary}set secondary(t){this._secondary=t}get nonBlocking(){return this._nonBlocking}set nonBlocking(t){this._nonBlocking=t}get ttl(){return this._ttl}set ttl(t){this.setTtl(t)}get cacheId(){return this._cacheId}set cacheId(t){this._cacheId=t}get sync(){return this._sync}set sync(t){this._sync=t,this._sync&&this._sync.subscribe(this._primary,this._cacheId)}setPrimary(t){(0,o.isKeyvInstance)(t)?this._primary=t:this._primary=new O.Keyv(t),this._primary.on("error",i=>{this.emit("error",i)})}setSecondary(t){(0,o.isKeyvInstance)(t)?this._secondary=t:this._secondary=new O.Keyv(t),this._secondary.on("error",i=>{this.emit("error",i)})}getNameSpace(){return typeof this._namespace=="function"?this._namespace():this._namespace}async get(t,i){return(await this.getRaw(t,i))?.value}async getRaw(t,i){let e;try{await this.hook("BEFORE_GET",t),e=await this._primary.getRaw(t);let s;e?this.emit("cache:hit",{key:t,value:e.value,store:"primary"}):this.emit("cache:miss",{key:t,store:"primary"});let n=i?.nonBlocking??this._nonBlocking;if(!e&&this._secondary){let a;n?a=await this.processSecondaryForGetRawNonBlocking(this._primary,this._secondary,t):a=await this.processSecondaryForGetRaw(this._primary,this._secondary,t),a&&(e=a.result,s=a.ttl)}await this.hook("AFTER_GET",{key:t,result:e,ttl:s})}catch(s){this.emit("error",s)}return this.stats.enabled&&(e?this._stats.incrementHits():this._stats.incrementMisses(),this.stats.incrementGets()),e}async getManyRaw(t,i){let e=[];try{await this.hook("BEFORE_GET_MANY",t),e=await this._primary.getManyRaw(t);for(let[n,a]of t.entries())e[n]?this.emit("cache:hit",{key:a,value:e[n].value,store:"primary"}):this.emit("cache:miss",{key:a,store:"primary"});let s=i?.nonBlocking??this._nonBlocking;this._secondary&&(s?await this.processSecondaryForGetManyRawNonBlocking(this._primary,this._secondary,t,e):await this.processSecondaryForGetManyRaw(this._primary,this._secondary,t,e)),await this.hook("AFTER_GET_MANY",{keys:t,result:e})}catch(s){this.emit("error",s)}if(this.stats.enabled){for(let s of e)s?this._stats.incrementHits():this._stats.incrementMisses();this.stats.incrementGets()}return e}async getMany(t,i){return(await this.getManyRaw(t,i)).map(s=>s?.value)}async set(t,i,e){let s=!1,n=(0,o.shorthandToMilliseconds)(e??this._ttl);try{let a={key:t,value:i,ttl:n};await this.hook("BEFORE_SET",a);let r=[];if(r.push(this._primary.set(a.key,a.value,a.ttl)),this._secondary&&r.push(this._secondary.set(a.key,a.value,a.ttl)),this._nonBlocking){s=await Promise.race(r);for(let h of r)h.catch(c=>{this.emit("error",c)})}else s=(await Promise.all(r))[0];await this.hook("AFTER_SET",a),this._sync&&s&&await this._sync.publish("cache:set",{cacheId:this._cacheId,key:a.key,value:a.value,ttl:a.ttl})}catch(a){this.emit("error",a)}return this.stats.enabled&&(this.stats.incrementKSize(t),this.stats.incrementCount(),this.stats.incrementVSize(i),this.stats.incrementSets()),s}async setMany(t){let i=!1;try{if(await this.hook("BEFORE_SET_MANY",t),i=await this.setManyKeyv(this._primary,t),this._secondary&&(this._nonBlocking?this.setManyKeyv(this._secondary,t).catch(e=>{this.emit("error",e)}):await this.setManyKeyv(this._secondary,t)),await this.hook("AFTER_SET_MANY",t),this._sync&&i)for(let e of t)await this._sync.publish("cache:set",{cacheId:this._cacheId,key:e.key,value:e.value,ttl:(0,o.shorthandToMilliseconds)(e.ttl)})}catch(e){this.emit("error",e)}if(this.stats.enabled)for(let e of t)this.stats.incrementKSize(e.key),this.stats.incrementCount(),this.stats.incrementVSize(e.value);return i}async take(t){let i=await this.get(t);return await this.delete(t),i}async takeMany(t){let i=await this.getMany(t);return await this.deleteMany(t),i}async has(t){let i=[];i.push(this._primary.has(t)),this._secondary&&i.push(this._secondary.has(t));let e=await Promise.all(i);for(let s of e)if(s)return!0;return!1}async hasMany(t){let i=await this.hasManyKeyv(this._primary,t),e=[];for(let[s,n]of t.entries())!i[s]&&this._secondary&&e.push(n);if(e.length>0&&this._secondary){let s=await this.hasManyKeyv(this._secondary,t);for(let[n,a]of t.entries())!i[n]&&s[n]&&(i[n]=s[n])}return i}async delete(t){let i=!1,e=[];if(this.stats.enabled){let s=await this._primary.get(t);s&&(this.stats.decreaseKSize(t),this.stats.decreaseVSize(s),this.stats.decreaseCount(),this.stats.incrementDeletes())}if(e.push(this._primary.delete(t)),this._secondary&&e.push(this._secondary.delete(t)),this.nonBlocking){i=await Promise.race(e);for(let s of e)s.catch(n=>{this.emit("error",n)})}else i=(await Promise.all(e))[0];return this._sync&&i&&await this._sync.publish("cache:delete",{cacheId:this._cacheId,key:t}),i}async deleteMany(t){if(this.stats.enabled){let e=await this._primary.get(t);for(let s of t)this.stats.decreaseKSize(s),this.stats.decreaseVSize(e),this.stats.decreaseCount(),this.stats.incrementDeletes()}let i=await this._primary.deleteMany(t);if(this._secondary&&(this._nonBlocking?this._secondary.deleteMany(t).catch(e=>{this.emit("error",e)}):await this._secondary.deleteMany(t)),this._sync&&i)for(let e of t)await this._sync.publish("cache:delete",{cacheId:this._cacheId,key:e});return i}async clear(){let t=[];t.push(this._primary.clear()),this._secondary&&t.push(this._secondary.clear()),await(this._nonBlocking?Promise.race(t):Promise.all(t)),this.stats.enabled&&(this._stats.resetStoreValues(),this._stats.incrementClears())}async disconnect(){let t=[];t.push(this._primary.disconnect()),this._secondary&&t.push(this._secondary.disconnect()),await(this._nonBlocking?Promise.race(t):Promise.all(t))}wrap(t,i){let e={get:async n=>this.get(n),has:async n=>this.has(n),set:async(n,a,r)=>{await this.set(n,a,r)},on:(n,a)=>{this.on(n,a)},emit:(n,...a)=>this.emit(n,...a)},s={ttl:i?.ttl??this._ttl,keyPrefix:i?.keyPrefix,createKey:i?.createKey,cacheErrors:i?.cacheErrors,cache:e,cacheId:this._cacheId,serialize:i?.serialize};return(0,T.wrap)(t,s)}async getOrSet(t,i,e){let n={cache:{get:async a=>this.get(a),has:async a=>this.has(a),set:async(a,r,h)=>{await this.set(a,r,h)},on:(a,r)=>{this.on(a,r)},emit:(a,...r)=>this.emit(a,...r)},cacheId:this._cacheId,ttl:e?.ttl??this._ttl,cacheErrors:e?.cacheErrors,throwErrors:e?.throwErrors};return(0,T.getOrSet)(t,i,n)}hash(t,i=o.HashAlgorithm.SHA256){let e=Object.values(o.HashAlgorithm).includes(i)?i:o.HashAlgorithm.SHA256;return(0,o.hash)(t,{algorithm:e})}async setManyKeyv(t,i){let e=[];for(let s of i){let n=(0,o.shorthandToMilliseconds)(s.ttl??this._ttl);e.push({key:s.key,value:s.value,ttl:n})}return await t.setMany(e),!0}async hasManyKeyv(t,i){let e=[];for(let s of i)e.push(t.has(s));return Promise.all(e)}async processSecondaryForGetRaw(t,i,e){let s=await i.getRaw(e);if(s?.value){this.emit("cache:hit",{key:e,value:s.value,store:"secondary"});let n=(0,o.getCascadingTtl)(this._ttl,this._primary.ttl),a=s.expires??void 0,r=(0,o.calculateTtlFromExpiration)(n,a),h={key:e,value:s.value,ttl:r};return await this.hook("BEFORE_SECONDARY_SETS_PRIMARY",h),await t.set(h.key,h.value,h.ttl),{result:s,ttl:r}}else{this.emit("cache:miss",{key:e,store:"secondary"});return}}async processSecondaryForGetRawNonBlocking(t,i,e){let s=await i.getRaw(e);if(s?.value){this.emit("cache:hit",{key:e,value:s.value,store:"secondary"});let n=(0,o.getCascadingTtl)(this._ttl,this._primary.ttl),a=s.expires??void 0,r=(0,o.calculateTtlFromExpiration)(n,a),h={key:e,value:s.value,ttl:r};return this.hook("BEFORE_SECONDARY_SETS_PRIMARY",h).then(async()=>{await t.set(h.key,h.value,h.ttl)}).catch(c=>{this.emit("error",c)}),{result:s,ttl:r}}else{this.emit("cache:miss",{key:e,store:"secondary"});return}}async processSecondaryForGetManyRaw(t,i,e,s){let n=[];for(let[h,c]of e.entries())s[h]||n.push(c);let a=await i.getManyRaw(n),r=0;for await(let[h,c]of e.entries())if(!s[h]){let y=a[r];if(y&&y.value!==void 0){s[h]=y,this.emit("cache:hit",{key:c,value:y.value,store:"secondary"});let b=(0,o.getCascadingTtl)(this._ttl,this._primary.ttl),{expires:u}=y;u===null&&(u=void 0);let w=(0,o.calculateTtlFromExpiration)(b,u),p={key:c,value:y.value,ttl:w};await this.hook("BEFORE_SECONDARY_SETS_PRIMARY",p),await t.set(p.key,p.value,p.ttl)}else this.emit("cache:miss",{key:c,store:"secondary"});r++}}async processSecondaryForGetManyRawNonBlocking(t,i,e,s){let n=[];for(let[h,c]of e.entries())s[h]||n.push(c);let a=await i.getManyRaw(n),r=0;for await(let[h,c]of e.entries())if(!s[h]){let y=a[r];if(y&&y.value!==void 0){s[h]=y,this.emit("cache:hit",{key:c,value:y.value,store:"secondary"});let b=(0,o.getCascadingTtl)(this._ttl,this._primary.ttl),{expires:u}=y;u===null&&(u=void 0);let w=(0,o.calculateTtlFromExpiration)(b,u),p={key:c,value:y.value,ttl:w};this.hook("BEFORE_SECONDARY_SETS_PRIMARY",p).then(async()=>{await t.set(p.key,p.value,p.ttl)}).catch(C=>{this.emit("error",C)})}else this.emit("cache:miss",{key:c,store:"secondary"});r++}}setTtl(t){typeof t=="string"||t===void 0?this._ttl=t:t>0?this._ttl=t:this._ttl=void 0}};0&&(module.exports={Cacheable,CacheableEvents,CacheableHooks,CacheableMemory,CacheableStats,CacheableSync,CacheableSyncEvents,HashAlgorithm,Keyv,KeyvCacheableMemory,KeyvHooks,calculateTtlFromExpiration,createKeyv,getCascadingTtl,getOrSet,hash,shorthandToMilliseconds,shorthandToTime,wrap,wrapSync});
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Cacheable: () => Cacheable,
24
+ CacheableEvents: () => CacheableEvents,
25
+ CacheableHooks: () => CacheableHooks,
26
+ CacheableMemory: () => import_memory2.CacheableMemory,
27
+ CacheableStats: () => import_utils2.Stats,
28
+ CacheableSync: () => CacheableSync,
29
+ CacheableSyncEvents: () => CacheableSyncEvents,
30
+ HashAlgorithm: () => import_utils2.HashAlgorithm,
31
+ Keyv: () => import_keyv2.Keyv,
32
+ KeyvCacheableMemory: () => import_memory2.KeyvCacheableMemory,
33
+ KeyvHooks: () => import_keyv2.KeyvHooks,
34
+ calculateTtlFromExpiration: () => import_utils2.calculateTtlFromExpiration,
35
+ createKeyv: () => import_memory2.createKeyv,
36
+ getCascadingTtl: () => import_utils2.getCascadingTtl,
37
+ getOrSet: () => import_memoize2.getOrSet,
38
+ hash: () => import_utils2.hash,
39
+ shorthandToMilliseconds: () => import_utils2.shorthandToMilliseconds,
40
+ shorthandToTime: () => import_utils2.shorthandToTime,
41
+ wrap: () => import_memoize2.wrap,
42
+ wrapSync: () => import_memoize2.wrapSync
43
+ });
44
+ module.exports = __toCommonJS(index_exports);
45
+ var import_memoize = require("@cacheable/memoize");
46
+ var import_memory = require("@cacheable/memory");
47
+ var import_utils = require("@cacheable/utils");
48
+ var import_hookified2 = require("hookified");
49
+ var import_keyv = require("keyv");
50
+
51
+ // src/enums.ts
52
+ var CacheableHooks = /* @__PURE__ */ ((CacheableHooks2) => {
53
+ CacheableHooks2["BEFORE_SET"] = "BEFORE_SET";
54
+ CacheableHooks2["AFTER_SET"] = "AFTER_SET";
55
+ CacheableHooks2["BEFORE_SET_MANY"] = "BEFORE_SET_MANY";
56
+ CacheableHooks2["AFTER_SET_MANY"] = "AFTER_SET_MANY";
57
+ CacheableHooks2["BEFORE_GET"] = "BEFORE_GET";
58
+ CacheableHooks2["AFTER_GET"] = "AFTER_GET";
59
+ CacheableHooks2["BEFORE_GET_MANY"] = "BEFORE_GET_MANY";
60
+ CacheableHooks2["AFTER_GET_MANY"] = "AFTER_GET_MANY";
61
+ CacheableHooks2["BEFORE_SECONDARY_SETS_PRIMARY"] = "BEFORE_SECONDARY_SETS_PRIMARY";
62
+ return CacheableHooks2;
63
+ })(CacheableHooks || {});
64
+ var CacheableEvents = /* @__PURE__ */ ((CacheableEvents2) => {
65
+ CacheableEvents2["ERROR"] = "error";
66
+ CacheableEvents2["CACHE_HIT"] = "cache:hit";
67
+ CacheableEvents2["CACHE_MISS"] = "cache:miss";
68
+ return CacheableEvents2;
69
+ })(CacheableEvents || {});
70
+
71
+ // src/sync.ts
72
+ var import_hookified = require("hookified");
73
+ var import_qified = require("qified");
74
+ var CacheableSyncEvents = /* @__PURE__ */ ((CacheableSyncEvents2) => {
75
+ CacheableSyncEvents2["ERROR"] = "error";
76
+ CacheableSyncEvents2["SET"] = "cache:set";
77
+ CacheableSyncEvents2["DELETE"] = "cache:delete";
78
+ return CacheableSyncEvents2;
79
+ })(CacheableSyncEvents || {});
80
+ var CacheableSync = class extends import_hookified.Hookified {
81
+ _qified = new import_qified.Qified();
82
+ /**
83
+ * Creates an instance of CacheableSync
84
+ * @param options - Configuration options for CacheableSync
85
+ */
86
+ constructor(options) {
87
+ super(options);
88
+ this._qified = this.createQified(options.qified);
89
+ }
90
+ /**
91
+ * Gets the Qified instance used for synchronization
92
+ * @returns The Qified instance
93
+ */
94
+ get qified() {
95
+ return this._qified;
96
+ }
97
+ /**
98
+ * Sets the Qified instance used for synchronization
99
+ * @param value - Either an existing Qified instance or MessageProvider(s)
100
+ */
101
+ set qified(value) {
102
+ this._qified = this.createQified(value);
103
+ }
104
+ /**
105
+ * Publishes a cache event to all the cache instances
106
+ * @param data - The cache item data containing cacheId, key, value, and optional ttl
107
+ */
108
+ async publish(event, data) {
109
+ await this._qified.publish(event, {
110
+ id: crypto.randomUUID(),
111
+ data
112
+ });
113
+ }
114
+ /**
115
+ * Subscribes to sync events and updates the provided storage
116
+ * @param storage - The Keyv storage instance to update
117
+ * @param cacheId - The cache ID to identify this instance
118
+ */
119
+ subscribe(storage, cacheId) {
120
+ this._qified.subscribe("cache:set" /* SET */, {
121
+ handler: async (message) => {
122
+ const data = message.data;
123
+ if (data.cacheId !== cacheId) {
124
+ await storage.set(data.key, data.value, data.ttl);
125
+ }
126
+ }
127
+ });
128
+ this._qified.subscribe("cache:delete" /* DELETE */, {
129
+ handler: async (message) => {
130
+ const data = message.data;
131
+ if (data.cacheId !== cacheId) {
132
+ await storage.delete(data.key);
133
+ }
134
+ }
135
+ });
136
+ }
137
+ /**
138
+ * Creates or returns a Qified instance from the provided value
139
+ * @param value - Either an existing Qified instance or MessageProvider(s)
140
+ * @returns A Qified instance configured with the provided message provider(s)
141
+ */
142
+ createQified(value) {
143
+ if (value instanceof import_qified.Qified) {
144
+ return value;
145
+ }
146
+ const providers = Array.isArray(value) ? value : [value];
147
+ return new import_qified.Qified({ messageProviders: providers });
148
+ }
149
+ };
150
+
151
+ // src/index.ts
152
+ var import_memoize2 = require("@cacheable/memoize");
153
+ var import_memory2 = require("@cacheable/memory");
154
+ var import_utils2 = require("@cacheable/utils");
155
+ var import_keyv2 = require("keyv");
156
+ var Cacheable = class extends import_hookified2.Hookified {
157
+ _primary = (0, import_memory.createKeyv)();
158
+ _secondary;
159
+ _nonBlocking = false;
160
+ _ttl;
161
+ _stats = new import_utils.Stats({ enabled: false });
162
+ _namespace;
163
+ _cacheId = Math.random().toString(36).slice(2);
164
+ _sync;
165
+ /**
166
+ * Creates a new cacheable instance
167
+ * @param {CacheableOptions} [options] The options for the cacheable instance
168
+ */
169
+ constructor(options) {
170
+ super();
171
+ if (options?.primary) {
172
+ this.setPrimary(options.primary);
173
+ }
174
+ if (options?.secondary) {
175
+ this.setSecondary(options.secondary);
176
+ }
177
+ if (options?.nonBlocking) {
178
+ this._nonBlocking = options.nonBlocking;
179
+ }
180
+ if (options?.stats) {
181
+ this._stats.enabled = options.stats;
182
+ }
183
+ if (options?.ttl) {
184
+ this.setTtl(options.ttl);
185
+ }
186
+ if (options?.cacheId) {
187
+ this._cacheId = options.cacheId;
188
+ }
189
+ if (options?.namespace) {
190
+ this._namespace = options.namespace;
191
+ this._primary.namespace = this.getNameSpace();
192
+ if (this._secondary) {
193
+ this._secondary.namespace = this.getNameSpace();
194
+ }
195
+ }
196
+ if (options?.sync) {
197
+ this._sync = options.sync instanceof CacheableSync ? options.sync : new CacheableSync(options.sync);
198
+ this._sync.subscribe(this._primary, this._cacheId);
199
+ }
200
+ }
201
+ /**
202
+ * The namespace for the cacheable instance
203
+ * @returns {string | (() => string) | undefined} The namespace for the cacheable instance
204
+ */
205
+ get namespace() {
206
+ return this._namespace;
207
+ }
208
+ /**
209
+ * Sets the namespace for the cacheable instance
210
+ * @param {string | (() => string) | undefined} namespace The namespace for the cacheable instance
211
+ * @returns {void}
212
+ */
213
+ set namespace(namespace) {
214
+ this._namespace = namespace;
215
+ this._primary.namespace = this.getNameSpace();
216
+ if (this._secondary) {
217
+ this._secondary.namespace = this.getNameSpace();
218
+ }
219
+ }
220
+ /**
221
+ * The statistics for the cacheable instance
222
+ * @returns {CacheableStats} The statistics for the cacheable instance
223
+ */
224
+ get stats() {
225
+ return this._stats;
226
+ }
227
+ /**
228
+ * The primary store for the cacheable instance
229
+ * @returns {Keyv} The primary store for the cacheable instance
230
+ */
231
+ get primary() {
232
+ return this._primary;
233
+ }
234
+ /**
235
+ * Sets the primary store for the cacheable instance
236
+ * @param {Keyv} primary The primary store for the cacheable instance
237
+ */
238
+ set primary(primary) {
239
+ this._primary = primary;
240
+ }
241
+ /**
242
+ * The secondary store for the cacheable instance
243
+ * @returns {Keyv | undefined} The secondary store for the cacheable instance
244
+ */
245
+ get secondary() {
246
+ return this._secondary;
247
+ }
248
+ /**
249
+ * Sets the secondary store for the cacheable instance. If it is set to undefined then the secondary store is disabled.
250
+ * @param {Keyv | undefined} secondary The secondary store for the cacheable instance
251
+ * @returns {void}
252
+ */
253
+ set secondary(secondary) {
254
+ this._secondary = secondary;
255
+ }
256
+ /**
257
+ * Gets whether the secondary store is non-blocking mode. It is set to false by default.
258
+ * If it is set to true then the secondary store will not block the primary store.
259
+ *
260
+ * [Learn more about non-blocking mode](https://cacheable.org/docs/cacheable/#non-blocking-operations).
261
+ *
262
+ * @returns {boolean} Whether the cacheable instance is non-blocking
263
+ */
264
+ get nonBlocking() {
265
+ return this._nonBlocking;
266
+ }
267
+ /**
268
+ * Sets whether the secondary store is non-blocking mode. It is set to false by default.
269
+ * If it is set to true then the secondary store will not block the primary store.
270
+ *
271
+ * [Learn more about non-blocking mode](https://cacheable.org/docs/cacheable/#non-blocking-operations).
272
+ *
273
+ * @param {boolean} nonBlocking Whether the cacheable instance is non-blocking
274
+ * @returns {void}
275
+ */
276
+ set nonBlocking(nonBlocking) {
277
+ this._nonBlocking = nonBlocking;
278
+ }
279
+ /**
280
+ * The time-to-live for the cacheable instance and will be used as the default value.
281
+ * can be a number in milliseconds or a human-readable format such as `1s` for 1 second or `1h` for 1 hour
282
+ * or undefined if there is no time-to-live.
283
+ *
284
+ * [Learn more about time-to-live](https://cacheable.org/docs/cacheable/#shorthand-for-time-to-live-ttl).
285
+ *
286
+ * @returns {number | string | undefined} The time-to-live for the cacheable instance in milliseconds, human-readable format or undefined
287
+ * @example
288
+ * ```typescript
289
+ * const cacheable = new Cacheable({ ttl: '1h' });
290
+ * console.log(cacheable.ttl); // 1h
291
+ * ```
292
+ */
293
+ get ttl() {
294
+ return this._ttl;
295
+ }
296
+ /**
297
+ * Sets the time-to-live for the cacheable instance and will be used as the default value.
298
+ * If you set a number it is miliseconds, if you set a string it is a human-readable
299
+ * format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that
300
+ * there is no time-to-live.
301
+ *
302
+ * [Learn more about time-to-live](https://cacheable.org/docs/cacheable/#shorthand-for-time-to-live-ttl).
303
+ *
304
+ * @param {number | string | undefined} ttl The time-to-live for the cacheable instance
305
+ * @example
306
+ * ```typescript
307
+ * const cacheable = new Cacheable();
308
+ * cacheable.ttl = '1h'; // Set the time-to-live to 1 hour
309
+ * ```
310
+ * or setting the time-to-live in milliseconds
311
+ * ```typescript
312
+ * const cacheable = new Cacheable();
313
+ * cacheable.ttl = 3600000; // Set the time-to-live to 1 hour
314
+ * ```
315
+ */
316
+ set ttl(ttl) {
317
+ this.setTtl(ttl);
318
+ }
319
+ /**
320
+ * The cacheId for the cacheable instance. This is primarily used for the wrap function to not have conflicts.
321
+ * If it is not set then it will be a random string that is generated
322
+ * @returns {string} The cacheId for the cacheable instance
323
+ */
324
+ get cacheId() {
325
+ return this._cacheId;
326
+ }
327
+ /**
328
+ * Sets the cacheId for the cacheable instance. This is primarily used for the wrap function to not have conflicts.
329
+ * If it is not set then it will be a random string that is generated
330
+ * @param {string} cacheId The cacheId for the cacheable instance
331
+ */
332
+ set cacheId(cacheId) {
333
+ this._cacheId = cacheId;
334
+ }
335
+ /**
336
+ * Gets the sync instance for the cacheable instance
337
+ * @returns {CacheableSync | undefined} The sync instance for the cacheable instance
338
+ */
339
+ get sync() {
340
+ return this._sync;
341
+ }
342
+ /**
343
+ * Sets the sync instance for the cacheable instance
344
+ * @param {CacheableSync | undefined} sync The sync instance for the cacheable instance
345
+ */
346
+ set sync(sync) {
347
+ this._sync = sync;
348
+ if (this._sync) {
349
+ this._sync.subscribe(this._primary, this._cacheId);
350
+ }
351
+ }
352
+ /**
353
+ * Sets the primary store for the cacheable instance
354
+ * @param {Keyv | KeyvStoreAdapter} primary The primary store for the cacheable instance
355
+ * @returns {void}
356
+ */
357
+ setPrimary(primary) {
358
+ if ((0, import_utils.isKeyvInstance)(primary)) {
359
+ this._primary = primary;
360
+ } else {
361
+ this._primary = new import_keyv.Keyv(primary);
362
+ }
363
+ this._primary.on("error", (error) => {
364
+ this.emit("error" /* ERROR */, error);
365
+ });
366
+ }
367
+ /**
368
+ * Sets the secondary store for the cacheable instance. If it is set to undefined then the secondary store is disabled.
369
+ * @param {Keyv | KeyvStoreAdapter} secondary The secondary store for the cacheable instance
370
+ * @returns {void}
371
+ */
372
+ setSecondary(secondary) {
373
+ if ((0, import_utils.isKeyvInstance)(secondary)) {
374
+ this._secondary = secondary;
375
+ } else {
376
+ this._secondary = new import_keyv.Keyv(secondary);
377
+ }
378
+ this._secondary.on("error", (error) => {
379
+ this.emit("error" /* ERROR */, error);
380
+ });
381
+ }
382
+ getNameSpace() {
383
+ if (typeof this._namespace === "function") {
384
+ return this._namespace();
385
+ }
386
+ return this._namespace;
387
+ }
388
+ /**
389
+ * Retrieves an entry from the cache.
390
+ *
391
+ * Checks the primary store first; if not found and a secondary store is configured,
392
+ * it will fetch from the secondary, repopulate the primary, and return the result.
393
+ *
394
+ * @typeParam T - The expected type of the stored value.
395
+ * @param {string} key - The cache key to retrieve.
396
+ * @param {GetOptions} - options such as to bypass `nonBlocking` for this call
397
+ * @returns {Promise<T | undefined>}
398
+ * A promise that resolves to the cached value if found, or `undefined`.
399
+ */
400
+ async get(key, options) {
401
+ const result = await this.getRaw(key, options);
402
+ return result?.value;
403
+ }
404
+ /**
405
+ * Retrieves the raw entry from the cache including metadata like expiration.
406
+ *
407
+ * Checks the primary store first; if not found and a secondary store is configured,
408
+ * it will fetch from the secondary, repopulate the primary, and return the result.
409
+ *
410
+ * @typeParam T - The expected type of the stored value.
411
+ * @param {string} key - The cache key to retrieve.
412
+ * @param {GetOptions} - options such as to bypass `nonBlocking` for this call
413
+ * @returns {Promise<StoredDataRaw<T>>}
414
+ * A promise that resolves to the full raw data object if found, or undefined.
415
+ */
416
+ async getRaw(key, options) {
417
+ let result;
418
+ try {
419
+ await this.hook("BEFORE_GET" /* BEFORE_GET */, key);
420
+ result = await this._primary.getRaw(key);
421
+ let ttl;
422
+ if (result) {
423
+ this.emit("cache:hit" /* CACHE_HIT */, {
424
+ key,
425
+ value: result.value,
426
+ store: "primary"
427
+ });
428
+ } else {
429
+ this.emit("cache:miss" /* CACHE_MISS */, { key, store: "primary" });
430
+ }
431
+ const nonBlocking = options?.nonBlocking ?? this._nonBlocking;
432
+ if (!result && this._secondary) {
433
+ let secondaryProcessResult;
434
+ if (nonBlocking) {
435
+ secondaryProcessResult = await this.processSecondaryForGetRawNonBlocking(
436
+ this._primary,
437
+ this._secondary,
438
+ key
439
+ );
440
+ } else {
441
+ secondaryProcessResult = await this.processSecondaryForGetRaw(
442
+ this._primary,
443
+ this._secondary,
444
+ key
445
+ );
446
+ }
447
+ if (secondaryProcessResult) {
448
+ result = secondaryProcessResult.result;
449
+ ttl = secondaryProcessResult.ttl;
450
+ }
451
+ }
452
+ await this.hook("AFTER_GET" /* AFTER_GET */, { key, result, ttl });
453
+ } catch (error) {
454
+ this.emit("error" /* ERROR */, error);
455
+ }
456
+ if (this.stats.enabled) {
457
+ if (result) {
458
+ this._stats.incrementHits();
459
+ } else {
460
+ this._stats.incrementMisses();
461
+ }
462
+ this.stats.incrementGets();
463
+ }
464
+ return result;
465
+ }
466
+ /**
467
+ * Retrieves multiple raw entries from the cache including metadata like expiration.
468
+ *
469
+ * Checks the primary store for each key; if a key is missing and a secondary store is configured,
470
+ * it will fetch from the secondary store, repopulate the primary store, and return the results.
471
+ *
472
+ * @typeParam T - The expected type of the stored values.
473
+ * @param {string[]} keys - The cache keys to retrieve.
474
+ * @param {GetOptions} - options such as to bypass `nonBlocking` on this call
475
+ * @returns {Promise<Array<StoredDataRaw<T>>>}
476
+ * A promise that resolves to an array of raw data objects.
477
+ */
478
+ async getManyRaw(keys, options) {
479
+ let result = [];
480
+ try {
481
+ await this.hook("BEFORE_GET_MANY" /* BEFORE_GET_MANY */, keys);
482
+ result = await this._primary.getManyRaw(keys);
483
+ for (const [i, key] of keys.entries()) {
484
+ if (result[i]) {
485
+ this.emit("cache:hit" /* CACHE_HIT */, {
486
+ key,
487
+ value: result[i].value,
488
+ store: "primary"
489
+ });
490
+ } else {
491
+ this.emit("cache:miss" /* CACHE_MISS */, { key, store: "primary" });
492
+ }
493
+ }
494
+ const nonBlocking = options?.nonBlocking ?? this._nonBlocking;
495
+ if (this._secondary) {
496
+ if (nonBlocking) {
497
+ await this.processSecondaryForGetManyRawNonBlocking(
498
+ this._primary,
499
+ this._secondary,
500
+ keys,
501
+ result
502
+ );
503
+ } else {
504
+ await this.processSecondaryForGetManyRaw(
505
+ this._primary,
506
+ this._secondary,
507
+ keys,
508
+ result
509
+ );
510
+ }
511
+ }
512
+ await this.hook("AFTER_GET_MANY" /* AFTER_GET_MANY */, { keys, result });
513
+ } catch (error) {
514
+ this.emit("error" /* ERROR */, error);
515
+ }
516
+ if (this.stats.enabled) {
517
+ for (const item of result) {
518
+ if (item) {
519
+ this._stats.incrementHits();
520
+ } else {
521
+ this._stats.incrementMisses();
522
+ }
523
+ }
524
+ this.stats.incrementGets();
525
+ }
526
+ return result;
527
+ }
528
+ /**
529
+ * Retrieves multiple entries from the cache.
530
+ * Checks the primary store for each key; if a key is missing and a secondary store is configured,
531
+ * it will fetch from the secondary store, repopulate the primary store, and return the results.
532
+ *
533
+ * @typeParam T - The expected type of the stored values.
534
+ * @param {string[]} keys - The cache keys to retrieve.
535
+ * @param {GetOptions} - options such as to bypass `nonBlocking` on this call
536
+ * @returns {Promise<Array<T | undefined>>}
537
+ * A promise that resolves to an array of cached values or `undefined` for misses.
538
+ */
539
+ async getMany(keys, options) {
540
+ const result = await this.getManyRaw(keys, options);
541
+ return result.map((item) => item?.value);
542
+ }
543
+ /**
544
+ * Sets the value of the key. If the secondary store is set then it will also set the value in the secondary store.
545
+ * @param {string} key the key to set the value of
546
+ * @param {T} value The value to set
547
+ * @param {number | string} [ttl] set a number it is miliseconds, set a string it is a human-readable
548
+ * format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live.
549
+ * @returns {boolean} Whether the value was set
550
+ */
551
+ async set(key, value, ttl) {
552
+ let result = false;
553
+ const finalTtl = (0, import_utils.shorthandToMilliseconds)(ttl ?? this._ttl);
554
+ try {
555
+ const item = { key, value, ttl: finalTtl };
556
+ await this.hook("BEFORE_SET" /* BEFORE_SET */, item);
557
+ const promises = [];
558
+ promises.push(this._primary.set(item.key, item.value, item.ttl));
559
+ if (this._secondary) {
560
+ promises.push(this._secondary.set(item.key, item.value, item.ttl));
561
+ }
562
+ if (this._nonBlocking) {
563
+ result = await Promise.race(promises);
564
+ for (const promise of promises) {
565
+ promise.catch((error) => {
566
+ this.emit("error" /* ERROR */, error);
567
+ });
568
+ }
569
+ } else {
570
+ const results = await Promise.all(promises);
571
+ result = results[0];
572
+ }
573
+ await this.hook("AFTER_SET" /* AFTER_SET */, item);
574
+ if (this._sync && result) {
575
+ await this._sync.publish("cache:set" /* SET */, {
576
+ cacheId: this._cacheId,
577
+ key: item.key,
578
+ value: item.value,
579
+ ttl: item.ttl
580
+ });
581
+ }
582
+ } catch (error) {
583
+ this.emit("error" /* ERROR */, error);
584
+ }
585
+ if (this.stats.enabled) {
586
+ this.stats.incrementKSize(key);
587
+ this.stats.incrementCount();
588
+ this.stats.incrementVSize(value);
589
+ this.stats.incrementSets();
590
+ }
591
+ return result;
592
+ }
593
+ /**
594
+ * Sets the values of the keys. If the secondary store is set then it will also set the values in the secondary store.
595
+ * @param {CacheableItem[]} items The items to set
596
+ * @returns {boolean} Whether the values were set
597
+ */
598
+ async setMany(items) {
599
+ let result = false;
600
+ try {
601
+ await this.hook("BEFORE_SET_MANY" /* BEFORE_SET_MANY */, items);
602
+ result = await this.setManyKeyv(this._primary, items);
603
+ if (this._secondary) {
604
+ if (this._nonBlocking) {
605
+ this.setManyKeyv(this._secondary, items).catch((error) => {
606
+ this.emit("error" /* ERROR */, error);
607
+ });
608
+ } else {
609
+ await this.setManyKeyv(this._secondary, items);
610
+ }
611
+ }
612
+ await this.hook("AFTER_SET_MANY" /* AFTER_SET_MANY */, items);
613
+ if (this._sync && result) {
614
+ for (const item of items) {
615
+ await this._sync.publish("cache:set" /* SET */, {
616
+ cacheId: this._cacheId,
617
+ key: item.key,
618
+ value: item.value,
619
+ ttl: (0, import_utils.shorthandToMilliseconds)(item.ttl)
620
+ });
621
+ }
622
+ }
623
+ } catch (error) {
624
+ this.emit("error" /* ERROR */, error);
625
+ }
626
+ if (this.stats.enabled) {
627
+ for (const item of items) {
628
+ this.stats.incrementKSize(item.key);
629
+ this.stats.incrementCount();
630
+ this.stats.incrementVSize(item.value);
631
+ }
632
+ }
633
+ return result;
634
+ }
635
+ /**
636
+ * Takes the value of the key and deletes the key. If the key does not exist then it will return undefined.
637
+ * @param {string} key The key to take the value of
638
+ * @returns {Promise<T | undefined>} The value of the key or undefined if the key does not exist
639
+ */
640
+ async take(key) {
641
+ const result = await this.get(key);
642
+ await this.delete(key);
643
+ return result;
644
+ }
645
+ /**
646
+ * Takes the values of the keys and deletes the keys. If the key does not exist then it will return undefined.
647
+ * @param {string[]} keys The keys to take the values of
648
+ * @returns {Promise<Array<T | undefined>>} The values of the keys or undefined if the key does not exist
649
+ */
650
+ async takeMany(keys) {
651
+ const result = await this.getMany(keys);
652
+ await this.deleteMany(keys);
653
+ return result;
654
+ }
655
+ /**
656
+ * Checks if the key exists in the primary store. If it does not exist then it will check the secondary store.
657
+ * @param {string} key The key to check
658
+ * @returns {Promise<boolean>} Whether the key exists
659
+ */
660
+ async has(key) {
661
+ const promises = [];
662
+ promises.push(this._primary.has(key));
663
+ if (this._secondary) {
664
+ promises.push(this._secondary.has(key));
665
+ }
666
+ const resultAll = await Promise.all(promises);
667
+ for (const result of resultAll) {
668
+ if (result) {
669
+ return true;
670
+ }
671
+ }
672
+ return false;
673
+ }
674
+ /**
675
+ * Checks if the keys exist in the primary store. If it does not exist then it will check the secondary store.
676
+ * @param {string[]} keys The keys to check
677
+ * @returns {Promise<boolean[]>} Whether the keys exist
678
+ */
679
+ async hasMany(keys) {
680
+ const result = await this.hasManyKeyv(this._primary, keys);
681
+ const missingKeys = [];
682
+ for (const [i, key] of keys.entries()) {
683
+ if (!result[i] && this._secondary) {
684
+ missingKeys.push(key);
685
+ }
686
+ }
687
+ if (missingKeys.length > 0 && this._secondary) {
688
+ const secondary = await this.hasManyKeyv(this._secondary, keys);
689
+ for (const [i, _key] of keys.entries()) {
690
+ if (!result[i] && secondary[i]) {
691
+ result[i] = secondary[i];
692
+ }
693
+ }
694
+ }
695
+ return result;
696
+ }
697
+ /**
698
+ * Deletes the key from the primary store. If the secondary store is set then it will also delete the key from the secondary store.
699
+ * @param {string} key The key to delete
700
+ * @returns {Promise<boolean>} Whether the key was deleted
701
+ */
702
+ async delete(key) {
703
+ let result = false;
704
+ const promises = [];
705
+ if (this.stats.enabled) {
706
+ const statResult = await this._primary.get(key);
707
+ if (statResult) {
708
+ this.stats.decreaseKSize(key);
709
+ this.stats.decreaseVSize(statResult);
710
+ this.stats.decreaseCount();
711
+ this.stats.incrementDeletes();
712
+ }
713
+ }
714
+ promises.push(this._primary.delete(key));
715
+ if (this._secondary) {
716
+ promises.push(this._secondary.delete(key));
717
+ }
718
+ if (this.nonBlocking) {
719
+ result = await Promise.race(promises);
720
+ for (const promise of promises) {
721
+ promise.catch((error) => {
722
+ this.emit("error" /* ERROR */, error);
723
+ });
724
+ }
725
+ } else {
726
+ const resultAll = await Promise.all(promises);
727
+ result = resultAll[0];
728
+ }
729
+ if (this._sync && result) {
730
+ await this._sync.publish("cache:delete" /* DELETE */, {
731
+ cacheId: this._cacheId,
732
+ key
733
+ });
734
+ }
735
+ return result;
736
+ }
737
+ /**
738
+ * Deletes the keys from the primary store. If the secondary store is set then it will also delete the keys from the secondary store.
739
+ * @param {string[]} keys The keys to delete
740
+ * @returns {Promise<boolean>} Whether the keys were deleted
741
+ */
742
+ async deleteMany(keys) {
743
+ if (this.stats.enabled) {
744
+ const statResult = await this._primary.get(keys);
745
+ for (const key of keys) {
746
+ this.stats.decreaseKSize(key);
747
+ this.stats.decreaseVSize(statResult);
748
+ this.stats.decreaseCount();
749
+ this.stats.incrementDeletes();
750
+ }
751
+ }
752
+ const result = await this._primary.deleteMany(keys);
753
+ if (this._secondary) {
754
+ if (this._nonBlocking) {
755
+ this._secondary.deleteMany(keys).catch((error) => {
756
+ this.emit("error" /* ERROR */, error);
757
+ });
758
+ } else {
759
+ await this._secondary.deleteMany(keys);
760
+ }
761
+ }
762
+ if (this._sync && result) {
763
+ for (const key of keys) {
764
+ await this._sync.publish("cache:delete" /* DELETE */, {
765
+ cacheId: this._cacheId,
766
+ key
767
+ });
768
+ }
769
+ }
770
+ return result;
771
+ }
772
+ /**
773
+ * Clears the primary store. If the secondary store is set then it will also clear the secondary store.
774
+ * @returns {Promise<void>}
775
+ */
776
+ async clear() {
777
+ const promises = [];
778
+ promises.push(this._primary.clear());
779
+ if (this._secondary) {
780
+ promises.push(this._secondary.clear());
781
+ }
782
+ await (this._nonBlocking ? Promise.race(promises) : Promise.all(promises));
783
+ if (this.stats.enabled) {
784
+ this._stats.resetStoreValues();
785
+ this._stats.incrementClears();
786
+ }
787
+ }
788
+ /**
789
+ * Disconnects the primary store. If the secondary store is set then it will also disconnect the secondary store.
790
+ * @returns {Promise<void>}
791
+ */
792
+ async disconnect() {
793
+ const promises = [];
794
+ promises.push(this._primary.disconnect());
795
+ if (this._secondary) {
796
+ promises.push(this._secondary.disconnect());
797
+ }
798
+ await (this._nonBlocking ? Promise.race(promises) : Promise.all(promises));
799
+ }
800
+ /**
801
+ * Wraps a function with caching
802
+ *
803
+ * [Learn more about wrapping functions](https://cacheable.org/docs/cacheable/#wrap--memoization-for-sync-and-async-functions).
804
+ * @param {Function} function_ The function to wrap
805
+ * @param {WrapOptions} [options] The options for the wrap function
806
+ * @returns {Function} The wrapped function
807
+ */
808
+ // biome-ignore lint/suspicious/noExplicitAny: type format
809
+ wrap(function_, options) {
810
+ const cacheAdapter = {
811
+ get: async (key) => this.get(key),
812
+ has: async (key) => this.has(key),
813
+ // biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
814
+ set: async (key, value, ttl) => {
815
+ await this.set(key, value, ttl);
816
+ },
817
+ /* c8 ignore start */
818
+ // biome-ignore lint/suspicious/noExplicitAny: CacheInstance interface
819
+ on: (event, listener) => {
820
+ this.on(event, listener);
821
+ },
822
+ /* c8 ignore stop */
823
+ // biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
824
+ emit: (event, ...args) => this.emit(event, ...args)
825
+ };
826
+ const wrapOptions = {
827
+ ttl: options?.ttl ?? this._ttl,
828
+ keyPrefix: options?.keyPrefix,
829
+ createKey: options?.createKey,
830
+ cacheErrors: options?.cacheErrors,
831
+ cache: cacheAdapter,
832
+ cacheId: this._cacheId,
833
+ serialize: options?.serialize
834
+ };
835
+ return (0, import_memoize.wrap)(function_, wrapOptions);
836
+ }
837
+ /**
838
+ * Retrieves the value associated with the given key from the cache. If the key is not found,
839
+ * invokes the provided function to calculate the value, stores it in the cache, and then returns it.
840
+ *
841
+ * @param {GetOrSetKey} key - The key to retrieve or set in the cache. This can also be a function that returns a string key.
842
+ * If a function is provided, it will be called with the cache options to generate the key.
843
+ * @param {() => Promise<T>} function_ - The asynchronous function that computes the value to be cached if the key does not exist.
844
+ * @param {GetOrSetFunctionOptions} [options] - Optional settings for caching, such as the time to live (TTL) or whether to cache errors.
845
+ * @return {Promise<T | undefined>} - A promise that resolves to the cached or newly computed value, or undefined if an error occurs and caching is not configured for errors.
846
+ */
847
+ async getOrSet(key, function_, options) {
848
+ const cacheAdapter = {
849
+ get: async (key2) => this.get(key2),
850
+ has: async (key2) => this.has(key2),
851
+ // biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
852
+ set: async (key2, value, ttl) => {
853
+ await this.set(key2, value, ttl);
854
+ },
855
+ /* c8 ignore start */
856
+ // biome-ignore lint/suspicious/noExplicitAny: CacheInstance interface
857
+ on: (event, listener) => {
858
+ this.on(event, listener);
859
+ },
860
+ /* c8 ignore stop */
861
+ // biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
862
+ emit: (event, ...args) => this.emit(event, ...args)
863
+ };
864
+ const getOrSetOptions = {
865
+ cache: cacheAdapter,
866
+ cacheId: this._cacheId,
867
+ ttl: options?.ttl ?? this._ttl,
868
+ cacheErrors: options?.cacheErrors,
869
+ throwErrors: options?.throwErrors
870
+ };
871
+ return (0, import_memoize.getOrSet)(key, function_, getOrSetOptions);
872
+ }
873
+ /**
874
+ * Will hash an object using the specified algorithm. The default algorithm is 'sha256'.
875
+ * @param {any} object the object to hash
876
+ * @param {string} algorithm the hash algorithm to use. The default is 'sha256'
877
+ * @returns {string} the hash of the object
878
+ */
879
+ hash(object, algorithm = import_utils.HashAlgorithm.SHA256) {
880
+ const validAlgorithm = Object.values(import_utils.HashAlgorithm).includes(algorithm) ? algorithm : import_utils.HashAlgorithm.SHA256;
881
+ return (0, import_utils.hash)(object, { algorithm: validAlgorithm });
882
+ }
883
+ async setManyKeyv(keyv, items) {
884
+ const entries = [];
885
+ for (const item of items) {
886
+ const finalTtl = (0, import_utils.shorthandToMilliseconds)(item.ttl ?? this._ttl);
887
+ entries.push({ key: item.key, value: item.value, ttl: finalTtl });
888
+ }
889
+ await keyv.setMany(entries);
890
+ return true;
891
+ }
892
+ async hasManyKeyv(keyv, keys) {
893
+ const promises = [];
894
+ for (const key of keys) {
895
+ promises.push(keyv.has(key));
896
+ }
897
+ return Promise.all(promises);
898
+ }
899
+ /**
900
+ * Processes a single key from secondary store for getRaw operation
901
+ * @param primary - the primary store to use
902
+ * @param secondary - the secondary store to use
903
+ * @param key - The key to retrieve from secondary store
904
+ * @returns Promise containing the result and TTL information
905
+ */
906
+ async processSecondaryForGetRaw(primary, secondary, key) {
907
+ const secondaryResult = await secondary.getRaw(key);
908
+ if (secondaryResult?.value) {
909
+ this.emit("cache:hit" /* CACHE_HIT */, {
910
+ key,
911
+ value: secondaryResult.value,
912
+ store: "secondary"
913
+ });
914
+ const cascadeTtl = (0, import_utils.getCascadingTtl)(this._ttl, this._primary.ttl);
915
+ const expires = secondaryResult.expires ?? void 0;
916
+ const ttl = (0, import_utils.calculateTtlFromExpiration)(cascadeTtl, expires);
917
+ const setItem = { key, value: secondaryResult.value, ttl };
918
+ await this.hook("BEFORE_SECONDARY_SETS_PRIMARY" /* BEFORE_SECONDARY_SETS_PRIMARY */, setItem);
919
+ await primary.set(setItem.key, setItem.value, setItem.ttl);
920
+ return { result: secondaryResult, ttl };
921
+ } else {
922
+ this.emit("cache:miss" /* CACHE_MISS */, { key, store: "secondary" });
923
+ return void 0;
924
+ }
925
+ }
926
+ /**
927
+ * Processes a single key from secondary store for getRaw operation in non-blocking mode
928
+ * Non-blocking mode means we don't wait for secondary operations that update primary store
929
+ * @param primary - the primary store to use
930
+ * @param secondary - the secondary store to use
931
+ * @param key - The key to retrieve from secondary store
932
+ * @returns Promise containing the result and TTL information
933
+ */
934
+ async processSecondaryForGetRawNonBlocking(primary, secondary, key) {
935
+ const secondaryResult = await secondary.getRaw(key);
936
+ if (secondaryResult?.value) {
937
+ this.emit("cache:hit" /* CACHE_HIT */, {
938
+ key,
939
+ value: secondaryResult.value,
940
+ store: "secondary"
941
+ });
942
+ const cascadeTtl = (0, import_utils.getCascadingTtl)(this._ttl, this._primary.ttl);
943
+ const expires = secondaryResult.expires ?? void 0;
944
+ const ttl = (0, import_utils.calculateTtlFromExpiration)(cascadeTtl, expires);
945
+ const setItem = { key, value: secondaryResult.value, ttl };
946
+ this.hook("BEFORE_SECONDARY_SETS_PRIMARY" /* BEFORE_SECONDARY_SETS_PRIMARY */, setItem).then(async () => {
947
+ await primary.set(setItem.key, setItem.value, setItem.ttl);
948
+ }).catch((error) => {
949
+ this.emit("error" /* ERROR */, error);
950
+ });
951
+ return { result: secondaryResult, ttl };
952
+ } else {
953
+ this.emit("cache:miss" /* CACHE_MISS */, { key, store: "secondary" });
954
+ return void 0;
955
+ }
956
+ }
957
+ /**
958
+ * Processes missing keys from secondary store for getManyRaw operation
959
+ * @param primary - the primary store to use
960
+ * @param secondary - the secondary store to use
961
+ * @param keys - The original array of keys requested
962
+ * @param result - The result array from primary store (will be modified)
963
+ * @returns Promise<void>
964
+ */
965
+ async processSecondaryForGetManyRaw(primary, secondary, keys, result) {
966
+ const missingKeys = [];
967
+ for (const [i, key] of keys.entries()) {
968
+ if (!result[i]) {
969
+ missingKeys.push(key);
970
+ }
971
+ }
972
+ const secondaryResults = await secondary.getManyRaw(missingKeys);
973
+ let secondaryIndex = 0;
974
+ for await (const [i, key] of keys.entries()) {
975
+ if (!result[i]) {
976
+ const secondaryResult = secondaryResults[secondaryIndex];
977
+ if (secondaryResult && secondaryResult.value !== void 0) {
978
+ result[i] = secondaryResult;
979
+ this.emit("cache:hit" /* CACHE_HIT */, {
980
+ key,
981
+ value: secondaryResult.value,
982
+ store: "secondary"
983
+ });
984
+ const cascadeTtl = (0, import_utils.getCascadingTtl)(this._ttl, this._primary.ttl);
985
+ let { expires } = secondaryResult;
986
+ if (expires === null) {
987
+ expires = void 0;
988
+ }
989
+ const ttl = (0, import_utils.calculateTtlFromExpiration)(cascadeTtl, expires);
990
+ const setItem = { key, value: secondaryResult.value, ttl };
991
+ await this.hook(
992
+ "BEFORE_SECONDARY_SETS_PRIMARY" /* BEFORE_SECONDARY_SETS_PRIMARY */,
993
+ setItem
994
+ );
995
+ await primary.set(setItem.key, setItem.value, setItem.ttl);
996
+ } else {
997
+ this.emit("cache:miss" /* CACHE_MISS */, {
998
+ key,
999
+ store: "secondary"
1000
+ });
1001
+ }
1002
+ secondaryIndex++;
1003
+ }
1004
+ }
1005
+ }
1006
+ /**
1007
+ * Processes missing keys from secondary store for getManyRaw operation in non-blocking mode
1008
+ * Non-blocking mode means we don't wait for secondary operations that update primary store
1009
+ * @param secondary - the secondary store to use
1010
+ * @param keys - The original array of keys requested
1011
+ * @param result - The result array from primary store (will be modified)
1012
+ * @returns Promise<void>
1013
+ */
1014
+ async processSecondaryForGetManyRawNonBlocking(primary, secondary, keys, result) {
1015
+ const missingKeys = [];
1016
+ for (const [i, key] of keys.entries()) {
1017
+ if (!result[i]) {
1018
+ missingKeys.push(key);
1019
+ }
1020
+ }
1021
+ const secondaryResults = await secondary.getManyRaw(missingKeys);
1022
+ let secondaryIndex = 0;
1023
+ for await (const [i, key] of keys.entries()) {
1024
+ if (!result[i]) {
1025
+ const secondaryResult = secondaryResults[secondaryIndex];
1026
+ if (secondaryResult && secondaryResult.value !== void 0) {
1027
+ result[i] = secondaryResult;
1028
+ this.emit("cache:hit" /* CACHE_HIT */, {
1029
+ key,
1030
+ value: secondaryResult.value,
1031
+ store: "secondary"
1032
+ });
1033
+ const cascadeTtl = (0, import_utils.getCascadingTtl)(this._ttl, this._primary.ttl);
1034
+ let { expires } = secondaryResult;
1035
+ if (expires === null) {
1036
+ expires = void 0;
1037
+ }
1038
+ const ttl = (0, import_utils.calculateTtlFromExpiration)(cascadeTtl, expires);
1039
+ const setItem = { key, value: secondaryResult.value, ttl };
1040
+ this.hook("BEFORE_SECONDARY_SETS_PRIMARY" /* BEFORE_SECONDARY_SETS_PRIMARY */, setItem).then(async () => {
1041
+ await primary.set(setItem.key, setItem.value, setItem.ttl);
1042
+ }).catch((error) => {
1043
+ this.emit("error" /* ERROR */, error);
1044
+ });
1045
+ } else {
1046
+ this.emit("cache:miss" /* CACHE_MISS */, {
1047
+ key,
1048
+ store: "secondary"
1049
+ });
1050
+ }
1051
+ secondaryIndex++;
1052
+ }
1053
+ }
1054
+ }
1055
+ setTtl(ttl) {
1056
+ if (typeof ttl === "string" || ttl === void 0) {
1057
+ this._ttl = ttl;
1058
+ } else if (ttl > 0) {
1059
+ this._ttl = ttl;
1060
+ } else {
1061
+ this._ttl = void 0;
1062
+ }
1063
+ }
1064
+ };
1065
+ // Annotate the CommonJS export names for ESM import in node:
1066
+ 0 && (module.exports = {
1067
+ Cacheable,
1068
+ CacheableEvents,
1069
+ CacheableHooks,
1070
+ CacheableMemory,
1071
+ CacheableStats,
1072
+ CacheableSync,
1073
+ CacheableSyncEvents,
1074
+ HashAlgorithm,
1075
+ Keyv,
1076
+ KeyvCacheableMemory,
1077
+ KeyvHooks,
1078
+ calculateTtlFromExpiration,
1079
+ createKeyv,
1080
+ getCascadingTtl,
1081
+ getOrSet,
1082
+ hash,
1083
+ shorthandToMilliseconds,
1084
+ shorthandToTime,
1085
+ wrap,
1086
+ wrapSync
1087
+ });