Runtimes

Runtimes

Kaito v3+ was designed to work with any runtime, including serverless runtimes like Cloudflare Workers or the Vercel Edge Runtime.

Bun

Bun is the runtime most suited for Kaito, as it has the fastest Request/Response server built in.

import {createKaitoHandler} from '@kaito-http/core';
 
const handle = createKaitoHandler({
	// ...
});
 
const server = Bun.serve({
	fetch: handle,
	port: 3000,
});
 
console.log(`Listening at ${server.url}`);

Node.js

Node.js does NOT have a native Request/Response based HTTP server built in, so we built one ourselves! It’s based on uWebSockets.js, which is a stupidly fast HTTP server written in C++ with Node.js bindings. It’s actually the same server that Bun uses, so it offers almost as good performance as Bun.

Installation

bun i @kaito-http/uws

To be super clear, @kaito-http/uws works with Node.js only, we’re only using Bun as a package manager in the command above. You can use any other package manager like npm or yarn.

Usage

import {createKaitoHandler} from '@kaito-http/core';
import {KaitoServer} from '@kaito-http/uws';
 
const handle = createKaitoHandler({
	// ...
});
 
const server = await KaitoServer.serve({
	fetch: handle,
	port: 3000,
});
 
console.log(`Listening at ${server.url}`);

Deno

Deno supports the Fetch API natively, so you can use Kaito with Deno without any extra work.

import {createKaitoHandler} from '@kaito-http/core';
 
const handle = createKaitoHandler({
	// ...
});
 
const server = Deno.serve(
	{
		port: 3000,
	},
	handle,
);
 
console.log(`Listening on`, server.addr);

Cloudflare Workers

Cloudflare Workers supports the Fetch API natively, so you can use Kaito with Cloudflare Workers without any extra work.

import {createKaitoHandler} from '@kaito-http/core';
 
const handle = createKaitoHandler({
	// ...
});
 
export default {
	fetch: handle,
} satisfies ExportedHandler;

Environment variables

Cloudflare Workers passes environment variables to the handler function, which is a little awkward with Kaito. Our recommendation is to use AsyncLocalStorage to pass info between the handler and the router. This requires you to enable the node compatibility mode on your Cloudflare Worker.

import {AsyncLocalStorage} from 'node:async_hooks';
 
interface Env {
	STRIPE_SECRET_KEY: string;
}
 
// Recommendation is to move the storage instance to the `context.ts` file
// and include the value in your context object.
const storage = new AsyncLocalStorage<{
	env: Env;
	cfCtx: ExecutionContext; // has .waitUntil() and .passThroughOnException()
}>();
 
const app = router().get('/', async ({ctx}) => {
	return {
		freeStripeKey: ctx.env.STRIPE_SECRET_KEY, // obviously don't send your stripe key to the client lol
	};
});
 
const handle = createKaitoHandler({
	router: app,
	getContext: async req => {
		const store = storage.getStore()!;
		return {
			env: store.env,
			cfCtx: store.cfCtx,
		};
	},
	// ...
});
 
export default {
	fetch: async (request, env, ctx) => {
		return storage.run({env, cfCtx: ctx}, () => handle(request));
	},
} satisfies ExportedHandler<Env>;