- Published on
Como criar um pacote JavaScript para o NPM
- Authors
- Name
- Luã Álvaro

INTRODUÇÃO
Se você é um desenvolvedor, eu tenho certeza que você já teve curiosidade ou até mesmo já tentou criar seu próprio pacote JavaScript e publicar no NPM
.
Eu particularmente sempre fiquei curioso com o fato de utilizar pacotes gerados e mantidos por outros desenvolvedores, e como um bom desenvolvedor, eu também queria poder fazer aquilo. No início da minha carreira, de forma frustrada, eu tentei criar algum módulo e disponibilizar no gerenciador de pacotes NPM
, que é o gerenciador de pacotes para o ambiente Node/JavaScript
.
Neste artigo nós vamos, juntos, criar um pacote JavaScript e disponibilizar de forma pública no NPM.
VAMOS FAZER ALGO REALMENTE ÚTIL?
Para que não seja apenas um pacote de teste, com uma função "Hello World" embutida, nós vamos fazer algo realmente útil. Pelo menos útil para mim. Existem algumas funções utilitárias que sempre acabo utilizando na maioria dos projetos que desenvolvo/faço parte.
Por exemplo: Função para validar um CPF, função para validar um CNPJ, função para criar uma Máscara de Telefone e afins.
Como estou sempre replicando estes códigos entre meus projetos, vamos condensá-los em um único módulo, para que eu, ou qualquer pessoa do mundo, possa instalar nos seus projetos e utilizar-se das funções utilitárias que vamos criar.
CRIAÇÃO DO REPOSITÓRIO
Vamos começar o nosso pacote javascript com a criação de um repositório remoto no Github.

Optei por criar um repositório público, chamado lual-utils
, por ser público, isso quer dizer que você pode clonar, e inclusive abrir contribuições ao projeto!
CLONAR REPOSITÓRIO E INICIAR PROJETO NPM
Irei clonar este repositório localmente para iniciar o desenvolvimento do nosso módulo npm:
git clone https://github.com/luaalvaro/lual-utils.git
cd lual-utils
Com o repositório na minha máquina, irei iniciar um novo projeto NPM
com o comando:
npm init -y
Será criado um arquivo package.json
no diretório raiz do nosso projeto, e nele vamos fazer algumas alterações para que esteja em conformidade com o nosso objetivo.
CONFIGURAÇÃO DO PROJETO
Para começar eu alterei a propriedade version
e description
.
Também alterei a prop main
para dist/index.js
. Isso quer dizer que o arquivo principal do nosso módulo será o index.js
que será "buildado" e disposto na pasta /dist
. Além disso também adicionei outras duas propriedades que irá complementar requisitos do NPM para que nosso pacote javascript funcione:
{
"main": "dist/index.js",
"module": "dist/index.mjs"
}
Outros detalhes singelos para as propriedades repository e também keywords que preenchi para deixar nosso arquivo completo e bem descrito.
DEPENDÊNCIAS DE DESENVOLVIMENTO
Vamos adicionar ao nosso projeto 2 dependências de desenvolvimento, para que principalmente possamos configurar o Typescript
no nosso módulo, isso irá facilitar o entendimento e usabilidade da nossa biblioteca.
npm install -D typescript tsup
E com estas dependências instaladas, nós podemos finalizar a configuração do nosso arquivo package.json
{
"scripts": {
"build":"tsup"
}
}
O módulo TSUP
irá se encarregar de fazer o build do nosso Typescript e criar todos os arquivos necessários para que possamos ter um módulo npm válido.
PACKAGE.JSON
Ao final da configuração temos o seguinte arquivo package.json
{
"name": "lual-utils",
"version": "0.0.1",
"description": "This repository aims to guide a tutorial on how to create an npm module, and mainly to add useful functions that I use in my daily life in various projects.",
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"repository": {
"url": "git+https://github.com/luaalvaro/lual-utils"
},
"scripts": {
"build": "tsup"
},
"keywords": ["helpers", "utils", "validation cpf", "whatsapp mask", "máscara whatsapp"],
"author": "Luã Álvaro",
"license": "MIT",
"devDependencies": {
"tsup": "^8.1.0",
"typescript": "^5.5.2"
}
}
VAMOS IGNORAR ALGUNS ARQUIVOS?
Neste momento, se você olhar para o contador do GIT, irá se espantar com a quantidade de arquivos que estão sendo rastreados pelo software. Vamos criar o tão famoso arquivo .gitignore e também será necessário criar um arquivo específico para o npm.
/dist
/node_modules
.env
.DS_Store
.env
.env.local
/src
/node_modules
/test
.env
.env.example
.DS_Store
tsconfig.json
tsup.config.js
.editorconfig
.prettierrc.json
jest.config.js
Perceba que estamos contemplando arquivos que ainda não temos no nosso projeto, mas é importante entender que temos 2 arquivos que irá ignorar outros arquivos.
O primeiro se trata do arquivo padrão e famoso .gitignore, ele serve para ignorar arquivos para serem enviados juntos com o commit para a linha do tempo no desenvolvimento.
O segundo arquivo segue a mesma linha que o primeiro, porém irá ignorar arquivos para ser enviado para o NPM, visto que esse deploy acontece de forma separada do github.
OPCIONAL, MAS DE EXTREMA IMPORTÂNCIA!
Este tópico é opcional para o tutorial, porém é de extrema importância e iremos adotar no nosso repositório. Iremos configurar o editor de código e o Prettier para que nosso projeto siga um padrão de desenvolvimento.
npm i -D prettier
Após a instalação do prettier precisamos adicionar 2 scripts ao nosso package.json, um para fazer o check do nosso repositório, procurando por arquivos que estejam fora do padrão definido. E um segundo para fazer o FIX desses arquivos que estiverem fora do padrão.
"scripts": {
"build": "tsup",
"lint:check": "prettier --check .",
"lint:fix": "prettier --write ."
},
Também iremos criar o arquivo .editorconfig e o arquivo .prettierrc.json na raiz do nosso projeto
root = true
[*]
indent_style = space
indent_size = 2
{
"trailingComma": "es5",
"semi": false,
"tabWidth": 2,
"singleQuote": true,
"jsxSingleQuote": true
}
ESTAMOS QUASE LÁ... VAMOS CONFIGURAR O TYPESCRIPT!
É bastante detalhe que estamos configurando, mas isso é de extrema importância para que nosso repositório e nosso módulo opere conforme padrões atuais de desenvolvimento.
Para configurar o nosso Typescript, vamos criar um arquivo de configuração e adicionar alguns valores padrões que irão definir versão, target, module e outras propriedades importantes:
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"esModuleInterop": true,
"strictNullChecks": true,
"target": "ES2022",
"moduleResolution": "Node10",
"module": "CommonJS",
"declaration": true,
"isolatedModules": true,
"noEmit": true,
"outDir": "dist"
},
"include": ["src"],
"exclude": ["node_modules"]
}
Com isso estamos a 1 passo de ter um base sólida para receber qualquer tipo de pacote para ser publicado no gerenciador de pacotes javascript.
Apenas vamos criar um arquivo de configuração para o tsup que vai lidar com a compilação e gerenciamento do nosso Typescript
import { defineConfig } from 'tsup'
export default defineConfig({
format: ['cjs', 'esm'],
entry: ['./src/index.ts'],
dts: true,
shims: true,
skipNodeModulesBundle: true,
clean: true,
})
Por mais que seja bastante detalhe, chegamos ao final das configurações necessárias para o nosso módulo javascript.
VAMOS PROGRAMAR O NOSSO MÓDULO NPM
Finalmente vamos partir para a parte do desenvolvimento em si, e não gostaria de decepcionar vocês, mas a parte mais difícil já foi feita! Que é a configuração inicial do nosso projeto, agora apenas iremos criar as funções que queremos disponibilizar no nosso pacote, fazer o build e a publicação para os servidores do npm.
const isCpfOrCnpjValid = (documentNumber: string) => {
documentNumber = documentNumber.replace(/\D/g, "");
if (documentNumber.length === 11) {
if (/^(\d)\1+$/.test(documentNumber)) {
return false;
}
let sum = 0;
for (let i = 0; i < 9; i++) {
sum += parseInt(documentNumber.charAt(i)) * (10 - i);
}
let rest = 11 - (sum % 11);
let verifyingDigit = rest === 10 || rest === 11 ? 0 : rest;
if (verifyingDigit !== parseInt(documentNumber.charAt(9))) {
return false;
}
sum = 0;
for (let i = 0; i < 10; i++) {
sum += parseInt(documentNumber.charAt(i)) * (11 - i);
}
rest = 11 - (sum % 11);
verifyingDigit = rest === 10 || rest === 11 ? 0 : rest;
if (verifyingDigit !== parseInt(documentNumber.charAt(10))) {
return false;
}
return true;
}
if (documentNumber.length === 14) {
if (
documentNumber == "00000000000000" ||
documentNumber == "11111111111111" ||
documentNumber == "22222222222222" ||
documentNumber == "33333333333333" ||
documentNumber == "44444444444444" ||
documentNumber == "55555555555555" ||
documentNumber == "66666666666666" ||
documentNumber == "77777777777777" ||
documentNumber == "88888888888888" ||
documentNumber == "99999999999999"
)
return false;
let docLength = documentNumber.length - 2;
let docNumbers = documentNumber.substring(0, docLength);
let docDigits = documentNumber.substring(docLength);
let sum = 0;
let pos = docLength - 7;
for (let i = docLength; i >= 1; i--) {
sum += Number(docNumbers.charAt(docLength - i)) * pos--;
if (pos < 2) pos = 9;
}
let result = sum % 11 < 2 ? 0 : 11 - (sum % 11);
if (result != Number(docDigits.charAt(0))) return false;
docLength = docLength + 1;
docNumbers = documentNumber.substring(0, docLength);
sum = 0;
pos = docLength - 7;
for (let i = docLength; i >= 1; i--) {
sum += Number(docNumbers.charAt(docLength - i)) * pos--;
if (pos < 2) pos = 9;
}
result = sum % 11 < 2 ? 0 : 11 - (sum % 11);
if (result != Number(docDigits.charAt(1))) return false;
return true;
}
};
export { isCpfOrCnpjValid };
Criei um diretório SRC na raiz do nosso projeto, que irá receber o nosso arquivo principal, e coloquei uma das funções que sempre acabo utilizando em meus projetos. Validação de CPF e CNPJ.
A partir de agora, ao iniciar um novo projeto eu simplesmente poderei instalar o módulo lual-utils e importar a função isCpfOrCnpjValid, isso irá facilitar demais a usabilidade do módulo, além de evitar um monte de código javascript solto e largado no nosso projeto.
GRAVANDO NOSSAS ALTERAÇÕES
Antes de partir para o build da nossa aplicação, vamos fazer o commit das nossas alterações com a primeira versão do nosso pacote
git add .
git commit -m "created mvp with 'isCpfOrCnpjValid' function"
BUILD DO PACOTE
Neste primeiro momento, nós iremos apenas configurar uma função que verifica e valida CPF e CNPJs, ao longo dos tempos irei adicionais mais funções que acabo mais utilizando nos projetos.
E como já comentei, o projeto fica open-source, e aceitando contribuições.
Para fazer o Build da nossa aplicação é tão simples quanto rodar o comando:
npm run build
Este comando irá rodar o tsup, buildar nossa aplicação, e criar uma pasta /dist com todos os arquivos necessários para publicação do nosso módulo npm.
PUBLICAÇÃO DO MÓDULO NPM
Para fazer a publicação do nosso módulo ao npm, será necessário ter uma conta criada. Para isso basta acessar https://www.npmjs.com/signup
Com a sua conta npm criada, vamos fazer login na nossa CLI com o comando npm login e em seguida fazer a publicação

Neste momento podemos simplesmente rodar o comando de publicação oferecido pela cli npm e teremos feito a publicação deste módulo de forma pública em toda a internet.
npm publish

E é isso! Parabéns!
Você tem um módulo criado e publicado no gerenciador de pacotes oficial e mais utilizado!
https://www.npmjs.com/package/lual-utils
UTILIZAÇÃO DO PACOTE CRIADO
Para validar se realmente deu tudo certo, vamos instalar o pacote criado em um outro projeto e testar alguns cpfs
npm i lual-utils
import { isCpfOrCnpjValid } from 'lual-utils'
const cpf = '12345678901'
const cnpj = '12345678901234'
console.log(isCpfOrCnpjValid(cpf)) // false
console.log(isCpfOrCnpjValid(cnpj)) // false
Desta maneira, finalizamos o nosso artigo por aqui. Espero que você tenha gostado, e tenha te ajudado de alguma forma.
Att e até a próxima.
Já pensou em integrar o seu sistema com o WhatsApp?
Eu sei que você, como desenvolvedor e dono de software, sofre com problemas de comunicação com seus clientes. Na grande maioria das vezes seus e-mails vão cair em caixas e spam e nunca serão lidas.
As mensagens enviadas através do WhatsApp são lidas em até 5 minutos. Então não perca tempo e dinheiro, e integre seu sistema com o WhatsApp com a GZAPPY API.
Crie sua primeira instância e comece a enviar e receber mensagens de forma automatizada com a API que foi feita pensada especialmente para você que é desenvolvedor!
Faça um teste gratuito hoje mesmo.