@repo/queue
A type-safe, schema-driven queue abstraction for Node.js.
- Job definitions as values
- Payload types inferred from schemas
- Queue-agnostic core with adapter-based backends
- Separate client and worker concerns
- Inspired by Laravel queues, built for TypeScript
Installation
npm install @repo/queue
Install a queue backend adapter as needed:
npm install pg-boss
Defining a Job
import { createJob } from "@repo/queue";
import { z } from "zod";
export const sendEmailsJob = createJob("send-emails", {
input: z.object({
email: z.string().email(),
subject: z.string(),
body: z.string(),
}),
handler: async ({ email, subject, body }, ctx) => {
// payload is fully typed
},
hooks: {
onError: (err, payload, ctx) => {},
onFailed: (err, payload, ctx) => {},
onSuccess: (result, payload, ctx) => {},
},
});
payloadtype is inferred from the schemahandlerreceives parsed/validated input- hooks are fully typed
Creating the Queue Runtime
import { createQueueRuntime } from "@repo/queue";
import { createPgBossAdapter } from "@repo/queue/adapters/pg-boss";
import { sendEmailsJob } from "./jobs/sendEmails.job";
export const queueRuntime = createQueueRuntime({
queues: [
{ name: "low", priority: 0 },
{ name: "high", priority: 10 },
],
adapter: createPgBossAdapter({
connectionString: process.env.DATABASE_URL,
}),
workers: [
{
job: sendEmailsJob,
concurrency: 10,
queues: ["low"],
},
],
});
Running Workers
Start listening to the workers in Svelte.
// hooks.server.ts
queueRuntime.startWorkers();
Dispatching Jobs (Client)
// src/lib/queue/queueClient.server.ts
const queueClient = queueRuntime.createClient();
await queueClient.dispatch(
sendEmailsJob,
{ email, subject, body },
);
- Dispatch is type-safe
- Payload must match the job schema
- Queue names are validated at compile time
There is a third argument you can pass for more context:
await queueClient.dispatch(
sendEmailsJob,
{ email, subject, body },
{ maxAttempts: 5, queue: "low" }
);
Adapters
The core is queue-agnostic. Backends are provided via adapters.
Currently supported:
pg-boss
Adapters are optional peer dependencies and only required if you use them.
Design Notes
- Jobs are first-class values, not strings
- Schemas define both runtime validation and TypeScript types
- No decorators, no DI container, no global registry
- Client and worker responsibilities are explicit