import { mkdir, mkdtemp } from 'node:fs/promises'; import path from 'node:path'; import { createHash } from 'node:crypto'; import { SetStore, type ImagePipeline } from '../../src/storage/sets.ts'; export const SECTIONS = ['bar', 'food'] as const; /** Deterministic stand-in for sharp, so storage tests need no image work. */ export class FakePipeline implements ImagePipeline { calls = 0; async process(data: Buffer, _originalName: string) { this.calls += 1; const hash = createHash('sha256').update(data).digest('hex').slice(0, 8); return { sourceExt: 'jpg' as const, hash, width: 3000, height: 2000, original: data, webp: Buffer.from(`webp:${hash}`), jpeg: Buffer.from(`jpeg:${hash}`), thumb: Buffer.from(`thumb:${hash}`), }; } } export function testClock(start = '2026-01-01T00:00:00.000Z') { let time = Date.parse(start); return { now: () => new Date(time), advance: (ms: number) => { time += ms; }, set: (iso: string) => { time = Date.parse(iso); }, }; } export async function tempDir(prefix: string): Promise { const base = path.join(process.cwd(), '.tmp'); await mkdir(base, { recursive: true }); return mkdtemp(path.join(base, `${prefix}-`)); } export function makeStore( dataDir: string, options: { clock?: ReturnType; maxPagesPerSet?: number } = {}, ) { const pipeline = new FakePipeline(); const clock = options.clock ?? testClock(); const store = new SetStore({ dataDir, pipeline, sections: [...SECTIONS], maxPagesPerSet: options.maxPagesPerSet ?? 40, timeZone: 'Asia/Kolkata', now: clock.now, }); return { store, pipeline, clock }; } export function pngBytes(label: string): Buffer { return Buffer.from(`fake-image:${label}`); }