text:
# Node.js - Aula 06 - Exercício

autor: Bruno Lima da Silva

## 1. Crie um Schema com cada tipo explicado, inserindo tanto um objeto correto, como um objeto que desencadeie erros de validação padrão, criar especificamente:
### -1.1 para String: enum, match, maxlength e minlength
String enum:
```js
const mongoose = require ('mongoose');
const Schema = mongoose.Schema;
const _schema = {
    n: {
        type: String,
        enum: 'Valid'
    }
};
const dataSchema = new Schema (_schema);
const data = { n: 'invalid' };
const model = mongoose.model ('pokemons', dataSchema);
const value = new model (data);
value.save ( (err, data) => {
    if (err) return console.log ('ERRO:', err);
    return console.log ('Inseriu:', data);
});
```
Saída
```
message: 'pokemons validation failed',
name: 'ValidationError',
errors:
 { n:
    { ValidatorError: `invalid` is not a valid enum value for path `n`.
        at MongooseError.ValidatorError (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/error/validator.js:24:11)
        at validate (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:704:13)
        at /home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:742:9
        at Array.forEach (native)
        at SchemaString.SchemaType.doValidate (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:710:19)
        at /home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/document.js:1354:9
        at _combinedTickCallback (internal/process/next_tick.js:67:7)
        at process._tickCallback (internal/process/next_tick.js:98:9)
        at Module.runMain (module.js:606:11)
        at run (bootstrap_node.js:394:7)
        at startup (bootstrap_node.js:149:9)
        at bootstrap_node.js:509:3
      message: '`invalid` is not a valid enum value for path `n`.',
      name: 'ValidatorError',
      properties: [Object],
      kind: 'enum',
      path: 'n',
      value: 'invalid' } } }
```
String match:
```js
const mongoose = require ('mongoose');
const Schema = mongoose.Schema;
const _schema = {
    n: {
        type: String,
        match: /^a/
    }
};
const dataSchema = new Schema (_schema);
const data = { n: 'Invalid' };
const model = mongoose.model ('pokemons', dataSchema);
const value = new model (data);
value.save ( (err, data) => {
    if (err) return console.log ('ERRO:', err);
    return console.log ('Inseriu:', data);
});
```
Saída
```
message: 'pokemons validation failed',
name: 'ValidationError',
errors:
 { n:
    { ValidatorError: Path `n` is invalid (Invalid).
        at MongooseError.ValidatorError (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/error/validator.js:24:11)
        at validate (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:704:13)
        at /home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:742:9
        at Array.forEach (native)
        at SchemaString.SchemaType.doValidate (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:710:19)
        at /home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/document.js:1354:9
        at _combinedTickCallback (internal/process/next_tick.js:67:7)
        at process._tickCallback (internal/process/next_tick.js:98:9)
        at Module.runMain (module.js:606:11)
        at run (bootstrap_node.js:394:7)
        at startup (bootstrap_node.js:149:9)
        at bootstrap_node.js:509:3
      message: 'Path `n` is invalid (Invalid).',
      name: 'ValidatorError',
      properties: [Object],
      kind: 'regexp',
      path: 'n',
      value: 'Invalid' } } }
```
String maxlength:
```js
const mongoose = require ('mongoose');
const Schema = mongoose.Schema;
const _schema = {
    n: {
        type: String,
        maxlength: 5
    }
};
const dataSchema = new Schema (_schema);
const data = { n: 'Bruno Lima da Silva' };
const model = mongoose.model ('pokemons', dataSchema);
const value = new model (data);
value.save ( (err, data) => {
    if (err) return console.log ('ERRO:', err);
    return console.log ('Inseriu:', data);
});
```
Saída
```
message: 'pokemons validation failed',
name: 'ValidationError',
errors:
 { n:
    { ValidatorError: Path `n` (`Bruno Lima da Silva`) is longer than the maximum allowed length (5).
        at MongooseError.ValidatorError (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/error/validator.js:24:11)
        at validate (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:704:13)
        at /home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:742:9
        at Array.forEach (native)
        at SchemaString.SchemaType.doValidate (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:710:19)
        at /home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/document.js:1354:9
        at _combinedTickCallback (internal/process/next_tick.js:67:7)
        at process._tickCallback (internal/process/next_tick.js:98:9)
        at Module.runMain (module.js:606:11)
        at run (bootstrap_node.js:394:7)
        at startup (bootstrap_node.js:149:9)
        at bootstrap_node.js:509:3
      message: 'Path `n` (`Bruno Lima da Silva`) is longer than the maximum allowed length (5).',
      name: 'ValidatorError',
      properties: [Object],
      kind: 'maxlength',
      path: 'n',
      value: 'Bruno Lima da Silva' } } }
```

String minlength:
```js
const mongoose = require ('mongoose');
const Schema = mongoose.Schema;
const _schema = {
    n: {
        type: String,
        minlength: 8
    }
};
const dataSchema = new Schema (_schema);
const data = { n: 'Bruno' };
const model = mongoose.model ('pokemons', dataSchema);
const value = new model (data);
value.save ( (err, data) => {
    if (err) return console.log ('ERRO:', err);
    return console.log ('Inseriu:', data);
});
```
Saída
```
message: 'pokemons validation failed',
name: 'ValidationError',
errors:
 { n:
    { ValidatorError: Path `n` (`Bruno`) is shorter than the minimum allowed length (8).
        at MongooseError.ValidatorError (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/error/validator.js:24:11)
        at validate (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:704:13)
        at /home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:742:9
        at Array.forEach (native)
        at SchemaString.SchemaType.doValidate (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:710:19)
        at /home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/document.js:1354:9
        at _combinedTickCallback (internal/process/next_tick.js:67:7)
        at process._tickCallback (internal/process/next_tick.js:98:9)
        at Module.runMain (module.js:606:11)
        at run (bootstrap_node.js:394:7)
        at startup (bootstrap_node.js:149:9)
        at bootstrap_node.js:509:3
      message: 'Path `n` (`Bruno`) is shorter than the minimum allowed length (8).',
      name: 'ValidatorError',
      properties: [Object],
      kind: 'minlength',
      path: 'n',
      value: 'Bruno' } } }
```

### -1.2 para Number:max e min
Number max:
```js
const mongoose = require ('mongoose');
const Schema = mongoose.Schema;
const _schema = {
    n: {
        type: Number,
        max: 10
    }
};
const dataSchema = new Schema (_schema);
const data = { n: 11 };
const model = mongoose.model ('pokemons', dataSchema);
const value = new model (data);
value.save ( (err, data) => {
    if (err) return console.log ('ERRO:', err);
    return console.log ('Inseriu:', data);
});
```
Saída
```
message: 'pokemons validation failed',
name: 'ValidationError',
errors:
 { n:
    { ValidatorError: Path `n` (11) is more than maximum allowed value (10).
        at MongooseError.ValidatorError (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/error/validator.js:24:11)
        at validate (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:704:13)
        at /home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:742:9
        at Array.forEach (native)
        at SchemaNumber.SchemaType.doValidate (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:710:19)
        at /home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/document.js:1354:9
        at _combinedTickCallback (internal/process/next_tick.js:67:7)
        at process._tickCallback (internal/process/next_tick.js:98:9)
        at Module.runMain (module.js:606:11)
        at run (bootstrap_node.js:394:7)
        at startup (bootstrap_node.js:149:9)
        at bootstrap_node.js:509:3
      message: 'Path `n` (11) is more than maximum allowed value (10).',
      name: 'ValidatorError',
      properties: [Object],
      kind: 'max',
      path: 'n',
      value: 11 } } }
```

Number min:
```js
const mongoose = require ('mongoose');
const Schema = mongoose.Schema;
const _schema = {
    n: {
        type: Number,
        min: 7
    }
};
const dataSchema = new Schema (_schema);
const data = { n: 5 };
const model = mongoose.model ('pokemons', dataSchema);
const value = new model (data);
value.save ( (err, data) => {
    if (err) return console.log ('ERRO:', err);
    return console.log ('Inseriu:', data);
});
```
Saída
```
message: 'pokemons validation failed',
name: 'ValidationError',
errors:
 { n:
    { ValidatorError: Path `n` (5) is less than minimum allowed value (7).
        at MongooseError.ValidatorError (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/error/validator.js:24:11)
        at validate (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:704:13)
        at /home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:742:9
        at Array.forEach (native)
        at SchemaNumber.SchemaType.doValidate (/home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/schematype.js:710:19)
        at /home/fsociety/be-mean-instagram/nodeJS/mongoose-pokemons/node_modules/mongoose/lib/document.js:1354:9
        at _combinedTickCallback (internal/process/next_tick.js:67:7)
        at process._tickCallback (internal/process/next_tick.js:98:9)
        at Module.runMain (module.js:606:11)
        at run (bootstrap_node.js:394:7)
        at startup (bootstrap_node.js:149:9)
        at bootstrap_node.js:509:3
      message: 'Path `n` (5) is less than minimum allowed value (7).',
      name: 'ValidatorError',
      properties: [Object],
      kind: 'min',
      path: 'n',
      value: 5 } } }
```

## 2. Cadastre 3 pokemons de uma só vez. (pesquisar)
```js
const mongoose = require ('mongoose');
const dbURI = 'mongodb://localhost/be-mean-instagram';
mongoose.connect (dbURI);
const Schema = mongoose.Schema;
const _schema = {
    name: String
};
const pokemonSchema = new Schema (_schema);
const PokemonModel = mongoose.model ('pokemons', pokemonSchema);
const poke = [
    {
        name: 'blsdotrocks'
    },
    {
        name: 'Karoline'
    },
    {
        name: 'Suissa'
    }
];
PokemonModel.create (poke, (err, poke) => {
    if (err) return console.log ('ERRO:', err);
    return console.log ('Inseriu:', poke);
});
```
Saída
```
➜  mongoose-pokemons node schema09.js
Inseriu: [ { __v: 0, name: 'blsdotrocks', _id: 582ce6bf5db3ae2c9f1faf3e },
  { __v: 0, name: 'Karoline', _id: 582ce6bf5db3ae2c9f1faf3f },
  { __v: 0, name: 'Suissa', _id: 582ce6bf5db3ae2c9f1faf40 } ]
```

## 3. Busque todos os Pokemons com attack > 50 e height > 0.5.
```js
const mongoose = require ('mongoose');
const dbURI = 'mongodb://localhost/be-mean-instagram';
mongoose.connect (dbURI);
const Schema = mongoose.Schema;
const _schema = {};
const pokemonSchema = new Schema (_schema);
const PokemonModel = mongoose.model ('pokemon', pokemonSchema);
const query = {attack: {$gt: 50}, height: {$gt: "0.5"}};
PokemonModel.find (query, (err, data) => {
    if (err) return console.log ('ERRO:', err);
    return console.log ('Buscou:', data);
});
```

## 4. Altere, inserindo, o Pokemon Nerdmon com attack = 49 e com os valores dos outros campos a sua escolha.
```js
const mongoose = require ('mongoose');
const dbURI = 'mongodb://localhost/be-mean-instagram';
mongoose.connect (dbURI);
const Schema = mongoose.Schema;
const _schema = {
    name: String,
    created: {type: Date, default: Date.now},
    type: [String],
    attack: Number,
    defense: Number,
    height: String,
    hp: Number,
    Speed: Number
};
const pokemonSchema = new Schema(_schema);
const PokemonModel = mongoose.model ('pokemons', pokemonSchema);
const query = {
    name: 'Nerdmon',
    attack: 49
};
PokemonModel.update (query, (err, data) => {
    if (err) return console.log ('ERRO:', err);
    return console.log ('Inseriu:', data);
});
```
Saída
```
Inseriu: { ok: 1, nModified: 1, n: 1 }
```
## 5. Remova todos os Pokemons com attack > 50.
```js
const mongoose = require ('mongoose');
const dbURI = 'mongodb://localhost/be-mean-instagram';
mongoose.connect (dbURI);
const Schema = mongoose.Schema;
const _schema = {
    name: String,
    created: {type: Date, default: Date.now},
    type: [String],
    attack: Number,
    defense: Number,
    height: String,
    hp: Number,
    Speed: Number
};
const pokemonSchema = new Schema (_schema);
const PokemonModel = mongoose.model ('pokemons', pokemonSchema);
const query = {attack: {$gt: 50}};
PokemonModel.remove (query, (err, data) => {
    if (err) return console.log ('ERRO', err);
    return console.log ('Delete', data);
});
```
Saída
```
result: { ok: 1, n: 461 },
```


text:
# Node.js - Aula 06 - Exercício
**user:** [filipe1309](https://github.com/filipe1309)
**autor:** Filipe Leuch Bonfim

## Crie um Schema com cada tipo explicado, inserindo tanto um objeto correto, como um objeto que desencadeie erros de validação padrão, criar especificamente:

* 1.1. para String: `enum`, `match`, `maxlength` e `minlength`

* 1.2.  para Number: `max` e `min`
```js
const mongoose = require('mongoose');

// Conexão com o mongo
const dbURI = 'mongodb://localhost/be-mean-instagram';
mongoose.connect(dbURI);

const Schema = mongoose.Schema;

// Definição do Schema
const meanArr = 'mongodb expressjs angularjs nodejs'.split(' ');
const _schema = {
      stringEnum: { type: String, enum: meanArr }
    , stringMatch: { type: String, match: /node((\.js)|js)?/i }
    , stringMinLength: { type: String, minlength: 5 }
    , stringMaxLength: { type: String, maxlength: 9 }
    , numMin: { type: Number, min: 12 }
    , numMax: { type: Number, max: 14 }
    , dateValue: { type: Date }
    , bufferValue:  Buffer
    , booleanValue:  Boolean
    , mixedValue:   Schema.Types.Mixed
    , objectValue: Schema.Types.ObjectId
    , arrayValue:   [String]
};

const class06Ex1Schema = new Schema(_schema);
const class06Ex1Model = mongoose.model('class06', class06Ex1Schema);
var class06Ex1Object = new class06Ex1Model;

// Inserções válidas
class06Ex1Object.stringEnum = 'nodejs';
class06Ex1Object.stringMatch = 'nodejs';
class06Ex1Object.stringMinLength = '1234567';
class06Ex1Object.stringMaxLength = '1234567';
class06Ex1Object.numMin = 13;
class06Ex1Object.numMax = 13;
class06Ex1Object.dateValue = Date.now();
class06Ex1Object.bufferValue = new Buffer(0);
class06Ex1Object.booleanValue = 1;
class06Ex1Object.mixedValue = 'Mean Stack';
class06Ex1Object.objectValue = new mongoose.Types.ObjectId;
class06Ex1Object.arrayValue.push('Inseriu!!!!');

// Inserções inválidas
class06Ex1Object.stringEnum = 'php';
class06Ex1Object.stringMatch = 'dog';
class06Ex1Object.stringMinLength = '1234';
class06Ex1Object.stringMaxLength = '1234567890';
class06Ex1Object.numMin = 11;
class06Ex1Object.numMax = 15;
class06Ex1Object.dateValue = '11/11/11';
class06Ex1Object.bufferValue = 'buf';
class06Ex1Object.booleanValue = {};
class06Ex1Object.mixedValue = undefined;
class06Ex1Object.objectValue = 'objeto';
class06Ex1Object.arrayValue.push(1);

class06Ex1Object.save(function (err, data) {
    if(err) return console.log(err);
    return console.log('Sucesso: ', data);
});
```

#### Saída
```js
// Inserções válidas
Sucesso:  { arrayValue: [ 'Inseriu!!!!' ],
  _id: 56e2338885ca37d42959fc1c,
  stringEnum: 'nodejs',
  stringMatch: 'nodejs',
  stringMinLength: '1234567',
  stringMaxLength: '1234567',
  numMin: 13,
  numMax: 13,
  dateValue: Thu Mar 10 2016 23:55:04 GMT-0300 (BRT),
  bufferValue:
   Binary {
     _bsontype: 'Binary',
     sub_type: 0,
     position: 0,
     buffer: <Buffer > },
  booleanValue: true,
  mixedValue: 'Mean Stack',
  objectValue: 56e2338885ca37d42959fc1d,
  __v: 0 }

// Inserções inválidas
{ [ValidationError: class06 validation failed]
  message: 'class06 validation failed',
  name: 'ValidationError',
  errors:
   { objectValue:
      { [CastError: Cast to ObjectID failed for value "objeto" at path "objectValue"]
        message: 'Cast to ObjectID failed for value "objeto" at path "objectValue"',
        name: 'CastError',
        kind: 'ObjectID',
        value: 'objeto',
        path: 'objectValue',
        reason: undefined },
     stringEnum:
      { [ValidatorError: `php` is not a valid enum value for path `stringEnum`.]
        properties: [Object],
        message: '`php` is not a valid enum value for path `stringEnum`.',
        name: 'ValidatorError',
        kind: 'enum',
        path: 'stringEnum',
        value: 'php' },
     stringMatch:
      { [ValidatorError: Path `stringMatch` is invalid (dog).]
        properties: [Object],
        message: 'Path `stringMatch` is invalid (dog).',
        name: 'ValidatorError',
        kind: 'regexp',
        path: 'stringMatch',
        value: 'dog' },
     stringMinLength:
      { [ValidatorError: Path `stringMinLength` (`1234`) is shorter than the minimum allowed length (5).]
        properties: [Object],
        message: 'Path `stringMinLength` (`1234`) is shorter than the minimum allowed length (5).',
        name: 'ValidatorError',
        kind: 'minlength',
        path: 'stringMinLength',
        value: '1234' },
     stringMaxLength:
      { [ValidatorError: Path `stringMaxLength` (`1234567890`) is longer than the maximum allowed length (9).]
        properties: [Object],
        message: 'Path `stringMaxLength` (`1234567890`) is longer than the maximum allowed length (9).',
        name: 'ValidatorError',
        kind: 'maxlength',
        path: 'stringMaxLength',
        value: '1234567890' },
     numMin:
      { [ValidatorError: Path `numMin` (11) is less than minimum allowed value (12).]
        properties: [Object],
        message: 'Path `numMin` (11) is less than minimum allowed value (12).',
        name: 'ValidatorError',
        kind: 'min',
        path: 'numMin',
        value: 11 },
     numMax:
      { [ValidatorError: Path `numMax` (15) is more than maximum allowed value (14).]
        properties: [Object],
        message: 'Path `numMax` (15) is more than maximum allowed value (14).',
        name: 'ValidatorError',
        kind: 'max',
        path: 'numMax',
        value: 15 }
        }
    }
```

## Cadastre 3 pokemons **de uma só vez**:
```js
const mongoose = require('mongoose');

// Conexão com o mongo
const dbURI = 'mongodb://localhost/be-mean-instagram';
mongoose.connect(dbURI);

const Schema = mongoose.Schema;

// Definição do Schema
const _schema = {
   attack: Number
  , created: { type: Date, default: Date.now }
  , defense: Number
  , height: Number
  , hp: Number
  , name: String
  , speed: Number
  , types: [String]
};

const pokemonsSchema = new Schema(_schema);
var pokemonsModel = mongoose.model('pokemons', pokemonsSchema);

var pokemon1 = {
      name: 'BeboMon'
    , attack: 51
    , defense: 51
    , height: 12.1
}

var pokemon2 = {
      name: 'CodeMon'
    , attack: 42
    , defense: 31
    , height: 6.18
}

var pokemon3 = {
      name: 'SonoMon'
    , attack: 10
    , defense: 09
    , height: 08
}

var novosPokemons = [pokemon1, pokemon2, pokemon3];

pokemonsModel.insertMany(novosPokemons, function(error, docs) {
    if(error) return console.log(error);
    return console.log('Sucesso: ', docs);
});
```

#### Saída
```js
Sucesso:  [ { created: Fri Mar 11 2016 00:38:28 GMT-0300 (BRT),
    types: [],
    _id: 56e23db4bd5799c830b1b07a,
    height: 12.1,
    defense: 51,
    attack: 51,
    name: 'BeboMon' },
  { created: Fri Mar 11 2016 00:38:28 GMT-0300 (BRT),
    types: [],
    _id: 56e23db4bd5799c830b1b07b,
    height: 6.18,
    defense: 31,
    attack: 42,
    name: 'CodeMon' },
  { created: Fri Mar 11 2016 00:38:28 GMT-0300 (BRT),
    types: [],
    _id: 56e23db4bd5799c830b1b07c,
    height: 8,
    defense: 9,
    attack: 10,
    name: 'SonoMon' } ]
```

## Busque **todos** os Pokemons com `attack > 50` e `height > 0.5`:
```js
const mongoose = require('mongoose');

// Conexão com o mongo
const dbURI = 'mongodb://localhost/be-mean-instagram';
mongoose.connect(dbURI);

const Schema = mongoose.Schema;

// Definição do Schema
const _schema = {
   attack: Number
  , created: { type: Date, default: Date.now }
  , defense: Number
  , height: Number
  , hp: Number
  , name: String
  , speed: Number
  , types: [String]
};

const pokemonsSchema = new Schema(_schema);
const pokemonsModel = mongoose.model('pokemons', pokemonsSchema);

var query = {$and: [{attack: {$gt: 50}}, {height: {$gt: 0.5}}]}

pokemonsModel.find(query, function (err, data) {
  if (err) return console.log('ERRO: ', err);
  return console.log('Buscou: ', data);
});
```

#### Saída
```js
Buscou:  [ { created: Fri Mar 11 2016 00:38:28 GMT-0300 (BRT),
    types: [],
    height: 12.1,
    defense: 51,
    attack: 51,
    name: 'BeboMon',
    _id: 56e23db4bd5799c830b1b07a }
]
```

## Altere, **inserindo**, o Pokemon `Nerdmon` com `attack` igual a 49 e com os valores dos outros campos a sua escolha.
```js
const mongoose = require('mongoose');

// Conexão com o mongo
const dbURI = 'mongodb://localhost/be-mean-instagram';
mongoose.connect(dbURI);

const Schema = mongoose.Schema;

// Definição do Schema
const _schema = {
      attack: Number
    , created: { type: Date, default: Date.now }
    , defense: Number
    , height: Number
    , hp: Number
    , name: String
    , speed: Number
    , types: [String]
};

const pokemonsSchema = new Schema(_schema);
const PokemonsModel = mongoose.model('pokemons', pokemonsSchema);

var nerdMon = {
      name: 'Nerdmon'
    , attack: 49
    , defense: 51
}

var nerdMonObj = new PokemonsModel(nerdMon);

nerdMonObj.save(function (err, data) {
    if (err) return console.log('ERRO: ', err);
    console.log('Sucesso: ', data)
});
```

#### Saída
```js
Sucesso:  { created: Fri Mar 11 2016 01:13:49 GMT-0300 (BRT),
  types: [],
  _id: 56e245fd5e430205354d4a4e,
  defense: 51,
  attack: 49,
  name: 'Nerdmon',
  __v: 0 }
```

## Remova **todos** os Pokemons com `attack` **acima de 50**.
```js
const mongoose = require('mongoose');

// Conexão com o mongo
const dbURI = 'mongodb://localhost/be-mean-instagram';
mongoose.connect(dbURI);

const Schema = mongoose.Schema;

// Definição do Schema
const _schema = {
      attack: Number
    , created: { type: Date, default: Date.now }
    , defense: Number
    , height: Number
    , hp: Number
    , name: String
    , speed: Number
    , types: [String]
};
const PokemonsSchema = new Schema(_schema);
const PokemonsModel = mongoose.model('pokemons', PokemonsSchema);
var query = {attack: {$gt: 50} }

PokemonsModel.remove(query, function (err, data) {
    if (err) return console.log('ERRO: ', err);
    return console.log('Excluiu: ', data);
});
```

#### Saída
```js
Excluiu:  { result: { ok: 1, n: 463 },
  connection:
   EventEmitter {
     domain: null,
     _events:
      { close: [Object],
        error: [Object],
        timeout: [Object],
        parseError: [Object],
        connect: [Function] },
     _eventsCount: 5,
     _maxListeners: undefined,
     options:
      { socketOptions: {},
        auto_reconnect: true,
        host: 'localhost',
        port: 27017,
        cursorFactory: [Object],
        reconnect: true,
        emitError: true,
        size: 5,
        disconnectHandler: [Object],
        bson: {},
        messageHandler: [Function],
        wireProtocolHandler: [Object] },
     id: 0,
     logger: { className: 'Connection' },
     bson: {},
     tag: undefined,
     messageHandler: [Function],
     maxBsonMessageSize: 67108864,
     port: 27017,
     host: 'localhost',
     keepAlive: true,
     keepAliveInitialDelay: 0,
     noDelay: true,
     connectionTimeout: 0,
     socketTimeout: 0,
     destroyed: false,
     domainSocket: false,
     singleBufferSerializtion: true,
     serializationFunction: 'toBinUnified',
     ca: null,
     cert: null,
     key: null,
     passphrase: null,
     ssl: false,
     rejectUnauthorized: false,
     checkServerIdentity: true,
     responseOptions: { promoteLongs: true },
     flushing: false,
     queue: [],
     connection:
      Socket {
        _connecting: false,
        _hadError: false,
        _handle: [Object],
        _parent: null,
        _host: 'localhost',
        _readableState: [Object],
        readable: true,
        domain: null,
        _events: [Object],
        _eventsCount: 8,
        _maxListeners: undefined,
        _writableState: [Object],
        writable: true,
        allowHalfOpen: false,
        destroyed: false,
        bytesRead: 250,
        _bytesDispatched: 231,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        _idleNext: null,
        _idlePrev: null,
        _idleTimeout: -1,
        read: [Function],
        _consuming: true },
     writeStream: null,
     hashedName: '29bafad3b32b11dc7ce934204952515ea5984b3c',
     buffer: null,
     sizeOfMessage: 0,
     bytesRead: 0,
     stubBuffer: null } }
```

repo_language: JavaScript

mime_type: text/plain


text:
# Node.js - Aula 12 - Exercício
**user:** [tuchedsf](https://github.com/tuchedsf)
**autor:** Diego Ferreira
**data:** 1467668568530

O quark que utilizei para este exercício foi a validacão do isbn-13, utilizado para livros deste 2007, podendo ajudar quem deseja construir alguma aplicação que catalogue livros ou bibliotecas.

Fonte: https://pt.wikipedia.org/wiki/International_Standard_Book_Number#ISBN-13

>A edição de 2005 do manual oficial do International ISBN Agency,[10] que abrange os ISBNs emitidos a partir de Janeiro de 2007, descreve como é efectuado o calculo, do dígito de verificação, do ISBN de 13 dígitos. O cálculo do dígito de verificação do ISBN-13 começa com os primeiros 12 dígitos dos 13, multiplicando alternadamente por 1 ou 3 , da esquerda para a direita, em seguida, estes produtos são somados módulo 10 para dar um valor que varia de 0 a 9, que subtraído a 10, que deixa um resultado de 1 a 10. Um zero (0) substitui 0 dez (10), garantindo assim, que o resultado da verificação não é maior que um dígito.

Link para o repositório: https://github.com/Webschool-io/Node-Atomic-Design_QUARKS/pull/10

Pasta: isISBN-13

Arquivos:

isISBN-13.js
```js
'use strict';
module.exports = (value) => {

  const arrayValues = value.toString().split("").map(Number);
  //console.log(arrayValues);
  let digCalculado = 0;
  //Se isbn nao tiver 13 posiçoes já pode ser considerado inválido
  if (arrayValues.length != 13 ) return false;
  /*
    1 passo:
    da posicao 1 a 12 do array deve-se multiplicar da seguinte forma:
    indice impar multiplica-se por 1
    indice par multiplica-se por 3
   */
  arrayValues.forEach(function (element,index){
    if (index != arrayValues.length -1) {
        //console.log("index: " + index + " element: " + element);
        if(index % 2 === 0){
            digCalculado = digCalculado + element;
        }else {
            digCalculado = digCalculado + (element * 3);
        }
    }
  });
  /* passo2:
  - e feito o mod 10 sobre a soma calculada e este valor subtraido de 10.
  - feito isso o resultado mod 10 deve ser igual ao elemento verificador a ultima posiçao do array
  */
  digCalculado = (10 - (digCalculado % 10)) % 10;

  /* passo3:
    comparacao se o digito calculado é igual ao passado no array
  */
  if (digCalculado === arrayValues[arrayValues.length -1]) return true;

  return false;
}
```

isISBN-13.test.js
```js
'use strict';

const describes = [
  {type: true
    , message:"ISBN válido"
    , values: [9780306406157, 9788525423498, 9788581303079]
  }
  , {type: false
    , message:"ISBN inválido"
    , values: [1111111111111, 123, 2367463526234, 9780306406156]
  }
];

//chama a classe generica de testes informando qual o arquivo do teste, e quais os testes a serem feitos.
const test = require('./module.tests.is.js')('isISBN-13', describes);
```

module.tests.is.js
```js

'use strict';

const expect = require('chai').expect;

module.exports = (testName, describes) => {
  const test =  (values, msg, valueToTest) => {
    values.forEach((element, index) =>{
      it(msg + " "+ element + " ", () =>{
       expect(require('./'+ testName)(element)).to.equal(valueToTest);
    });
   });
  }

  describe (testName, ()=> {
    describes.forEach((element, index) => {
      describe(element.message, () => {
        test(element.values,element.message, element.type)
      });
    });
  });
};
```


text:
# Node.js - Aula 12 - Exercício

**User:** [gkal19](https://github.com/gkal19)

**Autor:** Gabriel Kalani

**Data:** 1468533500436

[MEU QUARK](https://github.com/Webschool-io/Node-Atomic-Design_QUARKS/pull/11)

> O que é um Quark?

Como dizia o Sábio Sennin Jean Carlo Nascimento JavaScript Da Silva (eita), é nada mais é que a menor parte/módulo/função utilizada pelo Átomo.

> Quero saber mais...

Então vê a aulas aqui rsrs

[![Be MEAN: Node.JS (AULA 12 pt.1/3) Quarks](http://img.youtube.com/vi/2lml_4kOhgU/0.jpg)](http://www.youtube.com/watch?v=2lml_4kOhgU "Be MEAN: Node.JS (AULA 12 pt.1/3) Quarks")

Falou!!


text:
# Node.js - Aula 09 - Exercício
**user:** [tuchedsf](https://github.com/tuchedsf)
**autor:** Diego Ferreira

## Parte 1
###1) Faça uma lista de todas as funções que o modulo assert possui e coloque no md.

- assert -> Sinônimo de assert.ok, apenas atesta a existência da variável se é verdadeira.
- assert.deepEqual(atual, esperado, mensagem) -> testa se o valor atual é igual ao valor esperado, e valores primitivos são testados com comparação simples "==".
- assert.deepStrictEqual(atual, esperado, mensagem) -> idêntico ao deepEqual. A única diferença que aqui os valores primitivos são testados com "===", ou seja, além do "valor" também consideram o tipo do valor.
- assert.doesNotThrow(block, error, message) -> verifica se a função passada em "block" não retorna nenhum erro.
- assert.equal(atual, esperado, mensagem) -> verifica se o valor passada como atual é igual ao esperado e em caso de objetos se o objeto atual é igual ao esperado.
- assert.fail(atual, esperado, mensagem, operador) -> O operador serve para separar o elemento atual do esperado, em caso em caso de erro e se a mensagem não estiver preenchida. Caso a mensagem esteja preenchida é exibida a mensagem.
- assert.ifError(value) -> Testa se o valor não é um valor falso e dispara o throws se for verdadeiro.
- assert.notDeepEqual(atual, esperado, mensagem) -> Testa qualquer diferença entre os objetos tanto valor quanto tipo.
- assert.notDeepStrictEqual(atual, esperado, mensagem ) -> Testa se o valor do objeto atual é diferente do esperado porém leva em consideração o tipo de objeto.
- assert.notEqual(atual, esperado, mensagem) -> Testa se o valor do atual é diferente do esperado, leva em consideração o tipo de objeto.
- assert.notStrictEqual(atual, esperado, mensagem) -> Testa se o valor do atual é diferente do esperado, não leva em consideração o tipo de objeto.
- assert.ok(valor, mensagem) -> testa se o valor é verdadeiro.
- assert.strictEqual(atual, esperado, mensagem) -> testa se o valor e tipo do objeto são iguais.
- assert.throws(função[erro], mensagem) -> testa erros em funções.

###2) Modifique todos os testes que estão usando assert.equal para assert.deepStrictEqual(valor, result, "comentario") faça todos passarem, coloque os testes no md. ( primeira parte da aula)

Alteração assert add.spec.js
```js
'use strict';

const assert = require("assert");
const add = require("./assert_add");
//assert.equal(3, add(1,2));
//assert.equal(8, add(1,2,5));

assert.deepStrictEqual(3, add(1,2), "Resultado da soma diferente");
assert.deepStrictEqual(8, add(1,2,5), "Resultado da soma diferente");
```

Resultado:
```
Falha:
MacBook-Air-Diego:9tdd diego$ mocha assert_add_spec.js
assert.js:89
  throw new assert.AssertionError({
  ^
AssertionError: Resultado da soma diferente

Correção:
➜  test mocha assert_add_spec.js

  2 passing (4ms)
```

babystep.js
```js
'use strict';

const assert = require('assert');
const log =  require('./log');

//assert.equal('Hello World', log('Hello World'));
//assert.equal('final do hello world', log('final do hello world'));

assert.deepStrictEqual('Hello World', log('Hello World'));
assert.deepStrictEqual('final do hello world', log('final do hello world'));
```

Resultado:
```
Erro:
➜  test mocha log_spec.js

assert.js:89
  throw new assert.AssertionError({
  ^
AssertionError: 'Hell World' == 'Hello World'

Correção:
➜  test mocha log_spec.js

  2 passing (4ms)

```

###3) Na calculadora do CHAI crie mais 3 testes, um para divisão, outro para multiplicação e 1 para raiz quadrada, lembrando que não deve-se aceitar divisão por zero.

calc.js
```js
'use strict';

const Calc = {
    sum : (number1, number2) =>{
        return number1 + number2;
    }
    , subtract : (number1, number2) => {
        return number1 - number2;
    }
    , multiply : (number1, number2) => {
        return number1 * number2;
    }
    , divide : (number1, number2) => {
        return number1 / number2;
    }
    , square : (number) => {
        return Math.sqrt(number);
    }
};
module.exports = Calc;
```

chai_calc.js
```js
'use strict';
const Calc = require('../calc.js');
const expect = require('chai').expect;

describe("Calc", ()=> {
    describe("calc sum off two numbers", () =>{
        it("the function return the sum of two numbers", () => {
            const sum = Calc.sum(5,5);
            expect(sum).to.be.a('number');
            expect(sum).to.equal(10);
            expect(Calc).to.have.property('sum');
        });
    });
    describe("calc sub off two numbers", () =>{
        it("the function return the subtract of two numbers", () => {
            const subtract = Calc.subtract(5,5);
            expect(subtract).to.be.a('number');
            expect(subtract).to.equal(0);
            expect(Calc).to.have.property('subtract');
        });
    });
    describe("calc  multiply two numbers", () =>{
        it("the function return the multiply of two numbers", () => {
            const multiply = Calc.multiply(5,5);
            expect(multiply).to.be.a('number');
            expect(multiply).to.equal(25);
            expect(Calc).to.have.property('multiply');
        });
    });
    describe("calc  divide two numbers", () =>{
        const number1 = 5;
        const number2 = 1;
        it("the divisor great then 0", () => {
            expect(number2).to.be.a('number');
            expect(number2).not.to.be.NaN;
            expect(number2).to.be.at.least(1);
        });

        it("the function return the divide of two numbers", () => {
            const divide = Calc.divide(5,5);
            expect(divide).to.be.a('number');
            expect(divide).to.equal(1);
            expect(Calc).to.have.property('divide');
        });
    });
    describe("calc  square two numbers", () =>{
        it("the function return the square of two numbers", () => {
            const square = Calc.square(9);
            expect(square).to.be.a('number');
            expect(square).to.equal(3);
            expect(Calc).to.have.property('square');
        });
    });
});
```

Resultado após declaração dos testes sem implementação
```
mocha chai_ex_01.js

  Calc
    calc sum off two numbers
      ✓ the function return the sum of two numbers
    calc sub off two numbers
      ✓ the function return the subtract of two numbers
    calc  multiply two numbers
      ✓ the function return the multiply of two numbers
    calc  divide two numbers
      1) the divisor great then 0
      2) the function return the divide of two numbers
    calc  square two numbers
      3) the function return the square of two numbers

  3 passing (27ms)
  3 failing

  1) Calc calc  divide two numbers the divisor great then 0:
     AssertionError: expected 0 to be at least 1
      at Context.<anonymous> (chai_ex_01.js:43:29)

  2) Calc calc  divide two numbers the function return the divide of two numbers:
     TypeError: Calc.divide is not a function
      at Context.<anonymous> (chai_ex_01.js:47:24)

  3) Calc calc  square two numbers the function return the square of two numbers:
     TypeError: Calc.square is not a function
      at Context.<anonymous> (chai_ex_01.js:56:24)
```

Resultado apos implementação dos métodos:
```
mocha chai_ex_01.js

  Calc
    calc sum off two numbers
      ✓ the function return the sum of two numbers
    calc sub off two numbers
      ✓ the function return the subtract of two numbers
    calc  multiply two numbers
      ✓ the function return the multiply of two numbers
    calc  divide two numbers
      ✓ the divisor great then 0
      ✓ the function return the divide of two numbers
    calc  square two numbers
      ✓ the function return the square of two numbers

  6 passing (21ms)
```

###4) Use o expect para testar a exceção da divisão por zero. (complemento do exercício 3)

Feito no exercício antetior, abaixo apenas o teste criado para barrar divisão por 0.

```
describe("calc  divide two numbers", () =>{
        const number1 = 5;
        const number2 = 0;
        it("the divisor great then 0", () => {
            expect(number2).to.be.a('number');
            expect(number2).not.to.be.NaN;
            expect(number2).to.be.at.least(1);
        });
```

##Parte 02

###1) Use o exemplo de testes do getter e setter e crie um teste para o method. use o exemplo: (https://github.com/Webschool-io/be-mean-instagram/blob/master/Apostila%2Fmodule-nodejs%2Fsrc%2Fmongoose-atomic%2Fschema-method.js)

schema.js
```js
'use strict';
const mongoose = require('mongoose');
const Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/be-mean-instagram');

const _schema = {
  name:  String
, description: String
, type:   String
, attack:   Number
, defense:   Number
, height:   Number
};

const PokemonSchema = new Schema(_schema);

PokemonSchema.methods.findSimilarType = function (cb) {
   return this.model('Pokemon').find({ type: this.type }, cb);
};

const Pokemon = mongoose.model('Pokemon', PokemonSchema);

module.exports  = Pokemon;
```

schema-method-test.js
```js
'use strict';

const Pokemon = require('../schema-method');
const chai =  require('chai');
const expect = chai.expect;
const util = require('util');

describe('Pokemon methods test', ()=>{

    const Poke = { name: 'Teste', type: 'besta' };

    describe("validate find similar type", ()=> {
        it('lista apenas pokemons types iguais', (done) => {
            let pokeBusca = new Pokemon({name: 'Besta 2', type: 'besta'});
            pokeBusca.findSimilarType((err,data) => {
                expect(err).to.not.exist;
                expect(data).to.be.instanceof(Array);
                data.forEach((pokemon) => expect(pokemon).to.have.property('type').and.equal('besta'));
                done();
            });
        });
    });
});
```

Resultado:
```
mocha schema-method-test.js

  Pokemon methods test
    validate find similar type
      ✓ lista apenas timos iguais de pokemon

  1 passing (60ms)
```

###2) Use o exemplo de testes do getter e setter, o static, use o exemplo: https://github.com/Webschool-io/be-mean-instagram/blob/master/Apostila%2Fmodule-nodejs%2Fsrc%2Fmongoose-atomic%2Fschema-static.js

schema-static.js
```js
'use strict';

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/be-mean-instagram');

const _schema = {
  name:  String
, description: String
, type:   String
, attack:   Number
, defense:   Number
, height:   Number
};
const PokemonSchema = new Schema(_schema);

PokemonSchema.statics.search = function (name, cb) {
  return this.where('name', new RegExp(name, 'i')).exec(cb);
};

const Pokemon = mongoose.model('Pokemon', PokemonSchema);

module.exports = Pokemon;
```

schema-static-test.js
```js
'use strict';

const Pokemon = require('../schema-static');
const chai =  require('chai');
const expect = chai.expect;
const util = require('util');

describe('Pokemon static test', ()=>{
    describe("validate find nomes iguais", ()=> {
        it('lista pokemons de mesmo nome', (done) => {
            Pokemon.search('pikachu', function (err, data) {
                expect(err).to.not.exist;
                expect(data).to.be.instanceof(Array);
                data.forEach((pokemon) => expect(pokemon).to.have.property('name').and.equal('Pikachu'));
                done();
            });
        });
    });
});
```

Resultado:
```
mocha schema-static-test.js

  Pokemon static test
    validate find nomes iguais
      ✓ lista pokemons de mesmo nome

  1 passing (57ms)
```

###3) No controller ainda falta dois métodos para testar, o update e o delete, crie-os e faça os testes, no mesmo arquivo que contem os testes create e retrive.

controller-poke-test.js
```js
'use strict';

const util = require('util');
const chai =  require('chai');
const expect = chai.expect;

const pokeController = require('../controller-pokemon');
const Pokemon = require('../schema-static');

describe("Controller User teste", () => {

const poke = {
    name: 'Novo Poke', type: 'besta', attack: 28, defense: 42, height: 0.87
};

describe( "Create new pokemon", () => {
        it('expect a new pokemon has created', (done) => {
            pokeController.create(poke, (err,data) => {
                expect(err).to.not.exist;
                expect(data._id).to.exist;
                expect(data.attack).to.be.eq(28);
                expect(data.defense).to.be.eq(42);
                expect(data.height).to.be.eq(0.87);
                expect(data.type).to.be.eq('besta');
                expect(data.name).to.be.eq('Novo Poke');
                done();
            });
        });
    });

    describe( "Find pokemons with type eq besta", () => {
        it('expect a list of pokemons of type besta', (done) => {
            const query = {type: 'besta' };
            pokeController.retrive(query, (err,data) => {
                expect(err).to.not.exist;
                expect(data).to.be.instanceof(Array);
                data.forEach((pokemon) => expect(pokemon).to.have.property('type').and.equal('besta'));
                done();
            });
        });
    });

    const queryUpRm = {name: 'Novo Poke'};

    describe("Update the pokemon ", () => {
        it('expect update the pokemon', (done) => {
            const mod = {attack: 82, defense: 27};
            const options = {};
            pokeController.update(queryUpRm, mod, options, (err,data) => {
                expect(err).to.not.exist;
                expect(data.nModified).to.be.eq(1);
                expect(data.ok).to.be.eq(1);
                done();
            });
        });
    });

    describe('delete the pokemon', () => {
        it('expect delete the pokemon', (done) => {
            pokeController.delete(queryUpRm, (err, data) => {
                expect(err).to.not.exist;
                expect(data.result.ok).to.be.eq(1);
                done();
            });
        });
    });
});
```
`

Resultado após implementação dos testes e antes de implementar o controller.

```
mocha controller-poke-test.js

  Controller User teste
    Create new pokemon
      ✓ expect a new pokemon has created
    Find pokemons with type eq besta
      ✓ expect a list of pokemons of type besta
    Update the pokemon
      1) expect update the pokemon
    Delete the pokemon
      2) expect delete the pokemon
26 May 23:31:12 - { ok: 1, n: 1 }

  2 passing (108ms)
  2 failing

  1) Controller User teste Update the pokemon  expect update the pokemon:
     TypeError: pokeController.update is not a function
      at Context.<anonymous> (controller-poke-test.js:59:19)

  2) Controller User teste delete the pokemon expect delete the pokemon:
     TypeError: pokeController.delete is not a function
      at Context.<anonymous> (controller-poke-test.js:71:25)
```

Resultado após a implmentação dos metodos update e delete no controller.
```
mocha controller-poke-test.js

  Controller User teste
    Create new pokemon
      ✓ expect a new pokemon has created
    Find pokemons with type eq besta
      ✓ expect a list of pokemons of type besta
    Update the pokemon
      ✓ expect update the pokemon
    delete the pokemon
      ✓ expect delete the pokemon

  4 passing (89ms)
```

###4) Defina TDD em 3 linhas, baseado no que foi dito ate o momento.
TDD é uma metodologia de desenvolvimento baseada em testes. Ou seja, primeiro você constroi os casos de teste a partir da funcionalidade que deseja no sistema em seguida constrói o código para resolver aquele teste e refatora, com intuito de ter uma aplicação sempre testável e com o mínimo de bugs possíveis.


text:
# Node.js - Aula 09 - Exercício
**user:** [ednilsonamaral](https://github.com/ednilsonamaral)
**autor:** Ednilson Amaral

## Faça uma lista de todas as funções que o módulo `assert` possui e coloque no MD.

* `assert(value[, message])`;
* `assert.deepEqual(actual, expected[, message])`;
* `assert.deepStrictEqual(actual, expected[, message])`;
* `assert.doesNotThrow(block[, error][, message])`;
* `assert.equal(actual, expected[, message])`;
* `assert.fail(actual, expected, message, operator)`;
* `assert.ifError(value)`;
* `assert.notDeepEqual(actual, expected[, message])`;
* `assert.notDeepStrictEqual(actual, expected[, message])`;
* `assert.notEqual(actual, expected[, message])`;
* `assert.notStrictEqual(actual, expected[, message])`;
* `assert.ok(value[, message])`;
* `assert.strictEqual(actual, expected[, message])`;
* `assert.throws(block[, error][, message])`.

## Modifique todos os testes que estão sendo usados no `assert.equal` para `assert.deepStrictEqual(valor, result, 'comentário')`, faça todos passarem, coloque os testes no MD.

Primeiramente, fiz o teste falhar.

`add.spec.js`
```js
'use strict';

const assert = require('assert');

assert.deepStrictEqual(3, 2, ['Os números apresentados não são iguais!']);
```

Saída no terminal:

```
$ mocha add.spec.js

assert.js:89
  throw new assert.AssertionError({
  ^
AssertionError: Os números apresentados não são iguais!
    at Object.<anonymous> (/var/www/be-mean-instagram-nodejs/class-09/assert/add.spec.js:5:8)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at /usr/lib/node_modules/mocha/lib/mocha.js:219:27
    at Array.forEach (native)
    at Mocha.loadFiles (/usr/lib/node_modules/mocha/lib/mocha.js:216:14)
    at Mocha.run (/usr/lib/node_modules/mocha/lib/mocha.js:468:10)
    at Object.<anonymous> (/usr/lib/node_modules/mocha/bin/_mocha:403:18)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Function.Module.runMain (module.js:447:10)
    at startup (node.js:141:18)
    at node.js:933:3
```

Então, após, fiz o teste passar:

`add.spec.js`
```js
'use strict';

const assert = require('assert');

assert.deepStrictEqual(3, 3, ['Os números apresentados não são iguais!']);
```

Saída no terminal:

```
$ mocha add.spec.js

  1 passing (5ms)
```

## Na Calculadora do Chai, crie mais 3 testes, um para divisão, outro para multiplicação e um para raiz quadrada, lembrando que não deve aceitar divisão por zero.

* Use o `expect` para testar a exceção da divisão por zero.

Os arquivos são:

`calc.js`
```js
'use strict';

let sum  = (a,b) => a+b;
let sub  = (a,b) => a-b;
let mult = (a,b) => a*b;
let div  = (a,b) => a === 0 || b === 0 ? 0 : a / b;
let sqtr = a => Math.sqrt(a);

module.exports = {
	sum  : sum,
	sub  : sub,
	mult : mult,
	div  : div,
	sqtr : sqtr
};
```

`calc.spec.js`
```js
'use strict';

const expect = require('chai').expect;
const calc = require('./calc');

describe('calc', function() {
	describe('calc testing',  () => {
		it('sum of two number',  () => {
			expect(calc.sum(1,1)).to.equal(2);
		});

		it('sub of two number',  () => {
			expect(calc.sub(2,5)).to.equal(-3);
		});

		it('mult of two number',  () => {
			expect(calc.mult(5,5)).to.equal(25);
		});

		it('div of two number',  () => {
			expect(calc.div(15,5)).to.equal(3);
		});

		it('div of two number dont aceept div by zero',  () => {
			expect(calc.div(15,0)).to.equal(0);
			expect(calc.div(0,1)).to.equal(0);
		});

		it('sqtr of a number',  () => {
			expect(calc.sqtr(16)).to.equal(3);
		});
	});
});
```

Falhando, temos a saída no terminal:

```
$ mocha calc.spec.js

  calc
    calc testing
      ✓ sum of two number
      ✓ sub of two number
      ✓ mult of two number
      ✓ div of two number
      ✓ div of two number dont aceept div by zero
      1) sqtr of a number

  5 passing (27ms)
  1 failing

  1) calc calc testing sqtr of a number:

      AssertionError: expected 4 to equal 3
      + expected - actual

      -4
      +3

      at Context.<anonymous> (calc.spec.js:30:29)
```

Passando, temos a saída no terminal:

```
$ mocha calc.spec.js

  calc
    calc testing
      ✓ sum of two number
      ✓ sub of two number
      ✓ mult of two number
      ✓ div of two number
      ✓ div of two number dont aceept div by zero
      ✓ sqtr of a number

  6 passing (20ms)
```

Apenas um pequenina observação, quando fui fazer esse exercício (16/03/2016 às 08:30) fui visualizar os exemplos na apostila, então acabei notando que o Prof. Itacir colocou como exemplo a resolução do exercício, já com os módulos solicitados por ele e raiz quadrada. Apenas fiz os testes e colei os resultados aqui. Porém, os códigos acima são idênticos aos exemplos que ele deixou na apostila. [Link](https://github.com/Webschool-io/be-mean-instagram/tree/master/Apostila/module-nodejs/src/tdd/chai)!

## Use o exemplo  de testes do *getter* e *setter* e crie um teste para o *method*, use o exemplo (lembre-se de usar callback é testar):

[https://github.com/Webschool-io/be-mean-instagram/blob/master/Apostila/module-nodejs/src/mongoose-atomic/schema-method.js](https://github.com/Webschool-io/be-mean-instagram/blob/master/Apostila/module-nodejs/src/mongoose-atomic/schema-method.js)

`schema-method.spec.js`

```js
'use strict';

const expect = require('chai').expect,
      Pokemon = require('./schema-method'),
      util = require('util');

describe('Testando Methods', () => {
  const namePokemonzinho = {name: 'Pikachu'};
  const typePokemonzinho = {type: 'fogo'};

  describe('method... ', () => {
    it('expect type.typePokemonzinho to be eq ', () => {
      Pokemon.findOne(typePokemonzinho, (err, data) => {
        expect(err).to.not.exist;
        expect(data.type).to.be.eq(typePokemonzinho);

        done();
      });
    });
  });
});
```

Saída no terminal:

```
$ mocha schema-method.spec.js

  Testando Methods
    method...
      ✓ expect type.typePokemonzinho to be eq

  1 passing (60ms)
```

## Use o exemplo  de testes do *getter* e *setter*, o *static*, use o exemplo (lembre-se de usar callback é testar):

[https://github.com/Webschool-io/be-mean-instagram/blob/master/Apostila/module-nodejs/src/mongoose-atomic/schema-static.js](https://github.com/Webschool-io/be-mean-instagram/blob/master/Apostila/module-nodejs/src/mongoose-atomic/schema-static.js)

`schema-static.spec.js`

```js
'use strict';

const expect = require('chai').expect,
      Pokemon = require('./schema-method'),
      util = require('util');

describe('Testando Static', () => {
  const namePokemonzinho = {name: /pikachu/i};

  describe('static... ', () => {
    it('expect name.namePokemonzinho to be eq ', () => {
      Pokemon.findOne(namePokemonzinho, (err, data) => {
        expect(err).to.not.exist;
        expect(data.name).to.be.eq(namePokemonzinho);

        done();
      });
    });
  });
});
```

Saída no terminal:

```
$ mocha schema-static.spec.js

  Testando Static
    static...
      ✓ expect name.namePokemonzinho to be eq

  1 passing (56ms)
```

## No *controller* ainda faltam dois métodos para testar, o *update* e *delete*, crie-os  e faça os testes, no mesmo aRquivo que contém os testes, *create* e *retrieve*.

### Update

```js
'use strict';

const expect = require('chai').expect;
const ctrl = require('./pokemon-controller');

describe('Controller of Pokemons', () => {
  describe('UPDATE A POKEMON... ', () => {
    const descriptionPokemonzinho = {description: 'olá, tudo bem?!'};
    const attackPokemonzinho = {attack: {$gte: 25}};

    it('expect update a pokemonzinho ', done => {
      ctrl.update(descriptionPokemonzinho, attackPokemonzinho,(err,data) => {
        expect(err).to.not.exist;
        expect(data._id).to.exist;
        expect(data.attack).to.be.eq(attackPokemonzinho);
        expect(data.description).to.be.eq(descriptionPokemonzinho);

        done();
      });
    });
  });
});
```

Saída no terminal:

```
$ mocha pokemon-controller.spec.js

  Controller of Pokemons
    UPDATE A POKEMON...
Alterou: { result: { ok: 1, n: 1},

    ✓ expect update a pokemonzinho

1 passing (56ms)
```

### Delete

```js
'use strict';

const expect = require('chai').expect;
const ctrl = require('./pokemon-controller');

describe('Controller of Pokemons', () => {
  describe('DELETE A POKEMON... ', () => {
    const descriptionPokemonzinho = {description: 'olá, tudo bem?!'};
    const attackPokemonzinho = {attack: {$gte: 25}};

    it('expect delete a pokemonzinho ', done => {
      ctrl.delete(attackPokemonzinho,(err,data) => {
        expect(err).to.not.exist;
        expect(data._id).to.exist;
        expect(data.attack).to.be.eq(attackPokemonzinho);

        done();
      });
    });
  });
});
```

Saída no terminal:

```
$ mocha pokemon-controller.spec.js

  Controller of Pokemons
    DELETE A POKEMON...
Deletou: { result: { ok: 1, n: 1},

    ✓ expect delete a pokemonzinho

1 passing (56ms)
```

## Defina TDD em 3 linhas, baseado no que foi dito até o momento.

TDD é o desenvolvimento de softwares orientado a testes. Não fica apenas testando os códigos, também é considerado uma filosofia. Fortemente influenciada pelo movimento ágil. Ele traz inúmeras vantagens para sistemas complexos, sejam pequenos, médios ou grandes, já que é possível reduzir o tempo de *deploy* e correção de bugs, não desenvolvendo códigos desnecessários, melhorando assim a qualidade do software.


text:
# Node.js - Aula 09 - Exercício

**user:** [gkal19](https://github.com/gkal19)

**autor:** Gabriel Kalani

**Data:** 1468463801442

### 1 - Faça uma lista de todas as funções que o modulo assert possui e coloque no md.

* `assert(value[, message])`;
* `assert.deepEqual(actual, expected[, message])`;
* `assert.deepStrictEqual(actual, expected[, message])`;
* `assert.doesNotThrow(block[, error][, message])`;
* `assert.equal(actual, expected[, message])`;
* `assert.fail(actual, expected, message, operator)`;
* `assert.ifError(value)`;
* `assert.notDeepEqual(actual, expected[, message])`;
* `assert.notDeepStrictEqual(actual, expected[, message])`;
* `assert.notEqual(actual, expected[, message])`;
* `assert.notStrictEqual(actual, expected[, message])`;
* `assert.ok(value[, message])`;
* `assert.strictEqual(actual, expected[, message])`;
* `assert.throws(block[, error][, message])`.

### 2 - Modifique todos os testes que estão usando assert.equal para assert.deepStrictEqual(valor, result, "comentario") faça todos passarem, coloque os testes no md.

> Primeiramente, O teste deve falhar

```
`// add.spec.js
'use strict';

const assert = require('assert');

assert.deepStrictEqual(3, 2, ['Os números não são iguais!']);
```

```shell
gkal19:~/workspace/dever/nodejs $ mocha add.spec.js

assert.js:89
  throw new assert.AssertionError({
  ^
AssertionError: Os números não são iguais!
    at Object.<anonymous> (/home/ubuntu/workspace/dever/nodejs/add.spec.js:5:8)
    at Module._compile (module.js:435:26)
    at Object.Module._extensions..js (module.js:442:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:313:12)
    at Module.require (module.js:366:17)
    at require (module.js:385:17)
    at /home/ubuntu/.nvm/versions/node/v4.2.4/lib/node_modules/mocha/lib/mocha.js:220:27
    at Array.forEach (native)
    at Mocha.loadFiles (/home/ubuntu/.nvm/versions/node/v4.2.4/lib/node_modules/mocha/lib/mocha.js:217:14)
    at Mocha.run (/home/ubuntu/.nvm/versions/node/v4.2.4/lib/node_modules/mocha/lib/mocha.js:469:10)
    at Object.<anonymous> (/home/ubuntu/.nvm/versions/node/v4.2.4/lib/node_modules/mocha/bin/_mocha:404:18)
    at Module._compile (module.js:435:26)
    at Object.Module._extensions..js (module.js:442:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:313:12)
    at Function.Module.runMain (module.js:467:10)
    at startup (node.js:136:18)
    at node.js:963:3
```

> Agora o teste deve passar

```
// add.spec.js
'use strict';

const assert = require('assert');

assert.deepStrictEqual(3, 3, ['Os números não são iguais!']);
```

```shell
gkal19:~/workspace/dever/nodejs $ mocha add.spec.js

  1 passing (3ms)
```

> No exercício abaixo, vou logo falando que os arquivos são quase os mesmos das aulas do professor Pompeu, encontrados no [Link](https://github.com/Webschool-io/be-mean-instagram/tree/master/Apostila/module-nodejs/src/tdd/chai) ao lado.

## Na Calculadora do Chai, crie mais 3 testes, um para divisão, outro para multiplicação e um para raiz quadrada, lembrando que não deve aceitar divisão por zero.

> Usei o `expect` para testar a exceção da divisão por zero.`

```js
// calc.js
'use strict';

let sum  = (a,b) => a+b;
let sub  = (a,b) => a-b;
let mult = (a,b) => a*b;
let div  = (a,b) => a === 0 || b === 0 ? 0 : a / b;
let sqtr = a => Math.sqrt(a);

module.exports = {
  sum,
  sub,
  mult,
  div,
  sqtr
};
```

```js
// calc.spec.js
'use strict';

const expect = require('chai').expect;
const calc = require('./calc');

describe('calc', () => {
  describe('calc testing',  () => {
    it('sum of two number',  () => {
      expect(calc.sum(1,1)).to.equal(2);
    });

    it('sub of two number',  () => {
      expect(calc.sub(2,5)).to.equal(-3);
    });

    it('mult of two number',  () => {
      expect(calc.mult(5,5)).to.equal(25);
    });

    it('div of two number',  () => {
      expect(calc.div(15,5)).to.equal(3);
    });

    it('div of two number dont aceept div by zero',  () => {
      expect(calc.div(15,0)).to.equal(0);
      expect(calc.div(0,1)).to.equal(0);
    });

    it('sqtr of a number',  () => {
      expect(calc.sqtr(16)).to.equal(3);
    });
  });
});
```

> FALHANDO:

```shell
gkal19:~/workspace/dever/nodejs $ mocha calc.spec.js

  calc
    calc testing
      ✓ sum of two number
      ✓ sub of two number
      ✓ mult of two number
      ✓ div of two number
      ✓ div of two number dont aceept div by zero
      1) sqtr of a number

  5 passing (24ms)
  1 failing

  1) calc calc testing sqtr of a number:

      AssertionError: expected 4 to equal 3
      + expected - actual

      -4
      +3

      at Context.<anonymous> (calc.spec.js:30:29)
```

> PASSANDO:

```shell
gkal19:~/workspace/dever/nodejs $ mocha calc.spec.js

  calc
    calc testing
      ✓ sum of two number
      ✓ sub of two number
      ✓ mult of two number
      ✓ div of two number
      ✓ div of two number dont aceept div by zero
      ✓ sqtr of a number

  6 passing (20ms)
```

## Use o exemplo  de testes do *getter* e *setter* e crie um teste para o *method*, use o exemplo (lembre-se de usar callback é testar):
[LINK](https://github.com/Webschool-io/be-mean-instagram/blob/master/Apostila/module-nodejs/src/mongoose-atomic/schema-method.js)

```js
// schema-method.spec.js
'use strict';

const expect = require('chai').expect,
      Pokemon = require('./schema-method'),
      util = require('util');

describe('Testando as Methods', () => {
  const namePokemonzinho = {name: 'Pikachu'};
  const type = {type: 'fogo'};

  describe('method... ', () => {
    it('expect type.type to be eq ', () => {
      Pokemon.findOne(type, (err, data) => {
        expect(err).to.not.exist;
        expect(data.type).to.be.eq(type);

        done();
      });
    });
  });
});
```

```shell
gkal19:~/workspace/dever/nodejs mocha schema-method.spec.js

  Testando Methods
    method...
      ✓ expect type.type to be eq

  1 passing (20ms)
```

## Use o exemplo  de testes do *getter* e *setter*, o *static*, use o exemplo (lembre-se de usar callback é testar):
[LINK](https://github.com/Webschool-io/be-mean-instagram/blob/master/Apostila/module-nodejs/src/mongoose-atomic/schema-static.js)

```js
// schema-static.spec.js
'use strict';

const expect = require('chai').expect,
      Pokemon = require('./schema-method'),
      util = require('util');

describe('Testando Static', () => {
  const name = {name: /pikachu/i};

  describe('static... ', () => {
    it('expect name.name to be eq ', () => {
      Pokemon.findOne(name, (err, data) => {
        expect(err).to.not.exist;
        expect(data.name).to.be.eq(name);

        done();
      });
    });
  });
});
```

```
gkal19:~/workspace/dever/nodejs mocha schema-static.spec.js

  Testando Static
    static...
      ✓ expect name.name to be eq

  1 passing (56ms)
```

## No *controller* ainda faltam dois métodos para testar, o *update* e *delete*, crie-os  e faça os testes, no mesmo aRquivo que contém os testes, *create* e *retrieve*.

```js
// UPDATE
'use strict';

const expect = require('chai').expect;
const ctrl = require('./pokemon-controller');

describe('Controller of Pokemons', () => {
  describe('Atualizar um Pokémon... ', () => {
    const description = {description: 'Bem louco'};
    const attack = {attack: {$gte: 25}};

    it('expect update a pokemon ', done => {
      ctrl.update(description, attack,(err,data) => {
        expect(err).to.not.exist;
        expect(data._id).to.exist;
        expect(data.attack).to.be.eq(attack);
        expect(data.description).to.be.eq(description);

        done();
      });
    });
  });
});
// OUTPUT UPDATE
  Controller of Pokemons
    Atualizar um Pokémon...
Alterou: { result: { ok: 1, n: 1},

    ✓ expect update a pokemon

1 passing (56ms)

// DELETE
'use strict';

const expect = require('chai').expect;
const ctrl = require('./pokemon-controller');

describe('Controller of Pokemons', () => {
  describe('Deletar um Pokémon... ', () => {
    const description = {description: 'Fui deletado </3'};
    const attack = {attack: {$gte: 25}};

    it('expect delete a pokemon ', done => {
      ctrl.delete(attack,(err,data) => {
        expect(err).to.not.exist;
        expect(data._id).to.exist;
        expect(data.attack).to.be.eq(attack);

        done();
      });
    });
  });
});
// OUTPUT DELETE
  Controller of Pokemons
    Deletar um Pokémon...
Deletou: { result: { ok: 1, n: 1},

    ✓ expect delete a pokemon

1 passing (56ms)
```

## Defina TDD em 3 linhas, baseado no que foi dito até o momento.
TDD é o desenvolvimento de softwares orientado a testes, TDD é o Desenvolvimento Orientado por Testes ou para os mais THUG LIFE'S, TEST DRIVEN DEVELOPMENT, TDD é vida, TDD é amor. TDD te ajuda reduzindo o tempo de deploys e correção de bugs. Basicamente ele se baseia em pequenos ciclos de repetições e nós desenvolvemos o nosso software baseado em testes que são escritos antes do nosso código de produção!
- Clico de Desenvolvimento
  + RED
    * Escrevemos esse teste em que inicialmente ele não passa

    (Depois disso, adicionamos uma nova funcionalidade do sistema)

  + GREEN
    * Fazemos o teste passar nessa etapa
  + REFACTOR
    * Refatoramos o código da nova funcionalidade

    (E por fim, escrevemos o próximo Teste)

Use TDD e seja feliz :heart:

Fiz um belo Marketing agora.


text:
# Node.js - Aula 10 - Exercício
**user:** [tuchedsf](https://github.com/tuchedsf)
**autor:** Diego Ferreira

##PARTE 01
###1) Criar um módulo de redirecionamento para quando não encontrar a rota redirecionar para url/404.
```js
//modulo
'use strict'
module.exports = (req,res) => {
  res.redirect('/404');
}

//Principal
'use strict';

const express = require('express');
const app = express();
const callback404 = require('./modulo.redirect');

app.get('/', (req,res) => {
  res.send('<h1> Hello World </h1>');
}).get('/404', (req,res) => {
  res.status(404).send('404 - Not Found');
}).get('/*', (req,res) => {
  callback404(req,res);
});

app.listen(3000, () =>{
  console.log('Servidor sendo executado');
});
```

### 2) Criar módulo onde seja passado o retorno, podendo ser string ou buffer, caso seja String definir cabeçalho correto mesmo usando res.send.
```js
//modulo
module.exports = (req,res) => {
  res.set('Content-Type', 'text-html'); //seta o content type para text-html, senao iria mostrar 8ctrestrem
  res.send(new Buffer('<h1> Hello World </h1>'));
}

//Principal
'use strict';

const express = require('express');
const app = express();
const Content = require('./modules/Content');

app.get('/', (req,res) => {
  return Content(req,res);
});

app.listen(3000, () =>{
  console.log('Servidor sendo executado');
});
```

Cabeçalho:
```
Connection →keep-alive
Content-Length →22
Content-Type →text-html
Date →Sat, 28 May 2016 16:24:07 GMT
ETag →W/"16-JxTuzBN3iv2w2JCcxw774w"
X-Powered-By →Express
```

## PARTE 2
### 3) Criar um módulo para renderização de views, onde o mesmo recebe o caminho para a view e o tipo do template engine, para retornar a view corretamente.
No meu exemplo são utilizados os templates pug e jade, ou seja, o modulo recebe dois parametros o primeiro template que pode ser pug ou jade e o segundo a view que o mesmo deseja exibir.

app-exercicio3.js
```js
'use strict';

const express = require('express');
const app = express();
const path =  require('path');

const users = [
  {name : "Diego"}
  ,{name: "Jose "}
];

app.get('/users/:template/:view', function (req, res, next) {

  const template = req.params.template;
  const view = req.params.view;
  console.log(template);
  app.set('view engine',template);

  switch(view) {
     case 'list':
      res.render(path.join(__dirname,'/modules/users/views/'+view), {title: 'list user', message: 'Lista Usuarios',  template: template, view: view,users: users});
      break;
     case 'index':
     res.render(path.join(__dirname,'/modules/users/views/'+view), {title: 'Index file', message: 'Seja bem vindo pagina inicial', template: template, view: view});
   default:
     res.send(404, 'Não achei!');
}
});

app.listen(3000, function () {
  console.log('Servidor rodando em locahost:3000');
});
```

Obs.: Por padrão o pug e o jade utilizam da mesma formatação então apenas exibi o código de montagem da tela uma unica vez.
views/index.jade === views/index.pug
```
html
  head
    title= title
  body
    h1= template + ' - ' + view
    br
    h2= message
```

views/list.jade === views/list.pug
```
html
  head
    title= title
  body
    h1= template + ' - ' + view
    br
    h2= message
    ul
      each user in users
        li= user.name
```

Chamadas
```
http://localhost:3000/users/jade/index
http://localhost:3000/users/pug/index

jade - index

Seja bem vindo pagina inicial

http://localhost:3000/users/jade/list
http://localhost:3000/users/pug/list

jade - list

Lista Usuarios

Diego
Jose
```

### 4) Criar um módulo para entrega de arquivos, onde o mesmo recebe o caminho para o arquivo e o tipo do arquivo, para retornar o arquivo corretamente.

module/SendFiles.js
```js
'use strict';

module.exports = (req, res) => {

  const options = {
    root: __dirname + '/public/',
    dotfiles: 'deny',
    headers: {
      'x-timestamp': Date.now(),
      'x-sent': true
    }
  };

  let fileName = req.params.name;
  const fileType = req.params.type;

  switch (fileType) {
    case 'png':
      res.set('Content-Type', 'image/png');
      fileName = fileName +'.'+fileType;
      break;
    default:
      res.status(400).send('tipo do arquivo solicitado invalido');
      break;
  }

  res.sendFile(fileName, options, function (err) {
    if (err) {
      console.log(err);
      res.status(err.status).end();
    }
    else {
      console.log('Sent:', fileName);
    }
  });
};
```

app-exercicio4.js
```js
'use strict';

const express = require('express');
const app = express();
const SendFiles = require('./modules/files/SendFiles');

app.get('/file/:name/:type', function (req, res, next) {
  return SendFiles(req, res);
});

app.listen(3000, function () {
  console.log('Servidor rodando em locahost:3000');
});
```

Resultado
```
Chamada: localhost:3000/files/logo/png

Retorno: arquivo imagem png da pasta public com o nome logo e extensão png.
![](http://i35.tinypic.com/vmzl1e.jpg)

Caso for informado uma extensão invalida exemplo jpg, o retorno sera uma mensagem informando que o tipo do arquivo solicitado é invalido.
Chamada: localhost:3000/files/logo/jpg

Retorno:
tipo do arquivo solicitado invalido
```

## PARTE 3
### 5)  criar uma busca, dos pokemons, com o mongoose que pagine o resultado retornando os links corretamente e que essa busca seja retornada como:
- html
- json
Obs.: Não esquecer do link para previous e first quando necessários.

modules/pokemons/db-config.js
```js
//importar o mongoose
const mongoose = require('mongoose');
const uriDB = 'mongodb://localhost/be-mean-pokemons';
//criar uma conexão com mongo
mongoose.connect(uriDB);
mongoose.connection.on('connected', function(){
 console.log("Mongo default connection connected to " + uriDB);
});
mongoose.connection.on('error', function(err){
 console.log("Mongo default connection error" + err);
});
mongoose.connection.on('disconnected', function(){
 console.log("Mongo default connection disconnected");
});
mongoose.connection.on('open', function(){
 console.log("Mongo default connection open");
});
process.on('SIGINT',function(){
    mongoose.connection.close(function(){
       console.log("The connection is closed");
        process.exit(0);
    });
});
```

modules/pokemons/model.js
```js
'use strict';
module.exports = function(Schema, ModelName) {
    const mongoose = require('mongoose');
    return mongoose.model(ModelName, Schema);
}
```

modules/pokemons/molecule.js
```js
'use strict';

const mongoose = require('mongoose');

const _schema = {
  name : {type: String, required: true},
  attack : {type: Number, default : 0},
  defense : {type: Number},
  height : {type: Number },
  created: {type: Date},
  hp: {type: Number},
  speed: {type: Number},
  types: []
}

const PokemonSchema = new mongoose.Schema(_schema);

module.exports = PokemonSchema;
```

modules/pokemons/organism.js
```js
'use strict'

const Molecule = require('./molecule');
const Organism = require('./model')(Molecule, 'Pokemons');
const callback = require('./callback');

const find = (res, query, page) => {
        Organism.count({}, (err, count) => {
            const maxPages = Math.ceil(count/3);
            Organism.find(query,  (err, data) => callback(err,data, res, Number.parseInt(page), Number.parseInt(maxPages))).limit(3).skip(3 * (page - 1));
        });
};

const CRUD = {
    find
}
module.exports = CRUD;
```

modules/pokemons/callback.js
```js
'use strict'

const formataHtml = (data) => {
    let html = '';
    data.forEach(function (element, index, array) {
    console.log(element);
    html = html + '<ul>';
        html = html + '<li>' + element.id + '</li>';
        html = html + '<li>' + new Date(element.created) + '</li>';
        html = html + '<li>' + element.defense + '</li>';
        html = html + '<li>' + element.height + '</li>';
        html = html + '<li>' + element.name + '</li>';
        html = html + '<li>' + element.speed + '</li>';
        html = html + '<li>' + element.types.join(" - ") + '</li>';
        html = html + '<li>' + element.attack + '</li>';
        html = html + '</ul>';
    });
    return html;
}

module.exports = (err,data,res,page,maxPages) => {
    if (err) {
        console.log(err);
        res.status(404, err).end();
    }

    if ( page === 1 ) {
        res.links({
            next: 'http://localhost/pokemons?page='+ Number(page + 1) ,
            last: 'http://localhost/pokemons?page='+ maxPages
        });
    } else if (page > 1 && page < maxPages){
        res.links({
            first: 'http://localhost/pokemons?page=1',
            previous: 'http://localhost/pokemons?page='+ (page - 1),
            next: 'http://localhost/pokemons?page='+ (page + 1),
            last: 'http://localhost/pokemons?page='+ maxPages
        });
    }else if (page === maxPages){
        res.links({
            first: 'http://localhost/pokemons?page=1',
            previous: 'http://localhost/pokemons?page='+ (page - 1)
        });
    }

    res.format({
        'text/html' : function() {
            // res.set('ContentType','text/html');
            const html = formataHtml(data);
            res.type('html');
            res.send(html);
        }
        , 'application/json' : function() {
            //res.set('ContentType','json');
            res.type('json');
            res.json(data);
        }
        , 'default' : function() {
            res.status(406).send('Formato não aceito');
        }
    });
};
```

app-exercicio5.js
```js
'use strict'

require('./modules/pokemons/db-config');
const express = require('express');
const app = express();
const Pokemon = require('./modules/pokemons/organism');

app.get('/pokemons', (req,res) => {

const query = {};

let page = req.query.page;
if (page === undefined) page = 1;
//console.log(page);
 Pokemon.find(res, query, page);
});

app.listen(3000,() => {
    console.log('Servidor executando na porta 3000.');
});
```

###### parametro "Accept" no headers diferente de html e diferente de json
```
Method: GET
Chamada: localhost:3000/pokemons
Headers:  Accept - application/xml

Retorno:
Formato não aceito
```

###### parametro "Accept" json, retorno 3 primeiros elementos da coleção e no cabeçalho da resposta os links de navegação. Como é a primeira página aparecem apenas next e last.
```
Parametros requisição
Method: GET
Chamada: localhost:3000/pokemons
Headers:  Accept - application/xml

=====Resposta=====

Retorno cabeçalho:
Connection →keep-alive
Content-Length →495
Content-Type →application/json; charset=utf-8
Date →Tue, 28 Jun 2016 00:25:59 GMT
ETag →W/"1ef-4PIKqX0762kGtsv7eWywww"
Link →<http://localhost/pokemons?page=2>; rel="next", <http://localhost/pokemons?page=204>; rel="last"
Vary →Accept
X-Powered-By →Express

Retorno json:
[
  {
    "_id": "564b1dad25337263280d047c",
    "created": "2013-11-03T15:05:41.280Z",
    "defense": 80,
    "height": 10,
    "hp": 59,
    "name": "Wartortle",
    "speed": 58,
    "types": [
      "water"
    ],
    "attack": 63
  },
  {
    "_id": "564b1dad25337263280d047b",
    "created": "2013-11-03T15:05:41.273Z",
    "defense": 58,
    "height": 11,
    "hp": 58,
    "name": "Charmeleon",
    "speed": 80,
    "types": [
      "fire"
    ],
    "attack": 64
  },
  {
    "_id": "564b1dad25337263280d047a",
    "created": "2013-11-03T15:05:41.271Z",
    "defense": 43,
    "height": 6,
    "hp": 39,
    "name": "Charmander",
    "speed": 65,
    "types": [
      "fire"
    ],
    "attack": 52
  }
]
```

###### parametro "Accept" html para mostrar que alem do json aceita html,e passado uma página intermediária como parametro, então é retornado 3 elementos e nos headers da resposta os links first/previous/next/last de navegação.

```
Parametros requisição
Method: GET
Chamada: localhost:3000/pokemons?page=10
Headers:  Accept - text/html

=====Resposta=====

Retorno cabeçalho:
Connection →keep-alive
Content-Length →509
Content-Type →text/html; charset=utf-8
Date →Tue, 28 Jun 2016 00:31:10 GMT
ETag →W/"1fd-rGoXU5HAyva5iOyAe3VwdA"
Link →<http://localhost/pokemons?page=1>; rel="first", <http://localhost/pokemons?page=9>; rel="previous", <http://localhost/pokemons?page=11>; rel="next", <http://localhost/pokemons?page=204>; rel="last"
Vary →Accept
X-Powered-By →Express

Retorno html
<ul>
    <li>564b1daf25337263280d0495</li>
    <li>Sun Nov 03 2013 13:05:41 GMT-0200 (BRST)</li>
    <li>35</li>
    <li>7</li>
    <li>Bellsprout</li>
    <li>40</li>
    <li>poison - grass</li>
    <li>75</li>
</ul>
<ul>
    <li>564b1db025337263280d0497</li>
    <li>Sun Nov 03 2013 13:05:41 GMT-0200 (BRST)</li>
    <li>67</li>
    <li>8</li>
    <li>Nidorina</li>
    <li>56</li>
    <li>poison</li>
    <li>62</li>
</ul>
<ul>
    <li>564b1db025337263280d0498</li>
    <li>Sun Nov 03 2013 13:05:41 GMT-0200 (BRST)</li>
    <li>85</li>
    <li>6</li>
    <li>Sandshrew</li>
    <li>40</li>
    <li>ground</li>
    <li>75</li>
</ul>
```

###### parametro "Accept" json novamente,e passado a última página como parametro, é retornado a última página de elementos e nos headers da resposta os links first/previous de navegação.
```
Parametros requisição
Method: GET
Chamada: localhost:3000/pokemons?page=204
Headers:  Accept - application/json

=====Resposta=====
Retorno cabeçalho:
Connection →keep-alive
Content-Length →164
Content-Type →application/json; charset=utf-8
Date →Tue, 28 Jun 2016 00:32:20 GMT
ETag →W/"a4-YzzkHzo/NR9bvbxRKGlKHQ"
Link →<http://localhost/pokemons?page=1>; rel="first", <http://localhost/pokemons?page=203>; rel="previous"
Vary →Accept
X-Powered-By →Express

Retorno json
[
  {
    "_id": "564b1de725337263280d06da",
    "created": "2013-11-03T15:05:42.420Z",
    "defense": 62,
    "height": 0,
    "hp": 123,
    "name": "Gogoat",
    "speed": 68,
    "types": [
      "grass"
    ],
    "attack": 100
  }
]
```


text:
# Node.js - Aula 10 - Exercício

**User:** [gkal19](https://github.com/gkal19)

**Autor:** Gabriel Kalani

### 1 - Criar um módulo de redirecionamento para quando não encontrar a rota redirecionar para `url/404`
```js
'use strict';

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.redirect('admin');
})
.get('/admin', (req, res) => {
  res.send('Rota de Admin');
});
/*app.use(function(req, res, next) {
  res.status(404).send('Nada encontrado!');
});*/
app.get('*', (req, res) => {
  res.send('<section align="center"><h1>O que houve?! Tivemos um 404 aqui.</h1><hr><img src="https://raw.githubusercontent.com/Webschool-io/be-mean-instagram/master/Apostila/module-nodejs/src/aula-express/public/logo-webschool.png"></section>', 404);
});
app.listen(3000, () => {
  console.log('Servidor rodando em localhost:3000');
});
```
##### Resultado
![](http://i.imgur.com/B94I4bV.png)

> Explicando, bom no código podem ver que o GET está setado para ir apenas para `/admin` e nenhum outro além dele. Por isso na imagem acima, eu acessei no browser: `http://localhost:3000/admin/p` que resultou no seguinte.

### 2 - Adicionar o retorno correto para os seguinte códigos:
> 200,201,202,405,500

```js
// 200
app.get('/', (req, res) => {
    res.status(200).send('AEE CARAI, DE BOA!')
});

// 201
app.get('/', (req, res) => {
    res.status(201).send('DE BOA!')
});

// 202
app.get('/', (req, res) => {
    res.status(202).send('EHH, PODE SER!')
});

// 405
app.get('/', (req, res) => {
    res.status(405).send('NÃO PERMITIDO!')
});

// 500
app.get('/', (req, res) => {
    res.status(500).send('ERRO NO SERVIDOR!')
});
```

### 3 - Criar um módulo onde seja passado o retorno, podendo ser String ou Buffer, caso seja String definir cabeçalho correto mesmo usando res.send

### 4 - Criar uma busca, dos Pokemons, com o Mongoose que pagine o resultado retornando os links corretamente e que essa busca seja retornada como:

- html

- json

ps: Não esquecer do link para previous e first quando necessários.


text:
'use strict';

const express = require('express');
const app = express();

app.get('/', function(req, res) {
    res.send('Hey, YOW!!');
});

// page de not found
app.get('/not-found', function(req, res) {
    res.status(404).send('Sorry, page not found! =(');
});

// enviando not found para a página de não encontrado
app.get('/*', function(req, res) {
    res.redirect('/not-found');
})

app.listen(3000, function () {
    console.log('Servidor rodando em http://localhost:3000/');
});


text:
'use strict';

const path = require('path');
const express = require('express');
const app = express();

app.set('views', path.join(__dirname, 'modules'));
app.set('view engine', 'jade');

app.get('/', function(req, res) {
    res.render('index', {
        title: 'Be MEAN',
        message: 'Welcome to Be MEAN',
        description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
    });
});

app.listen(3000, function () {
    console.log('Servidor rodando em http://localhost:3000/');
});


text:
'use strict';

const express = require('express');
const app = express();
const SendFiles = require('./modules/SendFiles');

app.get('/file/:name/:type', function(req, res, next) {
    return SendFiles(req, res);
});

app.listen(3000, function() {
    console.log('Servidor rodando em http://localhost:3000');
});


text:
'use strict';

const express = require('express');
const app = express();

app.get('/', function(req, res) {
    res.set({'Content-Type': 'text/html'});
    res.send(new Buffer('Oi, bufferzinho! :)'));
});

app.listen(3000, function () {
    console.log('Servidor rodando em http://localhost:3000/');
});


text:
# Node.js - Aula 10 - Exercício
**user:** [ednilsonamaral](https://github.com/ednilsonamaral)
**autor:** Ednilson Amaral
**data:** 1468266682866

## Criar um módulo de redirecionamento para quando não encontrar a rota redirecionar para URL/404.

```js
'use strict';

const express = require('express');
const app = express();

app.get('/', function(req, res) {
    res.send('Hey, YOW!!');
});

// page de not found
app.get('/not-found', function(req, res) {
    res.status(404).send('Sorry, page not found! =(');
});

// enviando not found para a página de não encontrado
app.get('/*', function(req, res) {
    res.redirect('/not-found');
})

app.listen(3000, function () {
    console.log('Servidor rodando em http://localhost:3000/');
});
```

## Criar um módulo onde seja passado o retorno, podendo ser *String* ou *Buffer*, caso seja *String* definir cabeçalho correto mesmo usando `res.send`.

```js
'use strict';

const express = require('express');
const app = express();

app.get('/', function(req, res) {
    res.set({'Content-Type': 'text/html'});
    res.send(new Buffer('Oi, bufferzinho! :)'));
});

app.listen(3000, function () {
    console.log('Servidor rodando em http://localhost:3000/');
});
```

## Criar um módulo para renderização de views, onde o mesmo recebe o caminho para a view e o tipo do template engine, para retornar a view corretamente.

```js
'use strict';

const path = require('path');
const express = require('express');
const app = express();

app.set('views', path.join(__dirname, 'modules'));
app.set('view engine', 'jade');

app.get('/', function(req, res) {
    res.render('index', {
        title: 'Be MEAN',
        message: 'Welcome to Be MEAN',
        description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
    });
});

app.listen(3000, function () {
    console.log('Servidor rodando em http://localhost:3000/');
});
```

## Criar um módulo para entrega de arquivos, onde o mesmo recebe o caminho para o arquivo e o tipo do arquivo, para retornar o arquivo corretamente.

`modules/SendFiles.js`
```js
'use strict';

module.exports = function(req, res) {
    const options = {
        root: __dirname + '/_public/',
        dotfiles: 'deny',
        headers: {
            'x-timestamp': Date.now(),
            'x-sent': true
        }
    };

    const fileName = req.params.name;
    const fileType = req.params.type;

    switch (fileType){
        case 'png':
            res.set({'Content-Type': 'image/png'});
            fileName = fileName +'.'+fileType;
            break;
        default:
            res.status(400).send('Arquivo não suportado!');
            break;
    }

    res.sendFile(fileName, options, function (err) {
        if (err) {
            console.log(err);
            res.status(err.status).end();
        } else {
            console.log('Sent:', fileName);
        }
    });
};
```

`app-sendFiles.js`
```js
'use strict';

const express = require('express');
const app = express();
const SendFiles = require('./modules/SendFiles');

app.get('/file/:name/:type', function(req, res, next) {
    return SendFiles(req, res);
});

app.listen(3000, function() {
    console.log('Servidor rodando em http://localhost:3000');
});
```

## Criar uma busca, dos Pokemons, com o Mongoose, que pagine o resultado retornando os links corretamente e que essa busca seja retornada como:

- html
- json

- *ps: Não esquecer do link para `previous` e `first` quando necessários.*

- rota: /pokemons
- 3 páginas

`db/config.js`
```js
'use strict';

const mongoose = require('mongoose');
const uriDB = 'mongodb://localhost/be-mean';

mongoose.connect(uriDB);

mongoose.connection.on('connected', function(){
    console.log("Mongo default connection connected to " + uriDB);
});

mongoose.connection.on('error', function(err){
    console.log("Mongo default connection error" + err);
});

mongoose.connection.on('disconnected', function(){
    console.log("Mongo default connection disconnected");
});

mongoose.connection.on('open', function(){
    console.log("Mongo default connection open");
});

process.on('SIGINT',function(){
    mongoose.connection.close(function(){
        console.log("The connection is closed");
        process.exit(0);
    });
});
```

`model.js`
```js
'use strict';

module.exports = function(Schema, Model) {
    const mongoose = require('mongoose');
    return mongoose.model(Model, Schema);
}
```

`schema.js`
```js
'use strict';

const mongoose = require('mongoose');

const _schema = {
    name: {type: String, required: true},
    attack: {type: Number, default : 0},
    defense: {type: Number},
    height: {type: Number },
    created: {type: Date},
    hp: {type: Number},
    speed: {type: Number},
    types: []
};

const PokemonSchema = new mongoose.Schema(_schema);

module.exports = PokemonSchema;
```

`pagination.js`
```js
'use strict';

const formatandoHTML = function(data) {
    let html = '';

    data.forEach(function(pokemonItem, index, arr) {
        console.log(pokemonItem);

        html = html + '<ul>';
            html = html + '<li>' + new Date(pokemonItem.created) + '</li>';
            html = html + '<li>' + pokemonItem.defense + '</li>';
            html = html + '<li>' + pokemonItem.height + '</li>';
            html = html + '<li>' + pokemonItem.name + '</li>';
            html = html + '<li>' + pokemonItem.speed + '</li>';
            html = html + '<li>' + pokemonItem.types.join(" // ") + '</li>';
            html = html + '<li>' + pokemonItem.attack + '</li>';
        html = html + '</ul>';
    });

    return html;
};

module.exports = function(err, data, numPage, maxPages, res) {
    if(err) {
        console.log(err);
        res.status(404, err).end();
    }

    if(numPage === 1){
        res.links({
            next: 'http://localhost:3000/pokemons?page='+ Number(numPage + 1),
            last: 'http://localhost:3000/pokemons?page='+ maxPages
        });
    } else if (numPage > 1 && numPage < maxPages){
        res.links({
            first: 'http://localhost:3000/pokemons?numPage=1',
            previous: 'http://localhost:3000/pokemons?numPage='+ (numPage - 1),
            next: 'http://localhost:3000/pokemons?numPage='+ (numPage + 1),
            last: 'http://localhost:3000/pokemons?numPage='+ maxPages
        });
    } else if (numPage === maxPages){
        res.links({
            first: 'http://localhost:3000/pokemons?numPage=1',
            previous: 'http://localhost:3000/pokemons?numPage='+ (numPage - 1)
        });
    }

    res.format({
        'text/html' : function() {
            const html = formatandoHTML(data);
            res.type('html');
            res.send(html);
        },
        'application/json' : function() {
            res.type('json');
            res.json(data);
        },
        'default' : function() {
            res.status(406).send('Formato não suportado! Sorry!');
        }
    });
}
```

`find.js`
```js
'use strict';

const Schema = require('./schema');
const Model = require('./model')(Schema, 'Pokemons');
const Pagination = require('./pagination');

const findPokemon = function(req, res, query){
    Model.count({}, (err, count) => {
        const maxPages = Math.ceil(count/3);
        Model.find(query,  (err, data) =>
        Pagination(err,data, res, Number.parseInt(numPage), Number.parseInt(maxPages))).limit(3).skip(3 * (numPage - 1));
    });
};

const CRUD = {
    findPokemon
}

module.exports = CRUD;
```

`app.js`
```js
'use strict';

require('./db/config');
const express = require('express');
const app = express();
const Pokemon = require('./find');

app.get('/pokemons', function(req, res) {
    const query = {};
    let numPage = req.query.page;

    if (numPage === undefined) numPage = 1;
    //console.log(numPage);
    Pokemon.find(res, query, numPage);
});

app.listen(3000, function() {
    console.log('Servidor rodando em http://localhost:3000');
});
```


text:
'use strict';

module.exports = function(Schema, Model) {
    const mongoose = require('mongoose');
    return mongoose.model(Model, Schema);
}


text:
'use strict';

require('./db/config');
const express = require('express');
const app = express();
const Pokemon = require('./find');

app.get('/pokemons', function(req, res) {
    const query = {};
    let numPage = req.query.page;

    if (numPage === undefined) numPage = 1;
    //console.log(numPage);
    Pokemon.find(res, query, numPage);
});

app.listen(3000, function() {
    console.log('Servidor rodando em http://localhost:3000');
});


text:
'use strict';

const Schema = require('./schema');
const Model = require('./model')(Schema, 'Pokemons');
const Pagination = require('./pagination');

const findPokemon = function(req, res, query){
    Model.count({}, (err, count) => {
        const maxPages = Math.ceil(count/3);
        Model.find(query,  (err, data) =>
        Pagination(err,data, res, Number.parseInt(numPage), Number.parseInt(maxPages))).limit(3).skip(3 * (numPage - 1));
    });
};

const CRUD = {
    findPokemon
}

module.exports = CRUD;


text:
'use strict';

const formatandoHTML = function(data) {
    let html = '';

    data.forEach(function(pokemonItem, index, arr) {
        console.log(pokemonItem);

        html = html + '
';
            html = html + '
' + new Date(pokemonItem.created) + '
';
            html = html + '
' + pokemonItem.defense + '
';
            html = html + '
' + pokemonItem.height + '
';
            html = html + '
' + pokemonItem.name + '
';
            html = html + '
' + pokemonItem.speed + '
';
            html = html + '
' + pokemonItem.types.join(" // ") + '
';
            html = html + '
' + pokemonItem.attack + '
';
        html = html + '
';
    });

    return html;
};

module.exports = function(err, data, numPage, maxPages, res) {
    if(err) {
        console.log(err);
        res.status(404, err).end();
    }

    if(numPage === 1){
        res.links({
            next: 'http://localhost:3000/pokemons?page='+ Number(numPage + 1),
            last: 'http://localhost:3000/pokemons?page='+ maxPages
        });
    } else if (numPage > 1 && numPage < maxPages){
        res.links({
            first: 'http://localhost:3000/pokemons?numPage=1',
            previous: 'http://localhost:3000/pokemons?numPage='+ (numPage - 1),
            next: 'http://localhost:3000/pokemons?numPage='+ (numPage + 1),
            last: 'http://localhost:3000/pokemons?numPage='+ maxPages
        });
    } else if (numPage === maxPages){
        res.links({
            first: 'http://localhost:3000/pokemons?numPage=1',
            previous: 'http://localhost:3000/pokemons?numPage='+ (numPage - 1)
        });
    }

    res.format({
        'text/html' : function() {
            const html = formatandoHTML(data);
            res.type('html');
            res.send(html);
        },
        'application/json' : function() {
            res.type('json');
            res.json(data);
        },
        'default' : function() {
            res.status(406).send('Formato não suportado! Sorry!');
        }
    });
}


text:
'use strict';

const mongoose = require('mongoose');

const _schema = {
    name: {type: String, required: true},
    attack: {type: Number, default : 0},
    defense: {type: Number},
    height: {type: Number },
    created: {type: Date},
    hp: {type: Number},
    speed: {type: Number},
    types: []
};

const PokemonSchema = new mongoose.Schema(_schema);

module.exports = PokemonSchema;


text:
'use strict';

const mongoose = require('mongoose');
const uriDB = 'mongodb://localhost/be-mean';

mongoose.connect(uriDB);

mongoose.connection.on('connected', function(){
    console.log("Mongo default connection connected to " + uriDB);
});

mongoose.connection.on('error', function(err){
    console.log("Mongo default connection error" + err);
});

mongoose.connection.on('disconnected', function(){
    console.log("Mongo default connection disconnected");
});

mongoose.connection.on('open', function(){
    console.log("Mongo default connection open");
});

process.on('SIGINT',function(){
    mongoose.connection.close(function(){
        console.log("The connection is closed");
        process.exit(0);
    });
});


text:
'use strict';

module.exports = function(req, res) {
    const options = {
        root: __dirname + '/_public/',
        dotfiles: 'deny',
        headers: {
            'x-timestamp': Date.now(),
            'x-sent': true
        }
    };

    const fileName = req.params.name;
    const fileType = req.params.type;

    switch (fileType){
        case 'png':
            res.set({'Content-Type': 'image/png'});
            fileName = fileName +'.'+fileType;
            break;
        default:
            res.status(400).send('Arquivo não suportado!');
            break;
    }

    res.sendFile(fileName, options, function (err) {
        if (err) {
            console.log(err);
            res.status(err.status).end();
        } else {
            console.log('Sent:', fileName);
        }
    });
};


text:
html
    head
        title= title

    body
        h1= message

        p= description


text:
<!DOCTYPE html>

    <link
      href="mermaid.min.css"
      rel="stylesheet"
    />

    <title>AI Creator Archive</title>

repo_name: camenduru/ai-creator-archive

repo_language: Jupyter Notebook