Getting Started

A first useful chain needs only an install command, one middleware decision, and a fetch-compatible adapter.

Install

Add the package with the same package manager used by the project:

pnpm add alien-middleware

For srvx integration, install srvx too:

pnpm add alien-middleware srvx

Create a Chain

Import chain from the root entrypoint. Middleware runs in the order it is added.

import { chain } from 'alien-middleware'

const app = chain()
  .use(context => {
    console.log('request', context.request.method, context.url.pathname)
  })
  .use(() => {
    return new Response('ok')
  })

The first middleware returns nothing, so the next middleware runs. The second middleware returns a Response, so request-phase middleware after it would be skipped.

Serve with srvx

Use the srvx adapter when serve calls your handler with a srvx ServerRequest.

import { serve } from 'srvx'
import { chain } from 'alien-middleware'
import { toFetchHandler } from 'alien-middleware/srvx'

const app = chain().use(() => new Response('hello'))

serve({
  port: 3000,
  fetch: toFetchHandler(app),
})

After the server starts, GET / receives hello.

Run Without srvx

If your host calls a plain Web fetch handler, use toFetchHandler from the root entrypoint.

import { chain, toFetchHandler } from 'alien-middleware'

const app = chain().use(context => {
  return new Response(context.url.pathname)
})

export default {
  fetch: toFetchHandler(app),
}

Pass host data when middleware needs environment values, client IP, runtime metadata, or background work support.

const fetch = toFetchHandler(app, {
  host: request => ({
    env: name => process.env[name],
    runtime: { name: 'node' },
    waitUntil: promise => {
      void promise
    },
  }),
})

Add Typed Environment Values

Declare environment variables on the chain when downstream middleware should read them with a precise type.

type Env = {
  API_KEY: string
}

const app = chain<Env>().use(context => {
  const key = context.env('API_KEY')
  return new Response(key.slice(0, 3))
})

The key variable is typed as string. Trying to read an undeclared key is a type error unless your context type deliberately allows it.

Next Steps

Use Writing Middleware for request plugins, response callbacks, and isolated chains. Use Routing Requests when you need path parameters or method-specific handlers.

The first chain is tiny, but the Martians from Mars Attacks would still ask if it comes in green.