@stacksjs/cache 0.74.46 → 0.74.48

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 (2) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{createCache as d}from"@stacksjs/ts-cache";var{SQL:p}=globalThis.Bun;function y(e){return`\`${e.replace(/`/g,"``")}\``}class l{sql;table;qualified;prefix;stdTTL;ready=null;hits=0;misses=0;constructor(e={}){let{host:t="127.0.0.1",port:s=3306,username:r="root",password:i="",database:h="stacks",table:a="stacks_cache",ssl:o=!1}=e;this.table=a,this.qualified=y(a),this.prefix=e.prefix??"",this.stdTTL=e.stdTTL??0;let u=i?`${r}:${encodeURIComponent(i)}`:r,g=o?"?ssl=true":"";this.sql=new p(`mysql://${u}@${t}:${s}/${h}${g}`)}async ensureReady(){if(!this.ready)this.ready=this.sql.unsafe(`CREATE ROWSTORE TABLE IF NOT EXISTS ${this.qualified} ( cache_key VARCHAR(255) NOT NULL, value LONGTEXT NOT NULL, expires_at BIGINT NULL, PRIMARY KEY (cache_key) )`).then(()=>{return});await this.ready}k(e){return this.prefix?`${this.prefix}:${e}`:e}nowMs(){return Date.now()}expiryFor(e){let t=e??this.stdTTL;if(!t||t<=0)return null;return this.nowMs()+t*1000}async get(e){await this.ensureReady();let s=(await this.sql.unsafe(`SELECT value, expires_at FROM ${this.qualified} WHERE cache_key = ? LIMIT 1`,[this.k(e)]))[0];if(!s){this.misses++;return}if(s.expires_at!=null&&s.expires_at<=this.nowMs()){await this.del(e),this.misses++;return}return this.hits++,JSON.parse(s.value)}async mget(e){let t={};for(let s of e){let r=await this.get(s);if(r!==void 0)t[s]=r}return t}async set(e,t,s){await this.ensureReady();let r=this.expiryFor(s);return await this.sql.unsafe(`INSERT INTO ${this.qualified} (cache_key, value, expires_at) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE value = VALUES(value), expires_at = VALUES(expires_at)`,[this.k(e),JSON.stringify(t),r]),!0}async mset(e){for(let t of e)await this.set(t.key,t.value,t.ttl);return!0}async fetch(e,t,s){let r=await this.get(e);if(r!==void 0)return r;let i=await t();return await this.set(e,i,s),i}async del(e){await this.ensureReady();let t=Array.isArray(e)?e:[e];if(t.length===0)return 0;let s=t.map(()=>"?").join(", "),i=(await this.sql.unsafe(`DELETE FROM ${this.qualified} WHERE cache_key IN (${s})`,t.map((h)=>this.k(h)))).affectedRows;return typeof i==="number"?i:t.length}async has(e){return await this.get(e)!==void 0}async flush(){if(await this.ensureReady(),this.prefix)await this.sql.unsafe(`DELETE FROM ${this.qualified} WHERE cache_key LIKE ?`,[`${this.prefix}:%`]);else await this.sql.unsafe(`TRUNCATE TABLE ${this.qualified}`)}async keys(e){await this.ensureReady();let t=`${this.prefix?`${this.prefix}:`:""}${e?e.replace(/\*/g,"%"):"%"}`,s=await this.sql.unsafe(`SELECT cache_key FROM ${this.qualified} WHERE cache_key LIKE ? AND (expires_at IS NULL OR expires_at > ?)`,[t,this.nowMs()]),r=this.prefix?this.prefix.length+1:0;return s.map((i)=>r?i.cache_key.slice(r):i.cache_key)}async getTtl(e){await this.ensureReady();let s=(await this.sql.unsafe(`SELECT expires_at FROM ${this.qualified} WHERE cache_key = ? LIMIT 1`,[this.k(e)]))[0];if(!s)return;return s.expires_at==null?0:s.expires_at}async ttl(e,t){await this.ensureReady();let s=this.expiryFor(t);return((await this.sql.unsafe(`UPDATE ${this.qualified} SET expires_at = ? WHERE cache_key = ?`,[s,this.k(e)])).affectedRows??0)>0}async take(e){let t=await this.get(e);if(t!==void 0)await this.del(e);return t}async getStats(){await this.ensureReady();let e=await this.sql.unsafe(`SELECT COUNT(*) AS n FROM ${this.qualified} WHERE expires_at IS NULL OR expires_at > ?`,[this.nowMs()]);return{hits:this.hits,misses:this.misses,keys:Number(e[0]?.n??0),ksize:0,vsize:0}}async close(){await this.sql.end()}}import{CacheManager as D,MemoryDriver as I,RedisDriver as N}from"@stacksjs/ts-cache";import{CacheAsidePattern as U,MultiLevelPattern as W,RefreshAheadPattern as z,WriteThroughPattern as H,BatchOperations as B,CacheInvalidation as G,CacheLock as V,CircuitBreaker as X,memoize as Y,RateLimiter as j}from"@stacksjs/ts-cache";class c{manager;inflight=new Map;inflightTimeoutMs;constructor(e,t={}){this.manager=e,this.inflightTimeoutMs=t.inflightTimeoutMs??30000}async get(e){return await this.manager.get(e)}async mget(e){return await this.manager.mget(e)}async set(e,t,s){return await this.manager.set(e,t,s)}async mset(e){return await this.manager.mset(e)}async setForever(e,t){return await this.manager.set(e,t,0)}async getOrSet(e,t,s){let r=await this.manager.get(e);if(r!==void 0)return r;let i=this.inflight.get(e);if(i)return await i;let a=(async()=>{let m=await t();return await this.manager.set(e,m,s),this.manager.emit("fetch",e,m,s),m})(),o=()=>{if(this.inflight.get(e)===a)this.inflight.delete(e)};a.then(o,o);let u=this.inflightTimeoutMs,g=new Promise((m,T)=>{let f=setTimeout(()=>{o(),T(Error(`[cache] getOrSet('${e}') timed out after ${u}ms`))},u);a.then(()=>clearTimeout(f),()=>clearTimeout(f))});return this.inflight.set(e,a),await Promise.race([a,g])}async remember(e,t,s){return await this.getOrSet(e,s,t)}async rememberForever(e,t){return this.getOrSet(e,t,0)}async del(e){return await this.manager.del(e)}async has(e){return await this.manager.has(e)}async missing(e){return!await this.manager.has(e)}async remove(e){await this.manager.del(e)}async deleteMany(e){return await this.manager.del(e)}async clear(){await this.manager.flush()}async flush(){await this.manager.flush()}async keys(e){return await this.manager.keys(e)}async getTtl(e){return await this.manager.getTtl(e)}async ttl(e,t){return await this.manager.ttl(e,t)}async take(e){return await this.manager.take(e)}async getStats(){let e=await this.manager.getStats(),t=e.hits+e.misses;return{hits:e.hits,misses:e.misses,keys:e.keys,size:e.ksize+e.vsize,hitRate:t>0?e.hits/t:0}}async close(){await this.manager.close()}async disconnect(){await this.manager.close()}get cacheManager(){return this.manager}tags(e){return new n(this,e)}}class n{cache;tags;static TAG_PREFIX="__stacks_tag__:";static flushLocks=new Map;constructor(e,t){this.cache=e;this.tags=t;if(!t||t.length===0)throw Error("cache.tags(...) requires at least one tag")}tagKey(e){return`${n.TAG_PREFIX}${e}`}async indexKey(e){for(let t of this.tags){let s=this.tagKey(t),r=await this.cache.get(s)??[],i=new Set(r);if(!i.has(e))i.add(e),await this.cache.setForever(s,[...i])}}async put(e,t,s){let r=await this.cache.set(e,t,s);if(r)await this.indexKey(e);return r}async set(e,t,s){return this.put(e,t,s)}async setForever(e,t){let s=await this.cache.setForever(e,t);if(s)await this.indexKey(e);return s}async remember(e,t,s){let r=await this.cache.remember(e,t,s);return await this.indexKey(e),r}async rememberForever(e,t){let s=await this.cache.rememberForever(e,t);return await this.indexKey(e),s}async get(e){return this.cache.get(e)}async has(e){return this.cache.has(e)}async flush(){let e=0;for(let t of this.tags){let s=this.tagKey(t),r=n.flushLocks.get(s),i=r?r.catch(()=>0).then(()=>this.doFlushOne(s)):this.doFlushOne(s);n.flushLocks.set(s,i);try{e+=await i}finally{if(n.flushLocks.get(s)===i)n.flushLocks.delete(s)}}return e}async doFlushOne(e){let t=await this.cache.get(e)??[],s=0;if(t.length>0)s=await this.cache.del(t);return await this.cache.del(e),s}}function w(e={}){let t=d({driver:"memory",stdTTL:e.stdTTL??0,checkPeriod:e.checkPeriod??600,maxKeys:e.maxKeys??-1,useClones:e.useClones??!0,prefix:e.prefix});return new c(t)}function v(e={}){let t=d({driver:"redis",url:e.url,host:e.host??"localhost",port:e.port??6379,password:e.password,database:e.database??0,tls:e.tls??!1,stdTTL:e.stdTTL??0,prefix:e.prefix});return new c(t)}function b(e={}){let t=new l(e);return new c(t)}function _(e,t){if(e==="redis")return v(t);if(e==="singlestore")return b(t);return w(t)}var P=d({driver:"memory",stdTTL:0,checkPeriod:600,maxKeys:-1,useClones:!0}),x=new c(P),k=x;export{B as BatchOperations,U as CacheAsidePattern,G as CacheInvalidation,V as CacheLock,D as CacheManager,X as CircuitBreaker,I as MemoryDriver,W as MultiLevelPattern,j as RateLimiter,N as RedisDriver,z as RefreshAheadPattern,l as SingleStoreCacheStore,c as StacksCache,n as TaggedCache,H as WriteThroughPattern,k as cache,_ as createCache,w as createMemoryCache,v as createRedisCache,b as createSingleStoreCache,Y as memoize,x as memory};
2
+ import{createCache as d}from"@stacksjs/ts-cache";var{SQL:T}=globalThis.Bun;function p(e){return`\`${e.replace(/`/g,"``")}\``}class l{sql;table;qualified;prefix;stdTTL;ready=null;hits=0;misses=0;constructor(e={}){let{host:t="127.0.0.1",port:s=3306,username:r="root",password:i="",database:h="stacks",table:a="stacks_cache",ssl:o=!1}=e;this.table=a,this.qualified=p(a),this.prefix=e.prefix??"",this.stdTTL=e.stdTTL??0;let u=i?`${r}:${encodeURIComponent(i)}`:r,g=o?"?ssl=true":"";this.sql=new T(`mysql://${u}@${t}:${s}/${h}${g}`)}async ensureReady(){if(!this.ready)this.ready=this.sql.unsafe(`CREATE ROWSTORE TABLE IF NOT EXISTS ${this.qualified} ( cache_key VARCHAR(255) NOT NULL, value LONGTEXT NOT NULL, expires_at BIGINT NULL, PRIMARY KEY (cache_key) )`).then(()=>{return});await this.ready}k(e){return this.prefix?`${this.prefix}:${e}`:e}nowMs(){return Date.now()}expiryFor(e){let t=e??this.stdTTL;if(!t||t<=0)return null;return this.nowMs()+t*1000}async get(e){await this.ensureReady();let s=(await this.sql.unsafe(`SELECT value, expires_at FROM ${this.qualified} WHERE cache_key = ? LIMIT 1`,[this.k(e)]))[0];if(!s){this.misses++;return}if(s.expires_at!=null&&s.expires_at<=this.nowMs()){await this.del(e),this.misses++;return}return this.hits++,JSON.parse(s.value)}async mget(e){let t={};for(let s of e){let r=await this.get(s);if(r!==void 0)t[s]=r}return t}async set(e,t,s){await this.ensureReady();let r=this.expiryFor(s);return await this.sql.unsafe(`INSERT INTO ${this.qualified} (cache_key, value, expires_at) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE value = VALUES(value), expires_at = VALUES(expires_at)`,[this.k(e),JSON.stringify(t),r]),!0}async mset(e){for(let t of e)await this.set(t.key,t.value,t.ttl);return!0}async fetch(e,t,s){let r=await this.get(e);if(r!==void 0)return r;let i=await t();return await this.set(e,i,s),i}async del(e){await this.ensureReady();let t=Array.isArray(e)?e:[e];if(t.length===0)return 0;let s=t.map(()=>"?").join(", "),i=(await this.sql.unsafe(`DELETE FROM ${this.qualified} WHERE cache_key IN (${s})`,t.map((h)=>this.k(h)))).affectedRows;return typeof i==="number"?i:t.length}async has(e){return await this.get(e)!==void 0}async flush(){if(await this.ensureReady(),this.prefix)await this.sql.unsafe(`DELETE FROM ${this.qualified} WHERE cache_key LIKE ?`,[`${this.prefix}:%`]);else await this.sql.unsafe(`TRUNCATE TABLE ${this.qualified}`)}async keys(e){await this.ensureReady();let t=`${this.prefix?`${this.prefix}:`:""}${e?e.replace(/\*/g,"%"):"%"}`,s=await this.sql.unsafe(`SELECT cache_key FROM ${this.qualified} WHERE cache_key LIKE ? AND (expires_at IS NULL OR expires_at > ?)`,[t,this.nowMs()]),r=this.prefix?this.prefix.length+1:0;return s.map((i)=>r?i.cache_key.slice(r):i.cache_key)}async getTtl(e){await this.ensureReady();let s=(await this.sql.unsafe(`SELECT expires_at FROM ${this.qualified} WHERE cache_key = ? LIMIT 1`,[this.k(e)]))[0];if(!s)return;return s.expires_at==null?0:s.expires_at}async ttl(e,t){await this.ensureReady();let s=this.expiryFor(t);if(((await this.sql.unsafe(`UPDATE ${this.qualified} SET expires_at = ? WHERE cache_key = ?`,[s,this.k(e)])).affectedRows??0)>0)return!0;let i=await this.sql.unsafe(`SELECT 1 FROM ${this.qualified} WHERE cache_key = ? LIMIT 1`,[this.k(e)]);return Array.isArray(i)&&i.length>0}async take(e){let t=await this.get(e);if(t!==void 0)await this.del(e);return t}async getStats(){await this.ensureReady();let e=await this.sql.unsafe(`SELECT COUNT(*) AS n FROM ${this.qualified} WHERE expires_at IS NULL OR expires_at > ?`,[this.nowMs()]);return{hits:this.hits,misses:this.misses,keys:Number(e[0]?.n??0),ksize:0,vsize:0}}async close(){await this.sql.end()}}import{CacheManager as I,MemoryDriver as D,RedisDriver as N}from"@stacksjs/ts-cache";import{CacheAsidePattern as U,MultiLevelPattern as W,RefreshAheadPattern as H,WriteThroughPattern as z,BatchOperations as B,CacheInvalidation as G,CacheLock as V,CircuitBreaker as X,memoize as Y,RateLimiter as j}from"@stacksjs/ts-cache";class c{manager;inflight=new Map;inflightTimeoutMs;constructor(e,t={}){this.manager=e,this.inflightTimeoutMs=t.inflightTimeoutMs??30000}async get(e){return await this.manager.get(e)}async mget(e){return await this.manager.mget(e)}async set(e,t,s){return await this.manager.set(e,t,s)}async mset(e){return await this.manager.mset(e)}async setForever(e,t){return await this.manager.set(e,t,0)}async getOrSet(e,t,s){let r=await this.manager.get(e);if(r!==void 0)return r;let i=this.inflight.get(e);if(i)return await i;let a=(async()=>{let m=await t();return await this.manager.set(e,m,s),this.manager.emit("fetch",e,m,s),m})(),o=()=>{if(this.inflight.get(e)===a)this.inflight.delete(e)};a.then(o,o);let u=this.inflightTimeoutMs,g=new Promise((m,y)=>{let f=setTimeout(()=>{o(),y(Error(`[cache] getOrSet('${e}') timed out after ${u}ms`))},u);a.then(()=>clearTimeout(f),()=>clearTimeout(f))});return this.inflight.set(e,a),await Promise.race([a,g])}async remember(e,t,s){return await this.getOrSet(e,s,t)}async rememberForever(e,t){return this.getOrSet(e,t,0)}async del(e){return await this.manager.del(e)}async has(e){return await this.manager.has(e)}async missing(e){return!await this.manager.has(e)}async remove(e){await this.manager.del(e)}async deleteMany(e){return await this.manager.del(e)}async clear(){await this.manager.flush()}async flush(){await this.manager.flush()}async keys(e){return await this.manager.keys(e)}async getTtl(e){return await this.manager.getTtl(e)}async ttl(e,t){return await this.manager.ttl(e,t)}async take(e){return await this.manager.take(e)}async getStats(){let e=await this.manager.getStats(),t=e.hits+e.misses;return{hits:e.hits,misses:e.misses,keys:e.keys,size:e.ksize+e.vsize,hitRate:t>0?e.hits/t:0}}async close(){await this.manager.close()}async disconnect(){await this.manager.close()}get cacheManager(){return this.manager}tags(e){return new n(this,e)}}class n{cache;tags;static TAG_PREFIX="__stacks_tag__:";static flushLocks=new Map;constructor(e,t){this.cache=e;this.tags=t;if(!t||t.length===0)throw Error("cache.tags(...) requires at least one tag")}tagKey(e){return`${n.TAG_PREFIX}${e}`}async indexKey(e){for(let t of this.tags){let s=this.tagKey(t),r=await this.cache.get(s)??[],i=new Set(r);if(!i.has(e))i.add(e),await this.cache.setForever(s,[...i])}}async put(e,t,s){let r=await this.cache.set(e,t,s);if(r)await this.indexKey(e);return r}async set(e,t,s){return this.put(e,t,s)}async setForever(e,t){let s=await this.cache.setForever(e,t);if(s)await this.indexKey(e);return s}async remember(e,t,s){let r=await this.cache.remember(e,t,s);return await this.indexKey(e),r}async rememberForever(e,t){let s=await this.cache.rememberForever(e,t);return await this.indexKey(e),s}async get(e){return this.cache.get(e)}async has(e){return this.cache.has(e)}async flush(){let e=0;for(let t of this.tags){let s=this.tagKey(t),r=n.flushLocks.get(s),i=r?r.catch(()=>0).then(()=>this.doFlushOne(s)):this.doFlushOne(s);n.flushLocks.set(s,i);try{e+=await i}finally{if(n.flushLocks.get(s)===i)n.flushLocks.delete(s)}}return e}async doFlushOne(e){let t=await this.cache.get(e)??[],s=0;if(t.length>0)s=await this.cache.del(t);return await this.cache.del(e),s}}function w(e={}){let t=d({driver:"memory",stdTTL:e.stdTTL??0,checkPeriod:e.checkPeriod??600,maxKeys:e.maxKeys??-1,useClones:e.useClones??!0,prefix:e.prefix});return new c(t)}function v(e={}){let t=d({driver:"redis",url:e.url,host:e.host??"localhost",port:e.port??6379,password:e.password,database:e.database??0,tls:e.tls??!1,stdTTL:e.stdTTL??0,prefix:e.prefix});return new c(t)}function b(e={}){let t=new l(e);return new c(t)}function k(e,t){if(e==="redis")return v(t);if(e==="singlestore")return b(t);return w(t)}var P=d({driver:"memory",stdTTL:0,checkPeriod:600,maxKeys:-1,useClones:!0}),x=new c(P),_=x;export{B as BatchOperations,U as CacheAsidePattern,G as CacheInvalidation,V as CacheLock,I as CacheManager,X as CircuitBreaker,D as MemoryDriver,W as MultiLevelPattern,j as RateLimiter,N as RedisDriver,H as RefreshAheadPattern,l as SingleStoreCacheStore,c as StacksCache,n as TaggedCache,z as WriteThroughPattern,_ as cache,k as createCache,w as createMemoryCache,v as createRedisCache,b as createSingleStoreCache,Y as memoize,x as memory};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/cache",
3
3
  "type": "module",
4
- "version": "0.74.46",
4
+ "version": "0.74.48",
5
5
  "description": "Caching the Stacks way.",
6
6
  "author": "Chris Breuer",
7
7
  "contributors": [
@@ -62,6 +62,6 @@
62
62
  "@stacksjs/ts-cache": "^0.1.5"
63
63
  },
64
64
  "devDependencies": {
65
- "@stacksjs/config": "0.74.46"
65
+ "@stacksjs/config": "0.74.48"
66
66
  }
67
67
  }