import { expect, test } from "bun:test"; import { createDurableQueue, defineQueue, memoryQueueStore } from "../src/index.ts"; test("defineQueue creates typed producers and registers workers", async () => { const seen: number[] = []; const completed: number[] = []; const email = defineQueue({ name: "email", options: { store: memoryQueueStore() }, jobs: { send: { maxAttempts: 4, idempotency: (data: { messageId: number }) => `message:${data.messageId}`, validate: (data: unknown): data is { messageId: number } => typeof data === "object" && data !== null && Number.isInteger((data as { messageId?: unknown }).messageId), run: async ({ messageId }: { messageId: number }) => void seen.push(messageId), success: async ({ messageId }: { messageId: number }) => void completed.push(messageId), }, }, }); const first = await email.send.add({ messageId: 7 }); const duplicate = await email.jobs.send.add({ messageId: 7 }); expect(duplicate.id).toBe(first.id); expect(await email.send.status(first.id)).toBe("queued"); expect(await email.drain()).toBe(1); expect(seen).toEqual([7]); expect(completed).toEqual([7]); expect(await email.send.status(first.id)).toBe("completed"); }); test("durable queues expose lifecycle, health and events", async () => { const events: string[] = []; const queue = createDurableQueue({ pollMs: 10, onEvent: (event) => void events.push(event.type), }); queue.process("work", async () => {}); queue.start(); expect(queue.isRunning()).toBe(true); await queue.add("work", {}); await queue.drain(); const health = await queue.health(); expect(health.pending).toBe(0); expect(events).toContain("job.added"); expect(events).toContain("job.completed"); queue.stop(); expect(queue.isRunning()).toBe(false); await queue.shutdown(); }); test("defineQueue validates payloads before persistence", async () => { const queue = defineQueue({ name: "safe", jobs: { number: { validate: (data: unknown): data is number => typeof data === "number", run: async (_data: number) => {}, }, }, }); await expect(queue.number.add("no" as never)).rejects.toThrow("WRN-QUEUE-PAYLOAD"); });