A Straightforward REST API Framework for Deno. Zero-config server with path-based router.
✅ Zero-Config framework
✅ Instant path-based routing
✅ Dynamic route params with filename
✅ Hooks and Plugins
Table of Contents
Build an API server should be easy not a complex things. As developer, often we are struggle to build an API server, most of our time was used to restructure file and and refactor codes.
As business process evolve, more weird and complex things appears, and it's not a pokemon, but problem that we always hate.
And we don't remember where is the code and what the file for.
We're having a bad time, and after somewhile, you open old legacy codes, you feels like "who wrote this ugly codes?," it's cliché, doesn't it?
Today, developer forgot to write simple codes and file structure that every developers can read and mantain.
We're all love simplicity. And this framework exists.
As long as you have deno installed, and favourite code editor, you can start right away. How to start the server? let's don't skip reading this documentation.
You don't need to create bootstrap file like any other frameworks.
Just add routes
folder in your current working directory.
After that, add a hello.ts
file as your first router, and you're done.
Example Code
// <your_current_directory>/routes/hello.ts
import {
HttpRequest,
HttpResponse,
} from "https://deno.land/x/jurassic/@types/http.d.ts";
// Route Handler
export default (req: HttpRequest, res: HttpResponse) => {
return "Hello world";
};
Type this command in your current directory, from your favourite terminal.
deno run --allow-read --allow-net --allow-env https://deno.land/x/jurassic/server.ts
If you see log below, then your server is running successfuly.
Console Log
🦖 Start jurassic server
-------------------
[server info]
PORT: 8888
[routes]
- /hello
-------------------
Now access test in your browser http://localhost/hello
.
I believe building REST API router should be easy. As NextJS developer, I'm inspired by NextJS API directory, using bracket filename as dynamic routes params.
To create a dynamic route with params, just use bracket as directory or file name e.g [type]/[slug].ts
. You can use it as nested directory too.
You can accessing param within route handler with req.params
, e.g req.params.myParams
.
Example Code
// <your_current_directory>/routes/post/[id].ts
import {
HttpRequest,
HttpResponse,
} from "https://deno.land/x/jurassic/@types/http.d.ts";
export default (req: HttpRequest, res: HttpResponse) => {
return `Post ID: ${req.params.id}`;
};
By default your router will accepts all methods (GET
, POST
, PUT
, OPTIONS
, DELETE
), but you can define or restrict it, to do that just export method
variable. It support array or string.
Example Code
// <your_current_directory>/routes/v1/your-router.ts
import {
HttpRequest,
HttpResponse,
} from "https://deno.land/x/jurassic/@types/http.d.ts";
export const method = ["GET", "POST"];
// or
// export const method = "POST"
export default (req: HttpRequest, res: HttpResponse) => {
return `Method ${req.method}`;
};
In the previous section you can define or restrict router methods, but what if every method have different response or consume different database / service. You can use multiple handler:
Example Code
// <your_current_directory>/routes/v1/your-router.ts
import { HttpRequest, HttpResponse } from "https://deno.land/x/jurassic/@types/http.d.ts";
export const method = ["GET", "POST"];
export default {
get(req: HttpRequest, res: HttpResponse) => {
return `GET response`;
},
post(req: HttpRequest, res: HttpResponse) => {
return `POST response`;
}
};
Example Code
// <your_current_directory>/routes/v1/your-router.ts
import {
HttpRequest,
HttpResponse,
} from "https://deno.land/x/jurassic/@types/http.d.ts";
export const headers = {
// your http header here
};
export default (req: HttpRequest, res: HttpResponse) => {
return `My Router`;
};
You can set Content-Type
in headers
or contentType
variable. The difference is contentType
use shortcut.
Example Code
// <your_current_directory>/routes/hello.ts
import {
HttpRequest,
HttpResponse,
} from "https://deno.land/x/jurassic/@types/http.d.ts";
// You can set content type with headers.
export const headers = {
["Content-Type"]: "application/json",
};
// Or you can use shortcut.
export const contentType = "json";
export default (req: HttpRequest, res: HttpResponse) => {
return {
hello: "world",
universe: true,
cluster: "lineakia",
};
};
Use versioning path in your router for best practice. When you're upgrading API version, developer or API consumer won't get confused.
But it's okay if you define static route, such as ping
or health
(for health check API).
❌ /routes/post/[id].ts
❌ /routes/cart/[id].ts
✅ /routes/ping.ts
✅ /routes/health.ts
✅ /routes/v1/post/[id].ts
✅ /routes/v2/users.ts
✅ /routes/v2/user/@[id].ts
✅ /routes/v2/user/[dynamic].ts
You can change port and add environment to your project. Create a server.ts
file in your directory. And export port / env file. We added SERVER_ENV_
to your environment.
Example Code
// <your_current_directory>/server.ts
// Custom PORT
export const port = 3000;
// Environment
export const env = {
MY_KEY: "secret-key",
};
// <your_current_directory>/routes/hello.ts
// access environment
Deno.env.get("SERVER_ENV_MY_KEY");
See example codes in Examples directory.
MIT - 2020 (c) oknoorap. More details see LICENSE file.