Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como usar o MySQL com Deno e Oak


Recentemente escrevi sobre como fazer uma API Todo em Deno + Oak (sem usar um banco de dados) . Você pode encontrar o repositório em chapter_1:oak no GitHub.

Este tutorial continua de onde o outro parou, e vou falar sobre como integrar o MySQL em um projeto Deno e Oak.

Se a qualquer momento você quiser ver todo o código-fonte usado neste tutorial, ele está disponível em chapter_2:mysql . Sinta-se à vontade para dar uma estrela no GitHub se gostar.

Estou assumindo que você já completou o último tutorial mencionado acima. Se não, confira aqui e volte quando terminar.

Antes de começarmos, verifique se você tem um cliente MySQL instalado e em execução:
  • Servidor da comunidade MySQL [Baixe aqui]
  • MySQL Workbench [Baixe aqui]

Eu escrevi um pequeno guia para usuários do Mac OS sobre como configurar o MySQL porque também tive dificuldades com isso. Confira aqui.

Se você estiver em uma máquina Windows, você pode usar as mesmas ferramentas ou também pode usar o XAMPP para ter uma instância MySQL em execução em seu painel.

Assim que você tiver uma instância MySQL em execução, podemos começar nosso tutorial.

Vamos começar


Supondo que você esteja vindo deste artigo, Todo API em Deno + Oak (sem usar um banco de dados) , faremos o seguinte:
  • Criar uma conexão de banco de dados MySQL
  • Escreva um pequeno script que redefina o banco de dados toda vez que iniciamos nosso servidor Deno
  • Executar operações CRUD em uma tabela
  • Adicione a funcionalidade CRUD aos nossos controladores de API

Uma última coisa – aqui está toda a diferença de commit que foi feita no Capítulo 1 para adicionar o MySQL ao projeto (código-fonte que mostra as novas adições feitas no capítulo 1).

Na pasta raiz do seu projeto - o meu é chamado chapter_2:mysql , embora o seu pode ser chamado como você quiser - crie uma pasta chamada db . Dentro dessa pasta, crie um arquivo chamado config.ts e adicione o seguinte conteúdo a ele:
export const DATABASE: string = "deno";
export const TABLE = {
  TODO: "todo",
};

Nada extravagante aqui, apenas definindo nosso nome de banco de dados junto com um objeto para tabelas e depois exportando-o. Nosso projeto terá um banco de dados chamado "deno" e dentro desse banco de dados teremos apenas uma tabela chamada "todo".

Em seguida, dentro do db pasta, crie outro arquivo chamado client.ts e adicione o seguinte conteúdo:
import { Client } from "https://deno.land/x/mysql/mod.ts";
// config
import { DATABASE, TABLE } from "./config.ts";

const client = await new Client();

client.connect({
  hostname: "127.0.0.1",
  username: "root",
  password: "",
  db: "",
});

export default client;

Algumas coisas estão acontecendo aqui.

Estamos importando Client do mysql biblioteca. Client nos ajudará a conectar-se ao nosso banco de dados e realizar operações no banco de dados.
client.connect({
  hostname: "127.0.0.1",
  username: "root",
  password: "",
  db: "",
});

Client fornece um método chamado connect que recebe um objeto onde podemos fornecer o hostname , username , password e db . Com essas informações ele pode estabelecer uma conexão com nossa instância MySQL.

Certifique-se de que seu username não tem password , pois entrará em conflito com a conexão com a biblioteca MySQL do Deno. Se você não sabe como fazer isso, leia este tutorial que escrevi.

Saí do database campo em branco aqui porque quero selecioná-lo manualmente mais tarde no meu script.

Vamos adicionar um script que irá inicializar um banco de dados chamado "deno", selecioná-lo e dentro desse banco de dados criar uma tabela chamada "todo".

Dentro de db/client.ts arquivo vamos fazer algumas novas adições:
import { Client } from "https://deno.land/x/mysql/mod.ts";
// config
import { DATABASE, TABLE } from "./config.ts";

const client = await new Client();

client.connect({
  hostname: "127.0.0.1",
  username: "root",
  password: "",
  db: "",
});

const run = async () => {
  // create database (if not created before)
  await client.execute(`CREATE DATABASE IF NOT EXISTS ${DATABASE}`);
  // select db
  await client.execute(`USE ${DATABASE}`);

  // delete table if it exists before
  await client.execute(`DROP TABLE IF EXISTS ${TABLE.TODO}`);
  // create table
  await client.execute(`
    CREATE TABLE ${TABLE.TODO} (
        id int(11) NOT NULL AUTO_INCREMENT,
        todo varchar(100) NOT NULL,
        isCompleted boolean NOT NULL default false,
        PRIMARY KEY (id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  `);
};

run();

export default client;

Aqui estamos importando DATABASE e TABLE do nosso arquivo de configuração, usando esses valores em uma nova função chamada run() .

Vamos detalhar este run() função. Adicionei comentários no arquivo para ajudar você a entender o fluxo de trabalho:
const run = async () => {
  // create database (if not created before)
  await client.execute(`CREATE DATABASE IF NOT EXISTS ${DATABASE}`);
  // select db
  await client.execute(`USE ${DATABASE}`);

  // delete table if it exists before
  await client.execute(`DROP TABLE IF EXISTS ${TABLE.TODO}`);
  // create table
  await client.execute(`
    CREATE TABLE ${TABLE.TODO} (
        id int(11) NOT NULL AUTO_INCREMENT,
        todo varchar(100) NOT NULL,
        isCompleted boolean NOT NULL default false,
        PRIMARY KEY (id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  `);
};

run();
  • Crie um banco de dados chamado deno . Se já existir, não faça nada.
  • Em seguida, selecione o banco de dados a ser usado, chamado deno
  • Excluir a tabela dentro de deno chamado todo se já existe.
  • Em seguida, crie uma nova tabela dentro do deno db, chame-o de todo , e defina sua estrutura:Ele terá um incremento automático exclusivo id que será um inteiro, outro campo chamado todo que será uma string e, finalmente, um campo chamado isCompleted que é um booleano. Eu também defino id como minha chave primária.

A razão pela qual escrevi este script foi porque não quero ter informações extras na instância do MySQL. Toda vez que o script é executado, ele reinicializa tudo.

Você não precisa adicionar este script. Mas se você não fizer isso, você terá que criar manualmente um banco de dados e a tabela.

Além disso, confira os documentos da biblioteca Deno MySQL sobre criação de banco de dados e criação de tabela.

Voltando à nossa agenda, acabamos de alcançar duas coisas das quatro mencionadas no início do artigo:
  • Criar uma conexão de banco de dados MySQL
  • Escreva um pequeno script que redefina o banco de dados toda vez que iniciamos nosso servidor Deno

Isso já é 50% do tutorial. Infelizmente, não podemos ver muita coisa acontecendo agora. Vamos adicionar rapidamente algumas funcionalidades para que funcionem.

Executar operações CRUD em uma tabela e adicionar a funcionalidade aos nossos controladores de API


Precisamos atualizar nossa interface Todo primeiro. Vá para as interfaces/Todo.ts arquivo e adicione o seguinte:
export default interface Todo {
  id?: number,
  todo?: string,
  isCompleted?: boolean,
}

O que isso ? faz é que torna a chave no objeto opcional. Fiz isso porque mais tarde vou usar funções diferentes para passar objetos com apenas um id , todo , isCompleted , ou todos eles de uma vez.

Se você quiser saber mais sobre propriedades opcionais no TypeScript, acesse seus documentos aqui.

Em seguida, crie uma nova pasta chamada modelos e dentro dessa pasta, crie um arquivo chamado todo.ts . Adicione o seguinte conteúdo ao arquivo:
import client from "../db/client.ts";
// config
import { TABLE } from "../db/config.ts";
// Interface
import Todo from "../interfaces/Todo.ts";

export default {
  /**
   * Takes in the id params & checks if the todo item exists
   * in the database
   * @param id
   * @returns boolean to tell if an entry of todo exits in table
   */
  doesExistById: async ({ id }: Todo) => {},
  /**
   * Will return all the entries in the todo column
   * @returns array of todos
   */
  getAll: async () => {},
  /**
   * Takes in the id params & returns the todo item found
   * against it.
   * @param id
   * @returns object of todo item
   */
  getById: async ({ id }: Todo) => {},
  /**
   * Adds a new todo item to todo table
   * @param todo
   * @param isCompleted
   */
  add: async (
    { todo, isCompleted }: Todo,
  ) => {},
  /**
   * Updates the content of a single todo item
   * @param id
   * @param todo
   * @param isCompleted
   * @returns integer (count of effect rows)
   */
  updateById: async ({ id, todo, isCompleted }: Todo) => {},
  /**
   * Deletes a todo by ID
   * @param id
   * @returns integer (count of effect rows)
   */
  deleteById: async ({ id }: Todo) => {},
};

Agora as funções estão vazias, mas tudo bem. Vamos preenchê-los um por um.

Em seguida, vá para controllers/todo.ts arquivo e certifique-se de adicionar o seguinte:
// interfaces
import Todo from "../interfaces/Todo.ts";
// models
import TodoModel from "../models/todo.ts";

export default {
  /**
   * @description Get all todos
   * @route GET /todos
   */
  getAllTodos: async ({ response }: { response: any }) => {},
  /**
   * @description Add a new todo
   * @route POST /todos
   */
  createTodo: async (
    { request, response }: { request: any; response: any },
  ) => {},
  /**
   * @description Get todo by id
   * @route GET todos/:id
   */
  getTodoById: async (
    { params, response }: { params: { id: string }; response: any },
  ) => {},
  /**
   * @description Update todo by id
   * @route PUT todos/:id
   */
  updateTodoById: async (
    { params, request, response }: {
      params: { id: string };
      request: any;
      response: any;
    },
  ) => {},
  /**
   * @description Delete todo by id
   * @route DELETE todos/:id
   */
  deleteTodoById: async (
    { params, response }: { params: { id: string }; response: any },
  ) => {},
};

Aqui também temos funções vazias. Vamos começar a preenchê-los.

[Obter] todas as APIs de todos


Dentro de models/todo.ts , adicione uma definição para uma função chamada getAll :
import client from "../db/client.ts";
// config
import { TABLE } from "../db/config.ts";
// Interface
import Todo from "../interfaces/Todo.ts";

export default {
   /**
   * Will return all the entries in the todo column
   * @returns array of todos
   */
  getAll: async () => {
    return await client.query(`SELECT * FROM ${TABLE.TODO}`);
  },
}

O Client também expõe outro método além de connect (usamos um método "connect" em db/client.ts file) e isso é query . O client.query O método nos permite executar consultas MySQL diretamente do nosso código Deno como está.

Em seguida, vá para controllers/todo.ts adicionar definição para getAllTodos :
// interfaces
import Todo from "../interfaces/Todo.ts";
// models
import TodoModel from "../models/todo.ts";

export default {
  /**
   * @description Get all todos
   * @route GET /todos
   */
  getAllTodos: async ({ response }: { response: any }) => {
    try {
      const data = await TodoModel.getAll();
      response.status = 200;
      response.body = {
        success: true,
        data,
      };
    } catch (error) {
      response.status = 400;
      response.body = {
        success: false,
        message: `Error: ${error}`,
      };
    }
  },
}

Tudo o que estamos fazendo é importar TodoModel e usando seu método chamado getAll , que acabamos de definir agora. Como ele retorna como uma promessa, nós o envolvemos em async/await.

O método TodoModel.getAll() nos retornará um array que simplesmente retornaremos para response.body com status definido como 200 .

Se a promessa falhar ou houver outro erro, simplesmente vamos ao nosso bloco catch e retornamos o status 400 com success definido como falso. Também definimos a message ao que obtemos do bloco catch.

É isso, terminamos. Agora vamos abrir nosso terminal.

Verifique se sua instância do MySQL está em execução. No seu tipo de terminal:
$ deno run --allow-net server.ts 

Seu terminal deve ficar assim:

Meu console está me dizendo duas coisas aqui.
  1. Que meu servidor Deno API está sendo executado na porta 8080
  2. Que minha instância do MySQL está sendo executada em 127.0.0.1 , que é localhost

Vamos testar nossa API. Estou usando o Postman aqui, mas você pode usar seu cliente de API favorito.

No momento, ele retorna apenas dados vazios. Mas uma vez que adicionamos dados ao nosso todo table, ele retornará esses todos aqui.

Impressionante. Uma API inativa e mais quatro para ir.

[Post] adicionar uma API de tarefas


No models/todo.ts arquivo, adicione a seguinte definição para add() função:
export default {
   /**
   * Adds a new todo item to todo table
   * @param todo
   * @param isCompleted
   */
  add: async (
    { todo, isCompleted }: Todo,
  ) => {
    return await client.query(
      `INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?)`,
      [
        todo,
        isCompleted,
      ],
    );
  },
}

A função add recebe objeto como argumento, que tem dois itens:todo e isCompleted .

Então add: async ({ todo, isCompleted }: Todo) => {} também pode ser escrito como ({todo, isCompleted}: {todo:string, isCompleted:boolean}) . Mas como já temos uma interface definida em nosso interfaces/Todo.ts arquivo que é
export default interface Todo {
  id?: number,
  todo?: string,
  isCompleted?: boolean,
}

podemos simplesmente escrever isso como add: async ({ todo, isCompleted }: Todo) => {} . Isso diz ao TypeScript que esta função tem dois argumentos, todo , que é uma string, e isCompleted , que é um booleano.

Se você quiser ler mais sobre interfaces, o TypeScript tem um excelente documento que você pode encontrar aqui.

Dentro da nossa função temos o seguinte:
return await client.query(
  `INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?)`,
  [
    todo,
    isCompleted,
  ],
);

Esta consulta pode ser dividida em duas partes:
  • INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?) . Os dois pontos de interrogação aqui denotam o uso de variáveis ​​dentro desta consulta.
  • A outra parte, [todo, isCompleted] , são as variáveis ​​que irão na primeira parte da consulta e ser substituído por (?, ?)
  • Table.Todo é apenas uma string vinda do arquivo db/config.ts onde o Table.Todo valor é "todo "

Em seguida, dentro de nosso controllers/todo.ts arquivo, vá para a definição do createTodo() função:
export default {
   /**
   * @description Add a new todo
   * @route POST /todos
   */
  createTodo: async (
    { request, response }: { request: any; response: any },
  ) => {
    const body = await request.body();
    if (!request.hasBody) {
      response.status = 400;
      response.body = {
        success: false,
        message: "No data provided",
      };
      return;
    }

    try {
      await TodoModel.add(
        { todo: body.value.todo, isCompleted: false },
      );
      response.body = {
        success: true,
        message: "The record was added successfully",
      };
    } catch (error) {
      response.status = 400;
      response.body = {
        success: false,
        message: `Error: ${error}`,
      };
    }
  },
}

Vamos dividir isso em duas partes:

Parte 1
const body = await request.body();
if (!request.hasBody) {
  response.status = 400;
  response.body = {
    success: false,
    message: "No data provided",
  };
  return;
}

Tudo o que estamos fazendo aqui é verificar se o usuário está enviando dados no corpo. Caso contrário, retornaremos um status 400 e no corpo retorne success: false e message: <erromessage-string> .

Parte 2
try {
  await TodoModel.add(
    { todo: body.value.todo, isCompleted: false },
  );
  response.body = {
    success: true,
    message: "The record was added successfully",
  };
} catch (error) {
  response.status = 400;
  response.body = {
    success: false,
    message: `Error: ${error}`,
  };
}

Se não houver erro, o TodoModel.add() função é chamada e simplesmente retorna um status de 200 e uma mensagem de confirmação para o usuário.

Caso contrário, apenas lança um erro semelhante ao que fizemos na API anterior.

Agora terminamos. Ative seu terminal e verifique se sua instância MySQL está em execução. No seu tipo de terminal:
$ deno run --allow-net server.ts 

Vá para o Postman e execute a rota da API para este controlador:

Isso é ótimo, agora temos duas APIs funcionando. Faltam apenas três.

[GET] todo por id API


Em seu models/todo.ts arquivo, adicione definição para essas duas funções, doesExistById() e getById() :
export default {
   /**
   * Takes in the id params & checks if the todo item exists
   * in the database
   * @param id
   * @returns boolean to tell if an entry of todo exits in table
   */
  doesExistById: async ({ id }: Todo) => {
    const [result] = await client.query(
      `SELECT COUNT(*) count FROM ${TABLE.TODO} WHERE id = ? LIMIT 1`,
      [id],
    );
    return result.count > 0;
  },
  /**
   * Takes in the id params & returns the todo item found
   * against it.
   * @param id
   * @returns object of todo item
   */
  getById: async ({ id }: Todo) => {
    return await client.query(
      `SELECT * FROM ${TABLE.TODO} WHERE id = ?`,
      [id],
    );
  },
}

Vamos falar sobre cada função uma por uma:
  • doesExistById recebe um id e retorna um boolean indicando se uma tarefa específica existe ou não no banco de dados.

Vamos decompor esta função:
const [result] = await client.query(
  `SELECT COUNT(*) count FROM ${TABLE.TODO} WHERE id = ? LIMIT 1`,
  [id],
);
return result.count > 0;

Simplesmente verificamos a contagem aqui na tabela em relação a um ID de tarefas específico. Se a contagem for maior que zero, retornamos true . Caso contrário, retornamos false .
  • getById retorna o item todo em relação a um id específico:
return await client.query(
  `SELECT * FROM ${TABLE.TODO} WHERE id = ?`,
  [id],
);

Estamos simplesmente executando uma consulta MySQL aqui para obter um todo por id e retornar o resultado como está.

Em seguida, vá para seu controllers/todo.ts e adicione uma definição para um getTodoById método do controlador:
export default {
   /**
   * @description Get todo by id
   * @route GET todos/:id
   */
  getTodoById: async (
    { params, response }: { params: { id: string }; response: any },
  ) => {
    try {
      const isAvailable = await TodoModel.doesExistById(
        { id: Number(params.id) },
      );

      if (!isAvailable) {
        response.status = 404;
        response.body = {
          success: false,
          message: "No todo found",
        };
        return;
      }

      const todo = await TodoModel.getById({ id: Number(params.id) });
      response.status = 200;
      response.body = {
        success: true,
        data: todo,
      };
    } catch (error) {
      response.status = 400;
      response.body = {
        success: false,
        message: `Error: ${error}`,
      };
    }
  },
}

Vamos dividir isso em duas partes menores:
const isAvailable = await TodoModel.doesExistById(
  { id: Number(params.id) },
);

if (!isAvailable) {
  response.status = 404;
  response.body = {
    success: false,
    message: "No todo found",
  };
  return;
}

Primeiro, verificamos se o todo existe no banco de dados em relação a um id usando este método:
const isAvailable = await TodoModel.doesExistById(
  { id: Number(params.id) },
);

Aqui precisamos converter params.id em um Number porque nossa interface de tarefas só aceita id como um número. Em seguida, apenas passamos params.id para o doesExistById método. Este método retornará como um booleano.

Então, simplesmente verificamos se o todo não está disponível e retornamos um 404 método com nossa resposta padrão, como nos endpoints anteriores:
if (!isAvailable) {
  response.status = 404;
  response.body = {
    success: false,
    message: "No todo found",
  };
  return;
}

Então nós temos:
try {
const todo: Todo = await TodoModel.getById({ id: Number(params.id) });
response.status = 200;
response.body = {
  success: true,
  data: todo,
};
} catch (error) {
response.status = 400;
response.body = {
  success: false,
  message: `Error: ${error}`,
};

Isso é semelhante ao que estávamos fazendo em nossas APIs anteriores. Aqui estamos simplesmente obtendo dados do banco de dados, definindo a variável todo e, em seguida, retornando a resposta. Se houver um erro, simplesmente retornamos uma mensagem de erro padrão no bloco catch para o usuário.

Agora inicie seu terminal e verifique se sua instância MySQL está em execução. No seu tipo de terminal:
$ deno run --allow-net server.ts 

Vá para o Postman e execute a rota da API para este controlador.

Lembre-se que toda vez que reiniciamos nosso servidor nós resetamos o db. Se você não quiser esse comportamento, você pode simplesmente comentar o run função no arquivo db/client.ts .
retornará o todo para esse id se encontrado" width="2000" height="1165" loading=" preguiçoso">
Até agora, fizemos APIs para:
  • Obter todos
  • Criar uma nova tarefa
  • Obter uma tarefa por ID

E aqui estão as APIs restantes:
  • Atualizar uma tarefa por ID
  • Excluir uma tarefa por ID

[PUT] atualizar todo pela API de id


Vamos criar um modelo para esta API primeiro. Acesse nosso models/todo.ts arquivo e adicione uma definição para um updateById função:
**
 * Updates the content of a single todo item
 * @param id
 * @param todo
 * @param isCompleted
 * @returns integer (count of effect rows)
 */
updateById: async ({ id, todo, isCompleted }: Todo) => {
  const result = await client.query(
    `UPDATE ${TABLE.TODO} SET todo=?, isCompleted=? WHERE id=?`,
    [
      todo,
      isCompleted,
      id,
    ],
  );
  // return count of rows updated
  return result.affectedRows;
},

O updateById leva em 3 parâmetros:id , todo e isCompleted .

Simplesmente executamos uma consulta MySQL dentro desta função:
onst result = await client.query(
  `UPDATE ${TABLE.TODO} SET todo=?, isCompleted=? WHERE id=?`,
  [
    todo,
    isCompleted,
    id,
  ],
);

Isso atualiza o todo de um único item de tarefas e isCompleted por um id específico .

Em seguida, retornamos uma contagem de linhas atualizadas por esta consulta fazendo:
  // return count of rows updated
  return result.affectedRows;

A contagem será 0 ou 1, mas nunca mais que 1. Isso ocorre porque temos IDs exclusivos em nosso banco de dados – vários todos com o mesmo ID não podem existir.

Em seguida, vá para nossos controllers/todo.ts arquivo e adicione uma definição para um updateTodoById função:
updateTodoById: async (
  { params, request, response }: {
    params: { id: string };
    request: any;
    response: any;
  },
) => {
  try {
    const isAvailable = await TodoModel.doesExistById(
      { id: Number(params.id) },
    );
    if (!isAvailable) {
      response.status = 404;
      response.body = {
        success: false,
        message: "No todo found",
      };
      return;
    }

    // if todo found then update todo
    const body = await request.body();
    const updatedRows = await TodoModel.updateById({
      id: Number(params.id),
      ...body.value,
    });
    response.status = 200;
    response.body = {
      success: true,
      message: `Successfully updated ${updatedRows} row(s)`,
    };
  } catch (error) {
    response.status = 400;
    response.body = {
      success: false,
      message: `Error: ${error}`,
    };
  }
},

Isso é quase o mesmo de nossas APIs anteriores que escrevemos. A parte que é nova aqui é esta:
// if todo found then update todo
const body = await request.body();
const updatedRows = await TodoModel.updateById({
  id: Number(params.id),
  ...body.value,
});

Nós simplesmente pegamos o corpo que o usuário nos envia em JSON e passamos o corpo para nosso TodoModel.updateById função.

Temos que converter o id para um número para cumprir com nossa interface Todo.

A consulta é executada e retorna a contagem de linhas atualizadas. A partir daí, simplesmente o devolvemos em nossa resposta. Se houver um erro, ele vai para o bloco catch onde retornamos nossa mensagem de resposta padrão.

Vamos executar isso e ver se funciona. Verifique se sua instância do MySQL está em execução e execute o seguinte no seu terminal:
$ deno run --allow-net server.ts 

Vá para o Postman e execute a rota da API para este controlador:

[DELETE] todo por id API


Em seu models/todo.ts arquivo crie uma função chamada deleteById :
/**
 * Deletes a todo by ID
 * @param id
 * @returns integer (count of effect rows)
 */
deleteById: async ({ id }: Todo) => {
  const result = await client.query(
    `DELETE FROM ${TABLE.TODO} WHERE id = ?`,
    [id],
  );
  // return count of rows updated
  return result.affectedRows;
},

Aqui nós simplesmente passamos um id como um parâmetro e, em seguida, use a consulta de exclusão do MySQL. Em seguida, retornamos a contagem atualizada de linhas. A contagem atualizada será 0 ou 1 porque o ID de cada tarefa é exclusivo.

Em seguida, vá em seu controllers/todo.ts arquivo e defina um deleteByTodoId método:
/**
 * @description Delete todo by id
 * @route DELETE todos/:id
 */
deleteTodoById: async (
  { params, response }: { params: { id: string }; response: any },
) => {
  try {
    const updatedRows = await TodoModel.deleteById({
      id: Number(params.id),
    });
    response.status = 200;
    response.body = {
      success: true,
      message: `Successfully updated ${updatedRows} row(s)`,
    };
  } catch (error) {
    response.status = 400;
    response.body = {
      success: false,
      message: `Error: ${error}`,
    };
  }
},

Isso é bem direto. Passamos o params.id ao nosso TodoModel.deleteById e retornar a contagem de linhas atualizadas com esta consulta.

Se algo der errado, um erro é lançado no bloco catch que retorna nossa resposta de erro padrão.

Vamos verificar isso.

Verifique se sua instância do MySQL está em execução. No seu tipo de terminal:
$ deno run --allow-net server.ts 

Vá para o Postman e execute a rota da API para este controlador:

Com isso, terminamos com nosso tutorial Deno + Oak + MySQL.

Todo o código fonte está disponível aqui:https://github.com/adeelibr/deno-playground. Se você encontrar um problema, é só me avisar. Ou sinta-se à vontade para fazer um pull request e eu lhe darei crédito no repositório.

Se você achou este tutorial útil, compartilhe-o. E como sempre, estou disponível no Twitter em @adeelibr. Eu adoraria ouvir seus pensamentos sobre isso.