APIs e Microsserviços

11 ago, 2017

Node e TypeScript – Criação de uma API com Node e TypeScript

Publicidade

Node e TypeScript

Hoje veremos como podemos trabalhar com o TypeScript e o Node. Para este artigo iremos utilizar o ExpressJS para facilitar no momento de expor as nossas rotas.

Bom nosso primeiro passo será selecionar um diretório para a aplicação, depois disso vamos criar o arquivo que será responsável por fazer o transpile de .ts para .js. Para isso, crie um diretório com o nome node-typescript e dentro dele um arquivo chamado tsconfig.json, abra o seu editor de preferência e cole o código abaixo dentro do arquivo tsconfig.

{
 "compilerOptions": {
 "target": "es6",
 "module": "commonjs"
 },
 "include": [
 "src/**/*.ts"
 ],
 "exclude": [
 "node_modules"
 ]
}

Vamos entender o código acima:

Em compilerOptions nós estamos passando para o TypeScript utilizar o ES2015 e o CommonJS como output, esse é o mesmo modulo que o Node utiliza.

Em Include nós estamos passando onde ele deve buscar os nossos arquivos .ts e em Exclude onde ele não deve buscar, assim nós garantimos o escopo para ele trabalhar e garantimos que ele não irá fazer um transpile de arquivos indesejados.

Seguindo o nosso arquivo acima, agora precisamos criar o diretório src, como dito antes, será nele que iremos criar os arquivos .ts. Feito isso, precisamos iniciar o nosso projeto com o comando npm init -y, esse comando irá criar um novo arquivo chamado package.json para o nosso projeto. Até esse momento nós temos a estrutura abaixo:

Node e TypeScript

Agora vamos baixar o pacote do TypeScript. Para isso, execute o comando abaixo dentro no cmd dentro do caminho do seu projeto:

npm install typescript@2.0.6 --save-dev

Para que possamos validar se tudo está OK, vamos criar um novo arquivo chamado test.js dentro do diretório src e cole o código abaixo dentro dele:

console.log('Hello World!');

Agora para ficar legal e padrão, adicione a seguinte linha de código “outDir”: “dist” dentro do seu arquivo tsconfig.json. Para que você possa comparar segue abaixo como o arquivo deve ficar:

{
 "compilerOptions": {
 "target": "es6",
 "module": "commonjs",
 "outDir": "dist"
 },
 "include": [
 "src/**/*.ts"
 ],
 "exclude": [
 "node_modules"
 ]
}

Agora execute o comando node_modules/.bin/ts na sua console, ele deve criar um novo diretório chamado dist e dentro dele um aquivo test.js. Podemos ver esse resultado na imagem abaixo:

Node e TypeScript

A primeira parte do nosso código está OK 😉

Mas não seria melhor ter algo que em todas as nossas alterações já criasse os nossos arquivos ou atualizasse eles sem a necessidade de estarmos rodando o comando acima? Se a sua resposta for sim, podemos utilizar o Gulp. Ele irá nos auxiliar nessa task, de um modo automático, nós somente iremos baixar ele e configurar uma vez. Para isso, execute o comando abaixo na sua console:

npm install gulp@3.9.1 gulp-typescript@3.1.1 --save-dev

Agora iremos precisar criar o nosso arquivo responsável por automatizar essas builds. Para isso, crie um arquivo chamado gulpfile.js na raiz do seu projeto e cole o código abaixo dentro dele:

const gulp = require('gulp');
const ts = require('gulp-typescript');
const JSON_FILES = ['src/*.json', 'src/**/*.json'];
const tsProject = ts.createProject('tsconfig.json');
gulp.task('scripts', () => {
 const tsResult = tsProject.src()
 .pipe(tsProject());
 return tsResult.js.pipe(gulp.dest('dist'));
});
gulp.task('watch', ['scripts'], () => {
 gulp.watch('src/**/*.ts', ['scripts']);
});
gulp.task('assets', function() {
 return gulp.src(JSON_FILES)
 .pipe(gulp.dest('dist'));
});
gulp.task('default', ['watch', 'assets']);

Eu não irei entrar em detalhes do código acima por ele ser padrão, mas em resumo ele está pegando as configurações em tsProject do nosso arquivo tsconfig e depois indo no diretório src da mesma forma que estávamos trabalhando antes, a novidade é a ultima linha do nosso arquivo que irá ficar monitorando o diretório a procura de novos arquivos ou alterações. Para testar delete o diretório dist que nós criamos no teste anterior, em seguida execute o comando gulp no seu terminal. Podemos ver o resultado da execução desse comando na imagem abaixo:

Node e TypeScript

Show 😉 Agora que esta tudo configurado vamos as nossas APIS. Para isso, iremos precisar instalar o pacote express-generator junto com um pacote de debug para que possamos ver os logs no terminal.

npm install express@4.14.0 debug@2.2.0 --save

No TypeScript quando instalamos um pacote de terceiros, devemos também puxar os tipos de definições dos pacotes. Com isso conseguimos passar para o compilador a estrutura do módulo que estamos utilizando, passando as informações necessárias para que possa compilar corretamente.

Bom, sem mais bla bla bla, para que ele possa importar os pacotes de terceiros nós iremos precisar instalar mais um pacote. Para isso, execute o comando abaixo na sua console:

npm install @types/node@6.0.46 @types/express@4.0.33 @types/debug@0.0.29 --save-dev

Para que possamos testar e validar os pacotes, vamos criar o nosso primeiro server HTTP. Delete o arquivo test.ts e o diretório dist, agora crie um novo arquivo dentro de src chamado index.ts e cole dentro dele o código abaixo:

import * as http from 'http';
import * as debug from 'debug';
import App from './App';
debug('ts-express:server');
const port = normalizePort(process.env.PORT || 3000);
App.set('port', port);
const server = http.createServer(App);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
function normalizePort(val: number|string): number|string|boolean {
 let port: number = (typeof val === 'string') ? parseInt(val, 10) : val;
 if (isNaN(port)) return val;
 else if (port >= 0) return port;
 else return false;
}
function onError(error: NodeJS.ErrnoException): void {
 if (error.syscall !== 'listen') throw error;
 let bind = (typeof port === 'string') ? 'Pipe ' + port : 'Port ' + port;
 switch(error.code) {
 case 'EACCES':
 console.error(`${bind} requires elevated privileges`);
 process.exit(1);
 break;
 case 'EADDRINUSE':
 console.error(`${bind} is already in use`);
 process.exit(1);
 break;
 default:
 throw error;
 }
}
function onListening(): void {
 let addr = server.address();
 let bind = (typeof addr === 'string') ? `pipe ${addr}` : `port ${addr.port}`;
 debug(`Listening on ${bind}`);
}

Como eu estou utilizando o Visual Studio Code, ele pensa que não tenho o ./App no meu código, por hora podemos ignorar essa parte.

Agora quanto ao restante do código temos o debug para que possamos ver os logs na nossa console e a configuração da porta que estamos utilizando, que para esse exemplo é a 3000.

Em seguida nós estamos criando um server HTTP e passando o app para ele ser  responsável por configurar as nossas rotas. Por fim, estamos configurando para que em caso de erro apareça uma mensagem na console.

Vamos agora criar o arquivo App.ts dentro do diretório src, em seguida vamos adicionar o pacote body-parser para nos auxiliar com os objetos em json.

npm install express@4.14.0 body-parser@1.15.2 morgan@1.7.0 --save npm install @types/body-parser@0.0.33 @types/morgan@1.7.32 --save-dev

Notem que estamos seguindo a mesma linha que a dos pacotes acima, estamos baixando o pacote e as referencias para o TypeScript.

import * as path from 'path';
import * as express from 'express';
import * as logger from 'morgan';
import * as bodyParser from 'body-parser';
// Criando as configurações para o ExpressJS
class App {
// Instancia dele
 public express: express.Application;
 constructor() {
 this.express = express();
 this.middleware();
 this.routes();
 }
// Configuração para o nosso middler
 private middleware(): void {
 this.express.use(logger('dev'));
 this.express.use(bodyParser.json());
 this.express.use(bodyParser.urlencoded({ extended: false }));
 }
//Configuração da nossa API e nossos EndPoint e o famoso Hello 
 private routes(): void { 
 let router = express.Router();
 
 router.get('/', (req, res, next) => {
 res.json({
 message: 'Hello World!'
 });
 });
 this.express.use('/', router);
 }
}
export default new App().express;

Agora vamos executar o comando gulp scripts, ele irá criar a pasta dist e dentro dela os arquivos app.js e o index.js. Podemos ver o resultado desse comando na image abaixo:

Node e TypeScript

Para que possamos executar o projeto, vamos adicionar o código abaixo dentro do nosso package.json dentro de start.

“start”: “node dist/index.js”

Agora para que possamos executar o código para validarmos esse ponto precisamos executar npm start na nossa console e abrir o navegador no endereço http://localhost:3000/.

Notem que quando abrimos no navegador conseguimos pegar a requisição na nossa console conforme a imagem abaixo:

Node e TypeScript

Bom, até aqui conseguimos criar o arquivo index.ts que é responsável pelas configurações do nosso projeto como porta, log, etc. Criamos a nossa class App.ts que será responsável pelo bootstrap do nosso projeto, que será a class de start. Fizemos estes passos para deixar tudo no esquema para criação das API’s 😉

Para começar vamos criar um arquivo que será responsável pelas rotas, crie uma nova pasta chamada router dentro de src, após isso crie um novo arquivo chamado personRouter.ts e cole o código abaixo dentro dele:

import { Router, Request, Response, NextFunction } from 'express';
export class PersonRouter {
 router: Router
constructor() {
 this.router = Router();
 this.init();
 }
public get(req: Request, res: Response, next: NextFunction) {
 res.send("Person");
 }
init() {
 this.router.get('/', this.get);
 }
}
const personRouter = new PersonRouter();
personRouter.init();
export default personRouter.router;

Vamos entender o código acima:

  1. Estamos importando os pacotes na primeira linha do arquivo;
  2. Em seguida estamos criando uma classe chamada PersonRouter com um construtor referenciando router e o método init;
  3. Podemos observar que o método init esta passando uma rota para o nosso método get que irá retornar a mensagem Person para o nosso navergador;
  4. Por fim exportamos a nossa classe.

 

Agora para testar, basta importar a rota na nossa classe App.ts. Em seguida depois da rota padrão, vamos adicionar uma nova. Podemos ver essa implementação abaixo:

this.express.use(‘/’, router);
this.express.use(‘/api/v1/person’, PersonRouter);

Agora execute o comando gulp scripts para que ele possa criar os arquivos, assim que ele atualizar a pasta dist, execute o comando npm start e abra no seu navegador o endereço abaixo:

http://localhost:3000/api/v1/person

Caso tudo esteja OK, ele irá apresentar a mensagem person conforme a imagem abaixo:

Node e TypeScript

Com isso conseguimos dar primeiros passos com TypeScript e o Node.js, espero que tenham gostado e até a próxima pessoal 😉

Caso queira ver o código deste artigo, nós subimos no github.