import { readVoiceFields } from '../src/core/note'; import type { Env, ListedNote, NoteStore, RecordingStore, TranscribeResult, Transcriber, } from '../src/core/ports'; export class MemoryRecordings implements RecordingStore { files = new Map(); async write(path: string, data: ArrayBuffer): Promise { this.files.set(path, data.slice(0)); } async read(path: string): Promise { const data = this.files.get(path); if (!data) throw new Error(`no such file: ${path}`); return data.slice(0); } } export class MemoryNotes implements NoteStore { files = new Map(); // Имитация отстающего metadataCache: если задано, list() возвращает это. staleList: ListedNote[] | null = null; listCalls = 0; async exists(path: string): Promise { return this.files.has(path); } async create(path: string, content: string): Promise { if (this.files.has(path)) throw new Error(`already exists: ${path}`); this.files.set(path, content); } async list(): Promise { this.listCalls++; if (this.staleList) return this.staleList; return [...this.files] .map(([path, content]) => ({ path, frontmatter: readVoiceFields(content) as Record })) .filter((note) => 'voice-id' in note.frontmatter); } async process(path: string, fn: (content: string) => string): Promise { const content = this.files.get(path); if (content === undefined) return false; this.files.set(path, fn(content)); return true; } } export type Step = | TranscribeResult | Error | ((audio: ArrayBuffer, mime: string) => Promise); export class ScriptedTranscriber implements Transcriber { calls: { audio: ArrayBuffer; mime: string; signal: AbortSignal }[] = []; constructor(public steps: Step[] = []) {} async transcribe(audio: ArrayBuffer, mime: string, signal: AbortSignal): Promise { this.calls.push({ audio, mime, signal }); const step = this.steps.shift(); if (step === undefined) throw new Error('ScriptedTranscriber: no more steps'); if (step instanceof Error) throw step; if (typeof step === 'function') return step(audio, mime); return step; } } export class TestEnv implements Env { constructor( public time = new Date('2026-09-27T11:15:03.000Z'), public deviceId = 'test-device', public random: () => number = () => 0, ) {} now(): Date { return new Date(this.time); } advance(ms: number): void { this.time = new Date(this.time.getTime() + ms); } }