Bom dia amigos!
Apresento a sua atenção a tradução do artigo "The Deno Handbook: A TypeScript Runtime Tutorial with Code Examples" de Flavio Copes.
Neste artigo, aprenderemos como trabalhar com Deno. Vamos compará-lo ao Node.js e construir uma API REST simples com ele.
O que é Deno?
Se você está familiarizado com Node.js, o popular ecossistema JavaScript do lado do servidor, Deno é praticamente a mesma coisa. Quase, mas não exatamente.
Vamos começar com uma lista dos recursos do Deno que mais gosto:
- É baseado em JavaScript moderno
- Possui uma biblioteca padrão extensível
- Ele tem suporte para TypeScript padrão (isso significa que você não precisa compilar manualmente o TypeScript, o Deno faz isso automaticamente)
- Suporta módulos ES
- Não tem gerenciador de pacotes
- Tem um global
await
- Tem uma instalação de teste embutida
- Seu objetivo é a compatibilidade máxima do navegador. Para isso, ele fornece um
fetch
objeto inline e um globalwindow
Neste tutorial, exploraremos todas essas possibilidades.
Depois de se familiarizar com o Deno e seus recursos, o Node.js parecerá um pouco desatualizado.
Especialmente porque o Node.js é baseado em funções de retorno de chamada (ele foi escrito antes de promises e async / await). É improvável que eles apareçam lá, pois isso significa que mudanças fundamentais são necessárias.
O Node.js é ótimo e continuará sendo o padrão de fato no mundo do JavaScript. No entanto, acredito que a popularidade do Deno crescerá rapidamente graças ao seu suporte TypeScript e à biblioteca padrão moderna.
O Deno pode pagar um código moderno, pois não precisa de compatibilidade com versões anteriores. Claro, não há garantia de que esse código permanecerá atualizado na próxima década, mas hoje está.
Por que Deno? Porque agora?
Deno foi anunciado há quase 2 anos pelo criador do Node.js, Ryan Dahl, na JSConf EU. Assista ao vídeo do YouTube , é muito interessante e imperdível se você está trabalhando com Node.js e JavaScript.
Cada gerente de projeto (criador) é forçado a tomar decisões. Ryan lamenta algumas das primeiras decisões em Node. Além disso, a tecnologia avança e o JavaScript é uma linguagem completamente diferente hoje do que era em 2009 quando o Node. Pense no ES6 / 2016/2017 e assim por diante.
Então ele decidiu iniciar um novo projeto, uma espécie de segunda onda de aplicativos JavaScript do lado do servidor.
Só estou escrevendo este artigo agora porque leva muito tempo para a tecnologia amadurecer. Por fim, obtivemos o Deno 1.0 (lançado em 13 de maio de 2020), a primeira versão estável.
Este pode parecer um número comum, mas 1.0 significa que não haverá nenhuma mudança drástica até o Deno 2.0. Ao aprender uma nova tecnologia, você não quer que ela mude muito rapidamente.
Você deve aprender Deno?
Boa pergunta.
Aprender algo novo como Deno exige muito esforço. Meu conselho: se você está apenas começando com JS do lado do servidor e não conhece o Node.js ainda, e nunca escreveu TypeScript antes, comece com o Node.
Ninguém foi demitido por escolher a Node ainda (parafraseando uma frase famosa).
Mas se você gosta do TypeScript, que não depende de muitos pacotes npm, e quer usá-lo em qualquer lugar
await
, o Deno pode ser o que você está procurando.
Ele substituirá o Node.js?
Não. O Node.js é um gigante, uma grande autoridade, uma tecnologia incrivelmente bem suportada que não chegará a lugar nenhum na próxima década.
Suporte TypeScript de primeira classe
Deno é escrito em Rust e TypeScript, duas linguagens muito populares no mundo de hoje.
Isso significa que obtemos muitos benefícios do TypeScript, mesmo que estejamos escrevendo JavaScript.
A execução do código TypeScript com Deno não requer compilação - Deno faz isso automaticamente.
Você não precisa escrever código TypeScript, mas o fato de o núcleo do Deno ser escrito em TypeScript faz uma grande diferença.
Primeiro, uma grande porcentagem de desenvolvedores de JavaScript ama o TypeScript.
Em segundo lugar, as ferramentas que você usa podem obter muitas informações sobre softwares escritos em TypeScript, como o Deno.
Isso significa que, quando escrevemos código em VS Code, por exemplo (que foi totalmente integrado ao TypeScript desde seu início), obtemos benefícios como verificação de tipo ao escrever código ou recursos avançados de IntelliSense. Em outras palavras, a ajuda do editor de código se torna muito mais eficiente.
Diferenças do Node.js
Como o Deno é essencialmente um substituto do Node.js, faz sentido comparar os dois.
Geral:
- Ambos são baseados no motor V8
- Ambos são ótimos para o desenvolvimento de JavaScript do lado do servidor
Diferenças:
- O Node é escrito em C ++ e JavaScript. Deno é escrito em Rust e TypeScript.
- O Node possui um gerenciador de pacotes oficial
npm
. O Deno não tem esse gerenciador; em vez disso, ele permite importar qualquer módulo usando uma URL. - O Node usa a sintaxe CommonJS para importar pacotes. Deno usa a forma oficial - módulos ES.
- Deno ECMAScript , Node.js .
- Deno () . . Node.js , .
- Deno , .. , , Go, . .
Não ter um gerenciador de pacotes e usar uma URL para obter e importar pacotes tem suas vantagens e desvantagens. Uma das principais vantagens é a grande flexibilidade na capacidade de criar pacotes sem ter que publicá-los em um repositório como o npm.
Acho que alguma alternativa ao gerenciador de pacotes no Deno aparecerá mais cedo ou mais tarde.
O site oficial da Deno está hospedando pacotes de terceiros: https://deno.land/x/
Instalando Deno
Chega de conversa! Vamos instalar o Deno.
A maneira mais fácil de fazer isso é usando o Homebrew:
brew install deno
Outros métodos de instalação estão listados aqui .
Após a instalação, o comando fica disponível
deno
. Aqui está a ajuda que você pode obter digitando deno --help
:
flavio@mbp~> deno --help
deno 0.42.0
A secure JavaScript and TypeScript runtime
Docs: https://deno.land/std/manual.md
Modules: https://deno.land/std/ https://deno.land/x/
Bugs: https://github.com/denoland/deno/issues
To start the REPL, supply no arguments:
deno
To execute a script:
deno run https://deno.land/std/examples/welcome.ts
deno https://deno.land/std/examples/welcome.ts
To evaluate code in the shell:
deno eval "console.log(30933 + 404)"
Run 'deno help run' for 'run'-specific flags.
USAGE:
deno [OPTIONS] [SUBCOMMAND]
OPTIONS:
-h, --help
Prints help information
-L, --log-level <log-level>
Set log level [possible values: debug, info]
-q, --quiet
Suppress diagnostic output
By default, subcommands print human-readable diagnostic messages to stderr.
If the flag is set, restrict these messages to errors.
-V, --version
Prints version information
SUBCOMMANDS:
bundle Bundle module and dependencies into single file
cache Cache the dependencies
completions Generate shell completions
doc Show documentation for a module
eval Eval script
fmt Format source files
help Prints this message or the help of the given subcommand(s)
info Show info about cache or info related to source file
install Install script as an executable
repl Read Eval Print Loop
run Run a program given a filename or url to the module
test Run tests
types Print runtime TypeScript declarations
upgrade Upgrade deno executable to newest version
ENVIRONMENT VARIABLES:
DENO_DIR Set deno's base directory (defaults to $HOME/.deno)
DENO_INSTALL_ROOT Set deno install's output directory
(defaults to $HOME/.deno/bin)
NO_COLOR Set to disable color
HTTP_PROXY Proxy address for HTTP requests
(module downloads, fetch)
HTTPS_PROXY Same but for HTTPS
Deno Times
Você notou a seção
SUBCOMMANDS
? Esta é uma lista de todos os comandos que podemos executar. Que times nós temos?
bundle
- coleta o módulo e as dependências do projeto em um arquivocache
- armazena dependênciascompletions
- gera recargas de shelldoc
- mostra a documentação do móduloeval
- usado para calcular um bloco de código, por exemplodeno eval "console.log(1 + 2)"
fmt
- formatador de código integrado (comogoFmt
em Go)help
- exibe uma lista de comandos auxiliaresinfo
- mostra informações sobre o cache ou arquivoinstall
- define o script como executávelrepl
- ciclo de leitura-cálculo-saída (padrão)run
- executa o programa com o nome ou URL fornecido para o módulotest
- executa testestypes
- exibe uma lista de recursos do TypeScriptupgrade
- atualiza Deno para a versão mais recente
Você pode executar
deno <subcommand> help
para obter informações sobre um comando específico, por exemplo deno run --help
.
Podemos usar um comando
deno
para iniciar um loop de leitura-avaliação-saída:
Isso é o mesmo que iniciar
deno repl
.
Normalmente
deno
usado para iniciar um aplicativo Deno contido em um arquivo TypeScript.
Você pode executar arquivos TypeScript (.ts) e arquivos JavaScript (.js).
Se você não estiver familiarizado com o TypeScript, não se preocupe: Deno é escrito em TypeScript, mas você pode escrever seus aplicativos cliente em JavaScript.
Primeiro aplicativo no Deno
Vamos criar nosso primeiro aplicativo.
Para fazer isso, não precisamos nem escrever código, vamos executá-lo no terminal usando a URL.
Deno baixa o programa, compila-o e executa-o:
claro, não recomendo executar código aleatório da Internet. Neste caso, estamos lançando-o do site oficial do Deno, além disso, o Deno tem uma sandbox que impede os programas de fazerem o que não permitimos explicitamente.
Este programa é muito simples e é uma chamada
console.log()
:
console.log('Welcome to Deno ') // ,
Se você abrir https://deno.land/std/examples/welcome.ts em um navegador, verá o seguinte:
Estranho, não é? Você provavelmente esperava ver um arquivo TypeScript, mas, em vez disso, obteve uma página da web. A questão é que o servidor do site Deno sabe que você está usando um navegador e fornece uma página mais amigável.
Carregue a mesma URL usando
wget
, por exemplo, e obtenha text/plain
em seu lugar text/html
:
Quando você reinicia o programa, graças ao cache, nenhuma reinicialização é necessária: Uma reinicialização forçada pode ser executada
usando o sinalizador
--reload
:
deno run
tem muitas funções diferentes que não são exibidas por deno --help
. Para vê-los, você deve executar deno run --help
:
flavio@mbp~> deno run --help
deno-run
Run a program given a filename or url to the module.
By default all programs are run in sandbox without access to disk, network or
ability to spawn subprocesses.
deno run https://deno.land/std/examples/welcome.ts
Grant all permissions:
deno run -A https://deno.land/std/http/file_server.ts
Grant permission to read from disk and listen to network:
deno run --allow-read --allow-net https://deno.land/std/http/file_server.ts
Grant permission to read whitelisted files from disk:
deno run --allow-read=/etc https://deno.land/std/http/file_server.ts
USAGE:
deno run [OPTIONS] <SCRIPT_ARG>...
OPTIONS:
-A, --allow-all
Allow all permissions
--allow-env
Allow environment access
--allow-hrtime
Allow high resolution time measurement
--allow-net=<allow-net>
Allow network access
--allow-plugin
Allow loading plugins
--allow-read=<allow-read>
Allow file system read access
--allow-run
Allow running subprocesses
--allow-write=<allow-write>
Allow file system write access
--cached-only
Require that remote dependencies are already cached
--cert <FILE>
Load certificate authority from PEM encoded file
-c, --config <FILE>
Load tsconfig.json configuration file
-h, --help
Prints help information
--importmap <FILE>
UNSTABLE:
Load import map file
Docs: https://deno.land/std/manual.md#import-maps
Specification: https://wicg.github.io/import-maps/
Examples: https://github.com/WICG/import-maps#the-import-map
--inspect=<HOST:PORT>
activate inspector on host:port (default: 127.0.0.1:9229)
--inspect-brk=<HOST:PORT>
activate inspector on host:port and break at start of user script
--lock <FILE>
Check the specified lock file
--lock-write
Write lock file. Use with --lock.
-L, --log-level <log-level>
Set log level [possible values: debug, info]
--no-remote
Do not resolve remote modules
-q, --quiet
Suppress diagnostic output
By default, subcommands print human-readable diagnostic messages to stderr.
If the flag is set, restrict these messages to errors.
-r, --reload=<CACHE_BLACKLIST>
Reload source code cache (recompile TypeScript)
--reload
Reload everything
--reload=https://deno.land/std
Reload only standard modules
--reload=https://deno.land/std/fs/utils.ts,https://deno.land/std/fmt/colors.ts
Reloads specific modules
--seed <NUMBER>
Seed Math.random()
--unstable
Enable unstable APIs
--v8-flags=<v8-flags>
Set V8 command line options. For help: --v8-flags=--help
ARGS:
<SCRIPT_ARG>...
script args
Exemplos de código
Existem outros exemplos no site do Deno que podem ser encontrados aqui .
No momento da redação deste artigo, o seguinte poderia ser encontrado no repositório especificado:
cat.ts
- exibe o conteúdo dos arquivos passados como argumentoscatj.ts
- faz a mesma coisa,cat.ts
mas primeiro executa algumas manipulações com o conteúdo dos arquivoschat/
- implementação de chatcolors.ts
- um exemplo de estilização de texto usando móduloscurl.ts
- uma implementação simplescurl
que produz o conteúdo do URL passado como um argumentoecho_server.ts
- servidor de eco TCPgist.ts
- programa para colocar arquivos em gist.github.comtest.ts
- programa de testewelcome.ts
- o programa que lançamosxeval.ts
- permite que você execute o TypeScript obtido de qualquer fonte de dados padrão.deno xeval
foi removido da lista de times oficiais
Primeiro aplicativo real no Deno
Vamos escrever algum código.
O primeiro aplicativo com o qual lançamos
deno run https://deno.land/std/examples/welcome.ts
já foi escrito, então você não aprendeu nada novo sobre o Deno.
Vamos começar com um exemplo padrão postado no site Deno:
import { serve } from 'https://deno.land/std/http/server.ts'
const s = serve({ port: 8000 })
console.log('http://localhost:8000/')
for await (const req of s) {
req.respond({ body: 'Hello World\n' })
}
Aqui estamos importando uma função
serve
de um módulo http/server
. Vejo? Não foi necessário instalá-lo e ele não está armazenado em nosso computador como os módulos Node. Este é um dos motivos da rápida instalação do Deno.
Com a ajuda
https://deno.land/std/http/server.ts
, importamos a versão mais recente do módulo. Uma versão específica pode ser importada usando @VERSION
:
import { serve } from 'https://deno.land/std@v0.42.0/http/server.ts'
Esta é a função
serve
:
/**
* Create a HTTP server
*
* import { serve } from "https://deno.land/std/http/server.ts";
* const body = "Hello World\n";
* const s = serve({ port: 8000 });
* for await (const req of s) {
* req.respond({ body });
* }
*/
export function serve(addr: string | HTTPOptions): Server {
if (typeof addr === 'string') {
const [hostname, port] = addr.split(':')
addr = { hostname, port: Number(port) }
}
const listener = listen(addr)
return new Server(listener)
}
Em seguida, chamamos a função
serve()
e passamos a ela um objeto com uma propriedade port
.
Em seguida, executamos um loop para responder a cada solicitação do servidor:
for await (const req of s) {
req.respond({ body: 'Hello World\n' })
}
Observe que estamos usando a palavra-chave
await
sem envolver o código em uma async
função.
Vamos executar o programa localmente. Estou usando o VS Code, mas você pode usar qualquer editor.
Eu recomendo instalar uma extensão de justjavac (há outra com um nome semelhante, mas está obsoleta e pode desaparecer no futuro): A
extensão fornece vários utilitários para ajudá-lo a escrever aplicativos Deno.
Vamos criar um arquivo
app.ts
e colar nosso código nele:
Execute-o com
deno run app.ts
:
Deno irá carregar todas as dependências que o programa precisa, mas primeiro a que importamos no arquivo.
O arquivo https://deno.land/std/http/server.ts tem várias dependências próprias:
import { encode } from '../encoding/utf8.ts'
import { BufReader, BufWriter } from '../io/bufio.ts'
import { assert } from '../testing/asserts.ts'
import { deferred, Deferred, MuxAsyncIterator } from '../async/mod.ts'
import {
bodyReader,
chunkedBodyReader,
emptyReader,
writeResponse,
readRequest,
} from './_io.ts'
import Listener = Deno.Listener
import Conn = Deno.Conn
import Reader = Deno.Reader
Essas dependências são importadas automaticamente.
No final, temos um problema: o
que está acontecendo? Recebemos um erro de permissão negada.
Vamos falar sobre a sandbox.
Caixa de areia
Como mencionei antes, o Deno tem uma sandbox que impede os programas de fazer coisas para as quais não receberam permissão.
O que isto significa?
Como Ryan disse em sua palestra, às vezes você deseja executar um programa JavaScript fora do navegador e não deseja que o programa tenha acesso a tudo em seu sistema. Ou quando se trata do mundo externo usando a rede.
Nada impede que o aplicativo Node.js obtenha sua chave SSH ou outras informações de seu sistema e as envie para o servidor. É por isso que normalmente só instalamos pacotes Node de fontes confiáveis. Mas como sabemos se um dos projetos que estamos usando foi hackeado?
Deno imita o sistema de permissão usado pelo navegador. O código JavaScript em execução em um navegador não pode fazer nada com o seu sistema, a menos que você permita explicitamente.
Voltando ao Deno, se um programa precisa de acesso à rede, temos que dar a ele permissão para fazê-lo.
Isso é feito usando o sinalizador
--allow-net
:
deno run --allow-net app.ts
O servidor agora está sendo executado na porta 8000:
Outros sinalizadores:
--allow-env
- permite acesso a variáveis de ambiente--allow-hrtime
- permite medição de alta resolução--allow-net=<allow-net>
- permite acesso à rede--allow-plugin
- permite carregar plugins--allow-read=<allow-read>
- permite a leitura de arquivos--allow-run
- permite iniciar subprocessos--allow-write=<allow-write>
- permite gravar arquivos--allow-all
- concede todas as permissões (semelhante-A
)
Permissões para
net
, read
e write
pode ser parcial. Por exemplo, podemos permitir que arquivos somente leitura que estão em um determinado diretório: --allow-read=/dev
.
Formatação de código
Uma das coisas que adoro no Go é o comando
gofmt
. Todo o código Go parece o mesmo. Todo mundo está usando gofmt
.
Os desenvolvedores de JavaScript geralmente usam o Prettier e,
deno fmt
na verdade, também o usam em segundo plano.
Digamos que você tenha um arquivo mal formatado:
você inicia
deno fmt app.ts
e a formatação automática ocorre sem ponto-e-vírgula:
Biblioteca padrão
A biblioteca padrão de Deno é bastante extensa, apesar da idade do projeto.
Inclui o seguinte:
archieve
- utilitários para arquivamentoasync
- utilitários para trabalhar com código assíncronobytes
- funções auxiliares para divisão de bytesdatetime
- análise de datas / horasencoding
- codificação / decodificação em diferentes formatosflags
- analisando sinalizadores de linha de comandofmt
- formação e exibiçãofs
- interface do aplicativo para trabalhar com o sistema de arquivoshash
- biblioteca de criptografiahttp
- servidor HTTPio
- biblioteca de operações de entrada / saídalog
- utilitários para registromime
- suporte de dados mistosnode
- camada de compatibilidade retroativa com Nodepath
- trabalhar com caminhosws
- soquetes web
Mais um exemplo
Vamos dar uma olhada em outro exemplo oficial -
cat.ts
:
const filenames = Deno.args
for (const filename of filenames) {
const file = await Deno.open(filename)
await Deno.copy(file, Deno.stdout)
file.close()
}
Atribuímos
filenames
conteúdo a uma variável Deno.args
, que é uma variável que contém os argumentos passados usando a linha de comando.
Nós iteramos sobre eles e, para cada um, primeiro os usamos
Deno.open()
para abrir o arquivo e, em seguida, Deno.copy()
copiamos o conteúdo para Deno.stdout
. Finalmente, fechamos o arquivo.
Se você executar:
deno run https://deno.land/std/examples/cat.ts
O programa irá carregar e compilar, mas nada acontece porque não passamos nenhum argumento.
Agora vamos tentar isso:
deno run https://deno.land/std/examples/cat.ts app.ts
Recebemos erro de permissão:
Deno não tem acesso ao sistema por padrão. Vamos conceder a ele essa permissão com
--allow-read
:
deno run --allow-read=./ https://deno.land/std/examples/cat.ts app.ts
Expresso / Hapi / Koa / * existe para Deno?
Ah com certeza. Dê uma olhada nos seguintes projetos:
Exemplo: usando Oak para criar uma API REST
Vou criar uma API REST usando Oak. Oak é interessante porque é inspirado em Koa, o middleware popular para NOde.js, e tem uma sintaxe semelhante.
Nossa API será muito simples.
Nosso servidor armazenará na memória uma lista de cães, seus nomes e idades.
Queremos obter a seguinte funcionalidade:
- adicionar novos cachorros à lista
- obtenha uma lista de todos os cães
- obter informações sobre um cachorro específico
- remova um cachorro da lista
- atualizar a idade do cachorro
Estaremos escrevendo o código em Typescript, mas nada impede que você faça isso em JavaScript - apenas não especifique os tipos de dados.
Criamos um arquivo
app.ts
.
Vamos começar importando objetos de
Application
e Router
para Oak
:
import { Application, Router } from 'https://deno.land/x/oak/mod.ts'
Obtemos as variáveis de ambiente PORT e HOST:
const env = Deno.env.toObject()
const PORT = env.PORT || 4000
const HOST = env.HOST || '127.0.0.1'
Por padrão, nosso aplicativo será executado em localhost: 4000.
Crie um aplicativo Oak e inicie-o:
const router = new Router()
const app = new Application()
app.use(router.routes())
app.use(router.allowedMethods())
console.log(`Listening on port ${PORT}...`)
await app.listen(`${HOST}:${PORT}`)
O aplicativo agora deve funcionar.
Nós verificamos:
deno run --allow-env --allow-net app.ts
O Deno baixa as dependências:
E começa a escutar na porta 4000.
Na reinicialização, a etapa de instalação será ignorada graças ao cache:
Defina uma interface para o cão e, em seguida, defina um array
dog
contendo os objetos Dog
:
interface Dog {
name: string
age: number
}
let dogs: Array<Dog> = [
{
name: 'Roger',
age: 8,
},
{
name: 'Syd',
age: 7,
},
]
Vamos começar a implementar a API.
Tudo está no lugar. Vamos adicionar algumas funções ao roteador que serão chamadas ao acessar o endpoint especificado:
const router = new Router()
router
.get('/dogs', getDogs)
.get('/dogs/:name', getDog)
.post('/dogs', addDog)
.put('/dogs/:name', updateDog)
.delete('/dogs/:name', removeDog)
Nós definimos o seguinte:
GET /dogs
GET /dogs/:name
POST /dogs
PUT /dogs/:name
DELETE /dogs/:name
Vamos implementar essas rotas uma por uma.
Vamos começar com
GET /dogs
, que retorna uma lista de todos os cães:
export const getDogs = ({ response }: { response: any }) => {
response.body = dogs
}
Veja como obter um cachorro específico pelo nome:
export const getDog = ({
params,
response,
}: {
params: {
name: string
},
response: any
}) => {
const dog = dogs.filter(dog => dog.name === params.name)
if (dog.length) {
response.status = 200
response.body = dog[0]
return
}
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
}
Veja como adicionar um novo cachorro à lista:
export const addDog = async ({
request,
response,
}: {
request: any
response: any
}) => {
const body = await request.body()
const dog: Dog = await body.value
dogs.push(dog)
response.body = { msg: 'OK' }
response.status = 200
}
Veja como atualizar a idade do seu cão:
export const updateDog = async ({
params,
request,
response,
}: {
params: {
name: string
},
request: any
response: any
}) => {
const temp = dogs.filter((existingDog) => existingDog.name === params.name)
const body = await request.body()
const { age }: { age: number } = await body.value
if (temp.length) {
temp[0].age = age
response.status = 200
response.body = { msg: 'OK' }
return
}
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
}
E aqui está como remover um cachorro da lista:
export const removeDog = ({
params,
response,
}: {
params: {
name: string
},
response: any
}) => {
const lengthBefore = dogs.length
dogs = dogs.filter((dog) => dog.name !== params.name)
if (dogs.length === lengthBefore) {
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
return
}
response.body = { msg: 'OK' }
response.status = 200
}
Código completo do aplicativo:
import { Application, Router } from 'https://deno.land/x/oak/mod.ts'
const env = Deno.env.toObject()
const PORT = env.PORT || 4000
const HOST = env.HOST || '127.0.0.1'
interface Dog {
name: string
age: number
}
let dogs: Array<Dog> = [
{
name: 'Roger',
age: 8,
},
{
name: 'Syd',
age: 7,
},
]
export const getDogs = ({ response }: { response: any }) => {
response.body = dogs
}
export const getDog = ({
params,
response,
}: {
params: {
name: string
},
response: any
}) => {
const dog = dogs.filter(dog => dog.name === params.name)
if (dog.length) {
response.status = 200
response.body = dog[0]
return
}
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
}
export const addDog = async ({
request,
response,
}: {
request: any
response: any
}) => {
const body = await request.body()
const { name, age }: { name: string; age: number } = await body.value
dogs.push({
name: name,
age: age,
})
response.body = { msg: 'OK' }
response.status = 200
}
export const updateDog = async ({
params,
request,
response,
}: {
params: {
name: string
},
request: any
response: any
}) => {
const temp = dogs.filter((existingDog) => existingDog.name === params.name)
const body = await request.body()
const { age }: { age: number } = await body.value
if (temp.length) {
temp[0].age = age
response.status = 200
response.body = { msg: 'OK' }
return
}
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
}
export const removeDog = ({
params,
response,
}: {
params: {
name: string
},
response: any
}) => {
const lengthBefore = dogs.length
dogs = dogs.filter(dog => dog.name !== params.name)
if (dogs.length === lengthBefore) {
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
return
}
response.body = { msg: 'OK' }
response.status = 200
}
const router = new Router()
router
.get('/dogs', getDogs)
.get('/dogs/:name', getDog)
.post('/dogs', addDog)
.put('/dogs/:name', updateDog)
.delete('/dogs/:name', removeDog)
const app = new Application()
app.use(router.routes())
app.use(router.allowedMethods())
console.log(`Listening on port ${PORT}...`)
await app.listen(`${HOST}:${PORT}`)
Obrigado pela atenção.