Test library version

This commit is contained in:
2025-07-10 16:04:02 +03:00
parent c4ceb86b91
commit e23dc59bdf
6 changed files with 206 additions and 2 deletions

View File

@@ -1 +1,5 @@
// Reexport your entry components here
import Cache from '$lib/server/cache.js';
export { Cache };

35
src/lib/server/cache.ts Normal file
View File

@@ -0,0 +1,35 @@
import cache from './redis.js';
import type { RedisValue } from './redis.js';
interface CacheFacade {
ready(): Promise<boolean>;
put<T extends RedisValue>(key: string, value: T, ttl?: number): Promise<boolean>;
get<T extends RedisValue = RedisValue>(key: string, defaultValue?: T | null): Promise<T | null>;
has(key: string): Promise<boolean>;
forget(key: string): Promise<boolean>;
flush(): Promise<boolean>;
forever<T extends RedisValue>(key: string, value: T): Promise<boolean>;
remember<T extends RedisValue>(
key: string,
ttl: number,
callback: () => Promise<T> | T
): Promise<T>;
rememberForever<T extends RedisValue>(key: string, callback: () => Promise<T> | T): Promise<T>;
}
const Cache: CacheFacade = {
ready: () => cache.ready(),
put: <T extends RedisValue>(key: string, value: T, ttl?: number) => cache.put(key, value, ttl),
get: <T extends RedisValue = RedisValue>(key: string, defaultValue?: T | null) =>
cache.get<T>(key, defaultValue),
has: (key: string) => cache.has(key),
forget: (key: string) => cache.forget(key),
flush: () => cache.flush(),
forever: <T extends RedisValue>(key: string, value: T) => cache.forever(key, value),
remember: <T extends RedisValue>(key: string, ttl: number, callback: () => Promise<T> | T) =>
cache.remember(key, ttl, callback),
rememberForever: <T extends RedisValue>(key: string, callback: () => Promise<T> | T) =>
cache.rememberForever(key, callback)
};
export default Cache;

133
src/lib/server/redis.ts Normal file
View File

@@ -0,0 +1,133 @@
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<boolean>;
constructor(config?: Partial<RedisConfig>) {
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<boolean>((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<boolean> {
if (this._isReady) return true;
return this._readyPromise;
}
async put(key: string, value: RedisValue, ttl?: number): Promise<boolean> {
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<T extends RedisValue = RedisValue>(
key: string,
defaultValue: T | null = null
): Promise<T | null> {
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<boolean> {
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<boolean> {
await this.ready();
try {
return (await this.redis.del(key)) > 0;
} catch (error) {
console.error('Cache forget error:', error);
return false;
}
}
async flush(): Promise<boolean> {
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<boolean> {
return this.put(key, value);
}
async remember<T extends RedisValue>(
key: string,
ttl: number,
callback: () => Promise<T> | T
): Promise<T> {
const cached = await this.get<T>(key);
if (cached !== null) return cached;
const value = await callback();
await this.put(key, value, ttl);
return value;
}
async rememberForever<T extends RedisValue>(
key: string,
callback: () => Promise<T> | T
): Promise<T> {
return this.remember(key, 0, callback);
}
}
const cache = new Cache();
export default cache;