Release candidate — 1.0.0-rc.1
StitchAPI
Integrations

Hono

Edge-ready Hono middleware for StitchAPI — a principal-bound seam on c.var.stitch, an SSE bridge with streamStitchSse, and stitch errors mapped to HTTPException.

Use @stitchapi/hono when you serve an API with Hono on the edge or across runtimes. It is three thin bridges between StitchAPI's backend primitive (the seam) and Hono's Fetch-based request model: middleware that puts a principal-bound seam on the request context, an SSE helper, and a stitch-error → HTTP mapper.

Edge/multi-runtime by construction. Every import is from hono or stitchapi; there are no node:* imports, so the package runs unchanged on Node, Cloudflare Workers, Deno, Bun, and Vercel Edge.

Example

Install the package alongside core and Hono:

npm install @stitchapi/hono stitchapi hono

Build (and own) the seam once at startup, then register the middleware. With a principal resolver, each request's c.var.stitch is a seam.as(id) handle — a principal-bound seam with separate auth sessions per principal over one shared throttle. Parametrise your app with StitchEnv so c.get('stitch') is typed:

import { type StitchEnv,  } from '@stitchapi/hono';
import {  } from 'hono';
import {  } from 'stitchapi';
import {  } from 'zod';

const  = ({ : 'https://api.example.com' });

const  = new <StitchEnv>();

// Put a principal-bound seam on every request's context.
.(({ : , : () => ..('x-tenant') }));

.('/me', async () => {
    const  = await .('stitch').({
        : '/me',
        : .({ : .(), : .() }),
    })();
    return .();
});

The principal lives in the closure, never in a call argument, so a handler can never name another identity. Borrow, don't own: the middleware never calls seam.close() — you build the seam at startup and close it on shutdown.

Streaming — streamStitchSse

Stream a streaming/SSE stitch's .stream() to the client as Server-Sent Events, via Hono's streamSSE. Each delta becomes a data: message; a terminal error (or a throw) becomes a final event: error message; control events are consumed but not forwarded; and a client disconnect aborts the upstream stitch stream.

import { type StitchEnv, ,  } from '@stitchapi/hono';
import {  } from 'hono';
import {  } from 'stitchapi';
import {  } from 'stitchapi/sse';

const  = ({ : 'https://api.example.com' });

const  = new <StitchEnv>();
.(({ :  }));

.('/chat', () => {
    const  = 
        .('stitch')
        .({ : , : '/v1/messages' });
    return (
        ,
        .({ : { : ..('q') } }),
        { : () => ( as { : string }). },
    );
});

Errors — stitchOnError

A failed stitch rejects with a StitchError carrying the upstream status. Register stitchOnError() as your app's onError so handlers need no per-route try/catch — it maps a StitchError to a Hono HTTPException (502 by default, so an upstream's status is never leaked) and rethrows everything else:

import {  } from '@stitchapi/hono';
import {  } from 'hono';

const  = new ();

// default 502 — an upstream's 401/404/etc. is never leaked to your client.
.(());

// or propagate the upstream status instead:
.(({ : () => . ?? 502 }));

Or map a single error by hand with stitchError(err), which returns an HTTPException — or undefined for a non-Stitch error, so you can rethrow it untouched.

On Cloudflare Workers and other multi-runtime deployments, pair the seam with a shared store (e.g. @stitchapi/redis) so throttle and sessions are fleet-wide rather than per-isolate.

See also

On this page