routing-controllers -like library for the Oak
framework (jsr:@oak/oak
) 🚗 🐿️ 🦕
@Controller("/api/v1/pokemon")
class MyPokedex {
@Get("/:id")
viewEntry(ctx) {
if (ctx.params.id === "0025") return "Pikachu";
}
}
If you're familiar with the npm library routing-controllers, you'll find yourself very much at home.
However, please note that this libray is not meant to be a drop-in replacement for routing-controllers, as it attempts to conform to TC39 Decorators proposal which doesn't support Method Parameter Decorator yet. There's currently no plan to support TypeScript "experimental" decorators, but if you feel strongly for it, please feel free to fork this repo!
For easy reading, the examples below do not specify any explicit version when installing library dependencies. But in your production code, it's advisable to pin every dependency to a specific version.
Prerequisite: Deno
deno add @oak/oak @dklab/oak-routing-ctrl
// main.ts
import { Application } from "@oak/oak/application";
import {
Controller,
ControllerMethodArgs,
Get,
useOakServer,
} from "@dklab/oak-routing-ctrl";
const app = new Application();
@Controller("/v1")
class MyController {
@Get("/hello/:name")
@ControllerMethodArgs("param")
hello(param) {
return `hello, ${param.name}`;
}
}
useOakServer(app, [MyController]);
await app.listen({ port: 1993 });
deno run --allow-env --allow-net main.ts
# in another terminal
curl localhost:1993/v1/hello/world # prints: hello, world
View Example
import { Application } from "@oak/oak/application";
import {
Controller,
ControllerMethodArgs,
Post,
useOakServer,
} from "@dklab/oak-routing-ctrl";
@Controller("/v1")
class MyController {
@Post("/tell/:name")
@ControllerMethodArgs("param", "body")
tell(param, body) {
return `telling ${param.name} that "${body.message}"`;
}
}
const app = new Application();
useOakServer(app, [MyController]);
await app.listen({ port: 1993 });
_
curl -H"Content-Type: application/json" localhost:1993/v1/tell/alice -d'{"message": "all we need is love"}'
# prints: telling alice that "all we need is love"
View Example
import { Application } from "@oak/oak/application";
import {
Controller,
ControllerMethodArgs,
Get,
useOakServer,
} from "@dklab/oak-routing-ctrl";
@Controller("/v1")
class MyController {
@Get("/books/:category")
@ControllerMethodArgs("query", "param")
search(query, param) {
return `searching for books in category "${param.category}" with query "page=${query.page}"`;
}
}
const app = new Application();
useOakServer(app, [MyController]);
await app.listen({ port: 1993 });
_
curl localhost:1993/v1/books/thriller\?page=2
# prints: searching for books in category "thriller" with query "page=2"
View Example
import { Application } from "@oak/oak/application";
import { Controller, Get, useOakServer } from "@dklab/oak-routing-ctrl";
@Controller()
class MyController {
@Get("/foo/bar")
fooBar(ctx) {
return `request header x-foo has value "${
ctx.request.headers.get("x-foo")
}"`;
}
}
const app = new Application();
useOakServer(app, [MyController]);
await app.listen({ port: 1993 });
_
curl -H"x-foo: lorem" localhost:1993/foo/bar
# prints: request header x-foo has value "lorem"
View Example
npm i @jsr/oak__oak @jsr/dklab__oak-routing-ctrl
# note that `npx jsr i {package}` also works, but
# installing directly from the `@jsr` scope may result
# in better dependency resolutions
_
// alternatively imported from "@oak/oak/application"
import { Application } from "@jsr/oak__oak/application";
// alternatively imported from "@dklab/oak-routing-ctrl"
import {
Controller,
ControllerMethodArgs,
Get,
useOakServer,
} from "@jsr/dklab__oak-routing-ctrl";
@Controller("/v1")
export class MyController {
@Get("/hello/:name")
@ControllerMethodArgs("param")
hello(param: Record<string, string>) {
return `hello, ${param.name}`;
}
}
const app = new Application();
useOakServer(app, [MyController]);
await app.listen({ port: 1993 });
_
curl http://localhost:1993/v1/hello/world # prints: hello, world
View Example
npx jsr add @oak/oak @dklab/oak-routing-ctrl
_
import { Application } from "@oak/oak/application";
import {
Controller,
ControllerMethodArgs,
Get,
useOakServer,
} from "@dklab/oak-routing-ctrl/mod";
@Controller()
class MyCloudflareWorkerController {
@Get("/hello/:name")
@ControllerMethodArgs("param")
hello(param: { name: string }) {
return `hello, ${param.name}`;
}
}
const app = new Application();
useOakServer(app, [MyCloudflareWorkerController]);
export default { fetch: app.fetch };
_
curl http://{your-cloudflare-worker-domain}/hello/world # prints: hello, world
View Example
bunx jsr i @oak/oak @dklab/oak-routing-ctrl
_
import { Application, type RouterContext } from "@oak/oak";
import { Controller, Get, useOakServer } from "@dklab/oak-routing-ctrl";
@Controller("/v1")
class MyController {
@Get("/hello/:name")
hello(ctx: RouterContext<"/hello/:name">) {
return `hello, ${ctx.params.name}`;
}
}
const app = new Application();
useOakServer(app, [MyController]);
await app.listen({ port: 1993 });
_
curl http://localhost:1993/v1/hello/world # prints: hello, world
Serving Open API Spec (both as a JSON doc and as an HTML view) is supported as followed:
import { Application } from "@oak/oak";
import {
Controller,
ControllerMethodArgs,
Get,
useOakServer,
useOas,
z,
} from "@dklab/oak-routing-ctrl";
@Controller("/v1")
class MyController {
// using `zod` to express Open API Spec for this route
// e.g. `request` and `responses`
@Get("/hello/:name", {
request: {
params: z.object({
name: z.string(),
}),
},
responses: {
"200": {
description: "Success",
content: {
"text/plain": {
schema: z.string(),
},
},
},
},
})
@ControllerMethodArgs("param")
hello(param) {
return `hello, ${param.name}`;
}
}
useOakServer(app, [MyController]);
useOas(app, {
// optionally declare OAS info as per your project needs
info: {
version: "0.1.0",
title: "My awesome API",
description: "This is an awesome API",
},
});
await app.listen({ port: 1993 });
The following OAS resources are now served:
- UI: http://localhost:1993/swagger
- JSON doc: http://localhost:1993/oas.json
View Example OAS json doc
curl localhost:1993/oas.json
{
"openapi": "3.0.0",
"info": {
"version": "0.1.0",
"title": "My awesome API",
"description": "This is an awesome API"
},
"servers": [
{
"url": "http://localhost:1993"
}
],
"components": {
"schemas": {},
"parameters": {}
},
"paths": {
"/hello/{name}": {
"get": {
"parameters": [
{
"schema": {
"type": "string"
},
"required": true,
"name": "name",
"in": "path"
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
}
}
}
}
}
}
}
Documentation is hosted on the Javascript Registry: https://jsr.io/@dklab/oak-routing-ctrl/doc
deno test -A --coverage=cov_profile
deno coverage cov_profile