@warlock.js/cache 4.0.39 → 4.0.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/index.js CHANGED
@@ -1,3 +1,1681 @@
1
- import {log}from'@warlock.js/logger';import {rtrim,unset,get,set}from'@mongez/reinforcements';import {removeDirectoryAsync,ensureDirectoryAsync,putJsonFileAsync,getJsonFileAsync}from'@mongez/fs';import p from'path';var d=class extends Error{constructor(e){super(e),this.name="CacheError";}},x=class extends d{constructor(e){super(e),this.name="CacheConnectionError";}},u=class extends d{constructor(e){super(e),this.name="CacheConfigurationError";}},v=class extends d{constructor(e="No cache driver initialized. Call cache.init() or cache.use() first."){super(e),this.name="CacheDriverNotInitializedError";}};var C=class{currentDriver;loadedDrivers={};configurations={drivers:{},options:{}};globalEventListeners=new Map;name="cacheManager";get client(){return this.currentDriver?.client}setCacheConfigurations(e){this.configurations.default=e.default,this.configurations.drivers=e.drivers,this.configurations.options=e.options;}async use(e){if(typeof e=="string"){let t=await this.load(e);if(!t)throw new u(`Cache driver ${e} is not found, please declare it in the cache drivers in the configurations list.`);e=t;}return this.attachGlobalListeners(e),this.currentDriver=e,this}ensureDriverInitialized(){if(!this.currentDriver)throw new v}async get(e){return this.ensureDriverInitialized(),this.currentDriver.get(e)}async set(e,t,i){return this.ensureDriverInitialized(),this.currentDriver.set(e,t,i)}async remove(e){return this.ensureDriverInitialized(),this.currentDriver.remove(e)}async removeNamespace(e){return this.ensureDriverInitialized(),this.currentDriver.removeNamespace(e)}async flush(){return this.ensureDriverInitialized(),this.currentDriver.flush()}async connect(){return this.ensureDriverInitialized(),this.currentDriver.connect()}parseKey(e){return this.ensureDriverInitialized(),this.currentDriver.parseKey(e)}get options(){return this.ensureDriverInitialized(),this.currentDriver.options}setOptions(e){return this.ensureDriverInitialized(),this.currentDriver.setOptions(e||{})}async driver(e){return this.loadedDrivers[e]||await this.load(e)}async init(){let e=this.configurations.default;if(!e)return;let t=await this.driver(e);await this.use(t);}async load(e){if(this.loadedDrivers[e])return this.loadedDrivers[e];let t=this.configurations.drivers[e];if(!t)throw new u(`Cache driver ${e} is not found, please declare it in the cache drivers in the configurations list.`);let i=new t;return i.setOptions(this.configurations.options[e]||{}),await i.connect(),this.attachGlobalListeners(i),this.loadedDrivers[e]=i,i}registerDriver(e,t){this.configurations.drivers[e]=t;}async disconnect(){this.currentDriver&&await this.currentDriver.disconnect();}async has(e){return this.ensureDriverInitialized(),this.currentDriver.has(e)}async remember(e,t,i){return this.ensureDriverInitialized(),this.currentDriver.remember(e,t,i)}async pull(e){return this.ensureDriverInitialized(),this.currentDriver.pull(e)}async forever(e,t){return this.ensureDriverInitialized(),this.currentDriver.forever(e,t)}async increment(e,t){return this.ensureDriverInitialized(),this.currentDriver.increment(e,t)}async decrement(e,t){return this.ensureDriverInitialized(),this.currentDriver.decrement(e,t)}async many(e){return this.ensureDriverInitialized(),this.currentDriver.many(e)}async setMany(e,t){return this.ensureDriverInitialized(),this.currentDriver.setMany(e,t)}on(e,t){this.globalEventListeners.has(e)||this.globalEventListeners.set(e,new Set),this.globalEventListeners.get(e).add(t),this.currentDriver&&this.currentDriver.on(e,t);for(let i of Object.values(this.loadedDrivers))i.on(e,t);return this}off(e,t){let i=this.globalEventListeners.get(e);i&&i.delete(t),this.currentDriver&&this.currentDriver.off(e,t);for(let r of Object.values(this.loadedDrivers))r.off(e,t);return this}once(e,t){let i=async r=>{await t(r),this.off(e,i);};return this.on(e,i)}attachGlobalListeners(e){for(let[t,i]of this.globalEventListeners)for(let r of i)e.on(t,r);}async setNX(e,t,i){if(this.ensureDriverInitialized(),!this.currentDriver.setNX)throw new Error(`setNX is not supported by the current cache driver: ${this.currentDriver.name}`);return this.currentDriver.setNX(e,t,i)}tags(e){return this.ensureDriverInitialized(),this.currentDriver.tags(e)}},J=new C;var f=class{cacheTags;driver;constructor(e,t){this.cacheTags=e,this.driver=t;}tagKey(e){return `cache:tags:${e}`}async storeTaggedKey(e){for(let t of this.cacheTags){let i=this.tagKey(t),r=await this.driver.get(i)||[];r.includes(e)||(r.push(e),await this.driver.set(i,r,1/0));}}async getTaggedKeys(){let e=new Set;for(let t of this.cacheTags){let i=this.tagKey(t),r=await this.driver.get(i)||[];for(let s of r)e.add(s);}return e}async set(e,t,i){let r=this.driver.parseKey(e);return await this.driver.set(e,t,i),await this.storeTaggedKey(r),t}async get(e){return this.driver.get(e)}async remove(e){let t=this.driver.parseKey(e);await this.driver.remove(e);for(let i of this.cacheTags){let r=this.tagKey(i),c=(await this.driver.get(r)||[]).filter(h=>h!==t);await this.driver.set(r,c,1/0);}}async invalidate(){let e=await this.getTaggedKeys();for(let t of e)await this.driver.remove(t);for(let t of this.cacheTags)await this.driver.remove(this.tagKey(t));}async flush(){return this.invalidate()}async has(e){return this.driver.has(e)}async remember(e,t,i){let r=await this.get(e);if(r!==null)return r;let s=await i();return await this.set(e,s,t),s}async pull(e){let t=await this.get(e);return t!==null&&await this.remove(e),t}async forever(e,t){return this.set(e,t,1/0)}async increment(e,t=1){let i=await this.get(e)||0;if(typeof i!="number")throw new Error(`Cannot increment non-numeric value for key: ${this.driver.parseKey(e)}`);let r=i+t;return await this.set(e,r),r}async decrement(e,t=1){return this.increment(e,-t)}};function O(n,e={}){typeof n=="object"&&(n=JSON.stringify(n)),n=n.replace(/[{}"[\]]/g,"").replaceAll(/[:,]/g,".");let t=typeof e.globalPrefix=="function"?e.globalPrefix():e.globalPrefix;return rtrim(String(t?rtrim(t,".")+"."+n:n),".")}var L=(a=>(a[a.HALF_HOUR=1800]="HALF_HOUR",a[a.ONE_HOUR=3600]="ONE_HOUR",a[a.HALF_DAY=43200]="HALF_DAY",a[a.ONE_DAY=86400]="ONE_DAY",a[a.ONE_WEEK=604800]="ONE_WEEK",a[a.HALF_MONTH=1296e3]="HALF_MONTH",a[a.ONE_MONTH=2592e3]="ONE_MONTH",a[a.TWO_MONTHS=5184e3]="TWO_MONTHS",a[a.SIX_MONTHS=15768e3]="SIX_MONTHS",a[a.ONE_YEAR=31536e3]="ONE_YEAR",a))(L||{});var D={clearing:"Clearing namespace",cleared:"Namespace cleared",fetching:"Fetching key",fetched:"Key fetched",caching:"Caching key",cached:"Key cached",flushing:"Flushing cache",flushed:"Cache flushed",removing:"Removing key",removed:"Key removed",expired:"Key expired",notFound:"Key not found",connecting:"Connecting to the cache engine.",connected:"Connected to the cache engine.",disconnecting:"Disconnecting from the cache engine.",disconnected:"Disconnected from the cache engine.",error:"Error occurred"},o=class{clientDriver;get client(){return this.clientDriver||this}set client(e){this.clientDriver=e;}options;eventListeners=new Map;parseKey(e){return O(e,this.options)}setOptions(e){return this.options=e||{},this}on(e,t){return this.eventListeners.has(e)||this.eventListeners.set(e,new Set),this.eventListeners.get(e).add(t),this}off(e,t){let i=this.eventListeners.get(e);return i&&i.delete(t),this}once(e,t){let i=async r=>{await t(r),this.off(e,i);};return this.on(e,i)}async emit(e,t={}){let i=this.eventListeners.get(e);if(!i||i.size===0)return;let r={driver:this.name,...t},s=[];for(let c of i)try{let h=c(r);h instanceof Promise&&s.push(h);}catch(h){this.logError(`Error in event handler for '${e}'`,h);}s.length>0&&await Promise.allSettled(s);}async has(e){return await this.get(e)!==null}locks=new Map;async remember(e,t,i){let r=this.parseKey(e),s=await this.get(e);if(s!==null)return s;let c=this.locks.get(r);if(c)return c;let h=i().then(async m=>(await this.set(e,m,t),this.locks.delete(r),m)).catch(m=>{throw this.locks.delete(r),m});return this.locks.set(r,h),h}async pull(e){let t=await this.get(e);return t!==null&&await this.remove(e),t}async forever(e,t){return this.set(e,t,1/0)}async increment(e,t=1){let i=await this.get(e)||0;if(typeof i!="number")throw new Error(`Cannot increment non-numeric value for key: ${this.parseKey(e)}`);let r=i+t;return await this.set(e,r),r}async decrement(e,t=1){return this.increment(e,-t)}async many(e){return Promise.all(e.map(t=>this.get(t)))}async setMany(e,t){await Promise.all(Object.entries(e).map(([i,r])=>this.set(i,r,t)));}log(e,t){if(t&&(t=t.replaceAll("/",".")),e=="notFound"||e=="expired")return log.warn("cache:"+this.name,e,(t?t+" ":"")+D[e]);if(e.endsWith("ed"))return log.success("cache:"+this.name,e,(t?t+" ":"")+D[e]);log.info("cache:"+this.name,e,(t?t+" ":"")+D[e]);}logError(e,t){log.error("cache:"+this.name,"error",e),t&&console.log(t);}get ttl(){return this.options.ttl!==void 0?this.options.ttl:1/0}getExpiresAt(e=this.ttl){if(e)return new Date().getTime()+e*1e3}prepareDataForStorage(e,t){let i={data:e};return t&&(i.ttl=t,i.expiresAt=this.getExpiresAt(t)),i}async parseCachedData(e,t){if(this.log("fetched",e),t.expiresAt&&t.expiresAt<Date.now())return this.remove(e),null;let i=t.data;if(i==null)return i;let r=typeof i;if(r==="string"||r==="number"||r==="boolean")return i;try{return structuredClone(i)}catch(s){throw console.log(i),this.logError(`Failed to clone cached value for ${e}, typeof value: ${typeof i}`,s),s}}async connect(){this.log("connecting"),this.log("connected"),await this.emit("connected");}async disconnect(){this.log("disconnected"),await this.emit("disconnected");}tags(e){return new f(e,this)}};var E=class extends o{name="file";setOptions(e){if(!e.directory)throw new u("File driver requires 'directory' option to be configured.");return super.setOptions(e)}get directory(){let e=this.options.directory;if(typeof e=="function")return e();throw new u("Cache directory is not defined, please define it in the file driver options")}get fileName(){let e=this.options.fileName;return typeof e=="function"?e():"cache.json"}async removeNamespace(e){this.log("clearing",e);try{await removeDirectoryAsync(p.resolve(this.directory,e)),this.log("cleared",e);}catch{}return this}async set(e,t,i){e=this.parseKey(e),this.log("caching",e);let r=this.prepareDataForStorage(t,i),s=p.resolve(this.directory,e);return await ensureDirectoryAsync(s),await putJsonFileAsync(p.resolve(s,this.fileName),r),this.log("cached",e),await this.emit("set",{key:e,value:t,ttl:i}),this}async get(e){let t=this.parseKey(e);this.log("fetching",t);let i=p.resolve(this.directory,t);try{let r=await getJsonFileAsync(p.resolve(i,this.fileName)),s=await this.parseCachedData(t,r);return s===null?await this.emit("miss",{key:t}):await this.emit("hit",{key:t,value:s}),s}catch{return this.log("notFound",t),await this.emit("miss",{key:t}),this.remove(e),null}}async remove(e){let t=this.parseKey(e);this.log("removing",t);let i=p.resolve(this.directory,t);try{await removeDirectoryAsync(i),this.log("removed",t),await this.emit("removed",{key:t});}catch{}}async flush(){this.log("flushing"),this.options.globalPrefix?await this.removeNamespace(""):await removeDirectoryAsync(this.directory),this.log("flushed"),await this.emit("flushed");}async connect(){this.log("connecting"),await ensureDirectoryAsync(this.directory),this.log("connected"),await this.emit("connected");}};var y=class{constructor(e,t,i){this.key=e;this.value=t;i&&i!==1/0&&(this.expiresAt=Date.now()+i*1e3);}next=null;prev=null;expiresAt;get isExpired(){return this.expiresAt!==void 0&&this.expiresAt<Date.now()}},T=class extends o{name="lru";cache=new Map;head=new y("",null);tail=new y("",null);cleanupInterval;constructor(){super(),this.init(),this.startCleanup();}init(){this.head.next=this.tail,this.tail.prev=this.head;}startCleanup(){this.cleanupInterval&&clearInterval(this.cleanupInterval),this.cleanupInterval=setInterval(async()=>{let e=Date.now(),t=[];for(let[i,r]of this.cache)r.expiresAt&&r.expiresAt<=e&&t.push(i);for(let i of t){let r=this.cache.get(i);r&&(this.removeNode(r),this.cache.delete(i),this.log("expired",i),await this.emit("expired",{key:i}));}},1e3),this.cleanupInterval.unref();}async removeNamespace(e){throw new Error("Namespace is not supported in LRU cache driver.")}async set(e,t,i){e=this.parseKey(e),this.log("caching",e),i===void 0&&(i=this.ttl);let r=this.cache.get(e);if(r)r.value=t,i&&i!==1/0?r.expiresAt=Date.now()+i*1e3:r.expiresAt=void 0,this.moveHead(r);else {let s=new y(e,t,i);this.cache.set(e,s),this.addNode(s),this.cache.size>this.capacity&&this.removeTail();}return this.log("cached",e),await this.emit("set",{key:e,value:t,ttl:i}),this}moveHead(e){this.removeNode(e),this.addNode(e);}removeNode(e){e.prev.next=e.next,e.next.prev=e.prev;}addNode(e){e.next=this.head.next,e.prev=this.head,this.head.next.prev=e,this.head.next=e;}removeTail(){let e=this.tail.prev;this.removeNode(e),this.cache.delete(e.key);}async get(e){let t=this.parseKey(e);this.log("fetching",t);let i=this.cache.get(t);if(!i)return this.log("notFound",t),await this.emit("miss",{key:t}),null;if(i.isExpired)return this.removeNode(i),this.cache.delete(t),this.log("expired",t),await this.emit("expired",{key:t}),await this.emit("miss",{key:t}),null;this.moveHead(i),this.log("fetched",t);let r=i.value;if(r==null)return r;let s=typeof r;if(s==="string"||s==="number"||s==="boolean")return await this.emit("hit",{key:t,value:r}),r;try{let c=structuredClone(r);return await this.emit("hit",{key:t,value:c}),c}catch(c){throw this.logError(`Failed to clone cached value for ${t}`,c),c}}async remove(e){let t=this.parseKey(e);this.log("removing",t);let i=this.cache.get(t);i&&(this.removeNode(i),this.cache.delete(t)),this.log("removed",t),await this.emit("removed",{key:t});}async flush(){this.log("flushing"),this.cache.clear(),this.init(),this.log("flushed"),await this.emit("flushed");}get capacity(){return this.options.capacity||1e3}async disconnect(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=void 0),await super.disconnect();}};var b=class extends o{name="memory";data={};temporaryData={};cleanupInterval;accessOrder=[];constructor(){super(),this.startCleanup();}startCleanup(){this.cleanupInterval&&clearInterval(this.cleanupInterval),this.cleanupInterval=setInterval(async()=>{let e=Date.now();for(let t in this.temporaryData)this.temporaryData[t].expiresAt<=e&&(await this.remove(this.temporaryData[t].key),delete this.temporaryData[t],this.log("expired",t),await this.emit("expired",{key:t}));},1e3),this.cleanupInterval.unref();}async removeNamespace(e){return this.log("clearing",e),e=this.parseKey(e),unset(this.data,[e]),this.log("cleared",e),this}async set(e,t,i){let r=this.parseKey(e);this.log("caching",r),i===void 0&&(i=this.ttl);let s=this.prepareDataForStorage(t,i);i&&this.setTemporaryData(e,r,i);let h=!get(this.data,r);return set(this.data,r,s),this.trackAccess(r),h&&this.options.maxSize&&await this.enforceMaxSize(),this.log("cached",r),await this.emit("set",{key:r,value:t,ttl:i}),this}async get(e){let t=this.parseKey(e);this.log("fetching",t);let i=get(this.data,t);if(!i)return this.log("notFound",t),await this.emit("miss",{key:t}),null;let r=await this.parseCachedData(t,i);return r===null?await this.emit("miss",{key:t}):(this.trackAccess(t),await this.emit("hit",{key:t,value:r})),r}async remove(e){let t=this.parseKey(e);this.log("removing",t),unset(this.data,[t]),delete this.temporaryData[t],this.removeFromAccessOrder(t),this.log("removed",t),await this.emit("removed",{key:t});}async flush(){this.log("flushing"),this.options.globalPrefix?this.removeNamespace(""):(this.data={},this.accessOrder=[]),this.log("flushed"),await this.emit("flushed");}setTemporaryData(e,t,i){this.temporaryData[t]={key:JSON.stringify(e),expiresAt:Date.now()+i*1e3};}trackAccess(e){if(!this.options.maxSize)return;let t=this.accessOrder.indexOf(e);t>-1&&this.accessOrder.splice(t,1),this.accessOrder.push(e);}removeFromAccessOrder(e){let t=this.accessOrder.indexOf(e);t>-1&&this.accessOrder.splice(t,1);}async enforceMaxSize(){if(!this.options.maxSize)return;let e=this.getCacheSize();for(;e>this.options.maxSize&&this.accessOrder.length>0;){let t=this.accessOrder.shift();t&&(this.log("removing",t),unset(this.data,[t]),delete this.temporaryData[t],this.log("removed",t));}}getCacheSize(){return Object.keys(this.data).length}async disconnect(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=void 0),await super.disconnect();}};var M=class extends b{name="memoryExtended";async get(e){let t=this.parseKey(e);this.log("fetching",t);let i=get(this.data,t);if(!i)return this.log("notFound",t),null;let r=i.ttl||this.options.ttl;return r&&(this.setTemporaryData(e,t,r),i.expiresAt=this.getExpiresAt(r)),this.parseCachedData(t,i)}};var z=class extends o{options={};name="null";data={};get client(){return this}constructor(e={}){super(),this.setOptions(e);}setOptions(e){return this.options=e,this}parseKey(e){return ""}async removeNamespace(e){return log.info("cache","clearing namespace",e),log.success("cache","namespace cleared",e),this}async set(e,t){return log.info("cache","setting key",e),log.success("cache","key set",e),this}async get(e){return log.info("cache","fetching",e),log.success("cache","fetched",e),null}async remove(e){log.info("cache","removing",e),log.success("cache","removed",e);}async flush(){log.info("cache","flushing","all"),log.success("cache","flushed","all");}async connect(){log.success("cache","connected","Connected to null cache driver");}};var S=class extends o{name="redis";setOptions(e){if(!e.url&&!e.host)throw new u("Redis driver requires either 'url' or 'host' option to be configured.");return super.setOptions(e)}async removeNamespace(e){e=this.parseKey(e),this.log("clearing",e);let t=await this.client?.keys(`${e}*`);if(!t||t.length===0){this.log("notFound",e);return}return await this.client?.del(t),this.log("cleared",e),t}async set(e,t,i){return e=this.parseKey(e),this.log("caching",e),i===void 0&&(i=this.ttl),i&&i!==1/0?await this.client?.set(e,JSON.stringify(t),{EX:i}):await this.client?.set(e,JSON.stringify(t)),this.log("cached",e),await this.emit("set",{key:e,value:t,ttl:i}),t}async get(e){e=this.parseKey(e),this.log("fetching",e);let t=await this.client?.get(e);if(!t)return this.log("notFound",e),await this.emit("miss",{key:e}),null;this.log("fetched",e);let i=JSON.parse(t);if(i==null)return await this.emit("hit",{key:e,value:i}),i;let r=typeof i;if(r==="string"||r==="number"||r==="boolean")return await this.emit("hit",{key:e,value:i}),i;try{let s=structuredClone(i);return await this.emit("hit",{key:e,value:s}),s}catch(s){throw this.logError(`Failed to clone cached value for ${e}`,s),s}}async remove(e){e=this.parseKey(e),this.log("removing",e),await this.client?.del(e),this.log("removed",e),await this.emit("removed",{key:e});}async flush(){this.log("flushing"),this.options.globalPrefix?await this.removeNamespace(""):await this.client?.flushAll(),this.log("flushed"),await this.emit("flushed");}async connect(){if(this.clientDriver)return;let e=this.options;if(e&&!e.url&&e.host){let r=e.password||e.username?`${e.username}:${e.password}@`:"";if(!e.url){let s=e.host||"localhost",c=e.port||6379;e.url=`redis://${r}${s}:${c}`;}}let t={...e,...this.options.clientOptions||{}};this.log("connecting");let{createClient:i}=await import('redis');this.client=i(t),this.client.on("error",r=>{this.log("error",r.message);});try{await this.client.connect(),this.log("connected"),await this.emit("connected");}catch(r){log.error("cache","redis",r),await this.emit("error",{error:r});}}async disconnect(){this.client&&(this.log("disconnecting"),await this.client.quit(),this.log("disconnected"),await this.emit("disconnected"));}async increment(e,t=1){let i=this.parseKey(e);this.log("caching",i);let r=await this.client?.incrBy(i,t);return this.log("cached",i),await this.emit("set",{key:i,value:r,ttl:void 0}),r||0}async decrement(e,t=1){let i=this.parseKey(e);this.log("caching",i);let r=await this.client?.decrBy(i,t);return this.log("cached",i),await this.emit("set",{key:i,value:r,ttl:void 0}),r||0}async setNX(e,t,i){let r=this.parseKey(e);this.log("caching",r),i===void 0&&(i=this.ttl);let s;i&&i!==1/0?s=await this.client?.set(r,JSON.stringify(t),{NX:true,EX:i}):s=await this.client?.set(r,JSON.stringify(t),{NX:true});let c=s==="OK";return c?(this.log("cached",r),await this.emit("set",{key:r,value:t,ttl:i})):this.log("notFound",r),c}};
2
- export{o as BaseCacheDriver,L as CACHE_FOR,u as CacheConfigurationError,x as CacheConnectionError,v as CacheDriverNotInitializedError,d as CacheError,C as CacheManager,E as FileCacheDriver,T as LRUMemoryCacheDriver,b as MemoryCacheDriver,M as MemoryExtendedCacheDriver,z as NullCacheDriver,S as RedisCacheDriver,f as TaggedCache,J as cache,O as parseCacheKey};//# sourceMappingURL=index.js.map
1
+ import { log } from '@warlock.js/logger';
2
+ import { rtrim, unset, get, set } from '@mongez/reinforcements';
3
+ import { removeDirectoryAsync, ensureDirectoryAsync, putJsonFileAsync, getJsonFileAsync } from '@mongez/fs';
4
+ import path from 'path';
5
+
6
+ // ../../warlock.js/cache/src/types.ts
7
+ var CacheError = class extends Error {
8
+ constructor(message) {
9
+ super(message);
10
+ this.name = "CacheError";
11
+ }
12
+ };
13
+ var CacheConnectionError = class extends CacheError {
14
+ constructor(message) {
15
+ super(message);
16
+ this.name = "CacheConnectionError";
17
+ }
18
+ };
19
+ var CacheConfigurationError = class extends CacheError {
20
+ constructor(message) {
21
+ super(message);
22
+ this.name = "CacheConfigurationError";
23
+ }
24
+ };
25
+ var CacheDriverNotInitializedError = class extends CacheError {
26
+ constructor(message = "No cache driver initialized. Call cache.init() or cache.use() first.") {
27
+ super(message);
28
+ this.name = "CacheDriverNotInitializedError";
29
+ }
30
+ };
31
+
32
+ // ../../warlock.js/cache/src/cache-manager.ts
33
+ var CacheManager = class {
34
+ /**
35
+ * Cache Driver
36
+ */
37
+ currentDriver;
38
+ /**
39
+ * Loaded drivers
40
+ */
41
+ loadedDrivers = {};
42
+ /**
43
+ * Configurations list
44
+ */
45
+ configurations = {
46
+ drivers: {},
47
+ options: {}
48
+ };
49
+ /**
50
+ * Global event listeners
51
+ */
52
+ globalEventListeners = /* @__PURE__ */ new Map();
53
+ /**
54
+ * {@inheritdoc}
55
+ */
56
+ name = "cacheManager";
57
+ /**
58
+ * {@inheritdoc}
59
+ */
60
+ get client() {
61
+ return this.currentDriver?.client;
62
+ }
63
+ /**
64
+ * Set the cache configurations
65
+ */
66
+ setCacheConfigurations(configurations) {
67
+ this.configurations.default = configurations.default;
68
+ this.configurations.drivers = configurations.drivers;
69
+ this.configurations.options = configurations.options;
70
+ }
71
+ /**
72
+ * Use the given driver
73
+ */
74
+ async use(driver) {
75
+ if (typeof driver === "string") {
76
+ const driverInstance = await this.load(driver);
77
+ if (!driverInstance) {
78
+ throw new CacheConfigurationError(
79
+ `Cache driver ${driver} is not found, please declare it in the cache drivers in the configurations list.`
80
+ );
81
+ }
82
+ driver = driverInstance;
83
+ }
84
+ this.attachGlobalListeners(driver);
85
+ this.currentDriver = driver;
86
+ return this;
87
+ }
88
+ /**
89
+ * Ensure driver is initialized before operations
90
+ */
91
+ ensureDriverInitialized() {
92
+ if (!this.currentDriver) {
93
+ throw new CacheDriverNotInitializedError();
94
+ }
95
+ }
96
+ /**
97
+ * {@inheritdoc}
98
+ */
99
+ async get(key) {
100
+ this.ensureDriverInitialized();
101
+ return this.currentDriver.get(key);
102
+ }
103
+ /**
104
+ * Set a value in the cache
105
+ *
106
+ * @param key The cache key, could be an object or string
107
+ * @param value The value to be stored in the cache
108
+ * @param ttl The time to live in seconds
109
+ */
110
+ async set(key, value, ttl) {
111
+ this.ensureDriverInitialized();
112
+ return this.currentDriver.set(key, value, ttl);
113
+ }
114
+ /**
115
+ * {@inheritdoc}
116
+ */
117
+ async remove(key) {
118
+ this.ensureDriverInitialized();
119
+ return this.currentDriver.remove(key);
120
+ }
121
+ /**
122
+ * {@inheritdoc}
123
+ */
124
+ async removeNamespace(namespace) {
125
+ this.ensureDriverInitialized();
126
+ return this.currentDriver.removeNamespace(namespace);
127
+ }
128
+ /**
129
+ * {@inheritdoc}
130
+ */
131
+ async flush() {
132
+ this.ensureDriverInitialized();
133
+ return this.currentDriver.flush();
134
+ }
135
+ /**
136
+ * {@inheritdoc}
137
+ */
138
+ async connect() {
139
+ this.ensureDriverInitialized();
140
+ return this.currentDriver.connect();
141
+ }
142
+ /**
143
+ * {@inheritdoc}
144
+ */
145
+ parseKey(key) {
146
+ this.ensureDriverInitialized();
147
+ return this.currentDriver.parseKey(key);
148
+ }
149
+ /**
150
+ * {@inheritdoc}
151
+ */
152
+ get options() {
153
+ this.ensureDriverInitialized();
154
+ return this.currentDriver.options;
155
+ }
156
+ /**
157
+ * {@inheritdoc}
158
+ */
159
+ setOptions(options) {
160
+ this.ensureDriverInitialized();
161
+ return this.currentDriver.setOptions(options || {});
162
+ }
163
+ /**
164
+ * Get an instance of the cache driver
165
+ */
166
+ async driver(driverName) {
167
+ return this.loadedDrivers[driverName] || await this.load(driverName);
168
+ }
169
+ /**
170
+ * Initialize the cache manager and pick the default driver
171
+ */
172
+ async init() {
173
+ const defaultCacheDriverName = this.configurations.default;
174
+ if (!defaultCacheDriverName) {
175
+ return;
176
+ }
177
+ const driver = await this.driver(defaultCacheDriverName);
178
+ await this.use(driver);
179
+ }
180
+ /**
181
+ * Load the given cache driver name
182
+ */
183
+ async load(driver) {
184
+ if (this.loadedDrivers[driver]) return this.loadedDrivers[driver];
185
+ const Driver = this.configurations.drivers[driver];
186
+ if (!Driver) {
187
+ throw new CacheConfigurationError(
188
+ `Cache driver ${driver} is not found, please declare it in the cache drivers in the configurations list.`
189
+ );
190
+ }
191
+ const driverInstance = new Driver();
192
+ driverInstance.setOptions(
193
+ this.configurations.options[driver] || {}
194
+ );
195
+ await driverInstance.connect();
196
+ this.attachGlobalListeners(driverInstance);
197
+ this.loadedDrivers[driver] = driverInstance;
198
+ return driverInstance;
199
+ }
200
+ /**
201
+ * Register and bind a driver
202
+ */
203
+ registerDriver(driverName, driverClass) {
204
+ this.configurations.drivers[driverName] = driverClass;
205
+ }
206
+ /**
207
+ * Disconnect the cache manager
208
+ */
209
+ async disconnect() {
210
+ if (this.currentDriver) {
211
+ await this.currentDriver.disconnect();
212
+ }
213
+ }
214
+ /**
215
+ * {@inheritdoc}
216
+ */
217
+ async has(key) {
218
+ this.ensureDriverInitialized();
219
+ return this.currentDriver.has(key);
220
+ }
221
+ /**
222
+ * {@inheritdoc}
223
+ */
224
+ async remember(key, ttl, callback) {
225
+ this.ensureDriverInitialized();
226
+ return this.currentDriver.remember(key, ttl, callback);
227
+ }
228
+ /**
229
+ * {@inheritdoc}
230
+ */
231
+ async pull(key) {
232
+ this.ensureDriverInitialized();
233
+ return this.currentDriver.pull(key);
234
+ }
235
+ /**
236
+ * {@inheritdoc}
237
+ */
238
+ async forever(key, value) {
239
+ this.ensureDriverInitialized();
240
+ return this.currentDriver.forever(key, value);
241
+ }
242
+ /**
243
+ * {@inheritdoc}
244
+ */
245
+ async increment(key, value) {
246
+ this.ensureDriverInitialized();
247
+ return this.currentDriver.increment(key, value);
248
+ }
249
+ /**
250
+ * {@inheritdoc}
251
+ */
252
+ async decrement(key, value) {
253
+ this.ensureDriverInitialized();
254
+ return this.currentDriver.decrement(key, value);
255
+ }
256
+ /**
257
+ * {@inheritdoc}
258
+ */
259
+ async many(keys) {
260
+ this.ensureDriverInitialized();
261
+ return this.currentDriver.many(keys);
262
+ }
263
+ /**
264
+ * {@inheritdoc}
265
+ */
266
+ async setMany(items, ttl) {
267
+ this.ensureDriverInitialized();
268
+ return this.currentDriver.setMany(items, ttl);
269
+ }
270
+ /**
271
+ * Register a global event listener (applies to all drivers)
272
+ */
273
+ on(event, handler) {
274
+ if (!this.globalEventListeners.has(event)) {
275
+ this.globalEventListeners.set(event, /* @__PURE__ */ new Set());
276
+ }
277
+ this.globalEventListeners.get(event).add(handler);
278
+ if (this.currentDriver) {
279
+ this.currentDriver.on(event, handler);
280
+ }
281
+ for (const driver of Object.values(this.loadedDrivers)) {
282
+ driver.on(event, handler);
283
+ }
284
+ return this;
285
+ }
286
+ /**
287
+ * Remove a global event listener
288
+ */
289
+ off(event, handler) {
290
+ const handlers = this.globalEventListeners.get(event);
291
+ if (handlers) {
292
+ handlers.delete(handler);
293
+ }
294
+ if (this.currentDriver) {
295
+ this.currentDriver.off(event, handler);
296
+ }
297
+ for (const driver of Object.values(this.loadedDrivers)) {
298
+ driver.off(event, handler);
299
+ }
300
+ return this;
301
+ }
302
+ /**
303
+ * Register a one-time global event listener
304
+ */
305
+ once(event, handler) {
306
+ const onceHandler = async (data) => {
307
+ await handler(data);
308
+ this.off(event, onceHandler);
309
+ };
310
+ return this.on(event, onceHandler);
311
+ }
312
+ /**
313
+ * Attach global listeners to a driver
314
+ */
315
+ attachGlobalListeners(driver) {
316
+ for (const [event, handlers] of this.globalEventListeners) {
317
+ for (const handler of handlers) {
318
+ driver.on(event, handler);
319
+ }
320
+ }
321
+ }
322
+ /**
323
+ * Set if not exists (atomic operation)
324
+ * Returns true if key was set, false if key already existed
325
+ * Note: Only supported by drivers that implement setNX (e.g., Redis)
326
+ */
327
+ async setNX(key, value, ttl) {
328
+ this.ensureDriverInitialized();
329
+ if (!this.currentDriver.setNX) {
330
+ throw new Error(
331
+ `setNX is not supported by the current cache driver: ${this.currentDriver.name}`
332
+ );
333
+ }
334
+ return this.currentDriver.setNX(key, value, ttl);
335
+ }
336
+ /**
337
+ * Create a tagged cache instance for the given tags
338
+ */
339
+ tags(tags) {
340
+ this.ensureDriverInitialized();
341
+ return this.currentDriver.tags(tags);
342
+ }
343
+ };
344
+ var cache = new CacheManager();
345
+
346
+ // ../../warlock.js/cache/src/tagged-cache.ts
347
+ var TaggedCache = class {
348
+ /**
349
+ * The tags associated with this tagged cache instance
350
+ */
351
+ cacheTags;
352
+ /**
353
+ * The underlying cache driver
354
+ */
355
+ driver;
356
+ /**
357
+ * Constructor
358
+ */
359
+ constructor(tags, driver) {
360
+ this.cacheTags = tags;
361
+ this.driver = driver;
362
+ }
363
+ /**
364
+ * Get the tag key prefix for storing tag-key relationships
365
+ */
366
+ tagKey(tag) {
367
+ return `cache:tags:${tag}`;
368
+ }
369
+ /**
370
+ * Store tag-key relationship
371
+ */
372
+ async storeTaggedKey(key) {
373
+ for (const tag of this.cacheTags) {
374
+ const tagKey = this.tagKey(tag);
375
+ const keys = await this.driver.get(tagKey) || [];
376
+ if (!keys.includes(key)) {
377
+ keys.push(key);
378
+ await this.driver.set(tagKey, keys, Infinity);
379
+ }
380
+ }
381
+ }
382
+ /**
383
+ * Get all keys associated with tags
384
+ */
385
+ async getTaggedKeys() {
386
+ const allKeys = /* @__PURE__ */ new Set();
387
+ for (const tag of this.cacheTags) {
388
+ const tagKey = this.tagKey(tag);
389
+ const keys = await this.driver.get(tagKey) || [];
390
+ for (const key of keys) {
391
+ allKeys.add(key);
392
+ }
393
+ }
394
+ return allKeys;
395
+ }
396
+ /**
397
+ * {@inheritdoc}
398
+ */
399
+ async set(key, value, ttl) {
400
+ const parsedKey = this.driver.parseKey(key);
401
+ await this.driver.set(key, value, ttl);
402
+ await this.storeTaggedKey(parsedKey);
403
+ return value;
404
+ }
405
+ /**
406
+ * {@inheritdoc}
407
+ */
408
+ async get(key) {
409
+ return this.driver.get(key);
410
+ }
411
+ /**
412
+ * {@inheritdoc}
413
+ */
414
+ async remove(key) {
415
+ const parsedKey = this.driver.parseKey(key);
416
+ await this.driver.remove(key);
417
+ for (const tag of this.cacheTags) {
418
+ const tagKey = this.tagKey(tag);
419
+ const keys = await this.driver.get(tagKey) || [];
420
+ const updatedKeys = keys.filter((k) => k !== parsedKey);
421
+ await this.driver.set(tagKey, updatedKeys, Infinity);
422
+ }
423
+ }
424
+ /**
425
+ * Invalidate (clear) all keys associated with the current tags
426
+ */
427
+ async invalidate() {
428
+ const keysToRemove = await this.getTaggedKeys();
429
+ for (const key of keysToRemove) {
430
+ await this.driver.remove(key);
431
+ }
432
+ for (const tag of this.cacheTags) {
433
+ await this.driver.remove(this.tagKey(tag));
434
+ }
435
+ }
436
+ /**
437
+ * Flush all keys associated with the current tags
438
+ * @deprecated Use invalidate() instead for better semantics
439
+ */
440
+ async flush() {
441
+ return this.invalidate();
442
+ }
443
+ /**
444
+ * {@inheritdoc}
445
+ */
446
+ async has(key) {
447
+ return this.driver.has(key);
448
+ }
449
+ /**
450
+ * {@inheritdoc}
451
+ */
452
+ async remember(key, ttl, callback) {
453
+ const value = await this.get(key);
454
+ if (value !== null) {
455
+ return value;
456
+ }
457
+ const result = await callback();
458
+ await this.set(key, result, ttl);
459
+ return result;
460
+ }
461
+ /**
462
+ * {@inheritdoc}
463
+ */
464
+ async pull(key) {
465
+ const value = await this.get(key);
466
+ if (value !== null) {
467
+ await this.remove(key);
468
+ }
469
+ return value;
470
+ }
471
+ /**
472
+ * {@inheritdoc}
473
+ */
474
+ async forever(key, value) {
475
+ return this.set(key, value, Infinity);
476
+ }
477
+ /**
478
+ * {@inheritdoc}
479
+ */
480
+ async increment(key, value = 1) {
481
+ const current = await this.get(key) || 0;
482
+ if (typeof current !== "number") {
483
+ throw new Error(
484
+ `Cannot increment non-numeric value for key: ${this.driver.parseKey(key)}`
485
+ );
486
+ }
487
+ const newValue = current + value;
488
+ await this.set(key, newValue);
489
+ return newValue;
490
+ }
491
+ /**
492
+ * {@inheritdoc}
493
+ */
494
+ async decrement(key, value = 1) {
495
+ return this.increment(key, -value);
496
+ }
497
+ };
498
+ function parseCacheKey(key, options = {}) {
499
+ if (typeof key === "object") {
500
+ key = JSON.stringify(key);
501
+ }
502
+ key = key.replace(/[{}"[\]]/g, "").replaceAll(/[:,]/g, ".");
503
+ const cachePrefix = typeof options.globalPrefix === "function" ? options.globalPrefix() : options.globalPrefix;
504
+ return rtrim(String(cachePrefix ? rtrim(cachePrefix, ".") + "." + key : key), ".");
505
+ }
506
+ var CACHE_FOR = /* @__PURE__ */ ((CACHE_FOR2) => {
507
+ CACHE_FOR2[CACHE_FOR2["HALF_HOUR"] = 1800] = "HALF_HOUR";
508
+ CACHE_FOR2[CACHE_FOR2["ONE_HOUR"] = 3600] = "ONE_HOUR";
509
+ CACHE_FOR2[CACHE_FOR2["HALF_DAY"] = 43200] = "HALF_DAY";
510
+ CACHE_FOR2[CACHE_FOR2["ONE_DAY"] = 86400] = "ONE_DAY";
511
+ CACHE_FOR2[CACHE_FOR2["ONE_WEEK"] = 604800] = "ONE_WEEK";
512
+ CACHE_FOR2[CACHE_FOR2["HALF_MONTH"] = 1296e3] = "HALF_MONTH";
513
+ CACHE_FOR2[CACHE_FOR2["ONE_MONTH"] = 2592e3] = "ONE_MONTH";
514
+ CACHE_FOR2[CACHE_FOR2["TWO_MONTHS"] = 5184e3] = "TWO_MONTHS";
515
+ CACHE_FOR2[CACHE_FOR2["SIX_MONTHS"] = 15768e3] = "SIX_MONTHS";
516
+ CACHE_FOR2[CACHE_FOR2["ONE_YEAR"] = 31536e3] = "ONE_YEAR";
517
+ return CACHE_FOR2;
518
+ })(CACHE_FOR || {});
519
+
520
+ // ../../warlock.js/cache/src/drivers/base-cache-driver.ts
521
+ var messages = {
522
+ clearing: "Clearing namespace",
523
+ cleared: "Namespace cleared",
524
+ fetching: "Fetching key",
525
+ fetched: "Key fetched",
526
+ caching: "Caching key",
527
+ cached: "Key cached",
528
+ flushing: "Flushing cache",
529
+ flushed: "Cache flushed",
530
+ removing: "Removing key",
531
+ removed: "Key removed",
532
+ expired: "Key expired",
533
+ notFound: "Key not found",
534
+ connecting: "Connecting to the cache engine.",
535
+ connected: "Connected to the cache engine.",
536
+ disconnecting: "Disconnecting from the cache engine.",
537
+ disconnected: "Disconnected from the cache engine.",
538
+ error: "Error occurred"
539
+ };
540
+ var BaseCacheDriver = class {
541
+ /**
542
+ * CLient driver
543
+ */
544
+ clientDriver;
545
+ /**
546
+ * {@inheritdoc}
547
+ */
548
+ get client() {
549
+ return this.clientDriver || this;
550
+ }
551
+ /**
552
+ * Set client driver
553
+ */
554
+ set client(client) {
555
+ this.clientDriver = client;
556
+ }
557
+ /**
558
+ * Options list
559
+ */
560
+ options;
561
+ /**
562
+ * Event listeners storage
563
+ */
564
+ eventListeners = /* @__PURE__ */ new Map();
565
+ /**
566
+ * {@inheritdoc}
567
+ */
568
+ parseKey(key) {
569
+ return parseCacheKey(key, this.options);
570
+ }
571
+ /**
572
+ * {@inheritdoc}
573
+ */
574
+ setOptions(options) {
575
+ this.options = options || {};
576
+ return this;
577
+ }
578
+ /**
579
+ * Register an event listener
580
+ */
581
+ on(event, handler) {
582
+ if (!this.eventListeners.has(event)) {
583
+ this.eventListeners.set(event, /* @__PURE__ */ new Set());
584
+ }
585
+ this.eventListeners.get(event).add(handler);
586
+ return this;
587
+ }
588
+ /**
589
+ * Remove an event listener
590
+ */
591
+ off(event, handler) {
592
+ const handlers = this.eventListeners.get(event);
593
+ if (handlers) {
594
+ handlers.delete(handler);
595
+ }
596
+ return this;
597
+ }
598
+ /**
599
+ * Register a one-time event listener
600
+ */
601
+ once(event, handler) {
602
+ const onceHandler = async (data) => {
603
+ await handler(data);
604
+ this.off(event, onceHandler);
605
+ };
606
+ return this.on(event, onceHandler);
607
+ }
608
+ /**
609
+ * Emit an event to all registered listeners
610
+ */
611
+ async emit(event, data = {}) {
612
+ const handlers = this.eventListeners.get(event);
613
+ if (!handlers || handlers.size === 0) return;
614
+ const eventData = {
615
+ driver: this.name,
616
+ ...data
617
+ };
618
+ const promises = [];
619
+ for (const handler of handlers) {
620
+ try {
621
+ const result = handler(eventData);
622
+ if (result instanceof Promise) {
623
+ promises.push(result);
624
+ }
625
+ } catch (error) {
626
+ this.logError(`Error in event handler for '${event}'`, error);
627
+ }
628
+ }
629
+ if (promises.length > 0) {
630
+ await Promise.allSettled(promises);
631
+ }
632
+ }
633
+ /**
634
+ * {@inheritdoc}
635
+ */
636
+ async has(key) {
637
+ const value = await this.get(key);
638
+ return value !== null;
639
+ }
640
+ /**
641
+ * Lock storage for preventing cache stampede
642
+ */
643
+ locks = /* @__PURE__ */ new Map();
644
+ /**
645
+ * {@inheritdoc}
646
+ */
647
+ async remember(key, ttl, callback) {
648
+ const parsedKey = this.parseKey(key);
649
+ const cachedValue = await this.get(key);
650
+ if (cachedValue !== null) {
651
+ return cachedValue;
652
+ }
653
+ const existingLock = this.locks.get(parsedKey);
654
+ if (existingLock) {
655
+ return existingLock;
656
+ }
657
+ const promise = callback().then(async (result) => {
658
+ await this.set(key, result, ttl);
659
+ this.locks.delete(parsedKey);
660
+ return result;
661
+ }).catch((err) => {
662
+ this.locks.delete(parsedKey);
663
+ throw err;
664
+ });
665
+ this.locks.set(parsedKey, promise);
666
+ return promise;
667
+ }
668
+ /**
669
+ * {@inheritdoc}
670
+ */
671
+ async pull(key) {
672
+ const value = await this.get(key);
673
+ if (value !== null) {
674
+ await this.remove(key);
675
+ }
676
+ return value;
677
+ }
678
+ /**
679
+ * {@inheritdoc}
680
+ */
681
+ async forever(key, value) {
682
+ return this.set(key, value, Infinity);
683
+ }
684
+ /**
685
+ * {@inheritdoc}
686
+ */
687
+ async increment(key, value = 1) {
688
+ const current = await this.get(key) || 0;
689
+ if (typeof current !== "number") {
690
+ throw new Error(`Cannot increment non-numeric value for key: ${this.parseKey(key)}`);
691
+ }
692
+ const newValue = current + value;
693
+ await this.set(key, newValue);
694
+ return newValue;
695
+ }
696
+ /**
697
+ * {@inheritdoc}
698
+ */
699
+ async decrement(key, value = 1) {
700
+ return this.increment(key, -value);
701
+ }
702
+ /**
703
+ * {@inheritdoc}
704
+ */
705
+ async many(keys) {
706
+ return Promise.all(keys.map((key) => this.get(key)));
707
+ }
708
+ /**
709
+ * {@inheritdoc}
710
+ */
711
+ async setMany(items, ttl) {
712
+ await Promise.all(Object.entries(items).map(([key, value]) => this.set(key, value, ttl)));
713
+ }
714
+ /**
715
+ * Log the operation
716
+ */
717
+ log(operation, key) {
718
+ if (key) {
719
+ key = key.replaceAll("/", ".");
720
+ }
721
+ if (operation == "notFound" || operation == "expired") {
722
+ return log.warn(
723
+ "cache:" + this.name,
724
+ operation,
725
+ (key ? key + " " : "") + messages[operation]
726
+ );
727
+ }
728
+ if (operation.endsWith("ed")) {
729
+ return log.success(
730
+ "cache:" + this.name,
731
+ operation,
732
+ (key ? key + " " : "") + messages[operation]
733
+ );
734
+ }
735
+ log.info("cache:" + this.name, operation, (key ? key + " " : "") + messages[operation]);
736
+ }
737
+ /**
738
+ * Log error message
739
+ */
740
+ logError(message, error) {
741
+ log.error("cache:" + this.name, "error", message);
742
+ if (error) {
743
+ console.log(error);
744
+ }
745
+ }
746
+ /**
747
+ * Get time to live value
748
+ */
749
+ get ttl() {
750
+ return this.options.ttl !== void 0 ? this.options.ttl : Infinity;
751
+ }
752
+ /**
753
+ * Get time to live value in milliseconds
754
+ */
755
+ getExpiresAt(ttl = this.ttl) {
756
+ if (ttl) {
757
+ return (/* @__PURE__ */ new Date()).getTime() + ttl * 1e3;
758
+ }
759
+ }
760
+ /**
761
+ * Prepare data for storage
762
+ */
763
+ prepareDataForStorage(data, ttl) {
764
+ const preparedData = {
765
+ data
766
+ };
767
+ if (ttl) {
768
+ preparedData.ttl = ttl;
769
+ preparedData.expiresAt = this.getExpiresAt(ttl);
770
+ }
771
+ return preparedData;
772
+ }
773
+ /**
774
+ * Parse fetched data from cache
775
+ */
776
+ async parseCachedData(key, data) {
777
+ this.log("fetched", key);
778
+ if (data.expiresAt && data.expiresAt < Date.now()) {
779
+ this.remove(key);
780
+ return null;
781
+ }
782
+ const value = data.data;
783
+ if (value === null || value === void 0) {
784
+ return value;
785
+ }
786
+ const type = typeof value;
787
+ if (type === "string" || type === "number" || type === "boolean") {
788
+ return value;
789
+ }
790
+ try {
791
+ return structuredClone(value);
792
+ } catch (error) {
793
+ console.log(value);
794
+ this.logError(
795
+ `Failed to clone cached value for ${key}, typeof value: ${typeof value}`,
796
+ error
797
+ );
798
+ throw error;
799
+ }
800
+ }
801
+ /**
802
+ * {@inheritdoc}
803
+ */
804
+ async connect() {
805
+ this.log("connecting");
806
+ this.log("connected");
807
+ await this.emit("connected");
808
+ }
809
+ /**
810
+ * {@inheritdoc}
811
+ */
812
+ async disconnect() {
813
+ this.log("disconnected");
814
+ await this.emit("disconnected");
815
+ }
816
+ /**
817
+ * Create a tagged cache instance for the given tags
818
+ */
819
+ tags(tags) {
820
+ return new TaggedCache(tags, this);
821
+ }
822
+ };
823
+ var FileCacheDriver = class extends BaseCacheDriver {
824
+ /**
825
+ * {@inheritdoc}
826
+ */
827
+ name = "file";
828
+ /**
829
+ * {@inheritdoc}
830
+ */
831
+ setOptions(options) {
832
+ if (!options.directory) {
833
+ throw new CacheConfigurationError(
834
+ "File driver requires 'directory' option to be configured."
835
+ );
836
+ }
837
+ return super.setOptions(options);
838
+ }
839
+ /**
840
+ * Get the cache directory
841
+ */
842
+ get directory() {
843
+ const directory = this.options.directory;
844
+ if (typeof directory === "function") {
845
+ return directory();
846
+ }
847
+ throw new CacheConfigurationError(
848
+ "Cache directory is not defined, please define it in the file driver options"
849
+ );
850
+ }
851
+ /**
852
+ * Get file name
853
+ */
854
+ get fileName() {
855
+ const fileName = this.options.fileName;
856
+ if (typeof fileName === "function") {
857
+ return fileName();
858
+ }
859
+ return "cache.json";
860
+ }
861
+ /**
862
+ * {@inheritdoc}
863
+ */
864
+ async removeNamespace(namespace) {
865
+ this.log("clearing", namespace);
866
+ try {
867
+ await removeDirectoryAsync(path.resolve(this.directory, namespace));
868
+ this.log("cleared", namespace);
869
+ } catch (error) {
870
+ }
871
+ return this;
872
+ }
873
+ /**
874
+ * {@inheritdoc}
875
+ */
876
+ async set(key, value, ttl) {
877
+ key = this.parseKey(key);
878
+ this.log("caching", key);
879
+ const data = this.prepareDataForStorage(value, ttl);
880
+ const fileDirectory = path.resolve(this.directory, key);
881
+ await ensureDirectoryAsync(fileDirectory);
882
+ await putJsonFileAsync(path.resolve(fileDirectory, this.fileName), data);
883
+ this.log("cached", key);
884
+ await this.emit("set", { key, value, ttl });
885
+ return this;
886
+ }
887
+ /**
888
+ * {@inheritdoc}
889
+ */
890
+ async get(key) {
891
+ const parsedKey = this.parseKey(key);
892
+ this.log("fetching", parsedKey);
893
+ const fileDirectory = path.resolve(this.directory, parsedKey);
894
+ try {
895
+ const value = await getJsonFileAsync(
896
+ path.resolve(fileDirectory, this.fileName)
897
+ );
898
+ const result = await this.parseCachedData(parsedKey, value);
899
+ if (result === null) {
900
+ await this.emit("miss", { key: parsedKey });
901
+ } else {
902
+ await this.emit("hit", { key: parsedKey, value: result });
903
+ }
904
+ return result;
905
+ } catch (error) {
906
+ this.log("notFound", parsedKey);
907
+ await this.emit("miss", { key: parsedKey });
908
+ this.remove(key);
909
+ return null;
910
+ }
911
+ }
912
+ /**
913
+ * {@inheritdoc}
914
+ */
915
+ async remove(key) {
916
+ const parsedKey = this.parseKey(key);
917
+ this.log("removing", parsedKey);
918
+ const fileDirectory = path.resolve(this.directory, parsedKey);
919
+ try {
920
+ await removeDirectoryAsync(fileDirectory);
921
+ this.log("removed", parsedKey);
922
+ await this.emit("removed", { key: parsedKey });
923
+ } catch (error) {
924
+ }
925
+ }
926
+ /**
927
+ * {@inheritdoc}
928
+ */
929
+ async flush() {
930
+ this.log("flushing");
931
+ if (this.options.globalPrefix) {
932
+ await this.removeNamespace("");
933
+ } else {
934
+ await removeDirectoryAsync(this.directory);
935
+ }
936
+ this.log("flushed");
937
+ await this.emit("flushed");
938
+ }
939
+ /**
940
+ * {@inheritdoc}
941
+ */
942
+ async connect() {
943
+ this.log("connecting");
944
+ await ensureDirectoryAsync(this.directory);
945
+ this.log("connected");
946
+ await this.emit("connected");
947
+ }
948
+ };
949
+
950
+ // ../../warlock.js/cache/src/drivers/lru-memory-cache-driver.ts
951
+ var CacheNode = class {
952
+ constructor(key, value, ttl) {
953
+ this.key = key;
954
+ this.value = value;
955
+ if (ttl && ttl !== Infinity) {
956
+ this.expiresAt = Date.now() + ttl * 1e3;
957
+ }
958
+ }
959
+ next = null;
960
+ prev = null;
961
+ expiresAt;
962
+ get isExpired() {
963
+ return this.expiresAt !== void 0 && this.expiresAt < Date.now();
964
+ }
965
+ };
966
+ var LRUMemoryCacheDriver = class extends BaseCacheDriver {
967
+ /**
968
+ * {@inheritdoc}
969
+ */
970
+ name = "lru";
971
+ /**
972
+ * Cache map
973
+ */
974
+ cache = /* @__PURE__ */ new Map();
975
+ /**
976
+ * Head of the cache
977
+ */
978
+ head = new CacheNode("", null);
979
+ /**
980
+ * Tail of the cache
981
+ */
982
+ tail = new CacheNode("", null);
983
+ /**
984
+ * Cleanup interval reference
985
+ */
986
+ cleanupInterval;
987
+ /**
988
+ * {@inheritdoc}
989
+ */
990
+ constructor() {
991
+ super();
992
+ this.init();
993
+ this.startCleanup();
994
+ }
995
+ /**
996
+ * Initialize the cache
997
+ */
998
+ init() {
999
+ this.head.next = this.tail;
1000
+ this.tail.prev = this.head;
1001
+ }
1002
+ /**
1003
+ * Start the cleanup process for expired items
1004
+ */
1005
+ startCleanup() {
1006
+ if (this.cleanupInterval) {
1007
+ clearInterval(this.cleanupInterval);
1008
+ }
1009
+ this.cleanupInterval = setInterval(async () => {
1010
+ const now = Date.now();
1011
+ const expiredKeys = [];
1012
+ for (const [key, node] of this.cache) {
1013
+ if (node.expiresAt && node.expiresAt <= now) {
1014
+ expiredKeys.push(key);
1015
+ }
1016
+ }
1017
+ for (const key of expiredKeys) {
1018
+ const node = this.cache.get(key);
1019
+ if (node) {
1020
+ this.removeNode(node);
1021
+ this.cache.delete(key);
1022
+ this.log("expired", key);
1023
+ await this.emit("expired", { key });
1024
+ }
1025
+ }
1026
+ }, 1e3);
1027
+ this.cleanupInterval.unref();
1028
+ }
1029
+ /**
1030
+ * {@inheritdoc}
1031
+ */
1032
+ async removeNamespace(_namespace) {
1033
+ throw new Error("Namespace is not supported in LRU cache driver.");
1034
+ }
1035
+ /**
1036
+ * {@inheritdoc}
1037
+ */
1038
+ async set(key, value, ttl) {
1039
+ key = this.parseKey(key);
1040
+ this.log("caching", key);
1041
+ if (ttl === void 0) {
1042
+ ttl = this.ttl;
1043
+ }
1044
+ const existingNode = this.cache.get(key);
1045
+ if (existingNode) {
1046
+ existingNode.value = value;
1047
+ if (ttl && ttl !== Infinity) {
1048
+ existingNode.expiresAt = Date.now() + ttl * 1e3;
1049
+ } else {
1050
+ existingNode.expiresAt = void 0;
1051
+ }
1052
+ this.moveHead(existingNode);
1053
+ } else {
1054
+ const newNode = new CacheNode(key, value, ttl);
1055
+ this.cache.set(key, newNode);
1056
+ this.addNode(newNode);
1057
+ if (this.cache.size > this.capacity) {
1058
+ this.removeTail();
1059
+ }
1060
+ }
1061
+ this.log("cached", key);
1062
+ await this.emit("set", { key, value, ttl });
1063
+ return this;
1064
+ }
1065
+ /**
1066
+ * Move the node to the head
1067
+ */
1068
+ moveHead(node) {
1069
+ this.removeNode(node);
1070
+ this.addNode(node);
1071
+ }
1072
+ /**
1073
+ * Remove the node from the cache
1074
+ */
1075
+ removeNode(node) {
1076
+ node.prev.next = node.next;
1077
+ node.next.prev = node.prev;
1078
+ }
1079
+ /**
1080
+ * Add the node to the head
1081
+ */
1082
+ addNode(node) {
1083
+ node.next = this.head.next;
1084
+ node.prev = this.head;
1085
+ this.head.next.prev = node;
1086
+ this.head.next = node;
1087
+ }
1088
+ /**
1089
+ * Remove the tail node
1090
+ */
1091
+ removeTail() {
1092
+ const node = this.tail.prev;
1093
+ this.removeNode(node);
1094
+ this.cache.delete(node.key);
1095
+ }
1096
+ /**
1097
+ * {@inheritdoc}
1098
+ */
1099
+ async get(key) {
1100
+ const parsedKey = this.parseKey(key);
1101
+ this.log("fetching", parsedKey);
1102
+ const node = this.cache.get(parsedKey);
1103
+ if (!node) {
1104
+ this.log("notFound", parsedKey);
1105
+ await this.emit("miss", { key: parsedKey });
1106
+ return null;
1107
+ }
1108
+ if (node.isExpired) {
1109
+ this.removeNode(node);
1110
+ this.cache.delete(parsedKey);
1111
+ this.log("expired", parsedKey);
1112
+ await this.emit("expired", { key: parsedKey });
1113
+ await this.emit("miss", { key: parsedKey });
1114
+ return null;
1115
+ }
1116
+ this.moveHead(node);
1117
+ this.log("fetched", parsedKey);
1118
+ const value = node.value;
1119
+ if (value === null || value === void 0) {
1120
+ return value;
1121
+ }
1122
+ const type = typeof value;
1123
+ if (type === "string" || type === "number" || type === "boolean") {
1124
+ await this.emit("hit", { key: parsedKey, value });
1125
+ return value;
1126
+ }
1127
+ try {
1128
+ const clonedValue = structuredClone(value);
1129
+ await this.emit("hit", { key: parsedKey, value: clonedValue });
1130
+ return clonedValue;
1131
+ } catch (error) {
1132
+ this.logError(`Failed to clone cached value for ${parsedKey}`, error);
1133
+ throw error;
1134
+ }
1135
+ }
1136
+ /**
1137
+ * {@inheritdoc}
1138
+ */
1139
+ async remove(key) {
1140
+ const parsedKey = this.parseKey(key);
1141
+ this.log("removing", parsedKey);
1142
+ const node = this.cache.get(parsedKey);
1143
+ if (node) {
1144
+ this.removeNode(node);
1145
+ this.cache.delete(parsedKey);
1146
+ }
1147
+ this.log("removed", parsedKey);
1148
+ await this.emit("removed", { key: parsedKey });
1149
+ }
1150
+ /**
1151
+ * {@inheritdoc}
1152
+ */
1153
+ async flush() {
1154
+ this.log("flushing");
1155
+ this.cache.clear();
1156
+ this.init();
1157
+ this.log("flushed");
1158
+ await this.emit("flushed");
1159
+ }
1160
+ /**
1161
+ * Get lru capacity
1162
+ */
1163
+ get capacity() {
1164
+ return this.options.capacity || 1e3;
1165
+ }
1166
+ /**
1167
+ * {@inheritdoc}
1168
+ */
1169
+ async disconnect() {
1170
+ if (this.cleanupInterval) {
1171
+ clearInterval(this.cleanupInterval);
1172
+ this.cleanupInterval = void 0;
1173
+ }
1174
+ await super.disconnect();
1175
+ }
1176
+ };
1177
+ var MemoryCacheDriver = class extends BaseCacheDriver {
1178
+ /**
1179
+ * {@inheritdoc}
1180
+ */
1181
+ name = "memory";
1182
+ /**
1183
+ * Cached data
1184
+ */
1185
+ data = {};
1186
+ /**
1187
+ * List of data that will be cleared from cache
1188
+ */
1189
+ temporaryData = {};
1190
+ /**
1191
+ * Cleanup interval reference
1192
+ */
1193
+ cleanupInterval;
1194
+ /**
1195
+ * Access order tracking for LRU eviction (when maxSize is set)
1196
+ */
1197
+ accessOrder = [];
1198
+ /**
1199
+ * {@inheritdoc}
1200
+ */
1201
+ constructor() {
1202
+ super();
1203
+ this.startCleanup();
1204
+ }
1205
+ /**
1206
+ * Start the cleanup process whenever a data that has a cache key is set
1207
+ */
1208
+ startCleanup() {
1209
+ if (this.cleanupInterval) {
1210
+ clearInterval(this.cleanupInterval);
1211
+ }
1212
+ this.cleanupInterval = setInterval(async () => {
1213
+ const now = Date.now();
1214
+ for (const key in this.temporaryData) {
1215
+ if (this.temporaryData[key].expiresAt <= now) {
1216
+ await this.remove(this.temporaryData[key].key);
1217
+ delete this.temporaryData[key];
1218
+ this.log("expired", key);
1219
+ await this.emit("expired", { key });
1220
+ }
1221
+ }
1222
+ }, 1e3);
1223
+ this.cleanupInterval.unref();
1224
+ }
1225
+ /**
1226
+ * {@inheritdoc}
1227
+ */
1228
+ async removeNamespace(namespace) {
1229
+ this.log("clearing", namespace);
1230
+ namespace = this.parseKey(namespace);
1231
+ unset(this.data, [namespace]);
1232
+ this.log("cleared", namespace);
1233
+ return this;
1234
+ }
1235
+ /**
1236
+ * {@inheritdoc}
1237
+ */
1238
+ async set(key, value, ttl) {
1239
+ const parsedKey = this.parseKey(key);
1240
+ this.log("caching", parsedKey);
1241
+ if (ttl === void 0) {
1242
+ ttl = this.ttl;
1243
+ }
1244
+ const data = this.prepareDataForStorage(value, ttl);
1245
+ if (ttl) {
1246
+ this.setTemporaryData(key, parsedKey, ttl);
1247
+ }
1248
+ const existingData = get(this.data, parsedKey);
1249
+ const isNewKey = !existingData;
1250
+ set(this.data, parsedKey, data);
1251
+ this.trackAccess(parsedKey);
1252
+ if (isNewKey && this.options.maxSize) {
1253
+ await this.enforceMaxSize();
1254
+ }
1255
+ this.log("cached", parsedKey);
1256
+ await this.emit("set", { key: parsedKey, value, ttl });
1257
+ return this;
1258
+ }
1259
+ /**
1260
+ * {@inheritdoc}
1261
+ */
1262
+ async get(key) {
1263
+ const parsedKey = this.parseKey(key);
1264
+ this.log("fetching", parsedKey);
1265
+ const value = get(this.data, parsedKey);
1266
+ if (!value) {
1267
+ this.log("notFound", parsedKey);
1268
+ await this.emit("miss", { key: parsedKey });
1269
+ return null;
1270
+ }
1271
+ const result = await this.parseCachedData(parsedKey, value);
1272
+ if (result === null) {
1273
+ await this.emit("miss", { key: parsedKey });
1274
+ } else {
1275
+ this.trackAccess(parsedKey);
1276
+ await this.emit("hit", { key: parsedKey, value: result });
1277
+ }
1278
+ return result;
1279
+ }
1280
+ /**
1281
+ * {@inheritdoc}
1282
+ */
1283
+ async remove(key) {
1284
+ const parsedKey = this.parseKey(key);
1285
+ this.log("removing", parsedKey);
1286
+ unset(this.data, [parsedKey]);
1287
+ delete this.temporaryData[parsedKey];
1288
+ this.removeFromAccessOrder(parsedKey);
1289
+ this.log("removed", parsedKey);
1290
+ await this.emit("removed", { key: parsedKey });
1291
+ }
1292
+ /**
1293
+ * {@inheritdoc}
1294
+ */
1295
+ async flush() {
1296
+ this.log("flushing");
1297
+ if (this.options.globalPrefix) {
1298
+ this.removeNamespace("");
1299
+ } else {
1300
+ this.data = {};
1301
+ this.accessOrder = [];
1302
+ }
1303
+ this.log("flushed");
1304
+ await this.emit("flushed");
1305
+ }
1306
+ /**
1307
+ * Set the temporary data
1308
+ */
1309
+ setTemporaryData(key, parsedKey, ttl) {
1310
+ this.temporaryData[parsedKey] = {
1311
+ key: JSON.stringify(key),
1312
+ expiresAt: Date.now() + ttl * 1e3
1313
+ };
1314
+ }
1315
+ /**
1316
+ * Track access for LRU eviction
1317
+ */
1318
+ trackAccess(key) {
1319
+ if (!this.options.maxSize) return;
1320
+ const index = this.accessOrder.indexOf(key);
1321
+ if (index > -1) {
1322
+ this.accessOrder.splice(index, 1);
1323
+ }
1324
+ this.accessOrder.push(key);
1325
+ }
1326
+ /**
1327
+ * Remove key from access order tracking
1328
+ */
1329
+ removeFromAccessOrder(key) {
1330
+ const index = this.accessOrder.indexOf(key);
1331
+ if (index > -1) {
1332
+ this.accessOrder.splice(index, 1);
1333
+ }
1334
+ }
1335
+ /**
1336
+ * Enforce max size by evicting least recently used items
1337
+ */
1338
+ async enforceMaxSize() {
1339
+ if (!this.options.maxSize) return;
1340
+ const cacheSize = this.getCacheSize();
1341
+ while (cacheSize > this.options.maxSize && this.accessOrder.length > 0) {
1342
+ const lruKey = this.accessOrder.shift();
1343
+ if (lruKey) {
1344
+ this.log("removing", lruKey);
1345
+ unset(this.data, [lruKey]);
1346
+ delete this.temporaryData[lruKey];
1347
+ this.log("removed", lruKey);
1348
+ }
1349
+ }
1350
+ }
1351
+ /**
1352
+ * Get current cache size (number of cached items)
1353
+ */
1354
+ getCacheSize() {
1355
+ return Object.keys(this.data).length;
1356
+ }
1357
+ /**
1358
+ * {@inheritdoc}
1359
+ */
1360
+ async disconnect() {
1361
+ if (this.cleanupInterval) {
1362
+ clearInterval(this.cleanupInterval);
1363
+ this.cleanupInterval = void 0;
1364
+ }
1365
+ await super.disconnect();
1366
+ }
1367
+ };
1368
+ var MemoryExtendedCacheDriver = class extends MemoryCacheDriver {
1369
+ /**
1370
+ * {@inheritdoc}
1371
+ */
1372
+ name = "memoryExtended";
1373
+ /**
1374
+ * {@inheritdoc}
1375
+ */
1376
+ async get(key) {
1377
+ const parsedKey = this.parseKey(key);
1378
+ this.log("fetching", parsedKey);
1379
+ const value = get(this.data, parsedKey);
1380
+ if (!value) {
1381
+ this.log("notFound", parsedKey);
1382
+ return null;
1383
+ }
1384
+ const ttl = value.ttl || this.options.ttl;
1385
+ if (ttl) {
1386
+ this.setTemporaryData(key, parsedKey, ttl);
1387
+ value.expiresAt = this.getExpiresAt(ttl);
1388
+ }
1389
+ return this.parseCachedData(parsedKey, value);
1390
+ }
1391
+ };
1392
+ var NullCacheDriver = class extends BaseCacheDriver {
1393
+ /**
1394
+ * Options list
1395
+ */
1396
+ options = {};
1397
+ /**
1398
+ * {@inheritdoc}
1399
+ */
1400
+ name = "null";
1401
+ /**
1402
+ * Cached data
1403
+ */
1404
+ data = {};
1405
+ /**
1406
+ * {@inheritdoc}
1407
+ */
1408
+ get client() {
1409
+ return this;
1410
+ }
1411
+ /**
1412
+ * Constructor
1413
+ */
1414
+ constructor(options = {}) {
1415
+ super();
1416
+ this.setOptions(options);
1417
+ }
1418
+ /**
1419
+ * {@inheritdoc}
1420
+ */
1421
+ setOptions(options) {
1422
+ this.options = options;
1423
+ return this;
1424
+ }
1425
+ /**
1426
+ * {@inheritdoc}
1427
+ */
1428
+ parseKey(_key) {
1429
+ return "";
1430
+ }
1431
+ /**
1432
+ * {@inheritdoc}
1433
+ */
1434
+ async removeNamespace(namespace) {
1435
+ log.info("cache", "clearing namespace", namespace);
1436
+ log.success("cache", "namespace cleared", namespace);
1437
+ return this;
1438
+ }
1439
+ /**
1440
+ * {@inheritdoc}
1441
+ */
1442
+ async set(key, _value) {
1443
+ log.info("cache", "setting key", key);
1444
+ log.success("cache", "key set", key);
1445
+ return this;
1446
+ }
1447
+ /**
1448
+ * {@inheritdoc}
1449
+ */
1450
+ async get(key) {
1451
+ log.info("cache", "fetching", key);
1452
+ log.success("cache", "fetched", key);
1453
+ return null;
1454
+ }
1455
+ /**
1456
+ * {@inheritdoc}
1457
+ */
1458
+ async remove(key) {
1459
+ log.info("cache", "removing", key);
1460
+ log.success("cache", "removed", key);
1461
+ }
1462
+ /**
1463
+ * {@inheritdoc}
1464
+ */
1465
+ async flush() {
1466
+ log.info("cache", "flushing", "all");
1467
+ log.success("cache", "flushed", "all");
1468
+ }
1469
+ /**
1470
+ * {@inheritdoc}
1471
+ */
1472
+ async connect() {
1473
+ log.success("cache", "connected", "Connected to null cache driver");
1474
+ }
1475
+ };
1476
+ var RedisCacheDriver = class extends BaseCacheDriver {
1477
+ /**
1478
+ * Cache driver name
1479
+ */
1480
+ name = "redis";
1481
+ /**
1482
+ * {@inheritdoc}
1483
+ */
1484
+ setOptions(options) {
1485
+ if (!options.url && !options.host) {
1486
+ throw new CacheConfigurationError(
1487
+ "Redis driver requires either 'url' or 'host' option to be configured."
1488
+ );
1489
+ }
1490
+ return super.setOptions(options);
1491
+ }
1492
+ /**
1493
+ * {@inheritDoc}
1494
+ */
1495
+ async removeNamespace(namespace) {
1496
+ namespace = this.parseKey(namespace);
1497
+ this.log("clearing", namespace);
1498
+ const keys = await this.client?.keys(`${namespace}*`);
1499
+ if (!keys || keys.length === 0) {
1500
+ this.log("notFound", namespace);
1501
+ return;
1502
+ }
1503
+ await this.client?.del(keys);
1504
+ this.log("cleared", namespace);
1505
+ return keys;
1506
+ }
1507
+ /**
1508
+ * {@inheritDoc}
1509
+ */
1510
+ async set(key, value, ttl) {
1511
+ key = this.parseKey(key);
1512
+ this.log("caching", key);
1513
+ if (ttl === void 0) {
1514
+ ttl = this.ttl;
1515
+ }
1516
+ if (ttl && ttl !== Infinity) {
1517
+ await this.client?.set(key, JSON.stringify(value), { EX: ttl });
1518
+ } else {
1519
+ await this.client?.set(key, JSON.stringify(value));
1520
+ }
1521
+ this.log("cached", key);
1522
+ await this.emit("set", { key, value, ttl });
1523
+ return value;
1524
+ }
1525
+ /**
1526
+ * {@inheritDoc}
1527
+ */
1528
+ async get(key) {
1529
+ key = this.parseKey(key);
1530
+ this.log("fetching", key);
1531
+ const value = await this.client?.get(key);
1532
+ if (!value) {
1533
+ this.log("notFound", key);
1534
+ await this.emit("miss", { key });
1535
+ return null;
1536
+ }
1537
+ this.log("fetched", key);
1538
+ const parsedValue = JSON.parse(value);
1539
+ if (parsedValue === null || parsedValue === void 0) {
1540
+ await this.emit("hit", { key, value: parsedValue });
1541
+ return parsedValue;
1542
+ }
1543
+ const type = typeof parsedValue;
1544
+ if (type === "string" || type === "number" || type === "boolean") {
1545
+ await this.emit("hit", { key, value: parsedValue });
1546
+ return parsedValue;
1547
+ }
1548
+ try {
1549
+ const clonedValue = structuredClone(parsedValue);
1550
+ await this.emit("hit", { key, value: clonedValue });
1551
+ return clonedValue;
1552
+ } catch (error) {
1553
+ this.logError(`Failed to clone cached value for ${key}`, error);
1554
+ throw error;
1555
+ }
1556
+ }
1557
+ /**
1558
+ * {@inheritDoc}
1559
+ */
1560
+ async remove(key) {
1561
+ key = this.parseKey(key);
1562
+ this.log("removing", key);
1563
+ await this.client?.del(key);
1564
+ this.log("removed", key);
1565
+ await this.emit("removed", { key });
1566
+ }
1567
+ /**
1568
+ * {@inheritDoc}
1569
+ */
1570
+ async flush() {
1571
+ this.log("flushing");
1572
+ if (this.options.globalPrefix) {
1573
+ await this.removeNamespace("");
1574
+ } else {
1575
+ await this.client?.flushAll();
1576
+ }
1577
+ this.log("flushed");
1578
+ await this.emit("flushed");
1579
+ }
1580
+ /**
1581
+ * {@inheritDoc}
1582
+ */
1583
+ async connect() {
1584
+ if (this.clientDriver) return;
1585
+ const options = this.options;
1586
+ if (options && !options.url && options.host) {
1587
+ const auth = options.password || options.username ? `${options.username}:${options.password}@` : "";
1588
+ if (!options.url) {
1589
+ const host = options.host || "localhost";
1590
+ const port = options.port || 6379;
1591
+ options.url = `redis://${auth}${host}:${port}`;
1592
+ }
1593
+ }
1594
+ const clientOptions = {
1595
+ ...options,
1596
+ ...this.options.clientOptions || {}
1597
+ };
1598
+ this.log("connecting");
1599
+ const { createClient } = await import('redis');
1600
+ this.client = createClient(clientOptions);
1601
+ this.client.on("error", (error) => {
1602
+ this.log("error", error.message);
1603
+ });
1604
+ try {
1605
+ await this.client.connect();
1606
+ this.log("connected");
1607
+ await this.emit("connected");
1608
+ } catch (error) {
1609
+ log.error("cache", "redis", error);
1610
+ await this.emit("error", { error });
1611
+ }
1612
+ }
1613
+ /**
1614
+ * {@inheritDoc}
1615
+ */
1616
+ async disconnect() {
1617
+ if (!this.client) return;
1618
+ this.log("disconnecting");
1619
+ await this.client.quit();
1620
+ this.log("disconnected");
1621
+ await this.emit("disconnected");
1622
+ }
1623
+ /**
1624
+ * Atomic increment using Redis native INCRBY command
1625
+ * {@inheritdoc}
1626
+ */
1627
+ async increment(key, value = 1) {
1628
+ const parsedKey = this.parseKey(key);
1629
+ this.log("caching", parsedKey);
1630
+ const result = await this.client?.incrBy(parsedKey, value);
1631
+ this.log("cached", parsedKey);
1632
+ await this.emit("set", { key: parsedKey, value: result, ttl: void 0 });
1633
+ return result || 0;
1634
+ }
1635
+ /**
1636
+ * Atomic decrement using Redis native DECRBY command
1637
+ * {@inheritdoc}
1638
+ */
1639
+ async decrement(key, value = 1) {
1640
+ const parsedKey = this.parseKey(key);
1641
+ this.log("caching", parsedKey);
1642
+ const result = await this.client?.decrBy(parsedKey, value);
1643
+ this.log("cached", parsedKey);
1644
+ await this.emit("set", { key: parsedKey, value: result, ttl: void 0 });
1645
+ return result || 0;
1646
+ }
1647
+ /**
1648
+ * Set if not exists (atomic operation)
1649
+ * Returns true if key was set, false if key already existed
1650
+ */
1651
+ async setNX(key, value, ttl) {
1652
+ const parsedKey = this.parseKey(key);
1653
+ this.log("caching", parsedKey);
1654
+ if (ttl === void 0) {
1655
+ ttl = this.ttl;
1656
+ }
1657
+ let result;
1658
+ if (ttl && ttl !== Infinity) {
1659
+ result = await this.client?.set(parsedKey, JSON.stringify(value), {
1660
+ NX: true,
1661
+ EX: ttl
1662
+ });
1663
+ } else {
1664
+ result = await this.client?.set(parsedKey, JSON.stringify(value), {
1665
+ NX: true
1666
+ });
1667
+ }
1668
+ const wasSet = result === "OK";
1669
+ if (wasSet) {
1670
+ this.log("cached", parsedKey);
1671
+ await this.emit("set", { key: parsedKey, value, ttl });
1672
+ } else {
1673
+ this.log("notFound", parsedKey);
1674
+ }
1675
+ return wasSet;
1676
+ }
1677
+ };
1678
+
1679
+ export { BaseCacheDriver, CACHE_FOR, CacheConfigurationError, CacheConnectionError, CacheDriverNotInitializedError, CacheError, CacheManager, FileCacheDriver, LRUMemoryCacheDriver, MemoryCacheDriver, MemoryExtendedCacheDriver, NullCacheDriver, RedisCacheDriver, TaggedCache, cache, parseCacheKey };
1680
+ //# sourceMappingURL=index.js.map
3
1681
  //# sourceMappingURL=index.js.map