├── .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 | };
--------------------------------------------------------------------------------