import { Redis } from 'ioredis'; import { env } from '$env/dynamic/private'; export type RedisValue = string | number | boolean | object | null; interface RedisConfig { host: string; port: number; password?: string; db?: number; } class Cache { private redis: Redis; private _isReady: boolean; private readonly _readyPromise: Promise; constructor(config?: Partial) { const redisConfig: RedisConfig = { host: env.REDIS_HOST || '127.0.0.1', port: env.REDIS_PORT ? parseInt(env.REDIS_PORT) : 6379, password: env.REDIS_PASSWORD, db: env.REDIS_DB ? parseInt(env.REDIS_DB) : 0, ...config }; this.redis = new Redis(redisConfig); this._isReady = false; this._readyPromise = new Promise((resolve, reject) => { this.redis.on('ready', () => { this._isReady = true; resolve(true); }); this.redis.on('error', (err: Error) => { if (!this._isReady) reject(err); console.error('Redis error:', err); }); }); } async ready(): Promise { if (this._isReady) return true; return this._readyPromise; } async put(key: string, value: RedisValue, ttl?: number): Promise { await this.ready(); try { const serialized = JSON.stringify(value); if (ttl) { await this.redis.set(key, serialized, 'EX', ttl); } else { await this.redis.set(key, serialized); } return true; } catch (error) { console.error('Cache put error:', error); return false; } } async get( key: string, defaultValue: T | null = null ): Promise { await this.ready(); try { const value = await this.redis.get(key); return value ? (JSON.parse(value) as T) : defaultValue; } catch (error) { console.error('Cache get error:', error); return defaultValue; } } async has(key: string): Promise { await this.ready(); try { return (await this.redis.exists(key)) === 1; } catch (error) { console.error('Cache has error:', error); return false; } } async forget(key: string): Promise { await this.ready(); try { return (await this.redis.del(key)) > 0; } catch (error) { console.error('Cache forget error:', error); return false; } } async flush(): Promise { await this.ready(); try { await this.redis.flushdb(); return true; } catch (error) { console.error('Cache flush error:', error); return false; } } async forever(key: string, value: RedisValue): Promise { return this.put(key, value); } async remember( key: string, ttl: number, callback: () => Promise | T ): Promise { const cached = await this.get(key); if (cached !== null) return cached; const value = await callback(); await this.put(key, value, ttl); return value; } async rememberForever( key: string, callback: () => Promise | T ): Promise { return this.remember(key, 0, callback); } } const cache = new Cache(); export default cache;