- make
server.ts
in your folder. - inside of it we import Application and Router like this:
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
FYI for Deno, they are not using any package.json
or node_modules
. they are now entirely online. so, you will import them from deno.land in standard library or std.
- after that, we going to initialize app and port, under
import
.
const port = 5000;
const app = new Application();
console.log(`server running on port ${port}`);
await app.listen({ port });
and now to execute it. we need to use our terminal and call:
deno run --allow-net server.ts
remember we want to use --allow-net
or the flag. and there's many more of the flag like --allow-read
or --allow-write
and so on.
and now when we execute it. it will say that we don't have middleware to process requests, because we didn't initialize Router. now we going to make Router:
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
const port = 5000;
const app = new Application();
const router = new Router();
app.use(router.routes());
app.use(router.allowedMethods());
console.log(`server running on port ${port}`);
await app.listen({ port });
now we going to make GET API with the router:
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
const port = 5000;
const app = new Application();
const router = new Router();
app.use(router.routes());
app.use(router.allowedMethods());
router.get("/api", ({ response }: { response: any }) => {
response.body = "Selamat datang, Deno!";
});
console.log(`server running on port ${port}`);
await app.listen({ port });
and now we can execute it.
deno run --allow-net server.ts
right now we just use response
not useContext
because, again. we just need a response right now. and we use { response: any }
since right now we using typescript.
and now we use postman to see if the response is okay to the postman.
now we just type "http://localhost:5000/api".
now since this, all functions are in one place. Let's move the router to a separate file, so we can have a clean code.
now in server.ts
cut some the line using ctrl + x
. and it should be like this:
import { Application } from "https://deno.land/x/oak/mod.ts";
const port = 5000;
const app = new Application();
app.use(router.routes());
app.use(router.allowedMethods());
console.log(`server running on port ${port}`);
await app.listen({ port });
now we going ctrl + v
the line that has just been cut, and also make a file name routes.ts
and put in there:
import { Router } from "https://deno.land/x/oak/mod.ts";
const router = new Router();
router.get("/api", ({ response }: { response: any }) => {
response.body = "Selamat datang, Deno!";
});
export default router;
now we already export the router, now we going to import the router into server.ts
and it should be like this:
import { Application } from "https://deno.land/x/oak/mod.ts";
import router from "./router.ts";
const port = 5000;
const app = new Application();
app.use(router.routes());
app.use(router.allowedMethods());
console.log(`server running on port ${port}`);
await app.listen({ port });
now we have clean code and its already a response in postman. what's next 🤷 ? we going to add products so we can have a functional REST API
we going to make folder
any name you want but I want to name it controllers
. inside of it we make a file name products.ts
and we going to add our products, here's my example for it
interface Product {
id: string;
name: string;
desc: string;
price: number;
condition: string;
}
let products: Product[] = [
{
id: "1",
name: "Macbook Pro 2018",
desc: "13 inch, 8 GB RAM",
price: 20000000,
condition: "new",
},
{
id: "2",
name: "Motorola G5S Plus",
desc: "5.5 inch, 4 GB RAM",
price: 3000000,
condition: "new",
},
{
id: "3",
name: "Acer E5 475G",
desc: "14 inch, 12 GB RAM (upgraded)",
price: 7000000,
condition: "used",
},
{
id: "4",
name: "iPad 2",
desc: "10 inch, 2 GB RAM",
price: 5000000,
condition: "new",
},
];
and again since we want clean code, we going to move the interface and export it. now we going to make another file in the base folder and create types.ts
and cut the interface and it should be like this:
product.ts
:
import { Product } from "../types.ts";
let products: Product[] = [
{
id: "1",
name: "Macbook Pro 2018",
desc: "13 inch, 8 GB RAM",
price: 20000000,
condition: "new",
},
{
id: "2",
name: "Motorola G5S Plus",
desc: "5.5 inch, 4 GB RAM",
price: 3000000,
condition: "new",
},
{
id: "3",
name: "Acer E5 475G",
desc: "14 inch, 12 GB RAM (upgraded)",
price: 7000000,
condition: "used",
},
{
id: "4",
name: "iPad 2",
desc: "10 inch, 2 GB RAM",
price: 5000000,
condition: "new",
},
];
types.ts
:
export interface Product {
id: string;
name: string;
desc: string;
price: number;
condition: string;
}
now we going to make function to get all products and route to GET API. first we going to make getProducts
function under products.ts
:
const getProducts = ({ response }: { response: any }) => {
response.body = {
success: true,
data: products,
};
};
export { getProducts };
and now in the routes.ts
, we going to import getProducts
function and call it.
import { Router } from "https://deno.land/x/oak/mod.ts";
import { getProducts } from "./controllers/products.ts";
const router = new Router();
router.get("/api", getProducts);
export default router;
now this is calling all product. how 'bout we call single one of them and the rest of the CRUD? brace yourself bois. (this all are under the products
)
product.ts
:
// desc: get all product ↓
// routes: GET /api ↓
const getProducts = ({ response }: { response: any }) => {
response.body = {
success: true,
data: products,
};
};
// desc: get single product ↓
// routes: GET /api/:id ↓
const getProduct = ({ response }: { response: any }) => {
response.body = {
success: true,
};
};
// desc: add product ↓
// routes: POST /api ↓
const addProduct = ({ response }: { response: any }) => {
response.body = {
success: true,
};
};
// desc: update product ↓
// routes: PUT /api/:id ↓
const updateProduct = ({ response }: { response: any }) => {
response.body = {
success: true,
};
};
// desc: delete product ↓
// routes: DELETE /api/:id ↓
const deleteProduct = ({ response }: { response: any }) => {
response.body = {
success: true,
};
};
export { getProducts, getProduct, addProduct, updateProduct, deleteProduct };
now we going to import the rest of the CRUD.
routes.ts
:
import { Router } from "https://deno.land/x/oak/mod.ts";
import {
getProducts,
getProduct,
addProduct,
updateProduct,
deleteProduct,
} from "./controllers/products.ts";
const router = new Router();
router
.get("/api", getProducts)
.get("/api/:id", getProduct)
.post("/api", addProduct)
.put("/api/:id", updateProduct)
.delete("/api/:id", deleteProduct);
export default router;
now to make sure that the CRUD is on. we'll just call each one of them in postman
awesome, right now CRUD can be called, but we going to put logic inside of it.
now we going to update GET for each product.
const getProduct = ({
params,
response,
}: {
params: { id: string };
response: any;
}) => {
const product: Product | undefined = products.find((p) => p.id === params.id);
if (product) {
response.status = 200;
response.body = {
success: true,
data: product,
};
} else {
response.status = 404;
response.body = {
success: false,
msg: "no product found",
};
}
};
now for to POST product
import { v4 } from "https://deno.land/std/uuid/mod.ts";
---
rest of the code.
---
const addProduct = async (
{ response, request }: { request: any; response: any },
) => {
const body = await request.body();
if (!request.hasBody) {
response.status = 400,
response.body = {
success: false,
msg: "cannot add product",
};
} else {
const product: Product = body.value;
product.id = v4.generate();
products.push(product);
response.status = 201,
response.body = {
success: true,
data: product,
};
}
};
remember we need to import v4 from the deno.land
and also put async and await since request.body()
method returns promise
now for the PUT product
const updateProduct = async ({
params,
request,
response,
}: {
params: { id: string };
request: any;
response: any;
}) => {
const product: Product | undefined = products.find((p) => p.id === params.id);
if (product) {
const body = await request.body();
const updateData: {
name?: string;
desc?: string;
price?: number;
condition?: string;
} = body.value;
products = products.map((p) =>
p.id === params.id ? { ...p, ...updateData } : p
);
(response.status = 200),
(response.body = {
success: true,
data: products,
});
} else {
response.status = 404;
response.body = {
success: false,
msg: "no product found",
};
}
};
the code of GETbyID and PUT is the same at first but in the middle, we put map function
and last is for the DELETE product
const deleteProduct = ({
params,
response,
}: {
params: { id: string };
response: any;
}) => {
products = products.filter((p) => p.id !== params.id);
response.body = {
success: true,
msg: "product has been removed",
data: products,
};
};
and now we finally have a functional CRUD using deno.