Files
OmniRoute/src/lib/memory/cache.ts
diegosouzapw 592ca9b5c4 fix: remove hardcoded localhost default arg from GET /api/keys, unify coverage to single coverage/ dir, fix test to pass explicit Request
- Remove `new Request('http://localhost/api/keys')` default arg from GET handler in src/app/api/keys/route.ts (line 26)
- Fix api-key-reveal-route.test.mjs to pass explicit Request instead of calling GET() with no args
- Add --output-dir coverage to all c8 scripts in package.json
- Add coverage.reportsDirectory: 'coverage' to vitest.config.ts and vitest.mcp.config.ts
- Fix CHANGELOG.md structure (# Changelog + [Unreleased] to top)
- Remove 30+ stale coverage-* directories from project root
- Coverage: Statements 78.76% | Branches 72.75% | Functions 80.93% | Lines 78.76% (all thresholds passed)
2026-04-05 23:21:08 -03:00

77 lines
1.6 KiB
TypeScript

interface MemoryCache {
key: string;
value: unknown;
expiresAt: number;
}
class MemoryCachingLayer {
private cache: Map<string, MemoryCache> = new Map();
private maxSize: number = 1000;
private defaultTtl: number = 300000;
private hits: number = 0;
private misses: number = 0;
async get(key: string): Promise<unknown | null> {
const entry = this.cache.get(key);
if (!entry) {
this.misses += 1;
return null;
}
if (Date.now() > entry.expiresAt) {
this.cache.delete(key);
this.misses += 1;
return null;
}
this.hits += 1;
this.cache.delete(key);
this.cache.set(key, entry);
return entry.value;
}
async set(key: string, value: unknown, ttl?: number): Promise<void> {
if (this.cache.has(key)) {
this.cache.delete(key);
} else if (this.cache.size >= this.maxSize) {
const oldestKey = this.cache.keys().next().value;
if (oldestKey) {
this.cache.delete(oldestKey);
}
}
const now = Date.now();
this.cache.set(key, {
key,
value,
expiresAt: now + (ttl ?? this.defaultTtl),
});
}
async invalidate(pattern: string): Promise<void> {
const regex = new RegExp(pattern);
for (const key of this.cache.keys()) {
if (regex.test(key)) {
this.cache.delete(key);
}
}
}
async clear(): Promise<void> {
this.cache.clear();
this.hits = 0;
this.misses = 0;
}
stats() {
return {
size: this.cache.size,
maxSize: this.maxSize,
hits: this.hits,
misses: this.misses,
};
}
}
export const memoryCache = new MemoryCachingLayer();