O Deno chegou na versão 1.40 e essa é uma das versões mais legais de todas! Primeiro, porque ela tem a adição da Temporal API que eu estou falando aqui desde 2020! E eu acho que é o primeiro runtime a implementar essa funcionalidade de fato!
Além disso, uma série de outras novidades que eu vou passar por aqui uma por uma!
Temporal API
A temporal API é a nova forma de lidar com as datas no JavaScript, eu falei muito sobre ela neste artigo e mostrei todos os detalhes, então não vou entrar em muitos detalhes aqui, mas essencialmente, o Deno é o primeiro runtime que implementa essa API completamente.
Ela ainda está por trás de uma flag --unstable-temporal
mas você já pode utilizar da mesma forma que a documentação oficial informa! Se você rodar um terminal com deno --unstable-temporal
, você já pode fazer alguns testes:
console.log(Temporal.Now.instant()) // data e hora de hoje
console.log(Temporal.Now.zonedDateTimeISO()) // equivalente ao toISOString
const birthday = Temporal.PlainMonthDay.from("12-15");
const birthdayIn2030 = birthday.toPlainDate({ year: 2030 });
console.log(birthdayIn2030.toString()); // 2030-12-15
Por algum motivo o método
Temporal.Now.timeZoneId
não foi implementado.
Import.meta.filename e dirname
Isso aqui era algo que eu queria muito que acontecesse. Desde o advento dos ECMAScript modules, toda a forma de resolução de módulos mudou, o que significa que pegar o nome de um arquivo ou o diretório onde ele existe não são mais tão simples de buscar.
No Node, temos duas variáveis "mágicas" chamadas __dirname
e __ filename
que retornam respectivamente o caminho do diretório e do arquivo que você está executando.
Mas com ESM não podemos usá-las porque elas não são setadas no início da aplicação, então temos que buscar a URL do módulo com import.meta.url
, que retorna uma fileURL no modelo file://caminho
, e ai temos que usar dirname
nessa URL, mas apenas depois de converter essa URL para um caminho!
import { fileURLToPath } from 'node:url'
import { dirname } from 'node:path'
const fileurl = import.meta.url
const path = fileURLToPath(fileurl)
const dir = dirname(path)
const filename = path.split('/').pop()
console.log({ fileurl, path, dir, filename })
/*
{
fileurl: "file:///Users/lucas/repos/deno/teste.ts",
path: "/Users/lucas/repos/deno/teste.ts",
dir: "/Users/lucas/repos/deno",
filename: "teste.ts"
}
*/
Isso era muito chato! Especialmente se você tinha que lidar com caminhos constantemente, então duas propostas foram adicionadas para poder suportar tanto o arquivo quanto a pasta, chamadas import.meta.filename
e import.meta.dirname
, agora você pode substituir tudo isso por:
console.log(import.meta.dirname) // /Users/lucas/repos/deno
console.log(import.meta.filename) // /Users/lucas/repos/deno/teste.ts
Decorators
Finalmente vamos ter suporte nativo a decorators, uma proposta que está no estágio final e deve chegar nos browsers logo mais! Depois de mais de 5 anos em espera, a nova proposta junta todas as propostas anteriores em uma só.
Um exemplo clássico que a gente pode dar é o @trace
que serve para debugar qualquer função colocando um console antes e depois da execução:
function trace(fn: any, ctx: ClassMethodDecoratorContext) {
return function (...args: unknown[]) {
console.log("ENTERED", ctx.name);
const v = fn(...args);
console.log("EXITED", ctx.name);
return v;
};
}
class App {
@trace
static start() {
console.log("Hello World!");
}
}
App.start();
Imports mais simples
Essa é outra novidade interessante. Antigamente, quando tínhamos import maps com módulos que tinham subdiretórios, tínhamos que definir dois imports diferentes:
{
"imports": {
"preact": "npm:preact@10.5.13",
"preact/": "npm:/preact@10.5.13/"
}
}
Isso permitia que a gente pudesse importar tanto o top-level preact
com import preact from 'preact'
, e também os submódulos tipo import hooks from 'preact/hooks'
.
Agora a simplificação funciona para que você possa só ter um módulo no import map e consiga importar tudo da mesma raiz só com um map:
{
"imports": {
"preact": "npm:preact@10.5.13"
}
}
Embora eu não goste muito de usar import maps e prefira a abordagem de um arquivo
deps.ts
Outras mudanças
-
Uma série de APIs e comandos estão sendo depreciados, em especial o
deno.run
edeno.serveHttp
- Suporte ao
rejectionHandled
, um evento que é disparado sempre que uma exception acontece em uma promise que já foi rejeitada (quando você tem um catch não usado) - Suporte a janelas com WebGPU
- Suporte a novas APIs nativas do Node.js
- Melhores mensagens no deno lint e deno doc