Compose tasks and resources with predictable lifecycle, testing hooks, and runtime control
Runner is a TypeScript-first framework for building applications from tasks (functions) and resources (singletons), with explicit dependency injection, middleware, events, hooks, and lifecycle management.
import { r, run } from "@bluelibs/runner";
import { z } from "zod";
const db = r
.resource("app.db")
.init(async () => ({
users: {
insert: async (input: { name: string; email: string }) => ({
id: "user-1",
...input,
}),
},
}))
.build();
const mailer = r
.resource("app.mailer")
.init(async () => ({
sendWelcome: async (email: string) => {
console.log(`Sending welcome email to ${email}`);
},
}))
.build();
// Define a task with dependencies, schema validation, and type-safe input/output
const createUser = r
.task("users.create")
.dependencies({ db, mailer })
.inputSchema(z.object({ name: z.string(), email: z.string().email() }))
.run(async (input, { db, mailer }) => {
const user = await db.users.insert(input);
await mailer.sendWelcome(user.email);
return user;
})
.build();
// Compose resources and run your application
const app = r.resource("app").register([db, mailer, createUser]).build();
const runtime = await run(app);
await runtime.runTask(createUser, { name: "Ada", email: "ada@example.com" });
// await runtime.dispose() when you are done.
| Resource | Type | Description |
|---|---|---|
| Presentation Website | Website | Overview and features |
| GitHub Repository | GitHub | Source code, issues, and releases |
| Runner Dev Tools | GitHub | Development CLI and tooling |
| API Documentation | Docs | TypeDoc-generated reference |
| AI-Friendly Docs | Docs | Compact summary (<5000 tokens) |
| Full Guide | Docs | Complete documentation (composed) |
| Design Documents | Docs | Architecture notes and deep dives |
| Example: Express + OpenAPI + SQLite | Example | REST API with OpenAPI specification |
| Example: Fastify + MikroORM + PostgreSQL | Example | Full-stack application with ORM |
fetch runtime)| Capability | Node.js | Browser | Edge | Notes |
|---|---|---|---|---|
| Core runtime (tasks/resources/events/hooks) | Full | Full | Full | Platform adapters hide runtime differences |
Async Context (r.asyncContext) |
Full | None | None | Requires Node.js AsyncLocalStorage |
Durable workflows (@bluelibs/runner/node) |
Full | None | None | Node-only module |
Tunnels client (createExposureFetch) |
Full | Full | Full | Requires fetch |
Tunnels server (@bluelibs/runner/node) |
Full | None | None | Exposes tasks/events over HTTP |
New to Runner? Here's the absolute minimum you need to know:
init / dispose)app resource with .register([...])run(app) which gives you runTask() and dispose()That's it. Now let's get you to a first successful run.
This is the fastest way to run the TypeScript example at the top of this README:
npm i @bluelibs/runner zod
npm i -D typescript tsx
index.tsnpx tsx index.ts
That’s it! You now have a working Runtime and you can execute tasks with runtime.runTask(...).
Tip: If you prefer an end-to-end example with HTTP, OpenAPI, and persistence, jump to the examples below.
guide-units/)This project is licensed under the MIT License - see LICENSE.md.