Skip to content
cho-jsPublic

About

The only cross-platform, cross-runtime, decorator-based framework for building modular applications in JavaScript and TypeScript.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

9 stars

Watchers

1 watching

Forks

Repository files navigation

Nest Logo

The only cross-platform, cross-runtime, decorator-based framework for building modular applications in JavaScript and TypeScript.

Release CI License: MIT

CHO

Package Version For
@chojs/web JSR HTTP applications
@chojs/command JSR Command-line applications
@chojs/vendor-cho JSR Middlewares for the built-in router of @chojs/web, such as CORS
@chojs/vendor-hono JSR Running @chojs/web on Hono
@chojs/vendor-fastify JSR Running @chojs/web on Fastify (Node.js only)
@chojs/core JSR The dependency injection engine underneath

CHO is a tiny decorator-based framework for building modular applications. It uses modern JavaScript decorators (see About JavaScript Decorators) to provide a clean and efficient way to define the structure of an application.

The concept is inspired by Angular, NestJS and Spring, but with a different approach (or why this project exists):

Portability (Cross-Platform/Engine Agnostic)

In the modern software development landscape, the ability to deploy applications across various environments and platforms is crucial. Developers often face challenges when trying to ensure that their applications run seamlessly on different runtimes such as Node.js, Deno, Bun, Cloudflare Workers, AWS Lambda and more. Each of these runtimes has its own set of features, performance characteristics and limitations, making it difficult to write code that is truly portable.

CHO keeps application code away from all of that. A web handler receives the standard Request and answers with a standard Response; the HTTP library underneath is a small adapter you can swap. The framework itself uses no runtime-specific API, and every change is tested on Deno, Node.js and Bun. (An adapter may support fewer runtimes than the framework: each one says which.)

Standardization

Decorators and reflect metadata are not yet part of the official ECMAScript standard, leading to inconsistencies in their implementation across different runtimes (TS experimental vs TC39 proposal, for example). This lack of standardization can result in compatibility issues and hinder the adoption of these features in different production environments. This project aims to provide a consistent and reliable way to use decorators across multiple JavaScript runtimes, ensuring that developers can leverage these powerful features without worrying about compatibility issues.

The same CHO application runs with standard (TC39) decorators and with legacy or Bun decorators. It needs no reflect-metadata and no compiler plugin: dependencies are declared explicitly, and still checked against the constructor at compile time.

Build for Performance

Minimalistic and optimized for performance!

There is no reflection at runtime. The whole module graph is validated and linked once, when the application starts, so creating an instance afterwards needs no lookup, and a mistake in the wiring never waits for the first request to show up.


A quick look

An HTTP application:

import {
    ChoWeb,
    type ChoWebContext,
    Controller,
    Get,
    Injectable,
    Module,
} from "@chojs/web";

@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);
Deno.serve(app.handler); // Bun: Bun.serve({ fetch: app.handler })

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"});
Deno.exit(await app.run(Deno.args)); // greet hello --name you

Getting started

Pick the package for what you are building; it brings everything an application needs.

# an HTTP application
deno add jsr:@chojs/web
npx jsr add @chojs/web
bunx jsr add @chojs/web

# a command-line application
deno add jsr:@chojs/command
npx jsr add @chojs/command
bunx jsr add @chojs/command

@chojs/web has a router built in, on the standard URL Pattern API, so an HTTP application needs nothing else. To match requests with another HTTP library, give ChoWeb.create the linker of an adapter:

Router Runs on
Built in Runtimes with URLPattern: Deno, Node.js 24, Bun 1.3.4, Cloudflare Workers
@chojs/vendor-hono Deno, Node.js, Bun and edge runtimes
@chojs/vendor-fastify Node.js only

Deno and Bun run TypeScript decorators directly. On Node.js, compile the application with TypeScript 5 or run it with a tool such as tsx.

Documentation

Package Guide Specification
@chojs/web README specs
@chojs/command README specs
@chojs/vendor-cho README
@chojs/vendor-hono README
@chojs/vendor-fastify README
@chojs/core README specs

Runnable examples are in examples/.

Contributing

Contributions are welcome: see CONTRIBUTING.md and the code of conduct.

License

MIT

About JavaScript Decorators

This project uses the TC39 stage 3 decorators proposal (JavaScript decorators).

蝶

About

The only cross-platform, cross-runtime, decorator-based framework for building modular applications in JavaScript and TypeScript.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

9 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Contributors

Languages