- Notifications
You must be signed in to change notification settings - Fork0
TypeScript Decorators for easy scaffolding API services with the oak framework (jsr:@oak/oak)
License
Thesephi/oak-routing-ctrl
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
TypeScript Decorators for easy scaffolding API services with theOak framework (jsr:@oak/oak) 🚗 🐿️ 🦕
Works on Node.js, Bun, Cloudflare Workers, and Deno
@Controller("/api/v1/pokemon")classMyPokedex{ @Get("/:id")viewEntry(ctx){if(ctx.params.id==="0025")return"Pikachu";}}
If you're familiar with thenpm library routing-controllers,you'll find yourself very much at home.
However, please note that this libray isnot meant to be a drop-inreplacement for routing-controllers, as it attempts to conform toTC39 Decorators proposal whichdoesn't support Method Parameter Decoratoryet. 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 wheninstalling library dependencies. But in your production code, it's advisable topin every dependency to a specific version.
Prerequisite:Deno
// main.tsimport{Application}from"jsr:@oak/oak/application";import{Controller,ControllerMethodArgs,Get,useOakServer,}from"jsr:@dklab/oak-routing-ctrl";constapp=newApplication();@Controller("/v1")classMyController{ @Get("/hello/:name") @ControllerMethodArgs("param")hello(param){return`hello,${param.name}`;}}useOakServer(app,[MyController]);awaitapp.listen({port:1993});
deno run --allow-env --allow-net main.ts
# in another terminalcurl localhost:1993/v1/hello/world# prints: hello, world
View Example
import{Application}from"jsr:@oak/oak/application";import{Controller,ControllerMethodArgs,Post,useOakServer,}from"jsr:@dklab/oak-routing-ctrl";@Controller("/v1")classMyController{ @Post("/tell/:name") @ControllerMethodArgs("param","body")tell(param,body){return`telling${param.name} that "${body.message}"`;}}constapp=newApplication();useOakServer(app,[MyController]);awaitapp.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"jsr:@oak/oak/application";import{Controller,ControllerMethodArgs,Get,useOakServer,}from"jsr:@dklab/oak-routing-ctrl";@Controller("/v1")classMyController{ @Get("/books/:category") @ControllerMethodArgs("query","param")search(query,param){return`searching for books in category "${param.category}" with query "page=${query.page}"`;}}constapp=newApplication();useOakServer(app,[MyController]);awaitapp.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"jsr:@oak/oak/application";import{Controller,Get,useOakServer}from"jsr:@dklab/oak-routing-ctrl";@Controller()classMyController{ @Get("/foo/bar")fooBar(ctx){return`request header x-foo has value "${ctx.request.headers.get("x-foo")}"`;}}constapp=newApplication();useOakServer(app,[MyController]);awaitapp.listen({port:1993});
_
curl -H"x-foo: lorem" localhost:1993/foo/bar# prints: request header x-foo has value "lorem"
If you're on Node.js 22 (or above), please consult this example boilerplate:https://replit.com/@0x97FB9/auto-swagger-node-alpha
If you're on Node.js 21 (or below), then the example workflow below may apply toyou.
View Example for Node.js 21 and below
_
You can start with a boilerplate
npm create oak-nodejs-esbuild@latest
_
Or you can start from scratch
friendly note: if something doesn't work as advertised in this section,please file an issue, thanks!
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 might 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")exportclassMyController{ @Get("/hello/:name") @ControllerMethodArgs("param")hello(param:Record<string,string>){return`hello,${param.name}`;}}constapp=newApplication();useOakServer(app,[MyController]);awaitapp.listen({port:1993});
_
curl http://localhost:1993/v1/hello/world# prints: hello, worldnpm create oak-cloudflare-worker@latest
Live Demo (uptimenot guaranteed):https://oak-routing-ctrl-cloudflare.dklab.workers.dev/swagger
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()classMyCloudflareWorkerController{ @Get("/hello/:name") @ControllerMethodArgs("param")hello(param:{name:string}){return`hello,${param.name}`;}}constapp=newApplication();useOakServer(app,[MyCloudflareWorkerController]);exportdefault{fetch:app.fetch};
_
curl http://{your-cloudflare-worker-domain}/hello/world# prints: hello, worldnpm create oak-bun@latest
View Example
bunx jsr i @oak/oak @dklab/oak-routing-ctrl
_
import{Application,typeRouterContext}from"@oak/oak";import{Controller,Get,useOakServer}from"@dklab/oak-routing-ctrl";@Controller("/v1")classMyController{ @Get("/hello/:name")hello(ctx:RouterContext<"/hello/:name">){return`hello,${ctx.params.name}`;}}constapp=newApplication();useOakServer(app,[MyController]);awaitapp.listen({port:1993});
_
curl http://localhost:1993/v1/hello/world# prints: hello, worldServing Open API Spec (both as a JSON doc and as an HTML view) is supported asfollowed:
import{Application}from"@oak/oak";import{Controller,ControllerMethodArgs,Get,useOakServer,useOas,z,typezInfer,}from"@dklab/oak-routing-ctrl";constHelloNamePathParamsSchema=z.object({name:z.string()});constOpenApiSpecForHelloName={// using `zod` to express Open API Spec for this route// e.g. `request` and `responses`request:{params:HelloNamePathParamsSchema},responses:{"200":{description:"Success",content:{"text/html":{schema:z.string()}},},},};@Controller("/v1")classMyController{ @Get("/hello/:name",OpenApiSpecForHelloName,// API spec is entirely optional) @ControllerMethodArgs("param")hello(param:zInfer<typeofHelloNamePathParamsSchema>,// or type it however else you like){return`hello,${param.name}`;// intellisense should just work ™}}useOakServer(app,[MyController]);useOas(app,{// optionally declare OAS info as per your project needsinfo:{version:"0.1.0",title:"My awesome API",description:"This is an awesome API",},});awaitapp.listen({port:1993});
The following OAS resources are now served:
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
denotest -A --coverage=cov_profiledeno coverage cov_profileQ: can this library support fullstack web development?
A: yes, in fact there's a fullstack web framework on top of this library:FullSoak
About
TypeScript Decorators for easy scaffolding API services with the oak framework (jsr:@oak/oak)
Topics
Resources
License
Contributing
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Uh oh!
There was an error while loading.Please reload this page.
