Dominando Módulos Nativos do Node.js: fs, path, os e crypto em Projetos Reais Já leu

Introdução aos Módulos Nativos do Node.js O Node.js fornece diversos módulos nativos que permitem interagir com o sistema operacional sem depender de bibliotecas externas. Os quatro módulos que abordaremos — fs, path, os e crypto — são fundamentais para qualquer desenvolvedor JavaScript no backend. Eles cobrem manipulação de arquivos, caminhos de sistema, informações do SO e criptografia, respectivamente. Dominar esses módulos é essencial para construir aplicações robustas e seguras. Módulo fs: Operações com Arquivos O módulo fs (File System) permite ler, escrever e manipular arquivos no disco. Node.js oferece duas abordagens: síncrona (bloqueante) e assíncrona (não-bloqueante). Em produção, sempre use métodos assíncronos. Leitura e Escrita Básica Usando Promises e Async/Await A API Promises ( ) é recomendada em código moderno, permitindo uso com e tratamento de erros mais limpo. Módulo path: Manipulação de Caminhos O módulo path gerencia caminhos de arquivos de forma agnóstica ao sistema operacional. Ele resolve diferenças entre Windows ( ) e Unix ( ) automaticamente. Operações

Introdução aos Módulos Nativos do Node.js

O Node.js fornece diversos módulos nativos que permitem interagir com o sistema operacional sem depender de bibliotecas externas. Os quatro módulos que abordaremos — fs, path, os e crypto — são fundamentais para qualquer desenvolvedor JavaScript no backend. Eles cobrem manipulação de arquivos, caminhos de sistema, informações do SO e criptografia, respectivamente. Dominar esses módulos é essencial para construir aplicações robustas e seguras.

Módulo fs: Operações com Arquivos

O módulo fs (File System) permite ler, escrever e manipular arquivos no disco. Node.js oferece duas abordagens: síncrona (bloqueante) e assíncrona (não-bloqueante). Em produção, sempre use métodos assíncronos.

Leitura e Escrita Básica

const fs = require('fs');

// Escrita assíncrona
fs.writeFile('dados.txt', 'Olá, Node.js!', (err) => {
  if (err) throw err;
  console.log('Arquivo salvo!');
});

// Leitura assíncrona
fs.readFile('dados.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data); // Output: Olá, Node.js!
});

Usando Promises e Async/Await

const fs = require('fs').promises;

async function gerenciarArquivos() {
  try {
    // Escrever
    await fs.writeFile('config.json', JSON.stringify({ debug: true }));

    // Ler
    const conteudo = await fs.readFile('config.json', 'utf8');
    console.log(JSON.parse(conteudo));

    // Deletar
    await fs.unlink('config.json');
  } catch (err) {
    console.error('Erro:', err.message);
  }
}

gerenciarArquivos();

A API Promises (fs.promises) é recomendada em código moderno, permitindo uso com async/await e tratamento de erros mais limpo.

Módulo path: Manipulação de Caminhos

O módulo path gerencia caminhos de arquivos de forma agnóstica ao sistema operacional. Ele resolve diferenças entre Windows (\) e Unix (/) automaticamente.

Operações Comuns

const path = require('path');

// Concatenar caminhos
const caminhoCompleto = path.join(__dirname, 'uploads', 'imagem.jpg');
console.log(caminhoCompleto);
// Windows: C:\projeto\uploads\imagem.jpg
// Unix: /home/usuario/projeto/uploads/imagem.jpg

// Extrair informações
const arquivo = '/home/usuario/dados.json';
console.log(path.dirname(arquivo));    // /home/usuario
console.log(path.basename(arquivo));   // dados.json
console.log(path.extname(arquivo));    // .json

// Resolver caminho absoluto
const relativo = './config/app.js';
console.log(path.resolve(relativo));   // /caminho/completo/config/app.js

// Separadores
console.log(path.sep);   // \ (Windows) ou / (Unix)

Caso Prático: Validar Uploads

const path = require('path');
const fs = require('fs').promises;

async function validarUpload(nomeArquivo) {
  // Evitar traversal attacks
  const uploadDir = path.join(__dirname, 'uploads');
  const caminhoFinal = path.resolve(uploadDir, nomeArquivo);

  // Verificar se o arquivo está dentro do diretório permitido
  if (!caminhoFinal.startsWith(uploadDir)) {
    throw new Error('Caminho inválido!');
  }

  return caminhoFinal;
}

Módulo os: Informações do Sistema Operacional

O módulo os fornece informações sobre o hardware e o SO, sendo útil para decisões de configuração e monitoramento.

Consultas de Sistema

const os = require('os');

// Informações da plataforma
console.log(os.platform());     // 'linux', 'win32', 'darwin'
console.log(os.arch());         // 'x64', 'arm64'

// Recursos de hardware
console.log(os.cpus().length);  // Número de núcleos
console.log(os.totalmem());     // Memória total em bytes
console.log(os.freemem());      // Memória livre em bytes

// Caminhos padrão
console.log(os.homedir());      // /home/usuario (Unix) ou C:\Users\usuario (Windows)
console.log(os.tmpdir());       // Diretório temporário do SO

// Uptime do sistema (em segundos)
console.log(os.uptime());

Exemplo Prático: Monitoramento de Memória

const os = require('os');

function verificarMemoria() {
  const totalMem = os.totalmem();
  const freeMem = os.freemem();
  const usedMem = totalMem - freeMem;
  const percentualUso = (usedMem / totalMem * 100).toFixed(2);

  console.log(`Memória: ${percentualUso}% em uso`);

  if (percentualUso > 80) {
    console.warn('⚠️ Alerta: Uso elevado de memória!');
  }
}

// Verificar a cada 10 segundos
setInterval(verificarMemoria, 10000);

Módulo crypto: Criptografia e Hash

O módulo crypto implementa operações criptográficas: hash, HMAC, criptografia simétrica e assimétrica. É essencial para segurança.

Hash e HMAC

const crypto = require('crypto');

// Gerar hash SHA256 de uma senha
const senha = 'minha_senha_secreta';
const hash = crypto.createHash('sha256').update(senha).digest('hex');
console.log(hash); // a7d8e8c...

// HMAC com chave secreta
const chave = 'chave_privada';
const hmac = crypto.createHmac('sha256', chave)
  .update('mensagem')
  .digest('hex');
console.log(hmac);

// Verificar senha (nunca compare strings diretas!)
const hashArmazenado = crypto
  .createHash('sha256')
  .update('minha_senha_secreta')
  .digest('hex');

function verificarSenha(senhaDigitada, hashArmazenado) {
  const hashDigitada = crypto
    .createHash('sha256')
    .update(senhaDigitada)
    .digest('hex');

  // Usar timingSafeEqual para evitar timing attacks
  return crypto.timingSafeEqual(
    Buffer.from(hashDigitada),
    Buffer.from(hashArmazenado)
  );
}

Criptografia Simétrica

const crypto = require('crypto');

function criptografar(texto, chave) {
  // A chave deve ter 32 bytes para AES-256
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(chave), iv);

  let encriptado = cipher.update(texto, 'utf8', 'hex');
  encriptado += cipher.final('hex');

  // Retornar IV + dados (necessário para descriptografar)
  return iv.toString('hex') + ':' + encriptado;
}

function descriptografar(dados, chave) {
  const [ivHex, encriptado] = dados.split(':');
  const iv = Buffer.from(ivHex, 'hex');
  const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(chave), iv);

  let texto = decipher.update(encriptado, 'hex', 'utf8');
  texto += decipher.final('utf8');

  return texto;
}

// Uso
const chave = crypto.randomBytes(32);
const original = 'Dados sensíveis';
const criptografado = criptografar(original, chave);
const descriptografado = descriptografar(criptografado, chave);
console.log(descriptografado); // Dados sensíveis

Conclusão

Os quatro módulos nativos abordados formam a base para desenvolvimento backend com Node.js. O fs permite gerenciar arquivos, o path resolve caminhos de forma segura e portável, o os oferece informações do sistema para decisões dinâmicas, e o crypto protege dados sensíveis através de hashing e criptografia. Domine essas APIs e você terá ferramentas poderosas para construir aplicações profissionais. Lembre-se: sempre use operações assíncronizadas em produção, valide caminhos para evitar traversal attacks e implemente criptografia adequada para dados sensíveis.

Referências


Artigos relacionados