UNPKG

@supabase-cache-helpers/postgrest-server

Version:

A collection of server-side caching utilities for working with Supabase.

171 lines (170 loc) 4.01 kB
// src/stores/memory.ts var MemoryStore = class { state; capacity; name = "memory"; constructor(config) { this.state = config.persistentMap; this.capacity = config.capacity; } setMostRecentlyUsed(key, value) { this.state.delete(key); this.state.set(key, value); } async get(key) { const value = this.state.get(key); if (!value) { return Promise.resolve(void 0); } if (value.expires <= Date.now()) { await this.remove(key); } if (this.capacity) { this.setMostRecentlyUsed(key, value); } return Promise.resolve(value.entry); } async set(key, entry) { if (this.capacity) { this.setMostRecentlyUsed(key, { expires: entry.staleUntil, entry }); } else { this.state.set(key, { expires: entry.staleUntil, entry }); } if (this.capacity && this.state.size > this.capacity) { const oldestKey = this.state.keys().next().value; if (oldestKey !== void 0) { this.state.delete(oldestKey); } } return Promise.resolve(); } async remove(keys) { const cacheKeys = Array.isArray(keys) ? keys : [keys]; for (const key of cacheKeys) { this.state.delete(key); } return Promise.resolve(); } async removeByPrefix(prefix) { for (const key of this.state.keys()) { if (key.startsWith(prefix)) { this.state.delete(key); } } } async removeByPattern(pattern) { const regex = this.globToRegex(pattern); for (const key of this.state.keys()) { if (regex.test(key)) { this.state.delete(key); } } } /** * Convert a glob pattern to a regex, handling escaped characters. * Supports: * (any chars), ? (single char), \* \? \[ \] (literals) */ globToRegex(pattern) { let regex = "^"; let i = 0; while (i < pattern.length) { const char = pattern[i]; if (char === "\\" && i + 1 < pattern.length) { const next = pattern[i + 1]; regex += "\\" + next; i += 2; } else if (char === "*") { regex += ".*"; i++; } else if (char === "?") { regex += "."; i++; } else if (/[.+^${}()|[\]\\]/.test(char)) { regex += "\\" + char; i++; } else { regex += char; i++; } } regex += "$"; return new RegExp(regex); } }; // src/stores/redis.ts var RedisStore = class { redis; name = "redis"; prefix; constructor(config) { this.redis = config.redis; this.prefix = config.prefix || "sbch"; } buildCacheKey(key) { return [this.prefix, key].join("::"); } async get(key) { const res = await this.redis.get(this.buildCacheKey(key)); if (!res) return; return JSON.parse(res); } async set(key, entry) { await this.redis.set( this.buildCacheKey(key), JSON.stringify(entry), "PXAT", entry.staleUntil ); } async remove(keys) { const cacheKeys = (Array.isArray(keys) ? keys : [keys]).map( (key) => this.buildCacheKey(key).toString() ); this.redis.del(...cacheKeys); } async removeByPrefix(prefix) { const pattern = `${prefix}*`; let cursor = "0"; do { const [nextCursor, keys] = await this.redis.scan( cursor, "MATCH", pattern, "COUNT", 100 ); cursor = nextCursor; if (keys.length > 0) { await this.redis.del(...keys); } } while (cursor !== "0"); } async removeByPattern(pattern) { const fullPattern = this.buildCacheKey(pattern); let cursor = "0"; do { const [nextCursor, keys] = await this.redis.scan( cursor, "MATCH", fullPattern, "COUNT", 100 ); cursor = nextCursor; if (keys.length > 0) { await this.redis.del(...keys); } } while (cursor !== "0"); } }; export { MemoryStore, RedisStore }; //# sourceMappingURL=stores.js.map