A portable, typed request pipeline on Web-standard Request/Response.
NestJS-style lifecycle (guards · interceptors · serializers), zero framework lock-in.
📚 Documentation · Getting started · API reference
Runs natively on Bun · Deno · Cloudflare Workers · Next.js route handlers · Hono. One thin adapter for Express / Fastify.
import { pipe, ok } from 'pipeway'
import { body } from 'pipeway-steps'
import { z } from 'zod'
export const POST = pipe()
.use(async (ctx) => ok({ user: await authenticate(ctx.req) })) // guard → typed ctx
.use(body(z.object({ title: z.string() }))) // validation → typed body
.transform((res) => { res.headers.set('x-app', 'pipeway'); return res }) // interceptor
.handle(({ user, body }) => ({ created: body.title, by: user.id }))
// → (req: Request, params) => Promise<Response>- Portable. Your handler is
(Request) => Response. Mount it on any Web-standard runtime as-is; no rewrite when you switch from Next to Bun to Workers. - NestJS ergonomics, no Nest. Guards, interceptors, exception filters, serializers — as plain composable functions. No classes, no decorators, no DI container.
- Order enforced at compile time. A step that needs
userin context cannot be placed before the step that adds it. TypeScript rejects it. - Result-first. Return a domain
Result<T, E>and map errors to responses in one place. No exceptions-as-control-flow.
pipe()
.use(rateLimit) // ❌ Type error: rateLimit needs { user }, not in context yet
.use(auth) // add auth firstThe pipeline's context type accumulates as you .use(). A step declares what it
needs; if the current context doesn't satisfy it, it's a type error — not a
runtime surprise.
| Runtime | Adapter |
|---|---|
Bun (Bun.serve) |
none — mount directly |
Deno (Deno.serve) |
none |
| Cloudflare Workers | none |
| Next.js route handlers | none |
| Hono | none (c.req.raw) |
| Express / Fastify / Node http | pipeway-adapter-node |
| Package | What |
|---|---|
pipeway |
the pipeline core (use · map · catch · serialize · transform · handle · json) |
pipeway-steps |
Standard Schema steps — body, query (Zod / Valibot / ArkType) |
pipeway-adapter-node |
Express/Fastify/Node bridge |
pipeway-client |
portable Result-first REST client (unwrap for React Query / SWR) |
pipeway-next |
typed pipeline for Next.js server actions |
Routing · DI container · ORM · its own validation library. pipeway is a pipeline you mount into your router, not a framework.
MIT © Pierre-Philippe Prévost