import { HttpResponse, delay } from 'msw' /** Small, opinionated wrappers over MSW's response helpers used across handlers + tests. */ export function jsonResponse(body: T, init?: ResponseInit) { return HttpResponse.json(body as object, init) } export function errorResponse(status: number, message: string) { return HttpResponse.json({ error: message, status }, { status }) } export function noContent() { return new HttpResponse(null, { status: 204 }) } export function paginate(items: T[], page = 1, pageSize = items.length) { const start = (page - 1) * pageSize const slice = items.slice(start, start + pageSize) return { items: slice, totalCount: items.length, page, pageSize } } /** Inject latency into a handler. Use as: `await latency(50)` inside the resolver. */ export function latency(ms: number) { return delay(ms) } /** Build a Server-Sent-Events (SSE) `text/event-stream` body from a sequence of payloads. */ export function sse(events: Array<{ event?: string; data: unknown; id?: string }>) { const encoder = new TextEncoder() const stream = new ReadableStream({ start(controller) { for (const e of events) { const lines: string[] = [] if (e.id !== undefined) lines.push(`id: ${e.id}`) if (e.event !== undefined) lines.push(`event: ${e.event}`) const payload = typeof e.data === 'string' ? e.data : JSON.stringify(e.data) for (const line of payload.split('\n')) lines.push(`data: ${line}`) lines.push('', '') controller.enqueue(encoder.encode(lines.join('\n'))) } controller.close() }, }) return new HttpResponse(stream, { headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive', }, }) } /** Drop the connection mid-flight (used by resilience tests). */ export function dropResponse() { return HttpResponse.error() }