Build apps from tasks and resources with explicit dependencies, predictable lifecycle, and first-class testing
Runner is a TypeScript-first toolkit for building an app out of small, typed building blocks. You can find more details and a visual overview at runner.bluelibs.com.
dependencies, middleware, and input/output validationinit/dispose lifecycle (databases, clients, servers, caches)retry, timeout, circuitBreaker, cache, and rateLimitapp predictablyThe goal is simple: keep dependencies explicit, keep lifecycle predictable, and make your runtime easy to control in production and in tests.
import { r, run, globals } from "@bluelibs/runner";
import { z } from "zod";
// resources are singletons with lifecycle management and async construction
const db = r
.resource("app.db")
.init(async () => {
const conn = await postgres.connect(process.env.DB_URL);
return conn;
})
.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, middleware, and zod validation
const createUser = r
.task("users.create")
.dependencies({ db, mailer })
.middleware([globals.middleware.task.retry.with({ retries: 3 })])
.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") // top-level app resource
.register([db, mailer, createUser]) // register all elements
.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 |
|---|---|---|
| Official Website & Documentation | 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) |
| Support & Release Policy | Docs | Support windows and deprecation |
| 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/middleware/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 (createHttpClient) |
Full | Full | Full | Requires fetch |
Tunnels server (@bluelibs/runner/node) |
Full | None | None | Exposes tasks/events over HTTP |
Use these minimums before starting:
| Requirement | Minimum | Notes |
|---|---|---|
| Node.js | 18.x |
Enforced by package.json#engines.node |
| TypeScript | 5.6+ (recommended) |
Required for typed DX and examples in this repository |
| Package manager | npm / pnpm / yarn / bun | Examples use npm, but any modern package manager works |
fetch runtime |
Built-in or polyfilled | Required for tunnel clients (createHttpClient, universal HTTP client) |
If you use the Node-only package (@bluelibs/runner/node) for durable workflows or exposure, stay on a supported Node LTS line.
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:
Confirm prerequisites from Prerequisites (Node 18+, TypeScript 5.6+ recommended)
Install dependencies:
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.
@bluelibs/runner-dev gives you CLI scaffolding and runtime introspection.
npm install -g @bluelibs/runner-dev
# or
npx @bluelibs/runner-dev --help
# Scaffold a new Runner project
runner-dev new my-app --install
# Query tasks from a local TypeScript entry file (dry-run mode)
runner-dev query 'query { tasks { id } }' --entry-file ./src/main.ts
# Inspect a running app via GraphQL endpoint
ENDPOINT=http://localhost:1337/graphql runner-dev overview --details 10
For full CLI and Dev UI docs, see Runner Dev Tools.
guide-units/)This project is licensed under the MIT License - see LICENSE.md.