Você já fez sua própria biblioteca node.js?
Muitos dos projetos que criamos hoje em dia acabam usando bibliotecas externas, seja pra coisas simples como formatar uma data, ou até tarefas mais complexas, como criptografar dados ou lidar com streams.
Isso já virou parte do nosso dia a dia como dev. E tá tudo certo com isso. Mas às vezes, no meio dessa rotina, a gente esquece que também pode criar as nossas próprias soluções.
Criar a sua própria biblioteca, mesmo que simples, é um exercício valioso. Você começa a pensar na usabilidade, nos tipos, na estrutura, e até em como escrever um código que outras pessoas possam usar.
Além disso, muita biblioteca que a gente encontra por aí tá desatualizada, mal documentada ou foi feita com um propósito totalmente diferente do nosso. Nessas horas, fazer a sua pode ser o caminho mais rápido e confiável.
E não precisa ser algo gigante. Pode ser uma função reutilizável, um utilitário que você sempre usa ou uma abstração que você acha útil. O importante é começar.
Aqui no post, eu quero te incentivar a testar isso. Pega algo que você usaria em vários projetos e tenta transformar em uma lib.
Você vai perceber que, além de ser divertido, isso vai te ensinar muito sobre organização de código, publicação de pacotes, versionamento e até testes.
Agora que você entendeu o porquê, é hora de ver como fazer. Logo abaixo, vou te mostrar como estruturar e desenvolver uma biblioteca própria com Node.js e TypeScript.
Vamos começar criando o projeto do zero. Se você ainda não tiver uma pasta, é bem simples: no terminal, digite mkdir NOME_DA_PASTA
para criar e cd NOME_DA_PASTA
para entrar nela.
Com a pasta criada e já dentro dela no terminal, o próximo passo é inicializar o ambiente do Node.js. Isso vai depender do gerenciador de pacotes que você usa:
npm – npm init -y
pnpm – pnpm init
yarn – yarn init -y
Depois de inicializar o projeto, é hora de abrir ele no seu editor de códigos. Se você usa o VS Code, pode simplesmente digitar code .
no terminal, dentro da pasta do projeto, e ele já vai abrir automaticamente.
Com o projeto aberto, você vai ter a visualização de todos os arquivos iniciais: package.json
.
Como estamos usando TypeScript, vamos instalar ele nas dependências de desenvolvedor
npm – npm i typescript -D
pnpm – pnpm i typescript -D
yarn – yarn add typescript -D
O próximo passo é gerar o arquivo de configuração do TypeScript. Para isso, use o seguinte comando, de acordo com o gerenciador de pacotes que estiver usando:
npm – npx tsc --init
pnpm – pnpm exec tsc --init
yarn – yarn tsc --init
Vou explicar rapidinho o que são os arquivos que temos até agora, começando pelo package.json
.
package.json
{
"name": "minha-lib",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"packageManager": "pnpm@10.7.0",
"devDependencies": {
"typescript": "^5.8.3"
}
}
Esse arquivo descreve o seu projeto e ajuda ferramentas como o Node e o gerenciador de pacotes a entenderem como lidar com ele. Aqui vão os campos mais importantes:
name
– o nome da sua lib ou app. Vai ser usado caso você publique esse pacote.version
– a versão atual do seu projeto, seguindo o padrão semântico.description
– uma breve descrição do seu projeto, usada por quem for visualizar ou publicar a biblioteca.main
– o ponto de entrada principal do seu pacote (o arquivo que será executado).scripts
– comandos customizados que você pode rodar comnpm run
,pnpm run
, etc.keywords
– uma lista de palavras-chave que ajudam outras pessoas a encontrarem seu projeto em buscas.author
– o nome do autor ou equipe responsável pela criação do projeto.license
– define os termos de uso e distribuição do seu projeto, como MIT, ISC, GPL, etc.packageManager
– indica qual gerenciador de pacotes e versão foram usados.devDependencies
– dependências usadas apenas em desenvolvimento, como o TypeScript.
Por enquanto, só temos o TypeScript como dependência, mas esse arquivo vai crescer conforme o projeto evoluir.
Agora que instalamos o TypeScript e rodamos o tsc --init
, foi criado também o tsconfig.json
, que é o arquivo onde ficam todas as configurações do compilador TypeScript.
tsconfig.json
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
Esse arquivo serve pra dizer pro compilador como ele deve se comportar. Vamos passar rapidinho pelas opções principais:
target: "es2016"
– define pra qual versão do JavaScript o código será convertido. Aqui, ele vai gerar um JS compatível com o ES2016.module: "commonjs"
– define o sistema de módulos usado no JS gerado. O CommonJS é o padrão em ambientes como Node.js.esModuleInterop: true
– permite importar módulos CommonJS como se fossem ESModules. Isso evita bugs com alguns imports.forceConsistentCasingInFileNames: true
– garante que os nomes dos arquivos respeitem letras maiúsculas/minúsculas (evita erros no Linux, por exemplo).strict: true
– ativa várias regras de checagem mais rígidas do TypeScript, deixando o código mais seguro.skipLibCheck: true
– pula a verificação de tipos dentro das libs instaladas, pra compilar mais rápido.
Agora que você já entendeu para que servem esses arquivos iniciais, vamos começar a construir a nossa própria biblioteca. Para isso, crie um arquivo chamado index.ts
dentro de uma pasta chamada src
(source). O caminho ficará assim: src/index.ts
. Esse será o arquivo principal da nossa lib, o coração do projeto.
Dentro dele, vamos criar algumas funcionalidades. É claro que, no seu projeto real, você vai criar aquilo que fizer sentido pra sua necessidade. Aqui, vou demonstrar com duas funções simples: uma para extrair nomes a partir de e-mails e outra para gerar números aleatórios.
src/index.ts
export const extractNameByEmail = (email: string): string => {
const [name] = email.split("@");
return name || "";
};
export const randomInt = (min: number = 0, max: number = 1): number => {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
Criei duas funções como exemplo: uma que extrai o nome a partir de um e-mail, e outra que gera um número aleatório. Note que estou usando o export
, isso permite que essas funções sejam reutilizadas em qualquer lugar da aplicação. Ou seja, se essa biblioteca for instalada em outro projeto, essas funções já poderão ser usadas direto, sacou?
Estamos quase lá! Agora vamos configurar o nosso package.json
para deixar tudo redondinho.
package.json
{
"name": "@enzowxl/minha-lib",
"version": "0.0.1",
"description": "Uma biblioteca com duas funções existentes.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc"
},
"keywords": [
"typescript"
],
"author": "enzowxl",
"license": "ISC",
"packageManager": "pnpm@10.7.0",
"devDependencies": {
"typescript": "^5.8.3"
}
}
Primeiro, adicionei um escopo ao nome do pacote, ficando @enzowxl/minha-lib
. Isso ajuda a identificar que a biblioteca é minha e deixa mais organizado.
Também mudei a versão para 0.0.1
, já que estamos ainda no comecinho, só testando as coisas.
Coloquei uma descrição simples da lib e adicionei a palavra-chave typescript
pra facilitar a busca por quem estiver procurando algo do tipo.
Atualizei o campo main
pra apontar pro arquivo gerado após o build: dist/index.js
. E também adicionei types
com dist/index.d.ts
, que são os tipos da lib já que estamos fazendo o projeto em TypeScript.
No campo scripts
, criei um comando build
que roda o compilador TypeScript com tsc
.
E por fim, preenchi o campo author
com meu nome (enzowxl), porque né, a gente tem que assinar nossas criações.
Com o arquivo package.json
configurado, vamos configurar o arquivo tsconfig.json
.
tsconfig.json
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"outDir": "./dist",
"declaration": true,
}
}
A versão original do tsconfig.json
já vinha com configurações boas, como strict
ativado e esModuleInterop
habilitado. Mas pra transformar o projeto numa biblioteca de verdade, precisamos de mais alguns ajustes.
Adicionei a opção outDir
com valor ./dist
. Isso diz pro TypeScript onde colocar os arquivos compilados depois do build, no nosso caso, dentro da pasta dist
.
Também incluí a opção declaration
como true
. Isso faz com que o TypeScript gere os arquivos .d.ts
junto com o JavaScript, que é essencial pra quem vai usar a nossa lib com suporte completo a tipos.
Agora que configuramos o arquivo tsconfig.json
vamos rodar o build do projeto, por que rodaremos nosso código em JavaScript. Abra o projeto no terminal e rode o comando:
npm – npm run build
pnpm – pnpm build
yarn – yarn build
Após rodar o comando de build, o TypeScript vai compilar os arquivos que estão na pasta src
e jogar tudo dentro da pasta dist
, que é o que será consumido por quem instalar sua biblioteca.
Se você abrir a pasta dist
, vai ver que ela agora contém os arquivos index.js
e index.d.ts
. O primeiro é o código JavaScript convertido, e o segundo descreve os tipos da sua lib, o que permite recursos como autocompletar e validação quando alguém usá-la com TypeScript.
Pronto! Com isso, sua biblioteca já está empacotada e pronta para ser publicada e instalada em outros projetos.
Agora sim a gente pode ir pro passo final: publicar de verdade no NPM.
O primeiro passo é se certificar que você está logado com sua conta. No terminal, rode:
npm login
Isso vai pedir seu nome de usuário, senha e e-mail. Após isso, sua sessão vai ficar ativa.
Agora, pra publicar, é só rodar o comando:
npm publish --access public
Esse --access public
é necessário porque estamos usando um escopo no nome da lib (tipo @enzowxl/
), e por padrão, pacotes com escopo são privados. Esse flag deixa ela pública.
Pronto! Sua biblioteca já vai estar disponível no NPM e pronta pra ser usada por você ou qualquer outra pessoa no mundo.
Se quiser ver o projeto completo com todos os arquivos, clica no botão abaixo e explora à vontade. E se publicar a sua própria lib, me marca que eu quero ver também!