Módulos Internos (Core Modules) - Parte 1
Na lição anterior, você viu sobre o funcionamento dos módulos em NodeJS, aprendendo como eles são criados e usados por outros arquivos.
O conhecimento adquirido alí foi primordial para que pudéssemos estar aqui agora aprendendo sobre os Módulos Internos (Core Modules).
O funcionamento dos módulos internos é o mesmo, a diferença é que não precisamos criar o módulo e a sua lógica, uma vez que isso já foi feito pelos próprios desenvolvedores do NodeJS rs
Sendo assim, precisamos só importá-los para dentro da nossa aplicação, e entender como fazer o uso de seus métodos e propriedades 😅
Arquivos da lição
Os arquivos que veremos durante o decorrer desta lição, podem ser encontrados nos links abaixo:
O que são módulos internos?
Módulos Internos, ou também conhecidos como Core Modules, nada mais são do que módulos que foram criados e disponibilizados gratuitamente pelos próprios desenvolvedores do NodeJS.
De forma a adicionar funcionalidades que até então não existiam no Javascript (Client Side).
Para mais informações detalhadas do que são os módulos internos, não deixe de acessar a lição que fala sobre eles.
Os módulos internos tem por objetivo principal, adicionar e ampliar as capacidades do NodeJS em diversas áreas, desde a manipulação de arquivos até comunicação segura e controle de execução assíncrona.
Exemplos de módulos internos
Vou deixar com vocês, uma grande lista de apenas alguns módulos internos disponíveis para uso com o NodeJS.
Nesse primeiro momento, peço para que você dê somente uma passada de olho na lista abaixo, não é para implementar tudo isso agora, ok?
http: Fornece funcionalidades para criar um servidor HTTP e fazer solicitações HTTP.
const http = require('http');fs (file system): Permite interagir com o sistema de arquivos do sistema operacional.
const fs = require('fs');path: Fornece utilitários para trabalhar com caminhos de arquivo e diretório.
const path = require('path');events: Implementa um mecanismo de eventos que permite a comunicação entre objetos em seu aplicativo.
const events = require('events');util: Fornece utilitários comuns, como formatação de strings e manipulação de objetos.
const util = require('util');os: Oferece métodos para interagir com o sistema operacional, como obter informações sobre a CPU e a memória.
const os = require('os');querystring: Facilita a manipulação de strings de consulta em URLs.
const querystring = require('querystring');crypto: Fornece funcionalidades de criptografia, como hash e criptografia.
const crypto = require('crypto');url: Ajuda a analisar e formatar URLs.
const url = require('url');util: Fornece funções utilitárias comumente usadas.
const util = require('util');stream: Fornece uma implementação base para trabalhar com fluxos de dados. É especialmente útil ao lidar com grandes volumes de dados.
const stream = require('stream');zlib: Permite a compressão e descompressão de dados usando a biblioteca zlib.
const zlib = require('zlib');net: Oferece funcionalidades para criar servidores TCP (Transmission Control Protocol).
const net = require('net');dgram: Permite a criação de servidores UDP (User Datagram Protocol) e sockets.
const dgram = require('dgram');child_process: Facilita a execução de processos externos a partir de um aplicativo NodeJS.
const child_process = require('child_process');cluster: Permite a criação de processos filhos para distribuição de carga em ambientes multi-core.
const cluster = require('cluster');readline: Fornece uma interface para ler dados de um fluxo (como um arquivo ou a entrada do console) linha por linha.
const readline = require('readline');https: Similar ao módulo http, mas fornece funcionalidades para criar servidores HTTP seguros usando o protocolo HTTPS.
const https = require('https');tty: Oferece funcionalidades relacionadas a terminais (TTY), úteis ao trabalhar com a entrada e saída do console.
const tty = require('tty');dns: Fornece funcionalidades para realizar operações DNS, como resolução de nomes de domínio.
const dns = require('dns');url: Oferece utilitários para trabalhar com URLs.
const url = require('url');string_decoder: Fornece utilitários para decodificar buffers em strings, especialmente útil ao trabalhar com dados binários.
const StringDecoder = require('string_decoder').StringDecoder;punycode: Fornece funcionalidades para lidar com codificação e decodificação de strings de domínio internacionalizados (IDNs).
const punycode = require('punycode');v8: Fornece acesso às funcionalidades da engine V8 do Google Chrome, como estatísticas de uso de memória.
const v8 = require('v8');timers: Fornece funcionalidades para agendar a execução de código em intervalos regulares ou após um atraso.
const { setTimeout, setInterval, clearTimeout, clearInterval } = require('timers');assert: Fornece funções de assertivas que podem ser usadas para testar as condições e gerar erros se as assertivas não forem atendidas.
const assert = require('assert');buffer: Fornece funcionalidades para manipulação de dados binários em buffers.
const buffer = require('buffer');tls (Transport Layer Security): Fornece funcionalidades para criar servidores seguros usando o protocolo TLS/SSL.
const tls = require('tls');async_hooks: Permite rastrear a execução de operações assíncronas ao longo do tempo.
const async_hooks = require('async_hooks');module: Fornece funcionalidades relacionadas ao sistema de módulos do NodeJS, permitindo manipular o carregamento de módulos.
const module = require('module');Ufa... se você pensou que esses são todos os módulos internos do NodeJS, você está ligeiramente enganado rs
Existem muitos outros módulos internos que podem ser encontrados na documentação do NodeJS.
Conhecendo a variável PROCESS
Antes de continuarmos, é de vital importância que você tenha um mínimo de entendimento sobre a variável global do NodeJS, chamada de process.
Mas o que é essa variável, e para que ela serve?
De acordo com a documentação do NodeJS, essa variável fornece informações de controle sobre os processos em execução da própria aplicação.
Essa variável é criada diretamente pelo NodeJS por de baixo dos panos, de modo que não precisamos importa-la dentro de cada um de nossos sistemas.
Uma das utilizadades dessa variável, é que podemos ler argumentos que são passando no início da execução do programa.
Se lembra que para executar um programa em NodeJS nós usamos o comando node app.js dentro do nosso terminal?
Então, você sabia que é possível adicionar argumentos junto a instrução de execução? Não sabia? Então veja como isso é feito:
node app.js nome=miciliniNo comando acima, estou dizendo para o NodeJS abrir a aplicação app.js, onde estou passando um argumento chamado nome que armazena a string micilini.
Legal, mas como eu faço para recuperar esses argumentos dentro da aplicação?
É ai que entra a variável process 😄
Dentro do app.js, você pode fazer o uso do comando process.argv, que retorna todos os argumentos da aplicação atual:
/* Aplicação de Testes (app.js) */
//Observação: Quando rodar esta applicação faça isso passando um argumento: [node app.js nome=micilini]
console.log('Todos os Argumentos da Aplicação');
console.log(process.argv);//Retorna todos os argumentos da aplicaçãoComo você pôde observar, muitos argumentos além do nome (que definimos) foram retornados pela aplicação.
Caso queiramos retornar somente os argumentos que passamos, podemos fazer o uso do método slice do próprio Javascript, de modo a resgatar apenas o segundo argumento:
const argsPassed = process.argv.slice(2);//Retorna os argumentos que nós passamos
console.log(argsPassed);//o retorno será: 'nome=william'Para transformar esses argumentos em um objeto, podemos fazer o uso do método split do Javascript, observe:
/* Aplicação de Testes (app.js) */
//Observação: Quando rodar esta applicação faça isso passando um argumento: [node app.js nome=micilini]
console.log('Todos os Argumentos da Aplicação');
console.log(process.argv);//Retorna todos os argumentos da aplicação
const argsPassed = process.argv.slice(2);//Retorna os argumentos que nós passamos
console.log(argsPassed);
const nome = argsPassed[0].split("=")[1];
console.log('Olá ' + nome);//o retorno será 'Olá Micilini'E como eu faço para passar mais de um único argumento? Simples, basta dar espaço e seguir a mesma lógica 😋
node app.js nome=micilini site=https://micilini.com/Para selecionar o segundo argumento basta executar a lógica do slice e split🙂
Mas a variável process só serve para recuperar argumentos? Não, existem uma gama de possibilidades que você pode fazer com ela, vejamos algumas.
Métodos e Propriedades
process.env: retorna o arquivo .env que contém as variáveis do sistema. Como ainda não chegamos nessa lição de variáveis do ambiente em NodeJS, o retorno será undefined.
console.log(process.env.NODE_ENV); // Exemplo de acesso à variável de ambiente NODE_ENVprocess.cwd(): método que retorna o diretorio de trabalho atual da aplicação que está sendo executada.
console.log(process.cwd());// Retorna o diretório da aplicação atualprocess.pid: método que retorna o ID do processo NodeJS que está em execução.
console.log(process.pid);// Retorna o ID do NodeJS em execuçãoprocess.exit([code]): método que finaliza o processo de execução informando um código de saída (int).
process.exit(0); // Finaliza o processo com código de saída 0process.on(event, callback): método que permite escutar certos eventos da aplicação (exit, uncaughtException e entre outros).
process.on('exit', (code) => {
 console.log(`Processo encerrado com código de saída: ${code}`);
});process.stdin: método que permite escutar as entradas do usuário no console.
process.stdin.setEncoding('utf8');//Configura o charset do texto
console.log('Digite algo e pressione Enter:');//Diz ao usuário digitar algo no console
process.stdin.on('data', (dados) => {//Espera o usuário digitar, e assim que receber o input executa o bloco abaixo
 console.log(`Você digitou: ${dados.trim()}`);
 process.stdin.pause();//Pausa a entrada dos dados digitados pelo usuário
});process.stdout: método usado para imprimir no console uma mensagem de saída.
process.stdout.write('Isso é uma mensagem na saída padrão.\n');process.stderr: método usado para imprimir uma mensagem de erro padrão no console.
process.stderr.write('Isso é uma mensagem de erro na saída padrão de erro.\n');Para entender mais sobre o funcionamento da variável global process, não deixe de acessar a documentação.
O que acontece se eu criar uma variável com nome de process?
Quando você cria uma variável usando o mesmo nome da variável global, sua nova variável irá sobreescrever a referência ao objeto global process, o que pode acarretar comportamentos indesejados, observe:
const process = "Micilini";
console.log(process);//"Micilini"
process.exit(0);//Erro na aplicação, pois process é uma constante agora.Portanto, nunca crie uma variável com o nome de process 😆
Trabalhando com Core Modules
Para colocar a mão na massa e brincar um pouco com os módulos internos, vamos começar aprendendo a utilizar o módulo 'path', um dos módulos mais simples de se utilizar.
Módulo: path
O NodeJS, conta com um módulo interno capaz de trabalhar com caminhos de arquivos e diretórios, cujo nome é path.
Com ele você é capaz de resolver um caminho, retornar a extenção de um arquivo, retornar o diretório de um caminho, e entre outras coisas a mais.
É importante ressaltar que este módulo não lida com lida diretamente com a criação de pastas, e muito menos de arquivos, ok?
Para se trabalhar com o módulo path, comece criando o seu arquivo de testes (app.js) na pasta do seu projeto. Em seguida você vai precisar importar o módulo em si:
const path = require('path');Este módulo conta com diversos métodos e propriedades, veremos cada um deles a seguir.
Métodos e Propriedades do módulo path
path.extname(path): método usado para retornar a extensão do arquivo de um caminho.
/* Aplicação de Testes (app.js) */
const path = require('path');
//extname
const ext = path.extname('meu-arquivo.xtr');
console.log('A extensão é: ' + ext);//o retorno será 'A extensão é: .xtr'path.dirname(path): método usado para retornar o diretório de um caminho:
/* Aplicação de Testes (app.js) */
const path = require('path');
//dirname
const directory = path.dirname('/meu/caminho/eu.txt');
console.log('O caminho é: ' + directory);//o retorno será 'O caminho é: /meu/caminho/'path.normalize(path): método usado para normalizar um caminho, resolvendo ".." e "." segmentos.
/* Aplicação de Testes (app.js) */
const path = require('path');
//normalize
const normalizedPath = path.normalize('/meu/caminho/../eu.txt');
console.log('O caminho normalizado: ' + normalizedPath);//o retorno será 'O caminho é: \meu\eu.txt'path.isAbsolute(path): método usado para verificar se o caminho é absoluto.
/* Aplicação de Testes (app.js) */
const path = require('path');
//isAbsolute
const isAbsolute = path.isAbsolute('/meu/caminho/eu.txt');
console.log('O caminho absoluto? ' + isAbsolute);//o retorno será 'true'path.relative(from, to): método usado para retornar o caminho relativo de from para to.
/* Aplicação de Testes (app.js) */
const path = require('path');
//relative
const relativePath = path.relative('/caminho/para', '/caminho/para/arquivo.txt');
console.log('O caminho relativo: ' + relativePath);//o retorno será 'arquivo.txt'path.sep: propriedade que retorna o separador (string) de caminho específico do sistema ('/' no Unix, '\' no Windows). Bem útil quando estamos criando ou buscando por diretórios.
/* Aplicação de Testes (app.js) */
const path = require('path');
//sep
console.log('Separador do Sistema: ' + path.sep);//o retorno será de acordo com o sistema em usopath.delimiter: propriedade que retorna o delimitador de caminho específico do sistema (':' no Unix, ';' no Windows).
/* Aplicação de Testes (app.js) */
const path = require('path');
//delimiter
console.log('Delimitador do Sistema: ' + path.delimiter);//o retorno será de acordo com o sistema em usopath.basename(path[, ext]): método que retorna o nome do arquivo presente em um caminho.
A variável ext é opcional e e, se fornecido, remove a extensão especificada do nome do arquivo.
/* Aplicação de Testes (app.js) */
const path = require('path');
//basename (sem ext)
const fileName = path.basename('/minha/pasta/file.txt');
console.log('Nome do Arquivo é: ' + fileName);//o retorno será 'file.txt'
//basename (com ext)
const fileNameExt = path.basename('/minha/pasta/file.txt', '.txt');
console.log('Nome do Arquivo é: ' + fileNameExt);//o retorno será 'file'path.resolve([...paths]): método usado para resolver uma sequência de caminhos ou segmentos de caminho dado em um caminho absoluto.
/* Aplicação de Testes (app.js) */
const path = require('path');
//resolve
const absolutePath = path.resolve('meu', 'caminho', 'arquivo.txt');
console.log('Caminho é: ' + absolutePath);//o retorno será '..../meu/caminho/arquivo.txt'path.join([...paths]): método usado para combinar diversos segmentos de um caminho, em um caminho absoluto.
/* Aplicação de Testes (app.js) */
const path = require('path');
//join
const fullPath = path.join('/meu', 'caminho', 'eu.txt');
console.log('Caminho é: ' + fullPath);//o retorno será '\meu\caminho\eu.txtExistem muitos outros métodos e propriedades referentes ao path, para saber mais consulte a documentação.
Módulo: readline
O readline é um dos módulos internos bastante utilizados por aplicações que fazem o uso da linha de comando.
Como o nome já diz, este módulo permitindo a leitura de entrada do console (prompt) de forma assíncrona. Fazendo com que tudo o que você digitar no console (prompt), seja lido pela sua aplicação por meio desse módulo.
Para se trabalhar com o módulo readline, comece criando o seu arquivo de testes (app.js) na pasta do seu projeto. Em seguida você vai precisar importar o módulo em si:  
const readline = require('readline');Após isso, você vai precisar configurar a interface de leitura do readline, para isso você pode fazer o uso do método createInterface, para criar uma instância de interface de leitura:
/* Aplicação de Testes (app.js) */
const readline = require('readline');
const rl = readline.createInterface({
 input: process.stdin,
 output: process.stdout
});Como você pode perceber, estamos passando dois parâmetros para dentro do método createInterface, chamados de:
input: que recebe a variável process, mais especificamente o método stdin, passando a responsabilidade de leitura para o módulo readline.
output: que recebe também a variavel process passando a responsabilidade do stdout para o readline.
Feito isso, o módulo readline já esta pronto para trabalhar com os inputs e outputs do console 😄
Métodos e Propriedades do módulo readline
O módulo readline possui alguns métodos e propriedades principais, vejamos alguns deles.
question(prompt, callback): método que exibe o prompt para que o usuário possa digitar alguma entrada no console.
/* Aplicação de Testes (app.js) */
const readline = require('readline');
const readline = readline.createInterface({
 input: process.stdin,
 output: process.stdout
});
readline.question('Me diga o seu nome ', (answer) => {
 console.log(`Olá, ${answer}!`);
 readline.close();//Fecha a interface de leitura/gravação
});Observe no comando acima que o método question faz uma pergunta no console e aguarda o usuário informar algum dado.
Assim que esse dado é enviado, a resposta será armazenada dentro da variável answer para que possa seguir o fluxo, e por fim fechar a interface de leitura/gravação usando o close().
close(): Como dito anteriormente, é um método que serve para ser usado dentro do bloco do realine para fechar a interface.
 readline.close();//Fecha a interface de leitura/gravaçãoon(eventName, callback): é um método capaz de escutar qualquer tipo de interação que acontece no prompt. Por exemplo, podemos aciona-lo sempre quando o prompt fecha, ou quando o usuário digita alguma coisa.
Com relação ao eventName, ele é o nome do evento que podemos escutar, e neste caso possuímos 6 tipos principais.
'line': Acionado quando o usuário pressiona ENTER para enviar uma linha de entrada.
readline.on('line', (input) => {//O resultado digitado pelo usuário estará salvo dentro do input
 console.log(`Você digitou: ${input}`);
});'close': Acionado quando a interface de leitura é fechada.
readline.on('close', () => {
 console.log('Interface fechada.');
});'pause': Acionado quando a entrada é pausada.
readline.on('pause', () => {
 console.log('Leitura pausada.');
});'resume': Acionado quando a entrada é retomada após ter sido pausada.
readline.on('resume', () => {
 console.log('Leitura retomada.');
});'SIGCONT': Acionado quando a entrada está disponível novamente após ter sido pausada.
readline.on('SIGCONT', () => {
 console.log('Sinal SIGCONT recebido.');
});'SIGINT': Acionado quando o usuário pressiona Ctrl+C.
readline.on('SIGINT', () => {
 console.log('Ctrl+C pressionado.');
 readline.close();
});setPrompt(prompt): método usado para definir um prompt personalizado. Observe como isso pode ser feito.
readline.setPrompt('Digite um número de 1 a 10... ');// Define um prompt personalizado
readline.prompt();// Exibe o prompt, dando espaço para que o usuário digite o número no console
readline.on('line', (input) => {//'line' aguarda que o usuário digite algum valor e aperte ENTER para enviar
 const number = parseFloat(input);//Faz o parse do valor digitado pelo usuário para um valor númerico de ponto flutuante
 if (isNaN(number) || number < 1 || number > 10) {//Verifica se o número é válido, e se ele esta entre 1 a 10
 console.log('Isso não é um número válido. Tente novamente.');
 readline.prompt();//Exibe novamente o prompt até que o usuário digite um número válido
 }else{
 console.log(`Você digitou o número: ${number}`);
 readline.close();//Fecha o prompt
 }
});
readline.on('close', () => {// Evento 'close' é emitido quando a interface é fechada
 console.log('Encerrando a leitura.');
});Para mais informações sobre os métodos e propriedades do módulo readline, não deixe de consultar a documentação.
Conclusão
Pois bem, chegamos ao final da primeira parte que fala sobre os módulos internos.
Aqui, tivemos uma lição cheia de aprendizado, onde você viu um pouco mais sobre o funcionamento dos módulos internos (core modules), além de uma enorme lista de módulos disponíveis para uso.
Você também aprendeu sobre os módulos path, readline e a variável global process.
Te aguardo na segunda parte desse incrível conteúdo 😄
        
                    
                    