Portable
A web handler receives the standard Request and answers with a standard Response. The HTTP library underneath is a small adapter you can swap.
Runtimes
A tiny decorator-based framework for HTTP and command-line applications. Standard decorators, no reflection, the same code on Deno, Node.js, Bun and the edge.
An HTTP application:
import {
ChoWeb,
type ChoWebContext,
Controller,
Get,
Injectable,
Module,
} from "@chojs/web";
import { HonoLinker } from "@chojs/vendor-hono";
@Injectable()
class UserStore {
find(id: string) {
return { id, name: "Ada" };
}
}
@Controller({ route: "users", dependencies: [UserStore] })
class UsersController {
constructor(readonly store: UserStore) {}
@Get(":id") // GET /users/42
get(ctx: ChoWebContext) {
return this.store.find(ctx.params.id!); // sent as JSON
}
}
@Module({ providers: [UserStore], controllers: [UsersController] })
class App {}
const app = await ChoWeb.create(App, { linker: new HonoLinker() });Then serve app.handler with whatever the runtime has:
Deno.serve(app.handler);Bun.serve({ fetch: app.handler });import { serve } from "@hono/node-server";
serve({ fetch: app.handler, port: 3000 });A command-line application, with the same modules, controllers and providers:
import {
Action,
ChoCommand,
type ChoCommandContext,
Controller,
Help,
Module,
} from "@chojs/command";
@Controller()
class Greeter {
@Help("Say hello")
@Action("hello", { string: ["name"] })
hello(ctx: ChoCommandContext) {
console.log(`Hello, ${ctx.args.name ?? "world"}!`);
}
}
@Module({ controllers: [Greeter] })
class App {}
const app = ChoCommand.create(App, { name: "greet" });
const code = await app.run(Deno.args); // Node.js, Bun: process.argv.slice(2)