├── .gitignore ├── README.md ├── api └── livrosApi.js ├── data ├── livros.csv ├── livros.js ├── livros.zip ├── unzip.js └── zip.js ├── domain └── livro.js ├── http └── livrosHttp.js ├── index.js ├── infra └── teclado.js ├── package.json └── service └── livrosService.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Node.js Workshop 2 | 3 | Após finalizar o processo de instalação do Node.js, crie uma pasta para o projeto. 4 | 5 | ## Exercício 1 @ 10 minutos 6 | 7 | 1 - Crie um módulo chamado index (index.js), ele será o entry-point e deverá ser invocado da seguinte forma: 8 | 9 | ``` 10 | node index.js 11 | ``` 12 | 13 | 2 - Dentro do módulo index, crie uma função construtora (aquela que utiliza o operador new) chamada Livro, contendo as propriedades titulo, autor, isbn, paginas, ano, editora, idioma e assunto. 14 | 15 | ```javascript 16 | var Livro = function (titulo, autor, isbn, paginas, ano, editora, idioma, assunto) { 17 | this.titulo = titulo; 18 | this.autor = autor; 19 | this.isbn = isbn; 20 | this.paginas = paginas; 21 | this.ano = ano; 22 | this.editora = editora; 23 | this.idioma = idioma; 24 | this.assunto = assunto; 25 | }; 26 | ``` 27 | 28 | 3 - Crie também um array de livros, incluindo alguns livros diretamente dentro do array. 29 | 30 | 31 | ```javascript 32 | var livros = [ 33 | new Livro(...), 34 | new Livro(...), 35 | new Livro(...) 36 | ]; 37 | ``` 38 | 39 | 4 - Por fim, utilizando a função forEach, percorra o array de livros exibindo cada um deles. 40 | 41 | 42 | ```javascript 43 | livros.forEach(function (livro) { 44 | console.log(livro); 45 | }); 46 | ``` 47 | 48 | ## Exercício 2 (Sistema de Módulos) @ 30 minutos 49 | 50 | 1 - Crie uma pasta chamada domain e lá crie um módulo chamado livro (livro.js). 51 | 52 | 2 - Mova a função construtora Livro para lá, exportando-a na forma de uma função. 53 | 54 | ```javascript 55 | var Livro = function (titulo, autor, isbn, paginas, ano, editora, idioma, assunto) { 56 | this.titulo = titulo; 57 | this.autor = autor; 58 | this.isbn = isbn; 59 | this.paginas = paginas; 60 | this.ano = ano; 61 | this.editora = editora; 62 | this.idioma = idioma; 63 | this.assunto = assunto; 64 | }; 65 | 66 | module.exports = Livro; 67 | ``` 68 | 69 | 3 - Crie uma pasta chamada data e lá crie um módulo chamado livros (livros.js) 70 | 71 | 4 - Mova o array de livros para lá, utilizando a função require para importar a função construtora Livro. 72 | 73 | ```javascript 74 | var Livro = require('../domain/livro'); 75 | 76 | var livros = [ 77 | new Livro(...), 78 | new Livro(...), 79 | new Livro(...) 80 | ]; 81 | 82 | module.exports = livros; 83 | ``` 84 | 85 | 4 - Crie uma pasta chamada service e dentro crie um módulo chamado livrosService (livrosService.js). 86 | 87 | 5 - Mova a função forEach para dentro de uma função chamada exibirLivros, responsável por percorrer o array de livros e exibir seus detalhes. 88 | 89 | ```javascript 90 | var livros = require('../data/livros'); 91 | 92 | var exibirLivros = function () { 93 | livros.forEach(function (livro) { 94 | console.log(livro); 95 | }); 96 | }; 97 | 98 | module.exports = { 99 | exibirLivros: exibirLivros 100 | }; 101 | ``` 102 | 103 | 6 - Por fim, no módulo index, faça o require do módulo livrosService e invoque a função exibirLivros. 104 | 105 | ```javascript 106 | var livrosService = require('./service/livrosService'); 107 | 108 | livrosService.exibirLivros(); 109 | ``` 110 | 111 | ## Exercício 3 (Global Objects) @ 20 minutos 112 | 113 | 114 | 1 - No módulo index, faça a leitura do teclado e imprima tudo que é digitado. 115 | 116 | ```javascript 117 | process.stdin.on('readable', function () { 118 | var data = process.stdin.read(); 119 | if (data) console.log(data.toString()); 120 | }); 121 | ``` 122 | 123 | 2 - Crie uma pasta chamada infra e crie um módulo chamado teclado (teclado.js), movendo a função de leitura do teclado para o módulo teclado, recebendo um callback que será executado sempre que algo for digitado. 124 | 125 | ```javascript 126 | var aoDigitar = function (callback) { 127 | process.stdin.on('readable', function () { 128 | var data = process.stdin.read(); 129 | var linha = (data) ? data.toString() : ''; 130 | linha = linha.replace(/\n/, ''); 131 | if (linha) callback(linha); 132 | }); 133 | }; 134 | 135 | module.exports = { 136 | aoDigitar: aoDigitar 137 | }; 138 | ``` 139 | 140 | 3 - No módulo index, utilize a função require para importar o módulo teclado. 141 | 142 | ```javascript 143 | var livrosService = require('./service/livrosService'); 144 | var teclado = require('./infra/teclado.js'); 145 | 146 | teclado.aoDigitar(function (linha) { 147 | console.log(linha); 148 | }); 149 | ``` 150 | 151 | 4 - No módulo livrosService, crie uma função para exibirLivrosPorTitulo, utilizando o que foi digitado para realizar a busca. 152 | 153 | ```javascript 154 | var livros = require('../data/livros'); 155 | 156 | var exibirLivrosPorTitulo = function (titulo) { 157 | var livrosEncontrados = livros.filter(function (livro) { 158 | return livro.titulo.indexOf(titulo) > -1; 159 | }); 160 | if (livrosEncontrados.length === 0) { 161 | console.log("Nenhum livro foi encontrado!"); 162 | return; 163 | } 164 | livrosEncontrados.forEach(function(livro) { 165 | console.log(livro); 166 | }); 167 | }; 168 | 169 | module.exports = { 170 | exibirLivrosPorTitulo: exibirLivrosPorTitulo 171 | }; 172 | ``` 173 | 174 | 5 - Modifique o módulo index para invocar a função exibirLivrosPorTitulo sempre que alguma linha for digitada. 175 | 176 | ```javascript 177 | var livrosService = require('./service/livrosService'); 178 | var teclado = require('./infra/teclado.js'); 179 | 180 | teclado.aoDigitar(function (linha) { 181 | livrosService.exibirLivrosPorTitulo(linha); 182 | }); 183 | ``` 184 | 185 | 6 - Adicione a possibilidade de digitar /q para sair, utilizando a função process.exit() 186 | 187 | ```javascript 188 | var livrosService = require('./service/livrosService'); 189 | var teclado = require('./infra/teclado.js'); 190 | 191 | teclado.aoDigitar(function (linha) { 192 | if (linha === '/q') process.exit(); 193 | livrosService.exibirLivrosPorTitulo(linha); 194 | }); 195 | ``` 196 | 197 | 7 - Para dar a impressão que a busca está sendo realizada, faça com que a função exibirLivrosPorTitulo seja invocada com um atraso de 1000ms. 198 | 199 | ```javascript 200 | var livrosService = require('./service/livrosService'); 201 | var teclado = require('./infra/teclado.js'); 202 | 203 | teclado.aoDigitar(function (linha) { 204 | if (linha === '/q') process.exit(); 205 | setTimeout(function () { 206 | livrosService.exibirLivrosPorTitulo(linha); 207 | }, 1000); 208 | }); 209 | ``` 210 | 211 | ## Exercício 4 (Code Module) @ 30 minutos 212 | 213 | 1 - No módulo livros, obtenha a lista de livros diretamente do arquivo livros.csv, utilizando função readFile do módulo fs, criando o array de livros a partir do arquivo lido. 214 | 215 | ```javascript 216 | var fs = require('fs'); 217 | 218 | var livros = []; 219 | 220 | var carregarLivros = function () { 221 | fs.readFile('./data/livros.csv', 'utf8', function (err, csv) { 222 | if (err) { 223 | console.log(err); 224 | return; 225 | } 226 | var linhas = csv.split('\n'); 227 | linhas.forEach(function (linha) { 228 | var propriedades = linha.split(';'); 229 | var livro = new Livro(propriedades[0], propriedades[1], propriedades[2], propriedades[3], propriedades[4], propriedades[5], propriedades[6], propriedades[7]); 230 | livros.push(livro); 231 | }) 232 | }); 233 | }; 234 | 235 | carregarLivros(); 236 | 237 | module.exports = livros; 238 | ``` 239 | 240 | 2 - Crie um módulo chamado zip para comprimir o arquivo livros.csv utilizando o módulo zlib. 241 | 242 | ```javascript 243 | var fs = require('fs'); 244 | var path = require('path'); 245 | var gzip = require('zlib').createGzip(); 246 | 247 | var inp = fs.createReadStream(path.join(__dirname, '/livros.csv')); 248 | var out = fs.createWriteStream(path.join(__dirname, '/livros.zip')); 249 | inp.pipe(gzip).pipe(out); 250 | ``` 251 | 252 | 3 - Crie outro módulo chamado unzip para descomprimir o arquivo livros.zip. 253 | 254 | 255 | 4 - Modifique a função carregarLivros, do módulo livros, para descomprimir o arquivo livros.zip antes de montar o array. 256 | 257 | ```javascript 258 | var carregarLivros = function () { 259 | fs.readFile(__dirname + '/livros.zip', function (err, zip) { 260 | if (err) { 261 | console.log(err); 262 | return; 263 | } 264 | zlib.unzip(zip, function (err, data) { 265 | if (err) { 266 | console.log(err); 267 | return; 268 | } 269 | var csv = data.toString('utf8'); 270 | var linhas = csv.split('\n'); 271 | linhas.forEach(function (linha) { 272 | var propriedades = linha.split(';'); 273 | var livro = new Livro(propriedades[0], propriedades[1], propriedades[2], propriedades[3], propriedades[4], propriedades[5], propriedades[6], propriedades[7]); 274 | livros.push(livro); 275 | }); 276 | }); 277 | }); 278 | }; 279 | ``` 280 | 281 | 4 - Crie a pasta http, juntamente com o módulo livrosHttp, utilizando o módulo http para listar os livros pela web. 282 | 283 | ```javascript 284 | var http = require('http'); 285 | var livrosService = require('../service/livrosService'); 286 | 287 | var server = http.createServer(function (req, res) { 288 | res.writeHead(200, { 289 | 'Content-Type': 'text/html;charset=UTF-8' 290 | }); 291 | res.write("

Livros

") 292 | var livros = livrosService.getLivros(); 293 | livros.forEach(function (livro) { 294 | res.write("

" + livro.titulo + "

"); 295 | res.write("
" + livro.autor + "

"); 296 | }); 297 | res.end(); 298 | }); 299 | module.exports = server; 300 | ``` 301 | 302 | 5 - Mude o módulo index para que seja possível rodar por meio do modo teclado ou de http, passando por parâmetro a opção **-http**, permitindo com que seja possível acessar a lista de livros pelo navegador na url **http://localhost:3000** 303 | 304 | ```javascript 305 | var livrosService = require('./service/livrosService'); 306 | var livrosHttp = require('./http/livrosHttp'); 307 | var teclado = require('./infra/teclado.js'); 308 | 309 | var httpMode = process.argv.some(function (arg) { 310 | return arg === '-http'; 311 | }); 312 | 313 | if (httpMode) { 314 | console.log("Http Mode"); 315 | livrosHttp.listen(3000); 316 | return; 317 | } 318 | 319 | console.log("Keyboard Mode"); 320 | teclado.aoDigitar(function (linha) { 321 | if (linha === '/q') process.exit(); 322 | setTimeout(function () { 323 | livrosService.exibirLivrosPorTitulo(linha); 324 | }, 1000); 325 | }); 326 | ``` 327 | 328 | Para rodar no modo http, utilize o comando: 329 | 330 | ``` 331 | node index.js -http 332 | ``` 333 | 334 | 6 - Crie a função getLivrosPorTitulo no módulo livrosService. Não se esqueça de exportá-la. 335 | 336 | ```javascript 337 | var getLivrosPorTitulo = function (titulo) { 338 | if (!titulo) return livros; 339 | return livros.filter(function (livro) { 340 | return livro.titulo.indexOf(titulo) > -1; 341 | }); 342 | }; 343 | ``` 344 | 345 | 7 - Modifique o módulo livrosHttp para receber parâmetros pela url e realizar a busca por título, utilizando o módulo url. 346 | 347 | ```javascript 348 | var http = require('http'); 349 | var url = require('url'); 350 | var livrosService = require('../service/livrosService'); 351 | 352 | var server = http.createServer(function (req, res) { 353 | var titulo = url.parse(req.url, true).query.titulo; 354 | res.writeHead(200, { 355 | 'Content-Type': 'text/html;charset=UTF-8' 356 | }); 357 | res.write('

Livros: '+ titulo + '

'); 358 | var livros = livrosService.getLivrosPorTitulo(titulo); 359 | livros.forEach(function (livro) { 360 | res.write('

' + livro.titulo + '

'); 361 | res.write('
' + livro.autor + '

'); 362 | }); 363 | res.end(); 364 | }); 365 | 366 | module.exports = server; 367 | ``` 368 | 369 | ## Exercício 5 (Express) @ 10 minutos 370 | 371 | 1 - Crie o arquivo package.json: 372 | 373 | ``` 374 | npm init 375 | ``` 376 | 377 | 2 - Instale o Express utilizando o NPM: 378 | 379 | ``` 380 | npm install express --save 381 | ``` 382 | 383 | 3 - Crie uma chamada pasta api e o módulo livrosApi (livrosApi.js). 384 | 385 | ```javascript 386 | var express = require('express'); 387 | var app = express(); 388 | 389 | module.exports = app; 390 | ``` 391 | 392 | 4 - Defina uma rota utilizando o método get chamada /livros, retornando um JSON. 393 | 394 | ```javascript 395 | var express = require('express'); 396 | var app = express(); 397 | var livrosService = require('../service/livrosService'); 398 | 399 | app.get('/livros', function (req, res) { 400 | res.json(livrosService.getLivros()); 401 | }); 402 | 403 | module.exports = app; 404 | ``` 405 | 406 | 5 - Modifique o módulo index para rodar em modo api com o parâmetro -api 407 | 408 | ```javascript 409 | var apiMode = process.argv.some(function (arg) { 410 | return arg === '-api'; 411 | }); 412 | 413 | if (apiMode) { 414 | console.log("Api Mode"); 415 | livrosApi.listen(3000); 416 | return; 417 | } 418 | ``` 419 | 420 | Para rodar, utilize o comando: 421 | 422 | ``` 423 | node index.js -api 424 | ``` -------------------------------------------------------------------------------- /api/livrosApi.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | var livrosService = require('../service/livrosService'); 4 | 5 | app.get('/livros', function (req, res) { 6 | res.json(livrosService.getLivros()); 7 | }); 8 | 9 | module.exports = app; -------------------------------------------------------------------------------- /data/livros.csv: -------------------------------------------------------------------------------- 1 | Faça como Steve Jobs;Carmine Gallo;9788563066169;256;2010;Lua de Papel;Português;Administração e Negócios 2 | O Código Da Vinci;Dan Brown;9788575421130;423;2004;Sextante;Português;Aventura 3 | O Pequeno Príncipe;Antonie De Saint-Exupery;9788589987332;96;2015;Edipro;Português;Infantil -------------------------------------------------------------------------------- /data/livros.js: -------------------------------------------------------------------------------- 1 | var Livro = require('../domain/livro'); 2 | var fs = require('fs'); 3 | var zlib = require('zlib'); 4 | 5 | var livros = []; 6 | 7 | var carregarLivros = function () { 8 | fs.readFile(__dirname + '/livros.zip', function (err, zip) { 9 | if (err) { 10 | console.log(err); 11 | return; 12 | } 13 | zlib.unzip(zip, function (err, data) { 14 | if (err) { 15 | console.log(err); 16 | return; 17 | } 18 | var csv = data.toString('utf8'); 19 | var linhas = csv.split('\n'); 20 | linhas.forEach(function (linha) { 21 | var propriedades = linha.split(';'); 22 | var livro = Livro.fromProperties(propriedades); 23 | livros.push(livro); 24 | }); 25 | }); 26 | }); 27 | }; 28 | 29 | carregarLivros(); 30 | 31 | module.exports = livros; -------------------------------------------------------------------------------- /data/livros.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigobranas/node-workshop/0da17224bfc9a86a7da511a979777fa1bb1ff97e/data/livros.zip -------------------------------------------------------------------------------- /data/unzip.js: -------------------------------------------------------------------------------- 1 | // var fs = require('fs'); 2 | // var path = require('path'); 3 | // var zlib = require('zlib'); 4 | 5 | // fs.readFile(path.join(__dirname, '/livros.zip') , function (err, data) { 6 | // zlib.unzip(data, function (err, unzip) { 7 | // fs.writeFile(path.join(__dirname, '/livros.csv2'), unzip); 8 | // }); 9 | // }); 10 | var fs = require('fs'); 11 | var path = require('path'); 12 | var gunzip = require('zlib').createGunzip(); 13 | 14 | var inp = fs.createReadStream(path.join(__dirname, '/livros.zip')); 15 | var out = fs.createWriteStream(path.join(__dirname, '/livros.csv2')); 16 | inp.pipe(gunzip).pipe(out); -------------------------------------------------------------------------------- /data/zip.js: -------------------------------------------------------------------------------- 1 | // var fs = require('fs'); 2 | // var path = require('path'); 3 | // var zlib = require('zlib'); 4 | 5 | // fs.readFile(path.join(__dirname, '/livros.csv') , function (err, data) { 6 | // zlib.gzip(data, function (err, zip) { 7 | // fs.writeFile(path.join(__dirname, '/livros.zip'), zip); 8 | // }); 9 | // }); 10 | var fs = require('fs'); 11 | var path = require('path'); 12 | var gzip = require('zlib').createGzip(); 13 | 14 | var inp = fs.createReadStream(path.join(__dirname, '/livros.csv')); 15 | var out = fs.createWriteStream(path.join(__dirname, '/livros.zip')); 16 | inp.pipe(gzip).pipe(out); -------------------------------------------------------------------------------- /domain/livro.js: -------------------------------------------------------------------------------- 1 | var Livro = function (titulo, autor, isbn, paginas, ano, editora, idioma, assunto) { 2 | this.titulo = titulo; 3 | this.autor = autor; 4 | this.isbn = isbn; 5 | this.paginas = paginas; 6 | this.ano = ano; 7 | this.editora = editora; 8 | this.idioma = idioma; 9 | this.assunto = assunto; 10 | }; 11 | 12 | Livro.fromProperties = function (properties) { 13 | return new Livro(properties[0], properties[1], properties[2], properties[3], properties[4], properties[5], properties[6], properties[7]); 14 | }; 15 | 16 | module.exports = Livro; -------------------------------------------------------------------------------- /http/livrosHttp.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var url = require('url'); 3 | var livrosService = require('../service/livrosService'); 4 | 5 | var server = http.createServer(function (req, res) { 6 | var titulo = url.parse(req.url, true).query.titulo; 7 | res.writeHead(200, { 8 | 'Content-Type': 'text/html;charset=UTF-8' 9 | }); 10 | res.write('

Livros: '+ titulo + '

'); 11 | var livros = livrosService.getLivrosPorTitulo(titulo); 12 | livros.forEach(function (livro) { 13 | res.write('

' + livro.titulo + '

'); 14 | res.write('
' + livro.autor + '

'); 15 | }); 16 | res.end(); 17 | }); 18 | 19 | module.exports = server; -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var livrosService = require('./service/livrosService'); 2 | var livrosHttp = require('./http/livrosHttp'); 3 | var livrosApi = require('./api/livrosApi'); 4 | var teclado = require('./infra/teclado.js'); 5 | 6 | var httpMode = process.argv.some(function (arg) { 7 | return arg === '-http'; 8 | }); 9 | 10 | var apiMode = process.argv.some(function (arg) { 11 | return arg === '-api'; 12 | }); 13 | 14 | if (httpMode) { 15 | console.log("Http Mode"); 16 | livrosHttp.listen(3000); 17 | return; 18 | } 19 | 20 | if (apiMode) { 21 | console.log("Api Mode"); 22 | livrosApi.listen(3000); 23 | return; 24 | } 25 | 26 | console.log("Keyboard Mode"); 27 | var exibirMenu = function () { 28 | console.log(''); 29 | console.log('O que você está buscando?'); 30 | console.log(''); 31 | console.log('Basta digitar o título do livro'); 32 | console.log('Utilize o comando /q para sair.'); 33 | console.log(''); 34 | process.stdout.write('> '); 35 | }; 36 | 37 | teclado.aoDigitar(function (linha) { 38 | if (linha === '/q') process.exit(); 39 | console.log(''); 40 | setTimeout(function () { 41 | livrosService.exibirLivrosPorTitulo(linha); 42 | console.log(''); 43 | process.stdout.write('> '); 44 | }, 1000); 45 | }); 46 | 47 | exibirMenu(); -------------------------------------------------------------------------------- /infra/teclado.js: -------------------------------------------------------------------------------- 1 | var aoDigitar = function (callback) { 2 | process.stdin.on('readable', function () { 3 | var data = process.stdin.read(); 4 | var linha = (data) ? data.toString() : ''; 5 | linha = linha.replace(/\n/, ''); 6 | if (linha) callback(linha); 7 | }); 8 | }; 9 | 10 | module.exports = { 11 | aoDigitar: aoDigitar 12 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-workshop", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "body-parser": "^1.15.1", 13 | "express": "^4.13.4" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /service/livrosService.js: -------------------------------------------------------------------------------- 1 | var livros = require('../data/livros'); 2 | 3 | var exibirLivros = function () { 4 | livros.forEach(function (livro) { 5 | console.log(livro); 6 | }); 7 | }; 8 | 9 | var getLivros = function () { 10 | return livros; 11 | }; 12 | 13 | var getLivrosPorTitulo = function (titulo) { 14 | if (!titulo) return livros; 15 | return livros.filter(function (livro) { 16 | return livro.titulo.indexOf(titulo) > -1; 17 | }); 18 | }; 19 | 20 | var exibirLivrosPorTitulo = function (titulo) { 21 | console.log('Buscando por: ' + titulo); 22 | var livrosEncontrados = livros.filter(function (livro) { 23 | return livro.titulo.indexOf(titulo) > -1; 24 | }); 25 | if (livrosEncontrados.length === 0) { 26 | console.log("Nenhum livro foi encontrado!"); 27 | return; 28 | } 29 | console.log(livrosEncontrados.length + ' foram encontrados'); 30 | livrosEncontrados.forEach(function(livro) { 31 | console.log(livro); 32 | }); 33 | }; 34 | 35 | module.exports = { 36 | getLivros: getLivros, 37 | getLivrosPorTitulo: getLivrosPorTitulo, 38 | exibirLivros: exibirLivros, 39 | exibirLivrosPorTitulo: exibirLivrosPorTitulo 40 | }; --------------------------------------------------------------------------------