├── .gitignore ├── chapter_2:mysql ├── db │ ├── config.ts │ └── client.ts ├── interfaces │ └── Todo.ts ├── middlewares │ ├── notFound.ts │ └── logger.ts ├── routes │ └── todo.ts ├── server.ts ├── README.md ├── models │ └── todo.ts └── controllers │ └── todo.ts ├── guidelines ├── assets │ ├── 4-workbench.png │ ├── 3-mysql-after-start.png │ ├── 1-system-preferences.png │ ├── 2-mysql-before-start.png │ └── 5-workbench-query-panel.png └── setting-up-mysql-mac-os-catalina.md ├── chapter_1:oak ├── interfaces │ └── Todo.ts ├── middlewares │ ├── notFound.ts │ └── logger.ts ├── routes │ └── todo.ts ├── stubs │ └── todos.ts ├── README.md ├── server.ts └── controllers │ └── todo.ts └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_STORE -------------------------------------------------------------------------------- /chapter_2:mysql/db/config.ts: -------------------------------------------------------------------------------- 1 | export const DATABASE: string = "deno"; 2 | export const TABLE = { 3 | TODO: "todo", 4 | }; 5 | -------------------------------------------------------------------------------- /guidelines/assets/4-workbench.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeelibr/deno-playground/HEAD/guidelines/assets/4-workbench.png -------------------------------------------------------------------------------- /chapter_1:oak/interfaces/Todo.ts: -------------------------------------------------------------------------------- 1 | export default interface Todo { 2 | id: string, 3 | todo: string, 4 | isCompleted: boolean, 5 | } -------------------------------------------------------------------------------- /guidelines/assets/3-mysql-after-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeelibr/deno-playground/HEAD/guidelines/assets/3-mysql-after-start.png -------------------------------------------------------------------------------- /chapter_2:mysql/interfaces/Todo.ts: -------------------------------------------------------------------------------- 1 | export default interface Todo { 2 | id?: number, 3 | todo?: string, 4 | isCompleted?: boolean, 5 | } 6 | -------------------------------------------------------------------------------- /guidelines/assets/1-system-preferences.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeelibr/deno-playground/HEAD/guidelines/assets/1-system-preferences.png -------------------------------------------------------------------------------- /guidelines/assets/2-mysql-before-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeelibr/deno-playground/HEAD/guidelines/assets/2-mysql-before-start.png -------------------------------------------------------------------------------- /guidelines/assets/5-workbench-query-panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeelibr/deno-playground/HEAD/guidelines/assets/5-workbench-query-panel.png -------------------------------------------------------------------------------- /chapter_1:oak/middlewares/notFound.ts: -------------------------------------------------------------------------------- 1 | export default ({ response }: { response: any }) => { 2 | response.status = 404; 3 | response.body = { 4 | success: false, 5 | message: "404 - Not found.", 6 | }; 7 | }; 8 | -------------------------------------------------------------------------------- /chapter_2:mysql/middlewares/notFound.ts: -------------------------------------------------------------------------------- 1 | export default ({ response }: { response: any }) => { 2 | response.status = 404; 3 | response.body = { 4 | success: false, 5 | message: "404 - Not found.", 6 | }; 7 | }; 8 | -------------------------------------------------------------------------------- /chapter_1:oak/routes/todo.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "https://deno.land/x/oak/mod.ts"; 2 | 3 | const router = new Router(); 4 | // controller 5 | import todoController from "../controllers/todo.ts"; 6 | 7 | router 8 | .get("/todos", todoController.getAllTodos) 9 | .post("/todos", todoController.createTodo) 10 | .get("/todos/:id", todoController.getTodoById) 11 | .put("/todos/:id", todoController.updateTodoById) 12 | .delete("/todos/:id", todoController.deleteTodoById); 13 | 14 | export default router; 15 | -------------------------------------------------------------------------------- /chapter_2:mysql/routes/todo.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "https://deno.land/x/oak/mod.ts"; 2 | 3 | const router = new Router(); 4 | // controller 5 | import todoController from "../controllers/todo.ts"; 6 | 7 | router 8 | .get("/todos", todoController.getAllTodos) 9 | .post("/todos", todoController.createTodo) 10 | .get("/todos/:id", todoController.getTodoById) 11 | .put("/todos/:id", todoController.updateTodoById) 12 | .delete("/todos/:id", todoController.deleteTodoById); 13 | 14 | export default router; 15 | -------------------------------------------------------------------------------- /chapter_1:oak/stubs/todos.ts: -------------------------------------------------------------------------------- 1 | import { v4 } from "https://deno.land/std/uuid/mod.ts"; 2 | // interface 3 | import Todo from '../interfaces/Todo.ts'; 4 | 5 | let todos: Todo[] = [ 6 | { 7 | id: v4.generate(), 8 | todo: 'walk dog', 9 | isCompleted: true, 10 | }, 11 | { 12 | id: v4.generate(), 13 | todo: 'eat food', 14 | isCompleted: false, 15 | }, 16 | { 17 | id: v4.generate(), 18 | todo: 'exercise', 19 | isCompleted: true, 20 | }, 21 | { 22 | id: v4.generate(), 23 | todo: 'read a book', 24 | isCompleted: false, 25 | } 26 | ]; 27 | 28 | export default todos; -------------------------------------------------------------------------------- /chapter_1:oak/README.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | Tutorial for this codebase can be found at freecodecamp https://www.freecodecamp.org/news/create-a-todo-api-in-deno-written-by-a-guy-coming-from-node/ 4 | 5 | This tutorial focused on using oak to create a todo application. 6 | 7 | List of thing achieved; 8 | 9 | - Create a server using OAK 10 | - Create routes and there controller 11 | - Make an interface 12 | - Stub some data 13 | - Add logger middleware 14 | - Add a not found middleware 15 | 16 | ## Run 17 | 18 | ``` 19 | deno run --allow-net server.ts 20 | ``` 21 | 22 | ## Routes 23 | 24 | ``` 25 | GET /todos 26 | GET /todos/:id 27 | POST /todos 28 | PUT /todos/:id 29 | DELETE /todos/:id 30 | ``` 31 | -------------------------------------------------------------------------------- /chapter_1:oak/middlewares/logger.ts: -------------------------------------------------------------------------------- 1 | import { 2 | green, 3 | cyan, 4 | white, 5 | bgRed, 6 | } from "https://deno.land/std@0.53.0/fmt/colors.ts"; 7 | 8 | const X_RESPONSE_TIME: string = "X-Response-Time"; 9 | 10 | export default { 11 | logger: async ( 12 | { response, request }: { response: any, request: any }, 13 | next: Function, 14 | ) => { 15 | await next(); 16 | const responseTime = response.headers.get(X_RESPONSE_TIME); 17 | console.log(`${green(request.method)} ${cyan(request.url.pathname)}`); 18 | console.log(`${bgRed(white(String(responseTime)))}`); 19 | }, 20 | responseTime: async ( 21 | { response }: { response: any }, 22 | next: Function, 23 | ) => { 24 | const start = Date.now(); 25 | await next(); 26 | const ms: number = Date.now() - start; 27 | response.headers.set(X_RESPONSE_TIME, `${ms}ms`) 28 | }, 29 | }; 30 | -------------------------------------------------------------------------------- /chapter_2:mysql/middlewares/logger.ts: -------------------------------------------------------------------------------- 1 | import { 2 | green, 3 | cyan, 4 | white, 5 | bgRed, 6 | } from "https://deno.land/std@0.53.0/fmt/colors.ts"; 7 | 8 | const X_RESPONSE_TIME: string = "X-Response-Time"; 9 | 10 | export default { 11 | logger: async ( 12 | { response, request }: { response: any, request: any }, 13 | next: Function, 14 | ) => { 15 | await next(); 16 | const responseTime = response.headers.get(X_RESPONSE_TIME); 17 | console.log(`${green(request.method)} ${cyan(request.url.pathname)}`); 18 | console.log(`${bgRed(white(String(responseTime)))}`); 19 | }, 20 | responseTime: async ( 21 | { response }: { response: any }, 22 | next: Function, 23 | ) => { 24 | const start = Date.now(); 25 | await next(); 26 | const ms: number = Date.now() - start; 27 | response.headers.set(X_RESPONSE_TIME, `${ms}ms`) 28 | }, 29 | }; 30 | -------------------------------------------------------------------------------- /chapter_1:oak/server.ts: -------------------------------------------------------------------------------- 1 | import { Application } from "https://deno.land/x/oak/mod.ts"; 2 | import { green, yellow } from "https://deno.land/std@0.53.0/fmt/colors.ts"; 3 | 4 | // routes 5 | import todoRouter from "./routes/todo.ts"; 6 | // logger 7 | import logger from './middlewares/logger.ts'; 8 | // not found 9 | import notFound from './middlewares/notFound.ts'; 10 | 11 | const app = new Application(); 12 | const port: number = 8080; 13 | 14 | // order of execution is important; 15 | app.use(logger.logger); 16 | app.use(logger.responseTime); 17 | 18 | app.use(todoRouter.routes()); 19 | app.use(todoRouter.allowedMethods()); 20 | 21 | // 404 page 22 | app.use(notFound); 23 | 24 | app.addEventListener("listen", ({ secure, hostname, port }) => { 25 | const protocol = secure ? "https://" : "http://"; 26 | const url = `${protocol}${hostname ?? "localhost"}:${port}`; 27 | console.log( 28 | `${yellow("Listening on:")} ${green(url)}`, 29 | ); 30 | }); 31 | 32 | await app.listen({ port }); 33 | -------------------------------------------------------------------------------- /chapter_2:mysql/server.ts: -------------------------------------------------------------------------------- 1 | import { Application } from "https://deno.land/x/oak/mod.ts"; 2 | import { green, yellow } from "https://deno.land/std@0.53.0/fmt/colors.ts"; 3 | 4 | // routes 5 | import todoRouter from "./routes/todo.ts"; 6 | // logger 7 | import logger from './middlewares/logger.ts'; 8 | // not found 9 | import notFound from './middlewares/notFound.ts'; 10 | 11 | const app = new Application(); 12 | const port: number = 8080; 13 | 14 | // order of execution is important; 15 | app.use(logger.logger); 16 | app.use(logger.responseTime); 17 | 18 | app.use(todoRouter.routes()); 19 | app.use(todoRouter.allowedMethods()); 20 | 21 | // 404 page 22 | app.use(notFound); 23 | 24 | app.addEventListener("listen", ({ secure, hostname, port }) => { 25 | const protocol = secure ? "https://" : "http://"; 26 | const url = `${protocol}${hostname ?? "localhost"}:${port}`; 27 | console.log( 28 | `${yellow("Listening on:")} ${green(url)}`, 29 | ); 30 | }); 31 | 32 | await app.listen({ port }); 33 | -------------------------------------------------------------------------------- /chapter_2:mysql/db/client.ts: -------------------------------------------------------------------------------- 1 | import { Client } from "https://deno.land/x/mysql/mod.ts"; 2 | // config 3 | import { DATABASE, TABLE } from "./config.ts"; 4 | 5 | const client = await new Client(); 6 | 7 | client.connect({ 8 | hostname: "127.0.0.1", 9 | username: "root", 10 | password: "", 11 | db: "", 12 | }); 13 | 14 | const run = async () => { 15 | // create database (if not created before) 16 | await client.execute(`CREATE DATABASE IF NOT EXISTS ${DATABASE}`); 17 | // select db 18 | await client.execute(`USE ${DATABASE}`); 19 | 20 | // delete table if it exists before 21 | await client.execute(`DROP TABLE IF EXISTS ${TABLE.TODO}`); 22 | // create table 23 | await client.execute(` 24 | CREATE TABLE ${TABLE.TODO} ( 25 | id int(11) NOT NULL AUTO_INCREMENT, 26 | todo varchar(100) NOT NULL, 27 | isCompleted boolean NOT NULL default false, 28 | PRIMARY KEY (id) 29 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 30 | `); 31 | }; 32 | 33 | run(); 34 | 35 | export default client; 36 | -------------------------------------------------------------------------------- /chapter_2:mysql/README.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | Tutorial for this codebase can be found at https://www.freecodecamp.org/news/p/de7a850a-6d40-48a0-b6d7-8bf00ce66d10/ 4 | 5 | This tutorial builds on top of chapter 1 6 | 7 | List of thing achieved; 8 | 9 | - Create a DB connection 10 | - Write a script that initialized DB & creates a table 11 | - Write CRUD operations for DB & them in rest API's 12 | 13 | ## Steps [Execution order] 14 | 15 | ### Run 16 | 17 | ```bash 18 | deno run --allow-net server.ts 19 | ``` 20 | 21 | ## Routes 22 | 23 | ``` 24 | GET /todos 25 | GET /todos/:id 26 | POST /todos 27 | PUT /todos/:id 28 | DELETE /todos/:id 29 | ``` 30 | 31 | ### Installing MySQL community server & MySQL workbench 32 | 33 | Guideline written [here](../guidelines/setting-up-mysql-mac-os-catalina.md) 34 | 35 | ## Database Tricks 36 | 37 | Once you have `mysql community server` & `mysql workbench` installed. 38 | 39 | - Start MySql server 40 | - Open workbench 41 | - Run the following command 42 | 43 | ```sql 44 | select current_user(); 45 | set password = ""; 46 | ``` 47 | 48 | > This is because current mySql-deno pacakge doesn't work with latest mySql 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deno Playground 2 | 3 | A collection of deno apps to build. 4 | 5 | ### Chapter 1 6 | 7 | - It talks about setting up a basic todo application using deno/oak. Without using a database. 8 | - Tutorial link: https://www.freecodecamp.org/news/create-a-todo-api-in-deno-written-by-a-guy-coming-from-node/ 9 | 10 | ### Chapter 2 11 | 12 | - Builds on chapter 1, where we add MySQL to our Todo application 13 | - Tutorial link: https://www.freecodecamp.org/news/p/de7a850a-6d40-48a0-b6d7-8bf00ce66d10/ 14 | 15 | Please note in order to understand chapter 2, you need to go through chapter 1. 16 | 17 | 18 | # Troubleshoot 19 | 20 | ## Update for Deno Version 1.37.0 21 | 22 | Since the time of writing this tutorial, Deno has seen updates, and some code changes are required to keep it up to date. One such change is related to handling request bodies. 23 | 24 | In Deno version 1.0.2, you might have used the following code to handle request bodies: 25 | 26 | ```javascript 27 | const body = await request.body(); 28 | ``` 29 | 30 | However, with the current version of Deno (1.37.0), you should use the following code to access the request body: 31 | 32 | ```javascript 33 | const body = await request.body().value; 34 | 35 | ``` 36 | 37 | This change ensures compatibility with the latest Deno version and ensures your code continues to work as expected. 38 | 39 | Make sure to review your entire codebase for any other breaking changes or updates needed to stay in sync with the latest Deno version. Keep your code and tutorials up to date to provide the best experience for your users 40 | -------------------------------------------------------------------------------- /guidelines/setting-up-mysql-mac-os-catalina.md: -------------------------------------------------------------------------------- 1 | ## Setting up MySQL 2 | 3 | I am on a Mac OS system using version Catalina. To have MySQL running on my machine I had to install the following tools; 4 | 5 | - MySQL community server [download link](https://dev.mysql.com/downloads/mysql/) 6 | - MySQL workbench [download link](https://dev.mysql.com/downloads/workbench/) 7 | 8 | If you are on a windows machine you can use the same tools or you can use [XAMPP](https://www.apachefriends.org/index.html) as well. 9 | 10 | ### Installing MySQL 11 | 12 | First we have to install [MySQL community server](https://dev.mysql.com/downloads/mysql/). Install this and follow along the instructions. It will at the end stages of installion ask you to set a password for your username. 13 | 14 | > Set up a strong password. (We will remove it later 😂😂), because current MySQL lib of Deno doesn't connect to a username with a password. 15 | 16 | Go to your system preferences 17 | 18 | ![MAC OS system preferences](assets/1-system-preferences.png?raw=true "system preferences") 19 | 20 | Click on `MySQL` a new dialog will open up. 21 | 22 | ![MySQL before starting](assets/2-mysql-before-start.png?raw=true "mysql") 23 | 24 | Click on `Start MySQL Server` button 25 | 26 | ![MySQL after starting](assets/3-mysql-after-start.png?raw=true "mysql") 27 | 28 | ### Installing MySQL Workbench 29 | 30 | Next we have to install [MySQL workbench](https://dev.mysql.com/downloads/workbench/). Follow the steps along. Once it is installed. Open `workbench`. It should look like below. (Make sure before opening this that you have your MySQL instance running) 31 | 32 | ![MySQL workbench](assets/4-workbench.png?raw=true "workbench") 33 | 34 | Once open an instance of `localhost` It will open up a dialog like this 35 | 36 | ![MySQL workbench query panel](assets/5-workbench-query-panel.png?raw=true "workbench query panel") 37 | 38 | ##### Set your MySQL password to empty 39 | 40 | Inside the `query panel box` write the following query. 41 | 42 | ```sql 43 | select current_user(); 44 | set password = ""; 45 | ``` 46 | 47 | & hit `cmd + enter`. This will execute the query. 48 | 49 | What this query does is, it will select whatever the current user logged is (which is `root`) & for that user set it's password to `""` empty. 50 | 51 | ----- 52 | 53 | Having done this, you are ready to start playing with deno + oak + mysql 😍😍😍 -------------------------------------------------------------------------------- /chapter_2:mysql/models/todo.ts: -------------------------------------------------------------------------------- 1 | import client from "../db/client.ts"; 2 | // config 3 | import { TABLE } from "../db/config.ts"; 4 | // Interface 5 | import Todo from "../interfaces/Todo.ts"; 6 | 7 | export default { 8 | /** 9 | * Takes in the id params & checks if the todo item exists 10 | * in the database 11 | * @param id 12 | * @returns boolean to tell if an entry of todo exits in table 13 | */ 14 | doesExistById: async ({ id }: Todo) => { 15 | const [result] = await client.query( 16 | `SELECT COUNT(*) count FROM ${TABLE.TODO} WHERE id = ? LIMIT 1`, 17 | [id], 18 | ); 19 | return result.count > 0; 20 | }, 21 | /** 22 | * Will return all the entries in the todo column 23 | * @returns array of todos 24 | */ 25 | getAll: async () => { 26 | return await client.query(`SELECT * FROM ${TABLE.TODO}`); 27 | }, 28 | /** 29 | * Takes in the id params & returns the todo item found 30 | * against it. 31 | * @param id 32 | * @returns object of todo item 33 | */ 34 | getById: async ({ id }: Todo) => { 35 | return await client.query( 36 | `SELECT * FROM ${TABLE.TODO} WHERE id = ?`, 37 | [id], 38 | ); 39 | }, 40 | /** 41 | * Adds a new todo item to todo table 42 | * @param todo 43 | * @param isCompleted 44 | */ 45 | add: async ( 46 | { todo, isCompleted }: Todo, 47 | ) => { 48 | return await client.query( 49 | `INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?)`, 50 | [ 51 | todo, 52 | isCompleted, 53 | ], 54 | ); 55 | }, 56 | /** 57 | * Updates the content of a single todo item 58 | * @param id 59 | * @param todo 60 | * @param isCompleted 61 | * @returns integer (count of effect rows) 62 | */ 63 | updateById: async ({ id, todo, isCompleted }: Todo) => { 64 | const result = await client.query( 65 | `UPDATE ${TABLE.TODO} SET todo=?, isCompleted=? WHERE id=?`, 66 | [ 67 | todo, 68 | isCompleted, 69 | id, 70 | ], 71 | ); 72 | // return count of rows updated 73 | return result.affectedRows; 74 | }, 75 | /** 76 | * Deletes a todo by ID 77 | * @param id 78 | * @returns integer (count of effect rows) 79 | */ 80 | deleteById: async ({ id }: Todo) => { 81 | const result = await client.query( 82 | `DELETE FROM ${TABLE.TODO} WHERE id = ?`, 83 | [id], 84 | ); 85 | // return count of rows updated 86 | return result.affectedRows; 87 | }, 88 | }; 89 | -------------------------------------------------------------------------------- /chapter_1:oak/controllers/todo.ts: -------------------------------------------------------------------------------- 1 | import { v4 } from "https://deno.land/std/uuid/mod.ts"; 2 | // interfaces 3 | import Todo from "../interfaces/Todo.ts"; 4 | // stubs 5 | import todos from "../stubs/todos.ts"; 6 | 7 | export default { 8 | /** 9 | * @description Get all todos 10 | * @route GET /todos 11 | */ 12 | getAllTodos: ({ response }: { response: any }) => { 13 | response.status = 200; 14 | response.body = { 15 | success: true, 16 | data: todos, 17 | }; 18 | }, 19 | /** 20 | * @description Add a new todo 21 | * @route POST /todos 22 | */ 23 | createTodo: async ( 24 | { request, response }: { request: any; response: any }, 25 | ) => { 26 | const body = await request.body(); 27 | if (!request.hasBody) { 28 | response.status = 400; 29 | response.body = { 30 | success: false, 31 | message: "No data provided", 32 | }; 33 | return; 34 | } 35 | 36 | // if everything is fine then perform 37 | // operation and return todos with the 38 | // new data added. 39 | let newTodo: Todo = { 40 | id: v4.generate(), 41 | todo: body.value.todo, 42 | isCompleted: false, 43 | }; 44 | let data = [...todos, newTodo]; 45 | response.body = { 46 | success: true, 47 | data, 48 | }; 49 | }, 50 | /** 51 | * @description Get todo by id 52 | * @route GET todos/:id 53 | */ 54 | getTodoById: ( 55 | { params, response }: { params: { id: string }; response: any }, 56 | ) => { 57 | const todo: Todo | undefined = todos.find((t) => t.id === params.id); 58 | if (!todo) { 59 | response.status = 404; 60 | response.body = { 61 | success: false, 62 | message: "No todo found", 63 | }; 64 | return; 65 | } 66 | 67 | // If todo is found 68 | response.status = 200; 69 | response.body = { 70 | success: true, 71 | data: todo, 72 | }; 73 | }, 74 | /** 75 | * @description Update todo by id 76 | * @route PUT todos/:id 77 | */ 78 | updateTodoById: async ( 79 | { params, request, response }: { 80 | params: { id: string }, 81 | request: any, 82 | response: any, 83 | }, 84 | ) => { 85 | const todo: Todo | undefined = todos.find((t) => t.id === params.id); 86 | if (!todo) { 87 | response.status = 404; 88 | response.body = { 89 | success: false, 90 | message: "No todo found", 91 | }; 92 | return; 93 | } 94 | 95 | // if todo found then update todo 96 | const body = await request.body(); 97 | const updatedData: { todo?: string; isCompleted?: boolean } = body.value; 98 | let newTodos = todos.map((t) => { 99 | return t.id === params.id ? { ...t, ...updatedData } : t; 100 | }); 101 | response.status = 200; 102 | response.body = { 103 | success: true, 104 | data: newTodos, 105 | }; 106 | }, 107 | /** 108 | * @description Delete todo by id 109 | * @route DELETE todos/:id 110 | */ 111 | deleteTodoById: ( 112 | { params, response }: { params: { id: string }; response: any }, 113 | ) => { 114 | const allTodos = todos.filter((t) => t.id !== params.id); 115 | 116 | // remove the todo w.r.t id & return 117 | // remaining todos 118 | response.status = 200; 119 | response.body = { 120 | success: true, 121 | data: allTodos, 122 | }; 123 | }, 124 | }; 125 | -------------------------------------------------------------------------------- /chapter_2:mysql/controllers/todo.ts: -------------------------------------------------------------------------------- 1 | // interfaces 2 | import Todo from "../interfaces/Todo.ts"; 3 | // models 4 | import TodoModel from "../models/todo.ts"; 5 | 6 | export default { 7 | /** 8 | * @description Get all todos 9 | * @route GET /todos 10 | */ 11 | getAllTodos: async ({ response }: { response: any }) => { 12 | try { 13 | const data = await TodoModel.getAll(); 14 | response.status = 200; 15 | response.body = { 16 | success: true, 17 | data, 18 | }; 19 | } catch (error) { 20 | response.status = 400; 21 | response.body = { 22 | success: false, 23 | message: `Error: ${error}`, 24 | }; 25 | } 26 | }, 27 | /** 28 | * @description Add a new todo 29 | * @route POST /todos 30 | */ 31 | createTodo: async ( 32 | { request, response }: { request: any; response: any }, 33 | ) => { 34 | const body = await request.body(); 35 | if (!request.hasBody) { 36 | response.status = 400; 37 | response.body = { 38 | success: false, 39 | message: "No data provided", 40 | }; 41 | return; 42 | } 43 | 44 | try { 45 | await TodoModel.add( 46 | { todo: body.value.todo, isCompleted: false }, 47 | ); 48 | response.body = { 49 | success: true, 50 | message: "The record was added successfully", 51 | }; 52 | } catch (error) { 53 | response.status = 400; 54 | response.body = { 55 | success: false, 56 | message: `Error: ${error}`, 57 | }; 58 | } 59 | }, 60 | /** 61 | * @description Get todo by id 62 | * @route GET todos/:id 63 | */ 64 | getTodoById: async ( 65 | { params, response }: { params: { id: string }; response: any }, 66 | ) => { 67 | try { 68 | const isAvailable = await TodoModel.doesExistById( 69 | { id: Number(params.id) }, 70 | ); 71 | 72 | if (!isAvailable) { 73 | response.status = 404; 74 | response.body = { 75 | success: false, 76 | message: "No todo found", 77 | }; 78 | return; 79 | } 80 | 81 | const todo: Todo = await TodoModel.getById({ id: Number(params.id) }); 82 | response.status = 200; 83 | response.body = { 84 | success: true, 85 | data: todo, 86 | }; 87 | } catch (error) { 88 | response.status = 400; 89 | response.body = { 90 | success: false, 91 | message: `Error: ${error}`, 92 | }; 93 | } 94 | }, 95 | /** 96 | * @description Update todo by id 97 | * @route PUT todos/:id 98 | */ 99 | updateTodoById: async ( 100 | { params, request, response }: { 101 | params: { id: string }; 102 | request: any; 103 | response: any; 104 | }, 105 | ) => { 106 | try { 107 | const isAvailable = await TodoModel.doesExistById( 108 | { id: Number(params.id) }, 109 | ); 110 | if (!isAvailable) { 111 | response.status = 404; 112 | response.body = { 113 | success: false, 114 | message: "No todo found", 115 | }; 116 | return; 117 | } 118 | 119 | // if todo found then update todo 120 | const body = await request.body(); 121 | const updatedRows = await TodoModel.updateById({ 122 | id: Number(params.id), 123 | ...body.value, 124 | }); 125 | response.status = 200; 126 | response.body = { 127 | success: true, 128 | message: `Successfully updated ${updatedRows} row(s)`, 129 | }; 130 | } catch (error) { 131 | response.status = 400; 132 | response.body = { 133 | success: false, 134 | message: `Error: ${error}`, 135 | }; 136 | } 137 | }, 138 | /** 139 | * @description Delete todo by id 140 | * @route DELETE todos/:id 141 | */ 142 | deleteTodoById: async ( 143 | { params, response }: { params: { id: string }; response: any }, 144 | ) => { 145 | try { 146 | const updatedRows = await TodoModel.deleteById({ 147 | id: Number(params.id), 148 | }); 149 | response.status = 200; 150 | response.body = { 151 | success: true, 152 | message: `Successfully updated ${updatedRows} row(s)`, 153 | }; 154 | } catch (error) { 155 | response.status = 400; 156 | response.body = { 157 | success: false, 158 | message: `Error: ${error}`, 159 | }; 160 | } 161 | }, 162 | }; 163 | --------------------------------------------------------------------------------