Conheça esse runtime JS focado em segurança com um projeto de exemplo prático.

O Deno é um tempo de execução JavaScript construído no V8, o mesmo mecanismo JavaScript que alimenta o Google Chrome. O criador original do Node.js criou o Deno para resolver algumas das deficiências e preocupações de segurança do Node.js.

Embora seja relativamente novo, o Deno ganhou popularidade como um tempo de execução seguro e moderno do JavaScript. Seu foco em segurança, suporte para recursos de linguagem moderna e ferramentas amigáveis ​​ao desenvolvedor o tornam uma escolha atraente. Você pode usá-lo para criar aplicativos do lado do servidor, ferramentas de linha de comando e outros projetos JavaScript/TypeScript, como uma API simples.

Instalando Deno

Antes de poder usar o Deno, você deve fazer o download e instalá-lo. A instalação do Deno varia dependendo do seu sistema operacional.

No macOS e Linux, você pode instalar o Deno executando este comando:

curl -fsSL https://deno.land/x/install/install.sh | sh
instagram viewer

No Windows, você pode instalar o Deno com Powershell, usando este comando:

irm https://deno.land/install.ps1 | iex

Você pode confirmar que sua instalação foi bem-sucedida executando o comando abaixo:

deno --version

O comando acima deve imprimir a versão Deno no console.

Se você usa o VS Code como IDE, pode baixar Extensão VS Code do Deno para adicionar o IntelliSense, aprimorando sua produtividade e experiência de desenvolvimento ao trabalhar com projetos Deno.

Depois de instalar a extensão com sucesso, crie um .vscode pasta no diretório raiz do seu projeto e crie uma settings.json arquivo nele.

Em seguida, adicione o bloco de código abaixo ao settings.json arquivo para ativar o IntelliSense:

{
"deno.enable": true,
"deno.unstable": true,
}

Conectando a um banco de dados

Para este tutorial, você usará o MongoDB como um banco de dados para manter os dados de sua API.

Para conectar seu aplicativo Deno a um banco de dados MongoDB, crie um db.js arquivo no diretório raiz do seu projeto e adicione o bloco de código abaixo a ele:

// db.js
import { MongoClient } from"https://deno.land/x/[email protected]/mod.ts";

const client = new MongoClient();

try {
await client.connect("mongodb://localhost: 27017/todo");

console.log("Connected to database");
} catch (err) {
console.log("Error connecting to database", err);
}

const db = client.database("todo");

exportdefault db;

Ao contrário do Node.js, que depende de gerenciadores de pacotes como o Node Package Manager (npm) ou yarn, o Deno possui um sistema de gerenciamento de pacotes integrado para importar e gerenciar dependências diretamente de URLs.

Por exemplo, o bloco de código acima importa MongoClientName da URL https://deno.land/x/[email protected]/mod.ts, que leva ao pacote.

Em seguida, usando o driver Deno MongoDB importado (MongoClientName), o Deno estabelece uma conexão entre seu aplicativo e um banco de dados MongoDB local.

Em cenários ao vivo, é mais seguro armazenar suas credenciais de banco de dados em um .env arquivo em vez de armazená-los em texto simples, como feito acima.

Criando um modelo de banco de dados

Enquanto é possível interagir com um banco de dados MongoDB sem um modelo de banco de dados, isso pode levar a um código não estruturado e menos sustentável.

Para evitar isso, crie um TodoModel.ts arquivo no diretório raiz do seu projeto e estruture seus dados adicionando o bloco de código abaixo ao arquivo:

import db from"./db.ts";

interface Todo {
title: string;
description: string;
completed?: boolean;
}

const Todo = db.collection("todos");

exportdefault Todo;

O bloco de código acima define uma interface Pendência que representa a estrutura de um único item de tarefa. Em seguida, usando a interface Todo, ele cria uma coleção Todo chamando o método de coleção exposto por sua instância do MongoDB criada anteriormente.

Criando um servidor com Oak

Oak é um middleware para o servidor HTTP nativo do Deno. Foi inspirado no Koa, que é um alternativa ao Express.js.

Para criar um servidor com Oak, crie um main.ts arquivo no diretório raiz do seu projeto e adicione o bloco de código abaixo ao seu arquivo.

// main.ts

import { Application } from"https://deno.land/x/oak/mod.ts";
import router from"./router.ts";

const app = new Application();

app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: 8000 });
console.log("Server running on port 8000");

O bloco de código acima importa Aplicativo da URL do Oak e cria uma instância do aplicativo (aplicativo) que escuta o tráfego de entrada na porta 8000.

O app.use (router.routes()) line registra as rotas do roteador como middleware no aplicativo Oak. Isso significa que o aplicativo fará a correspondência entre as rotas registradas e as solicitações recebidas e os manipuladores correspondentes serão executados se houver uma correspondência.

O app.use (router.allowedMethods()) A linha lida com métodos HTTP que não são explicitamente definidos no roteador. Por exemplo, se receber uma solicitação com um método não suportado, por exemplo, uma solicitação PUT não registrada, o permitidoMetodos() middleware enviará automaticamente uma resposta apropriada (por exemplo, 405 Método não permitido).

Implementando a Funcionalidade CRUD

Este tutorial apresentará uma API de tarefas simples com funcionalidade CRUD.

Criar uma router.ts arquivo no diretório raiz do seu projeto e adicione o bloco de código abaixo ao seu arquivo:

import { Router } from"https://deno.land/x/oak/mod.ts";
import Todo from"./todoModel.ts";
import { ObjectId } from"https://deno.land/x/[email protected]/mod.ts";

const router = new Router(); // Create Router

O bloco de código acima importa e cria uma instância do roteador Oak. Usando esta instância, você pode criar manipuladores de rota para vários métodos HTTP chamando os respectivos nomes de método (pegar, publicar, colocar, excluir).

Por exemplo, o bloco de código abaixo é um exemplo de como você pode criar um manipulador de rota GET que retorna todos os documentos em sua coleção Todo.

router
.get("/api/todos", (ctx: RouterContextapi/todos">) => {
ctx.response.body = Todo.find();
})

Para enviar um objeto de resposta usando Deno, você deve atribuir o resposta.corpo objeto no RouterContex para o objeto de resposta. O mesmo se aplica aos códigos de status.

Para adicionar outros manipuladores de rota, você pode encadeá-los ao manipulador de rota anterior.

Igual a:

.get("/api/todo/:id", async (ctx: RouterContext<"/api/todo/:id">) => {
try {
const todo = await Todo.findOne({ _id: new ObjectId(ctx.params.id) });

if (!todo) {
ctx.response.status = 404;

ctx.response.body = {
msg: "Todo not found",
};

return;
}

ctx.response.body = todo;
} catch (error) {
ctx.response.status = 500;

ctx.response.body = {
msg: "Error getting todo",
error,
};
}
})

O bloco de código acima define um manipulador de rota GET que retorna um único item Todo que corresponde ao id nos parâmetros de URL.

Em seguida, defina um manipulador de rota CREATE que adiciona novos documentos à sua coleção:

.post("/api/todo/new", async (ctx: RouterContext<"/api/todo/new">) => {
const body = ctx.request.body();
const todo = await body.value;

if (!todo) {
ctx.response.status = 400;
ctx.response.body = { msg: "Invalid data. Please provide a valid todo." };
return;
}

const { title, description } = todo;

if (!(title && description)) {
ctx.response.status = 400;

ctx.response.body = {
msg: "Title or description missing. Please provide a valid todo.",
};

return;
}

try {
await Todo.insertOne({
title: todo.title,
description: todo.description,
completed: false,
});

ctx.response.status = 201;

ctx.response.body = {
msg: "Todo added successfully",
};
} catch (error) {
ctx.response.status = 500;

ctx.response.body = {
msg: "Error adding todo",
error,
};
}
})

Em seguida, adicione um manipulador de rota PUT que atualiza um Todo com base no eu ia parâmetro, com os dados enviados no corpo da requisição.

.put("/api/todo/:id", async (ctx: RouterContext<"/api/todo/:id">) => {
try {
const body = ctx.request.body();
const todo = await body.value;

await Todo.updateOne(
{ _id: new ObjectId(ctx.params.id) },
{ $set: { title: todo.title, description: todo.description } }
);

ctx.response.status = 200;

ctx.response.body = {
msg: "Todo updated successfully",
};
} catch (error) {
console.log(error);
ctx.response.status = 500;

ctx.response.body = {
msg: "Error updating todo",
error: error.message,
};
}
})

Por fim, crie um manipulador de rota DELETE que remove um Todo de sua coleção do MongoDB:

.delete("/api/todo/:id", async (ctx: RouterContext<"/api/todo/:id">) => {
await Todo.deleteOne({ _id: new ObjectId(ctx.params.id) });

ctx.response.status = 200;

ctx.response.body = {
msg: "Todo deleted successfully",
};
});

Você pode iniciar seu aplicativo Deno com este comando:

deno run --allow-net --allow-read --allow-env --watch main.ts

Por padrão, um script Deno não pode acessar nada fora de seu escopo, como a rede ou o sistema de arquivos. Portanto, para iniciar seu aplicativo, você deve incluir vários sinalizadores para conceder ao Deno as permissões necessárias.

--allow-net permite que Deno faça solicitações de rede. --allow-read permite que Deno acesse o sistema de arquivos e leia arquivos. --allow-env permite que Deno acesse variáveis ​​ambientais. O --assistir flag inicia seu aplicativo Deno no modo de relógio.

Migrando de Node.js para Deno

Migrar de Node.js para Deno para criar APIs REST pode trazer benefícios significativos de segurança, produtividade do desenvolvedor e gerenciamento de dependências. Usando o tempo de execução seguro do Deno, suporte nativo a TypeScript e gerenciamento de dependência simplificado, você pode criar facilmente APIs REST robustas e eficientes.

No entanto, o ecossistema imaturo de Deno pode fazer com que você reconsidere. Se você optar por migrar, avalie cuidadosamente os prós e os contras.