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. It’s the runtime with 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';
 
// Recommendation is to move the storage and getStore function to the context.ts file, and include the env in your context object.
const storage = new AsyncLocalStorage<{
	env: Record<string, string>;
	cfCtx: ExecutionContext; // has .waitUntil() and .passThroughOnException()
}>();
 
const getStore = () => {
	const value = storage.getStore();
	if (!value) throw new Error('No store found');
	return value;
};
 
const app = router().get('/', async ({ctx}) => {
	return {
		env: ctx.env,
	};
});
 
const handle = createKaitoHandler({
	router: app,
	getContext: async req => {
		const store = getStore();
		return {env: store.env, cfCtx: store.cfCtx};
	},
	// ...
});
 
export default {
	fetch: async (request, env) => storage.run({env}, () => handle(request)),
};